Annotation of embedaddon/sudo/plugins/sudoers/sudoers.c, revision 1.1.1.5

1.1       misho       1: /*
1.1.1.4   misho       2:  * Copyright (c) 1993-1996, 1998-2013 Todd C. Miller <Todd.Miller@courtesan.com>
1.1       misho       3:  *
                      4:  * Permission to use, copy, modify, and distribute this software for any
                      5:  * purpose with or without fee is hereby granted, provided that the above
                      6:  * copyright notice and this permission notice appear in all copies.
                      7:  *
                      8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                      9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     15:  *
                     16:  * Sponsored in part by the Defense Advanced Research Projects
                     17:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
                     18:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
                     19:  */
                     20: 
                     21: #define _SUDO_MAIN
                     22: 
                     23: #ifdef __TANDEM
                     24: # include <floss.h>
                     25: #endif
                     26: 
                     27: #include <config.h>
                     28: 
                     29: #include <sys/types.h>
                     30: #include <sys/stat.h>
                     31: #include <sys/socket.h>
                     32: #include <stdio.h>
                     33: #ifdef STDC_HEADERS
                     34: # include <stdlib.h>
                     35: # include <stddef.h>
                     36: #else
                     37: # ifdef HAVE_STDLIB_H
                     38: #  include <stdlib.h>
                     39: # endif
                     40: #endif /* STDC_HEADERS */
                     41: #ifdef HAVE_STRING_H
                     42: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
                     43: #  include <memory.h>
                     44: # endif
                     45: # include <string.h>
                     46: #endif /* HAVE_STRING_H */
                     47: #ifdef HAVE_STRINGS_H
                     48: # include <strings.h>
                     49: #endif /* HAVE_STRINGS_H */
                     50: #ifdef HAVE_UNISTD_H
                     51: # include <unistd.h>
                     52: #endif /* HAVE_UNISTD_H */
                     53: #include <pwd.h>
                     54: #include <errno.h>
                     55: #include <fcntl.h>
                     56: #include <signal.h>
                     57: #include <grp.h>
                     58: #include <time.h>
                     59: #include <netdb.h>
                     60: #ifdef HAVE_LOGIN_CAP_H
                     61: # include <login_cap.h>
                     62: # ifndef LOGIN_DEFROOTCLASS
                     63: #  define LOGIN_DEFROOTCLASS   "daemon"
                     64: # endif
1.1.1.2   misho      65: # ifndef LOGIN_SETENV
                     66: #  define LOGIN_SETENV 0
                     67: # endif
1.1       misho      68: #endif
                     69: #ifdef HAVE_SELINUX
                     70: # include <selinux/selinux.h>
                     71: #endif
                     72: #include <ctype.h>
1.1.1.2   misho      73: #ifndef HAVE_GETADDRINFO
                     74: # include "compat/getaddrinfo.h"
                     75: #endif
1.1       misho      76: 
                     77: #include "sudoers.h"
                     78: #include "auth/sudo_auth.h"
1.1.1.2   misho      79: #include "secure_path.h"
1.1       misho      80: 
                     81: /*
                     82:  * Prototypes
                     83:  */
1.1.1.4   misho      84: static char *find_editor(int nfiles, char **files, char ***argv_out);
                     85: static int cb_runas_default(const char *);
                     86: static int cb_sudoers_locale(const char *);
1.1       misho      87: static int set_cmnd(void);
1.1.1.4   misho      88: static void create_admin_success_flag(void);
                     89: static void init_vars(char * const *);
                     90: static void set_fqdn(void);
1.1       misho      91: static void set_loginclass(struct passwd *);
                     92: static void set_runasgr(const char *);
1.1.1.4   misho      93: static void set_runaspw(const char *);
                     94: static bool tty_present(void);
1.1       misho      95: 
                     96: /*
                     97:  * Globals
                     98:  */
                     99: struct sudo_user sudo_user;
                    100: struct passwd *list_pw;
                    101: int long_list;
                    102: uid_t timestamp_uid;
                    103: extern int errorlineno;
1.1.1.2   misho     104: extern bool parse_error;
1.1       misho     105: extern char *errorfile;
                    106: #ifdef HAVE_BSD_AUTH_H
                    107: char *login_style;
                    108: #endif /* HAVE_BSD_AUTH_H */
                    109: int sudo_mode;
                    110: 
                    111: static char *prev_user;
                    112: static char *runas_user;
                    113: static char *runas_group;
                    114: static struct sudo_nss_list *snl;
                    115: 
                    116: /* XXX - must be extern for audit bits of sudo_auth.c */
                    117: int NewArgc;
                    118: char **NewArgv;
                    119: 
1.1.1.4   misho     120: int
                    121: sudoers_policy_init(void *info, char * const envp[])
