diff -ur -x configure tcpdump-2004.02.24/acconfig.h tcpdump-2004.02.23.new/acconfig.h --- tcpdump-2004.02.24/acconfig.h Thu Jan 22 11:51:30 2004 +++ tcpdump-2004.02.23.new/acconfig.h Wed Feb 25 09:04:41 2004 @@ -129,3 +129,6 @@ /* define if should drop privileges by default */ #undef WITH_USER + +/* define if should chroot when dropping privileges */ +#undef WITH_CHROOT diff -ur -x configure tcpdump-2004.02.24/configure.in tcpdump-2004.02.23.new/configure.in --- tcpdump-2004.02.24/configure.in Sat Jan 31 07:26:51 2004 +++ tcpdump-2004.02.23.new/configure.in Wed Feb 25 09:23:03 2004 @@ -111,6 +111,15 @@ AC_MSG_RESULT(no) fi +AC_ARG_WITH(chroot, [ --with-chroot=DIRECTORY when dropping privileges, chroot to DIRECTORY]) +AC_MSG_CHECKING([where to chroot to]) +if test ! -z "$with_chroot" ; then + AC_DEFINE_UNQUOTED(WITH_CHROOT, "$withval") + AC_MSG_RESULT(to \"$withval\") +else + AC_MSG_RESULT(no) +fi + AC_MSG_CHECKING([whether to enable ipv6]) AC_ARG_ENABLE(ipv6, [ --enable-ipv6 enable ipv6 (with ipv4) support diff -ur -x configure tcpdump-2004.02.24/tcpdump.c tcpdump-2004.02.23.new/tcpdump.c --- tcpdump-2004.02.24/tcpdump.c Tue Feb 24 10:12:18 2004 +++ tcpdump-2004.02.23.new/tcpdump.c Wed Feb 25 09:56:25 2004 @@ -129,7 +129,7 @@ static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); -static void droproot(const char *); +static void droproot(const char *, const char *); #ifdef SIGINFO RETSIGTYPE requestinfo(int); @@ -324,15 +324,26 @@ #define U_FLAG #endif -/* Drop root privileges */ +/* Drop root privileges and chroot if necessary */ static void -droproot(const char *username) +droproot(const char *username, const char *chroot_dir) { struct passwd *pw = NULL; + if (chroot_dir && !username) { + fprintf(stderr, "Chroot without dropping root is insecure\n"); + exit(1); + } + pw = getpwnam(username); if (pw) { - if (initgroups(pw->pw_name, 0) != 0 || setgid(pw->pw_gid) != 0 || + if (chroot_dir) { + if (chroot(chroot_dir) != 0 || chdir (".") != 0) { + fprintf(stderr, "Couldn't chroot/chdir to '%.64s'\n", chroot_dir); + exit(1); + } + } + if (initgroups(pw->pw_name, pw->pw_gid) != 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); @@ -386,6 +397,7 @@ u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; char *username = NULL; + char *chroot_dir = NULL; #ifdef HAVE_PCAP_FINDALLDEVS pcap_if_t *devpointer; int devnum; @@ -704,6 +716,15 @@ if (tflag > 0) thiszone = gmt2local(0); +#ifdef WITH_CHROOT + /* if run as root, prepare for chrooting */ + if (getuid() == 0 || geteuid() == 0) { + /* future extensibility for cmd-line arguments */ + if (!chroot_dir) + chroot_dir = WITH_CHROOT; + } +#endif + #ifdef WITH_USER /* if run as root, prepare for dropping root privileges */ if (getuid() == 0 || geteuid() == 0) { @@ -885,9 +906,8 @@ * We cannot do this earlier, because we want to be able to open * the file (if done) for writing before giving up permissions. */ - if (username) { - droproot(username); - } + if (username || chroot_dir) + droproot(username, chroot_dir); #endif /* WIN32 */ #ifdef SIGINFO (void)setsignal(SIGINFO, requestinfo);