pflogd: Update to OpenBSD 4.1
authorJan Lentfer <Jan.Lentfer@web.de>
Sun, 8 Aug 2010 16:43:17 +0000 (18:43 +0200)
committerJan Lentfer <Jan.Lentfer@web.de>
Sun, 8 Aug 2010 19:50:06 +0000 (21:50 +0200)
usr.sbin/pflogd/Makefile
usr.sbin/pflogd/pflogd.8
usr.sbin/pflogd/pflogd.c
usr.sbin/pflogd/pflogd.h
usr.sbin/pflogd/privsep.c
usr.sbin/pflogd/privsep_fdpass.c

index c29a188..0dd5509 100644 (file)
@@ -3,6 +3,7 @@
 
 LDADD+= -lpcap -lutil
 DPAPP+=        ${LIBPCAP} ${LIBUTIL}
+CFLAGS+= -DHAVE_SNPRINTF
 
 PROG=  pflogd
 SRCS=  pflogd.c privsep.c privsep_fdpass.c
index c6a34be..273db5a 100644 (file)
@@ -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.
 .\"
 .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 .
index c799a4e..a629b99 100644 (file)
@@ -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);
                }
index 207454b..1b504a4 100644 (file)
@@ -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);
index c4d9029..3534392 100644 (file)
@@ -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 <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/socket.h>
@@ -29,6 +27,7 @@
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <pwd.h>
 #include <signal.h>
 #include <stdio.h>
@@ -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
index 50bfad0..e244b24 100644 (file)
@@ -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 <provos@citi.umich.edu>
@@ -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);