ftp://ftp.krokus.ru/pub/OpenBSD/distfiles/xscreensaver-4.22.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;
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   n = getgroups(sizeof(groups)-1, groups);
55   if (n < 0)
56     perror("getgroups failed");
57   else
58     {
59       int i;
60       fprintf (stderr, "eff. group list: [");
61       for (i = 0; i < n; i++)
62         {
63           g = getgrgid (groups[i]);
64           fprintf(stderr, "%s%s=%ld", (i == 0 ? "" : ", "),
65                   (g->gr_name ? g->gr_name : "???"),
66                   groups[i]);
67         }
68       fprintf (stderr, "]\n");
69     }
70 }
71
72 int
73 main (int argc, char **argv)
74 {
75   int i;
76   struct passwd *p = 0;
77   struct group *g = 0;
78
79   if (argc <= 1)
80     {
81       fprintf(stderr,
82               "usage: %s [ user/group ... ]\n"
83               "\tEach argument may be a user name, or user/group.\n"
84               "\tThis program will attempt to setuid/setgid to each\n"
85               "\tin turn, and report the results.  The user and group\n"
86               "\tnames may be strings, or numeric.\n",
87               argv[0]);
88       exit(1);
89     }
90
91   print();
92   for (i = 1; i < argc; i++)
93     {
94       char *user = argv[i];
95       char *group = strchr(user, '/');
96       if (!group)
97         group = strchr(user, '.');
98       if (group)
99         *group++ = 0;
100
101       if (group && *group)
102         {
103           long gid = 0;
104           int was_numeric = 0;
105
106           g = 0;
107           if (*group == '-' || (*group >= '0' && *group <= '9'))
108             if (1 == sscanf(group, "%ld", &gid))
109               {
110                 g = getgrgid (gid);
111                 was_numeric = 1;
112               }
113
114           if (!g)
115             g = getgrnam(group);
116
117           if (g)
118             {
119               gid = g->gr_gid;
120               group = g->gr_name;
121             }
122           else
123             {
124               if (was_numeric)
125                 {
126                   fprintf(stderr, "no group numbered %s.\n", group);
127                   group = "";
128                 }
129               else
130                 {
131                   fprintf(stderr, "no group named %s.\n", group);
132                   goto NOGROUP;
133                 }
134             }
135
136           fprintf(stderr, "setgroups(1, [%ld]) \"%s\"", gid, group);
137           {
138             gid_t g2 = gid;
139             if (setgroups(1, &g2) == 0)
140               fprintf(stderr, " succeeded.\n");
141             else
142               perror(" failed");
143           }
144
145           fprintf(stderr, "setgid(%ld) \"%s\"", gid, group);
146           if (setgid(gid) == 0)
147             fprintf(stderr, " succeeded.\n");
148           else
149             perror(" failed");
150
151         NOGROUP: ;
152         }
153
154       if (user && *user)
155         {
156           long uid = 0;
157           int was_numeric = 0;
158
159           p = 0;
160           if (*user == '-' || (*user >= '0' && *user <= '9'))
161             if (1 == sscanf(user, "%ld", &uid))
162               {
163                 p = getpwuid (uid);
164                 was_numeric = 1;
165               }
166
167           if (!p)
168             p = getpwnam(user);
169
170           if (p)
171             {
172               uid = p->pw_uid;
173               user = p->pw_name;
174             }
175           else
176             {
177               if (was_numeric)
178                 {
179                   fprintf(stderr, "no user numbered \"%s\".\n", user);
180                   user = "";
181                 }
182               else
183                 {
184                   fprintf(stderr, "no user named %s.\n", user);
185                   goto NOUSER;
186                 }
187             }
188
189           fprintf(stderr, "setuid(%ld) \"%s\"", uid, user);
190           if (setuid(uid) == 0)
191             fprintf(stderr, " succeeded.\n");
192           else
193             perror(" failed");
194         NOUSER: ;
195         }
196       print();
197     }
198
199   fprintf(stderr,
200           "running \"whoami\" and \"groups\" in a sub-process reports:\n");
201   fflush(stdout);
202   fflush(stderr);
203   system ("/bin/sh -c 'echo \"`whoami` / `groups`\"'");
204
205   fflush(stdout);
206   fflush(stderr);
207   exit(0);
208 }