1.1       misho     122: {
                    123:     volatile int sources = 0;
1.1.1.4   misho     124:     struct sudo_nss *nss, *nss_next;
                    125:     debug_decl(sudoers_policy_init, SUDO_DEBUG_PLUGIN)
1.1       misho     126: 
                    127:     bindtextdomain("sudoers", LOCALEDIR);
                    128: 
                    129:     sudo_setpwent();
                    130:     sudo_setgrent();
                    131: 
1.1.1.4   misho     132:     /* Register fatal/fatalx callback. */
                    133:     fatal_callback_register(sudoers_cleanup);
                    134: 
1.1       misho     135:     /* Initialize environment functions (including replacements). */
                    136:     env_init(envp);
                    137: 
                    138:     /* Setup defaults data structures. */
                    139:     init_defaults();
                    140: 
1.1.1.4   misho     141:     /* Parse info from front-end. */
                    142:     sudo_mode = sudoers_policy_deserialize_info(info, &runas_user, &runas_group);
1.1       misho     143: 
                    144:     init_vars(envp);           /* XXX - move this later? */
                    145: 
                    146:     /* Parse nsswitch.conf for sudoers order. */
                    147:     snl = sudo_read_nss();
                    148: 
                    149:     /* LDAP or NSS may modify the euid so we need to be root for the open. */
                    150:     set_perms(PERM_ROOT);
                    151: 
                    152:     /* Open and parse sudoers, set global defaults */
1.1.1.3   misho     153:     for (nss = snl->first; nss != NULL; nss = nss_next) {
                    154:         nss_next = nss->next;
                    155:         if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
                    156:             sources++;
                    157:             if (nss->setdefs(nss) != 0)
1.1.1.4   misho     158:                 log_warning(NO_STDERR, N_("problem with defaults entries"));
1.1.1.3   misho     159:         } else {
                    160:             tq_remove(snl, nss);
                    161:         }
1.1       misho     162:     }
                    163:     if (sources == 0) {
                    164:        warningx(_("no valid sudoers sources found, quitting"));
1.1.1.2   misho     165:        debug_return_bool(-1);
1.1       misho     166:     }
                    167: 
                    168:     /* XXX - collect post-sudoers parse settings into a function */
                    169: 
                    170:     /*
                    171:      * Initialize external group plugin, if any.
                    172:      */
                    173:     if (def_group_plugin) {
1.1.1.2   misho     174:        if (group_plugin_load(def_group_plugin) != true)
1.1       misho     175:            def_group_plugin = NULL;
                    176:     }
                    177: 
                    178:     /*
                    179:      * Set runas passwd/group entries based on command line or sudoers.
                    180:      * Note that if runas_group was specified without runas_user we
                    181:      * defer setting runas_pw so the match routines know to ignore it.
                    182:      */
1.1.1.4   misho     183:     /* XXX - qpm4u does more here as it may have already set runas_pw */
1.1       misho     184:     if (runas_group != NULL) {
                    185:        set_runasgr(runas_group);
                    186:        if (runas_user != NULL)
                    187:            set_runaspw(runas_user);
                    188:     } else
                    189:        set_runaspw(runas_user ? runas_user : def_runas_default);
                    190: 
                    191:     if (!update_defaults(SETDEF_RUNAS))
1.1.1.4   misho     192:        log_warning(NO_STDERR, N_("problem with defaults entries"));
1.1       misho     193: 
                    194:     if (def_fqdn)
                    195:        set_fqdn();     /* deferred until after sudoers is parsed */
                    196: 
                    197:     /* Set login class if applicable. */
1.1.1.2   misho     198:     set_loginclass(runas_pw ? runas_pw : sudo_user.pw);
1.1       misho     199: 
                    200:     restore_perms();
                    201: 
1.1.1.2   misho     202:     debug_return_bool(true);
1.1       misho     203: }
                    204: 
1.1.1.4   misho     205: int
1.1       misho     206: sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
1.1.1.4   misho     207:     void *closure)
1.1       misho     208: {
                    209:     char **edit_argv = NULL;
1.1.1.4   misho     210:     char *iolog_path = NULL;
                    211:     mode_t cmnd_umask = 0777;
1.1       misho     212:     struct sudo_nss *nss;
1.1.1.4   misho     213:     int cmnd_status = -1, oldlocale, validated;
1.1.1.2   misho     214:     volatile int rval = true;
                    215:     debug_decl(sudoers_policy_main, SUDO_DEBUG_PLUGIN)
1.1       misho     216: 
1.1.1.4   misho     217:     /* XXX - would like to move this to policy.c but need the cleanup. */
                    218:     if (fatal_setjmp() != 0) {
                    219:        /* error recovery via fatal(), fatalx() or log_fatal() */
1.1       misho     220:        rval = -1;
                    221:        goto done;
                    222:     }
                    223: 
                    224:     /* Is root even allowed to run sudo? */
                    225:     if (user_uid == 0 && !def_root_sudo) {
                    226:         warningx(_("sudoers specifies that root is not allowed to sudo"));
                    227:         goto bad;
                    228:     }    
                    229: 
                    230:     set_perms(PERM_INITIAL);
                    231: 
                    232:     /* Environment variables specified on the command line. */
                    233:     if (env_add != NULL && env_add[0] != NULL)
                    234:        sudo_user.env_vars = env_add;
                    235: 
                    236:     /*
                    237:      * Make a local copy of argc/argv, with special handling
                    238:      * for pseudo-commands and the '-i' option.
                    239:      */
                    240:     if (argc == 0) {
                    241:        NewArgc = 1;
                    242:        NewArgv = emalloc2(NewArgc + 1, sizeof(char *));
                    243:        NewArgv[0] = user_cmnd;
                    244:        NewArgv[1] = NULL;
                    245:     } else {
                    246:        /* Must leave an extra slot before NewArgv for bash's --login */
                    247:        NewArgc = argc;
                    248:        NewArgv = emalloc2(NewArgc + 2, sizeof(char *));
                    249:        memcpy(++NewArgv, argv, argc * sizeof(char *));
                    250:        NewArgv[NewArgc] = NULL;
1.1.1.2   misho     251:        if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && runas_pw != NULL)
1.1       misho     252:            NewArgv[0] = estrdup(runas_pw->pw_shell);
                    253:     }
                    254: 
                    255:     /* If given the -P option, set the "preserve_groups" flag. */
                    256:     if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
1.1.1.2   misho     257:        def_preserve_groups = true;
1.1       misho     258: 
1.1.1.5 ! misho     259:     /* Find command in path and apply per-command Defaults. */
1.1       misho     260:     cmnd_status = set_cmnd();
                    261: 
1.1.1.5 ! misho     262:     /* Check for -C overriding def_closefrom. */
        !           263:     if (user_closefrom >= 0 && user_closefrom != def_closefrom) {
        !           264:        if (!def_closefrom_override) {
        !           265:            warningx(_("you are not permitted to use the -C option"));
        !           266:            goto bad;
        !           267:        }
        !           268:        def_closefrom = user_closefrom;
        !           269:     }
        !           270: 
