Imported Debian patch 1.6.6-1.6
[debian/sudo] / sudo.c
1 /*
2  * Copyright (c) 1993-1996,1998-2002 Todd C. Miller <Todd.Miller@courtesan.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * 4. Products derived from this software may not be called "Sudo" nor
20  *    may "Sudo" appear in their names without specific prior written
21  *    permission from the author.
22  *
23  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
26  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * For a brief history of sudo, please see the HISTORY file included
35  * with this distribution.
36  */
37
38 #define _SUDO_SUDO_C
39
40 #include "config.h"
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <sys/param.h>
45 #include <sys/socket.h>
46 #ifdef HAVE_SETRLIMIT
47 # include <sys/time.h>
48 # include <sys/resource.h>
49 #endif
50 #include <stdio.h>
51 #ifdef STDC_HEADERS
52 # include <stdlib.h>
53 # include <stddef.h>
54 #else
55 # ifdef HAVE_STDLIB_H
56 #  include <stdlib.h>
57 # endif
58 #endif /* STDC_HEADERS */
59 #ifdef HAVE_STRING_H
60 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
61 #  include <memory.h>
62 # endif
63 # include <string.h>
64 #else
65 # ifdef HAVE_STRINGS_H
66 #  include <strings.h>
67 # endif
68 #endif /* HAVE_STRING_H */
69 #ifdef HAVE_UNISTD_H
70 # include <unistd.h>
71 #endif /* HAVE_UNISTD_H */
72 #include <pwd.h>
73 #include <errno.h>
74 #include <fcntl.h>
75 #include <signal.h>
76 #include <grp.h>
77 #include <time.h>
78 #include <netinet/in.h>
79 #include <netdb.h>
80 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
81 # ifdef __hpux
82 #  undef MAXINT
83 #  include <hpsecurity.h>
84 # else
85 #  include <sys/security.h>
86 # endif /* __hpux */
87 # include <prot.h>
88 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
89 #ifdef HAVE_LOGIN_CAP_H
90 # include <login_cap.h>
91 # ifndef LOGIN_DEFROOTCLASS
92 #  define LOGIN_DEFROOTCLASS    "daemon"
93 # endif
94 #endif
95
96 #include "sudo.h"
97 #include "interfaces.h"
98 #include "version.h"
99
100 #ifndef lint
101 static const char rcsid[] = "$Sudo: sudo.c,v 1.318 2002/01/15 23:43:59 millert Exp $";
102 #endif /* lint */
103
104 /*
105  * Prototypes
106  */
107 static int init_vars                    __P((int));
108 static int parse_args                   __P((void));
109 static void check_sudoers               __P((void));
110 static void initial_setup               __P((void));
111 static void set_loginclass              __P((struct passwd *));
112 static void usage                       __P((int));
113 static void usage_excl                  __P((int));
114 static struct passwd *get_authpw        __P((void));
115 extern void list_matches                __P((void));
116 extern char **rebuild_env               __P((int, char **));
117 extern char **zero_env                  __P((char **));
118 extern struct passwd *sudo_getpwnam     __P((const char *));
119 extern struct passwd *sudo_getpwuid     __P((uid_t));
120
121 /*
122  * Globals
123  */
124 int Argc;
125 char **Argv;
126 int NewArgc = 0;
127 char **NewArgv = NULL;
128 struct sudo_user sudo_user;
129 struct passwd *auth_pw;
130 FILE *sudoers_fp = NULL;
131 struct interface *interfaces;
132 int num_interfaces;
133 int tgetpass_flags;
134 extern int errorlineno;
135 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
136 static struct rlimit corelimit;
137 #endif /* RLIMIT_CORE */
138 #ifdef HAVE_LOGIN_CAP_H
139 login_cap_t *lc;
140 #endif /* HAVE_LOGIN_CAP_H */
141 #ifdef HAVE_BSD_AUTH_H
142 char *login_style;
143 #endif /* HAVE_BSD_AUTH_H */
144 void (*set_perms) __P((int, int));
145
146
147 int
148 main(argc, argv, envp)
149     int argc;
150     char **argv;
151     char **envp;
152 {
153     int validated;
154     int fd;
155     int cmnd_status;
156     int sudo_mode;
157     int pwflag;
158     char **new_environ;
159     sigaction_t sa;
160     extern int printmatches;
161     extern char **environ;
162
163     /* Must be done as the first thing... */
164 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
165     (void) set_auth_parameters(argc, argv);
166 # ifdef HAVE_INITPRIVS
167     initprivs();
168 # endif
169 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
170
171     /* Zero out the environment. */
172     environ = zero_env(envp);
173
174     Argv = argv;
175     Argc = argc;
176
177     if (geteuid() != 0) {
178         (void) fprintf(stderr, "Sorry, %s must be setuid root.\n", Argv[0]);
179         exit(1);
180     }
181
182     /*
183      * Ignore keyboard-generated signals so the user cannot interrupt
184      * us at some point and avoid the logging.
185      */
186     sigemptyset(&sa.sa_mask);
187     sa.sa_flags = SA_RESTART;
188     sa.sa_handler = SIG_IGN;
189     (void) sigaction(SIGINT, &sa, NULL);
190     (void) sigaction(SIGQUIT, &sa, NULL);
191     (void) sigaction(SIGTSTP, &sa, NULL);
192
193     /*
194      * Setup signal handlers, turn off core dumps, and close open files.
195      */
196     initial_setup();
197     setpwent();
198
199     /* Parse our arguments. */
200     sudo_mode = parse_args();
201
202     /* Setup defaults data structures. */
203     init_defaults();
204
205     /* Load the list of local ip addresses and netmasks.  */
206     load_interfaces();
207
208     pwflag = 0;
209     if (sudo_mode & MODE_SHELL)
210         user_cmnd = "shell";
211     else
212         switch (sudo_mode) {
213             case MODE_VERSION:
214                 (void) printf("Sudo version %s\n", version);
215                 if (getuid() == 0) {
216                     putchar('\n');
217                     dump_auth_methods();
218                     dump_defaults();
219                     dump_interfaces();
220                     dump_badenv();
221                 }
222                 exit(0);
223                 break;
224             case MODE_HELP:
225                 usage(0);
226                 break;
227             case MODE_VALIDATE:
228                 user_cmnd = "validate";
229                 pwflag = I_VERIFYPW_I;
230                 break;
231             case MODE_KILL:
232             case MODE_INVALIDATE:
233                 user_cmnd = "kill";
234                 pwflag = -1;
235                 break;
236             case MODE_LISTDEFS:
237                 list_options();
238                 exit(0);
239                 break;
240             case MODE_LIST:
241                 user_cmnd = "list";
242                 pwflag = I_LISTPW_I;
243                 printmatches = 1;
244                 break;
245         }
246
247     /* Must have a command to run... */
248     if (user_cmnd == NULL && NewArgc == 0)
249         usage(1);
250
251     cmnd_status = init_vars(sudo_mode);
252
253     check_sudoers();    /* check mode/owner on _PATH_SUDOERS */
254
255     /* Validate the user but don't search for pseudo-commands. */
256     validated = sudoers_lookup(pwflag);
257
258     /*
259      * If we have POSIX saved uids and the stay_setuid flag was not set,
260      * set the real, effective and saved uids to 0 and use set_perms_fallback()
261      * instead of set_perms_posix().
262      */
263 #if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
264     if (!def_flag(I_STAY_SETUID) && set_perms == set_perms_posix) {
265         if (setuid(0)) {
266             perror("setuid(0)");
267             exit(1);
268         }
269         set_perms = set_perms_fallback;
270     }
271 #endif
272
273     /*
274      * Look up runas user passwd struct.  If we are given a uid then
275      * there may be no corresponding passwd(5) entry (which is OK).
276      */
277     if (**user_runas == '#') {
278         runas_pw = sudo_getpwuid(atoi(*user_runas + 1));
279         if (runas_pw == NULL) {
280             runas_pw = emalloc(sizeof(struct passwd));
281             (void) memset((VOID *)runas_pw, 0, sizeof(struct passwd));
282             runas_pw->pw_uid = atoi(*user_runas + 1);
283         }
284     } else {
285         runas_pw = sudo_getpwnam(*user_runas);
286         if (runas_pw == NULL)
287             log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %s!", *user_runas);
288     }
289
290     /* This goes after the sudoers parse since we honor sudoers options. */
291     if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) {
292         remove_timestamp((sudo_mode == MODE_KILL));
293         exit(0);
294     }
295
296     if (validated & VALIDATE_ERROR)
297         log_error(0, "parse error in %s near line %d", _PATH_SUDOERS,
298             errorlineno);
299
300     /* Is root even allowed to run sudo? */
301     if (user_uid == 0 && !def_flag(I_ROOT_SUDO)) {
302         (void) fputs("You are already root, you don't need to use sudo.\n",
303             stderr);
304         exit(1);
305     }
306
307     /* If given the -P option, set the "preserve_groups" flag. */
308     if (sudo_mode & MODE_PRESERVE_GROUPS)
309         def_flag(I_PRESERVE_GROUPS) = TRUE;
310
311     /* If no command line args and "set_home" is not set, error out. */
312     if ((sudo_mode & MODE_IMPLIED_SHELL) && !def_flag(I_SHELL_NOARGS))
313         usage(1);
314
315     /* May need to set $HOME to target user if we are running a command. */
316     if ((sudo_mode & MODE_RUN) && (def_flag(I_ALWAYS_SET_HOME) ||
317         ((sudo_mode & MODE_SHELL) && def_flag(I_SET_HOME))))
318         sudo_mode |= MODE_RESET_HOME;
319
320     /* Bail if a tty is required and we don't have one.  */
321     if (def_flag(I_REQUIRETTY)) {
322         if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1)
323             log_error(NO_MAIL, "sorry, you must have a tty to run sudo");
324         else
325             (void) close(fd);
326     }
327
328     /* Fill in passwd struct based on user we are authenticating as.  */
329     auth_pw = get_authpw();
330
331     /* Require a password unless the NOPASS tag was set.  */
332     if (!(validated & FLAG_NOPASS))
333         check_user();
334
335     /* Build up custom environment that avoids any nasty bits. */
336     new_environ = rebuild_env(sudo_mode, envp);
337
338     if (validated & VALIDATE_OK) {
339         /* Finally tell the user if the command did not exist. */
340         if (cmnd_status == NOT_FOUND_DOT) {
341             (void) fprintf(stderr, "%s: ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.\n", Argv[0], user_cmnd, user_cmnd, user_cmnd);
342             exit(1);
343         } else if (cmnd_status == NOT_FOUND) {
344             (void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
345                 user_cmnd);
346             exit(1);
347         }
348
349         log_auth(validated, 1);
350         if (sudo_mode == MODE_VALIDATE)
351             exit(0);
352         else if (sudo_mode == MODE_LIST) {
353             list_matches();
354             exit(0);
355         }
356
357         /* This *must* have been set if we got a match but... */
358         if (safe_cmnd == NULL) {
359             log_error(MSG_ONLY,
360                 "internal error, safe_cmnd never got set for %s; %s",
361                 user_cmnd,
362                 "please report this error at http://courtesan.com/sudo/bugs/");
363         }
364
365         /* Reset signal handlers before we exec. */
366         sigemptyset(&sa.sa_mask);
367         sa.sa_flags = SA_RESTART;
368         sa.sa_handler = SIG_DFL;
369         (void) sigaction(SIGINT, &sa, NULL);
370         (void) sigaction(SIGQUIT, &sa, NULL);
371         (void) sigaction(SIGTSTP, &sa, NULL);
372
373         /* Override user's umask if configured to do so. */
374         if (def_ival(I_UMASK) != 0777)
375             (void) umask(def_mode(I_UMASK));
376
377         /* Restore coredumpsize resource limit. */
378 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
379         (void) setrlimit(RLIMIT_CORE, &corelimit);
380 #endif /* RLIMIT_CORE */
381
382         /* Become specified user or root. */
383         set_perms(PERM_RUNAS, sudo_mode);
384
385         /* Close the password and group files */
386         endpwent();
387         endgrent();
388
389         /* Install the new environment. */
390         environ = new_environ;
391
392 #ifndef PROFILING
393         if ((sudo_mode & MODE_BACKGROUND) && fork() > 0)
394             exit(0);
395         else
396             EXEC(safe_cmnd, NewArgv);   /* run the command */
397 #else
398         exit(0);
399 #endif /* PROFILING */
400         /*
401          * If we got here then the exec() failed...
402          */
403         (void) fprintf(stderr, "%s: unable to exec %s: %s\n",
404             Argv[0], safe_cmnd, strerror(errno));
405         exit(127);
406     } else if ((validated & FLAG_NO_USER) || (validated & FLAG_NO_HOST)) {
407         log_auth(validated, 1);
408         exit(1);
409     } else if (validated & VALIDATE_NOT_OK) {
410         if (def_flag(I_PATH_INFO)) {
411             /*
412              * We'd like to not leak path info at all here, but that can
413              * *really* confuse the users.  To really close the leak we'd
414              * have to say "not allowed to run foo" even when the problem
415              * is just "no foo in path" since the user can trivially set
416              * their path to just contain a single dir.
417              */
418             log_auth(validated,
419                 !(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND));
420             if (cmnd_status == NOT_FOUND)
421                 (void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
422                     user_cmnd);
423             else if (cmnd_status == NOT_FOUND_DOT)
424                 (void) fprintf(stderr, "%s: ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.\n", Argv[0], user_cmnd, user_cmnd, user_cmnd);
425         } else {
426             /* Just tell the user they are not allowed to run foo. */
427             log_auth(validated, 1);
428         }
429         exit(1);
430     } else {
431         /* should never get here */
432         log_auth(validated, 1);
433         exit(1);
434     }
435     exit(0);    /* not reached */
436 }
437
438 /*
439  * Initialize timezone, set umask, fill in ``sudo_user'' struct and
440  * load the ``interfaces'' array.
441  */
442 static int
443 init_vars(sudo_mode)
444     int sudo_mode;
445 {
446     char *p, thost[MAXHOSTNAMELEN];
447     int nohostname, rval;
448
449     /* Sanity check command from user. */
450     if (user_cmnd == NULL && strlen(NewArgv[0]) >= MAXPATHLEN) {
451         (void) fprintf(stderr, "%s: %s: Pathname too long\n", Argv[0],
452             NewArgv[0]);
453         exit(1);
454     }
455
456 #ifdef HAVE_TZSET
457     (void) tzset();             /* set the timezone if applicable */
458 #endif /* HAVE_TZSET */
459
460     /* Default value for cmnd and cwd, overridden later. */
461     if (user_cmnd == NULL)
462         user_cmnd = NewArgv[0];
463     (void) strcpy(user_cwd, "unknown");
464
465     /*
466      * We avoid gethostbyname() if possible since we don't want
467      * sudo to block if DNS or NIS is hosed.
468      * "host" is the (possibly fully-qualified) hostname and
469      * "shost" is the unqualified form of the hostname.
470      */
471     nohostname = gethostname(thost, sizeof(thost));
472     if (nohostname)
473         user_host = user_shost = "localhost";
474     else {
475         user_host = estrdup(thost);
476         if (def_flag(I_FQDN)) {
477             /* Defer call to set_fqdn() until log_error() is safe. */
478             user_shost = user_host;
479         } else {
480             if ((p = strchr(user_host, '.'))) {
481                 *p = '\0';
482                 user_shost = estrdup(user_host);
483                 *p = '.';
484             } else {
485                 user_shost = user_host;
486             }
487         }
488     }
489
490     if ((p = ttyname(STDIN_FILENO)) || (p = ttyname(STDOUT_FILENO))) {
491         if (strncmp(p, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
492             p += sizeof(_PATH_DEV) - 1;
493         user_tty = estrdup(p);
494     } else
495         user_tty = "unknown";
496
497     /*
498      * Get a local copy of the user's struct passwd with the shadow password
499      * if necessary.  It is assumed that euid is 0 at this point so we
500      * can read the shadow passwd file if necessary.
501      */
502     if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) {
503         /* Need to make a fake struct passwd for logging to work. */
504         struct passwd pw;
505         char pw_name[MAX_UID_T_LEN + 1];
506
507         pw.pw_uid = getuid();
508         (void) sprintf(pw_name, "%ld", (long) pw.pw_uid);
509         pw.pw_name = pw_name;
510         sudo_user.pw = &pw;
511
512         log_error(0, "uid %ld does not exist in the passwd file!",
513             (long) pw.pw_uid);
514     }
515     if (user_shell == NULL || *user_shell == '\0')
516         user_shell = sudo_user.pw->pw_shell;
517
518     /* It is now safe to use log_error() and set_perms() */
519
520     /*
521      * Must defer set_fqdn() until it is safe to call log_error()
522      */
523     if (def_flag(I_FQDN))
524         set_fqdn();
525
526     if (nohostname)
527         log_error(USE_ERRNO|MSG_ONLY, "can't get hostname");
528
529     /*
530      * Get current working directory.  Try as user, fall back to root.
531      */
532     set_perms(PERM_USER, sudo_mode);
533     if (!getcwd(user_cwd, sizeof(user_cwd))) {
534         set_perms(PERM_ROOT, sudo_mode);
535         if (!getcwd(user_cwd, sizeof(user_cwd))) {
536             (void) fprintf(stderr, "%s: Can't get working directory!\n",
537                            Argv[0]);
538             (void) strcpy(user_cwd, "unknown");
539         }
540     } else
541         set_perms(PERM_ROOT, sudo_mode);
542
543     /*
544      * If we were given the '-s' option (run shell) we need to redo
545      * NewArgv and NewArgc.
546      */
547     if ((sudo_mode & MODE_SHELL)) {
548         char **dst, **src = NewArgv;
549
550         NewArgv = (char **) emalloc (sizeof(char *) * (++NewArgc + 1));
551         if (user_shell && *user_shell) {
552             NewArgv[0] = user_shell;
553         } else {
554             (void) fprintf(stderr, "%s: Unable to determine shell.", Argv[0]);
555             exit(1);
556         }
557
558         /* copy the args from Argv */
559         for (dst = NewArgv + 1; (*dst = *src) != NULL; ++src, ++dst)
560             ;
561     }
562
563     /* Set login class if applicable. */
564     set_loginclass(sudo_user.pw);
565
566     /* Resolve the path and return. */
567     if ((sudo_mode & MODE_RUN)) {
568         /* XXX - should call this as runas user, not root. */
569         rval = find_path(NewArgv[0], &user_cmnd, user_path);
570         if (rval != FOUND) {
571             /* Failed as root, try as invoking user. */
572             set_perms(PERM_USER, sudo_mode);
573             rval = find_path(NewArgv[0], &user_cmnd, user_path);
574             set_perms(PERM_ROOT, sudo_mode);
575         }
576
577         /* set user_args */
578         if (NewArgc > 1) {
579             char *to, **from;
580             size_t size;
581
582             /* If MODE_SHELL not set then NewArgv is contiguous so just count */
583             if (!(sudo_mode & MODE_SHELL)) {
584                 size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) +
585                         strlen(NewArgv[NewArgc-1]) + 1;
586             } else {
587                 for (size = 0, from = NewArgv + 1; *from; from++)
588                     size += strlen(*from) + 1;
589             }
590
591             /* alloc and copy. */
592             to = user_args = (char *) emalloc(size);
593             for (from = NewArgv + 1; *from; from++) {
594                 (void) strcpy(to, *from);
595                 to += strlen(*from);
596                 *to++ = ' ';
597             }
598             *--to = '\0';
599         }
600     } else
601         rval = FOUND;
602
603     return(rval);
604 }
605
606 /*
607  * Command line argument parsing, can't use getopt(3).
608  */
609 static int
610 parse_args()
611 {
612     int rval = MODE_RUN;                /* what mode is suod to be run in? */
613     int excl = 0;                       /* exclusive arg, no others allowed */
614
615     NewArgv = Argv + 1;
616     NewArgc = Argc - 1;
617
618     if (NewArgc == 0) {                 /* no options and no command */
619         rval |= (MODE_IMPLIED_SHELL | MODE_SHELL);
620         return(rval);
621     }
622
623     def_flag(I_ENV_RESET) = TRUE;
624     while (NewArgc > 0 && NewArgv[0][0] == '-') {
625         if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0') {
626             (void) fprintf(stderr, "%s: Please use single character options\n",
627                 Argv[0]);
628             usage(1);
629         }
630
631         switch (NewArgv[0][1]) {
632             case 'p':
633                 /* Must have an associated prompt. */
634                 if (NewArgv[1] == NULL)
635                     usage(1);
636
637                 user_prompt = NewArgv[1];
638
639                 /* Shift Argv over and adjust Argc. */
640                 NewArgc--;
641                 NewArgv++;
642                 break;
643             case 'u':
644                 /* Must have an associated runas user. */
645                 if (NewArgv[1] == NULL)
646                     usage(1);
647
648                 user_runas = &NewArgv[1];
649
650                 /* Shift Argv over and adjust Argc. */
651                 NewArgc--;
652                 NewArgv++;
653                 break;
654 #ifdef HAVE_BSD_AUTH_H
655             case 'a':
656                 /* Must have an associated authentication style. */
657                 if (NewArgv[1] == NULL)
658                     usage(1);
659
660                 login_style = NewArgv[1];
661
662                 /* Shift Argv over and adjust Argc. */
663                 NewArgc--;
664                 NewArgv++;
665                 break;
666 #endif
667 #ifdef HAVE_LOGIN_CAP_H
668             case 'c':
669                 /* Must have an associated login class. */
670                 if (NewArgv[1] == NULL)
671                     usage(1);
672
673                 login_class = NewArgv[1];
674                 def_flag(I_USE_LOGINCLASS) = TRUE;
675
676                 /* Shift Argv over and adjust Argc. */
677                 NewArgc--;
678                 NewArgv++;
679                 break;
680 #endif
681             case 'b':
682                 rval |= MODE_BACKGROUND;
683                 break;
684             case 'v':
685                 rval = MODE_VALIDATE;
686                 if (excl && excl != 'v')
687                     usage_excl(1);
688                 excl = 'v';
689                 break;
690             case 'k':
691                 rval = MODE_INVALIDATE;
692                 if (excl && excl != 'k')
693                     usage_excl(1);
694                 excl = 'k';
695                 break;
696             case 'K':
697                 rval = MODE_KILL;
698                 if (excl && excl != 'K')
699                     usage_excl(1);
700                 excl = 'K';
701                 break;
702             case 'L':
703                 rval = MODE_LISTDEFS;
704                 if (excl && excl != 'L')
705                     usage_excl(1);
706                 excl = 'L';
707                 break;
708             case 'l':
709                 rval = MODE_LIST;
710                 if (excl && excl != 'l')
711                     usage_excl(1);
712                 excl = 'l';
713                 break;
714             case 'V':
715                 rval = MODE_VERSION;
716                 if (excl && excl != 'V')
717                     usage_excl(1);
718                 excl = 'V';
719                 break;
720             case 'h':
721                 rval = MODE_HELP;
722                 if (excl && excl != 'h')
723                     usage_excl(1);
724                 excl = 'h';
725                 break;
726             case 's':
727                 rval |= MODE_SHELL;
728                 if (excl && excl != 's')
729                     usage_excl(1);
730                 excl = 's';
731                 break;
732             case 'H':
733                 rval |= MODE_RESET_HOME;
734                 break;
735             case 'P':
736                 rval |= MODE_PRESERVE_GROUPS;
737                 break;
738             case 'S':
739                 tgetpass_flags |= TGP_STDIN;
740                 break;
741             case '-':
742                 NewArgc--;
743                 NewArgv++;
744                 if (rval == MODE_RUN)
745                     rval |= (MODE_IMPLIED_SHELL | MODE_SHELL);
746                 return(rval);
747             case '\0':
748                 (void) fprintf(stderr, "%s: '-' requires an argument\n",
749                     Argv[0]);
750                 usage(1);
751             default:
752                 (void) fprintf(stderr, "%s: Illegal option %s\n", Argv[0],
753                     NewArgv[0]);
754                 usage(1);
755         }
756         NewArgc--;
757         NewArgv++;
758     }
759
760     if (NewArgc > 0 && !(rval & MODE_RUN))
761         usage(1);
762
763     return(rval);
764 }
765
766 /*
767  * Sanity check sudoers mode/owner/type.
768  * Leaves a file pointer to the sudoers file open in ``fp''.
769  */
770 static void
771 check_sudoers()
772 {
773     struct stat statbuf;
774     int rootstat, i;
775     char c;
776
777     /*
778      * Fix the mode and group on sudoers file from old default.
779      * Only works if filesystem is readable/writable by root.
780      */
781     if ((rootstat = lstat(_PATH_SUDOERS, &statbuf)) == 0 &&
782         SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 &&
783         (statbuf.st_mode & 0007777) == 0400) {
784
785         if (chmod(_PATH_SUDOERS, SUDOERS_MODE) == 0) {
786             (void) fprintf(stderr, "%s: fixed mode on %s\n",
787                 Argv[0], _PATH_SUDOERS);
788             statbuf.st_mode |= SUDOERS_MODE;
789             if (statbuf.st_gid != SUDOERS_GID) {
790                 if (!chown(_PATH_SUDOERS,(uid_t) -1,SUDOERS_GID)) {
791                     (void) fprintf(stderr, "%s: set group on %s\n",
792                         Argv[0], _PATH_SUDOERS);
793                     statbuf.st_gid = SUDOERS_GID;
794                 } else {
795                     (void) fprintf(stderr,"%s: Unable to set group on %s: %s\n",
796                         Argv[0], _PATH_SUDOERS, strerror(errno));
797                 }
798             }
799         } else {
800             (void) fprintf(stderr, "%s: Unable to fix mode on %s: %s\n",
801                 Argv[0], _PATH_SUDOERS, strerror(errno));
802         }
803     }
804
805     /*
806      * Sanity checks on sudoers file.  Must be done as sudoers
807      * file owner.  We already did a stat as root, so use that
808      * data if we can't stat as sudoers file owner.
809      */
810     set_perms(PERM_SUDOERS, 0);
811
812     if (rootstat != 0 && lstat(_PATH_SUDOERS, &statbuf) != 0)
813         log_error(USE_ERRNO, "can't stat %s", _PATH_SUDOERS);
814     else if (!S_ISREG(statbuf.st_mode))
815         log_error(0, "%s is not a regular file", _PATH_SUDOERS);
816     else if (statbuf.st_size == 0)
817         log_error(0, "%s is zero length", _PATH_SUDOERS);
818     else if ((statbuf.st_mode & 07777) != SUDOERS_MODE)
819         log_error(0, "%s is mode 0%o, should be 0%o", _PATH_SUDOERS,
820             (statbuf.st_mode & 07777), SUDOERS_MODE);
821     else if (statbuf.st_uid != SUDOERS_UID)
822         log_error(0, "%s is owned by uid %ld, should be %d", _PATH_SUDOERS,
823             (long) statbuf.st_uid, SUDOERS_UID);
824     else if (statbuf.st_gid != SUDOERS_GID)
825         log_error(0, "%s is owned by gid %ld, should be %d", _PATH_SUDOERS,
826             (long) statbuf.st_gid, SUDOERS_GID);
827     else {
828         /* Solaris sometimes returns EAGAIN so try 10 times */
829         for (i = 0; i < 10 ; i++) {
830             errno = 0;
831             if ((sudoers_fp = fopen(_PATH_SUDOERS, "r")) == NULL ||
832                 fread(&c, sizeof(c), 1, sudoers_fp) != 1) {
833                 sudoers_fp = NULL;
834                 if (errno != EAGAIN && errno != EWOULDBLOCK)
835                     break;
836             } else
837                 break;
838             sleep(1);
839         }
840         if (sudoers_fp == NULL)
841             log_error(USE_ERRNO, "can't open %s", _PATH_SUDOERS);
842     }
843
844     set_perms(PERM_ROOT, 0);            /* change back to root */
845 }
846
847 /*
848  * Close all open files (except std*) and turn off core dumps.
849  * Also sets the set_perms() pointer to the correct function.
850  */
851 static void
852 initial_setup()
853 {
854     int fd, maxfd;
855 #ifdef HAVE_SETRLIMIT
856     struct rlimit rl;
857 #endif
858     sigaction_t sa;
859
860 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
861     /*
862      * Turn off core dumps.
863      */
864     (void) getrlimit(RLIMIT_CORE, &corelimit);
865     rl.rlim_cur = rl.rlim_max = 0;
866     (void) setrlimit(RLIMIT_CORE, &rl);
867 #endif /* RLIMIT_CORE */
868
869     /*
870      * Close any open fd's other than stdin, stdout and stderr.
871      */
872 #ifdef HAVE_SYSCONF
873     maxfd = sysconf(_SC_OPEN_MAX) - 1;
874 #else
875     maxfd = getdtablesize() - 1;
876 #endif /* HAVE_SYSCONF */
877 #ifdef RLIMIT_NOFILE
878     if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
879         if (rl.rlim_max != RLIM_INFINITY && rl.rlim_max <= maxfd)
880             maxfd = rl.rlim_max - 1;
881     }
882 #endif /* RLIMIT_NOFILE */
883
884     for (fd = maxfd; fd > STDERR_FILENO; fd--)
885         (void) close(fd);
886
887     /* Catch children as they die... */
888     sigemptyset(&sa.sa_mask);
889     sa.sa_flags = SA_RESTART;
890     sa.sa_handler = reapchild;
891     (void) sigaction(SIGCHLD, &sa, NULL);
892
893     /* Set set_perms pointer to the correct function */
894 #if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
895     if (sysconf(_SC_SAVED_IDS) == 1 && sysconf(_SC_VERSION) >= 199009)
896         set_perms = set_perms_posix;
897     else
898 #endif
899         set_perms = set_perms_fallback;
900 }
901
902 #ifdef HAVE_LOGIN_CAP_H
903 static void
904 set_loginclass(pw)
905     struct passwd *pw;
906 {
907     int errflags;
908
909     /*
910      * Don't make it a fatal error if the user didn't specify the login
911      * class themselves.  We do this because if login.conf gets
912      * corrupted we want the admin to be able to use sudo to fix it.
913      */
914     if (login_class)
915         errflags = NO_MAIL|MSG_ONLY;
916     else
917         errflags = NO_MAIL|MSG_ONLY|NO_EXIT;
918
919     if (login_class && strcmp(login_class, "-") != 0) {
920         if (strcmp(*user_runas, "root") != 0 && user_uid != 0) {
921             (void) fprintf(stderr, "%s: only root can use -c %s\n",
922                 Argv[0], login_class);
923             exit(1);
924         }
925     } else {
926         login_class = pw->pw_class;
927         if (!login_class || !*login_class)
928             login_class =
929                 (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
930     }
931
932     lc = login_getclass(login_class);
933     if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
934         log_error(errflags, "unknown login class: %s", login_class);
935         if (!lc)
936             lc = login_getclass(NULL);  /* needed for login_getstyle() later */
937     }
938 }
939 #else
940 static void
941 set_loginclass(pw)
942     struct passwd *pw;
943 {
944 }
945 #endif /* HAVE_LOGIN_CAP_H */
946
947 /*
948  * Look up the fully qualified domain name and set user_host and user_shost.
949  */
950 void
951 set_fqdn()
952 {
953     struct hostent *hp;
954     char *p;
955
956     if (!(hp = gethostbyname(user_host))) {
957         log_error(MSG_ONLY|NO_EXIT,
958             "unable to lookup %s via gethostbyname()", user_host);
959     } else {
960         if (user_shost != user_host)
961             free(user_shost);
962         free(user_host);
963         user_host = estrdup(hp->h_name);
964     }
965     if ((p = strchr(user_host, '.'))) {
966         *p = '\0';
967         user_shost = estrdup(user_host);
968         *p = '.';
969     } else {
970         user_shost = user_host;
971     }
972 }
973
974 /*
975  * Get passwd entry for the user we are going to authenticate as.
976  * By default, this is the user invoking sudo...
977  */
978 static struct passwd *
979 get_authpw()
980 {
981     struct passwd *pw;
982
983     if (def_ival(I_ROOTPW)) {
984         if ((pw = sudo_getpwuid(0)) == NULL)
985             log_error(0, "uid 0 does not exist in the passwd file!");
986     } else if (def_ival(I_RUNASPW)) {
987         if ((pw = sudo_getpwnam(def_str(I_RUNAS_DEFAULT))) == NULL)
988             log_error(0, "user %s does not exist in the passwd file!",
989                 def_str(I_RUNAS_DEFAULT));
990     } else if (def_ival(I_TARGETPW)) {
991         if (**user_runas == '#') {
992             if ((pw = sudo_getpwuid(atoi(*user_runas + 1))) == NULL)
993                 log_error(0, "uid %s does not exist in the passwd file!",
994                     user_runas);
995         } else {
996             if ((pw = sudo_getpwnam(*user_runas)) == NULL)
997                 log_error(0, "user %s does not exist in the passwd file!",
998                     user_runas);
999         }
1000     } else
1001         pw = sudo_user.pw;
1002
1003     return(pw);
1004 }
1005
1006 /*
1007  * Tell which options are mutually exclusive and exit.
1008  */
1009 static void
1010 usage_excl(exit_val)
1011     int exit_val;
1012 {
1013     (void) fprintf(stderr,
1014         "Only one of the -h, -k, -K, -l, -s, -v or -V options may be used\n");
1015     usage(exit_val);
1016 }
1017
1018 /*
1019  * Give usage message and exit.
1020  */
1021 static void
1022 usage(exit_val)
1023     int exit_val;
1024 {
1025
1026     (void) fprintf(stderr, "usage: sudo -V | -h | -L | -l | -v | -k | -K | %s",
1027         "[-H] [-P] [-S] [-b] [-p prompt]\n            [-u username/#uid] ");
1028 #ifdef HAVE_LOGIN_CAP_H
1029     (void) fprintf(stderr, "[-c class] ");
1030 #endif
1031 #ifdef HAVE_BSD_AUTH_H
1032     (void) fprintf(stderr, "[-a auth_type] ");
1033 #endif
1034     (void) fprintf(stderr, "-s | <command>\n");
1035     exit(exit_val);
1036 }