--- remove.c.orig 2003-05-05 15:15:48.000000000 +0200 +++ remove.c 2003-05-05 15:26:08.000000000 +0200 @@ -26,6 +26,12 @@ #include #include +/* SRM BEGIN */ +#include +#include +#include +/* SRM END */ + #if HAVE_STDBOOL_H # include #else @@ -81,6 +87,18 @@ int euidaccess (); int yesno (); +/* SRM BEGIN */ +#define BLOCKSIZE 32769 +#define DIR_SEPERATOR '/' +#define FLUSH sync() +#define RANDOM_DEVICE "/dev/urandom" +static int secure = 0; +static char fillbuf[BLOCKSIZE]; +static FILE *devrandom; +/* Functions */ +static int secure_delete(); +/* SRM END */ + extern char *program_name; /* state initialized by remove_init, freed by remove_fini */ @@ -605,6 +623,103 @@ return status; } +/* SRM BEGIN */ +void fill_buf(char pattern[3]) { + int loop; + int where; + for (loop = 0; loop < (BLOCKSIZE / 3); loop++) { + where = loop * 3; + fillbuf[where] = pattern[0]; + fillbuf[where+1] = pattern[1]; + fillbuf[where+2] = pattern[2]; + } +} + +void random_buf() { + int loop; + if (devrandom != NULL) + for (loop = 0; loop < BLOCKSIZE; loop++) + fillbuf[loop] = (unsigned char) (256.0*rand()/(RAND_MAX+1.0)); + else + fread(&fillbuf, BLOCKSIZE, 1, devrandom); +} + +/* overwriting the file several times */ + static int + secure_delete (delfile) + char *delfile; + { + unsigned char write_modes[27][3] = { + {"\x55\x55\x55"}, {"\xaa\xaa\xaa"}, {"\x92\x49\x24"}, {"\x49\x24\x92"}, + {"\x24\x92\x49"}, {"\x00\x00\x00"}, {"\x11\x11\x11"}, {"\x22\x22\x22"}, + {"\x33\x33\x33"}, {"\x44\x44\x44"}, {"\x55\x55\x55"}, {"\x66\x66\x66"}, + {"\x77\x77\x77"}, {"\x88\x88\x88"}, {"\x99\x99\x99"}, {"\xaa\xaa\xaa"}, + {"\xbb\xbb\xbb"}, {"\xcc\xcc\xcc"}, {"\xdd\xdd\xdd"}, {"\xee\xee\xee"}, + {"\xff\xff\xff"}, {"\x92\x49\x24"}, {"\x49\x24\x92"}, {"\x24\x92\x49"}, + {"\x6d\xb6\xdb"}, {"\xb6\xdb\x6d"}, {"\xdb\x6d\xb6"} + }; + unsigned char std_array[3] = "\xff\xff\xff"; + FILE *f; + int file; + unsigned long writes; + unsigned long counter; + unsigned long filesize; + struct stat filestat; + int turn; + int result; + unsigned char ch; + char newname[512]; + +/* open the file, get the filesize, calculate the numbers of needed writings */ + if (lstat(delfile, &filestat)) + return 1; + if (! S_ISREG(filestat.st_mode)) + return 1; + if ((f = fopen(delfile, "r+b")) == NULL) + return 1; + filesize = filestat.st_size; + writes = (1 + (filesize / BLOCKSIZE)); + file=fileno(f); + (void) setvbuf(stdout, NULL, _IONBF, 0); + devrandom = fopen(RANDOM_DEVICE, "r"); + + if (secure > 1) { + fill_buf(std_array); + for (counter=1; counter<=writes; counter++) + fwrite(&fillbuf, 1, BLOCKSIZE, f); + fflush(f); + fsync(file); + } + +/* do the overwriting stuff */ + for (turn=0; turn<=36; turn++) { + rewind(f); + if ((secure < 3) && (turn > 0)) break; + if ((turn>=5) && (turn<=31)) { + fill_buf(write_modes[turn-5]); + for (counter=1; counter<=writes; counter++) + fwrite(&fillbuf, 1, BLOCKSIZE, f); + } else { + for (counter=1; counter<=writes; counter++) { + random_buf(); + fwrite(&fillbuf, 1, BLOCKSIZE, f); + } + } + fflush(f); + if (fsync(file) < 0) + FLUSH; + } + (void) fclose(f); + (void) fclose(devrandom); +/* Hard Flush -> Force cached data to be written to disk */ + FLUSH; +/* open + truncating the file, so an attacker doesn't know the diskblocks */ + if ((file = open(delfile, O_WRONLY | O_TRUNC)) >= 0) + close(file); + return 0; +} +/* SRM END */ + /* Query the user if appropriate, and if ok try to remove the file or directory specified by FS. Return RM_OK if it is removed, and RM_ERROR or RM_USER_DECLINED if not. */ @@ -646,9 +761,16 @@ return RM_USER_DECLINED; } - if (x->verbose) - printf (_("removing %s\n"), quote (full_filename (pathname))); + if (x->verbose) { + if (secure) + printf (_("wiping %s\n"), quote (full_filename (pathname))); + else + printf (_("removing %s\n"), quote (full_filename (pathname))); + } + if (secure) + secure_delete(pathname); + if (unlink (pathname) && (errno != ENOENT || !x->ignore_missing_files)) { error (0, errno, _("cannot unlink %s"), quote (full_filename (pathname))); @@ -821,6 +943,8 @@ { mode_t filetype_mode; + secure = x->secure; + if (user_specified_name) { /* CAUTION: this use of base_name works only because any --- rm.c.orig 2003-05-05 14:58:35.000000000 +0200 +++ rm.c 2003-05-05 15:16:31.000000000 +0200 @@ -58,7 +58,7 @@ #define PROGRAM_NAME "rm" #define AUTHORS \ - "Paul Rubin, David MacKenzie, Richard Stallman, and Jim Meyering" + "Paul Rubin, David MacKenzie, Richard Stallman, Jim Meyering, and van Hauser" void strip_trailing_slashes (); @@ -71,6 +71,9 @@ {"force", no_argument, NULL, 'f'}, {"interactive", no_argument, NULL, 'i'}, {"recursive", no_argument, NULL, 'r'}, +/* SRM BEGIN */ + {"secure", no_argument, NULL, 's'}, +/* SRM END */ {"verbose", no_argument, NULL, 'v'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, @@ -93,6 +96,7 @@ -f, --force ignore nonexistent files, never prompt\n\ -i, --interactive prompt before any removal\n\ -r, -R, --recursive remove the contents of directories recursively\n\ + -s, --secure secure overwrite (-sss for full security)\n\ -v, --verbose explain what is being done\n\ --help display this help and exit\n\ --version output version information and exit\n\ @@ -105,10 +109,11 @@ \n\ Note that if you use rm to remove a file, it is usually possible to recover\n\ the contents of that file. If you want more assurance that the contents are\n\ -truly unrecoverable, consider using shred.\n\ +truly unrecoverable, use the -s option.\n\ "), program_name, program_name); puts (_("\nReport bugs to .")); + puts (_("\nWith secure_delete patch by van Hauser ")); } exit (status); } @@ -122,6 +127,7 @@ x->recursive = 0; x->stdin_tty = isatty (STDIN_FILENO); x->verbose = 0; + x->secure = 0; } int @@ -140,7 +146,7 @@ rm_option_init (&x); - while ((c = getopt_long (argc, argv, "dfirvR", long_opts, NULL)) != -1) + while ((c = getopt_long (argc, argv, "dfirsvR", long_opts, NULL)) != -1) { switch (c) { @@ -161,6 +167,11 @@ case 'R': x.recursive = 1; break; +/* SRM BEGIN */ + case 's': + x.secure++; + break; +/* SRM END */ case 'v': x.verbose = 1; break; --- remove.h.orig 2003-05-05 15:13:47.000000000 +0200 +++ remove.h 2003-05-05 15:14:13.000000000 +0200 @@ -18,6 +18,9 @@ Only works for the super-user. */ int unlink_dirs; + /* If nonzero, secure overwrites file contents */ + int secure; + /* If nonzero, display the name of each file removed. */ int verbose; };