/[winpt]/trunk/PTD/wptWipeFile.cpp
ViewVC logotype

Contents of /trunk/PTD/wptWipeFile.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (show annotations)
Mon Mar 7 13:21:36 2005 UTC (19 years, 11 months ago) by twoaday
File size: 11018 byte(s)
2005-03-03  Timo Schulz  <twoaday@g10code.com>
                                                                                
        * wptCardDlg.cpp (card_changepin_dlg_proc): Add item to re-type the
        new PIN. Suggested by Achim.
        Support to show the unmasked PIN.
        Modified TAB-order.
        * wptPINDlg.cpp (pin_cb_dlg_proc): Show unmasked PIN.
 
        * Fixed wrong GPG --command-fd strings. Thanks to Achim.
 
2005-03-04  Timo Schulz  <twoaday@g10code.com>
 
        * GPG asks twice for the new PIN. Thanks to Achim.
        * wptCardDlg.cpp (card_changepin_dlg_proc): Reset the 'safety' pin also.        Only check the passphrase if the backup flag is enabled. Again thanks to        Achim.
 
2005-03-06  Timo Schulz  <twoaday@freakmail.de>
 
        * wptKeySignDlg.cpp (do_fill_seckeylist): Skip secret keys without
        a public key. Noted by Kurt Fitzner.
 


