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