tcpdump mailing list archives

Dropping priviledges support


From: Earl Hood <earl () earlhood com>
Date: Tue, 20 Jan 2004 15:20:28 -0600


Since RedHat no longer support 7.3, I went to build tcpdump myself,
and noticed that priviledge dropping is not provided (at least
from what I saw) as is with the RH version of tcpdump.

Therefore, I adapted the patch work that RH did for its releases
for tcpdump 3.8.1.  One big difference between the RH version and
this patch is that RH used -U to specify which user to drop to, but
tcpdump 3.8.1 uses -U for something else.  Therefore, I went with -o.

The patch also does the auto-dropping to pcap user if the process
is running as root.

Is there any interest in making the priviledge dropping support
a default feature in the main distribution?

--ewh


diff -u --recursive tcpdump-3.8.1-org/VERSION tcpdump-3.8.1/VERSION
--- tcpdump-3.8.1-org/VERSION   Thu Aug  1 23:43:57 2002
+++ tcpdump-3.8.1/VERSION       Sun Jan 18 14:50:21 2004
@@ -1 +1 @@
-3.8
+3.8.1
diff -u --recursive tcpdump-3.8.1-org/tcpdump.1 tcpdump-3.8.1/tcpdump.1
--- tcpdump-3.8.1-org/tcpdump.1 Sun Nov 23 17:43:41 2003
+++ tcpdump-3.8.1/tcpdump.1     Sun Jan 18 14:55:39 2004
@@ -54,6 +54,10 @@
 .I module
 ]
 [
+.B \-o
+.I user
+]
+[
 .B \-r
 .I file
 ]
@@ -382,6 +386,11 @@
 if you give this flag then \fItcpdump\fP will print ``nic''
 instead of ``nic.ddn.mil''.
 .TP
+.B \-o
+Drop root priviledges and change user ID to \fIuser\fP.
+\fBNOTE\fR: This version of tcpdump will automatically drop to the
+pcap user if -o is not specified.
+.TP
 .B \-O
 Do not run the packet-matching code optimizer.
 This is useful only
diff -u --recursive tcpdump-3.8.1-org/tcpdump.c tcpdump-3.8.1/tcpdump.c
--- tcpdump-3.8.1-org/tcpdump.c Wed Dec 17 19:22:57 2003
+++ tcpdump-3.8.1/tcpdump.c     Sun Jan 18 14:53:35 2004
@@ -61,6 +61,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <pwd.h>
 
 #include "interface.h"
 #include "addrtoname.h"
@@ -298,6 +299,49 @@
 #define U_FLAG
 #endif
 
+#ifndef WIN32
+#define DROP_FLAG "o:"
+#define DROP_FLAG_OPT "o"
+#define DROP_FLAG_UOPT " [ -o user ]"
+
+#define WITH_USER "pcap"
+
+/* Drop root privileges */
+static
+void droproot(const char *username)
+{
+  struct passwd *pw = NULL;
+
+  if ((username == NULL) && (getuid() == 0 || geteuid() == 0)) {
+    username = WITH_USER;
+  }
+  if (username == NULL) {
+    setgid(getgid());
+    setuid(getuid());
+    return;
+  }
+
+  pw = getpwnam( username );
+  if ( pw ) {
+    if ( initgroups(pw->pw_name, NULL) != 0 || setgid(pw->pw_gid) != 0 ||
+       setuid(pw->pw_uid) != 0 ) {
+      fprintf(stderr, "Couldn't change to '%.32s' uid=%d gid=%d\n", username, 
+         pw->pw_uid, pw->pw_gid);
+      exit(1);
+    }
+  }
+  else {
+    fprintf(stderr, "Couldn't find user '%.32s'\n", username);
+    exit(1);
+  }
+}
+
+#else
+#define DROP_FLAG
+#define DROP_FLAG_OPT
+#define DROP_FLAG_UOPT
+#endif /* WIN32 */
+
 int
 main(int argc, char **argv)
 {
@@ -309,6 +353,7 @@
        struct bpf_program fcode;
 #ifndef WIN32
        RETSIGTYPE (*oldhandler)(int);
+       char *username = NULL;
 #endif
        struct print_info printinfo;
        struct dump_info dumpinfo;
@@ -343,7 +388,7 @@
 
        opterr = 0;
        while (
-           (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:nNOpqr:Rs:StT:u" U_FLAG "vw:xXy:Y")) != -1)
+           (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:nN" DROP_FLAG "Opqr:Rs:StT:u" U_FLAG 
"vw:xXy:Y")) != -1)
                switch (op) {
 
                case 'a':
@@ -494,7 +539,15 @@
                                      program_name, optarg);
                        (void)fprintf(stderr, "(no libsmi support)\n");
 #endif
-
+#ifndef WIN32
+               case 'o':
+                       if (optarg) {
+                           username = strdup(optarg);
+                       } else {
+                           /* NOT REACHED */
+                           usage();
+                       }
+#endif
                case 'O':
                        Oflag = 0;
                        break;
@@ -628,7 +681,9 @@
                 * people's trace files (especially if we're set-UID
                 * root).
                 */
-               setuid(getuid());
+               /* setuid(getuid()); */
+               droproot( username );
+
 #endif /* WIN32 */
                pd = pcap_open_offline(RFileName, ebuf);
                if (pd == NULL)
@@ -716,7 +771,9 @@
                 * Let user own process after socket has been opened.
                 */
 #ifndef WIN32
-               setuid(getuid());
+               /* setuid(getuid()); */
+               droproot( username );
+
 #endif /* WIN32 */
        }
        if (infile)
@@ -1126,9 +1183,9 @@
 #endif /* WIN32 */
 #endif /* HAVE_PCAP_LIB_VERSION */
        (void)fprintf(stderr,
-"Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name);
+"Usage: %s [-aAd" D_FLAG "eflLnNO" DROP_FLAG_OPT "pqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", 
program_name);
        (void)fprintf(stderr,
-"\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -r file ]\n");
+"\t\t[ -E algo:secret ] [ -F file ] [ -i interface ]" DROP_FLAG_UOPT " [ -r file ]\n");
        (void)fprintf(stderr,
 "\t\t[ -s snaplen ] [ -T type ] [ -w file ] [ -y datalinktype ]\n");
        (void)fprintf(stderr,
-
This is the TCPDUMP workers list. It is archived at
http://www.tcpdump.org/lists/workers/index.html
To unsubscribe use mailto:tcpdump-workers-request () tcpdump org?body=unsubscribe


Current thread: