[BACK]Return to sudo.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Annotation of src/usr.bin/sudo/sudo.c, Revision 1.5

1.1       millert     1: /*
1.3       millert     2:  * Copyright (c) 1994-1996,1998-2000 Todd C. Miller <Todd.Miller@courtesan.com>
1.1       millert     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 <stdio.h>
                     43: #ifdef STDC_HEADERS
                     44: #include <stdlib.h>
                     45: #endif /* STDC_HEADERS */
                     46: #ifdef HAVE_UNISTD_H
                     47: #include <unistd.h>
                     48: #endif /* HAVE_UNISTD_H */
                     49: #ifdef HAVE_STRING_H
                     50: #include <string.h>
                     51: #endif /* HAVE_STRING_H */
                     52: #ifdef HAVE_STRINGS_H
                     53: #include <strings.h>
                     54: #endif /* HAVE_STRINGS_H */
                     55: #include <pwd.h>
                     56: #include <errno.h>
                     57: #include <fcntl.h>
                     58: #include <signal.h>
                     59: #include <grp.h>
                     60: #include <time.h>
                     61: #include <sys/types.h>
                     62: #include <sys/stat.h>
                     63: #include <sys/param.h>
                     64: #include <netinet/in.h>
                     65: #include <netdb.h>
                     66: #ifdef HAVE_SETRLIMIT
                     67: #include <sys/time.h>
                     68: #include <sys/resource.h>
                     69: #endif
                     70: #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
                     71: # ifdef __hpux
                     72: #  undef MAXINT
                     73: #  include <hpsecurity.h>
                     74: # else
                     75: #  include <sys/security.h>
                     76: # endif /* __hpux */
                     77: # include <prot.h>
                     78: #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
1.4       millert    79: #ifdef HAVE_LOGINCAP
                     80: # include <login_cap.h>
                     81: # ifndef LOGIN_DEFROOTCLASS
                     82: #  define LOGIN_DEFROOTCLASS   "daemon"
                     83: # endif
                     84: #endif
1.1       millert    85:
                     86: #include "sudo.h"
                     87: #include "interfaces.h"
                     88: #include "version.h"
                     89:
                     90: #ifndef STDC_HEADERS
                     91: extern char *getenv    __P((char *));
                     92: #endif /* STDC_HEADERS */
                     93:
                     94: #ifndef lint
1.4       millert    95: static const char rcsid[] = "$Sudo: sudo.c,v 1.278 2000/03/24 20:13:12 millert Exp $";
1.1       millert    96: #endif /* lint */
                     97:
                     98: /*
                     99:  * Local type declarations
                    100:  */
                    101: struct env_table {
                    102:     char *name;
                    103:     int len;
                    104: };
                    105:
                    106: /*
                    107:  * Prototypes
                    108:  */
                    109: static int  parse_args                 __P((void));
                    110: static void usage                      __P((int));
                    111: static void usage_excl                 __P((int));
                    112: static void check_sudoers              __P((void));
                    113: static int init_vars                   __P((int));
1.4       millert   114: static int set_loginclass              __P((struct passwd *));
1.1       millert   115: static void add_env                    __P((int));
                    116: static void clean_env                  __P((char **, struct env_table *));
                    117: static void initial_setup              __P((void));
1.4       millert   118: static void update_epasswd             __P((void));
1.1       millert   119: extern struct passwd *sudo_getpwuid    __P((uid_t));
                    120: extern void list_matches               __P((void));
                    121:
                    122: /*
                    123:  * Globals
                    124:  */
                    125: int Argc;
                    126: char **Argv;
                    127: int NewArgc = 0;
                    128: char **NewArgv = NULL;
                    129: struct sudo_user sudo_user;
                    130: FILE *sudoers_fp = NULL;
                    131: struct interface *interfaces;
                    132: int num_interfaces;
1.4       millert   133: int tgetpass_flags;
1.1       millert   134: extern int errorlineno;
1.4       millert   135: static char *runas_homedir = NULL;     /* XXX */
                    136: #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
                    137: static struct rlimit corelimit;
                    138: #endif /* RLIMIT_CORE */
1.1       millert   139:
                    140: /*
                    141:  * Table of "bad" envariables to remove and len for strncmp()
                    142:  */
                    143: static struct env_table badenv_table[] = {
                    144:     { "IFS=", 4 },
                    145:     { "LOCALDOMAIN=", 12 },
                    146:     { "RES_OPTIONS=", 12 },
                    147:     { "HOSTALIASES=", 12 },
                    148:     { "LD_", 3 },
                    149:     { "_RLD", 4 },
                    150: #ifdef __hpux
                    151:     { "SHLIB_PATH=", 11 },
                    152: #endif /* __hpux */
                    153: #ifdef _AIX
                    154:     { "LIBPATH=", 8 },
                    155: #endif /* _AIX */
                    156: #ifdef HAVE_KERB4
                    157:     { "KRB_CONF", 8 },
                    158: #endif /* HAVE_KERB4 */
                    159: #ifdef HAVE_KERB5
                    160:     { "KRB5_CONFIG", 11 },
                    161: #endif /* HAVE_KERB5 */
                    162:     { "ENV=", 4 },
                    163:     { "BASH_ENV=", 9 },
                    164:     { (char *) NULL, 0 }
                    165: };
                    166:
                    167:
                    168: int
                    169: main(argc, argv)
                    170:     int argc;
                    171:     char **argv;
                    172: {
                    173:     int validated;
                    174:     int fd;
                    175:     int cmnd_status;
                    176:     int sudo_mode;
1.3       millert   177:     int sudoers_flags;
1.1       millert   178: #ifdef POSIX_SIGNALS
                    179:     sigset_t set, oset;
                    180: #else
                    181:     int omask;
                    182: #endif /* POSIX_SIGNALS */
                    183:     extern char **environ;
                    184:     extern int printmatches;
                    185:
                    186:     /* Must be done as the first thing... */
                    187: #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
                    188:     (void) set_auth_parameters(argc, argv);
                    189: # ifdef HAVE_INITPRIVS
                    190:     initprivs();
                    191: # endif
                    192: #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
                    193:
                    194:     Argv = argv;
                    195:     Argc = argc;
                    196:
                    197:     if (geteuid() != 0) {
                    198:        (void) fprintf(stderr, "Sorry, %s must be setuid root.\n", Argv[0]);
                    199:        exit(1);
                    200:     }
                    201:
                    202:     /*
                    203:      * Block signals so the user cannot interrupt us at some point and
                    204:      * avoid the logging.
                    205:      */
                    206: #ifdef POSIX_SIGNALS
                    207:     (void) sigemptyset(&set);
                    208:     (void) sigaddset(&set, SIGINT);
                    209:     (void) sigaddset(&set, SIGQUIT);
                    210:     (void) sigaddset(&set, SIGTSTP);
                    211:     (void) sigprocmask(SIG_BLOCK, &set, &oset);
                    212: #else
                    213:     omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTSTP));
                    214: #endif /* POSIX_SIGNALS */
                    215:
                    216:     /*
                    217:      * Setup signal handlers, turn off core dumps, and close open files.
                    218:      */
                    219:     initial_setup();
                    220:
                    221:     /*
                    222:      * Set the prompt based on $SUDO_PROMPT (can be overridden by `-p')
                    223:      */
                    224:     user_prompt = getenv("SUDO_PROMPT");
                    225:
                    226:     /* Parse our arguments. */
                    227:     sudo_mode = parse_args();
                    228:
                    229:     /* Setup defaults data structures. */
                    230:     init_defaults();
                    231:
1.3       millert   232:     sudoers_flags = 0;
1.1       millert   233:     if (sudo_mode & MODE_SHELL)
                    234:        user_cmnd = "shell";
                    235:     else
                    236:        switch (sudo_mode) {
                    237:            case MODE_VERSION:
                    238:                (void) printf("Sudo version %s\n", version);
                    239:                if (getuid() == 0) {
                    240:                    putchar('\n');
                    241:                    dump_auth_methods();
                    242:                    dump_defaults();
                    243:                }
                    244:                exit(0);
                    245:                break;
                    246:            case MODE_HELP:
                    247:                usage(0);
                    248:                break;
                    249:            case MODE_VALIDATE:
                    250:                user_cmnd = "validate";
1.3       millert   251:                sudoers_flags = def_ival(I_VERIFYPW);
1.1       millert   252:                break;
                    253:            case MODE_KILL:
                    254:            case MODE_INVALIDATE:
                    255:                user_cmnd = "kill";
1.3       millert   256:                sudoers_flags = PWCHECK_NEVER;
1.1       millert   257:                break;
                    258:            case MODE_LISTDEFS:
                    259:                list_options();
                    260:                exit(0);
                    261:                break;
                    262:            case MODE_LIST:
                    263:                user_cmnd = "list";
                    264:                printmatches = 1;
1.3       millert   265:                sudoers_flags = def_ival(I_LISTPW);
1.1       millert   266:                break;
                    267:        }
                    268:
                    269:     /* Must have a command to run... */
                    270:     if (user_cmnd == NULL && NewArgc == 0)
                    271:        usage(1);
                    272:
                    273:     clean_env(environ, badenv_table);
                    274:
                    275:     cmnd_status = init_vars(sudo_mode);
                    276:
                    277:     /* At this point, ruid == euid == 0 */
                    278:
                    279:     check_sudoers();   /* check mode/owner on _PATH_SUDOERS */
                    280:
1.2       millert   281:     add_env(!(sudo_mode & MODE_SHELL));        /* add in SUDO_* envariables */
                    282:
                    283:     /* Validate the user but don't search for pseudo-commands. */
1.3       millert   284:     validated = sudoers_lookup(sudoers_flags);
1.2       millert   285:
                    286:     /* This goes after the sudoers parse since we honor sudoers options. */
1.1       millert   287:     if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) {
                    288:        remove_timestamp((sudo_mode == MODE_KILL));
                    289:        exit(0);
                    290:     }
                    291:
                    292:     if (validated & VALIDATE_ERROR)
                    293:        log_error(0, "parse error in %s near line %d", _PATH_SUDOERS,
                    294:            errorlineno);
                    295:
                    296:     /* Is root even allowed to run sudo? */
                    297:     if (user_uid == 0 && !def_flag(I_ROOT_SUDO)) {
                    298:        (void) fputs("You are already root, you don't need to use sudo.\n",
                    299:            stderr);
                    300:        exit(1);
                    301:     }
                    302:
1.3       millert   303:     /* If no command line args and "set_home" is not set, error out. */
                    304:     if ((sudo_mode & MODE_IMPLIED_SHELL) && !def_flag(I_SHELL_NOARGS))
                    305:        usage(1);
                    306:
1.2       millert   307:     /* May need to set $HOME to target user. */
                    308:     if ((sudo_mode & MODE_SHELL) && def_flag(I_SET_HOME))
                    309:        sudo_mode |= MODE_RESET_HOME;
                    310:
1.1       millert   311:     /* Bail if a tty is required and we don't have one.  */
                    312:     if (def_flag(I_REQUIRETTY)) {
                    313:        if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1)
                    314:            log_error(NO_MAIL, "sorry, you must have a tty to run sudo");
                    315:        else
                    316:            (void) close(fd);
                    317:     }
                    318:
1.4       millert   319:     /* Update encrypted password in user_password if sudoers said to.  */
                    320:     update_epasswd();
                    321:
