/* test-uid.c --- playing with setuid. * xscreensaver, Copyright (c) 1998, 2005 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. No representations are made about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #ifdef HAVE_UNISTD_H # include #endif #include #include #include #include #include #include #include static void print(void) { int uid = getuid(); int gid = getgid(); int euid = geteuid(); int egid = getegid(); struct passwd *p = 0; struct group *g = 0; gid_t groups[1024]; int n, size; p = getpwuid (uid); g = getgrgid (gid); fprintf(stderr, "real user/group: %ld/%ld (%s/%s)\n", (long) uid, (long) gid, (p && p->pw_name ? p->pw_name : "???"), (g && g->gr_name ? g->gr_name : "???")); p = getpwuid (euid); g = getgrgid (egid); fprintf(stderr, "eff. user/group: %ld/%ld (%s/%s)\n", (long)euid, (long)egid, (p && p->pw_name ? p->pw_name : "???"), (g && g->gr_name ? g->gr_name : "???")); size = sizeof(groups) / sizeof(gid_t); n = getgroups(size - 1, groups); if (n < 0) perror("getgroups failed"); else { int i; fprintf (stderr, "eff. group list: ["); for (i = 0; i < n; i++) { g = getgrgid (groups[i]); fprintf(stderr, "%s%s=%ld", (i == 0 ? "" : ", "), (g->gr_name ? g->gr_name : "???"), (long) groups[i]); } fprintf (stderr, "]\n"); } } int main (int argc, char **argv) { int i; struct passwd *p = 0; struct group *g = 0; if (argc <= 1) { fprintf(stderr, "usage: %s [ user/group ... ]\n" "\tEach argument may be a user name, or user/group.\n" "\tThis program will attempt to setuid/setgid to each\n" "\tin turn, and report the results. The user and group\n" "\tnames may be strings, or numeric.\n", argv[0]); exit(1); } print(); for (i = 1; i < argc; i++) { char *user = argv[i]; char *group = strchr(user, '/'); if (!group) group = strchr(user, '.'); if (group) *group++ = 0; if (group && *group) { long gid = 0; int was_numeric = 0; g = 0; if (*group == '-' || (*group >= '0' && *group <= '9')) if (1 == sscanf(group, "%ld", &gid)) { g = getgrgid (gid); was_numeric = 1; } if (!g) g = getgrnam(group); if (g) { gid = g->gr_gid; group = g->gr_name; } else { if (was_numeric) { fprintf(stderr, "no group numbered %s.\n", group); group = ""; } else { fprintf(stderr, "no group named %s.\n", group); goto NOGROUP; } } fprintf(stderr, "setgroups(1, [%ld]) \"%s\"", gid, group); { gid_t g2 = gid; if (setgroups(1, &g2) == 0) fprintf(stderr, " succeeded.\n"); else perror(" failed"); } fprintf(stderr, "setgid(%ld) \"%s\"", gid, group); if (setgid(gid) == 0) fprintf(stderr, " succeeded.\n"); else perror(" failed"); NOGROUP: ; } if (user && *user) { long uid = 0; int was_numeric = 0; p = 0; if (*user == '-' || (*user >= '0' && *user <= '9')) if (1 == sscanf(user, "%ld", &uid)) { p = getpwuid (uid); was_numeric = 1; } if (!p) p = getpwnam(user); if (p) { uid = p->pw_uid; user = p->pw_name; } else { if (was_numeric) { fprintf(stderr, "no user numbered \"%s\".\n", user); user = ""; } else { fprintf(stderr, "no user named %s.\n", user); goto NOUSER; } } fprintf(stderr, "setuid(%ld) \"%s\"", uid, user); if (setuid(uid) == 0) fprintf(stderr, " succeeded.\n"); else perror(" failed"); NOUSER: ; } print(); } fprintf(stderr, "running \"whoami\" and \"groups\" in a sub-process reports:\n"); fflush(stdout); fflush(stderr); system ("/bin/sh -c 'echo \"`whoami` / `groups`\"'"); fflush(stdout); fflush(stderr); exit(0); }