1.1       misho     271:     /*
1.1.1.4   misho     272:      * Check sudoers sources, using the locale specified in sudoers.
1.1       misho     273:      */
1.1.1.4   misho     274:     sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
1.1       misho     275:     validated = FLAG_NO_USER | FLAG_NO_HOST;
                    276:     tq_foreach_fwd(snl, nss) {
                    277:        validated = nss->lookup(nss, validated, pwflag);
                    278: 
                    279:        if (ISSET(validated, VALIDATE_OK)) {
1.1.1.3   misho     280:            /* Handle [SUCCESS=return] */
1.1       misho     281:            if (nss->ret_if_found)
                    282:                break;
                    283:        } else {
                    284:            /* Handle [NOTFOUND=return] */
                    285:            if (nss->ret_if_notfound)
                    286:                break;
                    287:        }
                    288:     }
                    289: 
1.1.1.4   misho     290:     /* Restore user's locale. */
                    291:     sudoers_setlocale(oldlocale, NULL);
                    292: 
1.1       misho     293:     if (safe_cmnd == NULL)
                    294:        safe_cmnd = estrdup(user_cmnd);
                    295: 
                    296:     /* If only a group was specified, set runas_pw based on invoking user. */
                    297:     if (runas_pw == NULL)
                    298:        set_runaspw(user_name);
                    299: 
                    300:     /*
                    301:      * Look up the timestamp dir owner if one is specified.
                    302:      */
                    303:     if (def_timestampowner) {
                    304:        struct passwd *pw;
                    305: 
                    306:        if (*def_timestampowner == '#')
                    307:            pw = sudo_getpwuid(atoi(def_timestampowner + 1));
                    308:        else
                    309:            pw = sudo_getpwnam(def_timestampowner);
1.1.1.2   misho     310:        if (pw != NULL) {
                    311:            timestamp_uid = pw->pw_uid;
1.1.1.3   misho     312:            sudo_pw_delref(pw);
1.1.1.2   misho     313:        } else {
1.1.1.4   misho     314:            log_warning(0, N_("timestamp owner (%s): No such user"),
1.1       misho     315:                def_timestampowner);
1.1.1.2   misho     316:            timestamp_uid = ROOT_UID;
                    317:        }
1.1       misho     318:     }
                    319: 
                    320:     /* If no command line args and "shell_noargs" is not set, error out. */
                    321:     if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) {
                    322:        rval = -2; /* usage error */
                    323:        goto done;
                    324:     }
                    325: 
                    326:     /* Bail if a tty is required and we don't have one.  */
1.1.1.4   misho     327:     if (def_requiretty && !tty_present()) {
                    328:        audit_failure(NewArgv, N_("no tty"));
                    329:        warningx(_("sorry, you must have a tty to run sudo"));
                    330:        goto bad;
1.1       misho     331:     }
                    332: 
                    333:     /*
                    334:      * We don't reset the environment for sudoedit or if the user
                    335:      * specified the -E command line flag and they have setenv privs.
                    336:      */
                    337:     if (ISSET(sudo_mode, MODE_EDIT) ||
                    338:        (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv))
1.1.1.2   misho     339:        def_env_reset = false;
1.1       misho     340: 
                    341:     /* Build a new environment that avoids any nasty bits. */
                    342:     rebuild_env();
                    343: 
                    344:     /* Require a password if sudoers says so.  */
                    345:     rval = check_user(validated, sudo_mode);
1.1.1.3   misho     346:     if (rval != true) {
                    347:        if (!ISSET(validated, VALIDATE_OK))
1.1.1.4   misho     348:            log_denial(validated, false);
1.1       misho     349:        goto done;
1.1.1.3   misho     350:     }
1.1       misho     351: 
                    352:     /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
                    353:     /* XXX - causes confusion when root is not listed in sudoers */
                    354:     if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) {
                    355:        if (user_uid == 0 && strcmp(prev_user, "root") != 0) {
                    356:            struct passwd *pw;
                    357: 
                    358:            if ((pw = sudo_getpwnam(prev_user)) != NULL) {
                    359:                    if (sudo_user.pw != NULL)
1.1.1.3   misho     360:                        sudo_pw_delref(sudo_user.pw);
1.1       misho     361:                    sudo_user.pw = pw;
                    362:            }
                    363:        }
                    364:     }
                    365: 
                    366:     /* If the user was not allowed to run the command we are done. */
                    367:     if (!ISSET(validated, VALIDATE_OK)) {
1.1.1.3   misho     368:        log_failure(validated, cmnd_status);
1.1       misho     369:        goto bad;
                    370:     }
                    371: 
                    372:     /* Create Ubuntu-style dot file to indicate sudo was successful. */
                    373:     create_admin_success_flag();
                    374: 
                    375:     /* Finally tell the user if the command did not exist. */
                    376:     if (cmnd_status == NOT_FOUND_DOT) {
1.1.1.4   misho     377:        audit_failure(NewArgv, N_("command in current directory"));
1.1       misho     378:        warningx(_("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run."), user_cmnd, user_cmnd, user_cmnd);
                    379:        goto bad;
                    380:     } else if (cmnd_status == NOT_FOUND) {
1.1.1.4   misho     381:        if (ISSET(sudo_mode, MODE_CHECK)) {
                    382:            audit_failure(NewArgv, N_("%s: command not found"), NewArgv[0]);
                    383:            warningx(_("%s: command not found"), NewArgv[0]);
                    384:        } else {
                    385:            audit_failure(NewArgv, N_("%s: command not found"), user_cmnd);
                    386:            warningx(_("%s: command not found"), user_cmnd);
                    387:        }
1.1       misho     388:        goto bad;
                    389:     }
                    390: 
                    391:     /* If user specified env vars make sure sudoers allows it. */
                    392:     if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) {
                    393:        if (ISSET(sudo_mode, MODE_PRESERVE_ENV)) {
                    394:            warningx(_("sorry, you are not allowed to preserve the environment"));
                    395:            goto bad;
                    396:        } else
                    397:            validate_env_vars(sudo_user.env_vars);
                    398:     }
                    399: 
