--- server/dhcpd.c
+++ server/dhcpd.c	Sun Mar 18 03:58:15 2001
@@ -56,6 +56,15 @@
 #include "version.h"
 #include <omapip/omapip_p.h>
 
+#ifdef PARANOIA
+#	include <errno.h>
+#	include <pwd.h>
+/* get around the ISC's declaration of group */
+#define group  real_group
+#	include <grp.h>
+#undef group
+#endif
+
 static void usage PROTO ((void));
 
 TIME cur_time;
@@ -214,6 +223,15 @@
 	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
+
 
 	/* Set up the client classification system. */
 	classification_setup ();
@@ -262,6 +280,20 @@
 			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 ();
@@ -323,7 +355,7 @@
 				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);
@@ -384,6 +416,66 @@
 		}
 	}
   
+#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) {
@@ -587,6 +679,27 @@
 	dump_rc_history ();
 #endif
 
+#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 ();
 
@@ -851,6 +964,10 @@
 
 	log_fatal ("Usage: dhcpd [-p <UDP port #>] [-d] [-f]%s%s%s%s",
 		   "\n             [-cf config-file] [-lf lease-file]",
+#ifdef PARANOIA
+		   "\n             [-user <user>] [-group <group>]",
+		   "\n             [-chroot <dir>]",
+#endif
 #if defined (TRACING)
 		   "\n		   [-tf trace-output-file]",
 		   "\n		   [-play trace-input-file]",