wagglewunguswoo
This commit is contained in:
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user