Hi,

attached patch updates arpwatch to add -u <username> flag, to drop privileges
to non-privileged user after startup. Patch taken from Debian/Ubuntu, which
originates from RedHat. user/group _arpwatch added to PLIST,
and a user to be added to users.list

rc script is updated to add -u _arpwatch user to to the daemon.
manpage.

any comments, objections, or even OK?

cheers,
Sebastian

Index: Makefile
===================================================================
RCS file: /cvs/ports/net/arpwatch/Makefile,v
retrieving revision 1.49
diff -u -r1.49 Makefile
--- Makefile    24 Jul 2018 18:59:20 -0000      1.49
+++ Makefile    29 Oct 2018 13:51:33 -0000
@@ -3,7 +3,7 @@
 COMMENT=       monitor arp & rarp requests

 DISTNAME=      arpwatch-2.1a15
-REVISION=      18
+REVISION=      19
 CATEGORIES=    net

 MASTER_SITES=  ftp://ftp.ee.lbl.gov/
Index: patches/patch-arpwatch.8
===================================================================
RCS file: /cvs/ports/net/arpwatch/patches/patch-arpwatch.8,v
retrieving revision 1.1
diff -u -r1.1 patch-arpwatch.8
--- patches/patch-arpwatch.8    1 Jun 2001 23:36:32 -0000       1.1
+++ patches/patch-arpwatch.8    29 Oct 2018 13:51:33 -0000
@@ -1,8 +1,40 @@
 $OpenBSD: patch-arpwatch.8,v 1.1 2001/06/01 23:36:32 jakob Exp $

---- arpwatch.8.orig    Sat Jun  2 01:22:23 2001
-+++ arpwatch.8 Sat Jun  2 01:22:47 2001
-@@ -152,7 +152,7 @@ addresses was a DECnet address.
+Add -u flag, to drop privileges to that user given
+
+Index: arpwatch.8
+--- arpwatch.8.orig
++++ arpwatch.8
+@@ -43,6 +43,9 @@ arpwatch - keep track of ethernet/ip address pairings
+ ]] [
+ .B -r
+ .I file
++] [
++.B -u
++.I username
+ ]
+ .ad
+ .SH DESCRIPTION
+@@ -94,6 +97,18 @@ of reading from the network. In this case,
+ .B arpwatch
+ does not fork.
+ .LP
++The
++.B -u
++flag instructs
++.B arpwatch
++to drop root privileges and change the UID to
++.I username
++and GID to the primary group of
++.I username .
++This is recommended for security reasons, but
++.I username
++has to have write access to the default directory.
++.LP
+ Note that an empty
+ .I arp.dat
+ file must be created before the first time you run
+@@ -152,7 +167,7 @@ addresses was a DECnet address.
  .na
  .nh
  .nf
Index: patches/patch-arpwatch_c
===================================================================
RCS file: /cvs/ports/net/arpwatch/patches/patch-arpwatch_c,v
retrieving revision 1.1
diff -u -r1.1 patch-arpwatch_c
--- patches/patch-arpwatch_c    15 May 2018 19:10:24 -0000      1.1
+++ patches/patch-arpwatch_c    29 Oct 2018 13:51:33 -0000
@@ -2,11 +2,80 @@

 - Do not bail if the interface does not have an IP assigned.
 - time_t format string fixes
+- add -u flag, to drop privileges to that user

 Index: arpwatch.c
 --- arpwatch.c.orig
 +++ arpwatch.c
