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

Annotation of /trunk/PTD/wptWipeFile.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (hide 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 twoaday 2 /* 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 twoaday 5 unlink (path);
229     return 0;
230 twoaday 2 }
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 twoaday 5 /* disk is full */
381 twoaday 2 if (!frees.LowPart)
382 twoaday 5 return 0;
383 twoaday 2 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