1.1.1.4   misho     400:     if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT))) {
                    401:        if ((def_log_input || def_log_output) && def_iolog_file && def_iolog_dir) {
                    402:            const char prefix[] = "iolog_path=";
                    403:            iolog_path = expand_iolog_path(prefix, def_iolog_dir,
                    404:                def_iolog_file, &sudo_user.iolog_file);
1.1       misho     405:            sudo_user.iolog_file++;
                    406:        }
                    407:     }
                    408: 
                    409:     log_allowed(validated);
                    410:     if (ISSET(sudo_mode, MODE_CHECK))
                    411:        rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
                    412:     else if (ISSET(sudo_mode, MODE_LIST))
                    413:        display_privs(snl, list_pw ? list_pw : sudo_user.pw); /* XXX - return val */
                    414: 
                    415:     /* Cleanup sudoers sources */
                    416:     tq_foreach_fwd(snl, nss) {
                    417:        nss->close(nss);
                    418:     }
                    419:     if (def_group_plugin)
                    420:        group_plugin_unload();
                    421: 
                    422:     if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) {
                    423:        /* rval already set appropriately */
                    424:        goto done;
                    425:     }
                    426: 
                    427:     /*
                    428:      * Set umask based on sudoers.
                    429:      * If user's umask is more restrictive, OR in those bits too
                    430:      * unless umask_override is set.
                    431:      */
                    432:     if (def_umask != 0777) {
1.1.1.4   misho     433:        cmnd_umask = def_umask;
                    434:        if (!def_umask_override)
                    435:            cmnd_umask |= user_umask;
1.1       misho     436:     }
                    437: 
                    438:     if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
                    439:        char *p;
                    440: 
                    441:        /* Convert /bin/sh -> -sh so shell knows it is a login shell */
                    442:        if ((p = strrchr(NewArgv[0], '/')) == NULL)
                    443:            p = NewArgv[0];
                    444:        *p = '-';
                    445:        NewArgv[0] = p;
                    446: 
                    447:        /*
                    448:         * Newer versions of bash require the --login option to be used
                    449:         * in conjunction with the -c option even if the shell name starts
                    450:         * with a '-'.  Unfortunately, bash 1.x uses -login, not --login
                    451:         * so this will cause an error for that.
                    452:         */
                    453:        if (NewArgc > 1 && strcmp(NewArgv[0], "-bash") == 0 &&
                    454:            strcmp(NewArgv[1], "-c") == 0) {
                    455:            /* Use the extra slot before NewArgv so we can store --login. */
                    456:            NewArgv--;
                    457:            NewArgc++;
                    458:            NewArgv[0] = NewArgv[1];
                    459:            NewArgv[1] = "--login";
                    460:        }
                    461: 
1.1.1.2   misho     462: #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM))
1.1       misho     463:        /* Insert system-wide environment variables. */
1.1.1.2   misho     464:        read_env_file(_PATH_ENVIRONMENT, true);
1.1       misho     465: #endif
1.1.1.2   misho     466: #ifdef HAVE_LOGIN_CAP_H
                    467:        /* Set environment based on login class. */
                    468:        if (login_class) {
                    469:            login_cap_t *lc = login_getclass(login_class);
                    470:            if (lc != NULL) {
                    471:                setusercontext(lc, runas_pw, runas_pw->pw_uid, LOGIN_SETPATH|LOGIN_SETENV);
                    472:                login_close(lc);
                    473:            }
                    474:        }
                    475: #endif /* HAVE_LOGIN_CAP_H */
1.1       misho     476:     }
                    477: 
                    478:     /* Insert system-wide environment variables. */
                    479:     if (def_env_file)
1.1.1.2   misho     480:        read_env_file(def_env_file, false);
1.1       misho     481: 
                    482:     /* Insert user-specified environment variables. */
                    483:     insert_env_vars(sudo_user.env_vars);
                    484: 
                    485:     if (ISSET(sudo_mode, MODE_EDIT)) {
1.1.1.4   misho     486:        efree(safe_cmnd);
                    487:        safe_cmnd = find_editor(NewArgc - 1, NewArgv + 1, &edit_argv);
                    488:        if (safe_cmnd == NULL)
1.1       misho     489:            goto bad;
                    490:     }
                    491: 
                    492:     /* Must audit before uid change. */
                    493:     audit_success(NewArgv);
                    494: 
1.1.1.4   misho     495:     /* Setup execution environment to pass back to front-end. */
                    496:     rval = sudoers_policy_exec_setup(edit_argv ? edit_argv : NewArgv,
                    497:        env_get(), cmnd_umask, iolog_path, closure);
1.1       misho     498: 
1.1.1.4   misho     499:     /* Zero out stashed copy of environment, it is owned by the front-end. */
1.1.1.2   misho     500:     env_init(NULL);
1.1       misho     501: 
                    502:     goto done;
                    503: 
                    504: bad:
1.1.1.2   misho     505:     rval = false;
1.1       misho     506: 
                    507: done:
1.1.1.4   misho     508:     fatal_disable_setjmp();
1.1       misho     509:     rewind_perms();
                    510: 
                    511:     /* Close the password and group files and free up memory. */
                    512:     sudo_endpwent();
                    513:     sudo_endgrent();
                    514: 
