diff -uprk.orig iftop-0.16.orig/configure.in iftop-0.16/configure.in --- iftop-0.16.orig/configure.in 2004-02-28 21:53:37 +0300 +++ iftop-0.16/configure.in 2004-03-31 14:51:09 +0400 @@ -53,6 +53,26 @@ AC_ARG_WITH(libpcap, [libpcap_prefix=$withval], [libpcap_prefix=""]) +AC_ARG_WITH(user, + [ --with-user=USERNAME Drop privileges by default to USERNAME]) +AC_MSG_CHECKING([whether to drop root privileges by default]) +if test -n "$withval"; then + AC_DEFINE_UNQUOTED(WITH_USER, "$withval", [Drop privileges by default to this username]) + AC_MSG_RESULT(to \"$withval\") +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 by default]) +if test -n "$withval"; then + AC_DEFINE_UNQUOTED(WITH_CHROOT, "$withval", [Chroot to this directory when dropping privileges]) + AC_MSG_RESULT(to \"$withval\") +else + AC_MSG_RESULT(no) +fi + dnl dnl Fairly generic checks. dnl diff -uprk.orig iftop-0.16.orig/iftop.c iftop-0.16/iftop.c --- iftop-0.16.orig/iftop.c 2004-02-28 21:47:54 +0300 +++ iftop-0.16/iftop.c 2004-03-31 17:05:33 +0400 @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include "iftop.h" #include "addr_hash.h" @@ -469,7 +472,6 @@ void packet_init() { } // exit(0); - resolver_initialise(); pd = pcap_open_live(options.interface, CAPTURE_LENGTH, options.promiscuous, 1000, errbuf); // DEBUG: pd = pcap_open_offline("tcpdump.out", errbuf); @@ -516,10 +518,70 @@ void packet_loop(void* ptr) { } +static int droproot (void) { + uid_t uid; + gid_t gid; + + if (geteuid()) + return 0; + + if (setgroups(0, NULL) < 0) { + perror ("setgroups"); + return 1; + } + + if ((uid = getuid()) == 0) { +#ifndef WITH_USER + return 0; +#else /* WITH_USER */ + const char *username = WITH_USER; + struct passwd *pw = getpwnam(username); + + if (!pw) { + fprintf(stderr, "lookup of user \"%s\" failed\n", username); + return 1; + } + + gid = pw->pw_gid; + uid = pw->pw_uid; + + if (uid == 0) { + fprintf(stderr, "user \"%s\" should not be privileged\n", + username); + return 1; + } + + endpwent(); + +#endif /* WITH_USER */ + } else { + gid = getgid(); + } + +#ifdef WITH_CHROOT + { + const char *chroot_dir = WITH_CHROOT; + if (chroot(chroot_dir) < 0 || chdir ("/") < 0) { + fprintf(stderr, "chroot/chdir to \"%s\" failed: %s\n", + chroot_dir, strerror(errno)); + return 1; + } + } +#endif /* WITH_CHROOT */ + + if (setgid(gid) < 0 || setuid(uid) < 0) { + fprintf(stderr, "setuid/setgid to %u:%u failed: %s\n", + uid, gid, strerror(errno)); + return 1; + } + + return 0; +} + /* main: * Entry point. See usage(). */ int main(int argc, char **argv) { - pthread_t thread; + int rc; struct sigaction sa = {}; /* TODO: tidy this up */ @@ -534,21 +596,27 @@ int main(int argc, char **argv) { sa.sa_handler = finish; sigaction(SIGINT, &sa, NULL); - pthread_mutex_init(&tick_mutex, NULL); - packet_init(); init_history(); ui_init(); - pthread_create(&thread, NULL, (void*)&packet_loop, NULL); + if ((rc = droproot()) == 0) { + pthread_t thread; + + pthread_mutex_init(&tick_mutex, NULL); - ui_loop(); + resolver_initialise(); - pthread_cancel(thread); + pthread_create(&thread, NULL, (void*)&packet_loop, NULL); + + ui_loop(); + + pthread_cancel(thread); + } ui_finish(); - return 0; + return rc; }