From http://www.jwz.org/xscreensaver/xscreensaver-5.27.tar.gz
[xscreensaver] / driver / test-uid.c
1 /* test-uid.c --- playing with setuid.
2  * xscreensaver, Copyright (c) 1998, 2005 Jamie Zawinski <jwz@jwz.org>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <stdlib.h>
18 #ifdef HAVE_UNISTD_H
19 # include <unistd.h>
20 #endif
21
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <pwd.h>
28 #include <grp.h>
29
30 static void
31 print(void)
32 {
33   int uid = getuid();
34   int gid = getgid();
35   int euid = geteuid();
36   int egid = getegid();
37   struct passwd *p = 0;
38   struct group *g = 0;
39   gid_t groups[1024];
40   int n, size;
41
42   p = getpwuid (uid);
43   g = getgrgid (gid);
44   fprintf(stderr, "real user/group: %ld/%ld (%s/%s)\n", (long) uid, (long) gid,
45           (p && p->pw_name ? p->pw_name : "???"),
46           (g && g->gr_name ? g->gr_name : "???"));
47
48   p = getpwuid (euid);
49   g = getgrgid (egid);
50   fprintf(stderr, "eff. user/group: %ld/%ld (%s/%s)\n", (long)euid, (long)egid,
51           (p && p->pw_name ? p->pw_name : "???"),
52           (g && g->gr_name ? g->gr_name : "???"));
53
54   size = sizeof(groups) / sizeof(gid_t);
55   n = getgroups(size - 1, groups);
56   if (n < 0)
57     perror("getgroups failed");
58   else
59     {
60       int i;
61       fprintf (stderr, "eff. group list: [");
62       for (i = 0; i < n; i++)
63         {
64           g = getgrgid (groups[i]);
65           fprintf(stderr, "%s%s=%ld", (i == 0 ? "" : ", "),
66                   (g->gr_name ? g->gr_name : "???"),
67                   (long) groups[i]);
68         }
69       fprintf (stderr, "]\n");
70     }
71 }
72
73 int
74 main (int argc, char **argv)
75 {
76   int i;
77   struct passwd *p = 0;
78   struct group *g = 0;
79
80   if (argc <= 1)
81     {
82       fprintf(stderr,
83               "usage: %s [ user/group ... ]\n"
84               "\tEach argument may be a user name, or user/group.\n"
85               "\tThis program will attempt to setuid/setgid to each\n"
86               "\tin turn, and report the results.  The user and group\n"
87               "\tnames may be strings, or numeric.\n",
88               argv[0]);
89       exit(1);
90     }
91
92   print();
93   for (i = 1; i < argc; i++)
94     {
95       char *user = argv[i];
96       char *group = strchr(user, '/');
97       if (!group)
98         group = strchr(user, '.');
99       if (group)
100         *group++ = 0;
101
102       if (group && *group)
103         {
104           long gid = 0;
105           int was_numeric = 0;
106
107           g = 0;
108           if (*group == '-' || (*group >= '0' && *group <= '9'))
109             if (1 == sscanf(group, "%ld", &gid))
110               {
111                 g = getgrgid (gid);
112                 was_numeric = 1;
113               }
114
115           if (!g)
116             g = getgrnam(group);
117
118           if (g)
119             {
120               gid = g->gr_gid;
121               group = g->gr_name;
122             }
123           else
124             {
125               if (was_numeric)
126                 {
127                   fprintf(stderr, "no group numbered %s.\n", group);
128                   group = "";
129                 }
130               else
131                 {
132                   fprintf(stderr, "no group named %s.\n", group);
133                   goto NOGROUP;
134                 }
135             }
136
137           fprintf(stderr, "setgroups(1, [%ld]) \"%s\"", gid, group);
138           {
139             gid_t g2 = gid;
140             if (setgroups(1, &g2) == 0)
141               fprintf(stderr, " succeeded.\n");
142             else
143               perror(" failed");
144           }
145
146           fprintf(stderr, "setgid(%ld) \"%s\"", gid, group);
147           if (setgid(gid) == 0)
148             fprintf(stderr, " succeeded.\n");
149           else
150             perror(" failed");
151
152         NOGROUP: ;
153         }
154
155       if (user && *user)
156         {
157           long uid = 0;
158           int was_numeric = 0;
159
160           p = 0;
161           if (*user == '-' || (*user >= '0' && *user <= '9'))
162             if (1 == sscanf(user, "%ld", &uid))
163               {
164                 p = getpwuid (uid);
165                 was_numeric = 1;
166               }
167
168           if (!p)
169             p = getpwnam(user);
170
171           if (p)
172             {
173               uid = p->pw_uid;
174               user = p->pw_name;
175             }
176           else
177             {
178               if (was_numeric)
179                 {
180                   fprintf(stderr, "no user numbered \"%s\".\n", user);
181                   user = "";
182                 }
183               else
184                 {
185                   fprintf(stderr, "no user named %s.\n", user);
186                   goto NOUSER;
187                 }
188             }
189
190           fprintf(stderr, "setuid(%ld) \"%s\"", uid, user);
191           if (setuid(uid) == 0)
192             fprintf(stderr, " succeeded.\n");
193           else
194             perror(" failed");
195         NOUSER: ;
196         }
197       print();
198     }
199
200   fprintf(stderr,
201           "running \"whoami\" and \"groups\" in a sub-process reports:\n");
202   fflush(stdout);
203   fflush(stderr);
204   system ("/bin/sh -c 'echo \"`whoami` / `groups`\"'");
205
206   fflush(stdout);
207   fflush(stderr);
208   exit(0);
209 }