From: Jan Lentfer Date: Sun, 8 Aug 2010 16:43:17 +0000 (+0200) Subject: pflogd: Update to OpenBSD 4.1 X-Git-Url: https://gitweb.dragonflybsd.org/~lentferj/dragonfly.git/commitdiff_plain/c929e0df1b78e77735cbe1341ad0358818d85a53 pflogd: Update to OpenBSD 4.1 --- diff --git a/usr.sbin/pflogd/Makefile b/usr.sbin/pflogd/Makefile index c29a188f56..0dd5509a23 100644 --- a/usr.sbin/pflogd/Makefile +++ b/usr.sbin/pflogd/Makefile @@ -3,6 +3,7 @@ LDADD+= -lpcap -lutil DPAPP+= ${LIBPCAP} ${LIBUTIL} +CFLAGS+= -DHAVE_SNPRINTF PROG= pflogd SRCS= pflogd.c privsep.c privsep_fdpass.c diff --git a/usr.sbin/pflogd/pflogd.8 b/usr.sbin/pflogd/pflogd.8 index c6a34be173..273db5aa33 100644 --- a/usr.sbin/pflogd/pflogd.8 +++ b/usr.sbin/pflogd/pflogd.8 @@ -1,5 +1,4 @@ -.\" $OpenBSD: pflogd.8,v 1.24 2004/01/16 10:45:49 jmc Exp $ -.\" $DragonFly: src/usr.sbin/pflogd/pflogd.8,v 1.5 2007/07/29 17:27:46 swildner Exp $ +.\" $OpenBSD: pflogd.8,v 1.32 2006/12/08 10:26:38 joel Exp $ .\" .\" Copyright (c) 2001 Can Erkin Acar. All rights reserved. .\" @@ -36,14 +35,17 @@ .Op Fl \&Dx .Op Fl d Ar delay .Op Fl f Ar filename +.Op Fl i Ar interface .Op Fl s Ar snaplen .Op Ar expression .Sh DESCRIPTION .Nm is a background daemon which reads packets logged by .Xr pf 4 -to the packet logging interface -.Pa pflog0 +to a +.Xr pflog 4 +interface, normally +.Pa pflog0 , and writes the packets to a logfile (normally .Pa /var/log/pflog ) in @@ -82,7 +84,9 @@ temporarily uses the old snaplen to keep the log file consistent. tries to preserve the integrity of the log file against I/O errors. Furthermore, integrity of an existing log file is verified before appending. -If there is an invalid log file or an I/O error, logging is suspended until a +If there is an invalid log file or an I/O error, the log file is moved +out of the way and a new one is created. +If a new file cannot be created, logging is suspended until a .Dv SIGHUP or a .Dv SIGALRM @@ -102,11 +106,19 @@ If not specified, the default is 60 seconds. Log output filename. Default is .Pa /var/log/pflog . +.It Fl i Ar interface +Specifies the +.Xr pflog 4 +interface to use. +By default, +.Nm +will use +.Ar pflog0 . .It Fl s Ar snaplen Analyze at most the first .Ar snaplen -bytes of data from each packet rather than the default of 96. -The default of 96 is adequate for IP, ICMP, TCP, and UDP headers but may +bytes of data from each packet rather than the default of 116. +The default of 116 is adequate for IP, ICMP, TCP, and UDP headers but may truncate protocol information for other protocols. Other file parsers may desire a higher snaplen. .It Fl x @@ -130,6 +142,13 @@ Log specific tcp packets to a different log file with a large snaplen # pflogd -s 1600 -f suspicious.log port 80 and host evilhost .Ed .Pp +Log from another +.Xr pflog 4 +interface, excluding specific packets: +.Bd -literal -offset indent +# pflogd -i pflog3 -f network3.log "not (tcp and port 23)" +.Ed +.Pp Display binary logs: .Bd -literal -offset indent # tcpdump -n -e -ttt -r /var/log/pflog @@ -149,7 +168,7 @@ Tcpdump can restrict the output to packets logged on a specified interface, a rule number, a reason, a direction, an IP family or an action. .Pp -.Bl -tag -width "reason match " -compact +.Bl -tag -width "ruleset authpf " -compact .It ip Address family equals IPv4. .It ip6 @@ -158,11 +177,16 @@ Address family equals IPv6. Interface name equals "kue0". .It on kue0 Interface name equals "kue0". +.It ruleset authpf +Ruleset name equals "authpf". .It rulenum 10 Rule number equals 10. .It reason match Reason equals match. -Also accepts "bad-offset", "fragment", "short", "normalize" and "memory". +Also accepts "bad-offset", "fragment", "bad-timestamp", "short", +"normalize", "memory", "congestion", "ip-option", "proto-cksum", +"state-mismatch", "state-insert", "state-limit", "src-limit", +and "synproxy". .It action pass Action equals pass. Also accepts "block". @@ -178,16 +202,18 @@ the wi0 interface: # tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0 .Ed .Sh SEE ALSO -.Xr tcpdump 1 , .Xr pcap 3 , .Xr pf 4 , .Xr pflog 4 , .Xr pf.conf 5 , -.Xr newsyslog 8 +.Xr newsyslog 8 , +.Xr tcpdump 1 .Sh HISTORY The .Nm command appeared in .Ox 3.0 . .Sh AUTHORS -Can Erkin Acar +.Nm +was written by +.An Can Erkin Acar Aq canacar@openbsd.org . diff --git a/usr.sbin/pflogd/pflogd.c b/usr.sbin/pflogd/pflogd.c index c799a4edb7..a629b992df 100644 --- a/usr.sbin/pflogd/pflogd.c +++ b/usr.sbin/pflogd/pflogd.c @@ -1,5 +1,4 @@ -/* $OpenBSD: pflogd.c,v 1.27 2004/02/13 19:01:57 otto Exp $ */ -/* $DragonFly: src/usr.sbin/pflogd/pflogd.c,v 1.2 2004/12/18 22:48:04 swildner Exp $ */ +/* $OpenBSD: pflogd.c,v 1.37 2006/10/26 13:34:47 jmc Exp $ */ /* * Copyright (c) 2001 Theo de Raadt @@ -77,7 +76,7 @@ void dump_packet_nobuf(u_char *, const struct pcap_pkthdr *, const u_char *); int flush_buffer(FILE *); int init_pcap(void); 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); @@ -86,6 +85,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 size_t buflen = 0; /* allocated size of buffer */ @@ -104,8 +105,9 @@ set_suspended(int s) return; suspended = s; - setproctitle("[%s] -s %d -f %s", - suspended ? "suspended" : "running", cur_snaplen, filename); + setproctitle("[%s] -s %d -i %s -f %s", + suspended ? "suspended" : "running", + cur_snaplen, interface, filename); } char * @@ -151,8 +153,9 @@ logmsg(int pri, const char *message, ...) void usage(void) { - fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename] "); - fprintf(stderr, "[-s snaplen] [expression]\n"); + fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename]"); + fprintf(stderr, " [-i interface] [-s snaplen]\n"); + fprintf(stderr, " [expression]\n"); exit(1); } @@ -237,7 +240,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; @@ -259,23 +280,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)); - return (1); + close(fd); + return (-1); } if (fstat(fileno(fp), &st) == -1) { logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno)); - return (1); + fclose(fp); + return (-1); } /* set FILE unbuffered, we do our own buffering */ if (setvbuf(fp, NULL, _IONBF, 0)) { logmsg(LOG_ERR, "Failed to set output buffers"); - return (1); + fclose(fp); + return (-1); } #define TCPDUMP_MAGIC 0xa1b2c3d4 @@ -283,10 +307,9 @@ reset_dump(void) if (st.st_size == 0) { if (snaplen != cur_snaplen) { logmsg(LOG_NOTICE, "Using snaplen %d", snaplen); - if (set_snaplen(snaplen)) { + if (set_snaplen(snaplen)) logmsg(LOG_WARNING, "Failed, using old settings"); - } } hdr.magic = TCPDUMP_MAGIC; hdr.version_major = PCAP_VERSION_MAJOR; @@ -298,11 +321,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); } @@ -341,7 +368,6 @@ scan_dump(FILE *fp, off_t size) hdr.version_minor != PCAP_VERSION_MINOR || (int)hdr.linktype != hpcap->linktype || hdr.snaplen > PFLOGD_MAXSNAPLEN) { - logmsg(LOG_ERR, "Invalid/incompatible log file, move it away"); return (1); } @@ -395,8 +421,9 @@ dump_packet_nobuf(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) } if (fwrite(h, sizeof(*h), 1, f) != 1) { - /* try to undo header to prevent corruption */ off_t pos = ftello(f); + + /* try to undo header to prevent corruption */ if ((size_t)pos < sizeof(*h) || ftruncate(fileno(f), pos - sizeof(*h))) { logmsg(LOG_ERR, "Write failed, corrupted logfile!"); @@ -494,7 +521,7 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) return; } - append: + append: memcpy(bufpos, h, sizeof(*h)); memcpy(bufpos + sizeof(*h), sp, h->caplen); @@ -511,6 +538,7 @@ main(int argc, char **argv) struct pcap_stat pstat; int ch, np, Xflag = 0; pcap_handler phandler = dump_packet; + const char *errstr = NULL; /* Neither FreeBSD nor DFly have this; Max seems to think this may * be a paranoid check. Comment it out: @@ -523,18 +551,22 @@ main(int argc, char **argv) Debug = 1; break; case 'd': - delay = atoi(optarg); - if (delay < 5 || delay > 60*60) + delay = strtonum(optarg, 5, 60*60, &errstr); + if (errstr) usage(); break; case 'f': filename = optarg; break; + case 'i': + interface = optarg; + break; case 's': - snaplen = atoi(optarg); + snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN, + &errstr); if (snaplen <= 0) snaplen = DEF_SNAPLEN; - if (snaplen > PFLOGD_MAXSNAPLEN) + if (errstr) snaplen = PFLOGD_MAXSNAPLEN; break; case 'x': @@ -600,7 +632,7 @@ main(int argc, char **argv) bufpkt = 0; } - if (reset_dump()) { + if (reset_dump(Xflag) < 0) { if (Xflag) return (1); @@ -611,14 +643,14 @@ main(int argc, char **argv) while (1) { np = pcap_dispatch(hpcap, PCAP_NUM_PKTS, - dump_packet, (u_char *)dpcap); + phandler, (u_char *)dpcap); if (np < 0) logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap)); if (gotsig_close) break; if (gotsig_hup) { - if (reset_dump()) { + if (reset_dump(0)) { logmsg(LOG_ERR, "Logging suspended: open error"); set_suspended(1); @@ -629,6 +661,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/usr.sbin/pflogd/pflogd.h b/usr.sbin/pflogd/pflogd.h index 207454bbe6..1b504a40c7 100644 --- a/usr.sbin/pflogd/pflogd.h +++ b/usr.sbin/pflogd/pflogd.h @@ -1,5 +1,4 @@ -/* $OpenBSD: pflogd.h,v 1.2 2004/01/15 20:15:14 canacar Exp $ */ -/* $DragonFly: src/usr.sbin/pflogd/pflogd.h,v 1.1 2004/09/21 21:25:28 joerg Exp $ */ +/* $OpenBSD: pflogd.h,v 1.3 2006/01/15 16:38:04 canacar Exp $ */ /* * Copyright (c) 2003 Can Erkin Acar @@ -38,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/usr.sbin/pflogd/privsep.c b/usr.sbin/pflogd/privsep.c index c4d90298f4..3534392aa7 100644 --- a/usr.sbin/pflogd/privsep.c +++ b/usr.sbin/pflogd/privsep.c @@ -1,5 +1,4 @@ -/* $OpenBSD: privsep.c,v 1.8 2004/03/14 19:17:05 otto Exp $ */ -/* $DragonFly: src/usr.sbin/pflogd/privsep.c,v 1.1 2004/09/21 21:25:28 joerg Exp $ */ +/* $OpenBSD: privsep.c,v 1.16 2006/10/25 20:55:04 moritz Exp $ */ /* * Copyright (c) 2003 Can Erkin Acar @@ -17,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 #include #include #include @@ -29,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -42,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 */ }; @@ -56,10 +56,8 @@ 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; -extern char *errbuf; extern char *filename; extern pcap_t *hpcap; @@ -68,7 +66,7 @@ int priv_init(void) { int i, fd, socks[2], cmd; - int snaplen, ret; + int snaplen, ret, olderrno; struct passwd *pw; for (i = 1; i < NSIG; i++) @@ -97,26 +95,24 @@ priv_init(void) err(1, "unable to chdir"); gidset[0] = pw->pw_gid; + if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) + err(1, "setresgid() failed"); if (setgroups(1, gidset) == -1) err(1, "setgroups() failed"); - if (setegid(pw->pw_gid) == -1) - err(1, "setegid() failed"); - if (setgid(pw->pw_gid) == -1) - err(1, "setgid() failed"); - if (seteuid(pw->pw_uid) == -1) - err(1, "seteuid() failed"); - if (setuid(pw->pw_uid) == -1) - err(1, "setuid() failed"); + if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) + err(1, "setresuid() failed"); close(socks[0]); priv_fd = socks[1]; return 0; } /* Father */ - /* Pass ALRM/TERM/HUP through to child, and accept CHLD */ + /* Pass ALRM/TERM/HUP/INT/QUIT through to child, and accept CHLD */ signal(SIGALRM, sig_pass_to_chld); signal(SIGTERM, sig_pass_to_chld); signal(SIGHUP, sig_pass_to_chld); + signal(SIGINT, sig_pass_to_chld); + signal(SIGQUIT, sig_pass_to_chld); signal(SIGCHLD, sig_chld); setproctitle("[priv]"); @@ -148,12 +144,21 @@ priv_init(void) fd = open(filename, O_RDWR|O_CREAT|O_APPEND|O_NONBLOCK|O_NOFOLLOW, 0600); + olderrno = errno; + send_fd(socks[0], fd); if (fd < 0) logmsg(LOG_NOTICE, "[priv]: failed to open %s: %s", - filename, strerror(errno)); - send_fd(socks[0], fd); - close(fd); + filename, strerror(olderrno)); + else + 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: @@ -179,6 +184,47 @@ set_snaplen(int snap) return 0; } +static int +move_log(const char *name) +{ + char ren[PATH_MAX]; + u_int32_t 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 @@ -212,7 +258,7 @@ priv_open_log(void) int cmd, fd; if (priv_fd < 0) - errx(1, "%s: called from privileged portion\n", __func__); + errx(1, "%s: called from privileged portion", __func__); cmd = PRIV_OPEN_LOG; must_write(priv_fd, &cmd, sizeof(int)); @@ -220,6 +266,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 diff --git a/usr.sbin/pflogd/privsep_fdpass.c b/usr.sbin/pflogd/privsep_fdpass.c index 50bfad0627..e244b242f7 100644 --- a/usr.sbin/pflogd/privsep_fdpass.c +++ b/usr.sbin/pflogd/privsep_fdpass.c @@ -1,5 +1,4 @@ -/* $OpenBSD: privsep_fdpass.c,v 1.1 2003/10/22 18:51:55 canacar Exp $ */ -/* $DragonFly: src/usr.sbin/pflogd/privsep_fdpass.c,v 1.1 2004/09/21 21:25:28 joerg Exp $ */ +/* $OpenBSD: privsep_fdpass.c,v 1.2 2004/08/13 02:51:48 djm Exp $ */ /* * Copyright 2001 Niels Provos @@ -109,6 +108,10 @@ receive_fd(int sock) __func__, (long)n); if (result == 0) { cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg == NULL) { + warnx("%s: no message header", __func__); + return -1; + } if (cmsg->cmsg_type != SCM_RIGHTS) warnx("%s: expected type %d got %d", __func__, SCM_RIGHTS, cmsg->cmsg_type);