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
print(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
main(int argc,char ** argv)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 }
210