diff -upk.orig tcptraceroute-1.5beta7.orig/Makefile.am tcptraceroute-1.5beta7/Makefile.am --- tcptraceroute-1.5beta7.orig/Makefile.am 2004-12-27 23:57:56 +0000 +++ tcptraceroute-1.5beta7/Makefile.am 2005-01-03 16:48:23 +0000 @@ -1,5 +1,5 @@ bin_PROGRAMS = tcptraceroute -tcptraceroute_SOURCES = main.c datalink.c util.c probe.c capture.c +tcptraceroute_SOURCES = main.c datalink.c util.c probe.c capture.c droppriv.c man_MANS = tcptraceroute.1 docdir = $(datadir)/doc/tcptraceroute diff -upk.orig tcptraceroute-1.5beta7.orig/configure.ac tcptraceroute-1.5beta7/configure.ac --- tcptraceroute-1.5beta7.orig/configure.ac 2004-12-28 03:40:54 +0000 +++ tcptraceroute-1.5beta7/configure.ac 2005-01-03 16:44:57 +0000 @@ -24,6 +24,7 @@ AC_CHECK_FUNC(gethostbyname, ,[AC_CHECK_ AC_CHECK_FUNC(socket, ,[AC_CHECK_LIB(socket, socket)]) AC_CHECK_FUNC(connect, ,[AC_CHECK_LIB(inet, connect)]) AC_CHECK_FUNC(inet_aton, ,[AC_CHECK_LIB(resolv, inet_aton)]) +AC_CHECK_LIB(cap, cap_from_text, ,[AC_MSG_ERROR([cannot find libcap])]) AC_ARG_WITH(pcap, [], [ diff -upk.orig tcptraceroute-1.5beta7.orig/droppriv.c tcptraceroute-1.5beta7/droppriv.c --- tcptraceroute-1.5beta7.orig/droppriv.c 1970-01-01 00:00:00 +0000 +++ tcptraceroute-1.5beta7/droppriv.c 2006-03-29 16:36:08 +0000 @@ -0,0 +1,101 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "droppriv.h" + +uid_t user_uid = -1; + +void +priv_minimize(void) +{ + const char *dir = "/var/resolv"; + cap_t caps; + uid_t uid; + gid_t gid; + + user_uid = getuid(); + if (user_uid && geteuid()) + return; + + if (setgroups(0, NULL) < 0) + error(EXIT_FAILURE, errno, "setgroups"); + + if (prctl(PR_SET_KEEPCAPS, 1)) + error(EXIT_FAILURE, errno, "prctl PR_SET_KEEPCAPS failed"); + + if (user_uid == 0) + { + const char user[] = "iputils"; + struct passwd *pw = getpwnam(user); + + if (!pw) + error(EXIT_FAILURE, 0, "lookup of user \"%s\" failed", + user); + + gid = pw->pw_gid; + uid = pw->pw_uid; + endpwent(); + + if (uid == 0) + error(EXIT_FAILURE, 0, + "user \"%s\" shouldn't be root", user); + } else + { + uid = user_uid; + gid = getgid(); + } + + if (chroot(dir) < 0 || chdir("/") < 0) + error(EXIT_FAILURE, errno, "chroot to \"%s\" failed", dir); + + if (setgid(gid) < 0) + error(EXIT_FAILURE, errno, "setgid"); + + caps = cap_from_text + ("cap_setuid,cap_net_raw,cap_net_bind_service=ep"); + if (!caps) + error(EXIT_FAILURE, errno, "cap_from_text failed"); + + if (cap_set_proc(caps) < 0) + error(EXIT_FAILURE, errno, "cap_set_proc failed"); + + cap_free(caps); + + if (setreuid(uid, uid) < 0) + error(EXIT_FAILURE, errno, "setreuid"); + + caps = cap_from_text("cap_net_raw,cap_net_bind_service=ep"); + if (!caps) + error(EXIT_FAILURE, errno, "cap_from_text failed"); + + if (cap_set_proc(caps) < 0) + error(EXIT_FAILURE, errno, "cap_set_proc failed"); + + cap_free(caps); +} + +void +priv_drop(void) +{ + cap_t caps; + + caps = cap_from_text("all-ep"); + if (!caps) + error(EXIT_FAILURE, errno, "cap_from_text failed"); + + if (cap_set_proc(caps) < 0) + error(EXIT_FAILURE, errno, "cap_set_proc failed"); + + cap_free(caps); +} diff -upk.orig tcptraceroute-1.5beta7.orig/droppriv.h tcptraceroute-1.5beta7/droppriv.h --- tcptraceroute-1.5beta7.orig/droppriv.h 1970-01-01 00:00:00 +0000 +++ tcptraceroute-1.5beta7/droppriv.h 2005-01-03 16:44:57 +0000 @@ -0,0 +1,12 @@ +#ifndef TCPTRACEROUTE_DROPPRIV_H__ +#define TCPTRACEROUTE_DROPPRIV_H__ + +#include + +extern void priv_minimize(void); +extern void priv_drop(void); + +extern uid_t user_uid; + +#endif /* TCPTRACEROUTE_DROPPRIV_H__ */ + diff -upk.orig tcptraceroute-1.5beta7.orig/main.c tcptraceroute-1.5beta7/main.c --- tcptraceroute-1.5beta7.orig/main.c 2006-03-29 16:28:44 +0000 +++ tcptraceroute-1.5beta7/main.c 2006-03-29 16:34:22 +0000 @@ -21,6 +21,7 @@ */ #include "tcptraceroute.h" +#include "droppriv.h" /* globals */ u_long dst_ip, src_ip, isn; @@ -249,6 +250,8 @@ int main(int argc, char **argv) char *optstring, *s; int op, i, exitcode; + priv_minimize(); + src_ip = 0; src_prt = 0; dst_prt = DEFAULT_PORT; @@ -449,7 +452,7 @@ int main(int argc, char **argv) case 'P': /* ARG */ o_forceport = 1; case 'p': /* ARG */ - if (getuid()) fatal("Sorry, must be root to use -p\n"); + if (user_uid) fatal("Sorry, must be root to use -p\n"); src_prt = checknumericarg(); debug("src_prt set to %d\n", src_prt); break; @@ -465,7 +468,7 @@ int main(int argc, char **argv) break; case 's': /* ARG */ - if (getuid()) fatal("Sorry, must be root to use -s\n"); + if (user_uid) fatal("Sorry, must be root to use -s\n"); src = optarg; break; @@ -527,13 +530,10 @@ int main(int argc, char **argv) show_usage("Invalid number of arguments"); } - if (getuid() & geteuid()) - fatal("Got root?\n"); - initlibnet(); defaults(); initcapture(); - setuid(getuid()); + priv_drop(); exitcode = trace(); #if (LIBNET_API_VERSION >= 110) libnet_destroy(libnet_context);