1.1.1.2   misho     515:     debug_return_bool(rval);
1.1       misho     516: }
                    517: 
                    518: /*
1.1.1.4   misho     519:  * Initialize timezone and fill in ``sudo_user'' struct.
1.1       misho     520:  */
                    521: static void
                    522: init_vars(char * const envp[])
                    523: {
                    524:     char * const * ep;
1.1.1.5 ! misho     525:     bool unknown_user = false;
1.1.1.2   misho     526:     debug_decl(init_vars, SUDO_DEBUG_PLUGIN)
1.1       misho     527: 
1.1.1.4   misho     528:     sudoers_initlocale(setlocale(LC_ALL, NULL), def_sudoers_locale);
1.1       misho     529: 
                    530:     for (ep = envp; *ep; ep++) {
                    531:        /* XXX - don't fill in if empty string */
                    532:        switch (**ep) {
                    533:            case 'K':
                    534:                if (strncmp("KRB5CCNAME=", *ep, 11) == 0)
                    535:                    user_ccname = *ep + 11;
                    536:                break;
                    537:            case 'P':
                    538:                if (strncmp("PATH=", *ep, 5) == 0)
                    539:                    user_path = *ep + 5;
                    540:                break;
                    541:            case 'S':
                    542:                if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
                    543:                    user_prompt = *ep + 12;
                    544:                else if (strncmp("SUDO_USER=", *ep, 10) == 0)
                    545:                    prev_user = *ep + 10;
                    546:                break;
                    547:            }
                    548:     }
                    549: 
                    550:     /*
1.1.1.4   misho     551:      * Get a local copy of the user's struct passwd if we don't already
                    552:      * have one.
1.1       misho     553:      */
1.1.1.4   misho     554:     if (sudo_user.pw == NULL) {
                    555:        if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL) {
                    556:            /*
                    557:             * It is not unusual for users to place "sudo -k" in a .logout
                    558:             * file which can cause sudo to be run during reboot after the
                    559:             * YP/NIS/NIS+/LDAP/etc daemon has died.
                    560:             */
                    561:            if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE)
                    562:                fatalx(_("unknown uid: %u"), (unsigned int) user_uid);
1.1       misho     563: 
1.1.1.4   misho     564:            /* Need to make a fake struct passwd for the call to log_fatal(). */
                    565:            sudo_user.pw = sudo_mkpwent(user_name, user_uid, user_gid, NULL, NULL);
1.1.1.5 ! misho     566:            unknown_user = true;
1.1.1.4   misho     567:        }
1.1       misho     568:     }
                    569: 
                    570:     /*
1.1.1.5 ! misho     571:      * Get group list and store initialize permissions.
1.1       misho     572:      */
                    573:     if (user_group_list == NULL)
1.1.1.3   misho     574:        user_group_list = sudo_get_grlist(sudo_user.pw);
1.1.1.5 ! misho     575:     set_perms(PERM_INITIAL);
1.1       misho     576: 
                    577:     /* Set runas callback. */
                    578:     sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default;
                    579: 
1.1.1.4   misho     580:     /* Set locale callback. */
                    581:     sudo_defs_table[I_SUDOERS_LOCALE].callback = cb_sudoers_locale;
                    582: 
                    583:     /* Set maxseq callback. */
                    584:     sudo_defs_table[I_MAXSEQ].callback = io_set_max_sessid;
                    585: 
1.1.1.2   misho     586:     /* It is now safe to use log_fatal() and set_perms() */
1.1.1.5 ! misho     587:     if (unknown_user)
        !           588:        log_fatal(0, N_("unknown uid: %u"), (unsigned int) user_uid);
1.1.1.2   misho     589:     debug_return;
1.1       misho     590: }
                    591: 
                    592: /*
                    593:  * Fill in user_cmnd, user_args, user_base and user_stat variables
                    594:  * and apply any command-specific defaults entries.
                    595:  */
                    596: static int
                    597: set_cmnd(void)
                    598: {
                    599:     int rval;
                    600:     char *path = user_path;
1.1.1.2   misho     601:     debug_decl(set_cmnd, SUDO_DEBUG_PLUGIN)
1.1       misho     602: 
                    603:     /* Resolve the path and return. */
                    604:     rval = FOUND;
1.1.1.2   misho     605:     user_stat = ecalloc(1, sizeof(struct stat));
1.1       misho     606: 
                    607:     /* Default value for cmnd, overridden below. */
                    608:     if (user_cmnd == NULL)
                    609:        user_cmnd = NewArgv[0];
                    610: 
                    611:     if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
                    612:        if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
                    613:            if (def_secure_path && !user_is_exempt())
                    614:                path = def_secure_path;
                    615:            set_perms(PERM_RUNAS);
                    616:            rval = find_path(NewArgv[0], &user_cmnd, user_stat, path,
                    617:                def_ignore_dot);
                    618:            restore_perms();
                    619:            if (rval != FOUND) {
                    620:                /* Failed as root, try as invoking user. */
                    621:                set_perms(PERM_USER);
                    622:                rval = find_path(NewArgv[0], &user_cmnd, user_stat, path,
                    623:                    def_ignore_dot);
                    624:                restore_perms();
                    625:            }
                    626:        }
                    627: 
                    628:        /* set user_args */
                    629:        if (NewArgc > 1) {
                    630:            char *to, *from, **av;
                    631:            size_t size, n;
                    632: 
                    633:            /* Alloc and build up user_args. */
                    634:            for (size = 0, av = NewArgv + 1; *av; av++)
                    635:                size += strlen(*av) + 1;
                    636:            user_args = emalloc(size);
                    637:            if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
                    638:                /*
                    639:                 * When running a command via a shell, the sudo front-end
                    640:                 * escapes potential meta chars.  We unescape non-spaces
                    641:                 * for sudoers matching and logging purposes.
                    642:                 */
                    643:                for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
                    644:                    while (*from) {
                    645:                        if (from[0] == '\\' && !isspace((unsigned char)from[1]))
                    646:                            from++;
                    647:                        *to++ = *from++;
                    648:                    }
                    649:                    *to++ = ' ';
                    650:                }
                    651:                *--to = '\0';
                    652:            } else {
                    653:                for (to = user_args, av = NewArgv + 1; *av; av++) {
                    654:                    n = strlcpy(to, *av, size - (to - user_args));
                    655:                    if (n >= size - (to - user_args))
1.1.1.4   misho     656:                        fatalx(_("internal error, %s overflow"), "set_cmnd()");
1.1       misho     657:                    to += n;
                    658:                    *to++ = ' ';
                    659:                }
                    660:                *--to = '\0';
                    661:            }
                    662:        }
                    663:     }
1.1.1.4   misho     664:     if (strlen(user_cmnd) >= PATH_MAX) {
                    665:        errno = ENAMETOOLONG;
                    666:        fatal("%s", user_cmnd);
                    667:     }
1.1       misho     668: 
                    669:     if ((user_base = strrchr(user_cmnd, '/')) != NULL)
                    670:        user_base++;
                    671:     else
                    672:        user_base = user_cmnd;
                    673: 
                    674:     if (!update_defaults(SETDEF_CMND))
