On Mon, 2003-08-25 at 14:22, Chris B. Vetter wrote:
> Hi,
> 
> attached is a modified version of the patch I sent last week that
> finally takes care of the UID and GID retrieval, by trying to get that
> information BEFORE jail'ing gdomap to /tmp.
> 


I had to apply the patch by hand, so I'm not sure I did it right. Here's
another updated patch. I changed a few things and also added a fix for
changing to /tmp on MinGW.

Can you check if this is ok?  I'd still like to get comments from other
people as well, though, before I commit it.


Index: Tools/gdomap.c
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Tools/gdomap.c,v
retrieving revision 1.75
diff -u -p -r1.75 gdomap.c
--- Tools/gdomap.c	2 Sep 2003 02:44:15 -0000	1.75
+++ Tools/gdomap.c	3 Sep 2003 03:30:41 -0000
@@ -823,7 +823,7 @@ static unsigned long	prb_used = 0;
 static unsigned long	prb_size = 0;
 typedef struct	{
   struct in_addr	sin;
-  long			when;
+  time_t		when;
 } prb_type;
 static prb_type	**prb = 0;
 
@@ -4598,27 +4598,119 @@ printf(
 #endif
     }
 
-#if	!defined(__svr4__)
   /*
    * As another level of paranoia - restrict this process to /tmp
    */
-  if (chdir("/tmp") < 0)
-    {
-      sprintf(ebuf, "Unable to change directory to /tmp");
-      gdomap_log(LOG_CRIT);
-      exit(EXIT_FAILURE);
-    }
+  
+  {
+    char tmpdir[1024];
+    //
+    // Try to get the UID and GID first
+    //
+     
 #ifndef __MINGW__
-  if (geteuid() == 0)
-    {
-      if (chroot("/tmp") < 0)
-	{
-	  sprintf(ebuf, "Unable to change root to /tmp");
-	  gdomap_log(LOG_CRIT);
-	  exit(EXIT_FAILURE);
-	}
-      chdir("/");
-    }
+#ifdef __FreeBSD__
+    uid_t	uid = 65534; // setuid(2) expects an unsigned int
+    gid_t	gid = 65534; // dito for getgid(2)
+#else /* __FreeBSD__ */
+    int		uid = -2;
+    int		gid = -2;
+#endif /* __FreeBSD__ */
+    
+    /*
+     * If we are not 'root' simply use our own UID and GID so we can
+     * later kill it again if needed
+     */
+    
+    if( getuid() != 0 )
+      {
+	uid = getuid();
+	gid = getgid();
+      }
+    else // gdomap runs as 'root' so we try to switch to 'nobody'
+      {
+#ifdef	HAVE_PWD_H
+#ifdef	HAVE_GETPWNAM
+	const char	*name = "nobody";
+	struct passwd	*pwd;
+       
+#ifdef __FreeBSD__
+	// rewind the PWD database to the beginning and make sure it says open
+	setpassent(1);
+#endif
+       
+	/*
+	 * Translate name into a PWD pointer
+	 */
+       
+	pwd = (struct passwd *) getpwnam(name);
+       
+	if( pwd )
+	  {
+	    uid = pwd->pw_uid;
+	    gid = pwd->pw_gid;
+	  }
+	else // Failed, let's try as a number
+	  {
+	    long	id;
+	    char	*p;
+         
+	    id = strtol(name, &p, 10);
+         
+	    if( *name && !*p && (pwd = getpwuid(id)) )
+	      {
+		uid = pwd->pw_uid;
+		gid = pwd->pw_gid;
+	      }
+	    else // Failed as well, dump a warning
+	      {
+		sprintf(ebuf, "Cannot get UID and GID, assuming default values.");
+		gdomap_log(LOG_WARNING);
+	      }
+	  }
+#ifdef __FreeBSD__
+	// close the PWD database
+	endpwent();
+#endif /* __FreeBSD__ */
+#endif /* HAVE_GETPWNAM */
+#endif /* HAVE_PWD_H */
+      }
+#endif /* __MINGW__ */
+   
+    /*
+     * Now that we got the UID and GID, we can jail gdomap to /tmp
+     */
+     
+#if !defined(__svr4__)
+#ifndef __MINGW__
+    strcpy(tmpdir, "/tmp");
+#else
+    if (GetTempPath(1024, tmpdir) == 0)
+      {
+	sprintf(ebuf, "Unable to find temporary dir");
+	gdomap_log(LOG_INFO);
+	tmpdir[0] = '\0';
+      }
+    else
+#endif
+    if (chdir(tmpdir) < 0)
+      {
+	sprintf(ebuf, "Unable to change directory to %s", tmpdir);
+	gdomap_log(LOG_CRIT);
+	exit(EXIT_FAILURE);
+      }
+
+#ifndef __MINGW__
+    if (geteuid() == 0)
+      {
+	if (chroot(tmpdir) < 0)
+	  {
+	    sprintf(ebuf, "Unable to change root to %s", tmpdir);
+	    gdomap_log(LOG_CRIT);
+	    exit(EXIT_FAILURE);
+	  }
+	chdir("/");
+      }
 #endif /* __MINGW__ */
 #endif /* __svr4__ */
 
@@ -4627,33 +4719,28 @@ printf(
    * Try to become a 'safe' user now that we have
    * done everything that needs root priv.
    */
-  if (getuid () != 0)
-    {
-      /*
-       * Try to be the user who launched us ... so they can kill us too.
-       */
-      setuid (getuid ());
-      setgid (getgid ());
-    }
-  else
-    {
-      int	uid = -2;
-      int	gid = -2;
-#ifdef	HAVE_PWD_H
-#ifdef	HAVE_GETPWNAM
-      struct passwd *pw = getpwnam("nobody");
-
-      if (pw != 0)
-	{
-	  uid = pw->pw_uid;
-	  gid = pw->pw_gid;
-	}
-#endif
-#endif
-      setuid (uid);
-      setgid (gid);
-      setgroups (0, 0);	/* Empty additional groups list */
-    }
+    if (getuid () != 0)
+      {
+	/*
+	 * On FreeBSD, setgroups(2) only works correctly for root, therefor
+	 * we clear the group access list before the actual switch and dump
+	 * a warning if it fails
+	 */
+	
+	errno = 0;
+	
+	if( setgroups (0, NULL) < 0 )
+	  {
+	    sprintf(ebuf, "Cannot clear the group access list: %s",
+		    strerror(errno));
+	    gdomap_log(LOG_WARNING);
+	  }
+      }
+    
+    setuid(uid);
+    setgid(gid);
+  }
+  
   if (getuid() == 0)
     {
       sprintf(ebuf, "Still running as root after trying to change");
_______________________________________________
Bug-gnustep mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/bug-gnustep

Reply via email to