On Wed, 25 Feb 2004, Jefferson Ogata wrote:
> > This doesn't try to automatically create directories or whatever, but 
> > relies on the compile time option (e.g. /var/empty) but is IMHO better 
> > in some sense.
> 
> > -           if (initgroups(pw->pw_name, 0) != 0 || setgid(pw->pw_gid) != 0 ||
> > +           if (chroot_dir) {
> > +                   if (chroot(chroot_dir) != 0 || chdir (".") != 0) {
> 
> No, you have to chdir to "/". Or better, do (chdir(chroot_dir) != 0 || 
> chroot(".") != 0). 

Oops -- sorry for the typo!  Obviously, that should be chdir("/") :)

I was looking this after my another patch, to chroot/droproot ntp, and
didn't copy it appropriately.

> There's one issue that occurred to me with chroot: on some 
> platforms/configurations there may be a need for access to certain files outside 
> the jail. If any get*byname() calls are being used, there may be a need for 
> access to /etc/resolv.conf, /etc/protocols, etc. On IRIX, it's worse since all 
> the get*by*() calls end up relying on access to /ns. So if -n isn't in force, 
> chrooting might break some lookups. So that also argues for a commandline 
> argument at least to switch it off.

I would not enable tcpdump at compile time on such systems, so I don't
think this is a particularly nasty problem.

-- 
Pekka Savola                 "You each name yourselves king, yet the
Netcore Oy                    kingdom bleeds."
Systems. Networks. Security. -- George R.R. Martin: A Clash of Kings
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([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 -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);

Reply via email to