1.1.1.4   misho     675:        log_warning(NO_STDERR, N_("problem with defaults entries"));
1.1       misho     676: 
1.1.1.2   misho     677:     debug_return_int(rval);
1.1       misho     678: }
                    679: 
                    680: /*
                    681:  * Open sudoers and sanity check mode/owner/type.
                    682:  * Returns a handle to the sudoers file or NULL on error.
                    683:  */
                    684: FILE *
1.1.1.2   misho     685: open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
1.1       misho     686: {
1.1.1.2   misho     687:     struct stat sb;
1.1       misho     688:     FILE *fp = NULL;
1.1.1.2   misho     689:     debug_decl(open_sudoers, SUDO_DEBUG_PLUGIN)
1.1       misho     690: 
                    691:     set_perms(PERM_SUDOERS);
                    692: 
1.1.1.2   misho     693:     switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) {
                    694:        case SUDO_PATH_SECURE:
1.1.1.3   misho     695:            /*
                    696:             * If we are expecting sudoers to be group readable but
                    697:             * it is not, we must open the file as root, not uid 1.
                    698:             */
                    699:            if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP)) {
                    700:                if ((sb.st_mode & S_IRGRP) == 0) {
                    701:                    restore_perms();
                    702:                    set_perms(PERM_ROOT);
                    703:                }
                    704:            }
                    705:            /*
                    706:             * Open sudoers and make sure we can read it so we can present
                    707:             * the user with a reasonable error message (unlike the lexer).
                    708:             */
1.1.1.2   misho     709:            if ((fp = fopen(sudoers, "r")) == NULL) {
1.1.1.4   misho     710:                log_warning(USE_ERRNO, N_("unable to open %s"), sudoers);
1.1.1.2   misho     711:            } else {
                    712:                if (sb.st_size != 0 && fgetc(fp) == EOF) {
1.1.1.4   misho     713:                    log_warning(USE_ERRNO, N_("unable to read %s"),
1.1.1.2   misho     714:                        sudoers);
                    715:                    fclose(fp);
                    716:                    fp = NULL;
                    717:                } else {
                    718:                    /* Rewind fp and set close on exec flag. */
                    719:                    rewind(fp);
                    720:                    (void) fcntl(fileno(fp), F_SETFD, 1);
                    721:                }
                    722:            }
                    723:            break;
                    724:        case SUDO_PATH_MISSING:
1.1.1.4   misho     725:            log_warning(USE_ERRNO, N_("unable to stat %s"), sudoers);
1.1.1.2   misho     726:            break;
                    727:        case SUDO_PATH_BAD_TYPE:
1.1.1.4   misho     728:            log_warning(0, N_("%s is not a regular file"), sudoers);
1.1.1.2   misho     729:            break;
                    730:        case SUDO_PATH_WRONG_OWNER:
1.1.1.4   misho     731:            log_warning(0, N_("%s is owned by uid %u, should be %u"),
1.1.1.2   misho     732:                sudoers, (unsigned int) sb.st_uid, (unsigned int) sudoers_uid);
                    733:            break;
                    734:        case SUDO_PATH_WORLD_WRITABLE:
1.1.1.4   misho     735:            log_warning(0, N_("%s is world writable"), sudoers);
1.1.1.2   misho     736:            break;
                    737:        case SUDO_PATH_GROUP_WRITABLE:
1.1.1.4   misho     738:            log_warning(0, N_("%s is owned by gid %u, should be %u"),
1.1.1.2   misho     739:                sudoers, (unsigned int) sb.st_gid, (unsigned int) sudoers_gid);
                    740:            break;
                    741:        default:
                    742:            /* NOTREACHED */
                    743:            break;
1.1       misho     744:     }
                    745: 
                    746:     restore_perms();           /* change back to root */
1.1.1.2   misho     747: 
                    748:     debug_return_ptr(fp);
1.1       misho     749: }
                    750: 
                    751: #ifdef HAVE_LOGIN_CAP_H
                    752: static void
                    753: set_loginclass(struct passwd *pw)
                    754: {
1.1.1.2   misho     755:     const int errflags = NO_MAIL|MSG_ONLY;
                    756:     login_cap_t *lc;
                    757:     debug_decl(set_loginclass, SUDO_DEBUG_PLUGIN)
1.1       misho     758: 
1.1.1.2   misho     759:     if (!def_use_loginclass)
                    760:        debug_return;
1.1       misho     761: 
                    762:     if (login_class && strcmp(login_class, "-") != 0) {
                    763:        if (user_uid != 0 &&
                    764:            strcmp(runas_user ? runas_user : def_runas_default, "root") != 0)
1.1.1.4   misho     765:            fatalx(_("only root can use `-c %s'"), login_class);
1.1       misho     766:     } else {
                    767:        login_class = pw->pw_class;
                    768:        if (!login_class || !*login_class)
                    769:            login_class =
                    770:                (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
                    771:     }
                    772: 
1.1.1.2   misho     773:     /* Make sure specified login class is valid. */
1.1       misho     774:     lc = login_getclass(login_class);
                    775:     if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
1.1.1.2   misho     776:        /*
                    777:         * Don't make it a fatal error if the user didn't specify the login
                    778:         * class themselves.  We do this because if login.conf gets
                    779:         * corrupted we want the admin to be able to use sudo to fix it.
                    780:         */
                    781:        if (login_class)
1.1.1.4   misho     782:            log_fatal(errflags, N_("unknown login class: %s"), login_class);
1.1.1.2   misho     783:        else
1.1.1.4   misho     784:            log_warning(errflags, N_("unknown login class: %s"), login_class);
1.1.1.2   misho     785:        def_use_loginclass = false;
1.1       misho     786:     }
1.1.1.2   misho     787:     login_close(lc);
                    788:     debug_return;
1.1       misho     789: }
                    790: #else
                    791: static void
                    792: set_loginclass(struct passwd *pw)
                    793: {
                    794: }
                    795: #endif /* HAVE_LOGIN_CAP_H */
                    796: 
1.1.1.3   misho     797: #ifndef AI_FQDN
                    798: # define AI_FQDN AI_CANONNAME
                    799: #endif
                    800: 
