]> git.gag.com Git - debian/sudo/blob - set_perms.c
532964ffe3ff7c3ed0c395d7cdca36c3994caa63
[debian/sudo] / set_perms.c
1 /*
2  * Copyright (c) 1994-1996,1998-2006 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * Sponsored in part by the Defense Advanced Research Projects
17  * Agency (DARPA) and Air Force Research Laboratory, Air Force
18  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
19  */
20
21 #include <config.h>
22
23 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <sys/stat.h>
26 #include <stdio.h>
27 #ifdef STDC_HEADERS
28 # include <stdlib.h>
29 # include <stddef.h>
30 #else
31 # ifdef HAVE_STDLIB_H
32 #  include <stdlib.h>
33 # endif
34 #endif /* STDC_HEADERS */
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #else
38 # ifdef HAVE_STRINGS_H
39 #  include <strings.h>
40 # endif
41 #endif /* HAVE_STRING_H */
42 #ifdef HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif /* HAVE_UNISTD_H */
45 #ifdef HAVE_ERR_H
46 # include <err.h>
47 #else
48 # include "emul/err.h"
49 #endif /* HAVE_ERR_H */
50 #include <pwd.h>
51 #include <errno.h>
52 #include <grp.h>
53 #ifdef HAVE_LOGIN_CAP_H
54 # include <login_cap.h>
55 #endif
56
57 #include "sudo.h"
58
59 #ifndef lint
60 __unused static const char rcsid[] = "$Sudo: set_perms.c,v 1.30.2.4 2007/07/06 14:16:22 millert Exp $";
61 #endif /* lint */
62
63 #ifdef __TANDEM
64 # define ROOT_UID       65535
65 #else
66 # define ROOT_UID       0
67 #endif
68
69 /*
70  * Prototypes
71  */
72 static void runas_setup         __P((void));
73
74 #ifdef HAVE_SETRESUID
75 /*
76  * Set real and effective and saved uids and gids based on perm.
77  * We always retain a saved uid of 0 unless we are headed for an exec().
78  * We only flip the effective gid since it only changes for PERM_SUDOERS.
79  * This version of set_perms() works fine with the "stay_setuid" option.
80  */
81 void
82 set_perms(perm)
83     int perm;
84 {
85     switch (perm) {
86         case PERM_ROOT:
87                                 if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID))
88                                     errx(1, "setresuid(ROOT_UID, ROOT_UID, ROOT_UID) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid");
89                                 (void) setresgid(-1, user_gid, -1);
90                                 break;
91
92         case PERM_USER:
93                                 (void) setresgid(-1, user_gid, -1);
94                                 if (setresuid(user_uid, user_uid, ROOT_UID))
95                                     err(1, "setresuid(user_uid, user_uid, ROOT_UID)");
96                                 break;
97                                 
98         case PERM_FULL_USER:
99                                 /* headed for exec() */
100                                 (void) setgid(user_gid);
101                                 if (setresuid(user_uid, user_uid, user_uid))
102                                     err(1, "setresuid(user_uid, user_uid, user_uid)");
103                                 break;
104                                 
105         case PERM_RUNAS:
106                                 (void) setresgid(-1, runas_pw->pw_gid, -1);
107                                 if (setresuid(-1, runas_pw->pw_uid, -1))
108                                     err(1, "unable to change to runas uid");
109                                 break;
110
111         case PERM_FULL_RUNAS:
112                                 /* headed for exec(), assume euid == ROOT_UID */
113                                 runas_setup();
114                                 if (setresuid(def_stay_setuid ?
115                                     user_uid : runas_pw->pw_uid,
116                                     runas_pw->pw_uid, runas_pw->pw_uid))
117                                     err(1, "unable to change to runas uid");
118                                 break;
119
120         case PERM_SUDOERS:
121                                 /* assume euid == ROOT_UID, ruid == user */
122                                 if (setresgid(-1, SUDOERS_GID, -1))
123                                     err(1, "unable to change to sudoers gid");
124
125                                 /*
126                                  * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
127                                  * is group readable we use a non-zero
128                                  * uid in order to avoid NFS lossage.
129                                  * Using uid 1 is a bit bogus but should
130                                  * work on all OS's.
131                                  */
132                                 if (SUDOERS_UID == ROOT_UID) {
133                                     if ((SUDOERS_MODE & 040) && setresuid(ROOT_UID, 1, ROOT_UID))
134                                         err(1, "setresuid(ROOT_UID, 1, ROOT_UID)");
135                                 } else {
136                                     if (setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID))
137                                         err(1, "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)");
138                                 }
139                                 break;
140         case PERM_TIMESTAMP:
141                                 if (setresuid(ROOT_UID, timestamp_uid, ROOT_UID))
142                                     err(1, "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)");
143                                 break;
144     }
145 }
146
147 #else
148 # ifdef HAVE_SETREUID
149
150 /*
151  * Set real and effective uids and gids based on perm.
152  * We always retain a real or effective uid of ROOT_UID unless
153  * we are headed for an exec().
154  * This version of set_perms() works fine with the "stay_setuid" option.
155  */
156 void
157 set_perms(perm)
158     int perm;
159 {
160     switch (perm) {
161         case PERM_ROOT:
162                                 if (setreuid(-1, ROOT_UID))
163                                     errx(1, "setreuid(-1, ROOT_UID) failed, your operating system may have a broken setreuid() function\nTry running configure with --disable-setreuid");
164                                 if (setuid(ROOT_UID))
165                                     err(1, "setuid(ROOT_UID)");
166                                 (void) setregid(-1, user_gid);
167                                 break;
168
169         case PERM_USER:
170                                 (void) setregid(-1, user_gid);
171                                 if (setreuid(ROOT_UID, user_uid))
172                                     err(1, "setreuid(ROOT_UID, user_uid)");
173                                 break;
174                                 
175         case PERM_FULL_USER:
176                                 /* headed for exec() */
177                                 (void) setgid(user_gid);
178                                 if (setreuid(user_uid, user_uid))
179                                     err(1, "setreuid(user_uid, user_uid)");
180                                 break;
181                                 
182         case PERM_RUNAS:
183                                 (void) setregid(-1, runas_pw->pw_gid);
184                                 if (setreuid(-1, runas_pw->pw_uid))
185                                     err(1, "unable to change to runas uid");
186                                 break;
187
188         case PERM_FULL_RUNAS:
189                                 /* headed for exec(), assume euid == ROOT_UID */
190                                 runas_setup();
191                                 if (setreuid(def_stay_setuid ? user_uid :
192                                     runas_pw->pw_uid, runas_pw->pw_uid))
193                                     err(1, "unable to change to runas uid");
194                                 break;
195
196         case PERM_SUDOERS:
197                                 /* assume euid == ROOT_UID, ruid == user */
198                                 if (setregid(-1, SUDOERS_GID))
199                                     err(1, "unable to change to sudoers gid");
200
201                                 /*
202                                  * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
203                                  * is group readable we use a non-zero
204                                  * uid in order to avoid NFS lossage.
205                                  * Using uid 1 is a bit bogus but should
206                                  * work on all OS's.
207                                  */
208                                 if (SUDOERS_UID == ROOT_UID) {
209                                     if ((SUDOERS_MODE & 040) && setreuid(ROOT_UID, 1))
210                                         err(1, "setreuid(ROOT_UID, 1)");
211                                 } else {
212                                     if (setreuid(ROOT_UID, SUDOERS_UID))
213                                         err(1, "setreuid(ROOT_UID, SUDOERS_UID)");
214                                 }
215                                 break;
216         case PERM_TIMESTAMP:
217                                 if (setreuid(ROOT_UID, timestamp_uid))
218                                     err(1, "setreuid(ROOT_UID, timestamp_uid)");
219                                 break;
220     }
221 }
222
223 # else /* !HAVE_SETRESUID && !HAVE_SETREUID */
224 # ifdef HAVE_SETEUID
225
226 /*
227  * Set real and effective uids and gids based on perm.
228  * NOTE: does not support the "stay_setuid" option.
229  */
230 void
231 set_perms(perm)
232     int perm;
233 {
234     /*
235      * Since we only have setuid() and seteuid() and semantics
236      * for these calls differ on various systems, we set
237      * real and effective uids to ROOT_UID initially to be safe.
238      */
239     if (seteuid(ROOT_UID))
240         err(1, "seteuid(ROOT_UID)");
241     if (setuid(ROOT_UID))
242         err(1, "setuid(ROOT_UID)");
243
244     switch (perm) {
245         case PERM_ROOT:
246                                 /* uid set above */
247                                 (void) setegid(user_gid);
248                                 break;
249
250         case PERM_USER:
251                                 (void) setegid(user_gid);
252                                 if (seteuid(user_uid))
253                                     err(1, "seteuid(user_uid)");
254                                 break;
255                                 
256         case PERM_FULL_USER:
257                                 /* headed for exec() */
258                                 (void) setgid(user_gid);
259                                 if (setuid(user_uid))
260                                     err(1, "setuid(user_uid)");
261                                 break;
262                                 
263         case PERM_RUNAS:
264                                 (void) setegid(runas_pw->pw_gid);
265                                 if (seteuid(runas_pw->pw_uid))
266                                     err(1, "unable to change to runas uid");
267                                 break;
268
269         case PERM_FULL_RUNAS:
270                                 /* headed for exec() */
271                                 runas_setup();
272                                 if (setuid(runas_pw->pw_uid))
273                                     err(1, "unable to change to runas uid");
274                                 break;
275
276         case PERM_SUDOERS:
277                                 if (setegid(SUDOERS_GID))
278                                     err(1, "unable to change to sudoers gid");
279
280                                 /*
281                                  * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
282                                  * is group readable we use a non-zero
283                                  * uid in order to avoid NFS lossage.
284                                  * Using uid 1 is a bit bogus but should
285                                  * work on all OS's.
286                                  */
287                                 if (SUDOERS_UID == ROOT_UID) {
288                                     if ((SUDOERS_MODE & 040) && seteuid(1))
289                                         err(1, "seteuid(1)");
290                                 } else {
291                                     if (seteuid(SUDOERS_UID))
292                                         err(1, "seteuid(SUDOERS_UID)");
293                                 }
294                                 break;
295         case PERM_TIMESTAMP:
296                                 if (seteuid(timestamp_uid))
297                                     err(1, "seteuid(timestamp_uid)");
298                                 break;
299     }
300 }
301
302 # else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
303
304 /*
305  * Set uids and gids based on perm via setuid() and setgid().
306  * NOTE: does not support the "stay_setuid" or timestampowner options.
307  *       Also, SUDOERS_UID and SUDOERS_GID are not used.
308  */
309 void
310 set_perms(perm)
311     int perm;
312 {
313
314     switch (perm) {
315         case PERM_ROOT:
316                                 if (setuid(ROOT_UID))
317                                         err(1, "setuid(ROOT_UID)");
318                                 break;
319
320         case PERM_FULL_USER:
321                                 (void) setgid(user_gid);
322                                 if (setuid(user_uid))
323                                     err(1, "setuid(user_uid)");
324                                 break;
325                                 
326         case PERM_FULL_RUNAS:
327                                 runas_setup();
328                                 if (setuid(runas_pw->pw_uid))
329                                     err(1, "unable to change to runas uid");
330                                 break;
331
332         case PERM_USER:
333         case PERM_SUDOERS:
334         case PERM_RUNAS:
335         case PERM_TIMESTAMP:
336                                 /* Unsupported since we can't set euid. */
337                                 break;
338     }
339 }
340 #  endif /* HAVE_SETEUID */
341 # endif /* HAVE_SETREUID */
342 #endif /* HAVE_SETRESUID */
343
344 static void
345 runas_setup()
346 {
347 #ifdef HAVE_LOGIN_CAP_H
348     int flags;
349     extern login_cap_t *lc;
350 #endif
351
352     if (runas_pw->pw_name != NULL) {
353 #ifdef HAVE_PAM
354         pam_prep_user(runas_pw);
355 #endif /* HAVE_PAM */
356
357 #ifdef HAVE_LOGIN_CAP_H
358         if (def_use_loginclass) {
359             /*
360              * We don't have setusercontext() set the user since we
361              * may only want to set the effective uid.  Depending on
362              * sudoers and/or command line arguments we may not want
363              * setusercontext() to call initgroups().
364              */
365             flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
366             if (!def_preserve_groups)
367                 SET(flags, LOGIN_SETGROUP);
368             else if (setgid(runas_pw->pw_gid))
369                 warn("cannot set gid to runas gid");
370             if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) {
371                 if (runas_pw->pw_uid != ROOT_UID)
372                     err(1, "unable to set user context");
373                 else
374                     warn("unable to set user context");
375             }
376         } else
377 #endif /* HAVE_LOGIN_CAP_H */
378         {
379             if (setgid(runas_pw->pw_gid))
380                 warn("cannot set gid to runas gid");
381 #ifdef HAVE_INITGROUPS
382             /*
383              * Initialize group vector unless asked not to.
384              */
385             if (!def_preserve_groups &&
386                 initgroups(*user_runas, runas_pw->pw_gid) < 0)
387                 warn("cannot set group vector");
388 #endif /* HAVE_INITGROUPS */
389         }
390     }
391 }