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");