wagglewunguswoo
This commit is contained in:
@@ -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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# [Original Project is secure-delete here](https://github.com/BlackArch/secure-delete)
|
||||||
@@ -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 */
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
+/* SRM BEGIN */
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+/* 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 <vh@reptile.rug.ac.be>"));
|
||||||
|
}
|
||||||
|
exit (status);
|
||||||
|
}
|
||||||
@@ -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 <sys/types.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
+/* SRM BEGIN */
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+/* SRM END */
|
||||||
|
+
|
||||||
|
#if HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#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 <bug-fileutils@gnu.org>."));
|
||||||
|
+ puts (_("\nWith secure_delete patch by van Hauser <vh@thc.org>"));
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
};
|
||||||
@@ -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 ... ");
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef _SDEL_LIB_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#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
|
||||||
@@ -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
|
||||||
@@ -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 <vh@thc.org>
|
||||||
|
|
||||||
|
.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)
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -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 <vh@thc.org>
|
||||||
|
|
||||||
|
.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)
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -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 <vh@thc.org>
|
||||||
|
|
||||||
|
.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)
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
@@ -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 <vh@thc.org>
|
||||||
|
|
||||||
|
.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)
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -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."
|
||||||
+6
-6
@@ -21,7 +21,7 @@ encrypty(){
|
|||||||
./secure-delete/srm -rz $encrypted_volume_name
|
./secure-delete/srm -rz $encrypted_volume_name
|
||||||
# check success of previous or die
|
# check success of previous or die
|
||||||
echo "Wiping deallocated RAM..."
|
echo "Wiping deallocated RAM..."
|
||||||
sudo ./secure-delete/smem -l -v
|
sudo ./.secure-delete/smem -l -v
|
||||||
echo "Success: Done"
|
echo "Success: Done"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,16 +31,16 @@ decrypty(){
|
|||||||
scrypt dec $encrypted_archive_name $encrypted_volume_name
|
scrypt dec $encrypted_archive_name $encrypted_volume_name
|
||||||
# check success of previous or die
|
# check success of previous or die
|
||||||
echo "Successfully Decrytped, Shredding Encrypted Archive..."
|
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
|
# check success of previous or die
|
||||||
echo "Successfully Shredded Encrypted Archive, Decompressing..."
|
echo "Successfully Shredded Encrypted Archive, Decompressing..."
|
||||||
tar xfj $encrypted_volume_name
|
tar xfj $encrypted_volume_name
|
||||||
# check success of previous or die
|
# check success of previous or die
|
||||||
echo "Successfully Decompressed Decrypted Archive, Shredding Decrypted Archive..."
|
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
|
# check success of previous or die
|
||||||
echo "Shredding deallocated RAM..."
|
echo "Shredding deallocated RAM..."
|
||||||
sudo ./secure-delete/smem -l -v
|
sudo ./.secure-delete/smem -l -v
|
||||||
echo "Success: Done"
|
echo "Success: Done"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,8 +55,8 @@ elif [ $1 = "install" ]; then
|
|||||||
echo "Success: Installed"
|
echo "Success: Installed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [ -f "./secure-delete/smem" ]; then
|
if ! [ -f "./.secure-delete/smem" ]; then
|
||||||
cd ./secure-delete && make
|
cd ./.secure-delete && make
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [ -d $dir_to_encrypt ]; then
|
if ! [ -d $dir_to_encrypt ]; then
|
||||||
|
|||||||
Submodule secure-delete deleted from b63d8140ae
Reference in New Issue
Block a user