1.1       millert   322:     /* Require a password unless the NOPASS tag was set.  */
                    323:     if (!(validated & FLAG_NOPASS))
                    324:        check_user();
                    325:
                    326:     if (validated & VALIDATE_OK) {
                    327:        /* Finally tell the user if the command did not exist. */
                    328:        if (cmnd_status == NOT_FOUND_DOT) {
                    329:            (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);
                    330:            exit(1);
                    331:        } else if (cmnd_status == NOT_FOUND) {
                    332:            (void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
                    333:                user_cmnd);
                    334:            exit(1);
                    335:        }
                    336:
                    337:        log_auth(validated, 1);
                    338:        if (sudo_mode == MODE_VALIDATE)
                    339:            exit(0);
                    340:        else if (sudo_mode == MODE_LIST) {
                    341:            list_matches();
                    342:            exit(0);
                    343:        }
                    344:
                    345:        /* This *must* have been set if we got a match but... */
                    346:        if (safe_cmnd == NULL) {
                    347:            log_error(MSG_ONLY,
1.5     ! millert   348:                "internal error, safe_cmnd never got set for %s; %s",
1.1       millert   349:                user_cmnd,
                    350:                "please report this error at http://courtesan.com/sudo/bugs/");
                    351:        }
                    352:
                    353:        if (def_ival(I_LOGFACSTR))
                    354:            closelog();
                    355:
                    356:        /* Reset signal mask before we exec. */
                    357: #ifdef POSIX_SIGNALS
                    358:        (void) sigprocmask(SIG_SETMASK, &oset, NULL);
                    359: #else
                    360:        (void) sigsetmask(omask);
                    361: #endif /* POSIX_SIGNALS */
                    362:
                    363:        /* Override user's umask if configured to do so. */
                    364:        if (def_ival(I_UMASK) != 0777)
                    365:            (void) umask(def_mode(I_UMASK));
                    366:
                    367:        /* Replace the PATH envariable with a secure one. */
                    368:        if (def_str(I_SECURE_PATH) && !user_is_exempt())
                    369:            if (sudo_setenv("PATH", def_str(I_SECURE_PATH))) {
                    370:                (void) fprintf(stderr, "%s: cannot allocate memory!\n",
                    371:                    Argv[0]);
                    372:                exit(1);
                    373:            }
                    374:
1.4       millert   375:        /* Restore coredumpsize resource limit. */
                    376: #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
                    377:        (void) setrlimit(RLIMIT_CORE, &corelimit);
                    378: #endif /* RLIMIT_CORE */
                    379:
                    380:        /* Become specified user or root. */
                    381:        set_perms(PERM_RUNAS, sudo_mode);
1.5     ! millert   382:
        !           383:        /* Set $HOME for `sudo -H'.  Only valid at PERM_RUNAS. */
        !           384:        if ((sudo_mode & MODE_RESET_HOME) && runas_homedir)
        !           385:            (void) sudo_setenv("HOME", runas_homedir);
1.4       millert   386:
1.1       millert   387: #ifndef PROFILING
                    388:        if ((sudo_mode & MODE_BACKGROUND) && fork() > 0)
                    389:            exit(0);
                    390:        else
                    391:            EXEC(safe_cmnd, NewArgv);   /* run the command */
                    392: #else
                    393:        exit(0);
                    394: #endif /* PROFILING */
                    395:        /*
                    396:         * If we got here then the exec() failed...
                    397:         */
                    398:        (void) fprintf(stderr, "%s: unable to exec %s: %s\n",
                    399:            Argv[0], safe_cmnd, strerror(errno));
                    400:        exit(-1);
                    401:     } else if ((validated & FLAG_NO_USER) || (validated & FLAG_NO_HOST)) {
                    402:        log_auth(validated, 1);
                    403:        exit(1);
                    404:     } else if (validated & VALIDATE_NOT_OK) {
                    405:        if (def_flag(I_PATH_INFO)) {
                    406:            /*
                    407:             * We'd like to not leak path info at all here, but that can
                    408:             * *really* confuse the users.  To really close the leak we'd
                    409:             * have to say "not allowed to run foo" even when the problem
                    410:             * is just "no foo in path" since the user can trivially set
                    411:             * their path to just contain a single dir.
                    412:             */
                    413:            log_auth(validated,
                    414:                !(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND));
                    415:            if (cmnd_status == NOT_FOUND)
                    416:                (void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
                    417:                    user_cmnd);
                    418:            else if (cmnd_status == NOT_FOUND_DOT)
                    419:                (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);
                    420:        } else {
                    421:            /* Just tell the user they are not allowed to run foo. */
                    422:            log_auth(validated, 1);
                    423:        }
                    424:        exit(1);
                    425:     } else {
                    426:        /* should never get here */
                    427:        log_auth(validated, 1);
                    428:        exit(1);
                    429:     }
                    430:     exit(0);   /* not reached */
                    431: }
                    432:
                    433: /*
                    434:  * Initialize timezone, set umask, fill in ``sudo_user'' struct and
                    435:  * load the ``interfaces'' array.
                    436:  */
                    437: static int
                    438: init_vars(sudo_mode)
                    439:     int sudo_mode;
                    440: {
                    441:     char *p, thost[MAXHOSTNAMELEN];
                    442:
                    443:     /* Sanity check command from user. */
                    444:     if (user_cmnd == NULL && strlen(NewArgv[0]) >= MAXPATHLEN) {
                    445:        (void) fprintf(stderr, "%s: %s: Pathname too long\n", Argv[0],
                    446:            NewArgv[0]);
                    447:        exit(1);
                    448:     }
                    449:
                    450: #ifdef HAVE_TZSET
                    451:     (void) tzset();            /* set the timezone if applicable */
                    452: #endif /* HAVE_TZSET */
                    453:
                    454:     /* Default value for cmnd and cwd, overridden later. */
                    455:     if (user_cmnd == NULL)
                    456:        user_cmnd = NewArgv[0];
                    457:     (void) strcpy(user_cwd, "unknown");
                    458:
                    459:     /*
                    460:      * We avoid gethostbyname() if possible since we don't want
                    461:      * sudo to block if DNS or NIS is hosed.
                    462:      * "host" is the (possibly fully-qualified) hostname and
                    463:      * "shost" is the unqualified form of the hostname.
                    464:      */
                    465:     if ((gethostname(thost, sizeof(thost)))) {
                    466:        user_host = "localhost";
                    467:        log_error(USE_ERRNO|MSG_ONLY, "can't get hostname");
                    468:     } else
                    469:        user_host = estrdup(thost);
1.2       millert   470:     if (def_flag(I_FQDN))
                    471:        set_fqdn();
                    472:     else {
                    473:        if ((p = strchr(user_host, '.'))) {
                    474:            *p = '\0';
                    475:            user_shost = estrdup(user_host);
                    476:            *p = '.';
1.1       millert   477:        } else {
1.2       millert   478:            user_shost = user_host;
1.1       millert   479:        }
                    480:     }
                    481:
                    482:     if ((p = ttyname(STDIN_FILENO)) || (p = ttyname(STDOUT_FILENO))) {
                    483:        if (strncmp(p, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
                    484:            p += sizeof(_PATH_DEV) - 1;
                    485:        user_tty = estrdup(p);
                    486:     } else
                    487:        user_tty = "unknown";
                    488:
                    489:     /*
                    490:      * Get a local copy of the user's struct passwd with the shadow password
                    491:      * if necessary.  It is assumed that euid is 0 at this point so we
                    492:      * can read the shadow passwd file if necessary.
                    493:      */
                    494:     if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) {
                    495:        /* Need to make a fake struct passwd for logging to work. */
                    496:        struct passwd pw;
                    497:        char pw_name[MAX_UID_T_LEN + 1];
                    498:
                    499:        pw.pw_uid = getuid();
                    500:        (void) sprintf(pw_name, "%ld", (long) pw.pw_uid);
                    501:        pw.pw_name = pw_name;
                    502:        sudo_user.pw = &pw;
                    503:
                    504:        log_error(0, "uid %ld does not exist in the passwd file!",
                    505:            (long) pw.pw_uid);
                    506:     }
                    507:
                    508:     /* It is now safe to use log_error() and set_perms() */
                    509:
                    510:     /*
                    511:      * Get current working directory.  Try as user, fall back to root.
                    512:      */
                    513:     set_perms(PERM_USER, sudo_mode);
                    514:     if (!getcwd(user_cwd, sizeof(user_cwd))) {
                    515:        set_perms(PERM_ROOT, sudo_mode);
                    516:        if (!getcwd(user_cwd, sizeof(user_cwd))) {
                    517:            (void) fprintf(stderr, "%s: Can't get working directory!\n",
                    518:                           Argv[0]);
                    519:            (void) strcpy(user_cwd, "unknown");
                    520:        }
                    521:     } else
                    522:        set_perms(PERM_ROOT, sudo_mode);
                    523:
                    524:     /*
                    525:      * Load the list of local ip addresses and netmasks into
                    526:      * the interfaces array.
                    527:      */
                    528:     load_interfaces();
                    529:
                    530:     /*
                    531:      * If we were given the '-s' option (run shell) we need to redo
                    532:      * NewArgv and NewArgc.
                    533:      */
                    534:     if ((sudo_mode & MODE_SHELL)) {
                    535:        char **dst, **src = NewArgv;
                    536:
                    537:        NewArgv = (char **) emalloc (sizeof(char *) * (++NewArgc + 1));
                    538:        if (user_shell && *user_shell) {
                    539:            NewArgv[0] = user_shell;
                    540:        } else {
                    541:            (void) fprintf(stderr, "%s: Unable to determine shell.", Argv[0]);
                    542:            exit(1);
                    543:        }
                    544:
                    545:        /* copy the args from Argv */
                    546:        for (dst = NewArgv + 1; (*dst = *src) != NULL; ++src, ++dst)
                    547:            ;
                    548:     }
                    549:
                    550:     /* Resolve the path and return. */
                    551:     if ((sudo_mode & MODE_RUN))
                    552:        return(find_path(NewArgv[0], &user_cmnd));
                    553:     else
                    554:        return(FOUND);
                    555: }
                    556:
                    557: /*
                    558:  * Command line argument parsing, can't use getopt(3).
                    559:  */
                    560: static int
                    561: parse_args()
                    562: {
                    563:     int rval = MODE_RUN;               /* what mode is suod to be run in? */
                    564:     int excl = 0;                      /* exclusive arg, no others allowed */
                    565:
                    566:     NewArgv = Argv + 1;
                    567:     NewArgc = Argc - 1;
                    568:
1.2       millert   569:     if (NewArgc == 0) {                        /* no options and no command */
1.3       millert   570:        rval |= (MODE_IMPLIED_SHELL | MODE_SHELL);
1.1       millert   571:        return(rval);
                    572:     }
                    573:
                    574:     while (NewArgc > 0 && NewArgv[0][0] == '-') {
                    575:        if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0') {
                    576:            (void) fprintf(stderr, "%s: Please use single character options\n",
                    577:                Argv[0]);
                    578:            usage(1);
                    579:        }
                    580:
                    581:        switch (NewArgv[0][1]) {
                    582:            case 'p':
                    583:                /* Must have an associated prompt. */
                    584:                if (NewArgv[1] == NULL)
                    585:                    usage(1);
                    586:
                    587:                user_prompt = NewArgv[1];
                    588:
                    589:                /* Shift Argv over and adjust Argc. */
                    590:                NewArgc--;
                    591:                NewArgv++;
                    592:                break;
                    593:            case 'u':
                    594:                /* Must have an associated runas user. */
                    595:                if (NewArgv[1] == NULL)
                    596:                    usage(1);
                    597:
                    598:                user_runas = &NewArgv[1];
                    599:
                    600:                /* Shift Argv over and adjust Argc. */
                    601:                NewArgc--;
                    602:                NewArgv++;
                    603:                break;
1.4       millert   604: #ifdef HAVE_LOGINCAP
                    605:            case 'c':
                    606:                /* Must have an associated login class. */
                    607:                if (NewArgv[1] == NULL)
                    608:                    usage(1);
                    609:
                    610:                login_class = NewArgv[1];
                    611:                def_flag(I_LOGINCLASS) = TRUE;
                    612:
                    613:                /* Shift Argv over and adjust Argc. */
                    614:                NewArgc--;
                    615:                NewArgv++;
                    616:                break;
                    617: #endif
1.1       millert   618:            case 'b':
                    619:                rval |= MODE_BACKGROUND;
                    620:                break;
                    621:            case 'v':
                    622:                rval = MODE_VALIDATE;
                    623:                if (excl && excl != 'v')
                    624:                    usage_excl(1);
                    625:                excl = 'v';
                    626:                break;
                    627:            case 'k':
                    628:                rval = MODE_INVALIDATE;
                    629:                if (excl && excl != 'k')
                    630:                    usage_excl(1);
                    631:                excl = 'k';
                    632:                break;
                    633:            case 'K':
                    634:                rval = MODE_KILL;
                    635:                if (excl && excl != 'K')
                    636:                    usage_excl(1);
                    637:                excl = 'K';
                    638:                break;
                    639:            case 'L':
                    640:                rval = MODE_LISTDEFS;
                    641:                if (excl && excl != 'L')
                    642:                    usage_excl(1);
                    643:                excl = 'L';
                    644:                break;
                    645:            case 'l':
                    646:                rval = MODE_LIST;
                    647:                if (excl && excl != 'l')
                    648:                    usage_excl(1);
                    649:                excl = 'l';
                    650:                break;
                    651:            case 'V':
                    652:                rval = MODE_VERSION;
                    653:                if (excl && excl != 'V')
                    654:                    usage_excl(1);
                    655:                excl = 'V';
                    656:                break;
                    657:            case 'h':
                    658:                rval = MODE_HELP;
                    659:                if (excl && excl != 'h')
                    660:                    usage_excl(1);
                    661:                excl = 'h';
                    662:                break;
                    663:            case 's':
                    664:                rval |= MODE_SHELL;
1.2       millert   665:                if (excl && excl != 's')
                    666:                    usage_excl(1);
                    667:                excl = 's';
1.1       millert   668:                break;
                    669:            case 'H':
                    670:                rval |= MODE_RESET_HOME;
                    671:                break;
1.4       millert   672:            case 'S':
                    673:                tgetpass_flags |= TGP_STDIN;
                    674:                break;
1.1       millert   675:            case '-':
                    676:                NewArgc--;
                    677:                NewArgv++;
1.2       millert   678:                if (rval == MODE_RUN)
1.3       millert   679:                    rval |= (MODE_IMPLIED_SHELL | MODE_SHELL);
1.1       millert   680:                return(rval);
                    681:            case '\0':
                    682:                (void) fprintf(stderr, "%s: '-' requires an argument\n",
                    683:                    Argv[0]);
                    684:                usage(1);
                    685:            default:
                    686:                (void) fprintf(stderr, "%s: Illegal option %s\n", Argv[0],
                    687:                    NewArgv[0]);
                    688:                usage(1);
                    689:        }
                    690:        NewArgc--;
                    691:        NewArgv++;
                    692:     }
                    693:
                    694:     if (NewArgc > 0 && !(rval & MODE_RUN))
                    695:        usage(1);
                    696:
                    697:     return(rval);
                    698: }
                    699:
                    700: /*
                    701:  * Add sudo-specific variables into the environment.
                    702:  * Sets ``cmnd_args'' as a side effect.
                    703:  */
                    704: static void
                    705: add_env(contiguous)
                    706:     int contiguous;
                    707: {
                    708:     char idstr[MAX_UID_T_LEN + 1];
                    709:     size_t size;
                    710:     char *buf;
                    711:
                    712:     /* Add the SUDO_COMMAND envariable (cmnd + args). */
                    713:     size = strlen(user_cmnd) + 1;
                    714:     if (NewArgc > 1) {
                    715:        char *to, **from;
                    716:
                    717:        if (contiguous) {
                    718:            size += (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) +
                    719:                    strlen(NewArgv[NewArgc-1]) + 1;
                    720:        } else {
                    721:            for (from = &NewArgv[1]; *from; from++)
                    722:                size += strlen(*from) + 1;
                    723:        }
                    724:
                    725:        buf = (char *) emalloc(size);
                    726:
                    727:        /*
                    728:         * Copy the command and it's arguments info buf.
                    729:         */
                    730:        (void) strcpy(buf, user_cmnd);
                    731:        to = buf + strlen(user_cmnd);
                    732:        for (from = &NewArgv[1]; *from; from++) {
                    733:            *to++ = ' ';
                    734:            (void) strcpy(to, *from);
                    735:            to += strlen(*from);
                    736:        }
                    737:     } else {
                    738:        buf = user_cmnd;
                    739:     }
                    740:     if (sudo_setenv("SUDO_COMMAND", buf)) {
                    741:        (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
                    742:        exit(1);
                    743:     }
                    744:     if (NewArgc > 1)
                    745:        free(buf);
                    746:
                    747:     /* Grab a pointer to the flat arg string from the environment. */
                    748:     if (NewArgc > 1 && (user_args = getenv("SUDO_COMMAND"))) {
                    749:        if ((user_args = strchr(user_args, ' ')))
                    750:            user_args++;
                    751:        else
                    752:            user_args = NULL;
                    753:     }
                    754:
                    755:     /* Add the SUDO_USER environment variable. */
                    756:     if (sudo_setenv("SUDO_USER", user_name)) {
                    757:        (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
                    758:        exit(1);
                    759:     }
                    760:
                    761:     /* Add the SUDO_UID environment variable. */
                    762:     (void) sprintf(idstr, "%ld", (long) user_uid);
                    763:     if (sudo_setenv("SUDO_UID", idstr)) {
                    764:        (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
                    765:        exit(1);
                    766:     }
                    767:
                    768:     /* Add the SUDO_GID environment variable. */
                    769:     (void) sprintf(idstr, "%ld", (long) user_gid);
                    770:     if (sudo_setenv("SUDO_GID", idstr)) {
                    771:        (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
                    772:        exit(1);
                    773:     }
                    774:
                    775:     /* Set PS1 if SUDO_PS1 is set. */
                    776:     if ((buf = getenv("SUDO_PS1")))
                    777:        if (sudo_setenv("PS1", buf)) {
                    778:            (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
                    779:            exit(1);
                    780:        }
                    781: }
                    782:
                    783: /*
                    784:  * Sanity check sudoers mode/owner/type.
                    785:  * Leaves a file pointer to the sudoers file open in ``fp''.
                    786:  */
                    787: static void
                    788: check_sudoers()
                    789: {
                    790:     struct stat statbuf;
                    791:     int rootstat, i;
                    792:     char c;
                    793:
                    794:     /*
                    795:      * Fix the mode and group on sudoers file from old default.
                    796:      * Only works if filesystem is readable/writable by root.
                    797:      */
                    798:     if ((rootstat = lstat(_PATH_SUDOERS, &statbuf)) == 0 &&
                    799:        SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 &&
                    800:        (statbuf.st_mode & 0007777) == 0400) {
                    801:
                    802:        if (chmod(_PATH_SUDOERS, SUDOERS_MODE) == 0) {
                    803:            (void) fprintf(stderr, "%s: fixed mode on %s\n",
                    804:                Argv[0], _PATH_SUDOERS);
1.3       millert   805:            statbuf.st_mode |= SUDOERS_MODE;
1.1       millert   806:            if (statbuf.st_gid != SUDOERS_GID) {
                    807:                if (!chown(_PATH_SUDOERS,(uid_t) -1,SUDOERS_GID)) {
                    808:                    (void) fprintf(stderr, "%s: set group on %s\n",
                    809:                        Argv[0], _PATH_SUDOERS);
                    810:                    statbuf.st_gid = SUDOERS_GID;
                    811:                } else {
                    812:                    (void) fprintf(stderr,"%s: Unable to set group on %s: %s\n",
                    813:                        Argv[0], _PATH_SUDOERS, strerror(errno));
                    814:                }
                    815:            }
                    816:        } else {
                    817:            (void) fprintf(stderr, "%s: Unable to fix mode on %s: %s\n",
                    818:                Argv[0], _PATH_SUDOERS, strerror(errno));
                    819:        }
                    820:     }
                    821:
                    822:     /*
                    823:      * Sanity checks on sudoers file.  Must be done as sudoers
                    824:      * file owner.  We already did a stat as root, so use that
                    825:      * data if we can't stat as sudoers file owner.
                    826:      */
                    827:     set_perms(PERM_SUDOERS, 0);
                    828:
                    829:     if (rootstat != 0 && lstat(_PATH_SUDOERS, &statbuf) != 0)
                    830:        log_error(USE_ERRNO, "can't stat %s", _PATH_SUDOERS);
                    831:     else if (!S_ISREG(statbuf.st_mode))
                    832:        log_error(0, "%s is not a regular file", _PATH_SUDOERS);
                    833:     else if ((statbuf.st_mode & 07777) != SUDOERS_MODE)
                    834:        log_error(0, "%s is mode 0%o, should be 0%o", _PATH_SUDOERS,
                    835:            (statbuf.st_mode & 07777), SUDOERS_MODE);
                    836:     else if (statbuf.st_uid != SUDOERS_UID)
                    837:        log_error(0, "%s is owned by uid %ld, should be %d", _PATH_SUDOERS,
                    838:            (long) statbuf.st_uid, SUDOERS_UID);
                    839:     else if (statbuf.st_gid != SUDOERS_GID)
                    840:        log_error(0, "%s is owned by gid %ld, should be %d", _PATH_SUDOERS,
                    841:            (long) statbuf.st_gid, SUDOERS_GID);
                    842:     else {
                    843:        /* Solaris sometimes returns EAGAIN so try 10 times */
                    844:        for (i = 0; i < 10 ; i++) {
                    845:            errno = 0;
                    846:            if ((sudoers_fp = fopen(_PATH_SUDOERS, "r")) == NULL ||
                    847:                fread(&c, sizeof(c), 1, sudoers_fp) != 1) {
                    848:                sudoers_fp = NULL;
                    849:                if (errno != EAGAIN && errno != EWOULDBLOCK)
                    850:                    break;
                    851:            } else
                    852:                break;
                    853:            sleep(1);
                    854:        }
                    855:        if (sudoers_fp == NULL)
                    856:            log_error(USE_ERRNO, "can't open %s", _PATH_SUDOERS);
                    857:     }
                    858:
                    859:     set_perms(PERM_ROOT, 0);           /* change back to root */
                    860: }
                    861:
                    862: /*
                    863:  * Remove environment variables that match the entries in badenv_table.
                    864:  */
                    865: static void
                    866: clean_env(envp, badenv_table)
                    867:     char **envp;
                    868:     struct env_table *badenv_table;
                    869: {
                    870:     struct env_table *bad;
                    871:     char **cur;
                    872:
                    873:     /*
                    874:      * Remove any envars that match entries in badenv_table.
                    875:      */
                    876:     for (cur = envp; *cur; cur++) {
                    877:        for (bad = badenv_table; bad->name; bad++) {
                    878:            if (strncmp(*cur, bad->name, bad->len) == 0) {
                    879:                /* Got a match so remove it. */
                    880:                char **move;
                    881:
                    882:                for (move = cur; *move; move++)
                    883:                    *move = *(move + 1);
                    884:
                    885:                cur--;
                    886:
                    887:                break;
                    888:            }
                    889:        }
                    890:     }
                    891: }
                    892:
                    893: /*
                    894:  * Set real and effective uids and gids based on perm.
                    895:  */
                    896: void
                    897: set_perms(perm, sudo_mode)
                    898:     int perm;
                    899:     int sudo_mode;
                    900: {
                    901:     struct passwd *pw;
                    902:
                    903:     /*
                    904:      * First, set real & effective uids to root.
                    905:      * If perm is PERM_ROOT then we don't need to do anything else.
                    906:      */
                    907:     if (setuid(0)) {
                    908:        perror("setuid(0)");
                    909:        exit(1);
                    910:     }
                    911:
                    912:     switch (perm) {
                    913:        case PERM_USER:
                    914:                                (void) setgid(user_gid);
                    915:
                    916:                                if (seteuid(user_uid)) {
                    917:                                    perror("seteuid(user_uid)");
                    918:                                    exit(1);
                    919:                                }
                    920:                                break;
                    921:
                    922:        case PERM_FULL_USER:
                    923:                                (void) setgid(user_gid);
                    924:
                    925:                                if (setuid(user_uid)) {
                    926:                                    perror("setuid(user_uid)");
                    927:                                    exit(1);
                    928:                                }
                    929:                                break;
                    930:
                    931:        case PERM_RUNAS:
                    932:                                /* XXX - add group/gid support */
                    933:                                if (**user_runas == '#') {
                    934:                                    if (setuid(atoi(*user_runas + 1))) {
                    935:                                        (void) fprintf(stderr,
                    936:                                            "%s: cannot set uid to %s: %s\n",
                    937:                                            Argv[0], *user_runas, strerror(errno));
                    938:                                        exit(1);
                    939:                                    }
                    940:                                } else {
                    941:                                    if (!(pw = getpwnam(*user_runas))) {
                    942:                                        (void) fprintf(stderr,
                    943:                                            "%s: no passwd entry for %s!\n",
                    944:                                            Argv[0], *user_runas);
                    945:                                        exit(1);
                    946:                                    }
                    947:
                    948:                                    /* Set $USER and $LOGNAME to target user */
1.4       millert   949:                                    if (def_flag(I_LOGNAME)) {
                    950:                                        if (sudo_setenv("USER", pw->pw_name)) {
                    951:                                            (void) fprintf(stderr,
                    952:                                                "%s: cannot allocate memory!\n",
                    953:                                                Argv[0]);
                    954:                                            exit(1);
                    955:                                        }
                    956:                                        if (sudo_setenv("LOGNAME", pw->pw_name)) {
                    957:                                            (void) fprintf(stderr,
                    958:                                                "%s: cannot allocate memory!\n",
                    959:                                                Argv[0]);
                    960:                                            exit(1);
                    961:                                        }
1.1       millert   962:                                    }
1.4       millert   963:
                    964:                                    if (def_flag(I_LOGINCLASS)) {
                    965:                                        /*
                    966:                                         * setusercontext() will set uid/gid/etc
                    967:                                         * for us so no need to do it below.
                    968:                                         */
                    969:                                        if (set_loginclass(pw) > 0)
                    970:                                            break;
1.1       millert   971:                                    }
                    972:
                    973:                                    if (setgid(pw->pw_gid)) {
                    974:                                        (void) fprintf(stderr,
                    975:                                            "%s: cannot set gid to %ld: %s\n",
                    976:                                            Argv[0], (long) pw->pw_gid,
                    977:                                            strerror(errno));
                    978:                                        exit(1);
                    979:                                    }
1.2       millert   980: #ifdef HAVE_INITGROUPS
1.1       millert   981:                                    /*
                    982:                                     * Initialize group vector only if are
                    983:                                     * going to run as a non-root user.
                    984:                                     */
                    985:                                    if (strcmp(*user_runas, "root") != 0 &&
                    986:                                        initgroups(*user_runas, pw->pw_gid)
                    987:                                        == -1) {
                    988:                                        (void) fprintf(stderr,
                    989:                                            "%s: cannot set group vector: %s\n",
                    990:                                            Argv[0], strerror(errno));
                    991:                                        exit(1);
                    992:                                    }
1.2       millert   993: #endif /* HAVE_INITGROUPS */
1.1       millert   994:                                    if (setuid(pw->pw_uid)) {
                    995:                                        (void) fprintf(stderr,
                    996:                                            "%s: cannot set uid to %ld: %s\n",
                    997:                                            Argv[0], (long) pw->pw_uid,
                    998:                                            strerror(errno));
                    999:                                        exit(1);
                   1000:                                    }
                   1001:                                    if (sudo_mode & MODE_RESET_HOME)
                   1002:                                        runas_homedir = pw->pw_dir;
                   1003:                                }
                   1004:                                break;
                   1005:
                   1006:        case PERM_SUDOERS:
                   1007:                                if (setgid(SUDOERS_GID)) {
                   1008:                                    perror("setgid(SUDOERS_GID)");
                   1009:                                    exit(1);
                   1010:                                }
                   1011:
                   1012:                                /*
                   1013:                                 * If SUDOERS_UID == 0 and SUDOERS_MODE
                   1014:                                 * is group readable we use a non-zero
                   1015:                                 * uid in order to avoid NFS lossage.
                   1016:                                 * Using uid 1 is a bit bogus but should
                   1017:                                 * work on all OS's.
                   1018:                                 */
                   1019:                                if (SUDOERS_UID == 0) {
                   1020:                                    if ((SUDOERS_MODE & 040) && seteuid(1)) {
                   1021:                                        perror("seteuid(1)");
                   1022:                                        exit(1);
                   1023:                                    }
                   1024:                                } else {
                   1025:                                    if (seteuid(SUDOERS_UID)) {
                   1026:                                        perror("seteuid(SUDOERS_UID)");
                   1027:                                        exit(1);
                   1028:                                    }
                   1029:                                }
                   1030:                                break;
                   1031:     }
                   1032: }
                   1033:
                   1034: /*
                   1035:  * Close all open files (except std*) and turn off core dumps.
                   1036:  */
                   1037: static void
                   1038: initial_setup()
                   1039: {
                   1040:     int fd, maxfd;
                   1041: #ifdef HAVE_SETRLIMIT
                   1042:     struct rlimit rl;
                   1043: #endif
                   1044: #ifdef POSIX_SIGNALS
                   1045:     struct sigaction sa;
                   1046: #endif
                   1047:
                   1048: #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
                   1049:     /*
                   1050:      * Turn off core dumps.
                   1051:      */
1.4       millert  1052:     (void) getrlimit(RLIMIT_CORE, &corelimit);
1.1       millert  1053:     rl.rlim_cur = rl.rlim_max = 0;
                   1054:     (void) setrlimit(RLIMIT_CORE, &rl);
                   1055: #endif /* RLIMIT_CORE */
                   1056:
                   1057:     /*
                   1058:      * Close any open fd's other than stdin, stdout and stderr.
                   1059:      */
                   1060: #ifdef HAVE_SYSCONF
1.3       millert  1061:     maxfd = sysconf(_SC_OPEN_MAX) - 1;
1.1       millert  1062: #else
1.3       millert  1063:     maxfd = getdtablesize() - 1;
1.1       millert  1064: #endif /* HAVE_SYSCONF */
1.3       millert  1065: #ifdef RLIMIT_NOFILE
                   1066:     if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
                   1067:        if (rl.rlim_max != RLIM_INFINITY && rl.rlim_max <= maxfd)
                   1068:            maxfd = rl.rlim_max - 1;
                   1069:     }
                   1070: #endif /* RLIMIT_NOFILE */
1.1       millert  1071:
                   1072:     for (fd = maxfd; fd > STDERR_FILENO; fd--)
                   1073:        (void) close(fd);
                   1074:
                   1075:     /* Catch children as they die... */
                   1076: #ifdef POSIX_SIGNALS
                   1077:     (void) memset((VOID *)&sa, 0, sizeof(sa));
                   1078:     sa.sa_handler = reapchild;
                   1079:     (void) sigaction(SIGCHLD, &sa, NULL);
                   1080: #else
                   1081:     (void) signal(SIGCHLD, reapchild);
                   1082: #endif /* POSIX_SIGNALS */
                   1083: }
                   1084:
1.4       millert  1085: #ifdef HAVE_LOGINCAP
                   1086: static int
                   1087: set_loginclass(pw)
                   1088:     struct passwd *pw;
                   1089: {
                   1090:     login_cap_t *lc;
                   1091:     int errflags;
                   1092:
                   1093:     /*
                   1094:      * Don't make it a fatal error if the user didn't specify the login
                   1095:      * class themselves.  We do this because if login.conf gets
                   1096:      * corrupted we want the admin to be able to use sudo to fix it.
                   1097:      */
                   1098:     if (login_class)
                   1099:        errflags = NO_MAIL|MSG_ONLY;
                   1100:     else
                   1101:        errflags = NO_MAIL|MSG_ONLY|NO_EXIT;
                   1102:
                   1103:     if (login_class && strcmp(login_class, "-") != 0) {
                   1104:        if (strcmp(*user_runas, "root") != 0 && user_uid != 0) {
                   1105:            (void) fprintf(stderr, "%s: only root can use -c %s\n",
                   1106:                Argv[0], login_class);
                   1107:            exit(1);
                   1108:        }
                   1109:     } else {
                   1110:        login_class = pw->pw_class;
                   1111:        if (!login_class || !*login_class)
                   1112:            login_class =
                   1113:                (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
                   1114:     }
                   1115:
                   1116:     lc = login_getclass(login_class);
                   1117:     if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
                   1118:        log_error(errflags, "unknown login class: %s", login_class);
                   1119:        return(0);
                   1120:     }
                   1121:
                   1122:     /* Set everything except the environment and umask.  */
                   1123:     if (setusercontext(lc, pw, pw->pw_uid,
                   1124:        LOGIN_SETUSER|LOGIN_SETGROUP|LOGIN_SETRESOURCES|LOGIN_SETPRIORITY) < 0)
                   1125:        log_error(NO_MAIL|USE_ERRNO|MSG_ONLY,
                   1126:            "setusercontext() failed for login class %s", login_class);
                   1127:
                   1128:     login_close(lc);
                   1129:     return(1);
                   1130: }
                   1131: #else
                   1132: static int
                   1133: set_loginclass(pw)
                   1134:     struct passwd *pw;
                   1135: {
                   1136:     return(0);
                   1137: }
                   1138: #endif /* HAVE_LOGINCAP */
                   1139:
1.1       millert  1140: /*
1.2       millert  1141:  * Look up the fully qualified domain name and set user_host and user_shost.
                   1142:  */
                   1143: void
                   1144: set_fqdn()
                   1145: {
                   1146:     struct hostent *hp;
                   1147:     char *p;
                   1148:
                   1149:     if (def_flag(I_FQDN)) {
                   1150:        if (!(hp = gethostbyname(user_host))) {
                   1151:            log_error(USE_ERRNO|MSG_ONLY|NO_EXIT,
                   1152:                "unable to lookup %s via gethostbyname()", user_host);
                   1153:        } else {
                   1154:            free(user_host);
                   1155:            user_host = estrdup(hp->h_name);
                   1156:        }
                   1157:     }
                   1158:     if (user_shost != user_host)
                   1159:        free(user_shost);
                   1160:     if ((p = strchr(user_host, '.'))) {
                   1161:        *p = '\0';
                   1162:        user_shost = estrdup(user_host);
                   1163:        *p = '.';
                   1164:     } else {
                   1165:        user_shost = user_host;
                   1166:     }
                   1167: }
                   1168:
                   1169: /*
1.4       millert  1170:  * If the sudoers file says to prompt for a different user's password,
                   1171:  * update the encrypted password in user_passwd accordingly.
                   1172:  */
                   1173: static void
                   1174: update_epasswd()
                   1175: {
                   1176:     struct passwd *pw;
                   1177:
                   1178:     /* We may be configured to prompt for a password other than the user's */
                   1179:     if (def_ival(I_ROOTPW)) {
                   1180:        if ((pw = getpwuid(0)) == NULL)
                   1181:            log_error(0, "uid 0 does not exist in the passwd file!");
                   1182:        free(user_passwd);
                   1183:        user_passwd = estrdup(sudo_getepw(pw));
                   1184:     } else if (def_ival(I_RUNASPW)) {
                   1185:        if ((pw = getpwnam(def_str(I_RUNAS_DEF))) == NULL)
                   1186:            log_error(0, "user %s does not exist in the passwd file!",
                   1187:                def_str(I_RUNAS_DEF));
                   1188:        free(user_passwd);
                   1189:        user_passwd = estrdup(sudo_getepw(pw));
                   1190:     } else if (def_ival(I_TARGETPW)) {
                   1191:        if (**user_runas == '#') {
                   1192:            if ((pw = getpwuid(atoi(*user_runas + 1))) == NULL)
                   1193:                log_error(0, "uid %s does not exist in the passwd file!",
                   1194:                    user_runas);
                   1195:        } else {
                   1196:            if ((pw = getpwnam(*user_runas)) == NULL)
                   1197:                log_error(0, "user %s does not exist in the passwd file!",
                   1198:                    user_runas);
                   1199:        }
                   1200:        free(user_passwd);
                   1201:        user_passwd = estrdup(sudo_getepw(pw));
                   1202:     }
                   1203: }
                   1204:
                   1205: /*
1.1       millert  1206:  * Tell which options are mutually exclusive and exit.
                   1207:  */
                   1208: static void
                   1209: usage_excl(exit_val)
                   1210:     int exit_val;
                   1211: {
                   1212:     (void) fprintf(stderr,
1.2       millert  1213:        "Only one of the -h, -k, -K, -l, -s, -v or -V options may be used\n");
1.1       millert  1214:     usage(exit_val);
                   1215: }
                   1216:
                   1217: /*
                   1218:  * Give usage message and exit.
                   1219:  */
                   1220: static void
                   1221: usage(exit_val)
                   1222:     int exit_val;
                   1223: {
                   1224:     (void) fprintf(stderr,
1.4       millert  1225:        "usage: %s -V | -h | -L | -l | -v | -k | -K | [-H] [-S] [-b]\n%*s",
1.1       millert  1226:        Argv[0], (int) strlen(Argv[0]) + 8, " ");
1.4       millert  1227: #ifdef HAVE_LOGINCAP
                   1228:     (void) fprintf(stderr, "[-p prompt] [-u username/#uid] [-c class] -s | <command>\n");
                   1229: #else
                   1230:     (void) fprintf(stderr, "[-p prompt] [-u username/#uid] -s | <command>\n");
                   1231: #endif
1.1       millert  1232:     exit(exit_val);
                   1233: }