kshred.cpp
00001 /*--------------------------------------------------------------------------* 00002 KShred.h Copyright (c) 2000 MieTerra LLC. 00003 Credits: Andreas F. Pour <bugs@mieterra.com> 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy 00006 of this software and associated documentation files (the "Software"), to deal 00007 in the Software without restriction, including without limitation the rights 00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 copies of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00019 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00021 */ 00022 00023 #include "kshred.h" 00024 #include <time.h> 00025 #include <tdelocale.h> 00026 #include <kdebug.h> 00027 #include <stdlib.h> 00028 #include <tdeapplication.h> 00029 00030 // antlarr: KDE 4: Make it const TQString & 00031 KShred::KShred(TQString fileName) 00032 { 00033 if (fileName.isEmpty()) 00034 { 00035 kdError() << "KShred: missing file name in constructor" << endl; 00036 file = 0L; 00037 } 00038 else 00039 { 00040 file = new TQFile(); 00041 file->setName(fileName); 00042 if (!file->open(IO_ReadWrite)) 00043 { 00044 kdError() << "KShred: cannot open file '" << fileName.local8Bit().data() << "' for writing\n" << endl; 00045 file = 0L; 00046 fileSize = 0; 00047 } 00048 else 00049 fileSize = file->size(); 00050 00051 totalBytes = 0; 00052 bytesWritten = 0; 00053 lastSignalled = 0; 00054 tbpc = 0; 00055 fspc = 0; 00056 } 00057 } 00058 00059 00060 KShred::~KShred() 00061 { 00062 if (file != 0L) 00063 delete file; 00064 } 00065 00066 00067 bool 00068 KShred::fill1s() 00069 { 00070 return fillbyte(0xFF); 00071 } 00072 00073 00074 bool 00075 KShred::fill0s() 00076 { 00077 return fillbyte(0x0); 00078 } 00079 00080 00081 bool 00082 KShred::fillbyte(unsigned int byte) 00083 { 00084 if (file == 0L) 00085 return false; 00086 unsigned char buff[4096]; 00087 memset((void *) buff, byte, 4096); 00088 00089 unsigned int n; 00090 for (unsigned int todo = fileSize; todo > 0; todo -= n) 00091 { 00092 n = (todo > 4096 ? 4096 : todo); 00093 if (!writeData(buff, n)) 00094 return false; 00095 } 00096 if (!flush()) 00097 return false; 00098 return file->at(0); 00099 } 00100 00101 00102 bool 00103 KShred::fillpattern(unsigned char *data, unsigned int size) 00104 { 00105 if (file == 0L) 00106 return false; 00107 00108 unsigned int n; 00109 for (unsigned int todo = fileSize; todo > 0; todo -= n) 00110 { 00111 n = (todo > size ? size : todo); 00112 if (!writeData(data, n)) 00113 return false; 00114 } 00115 if (!flush()) 00116 return false; 00117 return file->at(0); 00118 } 00119 00120 00121 bool 00122 KShred::fillrandom() 00123 { 00124 if (file == 0L) 00125 return false; 00126 00127 long int buff[4096 / sizeof(long int)]; 00128 unsigned int n; 00129 00130 for (unsigned int todo = fileSize; todo > 0; todo -= n) 00131 { 00132 n = (todo > 4096 ? 4096 : todo); 00133 // assumes that 4096 is a multipe of sizeof(long int) 00134 int limit = (n + sizeof(long int) - 1) / sizeof(long int); 00135 for (int i = 0; i < limit; i++) 00136 buff[i] = kapp->random(); 00137 00138 if (!writeData((unsigned char *) buff, n)) 00139 return false; 00140 } 00141 if (!flush()) 00142 return false; 00143 return file->at(0); 00144 } 00145 00146 00147 // antlarr: KDE 4: Make it const TQString & 00148 bool 00149 KShred::shred(TQString fileName) 00150 { 00151 if (fileName.isEmpty()) 00152 return false; 00153 00154 KShred shredder(fileName); 00155 return shredder.shred(); 00156 } 00157 00158 00159 bool 00160 KShred::writeData(unsigned char *data, unsigned int size) 00161 { 00162 unsigned int ret = 0; 00163 00164 // write 'data' of size 'size' to the file 00165 while ((ret < size) && (file->putch((int) data[ret]) >= 0)) 00166 ret++; 00167 00168 if ((totalBytes > 0) && (ret > 0)) 00169 { 00170 if (tbpc == 0) 00171 { 00172 tbpc = ((unsigned int) (totalBytes / 100)) == 0 ? 1 : totalBytes / 100; 00173 fspc = ((unsigned int) (fileSize / 100)) == 0 ? 1 : fileSize / 100; 00174 } 00175 bytesWritten += ret; 00176 unsigned int pc = (unsigned int) (bytesWritten / tbpc); 00177 if (pc > lastSignalled) 00178 { 00179 emit processedSize(fspc * pc); 00180 lastSignalled = pc; 00181 } 00182 } 00183 return ret == size; 00184 } 00185 00186 00187 bool 00188 KShred::flush() 00189 { 00190 if (file == 0L) 00191 return false; 00192 00193 file->flush(); 00194 return (fsync(file->handle()) == 0); 00195 } 00196 00197 00198 // shred the file, then close and remove it 00199 // 00200 // UPDATED: this function now uses 35 passes based on the the article 00201 // Peter Gutmann, "Secure Deletion of Data from Magnetic and Solid-State 00202 // Memory", first published in the Sixth USENIX Security Symposium 00203 // Proceedings, San Jose, CA, July 22-25, 1996 (available online at 00204 // http://rootprompt.org/article.php3?article=473) 00205 00206 bool 00207 KShred::shred() 00208 { 00209 // WARNING 00210 // These numbers are octal. Do not remove the leading zeros! 00211 unsigned char p[6][3] = {{0222, 0111, 044}, {0111, 044, 0222}, 00212 { 044, 0222, 0111}, {0155, 0266, 0333}, 00213 {0266, 0333, 0155}, {0333, 0155, 0266}}; 00214 TQString msg = i18n("Shredding: pass %1 of 35"); 00215 00216 emit processedSize(0); 00217 00218 // thirty-five times writing the entire file size 00219 totalBytes = fileSize * 35; 00220 int iteration = 1; 00221 00222 for (int ctr = 0; ctr < 4; ctr++) 00223 if (!fillrandom()) 00224 return false; 00225 else 00226 { 00227 emit infoMessage(msg.arg(iteration)); 00228 } 00229 00230 if (!fillbyte((unsigned int) 0x55)) // '0x55' is 01010101 00231 return false; 00232 emit infoMessage(msg.arg(iteration)); 00233 00234 if (!fillbyte((unsigned int) 0xAA)) // '0xAA' is 10101010 00235 return false; 00236 emit infoMessage(msg.arg(iteration)); 00237 00238 for (unsigned int ctr = 0; ctr < 3; ctr++) 00239 if (!fillpattern(p[ctr], 3)) // '0x92', '0x49', '0x24' 00240 return false; 00241 else 00242 { 00243 emit infoMessage(msg.arg(iteration)); 00244 } 00245 00246 for (unsigned int ctr = 0; ctr <= 255 ; ctr += 17) 00247 if (!fillbyte(ctr)) // sequence of '0x00', '0x11', ..., '0xFF' 00248 return false; 00249 else 00250 { 00251 emit infoMessage(msg.arg(iteration)); 00252 } 00253 00254 for (unsigned int ctr = 0; ctr < 6; ctr++) 00255 if (!fillpattern(p[ctr], 3)) // '0x92', '0x49', '0x24' 00256 return false; 00257 else 00258 { 00259 emit infoMessage(msg.arg(iteration)); 00260 } 00261 00262 for (int ctr = 0; ctr < 4; ctr++) 00263 if (!fillrandom()) 00264 return false; 00265 else 00266 { 00267 emit infoMessage(msg.arg(iteration)); 00268 } 00269 00270 if (!file->remove()) 00271 return false; 00272 file = 0L; 00273 emit processedSize(fileSize); 00274 return true; 00275 } 00276 00277 #include "kshred.moc" 00278