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