1 /* wptWipeFile.cpp - Secure file removal
2 * Copyright (C) 2001-2005 Timo Schulz
3 * Copyright (C) 2000 Matt Gauthier
4 *
5 * WinPT software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * WinPT is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with WinPT; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 *
19 **************************************************************************
20 * This code based on the sunlink.c file from the SRM project, but *
21 * it was heavily modified to work with W32 and with added GCRYPT *
22 * support for gathering random bytes. *
23 * *
24 * The original code was placed under the GNU Lesser Public License, *
25 * even so I decide to put this file under the GNU General Public License.*
26 **************************************************************************
27 */
28
29 #include <windows.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sys/stat.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <direct.h>
36
37 #include "openpgp.h"
38 #include "wptW32API.h"
39 #include "wptErrors.h"
40 #include "wptTypes.h"
41
42
43 typedef unsigned __int64 DDWORD;
44
45 typedef struct {
46 HANDLE fd;
47 DDWORD filesize;
48 DDWORD offset;
49 BYTE *buffer;
50 DWORD buffsize;
51 const char *name;
52 int n_passes;
53 } wipe_context_s;
54
55
56 void (*progress_cb) (void *, DDWORD, DDWORD);
57 static void *progress_cb_value = NULL;
58
59 void (*unlink_cb)(void *, const char *, int, unsigned, unsigned) = NULL;
60 static void *unlink_cb_value = NULL;
61
62 static void
63 overwrite (wipe_context_s * ctx)
64 {
65 DDWORD blocks = 0, mod = 0;
66 DWORD nwritten = 0;
67 LONG size_high = 0;
68
69 blocks = ctx->filesize / ctx->buffsize;
70 mod = ctx->filesize % ctx->buffsize;
71 SetFilePointer (ctx->fd, 0, &size_high, FILE_BEGIN);
72 while (blocks--) {
73 if (!WriteFile (ctx->fd, ctx->buffer, ctx->buffsize, &nwritten, NULL))
74 break;
75 ctx->offset += nwritten;
76 if (unlink_cb)
77 unlink_cb (unlink_cb_value, ctx->name, 0, (unsigned)ctx->offset,
78 (unsigned)ctx->filesize*ctx->n_passes);
79 }
80 if (mod) {
81 WriteFile (ctx->fd, ctx->buffer, (DWORD)mod, &nwritten, NULL);
82 ctx->offset += nwritten;
83 if (unlink_cb)
84 unlink_cb (unlink_cb_value, ctx->name, 0, (unsigned)ctx->offset,
85 (unsigned)ctx->filesize*ctx->n_passes);
86 }
87 FlushFileBuffers (ctx->fd);
88 SetFilePointer (ctx->fd, 0, &size_high, FILE_BEGIN);
89 } /* overwrite */
90
91
92 static void
93 randomize_buffer (byte * buf, size_t bufsize, int level)
94 {
95 const int blocksize = 512;
96 int blocks = bufsize / blocksize;
97 int mod = bufsize % blocksize;
98
99 while (blocks--) {
100 gpg_randomize (buf, blocksize, level);
101 buf += blocksize;
102 }
103 if (mod)
104 gpg_randomize (buf, mod, level);
105 } /* randomize_buffer */
106
107
108 static void
109 overwrite_random (int npasses, wipe_context_s * ctx)
110 {
111 int i;
112
113 for (i = 0; i < npasses; i++) {
114 randomize_buffer (ctx->buffer, ctx->buffsize, 0);
115 overwrite (ctx);
116 }
117 } /* overwrite_random */
118
119
120 static void
121 overwrite_byte (int byte, wipe_context_s * ctx)
122 {
123 memset (ctx->buffer, byte, ctx->buffsize);
124 overwrite (ctx);
125 } /* overwrite_byte */
126
127
128 static void
129 overwrite_bytes (int byte1, int byte2, int byte3, wipe_context_s * ctx)
130 {
131 DWORD i;
132
133 memset (ctx->buffer, byte1, ctx->buffsize);
134 for (i = 1; i < ctx->buffsize; i += 3) {
135 ctx->buffer[i] = byte2;
136 ctx->buffer[i+1] = byte3;
137 }
138 overwrite (ctx);
139 } /* overwrite_bytes */
140
141
142 /**
143 * For the case the file is not a regular file (this is true for
144 * devices or directories) this function tries to rename the file
145 * to random pattern and then it will be delete (without random!).
146 **/
147 int
148 rename_unlink (const char * path)
149 {
150 struct stat statbuf;
151 char * new_name = NULL, * p = NULL, c;
152 int i = 0, rc = 0;
153 int is_dir = 0;
154
155 if (GetFileAttributes (path) & FILE_ATTRIBUTE_DIRECTORY)
156 is_dir = 1;
157
158 new_name = new char[strlen (path)+15];
159 if (!new_name)
160 BUG (0);
161
162 strcpy (new_name, path);
163 p = strrchr (new_name, '\\');
164 if (p != NULL) {
165 p++;
166 *p = '\0';
167 }
168 else
169 p = new_name;
170 do {
171 while (i < 14) {
172 c = gpg_random_char (1);
173 *p = c;
174 p++;
175 i++;
176 }
177 *p = '\0';
178 } while (stat (new_name, &statbuf) == 0);
179
180 if (rename (path, new_name) == -1) {
181 rc = WPTERR_FILE_READ;
182 goto leave;
183 }
184 if (is_dir && RemoveDirectory (new_name) == FALSE)
185 rc = WPTERR_FILE_REMOVE;
186 else if (!DeleteFile (new_name))
187 rc = WPTERR_FILE_REMOVE;
188
189 leave:
190 free_if_alloc (new_name);
191 return rc;
192 } /* rename_unlink */
193
194
195 static __int64
196 GetFileSize64 (const char * path)
197 {
198 FILE *fp = fopen (path, "r");
199 if (fp) {
200 struct _stati64 statbuf;
201 _fstati64 (fileno (fp), &statbuf);
202 fclose (fp);
203 return statbuf.st_size;
204 }
205 return -1;
206 } /* GetFileSize64 */
207
208
209 static int
210 _secure_unlink (const char * path, int mode, HANDLE *r_fd)
211 {
212 wipe_context_s ctx;
213 LONG size_high = 0;
214
215 if (GetFileAttributes (path) & FILE_ATTRIBUTE_DIRECTORY)
216 return rename_unlink (path);
217
218 memset (&ctx, 0, sizeof (ctx));
219 ctx.name = path;
220 ctx.buffsize = 16384;
221 ctx.buffer = new byte[ctx.buffsize];
222 if (!ctx.buffer)
223 BUG (0);
224
225 ctx.filesize = GetFileSize64 (path);
226 if (!ctx.filesize) {
227 free_if_alloc (ctx.buffer);
228 unlink (path);
229 return 0;
230 }
231
232 ctx.fd = CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
233 OPEN_ALWAYS, 0, NULL);
234 if (ctx.fd == INVALID_HANDLE_VALUE) {
235 free_if_alloc (ctx.buffer);
236 return WPTERR_FILE_OPEN;
237 }
238 else if (r_fd)
239 *r_fd = ctx.fd;
240
241 gpg_quick_random_gen (1);
242 if (unlink_cb)
243 unlink_cb (unlink_cb_value, ctx.name, 0, 0, 0);
244
245 switch (mode) {
246 case WIPE_MODE_FAST:
247 ctx.n_passes = 1;
248 overwrite_random (1, &ctx);
249 break;
250
251 case WIPE_MODE_SIMPLE:
252 ctx.n_passes = 2;
253 overwrite_random (2, &ctx);
254 break;
255
256 case WIPE_MODE_DOD:
257 ctx.n_passes = 5;
258 overwrite_random (1, &ctx);
259 overwrite_byte ((~1) & 0xFF, &ctx);
260 overwrite_random (1, &ctx);
261 overwrite_byte ((~4) & 0xFF, &ctx);
262 overwrite_random (1, &ctx);
263 break;
264
265 case WIPE_MODE_GUTMANN:
266 ctx.n_passes = 39;
267 overwrite_random (4, &ctx);
268 overwrite_byte( 0x55, &ctx );
269 overwrite_byte ( 0xAA, &ctx );
270 overwrite_bytes( 0x92, 0x49, 0x24, &ctx );
271 overwrite_bytes( 0x49, 0x24, 0x92, &ctx );
272 overwrite_bytes( 0x24, 0x92, 0x49, &ctx );
273 overwrite_byte( 0x00, &ctx );
274 overwrite_byte( 0x11, &ctx );
275 overwrite_byte( 0x22, &ctx );
276 overwrite_byte( 0x33, &ctx );
277 overwrite_byte( 0x44, &ctx );
278 overwrite_byte( 0x55, &ctx );
279 overwrite_byte( 0x66, &ctx );
280 overwrite_byte( 0x77, &ctx );
281 overwrite_byte( 0x88, &ctx );
282 overwrite_byte( 0x99, &ctx );
283 overwrite_byte( 0xAA, &ctx );
284 overwrite_byte( 0xBB, &ctx );
285 overwrite_byte( 0xCC, &ctx );
286 overwrite_byte( 0xDD, &ctx );
287 overwrite_byte( 0xEE, &ctx );
288 overwrite_byte( 0xFF, &ctx );
289 overwrite_bytes( 0x92, 0x49, 0x24, &ctx );
290 overwrite_bytes( 0x49, 0x24, 0x92, &ctx );
291 overwrite_bytes( 0x24, 0x92, 0x49, &ctx );
292 overwrite_bytes( 0x6D, 0xB6, 0xDB, &ctx );
293 overwrite_bytes( 0xB6, 0xDB, 0x6D, &ctx );
294 overwrite_bytes( 0xDB, 0x6D, 0xB6, &ctx );
295 overwrite_random( 4, &ctx );
296 break;
297 }
298
299 /* Set file length to zero so allocated clusters cannot be trailed */
300 SetFilePointer (ctx.fd, 0, &size_high, FILE_BEGIN);
301 SetEndOfFile (ctx.fd);
302 CloseHandle (ctx.fd);
303
304 memset (ctx.buffer, 0, ctx.buffsize); /* burn the last evidence */
305 free_if_alloc (ctx.buffer);
306
307 return rename_unlink (path);
308 }
309
310 int
311 secure_unlink (const char *path, int mode)
312 {
313 return _secure_unlink (path, mode, NULL);
314 } /* secure_unlink */
315
316
317
318 void
319 secure_unlink_set_cb (void (*cb)(void *, const char *, int, unsigned, unsigned),
320 void *cb_value)
321 {
322 unlink_cb = cb;
323 unlink_cb_value = cb_value;
324 } /* secure_unlink_set_cb */
325
326
327 /* Windows 98 - Q188074 */
328 #define REGISTRY_FILESYSTEM "System\\CurrentControlSet\\Control\\FileSystem"
329 #define REGISTRY_LOWDISKSPACE "DisableLowDiskSpaceBroadcast"
330
331
332 /* disables the annoying warning Windows 98 displays when disk space is low */
333 static void
334 handle_lowdiskspace_notify( const char * drive, int disable )
335 {
336 OSVERSIONINFO ov;
337 HKEY key;
338 DWORD n;
339
340 memset( &ov, 0, sizeof ov );
341 ov.dwOSVersionInfoSize = sizeof ov;
342 GetVersionEx( &ov );
343 if( ov.dwPlatformId == VER_PLATFORM_WIN32_NT )
344 return;
345
346 if( disable ) {
347 unsigned newi = (1 << (toupper((unsigned)drive) - (unsigned)'A'));
348 if( RegOpenKey( HKEY_LOCAL_MACHINE, REGISTRY_FILESYSTEM, &key ) ) {
349 n = sizeof newi;
350 RegSetValue( key, REGISTRY_LOWDISKSPACE, REG_DWORD, (LPCTSTR)newi, n );
351 RegCloseKey( key );
352 }
353 }
354 else {
355 if( RegOpenKey( HKEY_LOCAL_MACHINE, REGISTRY_FILESYSTEM, &key ) ) {
356 RegDeleteKey( key, REGISTRY_LOWDISKSPACE );
357 RegCloseKey( key );
358 }
359 }
360 } /* handle_lowdiskspace_notify */
361
362
363 int
364 wipe_freespace (const char * drive, HANDLE *r_fd,
365 void (*cb)(void *, DDWORD, DDWORD), void * cb_value)
366 {
367 ULARGE_INTEGER caller, total, frees;
368 LONG hpart=0;
369 HANDLE fd;
370 int disktyp = GetDriveType (drive);
371 int rc;
372 char * file;
373
374 if (disktyp != DRIVE_FIXED && disktyp != DRIVE_REMOVABLE)
375 return -1;
376 if (!GetDiskFreeSpaceEx (drive, &caller, &total, &frees))
377 return -1;
378 handle_lowdiskspace_notify (drive, 1);
379
380 /* disk is full */
381 if (!frees.LowPart)
382 return 0;
383 file = new char[strlen (drive)+8];
384 if (!file)
385 BUG (0);
386 sprintf (file, "%stemp_winpt.tmp", drive);
387 fd = CreateFile (file,
388 GENERIC_READ|GENERIC_WRITE,
389 FILE_SHARE_READ|FILE_SHARE_WRITE,
390 NULL, CREATE_ALWAYS, 0, NULL);
391 if (fd == INVALID_HANDLE_VALUE) {
392 free_if_alloc (file);
393 return WPTERR_FILE_OPEN;
394 }
395 hpart = frees.HighPart;
396 SetFilePointer (fd, frees.LowPart, &hpart, FILE_BEGIN);
397 SetEndOfFile (fd);
398 CloseHandle (fd);
399
400 if (cb && cb_value) {
401 progress_cb = cb;
402 progress_cb_value = cb_value;
403 }
404 rc = _secure_unlink (file, WIPE_MODE_FAST, r_fd);
405
406 handle_lowdiskspace_notify (drive, 0);
407 free_if_alloc (file);
408 return rc;
409 } /* wipe_freespace */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26