--- logrotate-3.7.5/logrotate.h.shred 2007-05-14 09:25:50.000000000 +0200 +++ logrotate-3.7.5/logrotate.h 2007-05-14 10:27:48.000000000 +0200 @@ -16,6 +16,7 @@ #define LOG_FLAG_SHAREDSCRIPTS (1 << 7) #define LOG_FLAG_COPY (1 << 8) #define LOG_FLAG_DATEEXT (1 << 9) +#define LOG_FLAG_SHRED (1 << 10) #define NO_MODE ((mode_t) -1) #define NO_UID ((uid_t) -1) @@ -44,6 +45,7 @@ char *uncompress_prog; char *compress_ext; int flags; + int shred_cycles; /* if !=0, pass -n shred_cycles to GNU shred */ mode_t createMode; /* if any/all of these are -1, we use the */ uid_t createUid; /* attributes from the log file just rotated */ gid_t createGid; --- logrotate-3.7.5/logrotate.c.shred 2007-05-14 09:25:30.000000000 +0200 +++ logrotate-3.7.5/logrotate.c 2007-05-14 10:35:41.000000000 +0200 @@ -53,6 +53,8 @@ char *mailCommand = DEFAULT_MAIL_COMMAND; time_t nowSecs = 0; +static int shred_file(char * filename, logInfo *log); + static int globerr(const char *pathname, int theerr) { message(MESS_ERROR, "error accessing %s: %s\n", pathname, @@ -188,11 +190,54 @@ return fd; } -static int removeLogFile(char *name) +#define SHRED_CALL "shred -u " +#define SHRED_COUNT_FLAG "-n " +#define DIGITS 10 +/* unlink, but try to call shred from GNU fileutils */ +static int shred_file(char * filename, logInfo *log) +{ + int len, ret; + char *cmd; + char count[DIGITS]; /* that's a lot of shredding :) */ + + if (!(log->flags & LOG_FLAG_SHRED)) { + return unlink(filename); + } + + len = strlen(filename) + strlen(SHRED_CALL); + len += strlen(SHRED_COUNT_FLAG) + DIGITS; + cmd = malloc(len); + + if (!cmd) { + message(MESS_ERROR, "malloc error while shredding"); + return unlink(filename); + } + strcpy(cmd, SHRED_CALL); + if (log->shred_cycles != 0) { + strcat(cmd, SHRED_COUNT_FLAG); + snprintf(count, DIGITS - 1, "%d", log->shred_cycles); + strcat(count, " "); + strcat(cmd, count); + } + strcat(cmd, filename); + ret = system(cmd); + free(cmd); + if (ret != 0) { + message(MESS_ERROR, "Failed to shred %s\n, trying unlink", filename); + if (ret != -1) { + message(MESS_NORMAL, "Shred returned %d\n", ret); + } + return unlink(filename); + } else { + return ret; + } +} + +static int removeLogFile(char *name, logInfo *log) { message(MESS_DEBUG, "removing old log %s\n", name); - if (!debug && unlink(name)) { + if (!debug && shred_file(name, log)) { message(MESS_ERROR, "Failed to remove old log %s: %s\n", name, strerror(errno)); return 1; @@ -255,7 +300,7 @@ return 1; } - unlink(name); + shred_file(name, log); return 0; } @@ -697,7 +742,7 @@ mailCommand, logNum, log); if (!hasErrors) - hasErrors = removeLogFile(mailFilename); + hasErrors = removeLogFile(mailFilename, log); } mail_out = i; } @@ -737,7 +782,7 @@ mailLogWrapper(mailFilename, mailCommand, logNum, log); if (!hasErrors) - hasErrors = removeLogFile(mailFilename); + hasErrors = removeLogFile(mailFilename, log); } } } @@ -954,7 +999,7 @@ } if (!hasErrors && rotNames->disposeName) - hasErrors = removeLogFile(rotNames->disposeName); + hasErrors = removeLogFile(rotNames->disposeName, log); #ifdef WITH_SELINUX if (selinux_enabled) { --- logrotate-3.7.5/logrotate.8.shred 2007-05-14 09:26:02.000000000 +0200 +++ logrotate-3.7.5/logrotate.8 2007-05-14 10:42:16.000000000 +0200 @@ -330,6 +330,10 @@ not be executed for the affected log only. .TP +\fBnoshred\fR +Do not use \fBshred\fR when deleting old log files. See also \fBshred\fR. + +.TP \fBnotifempty\fR Do not rotate the log if it is empty (this overrides the \fBifempty\fR option). @@ -403,6 +407,16 @@ actions will not be executed for any logs. This option overrides the \fBnosharedscripts\fR option and implies \fBcreate\fR option. +.TP +\fBshred\fR +Delete log files using \fBshred\fR -u instead of unlink(). This should +ensure that logs are not readable after their scheduled deletion; this is +off by default. See also \fBnoshred\fR. + +.TP +\fBshredcycles\fR \fIcount\fR +Asks GNU \fBshred\fR to overwite log files \fBcount\fR times before +deletion. Without this option, \fBshred\fR's default will be used. .TP \fBstart \fIcount\fR --- logrotate-3.7.5/config.c.shred 2007-05-14 09:26:42.000000000 +0200 +++ logrotate-3.7.5/config.c 2007-05-14 10:32:37.000000000 +0200 @@ -432,6 +432,7 @@ /* uncompress_prog */ NULL, /* compress_ext */ NULL, /* flags */ LOG_FLAG_IFEMPTY, + /* shred_cycles */ 0, /* createMode/Uid/Gid */ NO_MODE, NO_UID, NO_GID, /* compress_options_list/count */ NULL, 0 }; @@ -638,6 +639,14 @@ newlog->flags &= ~LOG_FLAG_DELAYCOMPRESS; *endtag = oldchar, start = endtag; + } else if (!strcmp(start, "shred")) { + newlog->flags |= LOG_FLAG_SHRED; + + *endtag = oldchar, start = endtag; + } else if (!strcmp(start, "noshred")) { + newlog->flags &= ~LOG_FLAG_SHRED; + + *endtag = oldchar, start = endtag; } else if (!strcmp(start, "sharedscripts")) { newlog->flags |= LOG_FLAG_SHAREDSCRIPTS; @@ -833,7 +842,22 @@ *endtag = oldchar, start = endtag; } #endif - } else if (!strcmp(start, "daily")) { + } else if (!strcmp(start, "shredcycles")) { + *endtag = oldchar, start = endtag; + + if (!isolateValue(configFile, lineNum, "shred cycles", + &start, &endtag)) { + oldchar = *endtag, *endtag = '\0'; + + newlog->shred_cycles = strtoul(start, &chptr, 0); + if (*chptr || newlog->shred_cycles < 0) { + message(MESS_ERROR, "%s:%d bad shred cycles '%s'\n", + configFile, lineNum, start); + return 1; + } + *endtag = oldchar, start = endtag; + } + } else if (!strcmp(start, "daily")) { *endtag = oldchar, start = endtag; newlog->criterium = ROT_DAYS;