diff -Naru arpwatch-2.1a15.orig/arpwatch.8 arpwatch-2.1a15/arpwatch.8 --- arpwatch-2.1a15.orig/arpwatch.8 2006-09-23 22:13:55.000000000 +0400 +++ arpwatch-2.1a15/arpwatch.8 2006-09-23 22:15:30.000000000 +0400 @@ -75,6 +75,18 @@ [ .B -a ] +.br +.ti +8 +[ +.B -u +.I username +] +.br +.ti +8 +[ +.B -R +.I seconds +] .ad .SH DESCRIPTION .B Arpwatch @@ -159,6 +171,32 @@ .B -N is given). (This feature comes from Debian). .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 +.IR username . +This is recommended for security reasons, but +.I username +has to have write access to the default directory. (This feature comes from Debian). +.LP +The +.B -R +flag instructs +.B arpwatch +to restart in +.I seconds +seconds after the interface went down. By default, in such cases +arpwatch would print an error message and exit. This option is +ignored if either the +.B -r +or +.B -u +flags are used. (This feature comes from Debian). +.LP Note that an empty .I arp.dat file must be created before the first time you run diff -Naru arpwatch-2.1a15.orig/arpwatch.c arpwatch-2.1a15/arpwatch.c --- arpwatch-2.1a15.orig/arpwatch.c 2006-09-23 22:13:55.000000000 +0400 +++ arpwatch-2.1a15/arpwatch.c 2006-09-23 22:11:41.000000000 +0400 @@ -62,7 +62,8 @@ #include #include #include - +#include +#include #include #include "gnuc.h" @@ -144,6 +145,24 @@ static char *interface; +void dropprivileges(const char* user) +{ + struct passwd* pw; + pw = getpwnam( user ); + if ( pw ) { + if ( initgroups(pw->pw_name, 0) != 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) { @@ -156,6 +175,7 @@ register char *rfilename; struct bpf_program code; char errbuf[PCAP_ERRBUF_SIZE]; + char* username = NULL; char options[] = "d" "f:" @@ -167,6 +187,7 @@ "s:" "p" "a" + "u:" ; if (argv[0] == NULL) @@ -233,6 +254,10 @@ ++allsubnets; break; + case 'u': + username = optarg; + break; + default: usage(); } @@ -310,12 +335,16 @@ #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); @@ -793,6 +822,7 @@ "[-s sendmail_path] " "[-p] " "[-a] " + "[-u username] " "\n" ;