1.1       misho     801: /*
                    802:  * Look up the fully qualified domain name and set user_host and user_shost.
1.1.1.3   misho     803:  * Use AI_FQDN if available since "canonical" is not always the same as fqdn.
1.1       misho     804:  */
1.1.1.4   misho     805: static void
1.1       misho     806: set_fqdn(void)
                    807: {
                    808:     struct addrinfo *res0, hint;
                    809:     char *p;
1.1.1.2   misho     810:     debug_decl(set_fqdn, SUDO_DEBUG_PLUGIN)
1.1       misho     811: 
1.1.1.5 ! misho     812:     memset(&hint, 0, sizeof(hint));
1.1       misho     813:     hint.ai_family = PF_UNSPEC;
1.1.1.3   misho     814:     hint.ai_flags = AI_FQDN;
1.1       misho     815:     if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) {
1.1.1.4   misho     816:        log_warning(MSG_ONLY, N_("unable to resolve host %s"), user_host);
1.1       misho     817:     } else {
                    818:        if (user_shost != user_host)
                    819:            efree(user_shost);
                    820:        efree(user_host);
                    821:        user_host = estrdup(res0->ai_canonname);
                    822:        freeaddrinfo(res0);
1.1.1.3   misho     823:        if ((p = strchr(user_host, '.')) != NULL)
                    824:            user_shost = estrndup(user_host, (size_t)(p - user_host));
                    825:        else
                    826:            user_shost = user_host;
1.1       misho     827:     }
1.1.1.2   misho     828:     debug_return;
1.1       misho     829: }
                    830: 
                    831: /*
                    832:  * Get passwd entry for the user we are going to run commands as
                    833:  * and store it in runas_pw.  By default, commands run as "root".
                    834:  */
1.1.1.2   misho     835: static void
1.1       misho     836: set_runaspw(const char *user)
                    837: {
1.1.1.2   misho     838:     debug_decl(set_runaspw, SUDO_DEBUG_PLUGIN)
                    839: 
1.1       misho     840:     if (runas_pw != NULL)
1.1.1.3   misho     841:        sudo_pw_delref(runas_pw);
1.1       misho     842:     if (*user == '#') {
                    843:        if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
                    844:            runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
                    845:     } else {
                    846:        if ((runas_pw = sudo_getpwnam(user)) == NULL)
1.1.1.4   misho     847:            log_fatal(NO_MAIL|MSG_ONLY, N_("unknown user: %s"), user);
1.1       misho     848:     }
1.1.1.2   misho     849:     debug_return;
1.1       misho     850: }
                    851: 
                    852: /*
                    853:  * Get group entry for the group we are going to run commands as
                    854:  * and store it in runas_gr.
                    855:  */
                    856: static void
                    857: set_runasgr(const char *group)
                    858: {
1.1.1.2   misho     859:     debug_decl(set_runasgr, SUDO_DEBUG_PLUGIN)
                    860: 
1.1       misho     861:     if (runas_gr != NULL)
1.1.1.3   misho     862:        sudo_gr_delref(runas_gr);
1.1       misho     863:     if (*group == '#') {
                    864:        if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
                    865:            runas_gr = sudo_fakegrnam(group);
                    866:     } else {
                    867:        if ((runas_gr = sudo_getgrnam(group)) == NULL)
1.1.1.4   misho     868:            log_fatal(NO_MAIL|MSG_ONLY, N_("unknown group: %s"), group);
1.1       misho     869:     }
1.1.1.2   misho     870:     debug_return;
1.1       misho     871: }
                    872: 
                    873: /*
                    874:  * Callback for runas_default sudoers setting.
                    875:  */
                    876: static int
                    877: cb_runas_default(const char *user)
                    878: {
                    879:     /* Only reset runaspw if user didn't specify one. */
                    880:     if (!runas_user && !runas_group)
                    881:        set_runaspw(user);
1.1.1.2   misho     882:     return true;
1.1       misho     883: }
                    884: 
                    885: /*
1.1.1.4   misho     886:  * Callback for sudoers_locale sudoers setting.
1.1       misho     887:  */
                    888: static int
1.1.1.4   misho     889: cb_sudoers_locale(const char *locale)
1.1       misho     890: {
1.1.1.4   misho     891:     sudoers_initlocale(NULL, locale);
                    892:     return true;
1.1       misho     893: }
                    894: 
1.1.1.4   misho     895: /*
                    896:  * Cleanup hook for fatal()/fatalx()
                    897:  */
                    898: void
                    899: sudoers_cleanup(void)
1.1       misho     900: {
1.1.1.4   misho     901:     struct sudo_nss *nss;
                    902:     debug_decl(sudoers_cleanup, SUDO_DEBUG_PLUGIN)
1.1       misho     903: 
1.1.1.4   misho     904:     if (snl != NULL) {
                    905:        tq_foreach_fwd(snl, nss)
                    906:            nss->close(nss);
1.1.1.2   misho     907:     }
1.1.1.4   misho     908:     if (def_group_plugin)
                    909:        group_plugin_unload();
                    910:     sudo_endpwent();
                    911:     sudo_endgrent();
1.1.1.2   misho     912: 
1.1.1.4   misho     913:     debug_return;
1.1       misho     914: }
                    915: 
                    916: static char *
