--- server/dhcpd.c +++ server/dhcpd.c 2008/09/05 08:22:38 @@ -47,6 +47,15 @@ static char url [] = "For info, please v #include "version.h" #include +#ifdef PARANOIA +# include +# include +/* get around the ISC's declaration of group */ +#define group real_group +# include +#undef group +#endif + static void usage PROTO ((void)); struct iaddr server_identifier; @@ -225,6 +234,15 @@ int main (argc, argv, envp) char *traceinfile = (char *)0; char *traceoutfile = (char *)0; #endif +#ifdef PARANOIA + char *set_user = NULL; + char *set_group = NULL; + char *set_chroot = NULL; + + uid_t set_uid = 0; + gid_t set_gid = 0; +#endif + /* Make sure that file descriptors 0 (stdin), 1, (stdout), and 2 (stderr) are open. To do this, we assume that when we @@ -286,6 +304,20 @@ int main (argc, argv, envp) daemon = 0; #endif log_perror = -1; +#ifdef 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 } else if (!strcmp (argv [i], "-s")) { if (++i == argc) usage (); @@ -347,7 +379,7 @@ int main (argc, argv, envp) log_fatal ("Insufficient memory to %s %s: %s", "record interface", argv [i], isc_result_totext (result)); - strcpy (tmp -> name, argv [i]); + strncpy (tmp -> name, argv [i], sizeof(tmp->name)-1); if (interfaces) { interface_reference (&tmp -> next, interfaces, MDL); @@ -412,6 +444,66 @@ int main (argc, argv, envp) } } +#ifdef PARANOIA + /* get user and group info if those options were given */ + if (set_user) { + struct passwd *tmp_pwd; + + /* + ** I query for the real UID and not for the effective UID + ** just to force the user to run this server as root and + ** not setting it suid. It should be a paranoia patch and + ** not a teletubbie patch. *eg* + ** Note: That the user is still able to set it suid! *zitter* + ** thomas@suse.de + */ + if (getuid()) + error ("you must be root to set user"); + + if (!(tmp_pwd = getpwnam(set_user))) + error ("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's declaration of group */ +#define group real_group + struct group *tmp_grp; + + /* + ** getuid() instead of geteuid(), see above + */ + if (getuid()) + error ("you must be root to set group"); + + if (!(tmp_grp = getgrnam(set_group))) + error ("no such group: %s", set_group); + + set_gid = tmp_grp->gr_gid; +#undef group + } + + if (set_chroot) { + if (getuid()) /* see above */ + error ("you must be root to use chroot"); + + if (chroot(set_chroot) != 0) { + error ("chroot(\"%s\"): %s", set_chroot, + strerror(errno)); + } + if (chdir ("/") != 0) { + /* probably permission denied */ + error ("chdir(\"/\"): %s", strerror(errno)); + } + } +#endif /* PARANOIA */ + remote_port = htons (ntohs (local_port) + 1); if (server) { @@ -601,6 +693,27 @@ int main (argc, argv, envp) omapi_set_int_value ((omapi_object_t *)dhcp_control_object, (omapi_object_t *)0, "state", server_running); +#ifdef PARANOIA + /* change uid to the specified one */ + + /* + ** common failure: forget to drop supplementary GID'S ;-> + ** thomas@suse.de + */ + + if (set_gid) { + if(setgroups(0, NULL) < 0) + error("couldn't drop supplementary groups!"); + if (setgid (set_gid) != 0) + error ("couldn't set gid to %d", set_gid); + } + + if (set_uid) { + if (setuid (set_uid) != 0) + error ("couldn't set uid to %d", set_uid); + } +#endif + /* Receive packets and dispatch them... */ dispatch (); @@ -879,6 +992,10 @@ static void usage () log_fatal ("Usage: dhcpd [-p ] [-d] [-f]%s%s%s%s", "\n [-cf config-file] [-lf lease-file]", +#ifdef PARANOIA + "\n [-user ] [-group ]", + "\n [-chroot ]", +#endif #if defined (TRACING) "\n [-tf trace-output-file]", "\n [-play trace-input-file]",