-@@ -223,9 +223,11 @@ main(int argc, char **argv)
+@@ -63,6 +63,9 @@ struct rtentry;
+ #include <syslog.h>
+ #include <unistd.h>
+
++#include <pwd.h>
++#include <grp.h>
++
+ #include <pcap.h>
+
+ #include "gnuc.h"
+@@ -141,6 +144,24 @@ int       sanity_ether(struct ether_header *, struct 
ether_a
+ int   sanity_fddi(struct fddi_header *, struct ether_arp *, int);
+ __dead        void usage(void) __attribute__((volatile));
+
++void dropprivileges(const char* user)
++{
++      struct passwd* pw;
++      pw = getpwnam( user );
++      if ( pw ) {
++              if ( initgroups(pw->pw_name, pw->pw_gid) != 0 || 
setgid(pw->pw_gid) != 0 ||
++                      setuid(pw->pw_uid) != 0 ) {
++                      syslog(LOG_ERR, "Couldn't change to '%.32s' uid=%d 
gid=%d", user,pw->pw_uid, pw->pw_gid);
++                      exit(1);
++              }
++      }
++      else {
++              syslog(LOG_ERR, "Couldn't find user '%.32s' in /etc/passwd", 
user);
++              exit(1);
++      }
++      syslog(LOG_INFO, "Running as uid=%d gid=%d", getuid(), getgid());
++}
++
+ int
+ main(int argc, char **argv)
+ {
+@@ -153,6 +174,7 @@ main(int argc, char **argv)
+       register char *interface, *rfilename;
+       struct bpf_program code;
+       char errbuf[PCAP_ERRBUF_SIZE];
++      char* username = NULL;
+
+       if (argv[0] == NULL)
+               prog = "arpwatch";
+@@ -170,7 +192,7 @@ main(int argc, char **argv)
+       interface = NULL;
+       rfilename = NULL;
+       pd = NULL;
+-      while ((op = getopt(argc, argv, "df:i:n:Nr:")) != EOF)
++      while ((op = getopt(argc, argv, "df:i:n:Nr:u:")) != EOF)
+               switch (op) {
+
+               case 'd':
+@@ -202,6 +224,15 @@ main(int argc, char **argv)
+                       rfilename = optarg;
+                       break;
+
++              case 'u':
++                      if ( optarg ) {
++                              username = strdup(optarg);
++                      } else {
++                              fprintf(stderr, "%s: Need username after -u\n", 
prog);
++                              usage();
++                      }
++                      break;
++
+               default:
+                       usage();
+               }
+@@ -223,9 +254,11 @@ main(int argc, char **argv)

                /* Determine network and netmask */
                if (pcap_lookupnet(interface, &net, &netmask, errbuf) < 0) {
@@ -21,7 +90,26 @@
                }

                /* Drop into the background if not debugging */
-@@ -401,7 +403,7 @@ process_ether(register u_char *u, register const struc
+@@ -279,12 +312,16 @@ main(int argc, char **argv)
+ #endif
+       }
+
++      if ( username ) {
++              dropprivileges( username );
++      } else {
+       /*
+        * Revert to non-privileged user after opening sockets
+        * (not needed on most systems).
+        */
+-      setgid(getgid());
+-      setuid(getuid());
++              setgid(getgid());
++              setuid(getuid());
++      }
+
+       /* Must be ethernet or fddi */
+       linktype = pcap_datalink(pd);
+@@ -401,7 +438,7 @@ process_ether(register u_char *u, register const struc
        t = h->ts.tv_sec;
        can_checkpoint = 0;
        if (!ent_add(sia, sea, t, NULL))
@@ -30,7 +118,7 @@
                    intoa(sia), e2str(sea), t);
        can_checkpoint = 1;
  }
-@@ -550,7 +552,7 @@ process_fddi(register u_char *u, register const struct
+@@ -550,7 +587,7 @@ process_fddi(register u_char *u, register const struct
        t = h->ts.tv_sec;
        can_checkpoint = 0;
        if (!ent_add(sia, sea, t, NULL))
@@ -38,4 +126,13 @@
 +              syslog(LOG_ERR, "ent_add(%s, %s, %lld) failed",
                    intoa(sia), e2str(sea), t);
        can_checkpoint = 1;
+ }
+@@ -750,7 +787,7 @@ usage(void)
+       extern char version[];
+
+       (void)fprintf(stderr, "Version %s\n", version);
+-      (void)fprintf(stderr, "usage: %s [-dN] [-f datafile] [-i interface]"
++      (void)fprintf(stderr, "usage: %s [-dN] [-f datafile] [-i interface] [-u 
username]"
+           " [-n net[/width]] [-r file]\n", prog);
+       exit(1);
  }
Index: pkg/PLIST
===================================================================
RCS file: /cvs/ports/net/arpwatch/pkg/PLIST,v
retrieving revision 1.11
diff -u -r1.11 PLIST
--- pkg/PLIST   16 May 2018 12:37:32 -0000      1.11
+++ pkg/PLIST   29 Oct 2018 13:51:33 -0000
@@ -1,4 +1,6 @@
 @comment $OpenBSD: PLIST,v 1.11 2018/05/16 12:37:32 jasper Exp $
+@newgroup _arpwatch:820
+@newuser _arpwatch:820:_arpwatch:daemon:arpwatch 
user:/nonexistent:/sbin/nologin
 @man man/man8/arpsnmp.8
 @man man/man8/arpwatch.8
 @bin sbin/arpsnmp
@@ -7,6 +9,7 @@
 share/examples/arpwatch/
 share/examples/arpwatch/arp.dat
 @mode 644
+@owner _arpwatch
 @sample /var/arpwatch/arp.dat
 @mode
 share/examples/arpwatch/arp2ethers
Index: pkg/arpwatch.rc
===================================================================
RCS file: /cvs/ports/net/arpwatch/pkg/arpwatch.rc,v
retrieving revision 1.2
diff -u -r1.2 arpwatch.rc
--- pkg/arpwatch.rc     11 Jan 2018 19:27:04 -0000      1.2
+++ pkg/arpwatch.rc     29 Oct 2018 13:51:33 -0000
@@ -2,7 +2,7 @@
 #
 # $OpenBSD: arpwatch.rc,v 1.2 2018/01/11 19:27:04 rpe Exp $

-daemon="${TRUEPREFIX}/sbin/arpwatch"
+daemon="${TRUEPREFIX}/sbin/arpwatch -u _arpwatch"

 . /etc/rc.d/rc.subr

Reply via email to