1.1.1.4   misho     917: resolve_editor(const char *ed, size_t edlen, int nfiles, char **files, char ***argv_out)
1.1       misho     918: {
1.1.1.4   misho     919:     char *cp, **nargv, *editor, *editor_path = NULL;
1.1.1.2   misho     920:     int ac, i, nargc;
                    921:     bool wasblank;
                    922:     debug_decl(resolve_editor, SUDO_DEBUG_PLUGIN)
1.1       misho     923: 
1.1.1.4   misho     924:     /* Note: editor becomes part of argv_out and is not freed. */
                    925:     editor = emalloc(edlen + 1);
                    926:     memcpy(editor, ed, edlen);
                    927:     editor[edlen] = '\0';
1.1       misho     928: 
                    929:     /*
                    930:      * Split editor into an argument vector; editor is reused (do not free).
                    931:      * The EDITOR and VISUAL environment variables may contain command
                    932:      * line args so look for those and alloc space for them too.
                    933:      */
                    934:     nargc = 1;
1.1.1.2   misho     935:     for (wasblank = false, cp = editor; *cp != '\0'; cp++) {
1.1       misho     936:        if (isblank((unsigned char) *cp))
1.1.1.2   misho     937:            wasblank = true;
1.1       misho     938:        else if (wasblank) {
1.1.1.2   misho     939:            wasblank = false;
1.1       misho     940:            nargc++;
                    941:        }
                    942:     }
                    943:     /* If we can't find the editor in the user's PATH, give up. */
                    944:     cp = strtok(editor, " \t");
                    945:     if (cp == NULL ||
                    946:        find_path(cp, &editor_path, NULL, getenv("PATH"), 0) != FOUND) {
                    947:        efree(editor);
1.1.1.2   misho     948:        debug_return_str(NULL);
1.1       misho     949:     }
                    950:     nargv = (char **) emalloc2(nargc + 1 + nfiles + 1, sizeof(char *));
                    951:     for (ac = 0; cp != NULL && ac < nargc; ac++) {
                    952:        nargv[ac] = cp;
                    953:        cp = strtok(NULL, " \t");
                    954:     }
                    955:     nargv[ac++] = "--";
                    956:     for (i = 0; i < nfiles; )
                    957:        nargv[ac++] = files[i++];
                    958:     nargv[ac] = NULL;
                    959: 
                    960:     *argv_out = nargv;
1.1.1.2   misho     961:     debug_return_str(editor_path);
1.1       misho     962: }
                    963: 
                    964: /*
                    965:  * Determine which editor to use.  We don't need to worry about restricting
                    966:  * this to a "safe" editor since it runs with the uid of the invoking user,
                    967:  * not the runas (privileged) user.
                    968:  */
                    969: static char *
                    970: find_editor(int nfiles, char **files, char ***argv_out)
                    971: {
1.1.1.4   misho     972:     const char *cp, *ep, *editor;
                    973:     char *editor_path = NULL, **ev, *ev0[4];
                    974:     size_t len;
1.1.1.2   misho     975:     debug_decl(find_editor, SUDO_DEBUG_PLUGIN)
1.1       misho     976: 
                    977:     /*
                    978:      * If any of SUDO_EDITOR, VISUAL or EDITOR are set, choose the first one.
                    979:      */
                    980:     ev0[0] = "SUDO_EDITOR";
                    981:     ev0[1] = "VISUAL";
                    982:     ev0[2] = "EDITOR";
                    983:     ev0[3] = NULL;
1.1.1.4   misho     984:     for (ev = ev0; editor_path == NULL && *ev != NULL; ev++) {
1.1       misho     985:        if ((editor = getenv(*ev)) != NULL && *editor != '\0') {
1.1.1.4   misho     986:            editor_path = resolve_editor(editor, strlen(editor), nfiles,
                    987:                files, argv_out);
1.1       misho     988:        }
                    989:     }
                    990:     if (editor_path == NULL) {
1.1.1.4   misho     991:        /* def_editor could be a path, split it up, avoiding strtok() */
                    992:        cp = editor = def_editor;
                    993:        do {
                    994:            if ((ep = strchr(cp, ':')) != NULL)
                    995:                len = ep - cp;
                    996:            else
                    997:                len = strlen(cp);
                    998:            editor_path = resolve_editor(cp, len, nfiles, files, argv_out);
                    999:            cp = ep + 1;
                   1000:        } while (ep != NULL && editor_path == NULL);
1.1       misho    1001:     }
                   1002:     if (!editor_path) {
1.1.1.4   misho    1003:        audit_failure(NewArgv, N_("%s: command not found"), editor);
1.1       misho    1004:        warningx(_("%s: command not found"), editor);
                   1005:     }
1.1.1.2   misho    1006:     debug_return_str(editor_path);
1.1       misho    1007: }
                   1008: 
                   1009: #ifdef USE_ADMIN_FLAG
                   1010: static void
                   1011: create_admin_success_flag(void)
                   1012: {
                   1013:     struct stat statbuf;
                   1014:     char flagfile[PATH_MAX];
                   1015:     int fd, n;
1.1.1.2   misho    1016:     debug_decl(create_admin_success_flag, SUDO_DEBUG_PLUGIN)
1.1       misho    1017: 
                   1018:     /* Check whether the user is in the admin group. */
                   1019:     if (!user_in_group(sudo_user.pw, "admin"))
1.1.1.2   misho    1020:        debug_return;
1.1       misho    1021: 
                   1022:     /* Build path to flag file. */
                   1023:     n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful",
                   1024:        user_dir);
                   1025:     if (n <= 0 || n >= sizeof(flagfile))
1.1.1.2   misho    1026:        debug_return;
1.1       misho    1027: 
                   1028:     /* Create admin flag file if it doesn't already exist. */
                   1029:     set_perms(PERM_USER);
                   1030:     if (stat(flagfile, &statbuf) != 0) {
                   1031:        fd = open(flagfile, O_CREAT|O_WRONLY|O_EXCL, 0644);
                   1032:        close(fd);
                   1033:     }
                   1034:     restore_perms();
1.1.1.2   misho    1035:     debug_return;
1.1       misho    1036: }
                   1037: #else /* !USE_ADMIN_FLAG */
                   1038: static void
                   1039: create_admin_success_flag(void)
                   1040: {
                   1041:     /* STUB */
                   1042: }
                   1043: #endif /* USE_ADMIN_FLAG */
                   1044: 
1.1.1.4   misho    1045: static bool
                   1046: tty_present(void)
1.1.1.2   misho    1047: {
1.1.1.4   misho    1048: #if defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV) || defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV) || defined(HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV) || defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || defined(HAVE_PSTAT_GETPROC) || defined(__linux__)
                   1049:     return user_ttypath != NULL;
                   1050: #else
                   1051:     int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY);
                   1052:     if (fd != -1)
                   1053:        close(fd);
                   1054:     return fd != -1;
                   1055: #endif
1.1.1.2   misho    1056: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>