diff --git a/.secure-delete/Makefile b/.secure-delete/Makefile new file mode 100644 index 0000000..6d7b268 --- /dev/null +++ b/.secure-delete/Makefile @@ -0,0 +1,51 @@ +CC=gcc +OPT=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE +#OPT=-Wall -D_DEBUG_ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE +INSTALL_DIR=/usr/local/bin +MAN_DIR=/usr/local/man +DOC_DIR=/usr/share/doc/secure_delete +OPT_MOD=-D__KERNEL__ -DMODULE -fomit-frame-pointer -fno-strict-aliasing -pipe +#LD_MOD=-r + +all: sdel-lib.o srm sfill sswap smem + @echo + @echo "A Puritan is someone who is deathly afraid that someone, somewhere, is" + @echo "having fun." + @echo + @echo "I hope YOU have fun!" + @echo + +sdel-lib.o: sdel-lib.c + $(CC) ${OPT} -c sdel-lib.c + +srm: srm.c + $(CC) ${OPT} -o srm srm.c sdel-lib.o + -strip srm +sfill: sfill.c + $(CC) ${OPT} -o sfill sfill.c sdel-lib.o + -strip sfill +sswap: sswap.c + $(CC) ${OPT} -o sswap sswap.c sdel-lib.o + -strip sswap +smem: smem.c + $(CC) ${OPT} -o smem smem.c sdel-lib.o + -strip smem + +clean: + rm -f sfill srm sswap smem sdel sdel-lib.o core *~ + +install: all + mkdir -p -m 755 ${INSTALL_DIR} 2> /dev/null + rm -f sdel && ln -s srm sdel + cp -f sdel srm sfill sswap smem the_cleaner.sh ${INSTALL_DIR} + chmod 711 ${INSTALL_DIR}/srm ${INSTALL_DIR}/sfill ${INSTALL_DIR}/sswap ${INSTALL_DIR}/smem ${INSTALL_DIR}/the_cleaner.sh + mkdir -p -m 755 ${MAN_DIR}/man1 2> /dev/null + cp -f srm.1 sfill.1 sswap.1 smem.1 ${MAN_DIR}/man1 + chmod 644 ${MAN_DIR}/man1/srm.1 ${MAN_DIR}/man1/sfill.1 ${MAN_DIR}/man1/sswap.1 ${MAN_DIR}/man1/smem.1 + mkdir -p -m 755 ${DOC_DIR} 2> /dev/null + cp -f CHANGES FILES README secure_delete.doc usenix6-gutmann.doc ${DOC_DIR} + #-test -e sdel-mod.o && cp -f sdel-mod.o /lib/modules/`uname -r`/kernel/drivers/char +# @-test '!' -e sdel-mod.o -a `uname -s` = 'Linux' && echo "type \"make sdel-mod install\" to compile and install the Linux loadable kernel module for secure delete" + @echo + @echo "If men could get pregnant, abortion would be a sacrament." + @echo diff --git a/.secure-delete/README.md b/.secure-delete/README.md new file mode 100644 index 0000000..2756e03 --- /dev/null +++ b/.secure-delete/README.md @@ -0,0 +1 @@ +# [Original Project is secure-delete here](https://github.com/BlackArch/secure-delete) diff --git a/.secure-delete/config.h b/.secure-delete/config.h new file mode 100644 index 0000000..cc911f0 --- /dev/null +++ b/.secure-delete/config.h @@ -0,0 +1,5 @@ +#define BLOCKSIZE 32769 /* must be mod 3 = 0, should be >= 16k */ +#define RANDOM_DEVICE "/dev/urandom" /* must not exist */ +#define DIR_SEPERATOR '/' /* '/' on unix, '\' on dos/win */ +#define FLUSH sync() /* system call to flush the disk */ +#define MAXINODEWIPE 4194304 /* 22 bits */ diff --git a/.secure-delete/rm-fileutil-3.x.diff b/.secure-delete/rm-fileutil-3.x.diff new file mode 100644 index 0000000..b7c63b3 --- /dev/null +++ b/.secure-delete/rm-fileutil-3.x.diff @@ -0,0 +1,235 @@ +--- src/rm.c.orig Sat Nov 23 23:11:12 1996 ++++ src/rm.c Sun Jan 24 13:37:20 1999 +@@ -1,3 +1,10 @@ ++/* patch for rm from fileutils-3.16 to support secure data deletion ++ * to be activated by -s. -sss gives full erasure security (38 overwrites) ++ * This patch is from the secure_delete-2.0.tar.gz package available ++ * at http://www.thehackerschoice.com - get it, and read the documentation! ++ * (c)1999 by van Hauser / [THC] - The Hacker's Choice, vh@reptile.rug.ac.be ++ */ ++ + /* `rm' file deletion utility for GNU. + Copyright (C) 88, 90, 91, 94, 95, 1996 Free Software Foundation, Inc. + +@@ -21,6 +28,11 @@ + #include + #include + #include ++/* SRM BEGIN */ ++#include ++#include ++#include ++/* SRM END */ + + #include "system.h" + #include "error.h" +@@ -50,6 +62,14 @@ + int yesno (); + void strip_trailing_slashes (); + ++/* SRM BEGIN */ ++#define BLOCKSIZE 32769 ++#define DIR_SEPERATOR '/' ++#define FLUSH sync() ++#define RANDOM_DEVICE "/dev/urandom" ++/* SRM END */ ++ ++static int secure_delete (); + static int clear_directory __P ((struct stat *statp)); + static int duplicate_entry __P ((struct pathstack *stack, ino_t inum)); + static int remove_dir __P ((struct stat *statp)); +@@ -68,6 +88,12 @@ + /* Path of file now being processed; extended as necessary. */ + static char *pathname; + ++/* SRM BEGIN */ ++static int secure; /* secure overwrite mode */ ++static char fillbuf[BLOCKSIZE]; ++static FILE *devrandom; ++/* SRM END */ ++ + /* Number of bytes currently allocated for `pathname'; + made larger when necessary, but never smaller. */ + static int pnsize; +@@ -104,6 +130,9 @@ + {"force", no_argument, NULL, 'f'}, + {"interactive", no_argument, NULL, 'i'}, + {"recursive", no_argument, &recursive, 1}, ++/* SRM BEGIN */ ++ {"secure_delete", no_argument, NULL, 's'}, ++/* SRM END */ + {"verbose", no_argument, &verbose, 1}, + {"help", no_argument, &show_help, 1}, + {"version", no_argument, &show_version, 1}, +@@ -125,8 +154,8 @@ + = unlink_dirs = 0; + pnsize = 256; + pathname = xmalloc (pnsize); +- +- while ((c = getopt_long (argc, argv, "dfirvR", long_opts, (int *) 0)) != EOF) ++ ++ while ((c = getopt_long (argc, argv, "dfirsvR", long_opts, (int *) 0)) != EOF) + { + switch (c) + { +@@ -147,6 +176,11 @@ + case 'R': + recursive = 1; + break; ++/* SRM BEGIN */ ++ case 's': ++ secure++; ++ break; ++/* SRM END */ + case 'v': + verbose = 1; + break; +@@ -198,6 +232,116 @@ + exit (err > 0); + } + ++/* 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 (verbose) ++ printf(" "); ++ ++ ++ if (secure > 1) { ++ fill_buf(std_array); ++ for (counter=1; counter<=writes; counter++) ++ fwrite(&fillbuf, 1, BLOCKSIZE, f); ++ if (verbose) ++ printf("*"); ++ 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; ++ if (verbose) ++ printf("*"); ++ } ++ (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); ++ if (verbose) ++ printf(" wiped\n"); ++ return 0; ++} ++ ++/* SRM END */ ++ + /* Remove file or directory `pathname' after checking appropriate things. + Return 0 if `pathname' is removed, 1 if not. */ + +@@ -264,8 +408,16 @@ + return 1; + } + +- if (verbose) +- printf ("%s\n", pathname); ++ if (verbose) { ++ printf ("%s", pathname); ++ if (secure == 0) ++ printf ("\n"); ++ } ++ ++/* SRM BEGIN */ ++ if (secure) ++ secure_delete(pathname); ++/* SRM END */ + + if (unlink (pathname) && (errno != ENOENT || !ignore_missing_files)) + { +@@ -536,11 +688,13 @@ + -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_delete 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\ + ")); + puts (_("\nReport bugs to fileutils-bugs@gnu.ai.mit.edu")); ++ puts (_("\nWith secure_delete patch by van Hauser ")); + } + exit (status); + } diff --git a/.secure-delete/rm-fileutil-4.1.diff b/.secure-delete/rm-fileutil-4.1.diff new file mode 100644 index 0000000..b925692 --- /dev/null +++ b/.secure-delete/rm-fileutil-4.1.diff @@ -0,0 +1,249 @@ +--- 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; + }; diff --git a/.secure-delete/sdel-lib.c b/.secure-delete/sdel-lib.c new file mode 100644 index 0000000..508cc56 --- /dev/null +++ b/.secure-delete/sdel-lib.c @@ -0,0 +1,349 @@ +/* Secure Delete Library - by van Hauser / [THC], vh@thc.org + * + * Secure Delete Library provides the following public functions: + * + * void sdel_init(int secure_random) + * Initializiation function for sdel_overwrite. It needs to be called + * once at program start, not for each file to be overwritten. + * Options: + * secure_random - if != 0 defines that the secure random number + * generator RANDOM_DEVICE should be used + * + * void sdel_finnish() + * Clean-up function, if sdel_init() was called in a program. It needs + * only to be called at the end of the program. + * + * int sdel_overwrite(int mode, int fd, long start, unsigned long bufsize, + * unsigned long length, int zero) + * This is the heart of sdel-lib. It overwrites the target file + * descriptor securely to make life hard even for the NSA. + * Read the next paragraph for the techniques. + * Options: + * mode = 0 - once overwrite with random data + * 1 - once overwrite with 0xff, then once with random data + * 2 - overwrite 38 times with special values + * fd - filedescriptor of the target to overwrite + * start - where to start overwriting. 0 is from the beginning + * this is needed for wiping swap spaces etc. + * bufsize - size of the buffer to use for overwriting, depends + * on the filesystem + * length - amount of data to write (file size), 0 means until + * an error occurs + * zero - last wipe is zero bytes, not random + * returns 0 on success, -1 on errors + * + * int sdel_unlink(char *filename, int directory, int truncate, int slow) + * First truncates the file (if it is not a directory), then renames it + * and finally rmdir/unlinks the target. + * Options: + * filename - filename/directory to unlink/rmdir + * directory - if != 0, it is a directory + * truncate - if != 0, it truncates the file + * slow - is either O_SYNC (see open(2)) or 0 + * returns 0 on success, -1 on errors + * + * Compiles clean on OpenBSD, Linux, Solaris, AIX and I guess all others. + * + */ + +/* + * For security reasons full 32kb blocks are written so that the whole block + * on which the file(s) live are overwritten. (change #define #BLOCKSIZE) + * Standard mode is a real security wipe for 38 times, flushing + * the caches after every write. The wipe technique was proposed by Peter + * Gutmann at Usenix '96 and includes 10 random overwrites plus 28 special + * defined characters. Take a look at the paper of him, it's really worth + * your time. + * + * Read the manual for limitations. + */ + +#include "sdel-lib.h" + +// +// STARTING FUNCTIONS +// + +void __sdel_fill_buf(char pattern[3], unsigned long bufsize, char *buf) { + int loop; + int where; + + for (loop = 0; loop < (bufsize / 3); loop++) { + where = loop * 3; + *buf++ = pattern[0]; + *buf++ = pattern[1]; + *buf++ = pattern[2]; + } +} + +void __sdel_random_buf(unsigned long bufsize, char *buf) { + int loop; + + if (devrandom == NULL) + for (loop = 0; loop < bufsize; loop++) + *buf++ = (unsigned char) (256.0*rand()/(RAND_MAX+1.0)); + else + fread(buf, bufsize, 1, devrandom); +} + +void __sdel_random_filename(char *filename) { + int i; + for (i = strlen(filename) - 1; + (filename[i] != DIR_SEPERATOR) && (i >= 0); + i--) + if (filename[i] != '.') /* keep dots in the filename */ + filename[i] = 97+(int) ((int) ((256.0 * rand()) / (RAND_MAX + 1.0)) % 26); +} + +void sdel_init(int secure_random) { + + (void) setvbuf(stdout, NULL, _IONBF, 0); + (void) setvbuf(stderr, NULL, _IONBF, 0); + + if (BLOCKSIZE<16384) + fprintf(stderr, "Programming Warning: in-compiled blocksize is <16k !\n"); + if (BLOCKSIZE % 3 > 0) + fprintf(stderr, "Programming Error: in-compiled blocksize is not a multiple of 3!\n"); + + srand( (getpid()+getuid()+getgid()) ^ time(0) ); + devrandom = NULL; +#ifdef RANDOM_DEVICE + if (secure_random) { + if ((devrandom = fopen(RANDOM_DEVICE, "r")) != NULL) + if (verbose) + printf("Using %s for random input.\n", RANDOM_DEVICE); + } +#endif + + __internal_sdel_init = 1; +} + +void sdel_finnish() { + if (devrandom != NULL) { + fclose(devrandom); + devrandom = NULL; + } + if (! __internal_sdel_init) { + fprintf(stderr, "Programming Error: sdel-lib was not initialized before calling sdel_finnish().\n"); + return; + } + __internal_sdel_init = 0; +} + +/* + * secure_overwrite function parameters: + * mode = 0 : once overwrite with random data + * 1 : once overwrite with 0xff, then once with random data + * 2 : overwrite 38 times with special values + * fd : filedescriptor of the target to overwrite + * start : where to start overwriting. 0 is from the beginning + * bufsize : size of the buffer to use for overwriting, depends on the filesystem + * length : amount of data to write (file size), 0 means until an error occurs + * + * returns 0 on success, -1 on errors + */ +int sdel_overwrite(int mode, int fd, long start, unsigned long bufsize, unsigned long length, int zero) { + unsigned long writes; + unsigned long counter; + int turn; + int last = 0; + char buf[65535]; + FILE *f; + + if (! __internal_sdel_init) + fprintf(stderr, "Programming Error: sdel-lib was not initialized before sdel_overwrite().\n"); + + if ((f = fdopen(fd, "r+b")) == NULL) + return -1; + +/* calculate the number of writes */ + if (length > 0) + writes = (1 + (length / bufsize)); + else + writes = 0; + +/* do the first overwrite */ + if (start == 0) + rewind(f); + else + if (fseek(f, start, SEEK_SET) != 0) + return -1; + if (mode != 0 || zero) { + if (mode == 0) + __sdel_fill_buf(std_array_00, bufsize, buf); + else + __sdel_fill_buf(std_array_ff, bufsize, buf); + if (writes > 0) + for (counter=1; counter<=writes; counter++) + fwrite(&buf, 1, bufsize, f); // dont care for errors + else + do {} while(fwrite(&buf, 1, bufsize, f) == bufsize); + if (verbose) + printf("*"); + fflush(f); + if (fsync(fd) < 0) + FLUSH; + if (mode == 0) + return 0; + } + +/* do the rest of the overwriting stuff */ + for (turn = 0; turn <= 36; turn++) { + if (start == 0) + rewind(f); + else + if (fseek(f, start, SEEK_SET) != 0) + return -1; + if ((mode < 2) && (turn > 0)) + break; + if ((turn >= 5) && (turn <= 31)) { + __sdel_fill_buf(write_modes[turn-5], bufsize, buf); + if (writes > 0) + for (counter = 1; counter <= writes; counter++) + fwrite(&buf, 1, bufsize, f); // dont care for errors + else + do {} while(fwrite(&buf, 1, bufsize, f) == bufsize); + } else { + if (zero && ((mode == 2 && turn == 36) || mode == 1)) { + last = 1; + __sdel_fill_buf(std_array_00, bufsize, buf); + } + if (writes > 0) { + for (counter = 1; counter <= writes; counter++) { + if (! last) + __sdel_random_buf(bufsize, buf); + fwrite(&buf, 1, bufsize, f); // dont care for errors + } + } else { + do { + if (! last) + __sdel_random_buf(bufsize, buf); + } while (fwrite(&buf, 1, bufsize, f) == bufsize); // dont care for errors + } + } + fflush(f); + if (fsync(fd) < 0) + FLUSH; + if (verbose) + printf("*"); + } + + (void) fclose(f); +/* Hard Flush -> Force cached data to be written to disk */ + FLUSH; + + return 0; +} + +/* + * secure_unlink function parameters: + * filename : the file or directory to remove + * directory : defines if the filename poses a directory + * truncate : truncate file + * slow : do things slowly, to prevent caching + * + * returns 0 on success, -1 on errors. + */ +int sdel_unlink(char *filename, int directory, int truncate, int slow) { + int fd; + int turn = 0; + int result; + char newname[strlen(filename) + 1]; + struct stat filestat; + +/* open + truncating the file, so an attacker doesn't know the diskblocks */ + if (! directory && truncate) + if ((fd = open(filename, O_WRONLY | O_TRUNC | slow)) >= 0) + close(fd); + +/* Generate random unique name, renaming and deleting of the file */ + strcpy(newname, filename); // not a buffer overflow as it has got the exact length + + do { + __sdel_random_filename(newname); + if ((result = lstat(newname, &filestat)) >= 0) + turn++; + } while ((result >= 0) && (turn <= 100)); + + if (turn <= 100) { + result = rename(filename, newname); + if (result != 0) { + fprintf(stderr, "Warning: Couldn't rename %s - ", filename); + perror(""); + strcpy(newname, filename); + } + } else { + fprintf(stderr,"Warning: Couldn't find a free filename for %s!\n",filename); + strcpy(newname, filename); + } + + if (directory) { + result = rmdir(newname); + if (result) { + printf("Warning: Unable to remove directory %s - ", filename); + perror(""); + (void) rename(newname, filename); + } else + if (verbose) + printf("Removed directory %s ...", filename); + } else { + result = unlink(newname); + if (result) { + printf("Warning: Unable to unlink file %s - ", filename); + perror(""); + (void) rename(newname, filename); + } else + if (verbose) + printf(" Removed file %s ...", filename); + } + + if (result != 0) + return -1; + + return 0; +} + +void sdel_wipe_inodes(char *loc, char **array) { + char *template = malloc(strlen(loc) + 16); + int i = 0; + int fail = 0; + int fd; + + if (verbose) + printf("Wiping inodes ..."); + + array = malloc(MAXINODEWIPE * sizeof(template)); + strcpy(template, loc); + if (loc[strlen(loc) - 1] != '/') + strcat(template, "/"); + strcat(template, "xxxxxxxx.xxx"); + + while(i < MAXINODEWIPE && fail < 5) { + __sdel_random_filename(template); + if (open(template, O_CREAT | O_EXCL | O_WRONLY, 0600) < 0) + fail++; + else { + array[i] = malloc(strlen(template)); + strcpy(array[i], template); + i++; + } + } + FLUSH; + + if (fail < 5) { + fprintf(stderr, "Warning: could not wipe all inodes!\n"); + } + + array[i] = NULL; + fd = 0; + while(fd < i) { + unlink(array[fd]); + free(array[fd]); + fd++; + } + free(array); + array = NULL; + FLUSH; + if (verbose) + printf(" Done ... "); +} diff --git a/.secure-delete/sdel-lib.h b/.secure-delete/sdel-lib.h new file mode 100644 index 0000000..757795e --- /dev/null +++ b/.secure-delete/sdel-lib.h @@ -0,0 +1,40 @@ +#ifndef _SDEL_LIB_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +// +// STARTING CONSTANTS AND VARIABLES +// + +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_ff[3] = "\xff\xff\xff"; +unsigned char std_array_00[3] = "\x00\x00\x00"; + +FILE *devrandom = NULL; +int verbose = 0; +int __internal_sdel_init = 0; + +#define _SDEL_LIB_H_ +#endif diff --git a/.secure-delete/sdel.h b/.secure-delete/sdel.h new file mode 100644 index 0000000..acbab02 --- /dev/null +++ b/.secure-delete/sdel.h @@ -0,0 +1,36 @@ +#ifndef _SDEL_H + +#include "config.h" + +#define VERSION "v3.1" +#define AUTHOR "van Hauser / THC" +#define EMAIL "vh@thc.org" +#define WEB "http://www.thc.org" + +#ifndef O_SYNC + #ifdef O_FSYNC + #define O_SYNC O_FSYNC + #else + #define O_SYNC 0 + #endif +#endif + +#ifndef O_LARGEFILE + #define O_LARGEFILE 0 +#endif + +char *prg; + +extern int verbose; + +extern void sdel_init(int secure_random); +extern void sdel_finnish(); +extern int sdel_overwrite(int mode, int fd, long start, unsigned long bufsize, unsigned long length, int zero); +extern int sdel_unlink(char *filename, int directory, int truncate, int slow); +extern void sdel_wipe_inodes(char *loc, char **array); +extern void __sdel_fill_buf(char pattern[3], unsigned long bufsize, char *buf); +extern void __sdel_random_buf(unsigned long bufsize, char *buf); +extern void __sdel_random_filename(char *filename); + +#define _SDEL_H +#endif diff --git a/.secure-delete/sfill.1 b/.secure-delete/sfill.1 new file mode 100644 index 0000000..8ea1bda --- /dev/null +++ b/.secure-delete/sfill.1 @@ -0,0 +1,134 @@ +.\" This definition swiped from the gcc(1) man page +.de Sp +.if n .sp +.if t .sp 0.4 +.. +.TH SFILL 1 + +.SH NAME +sfill \- secure free disk and inode space wiper (secure_deletion toolkit) + +.SH SYNOPSIS +.B sfill [-f] [-i] [-I] [-l] [-l] [-v] [-z] directory/mountpoint + +.SH DESCRIPTION +.I sfill +is designed to delete data which lies on available diskspace on mediums +in a secure manner which can not be recovered by thiefs, law enforcement +or other threats. +The wipe algorythm is based on the paper "Secure Deletion of Data from +Magnetic and Solid-State Memory" presented at the 6th Usenix Security +Symposium by Peter Gutmann, one of the leading civilian cryptographers. +.PP +The +.I secure data deletion +process of sfill goes like this: +.PP +.TP +.B * +1 pass with 0xff +.TP +.B * +5 random passes. /dev/urandom is used for a secure RNG if available. +.TP +.B * +27 passes with special values defined by Peter Gutmann. +.TP +.B * +5 random passes. /dev/urandom is used for a secure RNG if available. +.PP +afterwards as many temporary files as possible are generated to wipe the +free inode space. After no more temporary files can be created, they are +removed and sfill is finnished. +.PP + +.SH COMMANDLINE OPTIONS +.PP +.TP +.B \-f +fast (and insecure mode): no /dev/urandom, no synchronize mode. +.TP +.B \-i +wipe only free inode space, not free disk space +.TP +.B \-I +wipe only free disk space, not free inode space +.TP +.B \-l +lessens the security. Only two passes are written: one mode with 0xff +and a final mode with random values. +.TP +.B \-l +-l for a second time lessons the security even more: only one random pass +is written. +.TP +.B \-v +verbose mode +.TP +.B \-z +wipes the last write with zeros instead of random data +.PP +.PP +.B directory/mountpoint +this is the location of the file created in your filesystem. It should +lie on the partition you want to write. +.PP + +.SH LIMITATIONS +.TP +.B FILESYSTEM INTELLIGENCE +Most filesystems (ext2, ffs, etc.) have several features included to enhance +performance, which will result in that sfill might not receive all available +free space. Sad but true. Nothing can be done about that ... +.TP +.B NFS +Beware of NFS. You can't ensure you really completely wiped your data +from the remote disks. (especially because of caching) +.TP +.B Raid +Raid Systems use stripped disks and have got large caches. It's hard to wipe +them. +.TP +.B swap +Some of your data might have a copy in your swapspace. +.I sswap +is available for this task. + +.PP +.SH BUGS +No bugs. There was never a bug in the secure_deletion package (in contrast +to my other tools, whew, good luck ;-) +Send me any that you find. Patches are nice too :) + +.SH AUTHOR +.Sp +van Hauser / THC +.I + +.SH DISTRIBUTION +The newest version of the +.I secure_deletion package +can be obtained from +.I http://www.thc.org +.Sp +.I sfill +and the +.I secure_deletion package +is (C) 1997-2003 by van Hauser / THC (vh@thc.org) +.Sp +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; Version 2. +.Sp +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +.SH SEE ALSO +.I srm +(1), +.I sswap +(1), +.I smem +(1) diff --git a/.secure-delete/sfill.c b/.secure-delete/sfill.c new file mode 100644 index 0000000..c67a6a8 --- /dev/null +++ b/.secure-delete/sfill.c @@ -0,0 +1,237 @@ +/* Secure FILL - by van Hauser / [THC], vh@thc.org + * + * Secure FILL overwrites all available free diskspace by creating a file, + * wiping all free diskspace it gets and finally deleting the file. + * + * Standard mode is a real security wipe for 38 times, flushing + * the caches after every write. The wipe technique was proposed by Peter + * Gutmann at Usenix '96 and includes 10 random overwrites plus 28 special + * defined characters. Take a look at the paper of him, it's really worth + * your time. + * The option -l overwrites two times the data. (0xff + random) + * The option -ll overwrites the data once. (random) + * New with v2.3: wipes all inodes in the defined directory + * + * Read the manual for limitations. + * Compiles clean on OpenBSD, Linux, Solaris and AIX + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdel.h" + +#ifdef BLOCKSIZE +#undef BLOCKSIZE +#endif +#define BLOCKSIZE 65535 +#define MAXINODEWIPE 4194304 /* 22 bits */ + +char **array = NULL; +int slow = O_SYNC; +int debug = 1; +int zero = 0; +int inode_only = 0; +int fd = -1; +char *filename = NULL; +FILE *f; + +void help() { + printf("sfill %s (c) 1997-2003 by %s <%s>\n\n", VERSION, AUTHOR, EMAIL); + printf("Syntax: %s [-fiIlvz] directory\n\n", prg); + printf("Options:\n"); + printf("\t-f fast (and insecure mode): no /dev/urandom, no synchronize mode.\n"); + printf("\t-i wipe only inodes in the directory specified\n"); + printf("\t-I just wipe space, not inodes\n"); + printf("\t-l lessens the security (use twice for total insecure mode).\n"); + printf("\t-v is verbose mode.\n"); + printf("\t-z last wipe writes zeros, not random data.\n"); + printf("\nsfill does a secure overwrite of the free space on the partition the specified\ndirectory resides and all free inodes of the directory specified.\n"); + printf("Default is secure mode (38 writes).\n"); + printf("You can find updates at %s\n", WEB); + exit(1); +} + +void cleanup(int signo) { + fprintf(stderr,"\nTerminated by signal. Clean exit.\n"); + if (fd > 0) { + fsync(fd); + (void) close(fd); + sync(); + if (filename != NULL && unlink(filename) != 0) + fprintf(stderr, "Error: Could not remove temporary file %s!\n", filename); + } + if (array != NULL) { + int i = 0; + while(array[i] != NULL) { + unlink(array[i]); + i++; + } + } + exit(1); +} + +int main (int argc, char *argv[]) { + int result; + int secure = 2; /* standard is secure mode */ + int loop; + int turn; + int counter; + struct stat filestat; + struct rlimit rlim; + char type[15] = "random"; + + if (getuid() != 0) + fprintf(stderr,"Warning: you are not root. You might not be able to wipe the whole filesystem.\n"); + + prg = argv[0]; + if (argc == 1 || strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--h", 3) == 0) + help(); + + while (1) { + result = getopt(argc, argv, "fFiIlLsSvVzZ"); + if (result < 0) + break; + switch (result) { + case 'f' : + case 'F' : slow = 0; + break; + case 'i' : inode_only = 1; + break; + case 'I' : inode_only = -1; + break; + case 'l' : + case 'L' : if (secure) secure--; + break; + case 's' : + case 'S' : secure++; + break; + case 'v' : + case 'V' : verbose++; + break; + case 'Z' : + case 'z' : zero++; + break; + default : help(); + } + } + loop = optind; + if (loop >= argc) + help(); + if (zero) strcpy(type, "zero"); + + do { + char newname[strlen(argv[loop]) + 16]; + strcpy(newname, argv[loop]); // can not overflow + if (opendir(newname) == NULL) { /* no need for ensuring close */ + fprintf(stderr, "Error: %s is not a directory\n", newname); + } else { + + /* Generate random unique name for tempfile */ + srand(getpid()+getuid()); + + if (newname[strlen(newname)-1] != DIR_SEPERATOR) + strcat(newname, "/"); + + turn = 0; result = 0; + strcat(newname, "oooooooo.ooo"); + result = lstat(newname, &filestat); + + while ((result >= 0) && (turn <= 250)) { + for (counter = strlen(newname)-1; + (newname[counter] != DIR_SEPERATOR); + counter--) + if (newname[counter] != '.') + newname[counter] = 97+(int) (27.0 * rand() / (RAND_MAX + 1.0)); + if ((result = lstat(newname, &filestat)) >= 0) + turn++; + }; + if (result >= 0) + fprintf(stderr,"Error: couldn't find a free filename in %s\n",argv[loop]); + else { + signal(SIGINT, cleanup); + signal(SIGTERM, cleanup); + signal(SIGHUP, cleanup); + + sdel_init(slow); + + if (verbose && inode_only < 1) { + switch (secure) { + case 0 : printf("Wipe mode is insecure (one pass [%s])\n",type); + break; + case 1 : printf("Wipe mode is insecure (two passes [0xff/%s])\n",type); + break; + default: printf("Wipe mode is secure (38 special passes)\n"); + } + printf("Wiping now ...\n"); + } + +#ifdef RLIM_INFINITY + #ifdef RLIMIT_FSIZE + rlim.rlim_cur = RLIM_INFINITY; + rlim.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_FSIZE, &rlim) != 0) + fprintf(stderr, "Warning: Could not reset ulimit for filesize.\n"); + #else + fprintf(stderr, "Warning: not compiled with support for resetting ulimit for filesize.\n"); + #endif +#else + fprintf(stderr, "Warning: not compiled with support for resetting ulimit for filesize.\n"); +#endif + + result = 9; + if (inode_only < 1) { + /* create the file */ + if (verbose) printf("Creating %s ... ", newname); + if ((fd = open(newname, O_RDWR | O_EXCL | O_CREAT | O_LARGEFILE | slow, 0600 )) < 0) + result = 1; + else { + filename = newname; + result = sdel_overwrite(secure, fd, 0, BLOCKSIZE, 0, zero); + /* Hard Flush -> Force cached data to be written to disk - the defines above! */ + FLUSH; + if ((fd = open(newname, O_WRONLY | O_TRUNC)) >= 0) + close(fd); + } + } + + if ((result == 0 && inode_only == 0) || inode_only > 0) { + if (result == 0 && inode_only == 0) + printf(" "); + sdel_wipe_inodes(argv[loop], array); + result = 0; + } + + switch (result) { + case 0 : if (verbose) printf(" Finished\n"); + break; + case 1 : fprintf(stderr, "Error: No write permission for %s. ", argv[loop]); + perror(""); + break; + case 9: break; + default: fprintf(stderr, "Unknown error\n"); + } + if (unlink(newname) != 0) + fprintf(stderr, "Error: Could not remove temporary file %s!\n", newname); + filename = NULL; + } + } + loop++; + } while (loop < argc); + + sdel_finnish(); + + exit(0); +} diff --git a/.secure-delete/smem.1 b/.secure-delete/smem.1 new file mode 100644 index 0000000..a5273bf --- /dev/null +++ b/.secure-delete/smem.1 @@ -0,0 +1,107 @@ +.\" This definition swiped from the gcc(1) man page +.de Sp +.if n .sp +.if t .sp 0.4 +.. +.TH SMEM 1 + +.SH NAME +smem \- secure memory wiper (secure_deletion toolkit) + +.SH SYNOPSIS +.B smem [-f] [-l] [-l] [-v] + +.SH DESCRIPTION +.I smem +is designed to delete data which may lie still in your memory (RAM) +in a secure manner which can not be recovered by thiefs, law enforcement +or other threats. +Note that with the new SDRAMs, data will not wither away but will be kept +static - it is easy to extract the necessary information! +The wipe algorythm is based on the paper "Secure Deletion of Data from +Magnetic and Solid-State Memory" presented at the 6th Usenix Security +Symposium by Peter Gutmann, one of the leading civilian cryptographers. +.PP +The +.I secure data deletion +process of smem goes like this: +.PP +.TP +.B * +1 pass with 0x00 +.TP +.B * +5 random passes. /dev/urandom is used for a secure RNG if available. +.TP +.B * +27 passes with special values defined by Peter Gutmann. +.TP +.B * +5 random passes. /dev/urandom is used for a secure RNG if available. +.PP + +.SH COMMANDLINE OPTIONS +.PP +.TP +.B \-f +fast (and insecure mode): no /dev/urandom. +.TP +.B \-l +lessens the security. Only two passes are written: the first with 0x00 +and a final random one. +.TP +.B \-l +-l for a second time lessons the security even more: only one pass with +0x00 is written. +.TP +.B \-v +verbose mode +.PP + +.SH BEWARE +.TP +.B SLOW +Wiping the memory is very slow. You might use smem with the -ll option. (tip) +.TP +.B BETA! +.I smem +is still beta. + +.PP +.SH BUGS +No bugs. There was never a bug in the secure_deletion package (in contrast +to my other tools, whew, good luck ;-) +Send me any that you find. Patches are nice too :) + +.SH AUTHOR +.Sp +van Hauser / THC +.I + +.SH DISTRIBUTION +The newest version of the +.I secure_deletion package +can be obtained from +.I http://www.thc.org +.Sp +.I smem +and the +.I secure_deletion package +is (C) 1997-2003 by van Hauser / THC (vh@thc.org) +.Sp +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; Version 2. +.Sp +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +.SH SEE ALSO +.I srm +(1), +.I sfill +(1), +.I sswap +(1) diff --git a/.secure-delete/smem.c b/.secure-delete/smem.c new file mode 100644 index 0000000..8c6f364 --- /dev/null +++ b/.secure-delete/smem.c @@ -0,0 +1,209 @@ +/* Secure MEMORY cleaner - by van Hauser / [THC], vh@thc.org + * + * Note that this program is beta. It was tested with linux, solaris and + * openbsd but I can't tell for other platforms. + * + * Secure MEMORY overwrites all data in your memory it gets. + * The any -l option this does a real security wipe for 38 times, flushing + * the caches after every write. The wipe technique was proposed by Peter + * Gutmann at Usenix '96 and includes 10 random overwrites plus 29 special + * defined characters. Take a look at the paper of him, it's really worth + * your time. + * If run with one -l option, it wipes the memory twice, first with null + * bytes, then with random values. + * If run with two -l options, it wipes the memory only once with null bytes. + * + * Note that it is *very* slow. You might run it with "-llf" + * + * Read the manual for limitations. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdel.h" + +#ifdef BLOCKSIZE +#undef BLOCKSIZE +#endif +#define BLOCKSIZE 65536 + +char buf[BLOCKSIZE+2]; +int slow = 1; + +extern FILE *devrandom; + +void help() { + printf("smem %s (c) 1997-2003 by %s <%s>\n\n", VERSION, AUTHOR, EMAIL); + printf("Syntax: %s [-flv]\n\n", prg); + printf("Options:\n"); + printf("\t-f fast (and insecure mode): no /dev/urandom.\n"); + printf("\t-l lessens the security (use twice for total insecure mode).\n"); + printf("\t-v is verbose mode.\n"); + printf("\nsmem does a secure overwrite of the memory (RAM), because memory contents can\n"); + printf("be recovered even after a shutdown! Default is secure mode (38 writes).\n"); + printf("You can find updates at %s\n", WEB); + exit(1); +} + +int smash_it(int mode) { + 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"} + }; + + int turn; + unsigned int counter = 0; + unsigned char buffers[27][BLOCKSIZE+2]; + char *ptr; + struct rlimit rlim; + + if (verbose) { + switch (mode) { + case 0 : printf("Wipe mode is insecure (one pass with 0x00)\n"); + break; + case 1 : printf("Wipe mode is insecure (two passes [0x00/random])\n"); break; + default: printf("Wipe mode is secure (38 special passes)\n"); + } + } + + if (slow && mode) + if ((devrandom = fopen(RANDOM_DEVICE, "r")) != NULL) + if (verbose) + printf("Using %s for random input.\n", RANDOM_DEVICE); + +/* We set a new ulimit, so we can grab all memory ... */ +#ifdef RLIM_INFINITY + rlim.rlim_cur = RLIM_INFINITY; + rlim.rlim_max = RLIM_INFINITY; + #ifdef RLIMIT_DATA + if (setrlimit(RLIMIT_DATA, &rlim) != 0) + fprintf(stderr, "Warning: Could not reset ulimit for data.\n"); + #endif + #ifdef RLIMIT_STACK + if (setrlimit(RLIMIT_STACK, &rlim) != 0) + fprintf(stderr, "Warning: Could not reset ulimit for stack.\n"); + #endif + #ifdef RLIMIT_RSS + if (setrlimit(RLIMIT_RSS, &rlim) != 0) + fprintf(stderr, "Warning: Could not reset ulimit for rss.\n"); + #endif + #ifdef RLIMIT_MEMLOCK + if (setrlimit(RLIMIT_MEMLOCK, &rlim) != 0) + fprintf(stderr, "Warning: Could not reset ulimit for mem locked.\n"); + #endif + #ifndef RLIMIT_DATA + #ifndef RLIMIT_STACK + #ifndef RLIMIT_RSS + #ifndef RLIMIT_MEMLOCK + fprintf(stderr, "Warning: Not compiled with support for resetting ulimits for memory\n"); + #endif + #endif + #endif + #endif +#else + fprintf(stderr, "Warning: Not compiled with support for resetting ulimits for memory\n"); +#endif + + if (mode > 1) { + for (turn=0; turn<27; turn++) { + __sdel_fill_buf(write_modes[turn], BLOCKSIZE + 2, buf); + memcpy(buffers[turn], buf, BLOCKSIZE); + } + } + + alarm(600); /* needed to prevent mem caching */ + + while ( (ptr = calloc(4096, 16)) != NULL) { + if (mode > 0) { + for (turn=0; turn<=36; turn++) { + if ((mode == 1) && (turn > 0)) break; + if ((turn>=5) && (turn<=31)) { + memcpy(ptr, buffers[turn-5], BLOCKSIZE); + } else { + __sdel_random_buf(BLOCKSIZE + 2, buf); + memcpy(ptr, buf, BLOCKSIZE); + } + } + } + if (verbose && (counter > 8)) { /* every 512kb */ + printf("*"); + counter = 0; + } else counter++; + } + + if (devrandom) + fclose(devrandom); + if (verbose) + printf(" done\n"); + return 0; +} + +void cleanup() { + fprintf(stderr,"Terminated by signal. Clean exit.\n"); + if (devrandom) + fclose(devrandom); + fflush(stdout); + fflush(stderr); + exit(1); +} + +int main (int argc, char *argv[]) { + int secure = 2; + int result; + + prg = argv[0]; + if (argc == 2) + if ( (strncmp(argv[1],"-h", 2) == 0) || (strcmp(argv[1],"-?") == 0) ) + help(); + + while (1) { + result = getopt(argc, argv, "FfLlSsVvZz"); + if (result<0) break; + switch (result) { + case 'F' : + case 'f' : slow = 0; + break; + case 'L' : + case 'l' : if (secure) secure--; + break; + case 'S' : + case 's' : secure++; + break; + case 'V' : + case 'v' : verbose++; + break; + case 'Z': + case 'z': break; + default : help(); + } + } + + if (optind < argc) + help(); + + printf("Starting Wiping the memory, press Control-C to abort earlier. Help: \"%s -h\"\n", prg); + + (void) setvbuf(stdout, NULL, _IONBF, 0); + signal(SIGINT, cleanup); + signal(SIGTERM, cleanup); + signal(SIGHUP, cleanup); + signal(SIGALRM, cleanup); + + smash_it(secure); + + /* thats all */ + exit(0); +} diff --git a/.secure-delete/srm.1 b/.secure-delete/srm.1 new file mode 100644 index 0000000..f54dae5 --- /dev/null +++ b/.secure-delete/srm.1 @@ -0,0 +1,140 @@ +.\" This definition swiped from the gcc(1) man page +.de Sp +.if n .sp +.if t .sp 0.4 +.. +.TH SRM 1 + +.SH NAME +srm \- secure remove (secure_deletion toolkit) + +.SH SYNOPSIS +.B srm [-d] [-f] [-l] [-l] [-r] [-v] [-z] files + +.SH DESCRIPTION +.I srm +is designed to delete data on mediums in a secure manner which can not be +recovered by thiefs, law enforcement or other threats. +The wipe algorythm is based on the paper "Secure Deletion of Data from +Magnetic and Solid-State Memory" presented at the 6th Usenix Security +Symposium by Peter Gutmann, one of the leading civilian cryptographers. +.PP +The +.I secure data deletion +process of srm goes like this: +.PP +.TP +.B * +1 pass with 0xff +.TP +.B * +5 random passes. /dev/urandom is used for a secure RNG if available. +.TP +.B * +27 passes with special values defined by Peter Gutmann. +.TP +.B * +5 random passes. /dev/urandom is used for a secure RNG if available. +.TP +.B * +Rename the file to a random value +.TP +.B * +Truncate the file +.PP +.PP +As an additional measure of security, the file is opened in O_SYNC mode +and after each pass an fsync() call is done. +.I srm +writes 32k blocks for the purpose of speed, filling buffers of disk caches +to force them to flush and overwriting old data which belonged to the file. +.PP + +.SH COMMANDLINE OPTIONS +.PP +.TP +.B \-d +ignore the two special dot files . and .. on the commandline. (so you can +execute it like "srm -d .* *") +.TP +.B \-f +fast (and insecure mode): no /dev/urandom, no synchronize mode. +.TP +.B \-l +lessens the security. Only two passes are written: one mode with 0xff +and a final mode random values. +.TP +.B \-l +-l for a second time lessons the security even more: only one random pass +is written. +.TP +.B \-r +recursive mode, deletes all subdirectories. +.TP +.B \-v +verbose mode +.TP +.B \-z +wipes the last write with zeros instead of random data +.PP + +.SH LIMITATIONS +.TP +.B NFS +Beware of NFS. You can't ensure you really completely wiped your data +from the remote disks. +.TP +.B Raid +Raid Systems use stripped disks and have got large caches. It's hard to wipe +them. +.TP +.B swap, /tmp, etc. +Some of your data might have a temporary (deleted) copy somewhere on the +disk. You should use +.I sfill +which comes with the +.I secure_deletion package +to ensure to wipe also the free diskspace. However, If already a small +file aquired a block with your precious data, no tool known to me can help +you here. For a secure deletion of the swap space +.I sswap +is available. + +.PP +.SH BUGS +No bugs. There was never a bug in the secure_deletion package (in contrast +to my other tools, whew, good luck ;-) +Send me any that you find. Patches are nice too :) + +.SH AUTHOR +.Sp +van Hauser / THC +.I + +.SH DISTRIBUTION +The newest version of the +.I secure_deletion package +can be obtained from +.I http://www.thc.org +.Sp +.I srm +and the +.I secure_deletion package +is (C) 1997-2003 by van Hauser / THC (vh@thc.org) +.Sp +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; Version 2. +.Sp +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +.SH SEE ALSO +.I sfill +(1), +.I sswap +(1), +.I smem +(1) diff --git a/.secure-delete/srm.c b/.secure-delete/srm.c new file mode 100644 index 0000000..0eea7f5 --- /dev/null +++ b/.secure-delete/srm.c @@ -0,0 +1,309 @@ +/* Secure RM - by van Hauser / [THC], vh@thc.org + * + * Secure ReMove first overwrites then renames and finally deletes the target + * file(s) specified via parameters. + * For security reasons full 32kb blocks are written so that the whole block + * on which the file(s) live are overwritten. (change #define #BLOCKSIZE) + * The option -l overwrites two times the data. + * The option -ll overwrites the data once. + * Standard mode is a real security wipe for 38 times, flushing + * the caches after every write. The wipe technique was proposed by Peter + * Gutmann at Usenix '96 and includes 10 random overwrites plus 28 special + * defined characters. Take a look at the paper of him, it's really worth + * your time. + * + * Advice : set "alias rm 'srm -v'" + * + * Read the manual for limitations. + * Compiles clean on OpenBSD, Linux, Solaris, AIX and I guess all others. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdel.h" + +int slow = O_SYNC; +int recursive = 0; +int zero = 0; +unsigned long bufsize = BLOCKSIZE; +int fd; + +void help () { + printf("srm %s (c) 1997-2003 by %s <%s>\n\n", VERSION, AUTHOR, EMAIL); + printf("Syntax: %s [-dflrvz] file1 file2 etc.\n\n", prg); + printf("Options:\n"); + printf("\t-d ignore the two dot special files \".\" and \"..\".\n"); + printf("\t-f fast (and insecure mode): no /dev/urandom, no synchronize mode.\n"); + printf("\t-l lessens the security (use twice for total insecure mode).\n"); + printf("\t-r recursive mode, deletes all subdirectories.\n"); + printf("\t-v is verbose mode.\n"); + printf("\t-z last wipe writes zeros instead of random data.\n"); + printf("\nsrm does a secure overwrite/rename/delete of the target file(s).\n"); + printf("Default is secure mode (38 writes).\n"); + printf("You can find updates at %s\n", WEB); + exit(1); +} + +int smash_it(char *filename, int mode) { + struct stat filestat; + struct stat controlstat; + int i_am_a_directory = 0; + +/* get the file stats */ + if (lstat(filename, &filestat)) + return 1; + + if (S_ISREG(filestat.st_mode) && filestat.st_nlink > 1) { + fprintf(stderr, "Error: File %s - file is hardlinked %d time(s), skipping!\n", filename, filestat.st_nlink - 1); + return -1; + } + +/* if the blocksize on the filesystem is bigger than the on compiled with, enlarge! */ + if (filestat.st_blksize > bufsize) { + if (filestat.st_blksize > 65532) { + bufsize = 65535; + } else { + bufsize = (((filestat.st_blksize / 3) + 1) * 3); + } + } + +/* handle the recursive mode */ + if (recursive) + if (S_ISDIR(filestat.st_mode)) { + DIR *dir; + struct dirent *dir_entry; + struct stat cwd_stat; + char current_dir[4097]; + int res; + int chdir_success = 1; + + if (verbose) printf("DIRECTORY (going recursive now)\n"); + getcwd(current_dir, 4096); + current_dir[4096] = '\0'; + + /* a won race will chmod a file to 0700 if the user is owner/root + I'll think about a secure solution to this, however, I think + there isn't one - anyone with an idea? */ + if (chdir(filename)) { + (void) chmod(filename, 0700); /* ignore permission errors */ + if (chdir(filename)) { + fprintf(stderr,"Can't chdir() to %s, hence I can't wipe it.\n", filename); + chdir_success = 0; + } + } + + if (chdir_success) { + lstat(".", &controlstat); + lstat("..", &cwd_stat); + if ( (filestat.st_dev != controlstat.st_dev) || (filestat.st_ino != controlstat.st_ino) ) { + fprintf(stderr, "Race found! (directory %s became a link)\n", filename); + } else { + if ((dir = opendir (".")) != NULL) { + (void) chmod(".", 0700); /* ignore permission errors */ + dir = opendir ("."); + } + if (dir != NULL) { + while ((dir_entry = readdir(dir)) != NULL) + if (strcmp(dir_entry->d_name, ".") && strcmp(dir_entry->d_name, "..")) { + if (verbose) printf("Wiping %s ", dir_entry->d_name); + if ( (res = smash_it(dir_entry->d_name, mode)) > 0) { + if (res == 3) + fprintf(stderr,"File %s was raced, hence I won't wipe it.\n", dir_entry->d_name); + else { + fprintf(stderr,"Couldn't delete %s. ", dir_entry->d_name); + perror(""); + } + } else + if (verbose) printf(" Done\n"); + } + closedir(dir); + } + } + if(chdir(current_dir) != 0) { + fprintf(stderr, "Error: Can't chdir to %s (aborting) - ", current_dir); + perror(""); + exit(1); + } +/* + lstat(current_dir, &controlstat); + if ( (cwd_stat.st_dev != controlstat.st_dev) || (cwd_stat.st_ino != controlstat.st_ino) ) { + fprintf(stderr, "Race found! (directory %s was exchanged or its your working directory)\n", current_dir); + exit(1); + } +*/ + i_am_a_directory = 1; + } + } +/* end of recursive function */ + + + if (S_ISREG(filestat.st_mode)) { + + /* open the file for writing in sync. mode */ + if ((fd = open(filename, O_RDWR | O_LARGEFILE | slow)) < 0) { + /* here again this has a race problem ... hmmm */ + /* make it writable for us if possible */ + (void) chmod(filename, 0600); /* ignore errors */ + if ((fd = open(filename, O_RDWR | O_LARGEFILE | slow)) < 0) + return 1; + } + + fstat(fd, &controlstat); + if ((filestat.st_dev != controlstat.st_dev) || (filestat.st_ino != controlstat.st_ino) || (! S_ISREG(controlstat.st_mode))) { + close(fd); + return 3; + } + + if (sdel_overwrite(mode, fd, 0, bufsize, filestat.st_size > 0 ? filestat.st_size : 1, zero) == 0) + return sdel_unlink(filename, 0, 1, slow); + } /* end IS_REG() */ + else { + if (S_ISDIR(filestat.st_mode)) { + if (i_am_a_directory == 0) { + fprintf(stderr,"Warning: %s is a directory. I will not remove it, because the -r option is missing!\n", filename); + return 0; + } else + return sdel_unlink(filename, 1, 0, slow); + } else + if (! S_ISDIR(filestat.st_mode)) { + fprintf(stderr,"Warning: %s is not a regular file, rename/unlink only!", filename); + if (! verbose) + printf("\n"); + return sdel_unlink(filename, 0, 0, slow); + } + } + + return 99; // not reached +} + +void cleanup(int signo) { + fprintf(stderr,"Terminated by signal. Clean exit.\n"); + if (fd >= 0) + close(fd); + FLUSH; + exit(1); +} + +int main (int argc, char *argv[]) { + int errors = 0; + int dot = 0; + int result; + int secure = 2; /* Standard is now SECURE mode (38 overwrites) [since v2.0] */ + int loop; + struct rlimit rlim; + + prg = argv[0]; + if (argc < 2 || strncmp(argv[1], "-h", 2) == 0|| strncmp(argv[1], "--h", 3) == 0) + help(); + + while (1) { + result = getopt(argc, argv, "DdFfLlRrSsVvZz"); + if (result < 0) break; + switch (result) { + case 'd' : + case 'D' : dot = 1; + break; + case 'F' : + case 'f' : slow = 0; + break; + case 'L' : + case 'l' : if (secure) secure--; + break; + case 'R' : + case 'r' : recursive++; + break; + case 'S' : + case 's' : secure++; + break; + case 'V' : + case 'v' : verbose++; + break; + case 'Z' : + case 'z' : zero++; + break; + default : help(); + } + } + loop = optind; + if (loop == argc) + help(); + + signal(SIGINT, cleanup); + signal(SIGTERM, cleanup); + signal(SIGHUP, cleanup); + + sdel_init(slow); + + if (verbose) { + char type[15] = "random"; + if (zero) strcpy(type, "zero"); + switch (secure) { + case 0 : printf("Wipe mode is insecure (one pass [%s])\n",type); + break; + case 1 : printf("Wipe mode is insecure (two passes [0xff/%s])\n",type); + break; + default: printf("Wipe mode is secure (38 special passes)\n"); + } + } + +#ifdef RLIM_INFINITY + #ifdef RLIMIT_FSIZE + rlim.rlim_cur = RLIM_INFINITY; + rlim.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_FSIZE, &rlim) != 0) + fprintf(stderr, "Warning: Could not reset ulimit for filesize.\n"); + #else + fprintf(stderr, "Warning: Not compiled with support for resetting ulimit filesize.\n"); + #endif +#endif + + while (loop < argc) { + char rmfile[strlen(argv[loop]) + 1]; + strcpy(rmfile, argv[loop]); + loop++; + if (strcmp("/", rmfile) == 0) { + fprintf(stderr,"Warning: Do you really want to remove the ROOT directory??\n"); + fprintf(stderr,"I'm giving you 5 seconds to abort ... press Control-C\n"); + sleep(6); + fprintf(stderr,"Doing my evil work now, don't whimp later, you had been informed!\n"); + } + if (dot) + if ((strcmp(".", rmfile) == 0) || (strcmp("..", rmfile) == 0)) + continue; + if (verbose) + printf("Wiping %s ", rmfile); + result = (int) smash_it(rmfile, secure); + switch (result) { + case 0 : if (verbose) printf(" Done\n"); + break; + case 1 : fprintf(stderr, "Error: File %s - ", rmfile); + perror(""); + break; + case -1: break; + case 3 : fprintf(stderr, "File %s was raced, hence I won't wipe it!\n", rmfile); + break; + default: fprintf(stderr, "Unknown error\n"); + } + if (result) + errors++; + } + + sdel_finnish(); + + if (errors) + return 1; + else + return 0; +} diff --git a/.secure-delete/sswap.1 b/.secure-delete/sswap.1 new file mode 100644 index 0000000..4b947a3 --- /dev/null +++ b/.secure-delete/sswap.1 @@ -0,0 +1,110 @@ +.\" This definition swiped from the gcc(1) man page +.de Sp +.if n .sp +.if t .sp 0.4 +.. +.TH SSWAP 1 + +.SH NAME +sswap \- secure swap wiper (secure_deletion toolkit) + +.SH SYNOPSIS +.B sswap [-f] [-l] [-l] [-v] [-z] swapdevice + +.SH DESCRIPTION +.I sswap +is designed to delete data which may lie still on your swapspace +in a secure manner which can not be recovered by thiefs, law enforcement +or other threats. +The wipe algorythm is based on the paper "Secure Deletion of Data from +Magnetic and Solid-State Memory" presented at the 6th Usenix Security +Symposium by Peter Gutmann, one of the leading civilian cryptographers. +.PP +The +.I secure data deletion +process of sswap goes like this: +.PP +.TP +.B * +1 pass with 0xff +.TP +.B * +5 random passes. /dev/urandom is used for a secure RNG if available. +.TP +.B * +27 passes with special values defined by Peter Gutmann. +.TP +.B * +5 random passes. /dev/urandom is used for a secure RNG if available. +.PP + +.SH COMMANDLINE OPTIONS +.PP +.TP +.B \-f +fast (and insecure mode): no /dev/urandom, no synchronize mode. +.TP +.B \-l +lessens the security. Only two passes are written: one mode with 0xff and +a final mode with random values. +.TP +.B \-l +-l for a second time lessons the security even more: only one pass with +random values is written. +.TP +.B \-v +verbose mode +.TP +.B \-z +wipes the last write with zeros instead of random data +.PP + +.SH BEWARE +.TP +.B swapoff +unmount your swapspace before using this tool! Otherwise your system might +crash! +.TP +.B BETA! +.I sswap +is still beta. It was only tested on Linux but on this system it performed +it's work all of the time. + +.PP +.SH BUGS +No bugs. There was never a bug in the secure_deletion package (in contrast +to my other tools, whew, good luck ;-) +Send me any that you find. Patches are nice too :) + +.SH AUTHOR +.Sp +van Hauser / THC +.I + +.SH DISTRIBUTION +The newest version of the +.I secure_deletion package +can be obtained from +.I http://www.thc.org +.Sp +.I sswap +and the +.I secure_deletion package +is (C) 1997-2003 by van Hauser / THC (vh@thc.org) +.Sp +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; Version 2. +.Sp +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +.SH SEE ALSO +.I srm +(1), +.I sfill +(1), +.I smem +(1) diff --git a/.secure-delete/sswap.c b/.secure-delete/sswap.c new file mode 100644 index 0000000..ae2199f --- /dev/null +++ b/.secure-delete/sswap.c @@ -0,0 +1,160 @@ +/* Secure SWAP cleaner - by van Hauser / [THC], vh@thc.org + * + * Note that this program is beta. It was tested with linux, but I can't + * tell for other platforms. Read the statement at #define SWAP_PAGESIZE + * on how to use this program on other unix machines. + * + * of course: you have to turn of the swapspace before using this program ! + * + * Secure SWAP overwrites all data on your swap device. + * Standard mode is a real security wipe for 38 times, flushing + * the caches after every write. The wipe technique was proposed by Peter + * Gutmann at Usenix '96 and includes 10 random overwrites plus 28 special + * defined characters. Take a look at the paper of him, it's really worth + * your time. + * The option -l overwrites two times the data. (0xff + random) + * The option -ll overwrites the data once. (random) + * + * Read the manual for limitations. + * Compiles clean on OpenBSD, Linux, Solaris and AIX + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdel.h" + +/* SWAP_PAGESIZE is an important variable. You have to set this + * to your header length of your swapdevice. For Linux this is 4096, + * I don't know for the other OSs. To be sure, set this to 0 and + * recreate your swapspace afterwards (for linux: mkswap /dev/swapdevice) + */ +#define SWAP_PAGESIZE 4096 +#ifdef BLOCKSIZE + #undef BLOCKSIZE +#endif +#define BLOCKSIZE 65535 + +int fd; +int slow = O_SYNC; +int zero = 0; + +void help() { + printf("sswap %s (c) 1997-2003 by %s <%s>\n\n", VERSION, AUTHOR, EMAIL); + printf("Syntax: %s [-flvz] [-j start] /dev/of_swap_device\n\n", prg); + printf("Options:\n"); + printf("\t-f fast (and insecure mode): no /dev/urandom, no synchronize mode.\n"); + printf("\t-j jump over the first number of bytes when wiping. (default: %d)\n", SWAP_PAGESIZE); + printf("\t-l lessens the security (use twice for total insecure mode).\n"); + printf("\t-v is verbose mode.\n"); + printf("\t-z last wipe writes zeros instead of random data.\n"); + printf("\nsswap does a secure overwrite of the swap space.\n"); + printf("Default is secure mode (38 writes).\n"); + printf("Updates can be found at %s\n", WEB); + printf("\nNOTE: You must disable the swapspace before using this program!\007\n"); + exit(1); +} + +void cleanup() { + fprintf(stderr,"\nTerminated by signal. Clean exit.\n"); + close(fd); + sync(); + exit(1); +} + +int main (int argc, char *argv[]) { + int secure = 2; + int result; + int mode; + unsigned long start = SWAP_PAGESIZE; + struct stat stats; + char *filename; + + prg = argv[0]; + if (argc == 1 || strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--h", 3) == 0) + help(); + + while (1) { + result = getopt(argc, argv, "FfJ:j:LlSsVvZz"); + if (result<0) break; + switch (result) { + case 'F' : + case 'f' : slow = 0; + break; + case 'J' : + case 'j' : start = atol(optarg); + if (start < 0 || start > 65535) { + fprintf(stderr, "Error: The -j option must be set between 0 and 65535!\n"); + exit(-1); + } + break; + case 'L' : + case 'l' : if (secure) secure--; + break; + case 'S' : + case 's' : secure++; + break; + case 'V' : + case 'v' : verbose++; + break; + case 'Z' : + case 'z' : zero++; + break; + default : help(); + } + } + + if ((optind+1) != argc) + help(); + + signal(SIGINT, cleanup); + signal(SIGTERM, cleanup); + signal(SIGHUP, cleanup); + + filename = argv[optind]; + mode = secure; + + if ((fd = open (filename, O_RDWR | O_LARGEFILE | slow)) < 0) { + fprintf(stderr, "Error: Can't open %s for writing.", filename); + perror(""); + exit(1); + } + + fstat(fd, &stats); + if (!S_ISBLK(stats.st_mode)) { + fprintf(stderr, "Error: Target is not a block device - %s\n", filename); + exit(1); + } + + if (verbose) { + char type[15] = "random"; + if (zero) strcpy(type, "zero"); + switch (mode) { + case 0 : printf("Wipe mode is insecure (one pass [%s])\n",type); + break; + case 1 : printf("Wipe mode is insecure (two passes [0xff/%s])\n",type); + break; + default: printf("Wipe mode is secure (38 special passes)\n"); + } + printf("Writing to device %s: ", filename); + } + + sdel_init(slow); + + if (sdel_overwrite(mode, fd, start, BLOCKSIZE, 0, zero) == 0) + if (verbose) + printf(" done\n"); + + sdel_finnish(); + + /* thats all */ + exit(0); +} diff --git a/.secure-delete/the_cleaner.sh b/.secure-delete/the_cleaner.sh new file mode 100644 index 0000000..b881076 --- /dev/null +++ b/.secure-delete/the_cleaner.sh @@ -0,0 +1,126 @@ +#!/bin/sh +# +# THE CLEANER SCRIPT +# Part of the secure_data_deletion toolkit by van Hauser / THC +# Run at your own risk. Tested on Linux only. +# +# Run this to wipe your system as most as possible with automatic stuff. +# You should run this in the STOP runlevels 2 and 3. +# +# ------------------------------------------------------------------------ +# +# Please configure the following variables: +# +# +# WIPE_MODE: 1-3 +# 1: highly secure mode (38 wipes) +# 2: insecure mode (2 wipes) +# 3: highly insecure mode (1 wipe) +WIPE_MODE=3 +# +# +# WIPE_FAST: yes/no +# yes: dont use a secure random number generator, less secure +# no: use a secure random number generator, secure +WIPE_FAST=yes +# +# +# WIPE_VERBOSE: yes/no +# yes: write verbose messages +# no: only write if error/warnings occur +WIPE_VERBOSE=yes +# +# +# WIPE_DIRECTORIES: directories you want to wipe completely all files and +# subdirectories from. Usually /tmp, /usr/tmp and /var/tmp. +WIPE_DIRECTORIES="/tmp /usr/tmp /var/tmp" +# +# WIPE_USER_FILES: files you want to wipe from user directories. Usually +# .*history*, .netscape/cache/*, .netscape/history*, +# .netscape/cookies, tmp/*, *~ and core +WIPE_USER_FILES=".*history* .netscape/cache/ .netscape/history* \ + .netscape/cookies .lynx_cookies tmp/* *~ .gqview_thmb/ dead.letter core" + +# ------------------------------------------------------------------------ +# +# Preparation Phase +# +test "$WIPE_MODE" -gt 0 -a "$WIPE_MODE" -lt 4 || { + echo "WIPE_MODE must be a value between 1 and 3." + exit 1 +} +test "$WIPE_FAST" = yes -o "$WIPE_FAST" = "no" || { + echo "WIPE_FAST must be either yes or no." + exit 1 +} +test "$WIPE_VERBOSE" = yes -o "$WIPE_VERBOSE" = "no" || { + echo "WIPE_VERBOSE must be either yes or no." + exit 1 +} +MODE="" +test "$WIPE_MODE" -eq 2 && MODE="-l" +test "$WIPE_MODE" -eq 3 && MODE="-ll" +FAST="" +test "$WIPE_FAST" = yes && FAST="-f" +VERBOSE="" +test "$WIPE_VERBOSE" = yes && VERBOSE="-v" + +# ------------------------------------------------------------------------ +# +# Starting the wiping process +# + +# Wipe directories +test -z "$VERBOSE" || echo "STARTING THE CLEANER." +test -z "$VERBOSE" || echo "CLEANER: Wiping directory contents" +for i in $WIPE_DIRECTORIES; do + test -z "$i" -o "$i" = "." -o "$i" = ".." -o "$i" = "/" || { + test -z "$VERBOSE" || echo " $i" + cd "$i" && srm $MODE $FAST -d -r -- .* * + } +done + +# Wipe files +test -z "$VERBOSE" || echo "CLEANER: Wiping user files" +awk -F: '{ print $1 " " $6 }' /etc/passwd | +while read user homedir; do + test "$homedir" = "" -o "$homedir" = "." -o "$homedir" = ".." || { + cd "$homedir" && { + test -z "$VERBOSE" || echo " $user" + for j in $WIPE_USER_FILES; do + test -z "$j" || { + test -L "$j" || { + test -e "$j" && srm $MODE $FAST -d -r -- $j +# test -e "$j" && "i would wipe: $j" + } + } + done + } + } +done + +# Wipe free space and inodes +test -z "$VERBOSE" || echo "CLEANER: Wiping free space and inodes on filesystems" +for i in `mount|grep -E '^/dev/.* type ext'|awk '{print$3}'`; do + test -z "$VERBOSE" || echo " $i" + test -z "$i" || sfill $MODE $FAST "$i" +done + +# Now the swap space: +test -z "$VERBOSE" || echo "CLEANER: Wiping swap space" +#ACTIVE=`swapoff -s|grep ^/dev/|awk '{print$1}'` +swapoff -a +for i in `(grep -w swap /etc/fstab|awk '{print$1}';echo "$ACTIVE";)|sort -u`; do + test -z "$VERBOSE" || echo " $i" + test -z "$i" || sswap $MODE $FAST "$i" +done + +# Finally the memory: +test -z "$VERBOSE" || echo "CLEANER: Wiping the memory" +smem $MODE $FAST +# + +swapon -a + +# FINNISHED! +test -z "$VERBOSE" || echo "THE CLEANER FINNISHED." diff --git a/hiddencrypto.sh b/hiddencrypto.sh index 84c6ea6..b09a9d4 100644 --- a/hiddencrypto.sh +++ b/hiddencrypto.sh @@ -21,7 +21,7 @@ encrypty(){ ./secure-delete/srm -rz $encrypted_volume_name # check success of previous or die echo "Wiping deallocated RAM..." - sudo ./secure-delete/smem -l -v + sudo ./.secure-delete/smem -l -v echo "Success: Done" } @@ -31,16 +31,16 @@ decrypty(){ scrypt dec $encrypted_archive_name $encrypted_volume_name # check success of previous or die echo "Successfully Decrytped, Shredding Encrypted Archive..." - ./secure-delete/srm -rz $encrypted_archive_name + ./.secure-delete/srm -rz $encrypted_archive_name # check success of previous or die echo "Successfully Shredded Encrypted Archive, Decompressing..." tar xfj $encrypted_volume_name # check success of previous or die echo "Successfully Decompressed Decrypted Archive, Shredding Decrypted Archive..." - ./secure-delete/srm -rz $encrypted_volume_name + ./.secure-delete/srm -rz $encrypted_volume_name # check success of previous or die echo "Shredding deallocated RAM..." - sudo ./secure-delete/smem -l -v + sudo ./.secure-delete/smem -l -v echo "Success: Done" } @@ -55,8 +55,8 @@ elif [ $1 = "install" ]; then echo "Success: Installed" fi - if ! [ -f "./secure-delete/smem" ]; then - cd ./secure-delete && make + if ! [ -f "./.secure-delete/smem" ]; then + cd ./.secure-delete && make fi if ! [ -d $dir_to_encrypt ]; then diff --git a/secure-delete b/secure-delete deleted file mode 160000 index b63d814..0000000 --- a/secure-delete +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b63d8140ae57b3df1e66ba5c91547b139f716bfb