--- tcpdump-3.7.1.dist/tcpdump.1 Sun Jun 30 14:12:39 2002 +++ tcpdump-3.7.1/tcpdump.1 Sun Jun 30 14:11:09 2002 @@ -66,6 +66,10 @@ .I type ] [ +.B \-U +.I user +] +[ .B \-w .I file ] @@ -348,6 +352,12 @@ .B \-tt Print an unformatted timestamp on each dump line. .TP +.B \-U +Drops root privileges and changes user ID to +.I user +and group ID to the primary group of +.IR user . +.TP .B \-ttt Print a delta (in micro-seconds) between current and previous line on each dump line. --- tcpdump-3.7.1.dist/tcpdump.c Sun Dec 23 00:12:23 2001 +++ tcpdump-3.7.1/tcpdump.c Sun Jun 30 14:11:09 2002 @@ -57,7 +57,7 @@ #include #include #include - +#include #include "interface.h" #include "addrtoname.h" @@ -186,6 +186,25 @@ pcap_dumper_t *p; }; +/* Drop root privileges */ +void droproot(const char *username) +{ + struct passwd *pw = NULL; + 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); + } +} + int main(int argc, char **argv) { @@ -198,6 +217,7 @@ struct dump_info dumpinfo; u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; + char *username = NULL; cnt = -1; device = NULL; @@ -218,7 +238,7 @@ opterr = 0; while ( - (op = getopt(argc, argv, "ac:C:deE:fF:i:lm:nNOpqr:Rs:StT:uvw:xXY")) != -1) + (op = getopt(argc, argv, "ac:C:deE:fF:i:lm:nNOpqr:Rs:StT:uvw:xXYU:")) != -1) switch (op) { case 'a': @@ -381,6 +401,16 @@ } break; #endif + case 'U': + if ( optarg ) { + username = strdup(optarg); + } + else { + usage(); + /* NOTREACHED */ + } + break; + default: usage(); /* NOTREACHED */ @@ -398,7 +428,13 @@ * Also, this prevents the user from reading anyone's * trace file. */ - setuid(getuid()); + if ( username ) { + droproot( username ); + } + else { + if ( setgid(getgid()) != 0 || setuid(getuid()) != 0 ) + fprintf(stderr, "Warning: setgid/setuid failed !\n"); + } pd = pcap_open_offline(RFileName, ebuf); if (pd == NULL) @@ -432,7 +468,13 @@ /* * Let user own process after socket has been opened. */ - setuid(getuid()); + if ( username ) { + droproot( username ); + } + else { + if ( setgid(getgid()) != 0 || setuid(getuid()) != 0 ) + fprintf(stderr, "Warning: setgid/setuid failed !\n"); + } } if (infile) cmdbuf = read_infile(infile); @@ -642,6 +684,6 @@ (void)fprintf(stderr, "\t\t[ -F file ] [ -i interface ] [ -r file ] [ -s snaplen ]\n"); (void)fprintf(stderr, -"\t\t[ -T type ] [ -w file ] [ -E algo:secret ] [ expression ]\n"); +"\t\t[ -T type ] [-U user] [ -w file ] [ -E algo:secret ] [ expression ]\n"); exit(1); }