diff --git a/.gitignore b/.gitignore index 82de8ad..ddf095d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /arpwatch-2.1a15.tar.gz /ethercodes-20110707.dat.bz2 /arpwatch-3.1.tar.gz +/arpwatch-3.2.tar.gz diff --git a/arpwatch-3.1-all-zero-bogon.patch b/arpwatch-3.1-all-zero-bogon.patch new file mode 100644 index 0000000..43066c4 --- /dev/null +++ b/arpwatch-3.1-all-zero-bogon.patch @@ -0,0 +1,23 @@ +RHBZ #244606: Correctly handle -n 0/32 to allow the user to disable reporting +bogons from 0.0.0.0. + +diff -Naur arpwatch-3.1-original/arpwatch.c arpwatch-3.1/arpwatch.c +--- arpwatch-3.1-original/arpwatch.c 2019-11-30 13:35:23.000000000 -0500 ++++ arpwatch-3.1/arpwatch.c 2020-11-07 12:10:53.357839069 -0500 +@@ -814,10 +814,12 @@ + + /* XXX hack */ + n = ntohl(inet_addr(tstr)); +- while ((n & 0xff000000) == 0) { +- n <<= 8; +- if (n == 0) +- return (0); ++ if (n || width != 32) { ++ while ((n & 0xff000000) == 0) { ++ n <<= 8; ++ if (n == 0) ++ return (0); ++ } + } + n = htonl(n); + diff --git a/arpwatch-3.1-arp2ethers-sort-invocation.patch b/arpwatch-3.1-arp2ethers-sort-invocation.patch new file mode 100644 index 0000000..e321627 --- /dev/null +++ b/arpwatch-3.1-arp2ethers-sort-invocation.patch @@ -0,0 +1,15 @@ +Fix nonstandard sort flags (obsolete + notation for keys, available in some +BSDs for compatibility but non-POSIX and not supported by GNU sort). + +diff -Naur arpwatch-3.1-original/arp2ethers arpwatch-3.1/arp2ethers +--- arpwatch-3.1-original/arp2ethers 2013-02-16 03:10:28.000000000 -0500 ++++ arpwatch-3.1/arp2ethers 2020-11-07 11:22:04.762234105 -0500 +@@ -13,7 +13,7 @@ + # - sort + # + +-sort +2rn arp.dat | ++sort -k 2 -rn arp.dat | + awk 'NF == 4 { print }' | + awk -f p.awk | + egrep -v '\.[0-9][0-9]*$' | diff --git a/arpwatch-3.1-arpfetch-stray-rm.patch b/arpwatch-3.1-arpfetch-stray-rm.patch new file mode 100644 index 0000000..6dfbd0b --- /dev/null +++ b/arpwatch-3.1-arpfetch-stray-rm.patch @@ -0,0 +1,11 @@ +Fix stray rm (of an undefined variable). + +diff -Naur arpwatch-3.1-original/arpfetch arpwatch-3.1/arpfetch +--- arpwatch-3.1-original/arpfetch 2013-02-16 03:10:28.000000000 -0500 ++++ arpwatch-3.1/arpfetch 2020-11-07 11:22:59.344575624 -0500 +@@ -29,5 +29,3 @@ + ea = $2 + print ea "\t" ip + }' +- +-rm -f ${t1} diff --git a/arpwatch-3.1-configure-no-local-pcap.patch b/arpwatch-3.1-configure-no-local-pcap.patch new file mode 100644 index 0000000..a855de3 --- /dev/null +++ b/arpwatch-3.1-configure-no-local-pcap.patch @@ -0,0 +1,15 @@ +Do not attempt to search for local libpcap libraries lying around in the parent +of the build directory, or anywhere else random. This is not expected to +succeed anyway, but it is better to be sure. + +diff -Naur arpwatch-3.1-original/configure arpwatch-3.1/configure +--- arpwatch-3.1-original/configure 2020-04-05 20:22:04.000000000 -0400 ++++ arpwatch-3.1/configure 2020-11-07 11:59:40.114550004 -0500 +@@ -5437,6 +5437,7 @@ + places=`ls .. | sed -e 's,/$,,' -e 's,^,../,' | \ + egrep '/libpcap-[0-9]*\.[0-9]*(\.[0-9]*)?([ab][0-9]*)?$'` + for dir in $places ../libpcap libpcap ; do ++ break + basedir=`echo $dir | sed -e 's/[ab][0-9]*$//'` + if test $lastdir = $basedir ; then + continue; diff --git a/arpwatch-3.1-devlookup.patch b/arpwatch-3.1-devlookup.patch new file mode 100644 index 0000000..040705f --- /dev/null +++ b/arpwatch-3.1-devlookup.patch @@ -0,0 +1,145 @@ +When -i is not given, iterate all available devices until a usable one is found +instead of just trying the first one and giving up if it is not usable. See +RHBZ #842660. + +Additionally, handle the case where a device provides both supported and +unsupported datalink types. + +diff -Naur arpwatch-3.1-original/arpwatch.c arpwatch-3.1/arpwatch.c +--- arpwatch-3.1-original/arpwatch.c 2019-11-30 13:35:23.000000000 -0500 ++++ arpwatch-3.1/arpwatch.c 2021-04-24 09:02:50.762535242 -0400 +@@ -161,6 +161,8 @@ + RETSIGTYPE die(int); + int isbogon(u_int32_t); + int main(int, char **); ++int try_open_live(pcap_t ** pd_ptr, char const * interface_name, ++ int promiscuous_enable); + void process_ether(u_char *, const struct pcap_pkthdr *, const u_char *); + void process_fddi(u_char *, const struct pcap_pkthdr *, const u_char *); + int readsnmp(char *); +@@ -177,7 +179,7 @@ + int op, snaplen, timeout, linktype, status; + pcap_t *pd; + FILE *fp; +- pcap_if_t *alldevs; ++ pcap_if_t *alldevs, *dev; + char *interface, *rfilename; + struct bpf_program code; + char errbuf[PCAP_ERRBUF_SIZE]; +@@ -309,13 +311,18 @@ + "%s: pcap_findalldevs: %s\n", prog, errbuf); + exit(1); + } +- if (alldevs == NULL) { ++ for (dev = alldevs; dev; dev = dev->next) { ++ if (try_open_live(&pd, dev->name, promisc)) { ++ interface = savestr(alldevs->name); ++ break; ++ } ++ } ++ pcap_freealldevs(alldevs); ++ if (interface == NULL) { + (void)fprintf(stderr, "%s: pcap_findalldevs:" + " no suitable devices found\n", prog); + exit(1); + } +- interface = savestr(alldevs->name); +- pcap_freealldevs(alldevs); + #else + if (interface = pcap_lookupdev(errbuf)) == NULL) { + (void)fprintf(stderr, +@@ -354,15 +361,12 @@ + } + swapped = pcap_is_swapped(pd); + } else { +- snaplen = max(sizeof(struct ether_header), +- sizeof(struct fddi_header)) + sizeof(struct ether_arp); +- timeout = 1000; +- pd = pcap_open_live(interface, snaplen, promisc, timeout, +- errbuf); + if (pd == NULL) { +- lg(LOG_ERR, "pcap open %s: %s", interface, errbuf); +- exit(1); ++ if (!try_open_live(&pd, interface, promisc)) { ++ exit(1); ++ } + } ++ /* else pd was already opened based on pcap_findalldevs */ + #ifdef WORDS_BIGENDIAN + swapped = 1; + #endif +@@ -452,6 +456,74 @@ + exit(0); + } + ++int ++try_open_live(pcap_t ** pd_ptr, char const * interface_name, int promiscuous_enable) { ++ /* Attempt to open an interface and set up a supported datalink type; ++ * return nonzero on success and zero on failure (and log a message). ++ */ ++ int snaplen, timeout, n_datalinks, datalink_i; ++ int * datalinks, datalink; ++ char errbuf[PCAP_ERRBUF_SIZE]; ++ ++ snaplen = max(sizeof(struct ether_header), ++ sizeof(struct fddi_header)) + sizeof(struct ether_arp); ++ timeout = 1000; ++ datalinks = NULL; ++ ++ /* Just in case... */ ++ if (*pd_ptr != NULL) { ++ pcap_close(*pd_ptr); ++ *pd_ptr = NULL; ++ } ++ ++ *pd_ptr = pcap_open_live(interface_name, snaplen, promiscuous_enable, ++ timeout, errbuf); ++ if (*pd_ptr == NULL) { ++ lg(LOG_ERR, "pcap open %s: %s", interface_name, errbuf); ++ goto fail; ++ } ++ ++ /* Must be able to select an ethernet or fddi datalink */ ++ n_datalinks = pcap_list_datalinks(*pd_ptr, &datalinks); ++ if (n_datalinks < 0) { ++ lg(LOG_ERR, "pcap_list_datalinks %s: %s", interface_name, ++ pcap_geterr(*pd_ptr)); ++ goto fail; ++ } ++ for (datalink_i = 0; datalink_i < n_datalinks; ++datalink_i) { ++ switch (datalinks[datalink_i]) { ++ case DLT_EN10MB: ++ case DLT_FDDI: ++ break; ++ default: ++ continue; /* unsupported; try the next datalink */ ++ } ++ if (pcap_set_datalink(*pd_ptr, datalinks[datalink_i]) != 0) { ++ lg(LOG_ERR, "pcap_set_datalink %s %d: %s", ++ interface_name, datalinks[datalink_i], ++ pcap_geterr(*pd_ptr)); ++ continue; ++ } ++ break; /* success */ ++ } ++ if (datalink_i >= n_datalinks) { ++ lg(LOG_ERR, "no ethernet or fddi datalink for %s", ++ interface_name); ++ goto fail; ++ } ++ ++ free(datalinks); ++ return 1; /* success */ ++ ++fail: ++ if (*pd_ptr != NULL) { ++ pcap_close(*pd_ptr); ++ *pd_ptr = NULL; ++ } ++ free(datalinks); ++ return 0; /* failure */ ++} ++ + /* Process an ethernet arp/rarp packet */ + void + process_ether(u_char *u, const struct pcap_pkthdr *h, const u_char *p) diff --git a/arpwatch-3.1-exitcode.patch b/arpwatch-3.1-exitcode.patch new file mode 100644 index 0000000..a6c2d34 --- /dev/null +++ b/arpwatch-3.1-exitcode.patch @@ -0,0 +1,15 @@ +When arpwatch is terminated cleanly by a signal (INT/TERM/HUP) handler, the +exit code should be zero for success instead of nonzero for failure. + +diff -Naur arpwatch-3.1-original/arpwatch.c arpwatch-3.1/arpwatch.c +--- arpwatch-3.1-original/arpwatch.c 2019-11-30 13:35:23.000000000 -0500 ++++ arpwatch-3.1/arpwatch.c 2020-11-08 12:55:51.429575973 -0500 +@@ -892,7 +892,7 @@ + + lg(LOG_DEBUG, "exiting"); + checkpoint(0); +- exit(1); ++ exit(0); + } + + RETSIGTYPE diff --git a/arpwatch-3.1-man-references.patch b/arpwatch-3.1-man-references.patch new file mode 100644 index 0000000..b7735c5 --- /dev/null +++ b/arpwatch-3.1-man-references.patch @@ -0,0 +1,76 @@ +Fix section numbers in man page cross-references. With minor changes, this +patch dates all the way back to arpwatch-2.1a4-man.patch, from RHBZ#15442. + +diff -Naur arpwatch-3.1-original/arpsnmp.8.in arpwatch-3.1/arpsnmp.8.in +--- arpwatch-3.1-original/arpsnmp.8.in 2019-12-01 14:01:07.000000000 -0500 ++++ arpwatch-3.1/arpsnmp.8.in 2020-11-05 15:13:01.296113145 -0500 +@@ -45,7 +45,7 @@ + and reports certain changes via email. + .Nm + reads information from a file (usually generated by +-.Xr snmpwalk 3 ) . ++.Xr snmpwalk 1 ) . + .Pp + The format of the input file is the same as + .Ar arp.dat ; +@@ -119,9 +119,9 @@ + .Pp + .Sh "REPORT MESSAGES" + See the +-.Xr arpwatch 1 ++.Xr arpwatch 8 + man page for details on the report messages generated by +-.Xr arpsnmp 1 . ++.Xr arpsnmp 8 . + .Sh FILES + .Bl -tag -width ".Pa /usr/local/arpwatch" -compact + .It Pa /usr/local/arpwatch +@@ -132,7 +132,7 @@ + vendor ethernet block list + .Sh "SEE ALSO" + .Xr arpwatch 8 , +-.Xr snmpwalk 8 , ++.Xr snmpwalk 1 , + .Xr arp 8 , + .Sh AUTHORS + .An Craig Leres +diff -Naur arpwatch-3.1-original/arpwatch.8.in arpwatch-3.1/arpwatch.8.in +--- arpwatch-3.1-original/arpwatch.8.in 2019-12-01 14:01:07.000000000 -0500 ++++ arpwatch-3.1/arpwatch.8.in 2020-11-05 15:14:12.117564292 -0500 +@@ -117,9 +117,9 @@ + .Fl r + flag is used to specify a savefile + (perhaps created by +-.Xr tcpdump 1 ++.Xr tcpdump 8 + or +-.Xr pcapture 1 ) ++.Xr pcapture 8 ) + to read from instead + of reading from the network. In this case + .Nm +@@ -163,9 +163,9 @@ + .Pp + .Sh "REPORT MESSAGES" + Here's a quick list of the report messages generated by +-.Xr arpwatch 1 ++.Xr arpwatch 8 + (and +-.Xr arpsnmp 1 ) : ++.Xr arpsnmp 8 ) : + .Pp + .Bl -tag -width xxx + .It Ic "new activity" +@@ -216,9 +216,9 @@ + .Sh "SEE ALSO" + .Xr arpsnmp 8 , + .Xr arp 8 , +-.Xr bpf 4 , +-.Xr tcpdump 1 , +-.Xr pcapture 1 , ++.Xr bpf 2 , ++.Xr tcpdump 8 , ++.Xr pcapture 8 , + .Xr pcap 3 + .Sh AUTHORS + .An Craig Leres diff --git a/arpwatch-3.2-change-user.patch b/arpwatch-3.2-change-user.patch new file mode 100644 index 0000000..aeb81c8 --- /dev/null +++ b/arpwatch-3.2-change-user.patch @@ -0,0 +1,146 @@ +Add, and document, a -u argument to change to a specified unprivileged user +after establishing sockets. + +This patch rebases and combines arpwatch-drop.patch, which provided -u; +arpwatch-drop-man.patch, which documented it; and +arpwatch-2.1a15-dropgroup.patch, which fixed CVE-2012-2653 (RHBZ #825328) in +the original arpwatch-drop.patch, into a single combined patch. It also removes +an unnecessary and unchecked strdup() in the original patch that could have +theoretically led to a null pointer dereference. + +diff -Naur arpwatch-3.2-original/arpwatch.8.in arpwatch-3.2/arpwatch.8.in +--- arpwatch-3.2-original/arpwatch.8.in 2021-12-14 19:47:54.000000000 -0500 ++++ arpwatch-3.2/arpwatch.8.in 2021-12-16 08:18:21.803266980 -0500 +@@ -43,6 +43,7 @@ + .Op Fl n Ar net[/width] + .Op Fl x Ar net[/width] + .Op Fl r Ar file ++.Op Fl u Ar username + .Sh DESCRIPTION + .Nm + keeps track of ethernet/ip address pairings. It syslogs activity +@@ -137,13 +138,30 @@ + Note that an empty + .Ar arp.dat + file must be created before the first time you run +-.Fl arpwatch . ++.Nm . ++Also, the default directory (where ++.Ar arp.dat ++is stored) must be owned by ++.Ar username ++if the ++.Fl u ++flag is used. + .Pp + The + .Fl s + flag suppresses reports sent by email. + .Pp + The ++.Fl u ++flag causes ++.Nm ++to drop root privileges and change user ID to ++.Ar username ++and group ID to that of the primary group of ++.Ar username . ++This is recommended for security reasons. ++.Pp ++The + .Fl v + flag disables the reporting of VRRP/CARP ethernet prefixes as + described in RFC5798 (@MACZERO@0:@MACZERO@0:5e:@MACZERO@0:@MACZERO@1:xx). +diff -Naur arpwatch-3.2-original/arpwatch.c arpwatch-3.2/arpwatch.c +--- arpwatch-3.2-original/arpwatch.c 2019-11-30 13:35:23.000000000 -0500 ++++ arpwatch-3.2/arpwatch.c 2021-12-16 08:18:21.812267045 -0500 +@@ -72,6 +72,8 @@ + #include + #include + ++#include ++#include + #include + + #include "gnuc.h" +@@ -170,6 +172,24 @@ + int toskip(u_int32_t); + void usage(void) __attribute__((noreturn)); + ++void dropprivileges(const char* user) ++{ ++ struct passwd* const pw = getpwnam(user); ++ if (pw) { ++ if (setgid(pw->pw_gid) != 0 || setgroups(0, NULL) != 0 || ++ setuid(pw->pw_uid) != 0) { ++ lg(LOG_ERR, "Couldn't change to '%.32s' uid=%d gid=%d", ++ user, pw->pw_uid, pw->pw_gid); ++ exit(1); ++ } ++ } else { ++ lg(LOG_ERR, "Couldn't find user '%.32s' in /etc/passwd", ++ user); ++ exit(1); ++ } ++ lg(LOG_DEBUG, "Running as uid=%d gid=%d", getuid(), getgid()); ++} ++ + int + main(int argc, char **argv) + { +@@ -181,6 +201,7 @@ + char *interface, *rfilename; + struct bpf_program code; + char errbuf[PCAP_ERRBUF_SIZE]; ++ char* serveruser = NULL; + + if (argv[0] == NULL) + prog = "arpwatch"; +@@ -198,7 +219,7 @@ + interface = NULL; + rfilename = NULL; + pd = NULL; +- while ((op = getopt(argc, argv, "CdD:Ff:i:n:NpP:qr:svw:W:x:zZ")) != EOF) ++ while ((op = getopt(argc, argv, "CdD:Ff:i:n:NpP:qr:svw:W:x:zZu:")) != EOF) + switch (op) { + + case 'C': +@@ -283,6 +304,17 @@ + zeropad = 1; + break; + ++ case 'u': ++ if (optarg) { ++ /* no need to strdup() a pointer into the ++ * original arguments vector */ ++ serveruser = optarg; ++ } else { ++ fprintf(stderr, "%s: Need username after -u\n", prog); ++ usage(); ++ } ++ break; ++ + default: + usage(); + } +@@ -379,6 +411,11 @@ + } + } + ++ /* Explicit user change (privilege drop) with -u? */ ++ if (serveruser) { ++ dropprivileges(serveruser); ++ } ++ + /* + * Revert to non-privileged user after opening sockets + * (not needed on most systems). +@@ -927,6 +964,7 @@ + "usage: %s [-CdFNpqsvzZ] [-D arpdir] [-f datafile]" + " [-i interface]\n\t" + " [-P pidfile] [-w watcher@email] [-W watchee@email]\n\t" +- " [-n net[/width]] [-x net[/width]] [-r file]\n", prog); ++ " [-n net[/width]] [-x net[/width]] [-r file] [-u username]\n", ++ prog); + exit(1); + } diff --git a/arpwatch-3.2-no-usr-local-path.patch b/arpwatch-3.2-no-usr-local-path.patch new file mode 100644 index 0000000..a92adba --- /dev/null +++ b/arpwatch-3.2-no-usr-local-path.patch @@ -0,0 +1,40 @@ +Do not add /usr/local/bin or /usr/local/sbin to the PATH in any scripts. + +diff -Naur arpwatch-3.2-original/arpfetch arpwatch-3.2/arpfetch +--- arpwatch-3.2-original/arpfetch 2013-02-16 03:10:28.000000000 -0500 ++++ arpwatch-3.2/arpfetch 2021-12-16 08:26:26.931846139 -0500 +@@ -4,8 +4,6 @@ + # arpfetch - collect arp data from a cisco using net-snmp + # + +-export PATH="/usr/local/bin:${PATH}" +- + prog=`basename $0` + + if [ $# -ne 2 ]; then +diff -Naur arpwatch-3.2-original/bihourly.sh arpwatch-3.2/bihourly.sh +--- arpwatch-3.2-original/bihourly.sh 2016-09-16 22:40:54.000000000 -0400 ++++ arpwatch-3.2/bihourly.sh 2021-12-16 08:26:35.671910709 -0500 +@@ -3,9 +3,6 @@ + # + # bihourly arpwatch job + # +-PATH=${PATH}:/usr/local/sbin +-export PATH +-# + cd /usr/local/arpwatch + # + list="`cat list`" +diff -Naur arpwatch-3.2-original/update-ethercodes.sh.in arpwatch-3.2/update-ethercodes.sh.in +--- arpwatch-3.2-original/update-ethercodes.sh.in 2021-12-14 19:47:54.000000000 -0500 ++++ arpwatch-3.2/update-ethercodes.sh.in 2021-12-16 08:26:16.309767665 -0500 +@@ -6,9 +6,6 @@ + + prog="`basename $0`" + +-PATH=/usr/local/bin:${PATH} +-export PATH +- + t1=/tmp/${prog}.1.$$ + + trap 'rm -f ${t1}; exit 1' 1 2 3 15 EXIT diff --git a/arpwatch-all-zero-bogon.patch b/arpwatch-all-zero-bogon.patch deleted file mode 100644 index 43066c4..0000000 --- a/arpwatch-all-zero-bogon.patch +++ /dev/null @@ -1,23 +0,0 @@ -RHBZ #244606: Correctly handle -n 0/32 to allow the user to disable reporting -bogons from 0.0.0.0. - -diff -Naur arpwatch-3.1-original/arpwatch.c arpwatch-3.1/arpwatch.c ---- arpwatch-3.1-original/arpwatch.c 2019-11-30 13:35:23.000000000 -0500 -+++ arpwatch-3.1/arpwatch.c 2020-11-07 12:10:53.357839069 -0500 -@@ -814,10 +814,12 @@ - - /* XXX hack */ - n = ntohl(inet_addr(tstr)); -- while ((n & 0xff000000) == 0) { -- n <<= 8; -- if (n == 0) -- return (0); -+ if (n || width != 32) { -+ while ((n & 0xff000000) == 0) { -+ n <<= 8; -+ if (n == 0) -+ return (0); -+ } - } - n = htonl(n); - diff --git a/arpwatch-arp2ethers-sort-invocation.patch b/arpwatch-arp2ethers-sort-invocation.patch deleted file mode 100644 index e321627..0000000 --- a/arpwatch-arp2ethers-sort-invocation.patch +++ /dev/null @@ -1,15 +0,0 @@ -Fix nonstandard sort flags (obsolete + notation for keys, available in some -BSDs for compatibility but non-POSIX and not supported by GNU sort). - -diff -Naur arpwatch-3.1-original/arp2ethers arpwatch-3.1/arp2ethers ---- arpwatch-3.1-original/arp2ethers 2013-02-16 03:10:28.000000000 -0500 -+++ arpwatch-3.1/arp2ethers 2020-11-07 11:22:04.762234105 -0500 -@@ -13,7 +13,7 @@ - # - sort - # - --sort +2rn arp.dat | -+sort -k 2 -rn arp.dat | - awk 'NF == 4 { print }' | - awk -f p.awk | - egrep -v '\.[0-9][0-9]*$' | diff --git a/arpwatch-arpfetch-stray-rm.patch b/arpwatch-arpfetch-stray-rm.patch deleted file mode 100644 index 6dfbd0b..0000000 --- a/arpwatch-arpfetch-stray-rm.patch +++ /dev/null @@ -1,11 +0,0 @@ -Fix stray rm (of an undefined variable). - -diff -Naur arpwatch-3.1-original/arpfetch arpwatch-3.1/arpfetch ---- arpwatch-3.1-original/arpfetch 2013-02-16 03:10:28.000000000 -0500 -+++ arpwatch-3.1/arpfetch 2020-11-07 11:22:59.344575624 -0500 -@@ -29,5 +29,3 @@ - ea = $2 - print ea "\t" ip - }' -- --rm -f ${t1} diff --git a/arpwatch-change-user.patch b/arpwatch-change-user.patch deleted file mode 100644 index 259a48f..0000000 --- a/arpwatch-change-user.patch +++ /dev/null @@ -1,146 +0,0 @@ -Add, and document, a -u argument to change to a specified unprivileged user -after establishing sockets. - -This patch rebases and combines arpwatch-drop.patch, which provided -u; -arpwatch-drop-man.patch, which documented it; and -arpwatch-2.1a15-dropgroup.patch, which fixed CVE-2012-2653 (RHBZ #825328) in -the original arpwatch-drop.patch, into a single combined patch. It also removes -an unnecessary and unchecked strdup() in the original patch that could have -theoretically led to a null pointer dereference. - -diff -Naur arpwatch-3.1-original/arpwatch.8.in arpwatch-3.1/arpwatch.8.in ---- arpwatch-3.1-original/arpwatch.8.in 2019-12-01 14:01:07.000000000 -0500 -+++ arpwatch-3.1/arpwatch.8.in 2020-11-11 08:41:45.881555301 -0500 -@@ -43,6 +43,7 @@ - .Op Fl n Ar net[/width] - .Op Fl x Ar net[/width] - .Op Fl r Ar file -+.Op Fl u Ar username - .Sh DESCRIPTION - .Nm - keeps track of ethernet/ip address pairings. It syslogs activity -@@ -128,13 +129,30 @@ - Note that an empty - .Ar arp.dat - file must be created before the first time you run --.Fl arpwatch . -+.Nm . -+Also, the default directory (where -+.Ar arp.dat -+is stored) must be owned by -+.Ar username -+if the -+.Fl u -+flag is used. - .Pp - The - .Fl s - flag suppresses reports sent by email. - .Pp - The -+.Fl u -+flag causes -+.Nm -+to drop root privileges and change user ID to -+.Ar username -+and group ID to that of the primary group of -+.Ar username . -+This is recommended for security reasons. -+.Pp -+The - .Fl v - flag disables the reporting of VRRP/CARP ethernet prefixes as - described in RFC5798 (00:00:5e:00:01:xx). -diff -Naur arpwatch-3.1-original/arpwatch.c arpwatch-3.1/arpwatch.c ---- arpwatch-3.1-original/arpwatch.c 2019-11-30 13:35:23.000000000 -0500 -+++ arpwatch-3.1/arpwatch.c 2020-11-11 08:42:34.574856970 -0500 -@@ -72,6 +72,8 @@ - #include - #include - -+#include -+#include - #include - - #include "gnuc.h" -@@ -170,6 +172,24 @@ - int toskip(u_int32_t); - void usage(void) __attribute__((noreturn)); - -+void dropprivileges(const char* user) -+{ -+ struct passwd* const pw = getpwnam(user); -+ if (pw) { -+ if (setgid(pw->pw_gid) != 0 || setgroups(0, NULL) != 0 || -+ setuid(pw->pw_uid) != 0) { -+ lg(LOG_ERR, "Couldn't change to '%.32s' uid=%d gid=%d", -+ user, pw->pw_uid, pw->pw_gid); -+ exit(1); -+ } -+ } else { -+ lg(LOG_ERR, "Couldn't find user '%.32s' in /etc/passwd", -+ user); -+ exit(1); -+ } -+ lg(LOG_DEBUG, "Running as uid=%d gid=%d", getuid(), getgid()); -+} -+ - int - main(int argc, char **argv) - { -@@ -181,6 +201,7 @@ - char *interface, *rfilename; - struct bpf_program code; - char errbuf[PCAP_ERRBUF_SIZE]; -+ char* serveruser = NULL; - - if (argv[0] == NULL) - prog = "arpwatch"; -@@ -198,7 +219,7 @@ - interface = NULL; - rfilename = NULL; - pd = NULL; -- while ((op = getopt(argc, argv, "CdD:Ff:i:n:NpP:qr:svw:W:x:zZ")) != EOF) -+ while ((op = getopt(argc, argv, "CdD:Ff:i:n:NpP:qr:svw:W:x:zZu:")) != EOF) - switch (op) { - - case 'C': -@@ -283,6 +304,17 @@ - zeropad = 1; - break; - -+ case 'u': -+ if (optarg) { -+ /* no need to strdup() a pointer into the -+ * original arguments vector */ -+ serveruser = optarg; -+ } else { -+ fprintf(stderr, "%s: Need username after -u\n", prog); -+ usage(); -+ } -+ break; -+ - default: - usage(); - } -@@ -379,6 +411,11 @@ - } - } - -+ /* Explicit user change (privilege drop) with -u? */ -+ if (serveruser) { -+ dropprivileges(serveruser); -+ } -+ - /* - * Revert to non-privileged user after opening sockets - * (not needed on most systems). -@@ -927,6 +964,7 @@ - "usage: %s [-CdFNpqsvzZ] [-D arpdir] [-f datafile]" - " [-i interface]\n\t" - " [-P pidfile] [-w watcher@email] [-W watchee@email]\n\t" -- " [-n net[/width]] [-x net[/width]] [-r file]\n", prog); -+ " [-n net[/width]] [-x net[/width]] [-r file] [-u username]\n", -+ prog); - exit(1); - } diff --git a/arpwatch-configure-no-local-pcap.patch b/arpwatch-configure-no-local-pcap.patch deleted file mode 100644 index a855de3..0000000 --- a/arpwatch-configure-no-local-pcap.patch +++ /dev/null @@ -1,15 +0,0 @@ -Do not attempt to search for local libpcap libraries lying around in the parent -of the build directory, or anywhere else random. This is not expected to -succeed anyway, but it is better to be sure. - -diff -Naur arpwatch-3.1-original/configure arpwatch-3.1/configure ---- arpwatch-3.1-original/configure 2020-04-05 20:22:04.000000000 -0400 -+++ arpwatch-3.1/configure 2020-11-07 11:59:40.114550004 -0500 -@@ -5437,6 +5437,7 @@ - places=`ls .. | sed -e 's,/$,,' -e 's,^,../,' | \ - egrep '/libpcap-[0-9]*\.[0-9]*(\.[0-9]*)?([ab][0-9]*)?$'` - for dir in $places ../libpcap libpcap ; do -+ break - basedir=`echo $dir | sed -e 's/[ab][0-9]*$//'` - if test $lastdir = $basedir ; then - continue; diff --git a/arpwatch-devlookup.patch b/arpwatch-devlookup.patch deleted file mode 100644 index 040705f..0000000 --- a/arpwatch-devlookup.patch +++ /dev/null @@ -1,145 +0,0 @@ -When -i is not given, iterate all available devices until a usable one is found -instead of just trying the first one and giving up if it is not usable. See -RHBZ #842660. - -Additionally, handle the case where a device provides both supported and -unsupported datalink types. - -diff -Naur arpwatch-3.1-original/arpwatch.c arpwatch-3.1/arpwatch.c ---- arpwatch-3.1-original/arpwatch.c 2019-11-30 13:35:23.000000000 -0500 -+++ arpwatch-3.1/arpwatch.c 2021-04-24 09:02:50.762535242 -0400 -@@ -161,6 +161,8 @@ - RETSIGTYPE die(int); - int isbogon(u_int32_t); - int main(int, char **); -+int try_open_live(pcap_t ** pd_ptr, char const * interface_name, -+ int promiscuous_enable); - void process_ether(u_char *, const struct pcap_pkthdr *, const u_char *); - void process_fddi(u_char *, const struct pcap_pkthdr *, const u_char *); - int readsnmp(char *); -@@ -177,7 +179,7 @@ - int op, snaplen, timeout, linktype, status; - pcap_t *pd; - FILE *fp; -- pcap_if_t *alldevs; -+ pcap_if_t *alldevs, *dev; - char *interface, *rfilename; - struct bpf_program code; - char errbuf[PCAP_ERRBUF_SIZE]; -@@ -309,13 +311,18 @@ - "%s: pcap_findalldevs: %s\n", prog, errbuf); - exit(1); - } -- if (alldevs == NULL) { -+ for (dev = alldevs; dev; dev = dev->next) { -+ if (try_open_live(&pd, dev->name, promisc)) { -+ interface = savestr(alldevs->name); -+ break; -+ } -+ } -+ pcap_freealldevs(alldevs); -+ if (interface == NULL) { - (void)fprintf(stderr, "%s: pcap_findalldevs:" - " no suitable devices found\n", prog); - exit(1); - } -- interface = savestr(alldevs->name); -- pcap_freealldevs(alldevs); - #else - if (interface = pcap_lookupdev(errbuf)) == NULL) { - (void)fprintf(stderr, -@@ -354,15 +361,12 @@ - } - swapped = pcap_is_swapped(pd); - } else { -- snaplen = max(sizeof(struct ether_header), -- sizeof(struct fddi_header)) + sizeof(struct ether_arp); -- timeout = 1000; -- pd = pcap_open_live(interface, snaplen, promisc, timeout, -- errbuf); - if (pd == NULL) { -- lg(LOG_ERR, "pcap open %s: %s", interface, errbuf); -- exit(1); -+ if (!try_open_live(&pd, interface, promisc)) { -+ exit(1); -+ } - } -+ /* else pd was already opened based on pcap_findalldevs */ - #ifdef WORDS_BIGENDIAN - swapped = 1; - #endif -@@ -452,6 +456,74 @@ - exit(0); - } - -+int -+try_open_live(pcap_t ** pd_ptr, char const * interface_name, int promiscuous_enable) { -+ /* Attempt to open an interface and set up a supported datalink type; -+ * return nonzero on success and zero on failure (and log a message). -+ */ -+ int snaplen, timeout, n_datalinks, datalink_i; -+ int * datalinks, datalink; -+ char errbuf[PCAP_ERRBUF_SIZE]; -+ -+ snaplen = max(sizeof(struct ether_header), -+ sizeof(struct fddi_header)) + sizeof(struct ether_arp); -+ timeout = 1000; -+ datalinks = NULL; -+ -+ /* Just in case... */ -+ if (*pd_ptr != NULL) { -+ pcap_close(*pd_ptr); -+ *pd_ptr = NULL; -+ } -+ -+ *pd_ptr = pcap_open_live(interface_name, snaplen, promiscuous_enable, -+ timeout, errbuf); -+ if (*pd_ptr == NULL) { -+ lg(LOG_ERR, "pcap open %s: %s", interface_name, errbuf); -+ goto fail; -+ } -+ -+ /* Must be able to select an ethernet or fddi datalink */ -+ n_datalinks = pcap_list_datalinks(*pd_ptr, &datalinks); -+ if (n_datalinks < 0) { -+ lg(LOG_ERR, "pcap_list_datalinks %s: %s", interface_name, -+ pcap_geterr(*pd_ptr)); -+ goto fail; -+ } -+ for (datalink_i = 0; datalink_i < n_datalinks; ++datalink_i) { -+ switch (datalinks[datalink_i]) { -+ case DLT_EN10MB: -+ case DLT_FDDI: -+ break; -+ default: -+ continue; /* unsupported; try the next datalink */ -+ } -+ if (pcap_set_datalink(*pd_ptr, datalinks[datalink_i]) != 0) { -+ lg(LOG_ERR, "pcap_set_datalink %s %d: %s", -+ interface_name, datalinks[datalink_i], -+ pcap_geterr(*pd_ptr)); -+ continue; -+ } -+ break; /* success */ -+ } -+ if (datalink_i >= n_datalinks) { -+ lg(LOG_ERR, "no ethernet or fddi datalink for %s", -+ interface_name); -+ goto fail; -+ } -+ -+ free(datalinks); -+ return 1; /* success */ -+ -+fail: -+ if (*pd_ptr != NULL) { -+ pcap_close(*pd_ptr); -+ *pd_ptr = NULL; -+ } -+ free(datalinks); -+ return 0; /* failure */ -+} -+ - /* Process an ethernet arp/rarp packet */ - void - process_ether(u_char *u, const struct pcap_pkthdr *h, const u_char *p) diff --git a/arpwatch-exitcode.patch b/arpwatch-exitcode.patch deleted file mode 100644 index a6c2d34..0000000 --- a/arpwatch-exitcode.patch +++ /dev/null @@ -1,15 +0,0 @@ -When arpwatch is terminated cleanly by a signal (INT/TERM/HUP) handler, the -exit code should be zero for success instead of nonzero for failure. - -diff -Naur arpwatch-3.1-original/arpwatch.c arpwatch-3.1/arpwatch.c ---- arpwatch-3.1-original/arpwatch.c 2019-11-30 13:35:23.000000000 -0500 -+++ arpwatch-3.1/arpwatch.c 2020-11-08 12:55:51.429575973 -0500 -@@ -892,7 +892,7 @@ - - lg(LOG_DEBUG, "exiting"); - checkpoint(0); -- exit(1); -+ exit(0); - } - - RETSIGTYPE diff --git a/arpwatch-man-references.patch b/arpwatch-man-references.patch deleted file mode 100644 index b7735c5..0000000 --- a/arpwatch-man-references.patch +++ /dev/null @@ -1,76 +0,0 @@ -Fix section numbers in man page cross-references. With minor changes, this -patch dates all the way back to arpwatch-2.1a4-man.patch, from RHBZ#15442. - -diff -Naur arpwatch-3.1-original/arpsnmp.8.in arpwatch-3.1/arpsnmp.8.in ---- arpwatch-3.1-original/arpsnmp.8.in 2019-12-01 14:01:07.000000000 -0500 -+++ arpwatch-3.1/arpsnmp.8.in 2020-11-05 15:13:01.296113145 -0500 -@@ -45,7 +45,7 @@ - and reports certain changes via email. - .Nm - reads information from a file (usually generated by --.Xr snmpwalk 3 ) . -+.Xr snmpwalk 1 ) . - .Pp - The format of the input file is the same as - .Ar arp.dat ; -@@ -119,9 +119,9 @@ - .Pp - .Sh "REPORT MESSAGES" - See the --.Xr arpwatch 1 -+.Xr arpwatch 8 - man page for details on the report messages generated by --.Xr arpsnmp 1 . -+.Xr arpsnmp 8 . - .Sh FILES - .Bl -tag -width ".Pa /usr/local/arpwatch" -compact - .It Pa /usr/local/arpwatch -@@ -132,7 +132,7 @@ - vendor ethernet block list - .Sh "SEE ALSO" - .Xr arpwatch 8 , --.Xr snmpwalk 8 , -+.Xr snmpwalk 1 , - .Xr arp 8 , - .Sh AUTHORS - .An Craig Leres -diff -Naur arpwatch-3.1-original/arpwatch.8.in arpwatch-3.1/arpwatch.8.in ---- arpwatch-3.1-original/arpwatch.8.in 2019-12-01 14:01:07.000000000 -0500 -+++ arpwatch-3.1/arpwatch.8.in 2020-11-05 15:14:12.117564292 -0500 -@@ -117,9 +117,9 @@ - .Fl r - flag is used to specify a savefile - (perhaps created by --.Xr tcpdump 1 -+.Xr tcpdump 8 - or --.Xr pcapture 1 ) -+.Xr pcapture 8 ) - to read from instead - of reading from the network. In this case - .Nm -@@ -163,9 +163,9 @@ - .Pp - .Sh "REPORT MESSAGES" - Here's a quick list of the report messages generated by --.Xr arpwatch 1 -+.Xr arpwatch 8 - (and --.Xr arpsnmp 1 ) : -+.Xr arpsnmp 8 ) : - .Pp - .Bl -tag -width xxx - .It Ic "new activity" -@@ -216,9 +216,9 @@ - .Sh "SEE ALSO" - .Xr arpsnmp 8 , - .Xr arp 8 , --.Xr bpf 4 , --.Xr tcpdump 1 , --.Xr pcapture 1 , -+.Xr bpf 2 , -+.Xr tcpdump 8 , -+.Xr pcapture 8 , - .Xr pcap 3 - .Sh AUTHORS - .An Craig Leres diff --git a/arpwatch-no-usr-local-path.patch b/arpwatch-no-usr-local-path.patch deleted file mode 100644 index 7085910..0000000 --- a/arpwatch-no-usr-local-path.patch +++ /dev/null @@ -1,40 +0,0 @@ -Do not add /usr/local/bin or /usr/local/sbin to the PATH in any scripts. - -diff -Naur arpwatch-3.1-original/arpfetch arpwatch-3.1/arpfetch ---- arpwatch-3.1-original/arpfetch 2013-02-16 03:10:28.000000000 -0500 -+++ arpwatch-3.1/arpfetch 2020-11-07 11:44:13.159658841 -0500 -@@ -4,8 +4,6 @@ - # arpfetch - collect arp data from a cisco using net-snmp - # - --export PATH="/usr/local/bin:${PATH}" -- - prog=`basename $0` - - if [ $# -ne 2 ]; then -diff -Naur arpwatch-3.1-original/bihourly.sh arpwatch-3.1/bihourly.sh ---- arpwatch-3.1-original/bihourly.sh 2016-09-16 22:40:54.000000000 -0400 -+++ arpwatch-3.1/bihourly.sh 2020-11-07 11:44:19.603699928 -0500 -@@ -3,9 +3,6 @@ - # - # bihourly arpwatch job - # --PATH=${PATH}:/usr/local/sbin --export PATH --# - cd /usr/local/arpwatch - # - list="`cat list`" -diff -Naur arpwatch-3.1-original/update-ethercodes.sh.in arpwatch-3.1/update-ethercodes.sh.in ---- arpwatch-3.1-original/update-ethercodes.sh.in 2020-04-05 20:35:37.000000000 -0400 -+++ arpwatch-3.1/update-ethercodes.sh.in 2020-11-07 11:44:23.293723456 -0500 -@@ -4,9 +4,6 @@ - # Generate ethercodes.dat - # - --PATH=/usr/local/bin:${PATH} --export PATH -- - if [ ! -f arp.dat ]; then - cd /usr/local/arpwatch || exit 1 - fi diff --git a/arpwatch.spec b/arpwatch.spec index 06f2293..4384da6 100644 --- a/arpwatch.spec +++ b/arpwatch.spec @@ -1,6 +1,6 @@ Name: arpwatch Epoch: 14 -Version: 3.1 +Version: 3.2 Release: %autorelease Summary: Network monitoring tools for tracking IP addresses on a network @@ -39,32 +39,32 @@ Source5: massagevendor.8 # Fix section numbers in man page cross-references. With minor changes, this # patch dates all the way back to arpwatch-2.1a4-man.patch, from RHBZ #15442. -Patch1: arpwatch-man-references.patch +Patch1: arpwatch-3.1-man-references.patch # Add, and document, a -u argument to change to a specified unprivileged user # after establishing sockets. This combines and improves multiple previous # patches; see patch header and changelog for notes. -Patch2: arpwatch-change-user.patch +Patch2: arpwatch-3.2-change-user.patch # Fix nonstandard sort flags in arp2ethers script. -Patch3: arpwatch-arp2ethers-sort-invocation.patch +Patch3: arpwatch-3.1-arp2ethers-sort-invocation.patch # Fix stray rm (of an undefined variable) in example arpfetch script. -Patch4: arpwatch-arpfetch-stray-rm.patch +Patch4: arpwatch-3.1-arpfetch-stray-rm.patch # Do not add /usr/local/bin or /usr/local/sbin to the PATH in any scripts -Patch5: arpwatch-no-usr-local-path.patch +Patch5: arpwatch-3.2-no-usr-local-path.patch # Do not attempt to search for local libpcap libraries lying around in the # parent of the build directory, or anywhere else random. This is not expected # to succeed anyway, but it is better to be sure. -Patch6: arpwatch-configure-no-local-pcap.patch +Patch6: arpwatch-3.1-configure-no-local-pcap.patch # RHBZ #244606: Correctly handle -n 0/32 to allow the user to disable reporting # bogons from 0.0.0.0. -Patch7: arpwatch-all-zero-bogon.patch +Patch7: arpwatch-3.1-all-zero-bogon.patch # When arpwatch is terminated cleanly by a signal (INT/TERM/HUP) handler, the # exit code should be zero for success instead of nonzero for failure. -Patch8: arpwatch-exitcode.patch +Patch8: arpwatch-3.1-exitcode.patch # When -i is not given, do not just try the first device found, but keep # checking devices until a usable one is found, if any is available. # Additionally, handle the case where a device provides both supported and # unsupported datalink types. -Patch9: arpwatch-devlookup.patch +Patch9: arpwatch-3.1-devlookup.patch %global pkgstatedir %{_sharedstatedir}/arpwatch %global service_user arpwatch @@ -99,9 +99,12 @@ sed -r -i 's|(-f *)([^[:blank:]+]\.awk)|\1%{_datadir}/arpwatch/\2|' arp2ethers # not installed. sed -r -i 's|/usr/local/arpwatch|%{pkgstatedir}|g' *.8.in *.sh.in *.sh +# Fix Python interpreter path (but note that this script is not installed) +sed -r -i 's|/usr/local/bin/python|%{python3}|g' update-ethercodes.sh.in + %build -%configure V_SENDMAIL=/usr/sbin/sendmail PYTHON=%{python3} +%configure --with-sendmail=/usr/sbin/sendmail PYTHON=%{python3} %make_build ARPDIR=%{pkgstatedir} diff --git a/sources b/sources index 3cc00f4..0f2617d 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (arpwatch-3.1.tar.gz) = 2e6f6e388e1828e34626e36356a89f3bc95d268b9242955d6636ac05041bcf533e7625ed73b37b6ea5eab8cfed54b8c483547556c98664efff63c18639efa282 +SHA512 (arpwatch-3.2.tar.gz) = 0a028e770e73f8ff2e926da5ab58e067c05908924a60cfc52c5fb7d57a0f36d3087f6cedb4a8b39b66ce85a4f6a12a594e7e74fd044331e5f346bcc9add99585