From: hannes Date: Wed, 25 Feb 2004 14:23:32 +0000 (+0000) Subject: from Pekka Savola : X-Git-Tag: tcpdump-3.9.1~467 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/6d605cea6d44577717311d651f579e6fd795f057 from Pekka Savola : - add compile time option WITH_CHROOT - chroot() when dropping privileges --- diff --git a/acconfig.h b/acconfig.h index 5a2b508b..7b682c3f 100644 --- a/acconfig.h +++ b/acconfig.h @@ -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 --git a/configure.in b/configure.in index 609859d1..2efabe38 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/tcpdump/configure.in,v 1.175 2004-01-31 05:26:51 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/tcpdump/configure.in,v 1.176 2004-02-25 14:23:32 hannes Exp $ (LBL) dnl dnl Copyright (c) 1994, 1995, 1996, 1997 dnl The Regents of the University of California. All rights reserved. @@ -6,7 +6,7 @@ dnl dnl Process this file with autoconf to produce a configure script. dnl -AC_REVISION($Revision: 1.175 $) +AC_REVISION($Revision: 1.176 $) AC_PREREQ(2.50) AC_INIT(tcpdump.c) @@ -111,6 +111,15 @@ else AC_MSG_RESULT(no) fi +AC_ARG_WITH(chroot, [ --with-chroot=DIRECTORY when dropping privileges, chroot to DIRECTORY]) +AC_MSG_CHECKING([whether to chroot]) +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 --git a/tcpdump.c b/tcpdump.c index 7f751f0e..e3693e73 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -30,7 +30,7 @@ static const char copyright[] _U_ = "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ The Regents of the University of California. All rights reserved.\n"; static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.231 2004-02-24 08:12:18 hannes Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.232 2004-02-25 14:23:32 hannes Exp $ (LBL)"; #endif /* @@ -129,7 +129,7 @@ static void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn)); 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 @@ show_dlts_and_exit(pcap_t *pd) #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 @@ main(int argc, char **argv) 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 @@ main(int argc, char **argv) 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 @@ main(int argc, char **argv) * 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);