2 * Copyright (c) 1993-1996,1998-2002 Todd C. Miller <Todd.Miller@courtesan.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
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.
34 * For a brief history of sudo, please see the HISTORY file included
35 * with this distribution.
42 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/socket.h>
47 # include <sys/time.h>
48 # include <sys/resource.h>
58 #endif /* STDC_HEADERS */
60 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
65 # ifdef HAVE_STRINGS_H
68 #endif /* HAVE_STRING_H */
71 #endif /* HAVE_UNISTD_H */
78 #include <netinet/in.h>
80 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
83 # include <hpsecurity.h>
85 # include <sys/security.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"
97 #include "interfaces.h"
101 static const char rcsid[] = "$Sudo: sudo.c,v 1.318 2002/01/15 23:43:59 millert Exp $";
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));
127 char **NewArgv = NULL;
128 struct sudo_user sudo_user;
129 struct passwd *auth_pw;
130 FILE *sudoers_fp = NULL;
131 struct interface *interfaces;
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
140 #endif /* HAVE_LOGIN_CAP_H */
141 #ifdef HAVE_BSD_AUTH_H
143 #endif /* HAVE_BSD_AUTH_H */
144 void (*set_perms) __P((int, int));
148 main(argc, argv, envp)
160 extern int printmatches;
161 extern char **environ;
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
169 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
171 /* Zero out the environment. */
172 environ = zero_env(envp);
177 if (geteuid() != 0) {
178 (void) fprintf(stderr, "Sorry, %s must be setuid root.\n", Argv[0]);
183 * Ignore keyboard-generated signals so the user cannot interrupt
184 * us at some point and avoid the logging.
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);
194 * Setup signal handlers, turn off core dumps, and close open files.
199 /* Parse our arguments. */
200 sudo_mode = parse_args();
202 /* Setup defaults data structures. */
205 /* Load the list of local ip addresses and netmasks. */
209 if (sudo_mode & MODE_SHELL)
214 (void) printf("Sudo version %s\n", version);
228 user_cmnd = "validate";
229 pwflag = I_VERIFYPW_I;
232 case MODE_INVALIDATE:
247 /* Must have a command to run... */
248 if (user_cmnd == NULL && NewArgc == 0)
251 cmnd_status = init_vars(sudo_mode);
253 check_sudoers(); /* check mode/owner on _PATH_SUDOERS */
255 /* Validate the user but don't search for pseudo-commands. */
256 validated = sudoers_lookup(pwflag);
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().
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) {
269 set_perms = set_perms_fallback;
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).
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);
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);
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));
296 if (validated & VALIDATE_ERROR)
297 log_error(0, "parse error in %s near line %d", _PATH_SUDOERS,
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",
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;
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))
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;
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");
328 /* Fill in passwd struct based on user we are authenticating as. */
329 auth_pw = get_authpw();
331 /* Require a password unless the NOPASS tag was set. */
332 if (!(validated & FLAG_NOPASS))
335 /* Build up custom environment that avoids any nasty bits. */
336 new_environ = rebuild_env(sudo_mode, envp);
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);
343 } else if (cmnd_status == NOT_FOUND) {
344 (void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
349 log_auth(validated, 1);
350 if (sudo_mode == MODE_VALIDATE)
352 else if (sudo_mode == MODE_LIST) {
357 /* This *must* have been set if we got a match but... */
358 if (safe_cmnd == NULL) {
360 "internal error, safe_cmnd never got set for %s; %s",
362 "please report this error at http://courtesan.com/sudo/bugs/");
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);
373 /* Override user's umask if configured to do so. */
374 if (def_ival(I_UMASK) != 0777)
375 (void) umask(def_mode(I_UMASK));
377 /* Restore coredumpsize resource limit. */
378 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
379 (void) setrlimit(RLIMIT_CORE, &corelimit);
380 #endif /* RLIMIT_CORE */
382 /* Become specified user or root. */
383 set_perms(PERM_RUNAS, sudo_mode);
385 /* Close the password and group files */
389 /* Install the new environment. */
390 environ = new_environ;
393 if ((sudo_mode & MODE_BACKGROUND) && fork() > 0)
396 EXEC(safe_cmnd, NewArgv); /* run the command */
399 #endif /* PROFILING */
401 * If we got here then the exec() failed...
403 (void) fprintf(stderr, "%s: unable to exec %s: %s\n",
404 Argv[0], safe_cmnd, strerror(errno));
406 } else if ((validated & FLAG_NO_USER) || (validated & FLAG_NO_HOST)) {
407 log_auth(validated, 1);
409 } else if (validated & VALIDATE_NOT_OK) {
410 if (def_flag(I_PATH_INFO)) {
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.
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],
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);
426 /* Just tell the user they are not allowed to run foo. */
427 log_auth(validated, 1);
431 /* should never get here */
432 log_auth(validated, 1);
435 exit(0); /* not reached */
439 * Initialize timezone, set umask, fill in ``sudo_user'' struct and
440 * load the ``interfaces'' array.
446 char *p, thost[MAXHOSTNAMELEN];
447 int nohostname, rval;
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],
457 (void) tzset(); /* set the timezone if applicable */
458 #endif /* HAVE_TZSET */
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");
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.
471 nohostname = gethostname(thost, sizeof(thost));
473 user_host = user_shost = "localhost";
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;
480 if ((p = strchr(user_host, '.'))) {
482 user_shost = estrdup(user_host);
485 user_shost = user_host;
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);
495 user_tty = "unknown";
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.
502 if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) {
503 /* Need to make a fake struct passwd for logging to work. */
505 char pw_name[MAX_UID_T_LEN + 1];
507 pw.pw_uid = getuid();
508 (void) sprintf(pw_name, "%ld", (long) pw.pw_uid);
509 pw.pw_name = pw_name;
512 log_error(0, "uid %ld does not exist in the passwd file!",
515 if (user_shell == NULL || *user_shell == '\0')
516 user_shell = sudo_user.pw->pw_shell;
518 /* It is now safe to use log_error() and set_perms() */
521 * Must defer set_fqdn() until it is safe to call log_error()
523 if (def_flag(I_FQDN))
527 log_error(USE_ERRNO|MSG_ONLY, "can't get hostname");
530 * Get current working directory. Try as user, fall back to root.
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",
538 (void) strcpy(user_cwd, "unknown");
541 set_perms(PERM_ROOT, sudo_mode);
544 * If we were given the '-s' option (run shell) we need to redo
545 * NewArgv and NewArgc.
547 if ((sudo_mode & MODE_SHELL)) {
548 char **dst, **src = NewArgv;
550 NewArgv = (char **) emalloc (sizeof(char *) * (++NewArgc + 1));
551 if (user_shell && *user_shell) {
552 NewArgv[0] = user_shell;
554 (void) fprintf(stderr, "%s: Unable to determine shell.", Argv[0]);
558 /* copy the args from Argv */
559 for (dst = NewArgv + 1; (*dst = *src) != NULL; ++src, ++dst)
563 /* Set login class if applicable. */
564 set_loginclass(sudo_user.pw);
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);
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);
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;
587 for (size = 0, from = NewArgv + 1; *from; from++)
588 size += strlen(*from) + 1;
591 /* alloc and copy. */
592 to = user_args = (char *) emalloc(size);
593 for (from = NewArgv + 1; *from; from++) {
594 (void) strcpy(to, *from);
607 * Command line argument parsing, can't use getopt(3).
612 int rval = MODE_RUN; /* what mode is suod to be run in? */
613 int excl = 0; /* exclusive arg, no others allowed */
618 if (NewArgc == 0) { /* no options and no command */
619 rval |= (MODE_IMPLIED_SHELL | MODE_SHELL);
623 while (NewArgc > 0 && NewArgv[0][0] == '-') {
624 if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0') {
625 (void) fprintf(stderr, "%s: Please use single character options\n",
630 switch (NewArgv[0][1]) {
632 /* Must have an associated prompt. */
633 if (NewArgv[1] == NULL)
636 user_prompt = NewArgv[1];
638 /* Shift Argv over and adjust Argc. */
643 /* Must have an associated runas user. */
644 if (NewArgv[1] == NULL)
647 user_runas = &NewArgv[1];
649 /* Shift Argv over and adjust Argc. */
653 #ifdef HAVE_BSD_AUTH_H
655 /* Must have an associated authentication style. */
656 if (NewArgv[1] == NULL)
659 login_style = NewArgv[1];
661 /* Shift Argv over and adjust Argc. */
666 #ifdef HAVE_LOGIN_CAP_H
668 /* Must have an associated login class. */
669 if (NewArgv[1] == NULL)
672 login_class = NewArgv[1];
673 def_flag(I_USE_LOGINCLASS) = TRUE;
675 /* Shift Argv over and adjust Argc. */
681 rval |= MODE_BACKGROUND;
684 rval = MODE_VALIDATE;
685 if (excl && excl != 'v')
690 rval = MODE_INVALIDATE;
691 if (excl && excl != 'k')
697 if (excl && excl != 'K')
702 rval = MODE_LISTDEFS;
703 if (excl && excl != 'L')
709 if (excl && excl != 'l')
715 if (excl && excl != 'V')
721 if (excl && excl != 'h')
727 if (excl && excl != 's')
732 rval |= MODE_RESET_HOME;
735 rval |= MODE_PRESERVE_GROUPS;
738 tgetpass_flags |= TGP_STDIN;
743 if (rval == MODE_RUN)
744 rval |= (MODE_IMPLIED_SHELL | MODE_SHELL);
747 (void) fprintf(stderr, "%s: '-' requires an argument\n",
751 (void) fprintf(stderr, "%s: Illegal option %s\n", Argv[0],
759 if (NewArgc > 0 && !(rval & MODE_RUN))
766 * Sanity check sudoers mode/owner/type.
767 * Leaves a file pointer to the sudoers file open in ``fp''.
777 * Fix the mode and group on sudoers file from old default.
778 * Only works if filesystem is readable/writable by root.
780 if ((rootstat = lstat(_PATH_SUDOERS, &statbuf)) == 0 &&
781 SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 &&
782 (statbuf.st_mode & 0007777) == 0400) {
784 if (chmod(_PATH_SUDOERS, SUDOERS_MODE) == 0) {
785 (void) fprintf(stderr, "%s: fixed mode on %s\n",
786 Argv[0], _PATH_SUDOERS);
787 statbuf.st_mode |= SUDOERS_MODE;
788 if (statbuf.st_gid != SUDOERS_GID) {
789 if (!chown(_PATH_SUDOERS,(uid_t) -1,SUDOERS_GID)) {
790 (void) fprintf(stderr, "%s: set group on %s\n",
791 Argv[0], _PATH_SUDOERS);
792 statbuf.st_gid = SUDOERS_GID;
794 (void) fprintf(stderr,"%s: Unable to set group on %s: %s\n",
795 Argv[0], _PATH_SUDOERS, strerror(errno));
799 (void) fprintf(stderr, "%s: Unable to fix mode on %s: %s\n",
800 Argv[0], _PATH_SUDOERS, strerror(errno));
805 * Sanity checks on sudoers file. Must be done as sudoers
806 * file owner. We already did a stat as root, so use that
807 * data if we can't stat as sudoers file owner.
809 set_perms(PERM_SUDOERS, 0);
811 if (rootstat != 0 && lstat(_PATH_SUDOERS, &statbuf) != 0)
812 log_error(USE_ERRNO, "can't stat %s", _PATH_SUDOERS);
813 else if (!S_ISREG(statbuf.st_mode))
814 log_error(0, "%s is not a regular file", _PATH_SUDOERS);
815 else if (statbuf.st_size == 0)
816 log_error(0, "%s is zero length", _PATH_SUDOERS);
817 else if ((statbuf.st_mode & 07777) != SUDOERS_MODE)
818 log_error(0, "%s is mode 0%o, should be 0%o", _PATH_SUDOERS,
819 (statbuf.st_mode & 07777), SUDOERS_MODE);
820 else if (statbuf.st_uid != SUDOERS_UID)
821 log_error(0, "%s is owned by uid %ld, should be %d", _PATH_SUDOERS,
822 (long) statbuf.st_uid, SUDOERS_UID);
823 else if (statbuf.st_gid != SUDOERS_GID)
824 log_error(0, "%s is owned by gid %ld, should be %d", _PATH_SUDOERS,
825 (long) statbuf.st_gid, SUDOERS_GID);
827 /* Solaris sometimes returns EAGAIN so try 10 times */
828 for (i = 0; i < 10 ; i++) {
830 if ((sudoers_fp = fopen(_PATH_SUDOERS, "r")) == NULL ||
831 fread(&c, sizeof(c), 1, sudoers_fp) != 1) {
833 if (errno != EAGAIN && errno != EWOULDBLOCK)
839 if (sudoers_fp == NULL)
840 log_error(USE_ERRNO, "can't open %s", _PATH_SUDOERS);
843 set_perms(PERM_ROOT, 0); /* change back to root */
847 * Close all open files (except std*) and turn off core dumps.
848 * Also sets the set_perms() pointer to the correct function.
854 #ifdef HAVE_SETRLIMIT
859 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
861 * Turn off core dumps.
863 (void) getrlimit(RLIMIT_CORE, &corelimit);
864 rl.rlim_cur = rl.rlim_max = 0;
865 (void) setrlimit(RLIMIT_CORE, &rl);
866 #endif /* RLIMIT_CORE */
869 * Close any open fd's other than stdin, stdout and stderr.
872 maxfd = sysconf(_SC_OPEN_MAX) - 1;
874 maxfd = getdtablesize() - 1;
875 #endif /* HAVE_SYSCONF */
877 if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
878 if (rl.rlim_max != RLIM_INFINITY && rl.rlim_max <= maxfd)
879 maxfd = rl.rlim_max - 1;
881 #endif /* RLIMIT_NOFILE */
883 for (fd = maxfd; fd > STDERR_FILENO; fd--)
886 /* Catch children as they die... */
887 sigemptyset(&sa.sa_mask);
888 sa.sa_flags = SA_RESTART;
889 sa.sa_handler = reapchild;
890 (void) sigaction(SIGCHLD, &sa, NULL);
892 /* Set set_perms pointer to the correct function */
893 #if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
894 if (sysconf(_SC_SAVED_IDS) == 1 && sysconf(_SC_VERSION) >= 199009)
895 set_perms = set_perms_posix;
898 set_perms = set_perms_fallback;
901 #ifdef HAVE_LOGIN_CAP_H
909 * Don't make it a fatal error if the user didn't specify the login
910 * class themselves. We do this because if login.conf gets
911 * corrupted we want the admin to be able to use sudo to fix it.
914 errflags = NO_MAIL|MSG_ONLY;
916 errflags = NO_MAIL|MSG_ONLY|NO_EXIT;
918 if (login_class && strcmp(login_class, "-") != 0) {
919 if (strcmp(*user_runas, "root") != 0 && user_uid != 0) {
920 (void) fprintf(stderr, "%s: only root can use -c %s\n",
921 Argv[0], login_class);
925 login_class = pw->pw_class;
926 if (!login_class || !*login_class)
928 (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
931 lc = login_getclass(login_class);
932 if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
933 log_error(errflags, "unknown login class: %s", login_class);
935 lc = login_getclass(NULL); /* needed for login_getstyle() later */
944 #endif /* HAVE_LOGIN_CAP_H */
947 * Look up the fully qualified domain name and set user_host and user_shost.
955 if (!(hp = gethostbyname(user_host))) {
956 log_error(MSG_ONLY|NO_EXIT,
957 "unable to lookup %s via gethostbyname()", user_host);
959 if (user_shost != user_host)
962 user_host = estrdup(hp->h_name);
964 if ((p = strchr(user_host, '.'))) {
966 user_shost = estrdup(user_host);
969 user_shost = user_host;
974 * Get passwd entry for the user we are going to authenticate as.
975 * By default, this is the user invoking sudo...
977 static struct passwd *
982 if (def_ival(I_ROOTPW)) {
983 if ((pw = sudo_getpwuid(0)) == NULL)
984 log_error(0, "uid 0 does not exist in the passwd file!");
985 } else if (def_ival(I_RUNASPW)) {
986 if ((pw = sudo_getpwnam(def_str(I_RUNAS_DEFAULT))) == NULL)
987 log_error(0, "user %s does not exist in the passwd file!",
988 def_str(I_RUNAS_DEFAULT));
989 } else if (def_ival(I_TARGETPW)) {
990 if (**user_runas == '#') {
991 if ((pw = sudo_getpwuid(atoi(*user_runas + 1))) == NULL)
992 log_error(0, "uid %s does not exist in the passwd file!",
995 if ((pw = sudo_getpwnam(*user_runas)) == NULL)
996 log_error(0, "user %s does not exist in the passwd file!",
1006 * Tell which options are mutually exclusive and exit.
1009 usage_excl(exit_val)
1012 (void) fprintf(stderr,
1013 "Only one of the -h, -k, -K, -l, -s, -v or -V options may be used\n");
1018 * Give usage message and exit.
1025 (void) fprintf(stderr, "usage: sudo -V | -h | -L | -l | -v | -k | -K | %s",
1026 "[-H] [-P] [-S] [-b] [-p prompt]\n [-u username/#uid] ");
1027 #ifdef HAVE_LOGIN_CAP_H
1028 (void) fprintf(stderr, "[-c class] ");
1030 #ifdef HAVE_BSD_AUTH_H
1031 (void) fprintf(stderr, "[-a auth_type] ");
1033 (void) fprintf(stderr, "-s | <command>\n");