diff options
-rw-r--r-- | sbin/pflogd/pflogd.c | 49 | ||||
-rw-r--r-- | sbin/pflogd/pflogd.h | 3 | ||||
-rw-r--r-- | sbin/pflogd/privsep.c | 69 |
3 files changed, 106 insertions, 15 deletions
diff --git a/sbin/pflogd/pflogd.c b/sbin/pflogd/pflogd.c index 598d7b434db..d8483188a54 100644 --- a/sbin/pflogd/pflogd.c +++ b/sbin/pflogd/pflogd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pflogd.c,v 1.34 2005/07/04 22:35:48 deraadt Exp $ */ +/* $OpenBSD: pflogd.c,v 1.35 2006/01/15 16:38:04 canacar Exp $ */ /* * Copyright (c) 2001 Theo de Raadt @@ -73,7 +73,7 @@ int flush_buffer(FILE *); int init_pcap(void); void logmsg(int, const char *, ...); void purge_buffer(void); -int reset_dump(void); +int reset_dump(int); int scan_dump(FILE *, off_t); int set_snaplen(int); void set_suspended(int); @@ -82,6 +82,8 @@ void sig_close(int); void sig_hup(int); void usage(void); +static int try_reset_dump(int); + /* buffer must always be greater than snaplen */ static int bufpkt = 0; /* number of packets in buffer */ static int buflen = 0; /* allocated size of buffer */ @@ -228,7 +230,25 @@ set_snaplen(int snap) } int -reset_dump(void) +reset_dump(int nomove) +{ + int ret; + + for (;;) { + ret = try_reset_dump(nomove); + if (ret <= 0) + break; + } + + return (ret); +} + +/* + * tries to (re)open log file, nomove flag is used with -x switch + * returns 0: success, 1: retry (log moved), -1: error + */ +int +try_reset_dump(int nomove) { struct pcap_file_header hdr; struct stat st; @@ -250,26 +270,26 @@ reset_dump(void) */ fd = priv_open_log(); if (fd < 0) - return (1); + return (-1); fp = fdopen(fd, "a+"); if (fp == NULL) { logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno)); close(fd); - return (1); + return (-1); } if (fstat(fileno(fp), &st) == -1) { logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno)); fclose(fp); - return (1); + return (-1); } /* set FILE unbuffered, we do our own buffering */ if (setvbuf(fp, NULL, _IONBF, 0)) { logmsg(LOG_ERR, "Failed to set output buffers"); fclose(fp); - return (1); + return (-1); } #define TCPDUMP_MAGIC 0xa1b2c3d4 @@ -291,11 +311,15 @@ reset_dump(void) if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) { fclose(fp); - return (1); + return (-1); } } else if (scan_dump(fp, st.st_size)) { - /* XXX move file and continue? */ fclose(fp); + if (nomove || priv_move_log()) { + logmsg(LOG_ERR, + "Invalid/incompatible log file, move it away"); + return (-1); + } return (1); } @@ -334,7 +358,6 @@ scan_dump(FILE *fp, off_t size) hdr.version_minor != PCAP_VERSION_MINOR || hdr.linktype != hpcap->linktype || hdr.snaplen > PFLOGD_MAXSNAPLEN) { - logmsg(LOG_ERR, "Invalid/incompatible log file, move it away"); return (1); } @@ -594,7 +617,7 @@ main(int argc, char **argv) bufpkt = 0; } - if (reset_dump()) { + if (reset_dump(Xflag) < 0) { if (Xflag) return (1); @@ -612,7 +635,7 @@ main(int argc, char **argv) if (gotsig_close) break; if (gotsig_hup) { - if (reset_dump()) { + if (reset_dump(0)) { logmsg(LOG_ERR, "Logging suspended: open error"); set_suspended(1); @@ -623,6 +646,8 @@ main(int argc, char **argv) if (gotsig_alrm) { if (dpcap) flush_buffer(dpcap); + else + gotsig_hup = 1; gotsig_alrm = 0; alarm(delay); } diff --git a/sbin/pflogd/pflogd.h b/sbin/pflogd/pflogd.h index 3baecb66fe6..596e6969261 100644 --- a/sbin/pflogd/pflogd.h +++ b/sbin/pflogd/pflogd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pflogd.h,v 1.2 2004/01/15 20:15:14 canacar Exp $ */ +/* $OpenBSD: pflogd.h,v 1.3 2006/01/15 16:38:04 canacar Exp $ */ /* * Copyright (c) 2003 Can Erkin Acar @@ -37,6 +37,7 @@ void logmsg(int priority, const char *message, ...); int priv_init(void); int priv_set_snaplen(int snaplen); int priv_open_log(void); +int priv_move_log(void); pcap_t *pcap_open_live_fd(int fd, int snaplen, char *ebuf); void set_pcap_filter(void); diff --git a/sbin/pflogd/privsep.c b/sbin/pflogd/privsep.c index 33d6b9c05f8..66734ee2857 100644 --- a/sbin/pflogd/privsep.c +++ b/sbin/pflogd/privsep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: privsep.c,v 1.13 2004/12/22 09:21:02 otto Exp $ */ +/* $OpenBSD: privsep.c,v 1.14 2006/01/15 16:38:04 canacar Exp $ */ /* * Copyright (c) 2003 Can Erkin Acar @@ -16,7 +16,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/ioctl.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> @@ -28,6 +27,7 @@ #include <err.h> #include <errno.h> #include <fcntl.h> +#include <limits.h> #include <pcap.h> #include <pcap-int.h> #include <pwd.h> @@ -41,6 +41,7 @@ enum cmd_types { PRIV_SET_SNAPLEN, /* set the snaplength */ + PRIV_MOVE_LOG, /* move logfile away */ PRIV_OPEN_LOG /* open logfile for appending */ }; @@ -55,6 +56,7 @@ static int may_read(int, void *, size_t); static void must_read(int, void *, size_t); static void must_write(int, void *, size_t); static int set_snaplen(int snap); +static int move_log(const char *name); /* bpf filter expression common to parent and child */ extern char *filter; @@ -159,6 +161,13 @@ priv_init(void) close(fd); break; + case PRIV_MOVE_LOG: + logmsg(LOG_DEBUG, + "[priv]: msg PRIV_MOVE_LOG received"); + ret = move_log(filename); + must_write(socks[0], &ret, sizeof(int)); + break; + default: logmsg(LOG_ERR, "[priv]: unknown command %d", cmd); _exit(1); @@ -182,6 +191,47 @@ set_snaplen(int snap) return 0; } +static int +move_log(const char *name) +{ + char ren[PATH_MAX]; + int len; + + for (;;) { + int fd; + + len = snprintf(ren, sizeof(ren), "%s.bad.%08x", + name, arc4random()); + if (len >= sizeof(ren)) { + logmsg(LOG_ERR, "[priv] new name too long"); + return (1); + } + + /* lock destinanion */ + fd = open(ren, O_CREAT|O_EXCL, 0); + if (fd >= 0) { + close(fd); + break; + } + /* if file exists, try another name */ + if (errno != EEXIST && errno != EINTR) { + logmsg(LOG_ERR, "[priv] failed to create new name: %s", + strerror(errno)); + return (1); + } + } + + if (rename(name, ren)) { + logmsg(LOG_ERR, "[priv] failed to rename %s to %s: %s", + name, ren, strerror(errno)); + return (1); + } + + logmsg(LOG_NOTICE, + "[priv]: log file %s moved to %s", name, ren); + + return (0); +} /* * send the snaplength to privileged process @@ -223,6 +273,21 @@ priv_open_log(void) return (fd); } +/* Move-away and reopen log-file */ +int +priv_move_log(void) +{ + int cmd, ret; + + if (priv_fd < 0) + errx(1, "%s: called from privileged portion\n", __func__); + + cmd = PRIV_MOVE_LOG; + must_write(priv_fd, &cmd, sizeof(int)); + must_read(priv_fd, &ret, sizeof(int)); + + return (ret); +} /* If priv parent gets a TERM or HUP, pass it through to child instead */ static void |