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

Annotation of /trunk/PTD/wptWipeFile.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations)
Mon Jan 31 11:02:21 2005 UTC (20 years, 1 month ago) by twoaday
File MIME type: text/plain
File size: 10461 byte(s)
WinPT initial checkin.


1 twoaday 2 /* wptWipeFile.c - Secure file removal
2     * Copyright (C) 2000 Matt Gauthier
3     * Copyright (C) 2001, 2002, 2003 Timo Schulz
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    
39     enum {
40     WIPE_MODE_SIMPLE = 0,
41     WIPE_MODE_DOD = 1,
42     WIPE_MODE_GUTMANN = 2
43     };
44    
45     enum { /* WinPT error codes */
46     ERR_FILE_READ = 4,
47     ERR_FILE_OPEN = 2,
48     ERR_FILE_REMOVE = 8,
49     ERR_FILE_ZERO = 9,
50     ERR_NOMEMORY = 25
51     };
52    
53     typedef unsigned __int64 DDWORD;
54    
55     typedef struct {
56     HANDLE fd;
57     DDWORD filesize;
58     byte * buffer;
59     size_t buffsize;
60     } wipe_context_s;
61    
62    
63     void (*progress_cb) (void *, DDWORD, DDWORD);
64     static void * progress_cb_value = NULL;
65    
66    
67     static void
68     overwrite (wipe_context_s * ctx)
69     {
70     DDWORD blocks = 0, mod = 0;
71     DWORD nwritten = 0, npos = 0;
72     DWORD size_high = 0;
73    
74     blocks = ctx->filesize / ctx->buffsize;
75     mod = ctx->filesize % ctx->buffsize;
76     SetFilePointer (ctx->fd, 0, &size_high, FILE_BEGIN);
77     while (blocks--) {
78     if (!WriteFile (ctx->fd, ctx->buffer, ctx->buffsize, &nwritten, NULL))
79     break;
80     npos += nwritten;
81     if (progress_cb)
82     progress_cb (progress_cb_value, npos, ctx->filesize);
83     }
84     if (mod) {
85     WriteFile (ctx->fd, ctx->buffer, (DWORD)mod, &nwritten, NULL);
86     npos += nwritten;
87     if (progress_cb)
88     progress_cb (progress_cb_value, npos, ctx->filesize);
89     }
90     FlushFileBuffers (ctx->fd);
91     SetFilePointer (ctx->fd, 0, &size_high, FILE_BEGIN);
92     } /* overwrite */
93    
94    
95     static void
96     randomize_buffer (byte * buf, size_t bufsize, int level)
97     {
98     const int blocksize = 512;
99     int blocks = bufsize / blocksize;
100     int mod = bufsize % blocksize;
101    
102     while (blocks--) {
103     gpg_randomize (buf, blocksize, level);
104     buf += blocksize;
105     }
106     if (mod)
107     gpg_randomize (buf, mod, level);
108     } /* randomize_buffer */
109    
110    
111     static void
112     overwrite_random (int num_passes, wipe_context_s * ctx)
113     {
114     int i = 0;
115    
116     for (i = 0; i < num_passes; i++) {
117     randomize_buffer (ctx->buffer, ctx->buffsize, 0);
118     overwrite (ctx);
119     }
120     } /* overwrite_random */
121    
122    
123     static void
124     overwrite_byte (int byte, wipe_context_s * ctx)
125     {
126     memset (ctx->buffer, byte, ctx->buffsize);
127     overwrite (ctx);
128     } /* overwrite_byte */
129    
130    
131     static void
132     overwrite_bytes (int byte1, int byte2, int byte3, wipe_context_s * ctx)
133     {
134     size_t i = 0;
135    
136     memset (ctx->buffer, byte1, ctx->buffsize);
137     for (i = 1; i < ctx->buffsize; i += 3) {
138     ctx->buffer[i] = byte2;
139     ctx->buffer[i+1] = byte3;
140     }
141     overwrite (ctx);
142     } /* overwrite_bytes */
143    
144    
145     /**
146     * For the case the file is not a regular file (this is true for
147     * devices or directories) this function tries to rename the file
148     * to random pattern and then it will be delete (without random!).
149     **/
150     int
151     rename_unlink (const char * path)
152     {
153     struct stat statbuf;
154     char * new_name = NULL, * p = NULL, c;
155     int i = 0, rc = 0;
156     int is_dir = 0;
157    
158    
159     if (GetFileAttributes (path) & FILE_ATTRIBUTE_DIRECTORY)
160     is_dir = 1;
161    
162     new_name = (char *)malloc (strlen (path) + 15);
163     if (!new_name)
164     return ERR_NOMEMORY;
165    
166     strcpy (new_name, path);
167     p = strrchr (new_name, '\\');
168     if (p != NULL) {
169     p++;
170     *p = '\0';
171     }
172     else
173     p = new_name;
174     do {
175     while (i < 14) {
176     c = gpg_random_char (1);
177     *p = c; p++; i++;
178     }
179     *p = '\0';
180     } while (stat (new_name, &statbuf) == 0);
181    
182     if (rename (path, new_name) == -1) {
183     rc = ERR_FILE_READ;
184     goto leave;
185     }
186     if (is_dir && RemoveDirectory (new_name) == FALSE)
187     rc = ERR_FILE_REMOVE;
188     else if (!DeleteFile (new_name))
189     rc = ERR_FILE_REMOVE;
190    
191     leave:
192     free (new_name);
193     return rc;
194     } /* rename_unlink */
195    
196    
197     static __int64
198     GetFileSize64( const char * path )
199     {
200     FILE *fp = fopen( path, "r" );
201     if( fp ) {
202     struct _stati64 statbuf;
203     _fstati64( fileno( fp ), &statbuf );
204     fclose( fp );
205     return statbuf.st_size;
206     }
207     return -1;
208     } /* GetFileSize64 */
209    
210    
211     int
212     secure_unlink( const char *path, const int mode )
213     {
214     wipe_context_s ctx = {0};
215     DWORD size_high = 0;
216    
217     if( GetFileAttributes( path ) & FILE_ATTRIBUTE_DIRECTORY)
218     return rename_unlink( path );
219    
220     ctx.buffsize = 8192;
221     ctx.buffer = (byte *)malloc( ctx.buffsize );
222     if( !ctx.buffer )
223     return ERR_NOMEMORY;
224    
225     ctx.filesize = GetFileSize64( path );
226     if( !ctx.filesize ) {
227     free( ctx.buffer );
228     return ERR_FILE_ZERO;
229     }
230    
231     ctx.fd = CreateFile( path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL );
232     if( ctx.fd == INVALID_HANDLE_VALUE ) {
233     free( ctx.buffer );
234     return ERR_FILE_OPEN;
235     }
236    
237     gpg_quick_random_gen( 1 );
238    
239     switch( mode ) {
240     case WIPE_MODE_SIMPLE:
241     overwrite_random( 2, &ctx );
242     break;
243    
244     case WIPE_MODE_DOD:
245     overwrite_random( 1, &ctx );
246     overwrite_byte( (~1) & 0xFF, &ctx );
247     overwrite_random( 1, &ctx );
248     overwrite_byte( (~4) & 0xFF, &ctx );
249     overwrite_random( 1, &ctx );
250     break;
251    
252     case WIPE_MODE_GUTMANN:
253     overwrite_random( 4, &ctx);
254     overwrite_byte( 0x55, &ctx );
255     overwrite_byte ( 0xAA, &ctx );
256     overwrite_bytes( 0x92, 0x49, 0x24, &ctx );
257     overwrite_bytes( 0x49, 0x24, 0x92, &ctx );
258     overwrite_bytes( 0x24, 0x92, 0x49, &ctx );
259     overwrite_byte( 0x00, &ctx );
260     overwrite_byte( 0x11, &ctx );
261     overwrite_byte( 0x22, &ctx );
262     overwrite_byte( 0x33, &ctx );
263     overwrite_byte( 0x44, &ctx );
264     overwrite_byte( 0x55, &ctx );
265     overwrite_byte( 0x66, &ctx );
266     overwrite_byte( 0x77, &ctx );
267     overwrite_byte( 0x88, &ctx );
268     overwrite_byte( 0x99, &ctx );
269     overwrite_byte( 0xAA, &ctx );
270     overwrite_byte( 0xBB, &ctx );
271     overwrite_byte( 0xCC, &ctx );
272     overwrite_byte( 0xDD, &ctx );
273     overwrite_byte( 0xEE, &ctx );
274     overwrite_byte( 0xFF, &ctx );
275     overwrite_bytes( 0x92, 0x49, 0x24, &ctx );
276     overwrite_bytes( 0x49, 0x24, 0x92, &ctx );
277     overwrite_bytes( 0x24, 0x92, 0x49, &ctx );
278     overwrite_bytes( 0x6D, 0xB6, 0xDB, &ctx );
279     overwrite_bytes( 0xB6, 0xDB, 0x6D, &ctx );
280     overwrite_bytes( 0xDB, 0x6D, 0xB6, &ctx );
281     overwrite_random( 4, &ctx );
282     break;
283     }
284    
285     /* Set file length to zero so allocated clusters cannot be trailed */
286     SetFilePointer( ctx.fd, 0, &size_high, FILE_BEGIN );
287     SetEndOfFile( ctx.fd );
288     CloseHandle( ctx.fd );
289    
290     /* free memory */
291     memset( ctx.buffer, 0, ctx.buffsize ); /* burn the last evidence */
292     free( ctx.buffer);
293    
294     return rename_unlink( path );
295     } /* secure_unlink */
296    
297    
298     /* Windows 98 - Q188074 */
299     #define REGISTRY_FILESYSTEM "System\\CurrentControlSet\\Control\\FileSystem"
300     #define REGISTRY_LOWDISKSPACE "DisableLowDiskSpaceBroadcast"
301    
302    
303     /* disables the annoying warning Windows 98 displays when disk space is low */
304     static void
305     handle_lowdiskspace_notify( const char * drive, int disable )
306     {
307     OSVERSIONINFO ov;
308     HKEY key;
309     DWORD n;
310    
311     memset( &ov, 0, sizeof ov );
312     ov.dwOSVersionInfoSize = sizeof ov;
313     GetVersionEx( &ov );
314     if( ov.dwPlatformId == VER_PLATFORM_WIN32_NT )
315     return;
316    
317     if( disable ) {
318     unsigned new = (1 << (toupper((unsigned)drive) - (unsigned)'A'));
319     if( RegOpenKey( HKEY_LOCAL_MACHINE, REGISTRY_FILESYSTEM, &key ) ) {
320     n = sizeof new;
321     RegSetValue( key, REGISTRY_LOWDISKSPACE, REG_DWORD, (LPCTSTR)new, n );
322     RegCloseKey( key );
323     }
324     }
325     else {
326     if( RegOpenKey( HKEY_LOCAL_MACHINE, REGISTRY_FILESYSTEM, &key ) ) {
327     RegDeleteKey( key, REGISTRY_LOWDISKSPACE );
328     RegCloseKey( key );
329     }
330     }
331     } /* handle_lowdiskspace_notify */
332    
333    
334     int
335     wipe_freespace( const char * drive,
336     void (*cb)(void *, DDWORD, DDWORD), void * cb_value )
337     {
338     ULARGE_INTEGER caller, total, frees;
339     HANDLE fd;
340     int disktyp = GetDriveType( drive ), rc;
341     char * file;
342     OSVERSIONINFO osinf;
343    
344     memset (&osinf, 0, sizeof osinf);
345     osinf.dwOSVersionInfoSize = sizeof osinf;
346     GetVersionEx (&osinf);
347    
348     if( disktyp != DRIVE_FIXED && disktyp != DRIVE_REMOVABLE )
349     return -1;
350     if( !GetDiskFreeSpaceEx( drive, &caller, &total, &frees ) )
351     return -1;
352     if (osinf.dwPlatformId != VER_PLATFORM_WIN32_NT)
353     handle_lowdiskspace_notify (drive, 1);
354    
355     if( !frees.LowPart )
356     return ERR_FILE_ZERO;
357     file = malloc( strlen( drive ) + 8 );
358     if( !file )
359     return ERR_NOMEMORY;
360     sprintf( file, "%stemp", drive );
361    
362     fd = CreateFile( file,
363     GENERIC_READ|GENERIC_WRITE,
364     FILE_SHARE_READ|FILE_SHARE_WRITE,
365     NULL, CREATE_ALWAYS, 0, NULL );
366     if( fd == INVALID_HANDLE_VALUE ) {
367     free( file );
368     return ERR_FILE_OPEN;
369     }
370     SetFilePointer( fd, frees.LowPart, &frees.HighPart, FILE_BEGIN );
371     SetEndOfFile( fd );
372     CloseHandle( fd );
373    
374     if( cb && cb_value ) {
375     progress_cb = cb;
376     progress_cb_value = cb_value;
377     }
378     rc = secure_unlink( file, WIPE_MODE_SIMPLE );
379    
380     handle_lowdiskspace_notify( drive, 0 );
381     free( file );
382     return rc;
383     } /* wipe_freespace */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26