From: David Hankins Date: Wed, 27 Feb 2008 21:22:17 +0000 (+0000) Subject: - Ari Edelkind's PARANOIA patch has been included and may be compiled in X-Git-Tag: v4_1_0a2~53 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=63971a832353a02d329d93d7d6af8d211ed7911f;p=thirdparty%2Fdhcp.git - Ari Edelkind's PARANOIA patch has been included and may be compiled in via two ./configure parameters, --enable-paranoia and --enable-early-chroot. [ISC-Bugs #17611] --- diff --git a/RELNOTES b/RELNOTES index a6b2e896b..dd06e76ef 100644 --- a/RELNOTES +++ b/RELNOTES @@ -48,6 +48,12 @@ work on other platforms. Please report any problems and suggested fixes to . + Changes since 4.1.0a1 + +- Ari Edelkind's PARANOIA patch has been included and may be compiled in + via two ./configure parameters, --enable-paranoia and + --enable-early-chroot. + Changes since 4.0.0 (new features) - Added DHCPv6 rapid commit support. diff --git a/configure.ac b/configure.ac index 0f43814e2..f09ad129d 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,29 @@ if test "$enable_dhcpv6" != "no"; then [Define to 1 to include DHCPv6 support.]) fi +# PARANOIA is off by default (until we can test it with all features) +AC_ARG_ENABLE(paranoia, + AC_HELP_STRING([--enable-paranoia], + [enable support for chroot/setuid (default is no)])) +AC_ARG_ENABLE(early_chroot, + AC_HELP_STRING([--eanble-early-chroot], + [enable chrooting prior to configuration (default is no)])) +# If someone enables early chroot, but does not enable paranoia, do so for +# them. +if test "$enable_paranoia" != "yes" && \ + test "$enable_early_chroot" = "yes" ; then + enable_paranoia="yes" +fi + +if test "$enable_paranoia" = "yes" ; then + AC_DEFINE([PARANOIA], [1], + [Define to any value to include Ari's PARANOIA patch.]) +fi +if test "$enable_early_chroot" = "yes" ; then + AC_DEFINE([EARLY_CHROOT], [1], + [Define to any value to chroot() prior to loading config.]) +fi + ### ### Path fun. Older versions of DHCP were installed in /usr/sbin, so we ### need to look there and potentially overwrite by default (but not if diff --git a/server/dhcpd.c b/server/dhcpd.c index 0b488d38d..c6084df31 100644 --- a/server/dhcpd.c +++ b/server/dhcpd.c @@ -47,6 +47,16 @@ static char url [] = "For info, please visit http://www.isc.org/sw/dhcp/"; #include #include +#if defined (PARANOIA) +# include +# include +# include +/* get around the ISC declaration of group */ +# define group real_group +# include +# undef group +#endif /* PARANOIA */ + static void usage(void); struct iaddr server_identifier; @@ -196,6 +206,22 @@ static void omapi_listener_start (void *foo) omapi_object_dereference (&listener, MDL); } +#if defined (PARANOIA) +/* to be used in one of two possible scenarios */ +static void setup_chroot (char *chroot_dir) { + if (geteuid()) + log_fatal ("you must be root to use chroot"); + + if (chroot(chroot_dir)) { + log_fatal ("chroot(\"%s\"): %m", chroot_dir); + } + if (chdir ("/")) { + /* probably permission denied */ + log_fatal ("chdir(\"/\"): %m"); + } +} +#endif /* PARANOIA */ + #ifndef UNIT_TEST int main(int argc, char **argv) { @@ -228,6 +254,15 @@ main(int argc, char **argv) { char *traceoutfile = (char *)0; #endif +#if defined (PARANOIA) + char *set_user = 0; + char *set_group = 0; + char *set_chroot = 0; + + uid_t set_uid = 0; + gid_t set_gid = 0; +#endif /* PARANOIA */ + /* Make sure that file descriptors 0 (stdin), 1, (stdout), and 2 (stderr) are open. To do this, we assume that when we open a file the lowest available file descriptor is used. */ @@ -287,6 +322,20 @@ main(int argc, char **argv) { if (++i == argc) usage (); server = argv [i]; +#if defined (PARANOIA) + } else if (!strcmp (argv [i], "-user")) { + if (++i == argc) + usage (); + set_user = argv [i]; + } else if (!strcmp (argv [i], "-group")) { + if (++i == argc) + usage (); + set_group = argv [i]; + } else if (!strcmp (argv [i], "-chroot")) { + if (++i == argc) + usage (); + set_chroot = argv [i]; +#endif /* PARANOIA */ } else if (!strcmp (argv [i], "-cf")) { if (++i == argc) usage (); @@ -440,6 +489,44 @@ main(int argc, char **argv) { trace_seed_stop, MDL); #endif +#if defined (PARANOIA) + /* get user and group info if those options were given */ + if (set_user) { + struct passwd *tmp_pwd; + + if (geteuid()) + log_fatal ("you must be root to set user"); + + if (!(tmp_pwd = getpwnam(set_user))) + log_fatal ("no such user: %s", set_user); + + set_uid = tmp_pwd->pw_uid; + + /* use the user's group as the default gid */ + if (!set_group) + set_gid = tmp_pwd->pw_gid; + } + + if (set_group) { +/* get around the ISC declaration of group */ +#define group real_group + struct group *tmp_grp; + + if (geteuid()) + log_fatal ("you must be root to set group"); + + if (!(tmp_grp = getgrnam(set_group))) + log_fatal ("no such group: %s", set_group); + + set_gid = tmp_grp->gr_gid; +#undef group + } + +# if defined (EARLY_CHROOT) + if (set_chroot) setup_chroot (set_chroot); +# endif /* EARLY_CHROOT */ +#endif /* PARANOIA */ + /* Default to the DHCP/BOOTP port. */ if (!local_port) { @@ -583,6 +670,10 @@ main(int argc, char **argv) { log_fatal ("Configuration file errors encountered -- exiting"); postconf_initialization (quiet); + +#if defined (PARANOIA) && !defined (EARLY_CHROOT) + if (set_chroot) setup_chroot (set_chroot); +#endif /* PARANOIA && !EARLY_CHROOT */ /* test option should cause an early exit */ if (cftest && !lftest) @@ -661,6 +752,22 @@ main(int argc, char **argv) { else if (pid) exit (0); } + +#if defined (PARANOIA) + /* change uid to the specified one */ + + if (set_gid) { + if (setgroups (0, (void *)0)) + log_fatal ("setgroups: %m"); + if (setgid (set_gid)) + log_fatal ("setgid(%d): %m", (int) set_gid); + } + + if (set_uid) { + if (setuid (set_uid)) + log_fatal ("setuid(%d): %m", (int) set_uid); + } +#endif /* PARANOIA */ /* Read previous pid file. */ if ((i = open (path_dhcpd_pid, O_RDONLY)) >= 0) { @@ -1056,6 +1163,10 @@ usage(void) { #else /* !DHCPv6 */ " [-cf config-file] [-lf lease-file]\n" #endif /* DHCPv6 */ +#if defined (PARANOIA) + /* meld into the following string */ + " [-user user] [-group group] [-chroot dir]\n" +#endif /* PARANOIA */ #if defined (TRACING) " [-tf trace-output-file]\n" " [-play trace-input-file]\n"