Annotation of embedaddon/sudo/plugins/sudoers/policy.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2010-2013 Todd C. Miller <Todd.Miller@courtesan.com>
                      3:  *
                      4:  * Permission to use, copy, modify, and distribute this software for any
                      5:  * purpose with or without fee is hereby granted, provided that the above
                      6:  * copyright notice and this permission notice appear in all copies.
                      7:  *
                      8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                      9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     15:  */
                     16: 
                     17: #include <config.h>
                     18: 
                     19: #include <sys/types.h>
                     20: #include <sys/stat.h>
                     21: #include <netinet/in.h>
                     22: #include <stdio.h>
                     23: #ifdef STDC_HEADERS
                     24: # include <stdlib.h>
                     25: # include <stddef.h>
                     26: #else
                     27: # ifdef HAVE_STDLIB_H
                     28: #  include <stdlib.h>
                     29: # endif
                     30: #endif /* STDC_HEADERS */
                     31: #ifdef HAVE_STRING_H
                     32: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
                     33: #  include <memory.h>
                     34: # endif
                     35: # include <string.h>
                     36: #endif /* HAVE_STRING_H */
                     37: #ifdef HAVE_STRINGS_H
                     38: # include <strings.h>
                     39: #endif /* HAVE_STRINGS_H */
                     40: #ifdef HAVE_UNISTD_H
                     41: # include <unistd.h>
                     42: #endif /* HAVE_UNISTD_H */
                     43: #include <errno.h>
                     44: #include <grp.h>
                     45: #include <pwd.h>
                     46: 
                     47: #include "sudoers.h"
                     48: #include "sudoers_version.h"
                     49: #include "interfaces.h"
                     50: 
                     51: /*
                     52:  * Info passed in from the sudo front-end.
                     53:  */
                     54: struct sudoers_policy_open_info {
                     55:     char * const *settings;
                     56:     char * const *user_info;
                     57:     char * const *plugin_args;
                     58: };
                     59: 
                     60: /*
                     61:  * Command execution args to be filled in: argv, envp and command info.
                     62:  */
                     63: struct sudoers_exec_args {
                     64:     char ***argv;
                     65:     char ***envp;
                     66:     char ***info;
                     67: };
                     68: 
                     69: static int sudo_version;
                     70: static const char *interfaces_string;
                     71: sudo_conv_t sudo_conv;
                     72: const char *path_ldap_conf = _PATH_LDAP_CONF;
                     73: const char *path_ldap_secret = _PATH_LDAP_SECRET;
                     74: 
                     75: extern __dso_public struct policy_plugin sudoers_policy;
                     76: 
                     77: #ifdef HAVE_BSD_AUTH_H
                     78: extern char *login_style;
                     79: #endif /* HAVE_BSD_AUTH_H */
                     80: 
                     81: /*
                     82:  * Deserialize args, settings and user_info arrays.
                     83:  * Fills in struct sudo_user and other common sudoers state.
                     84:  */
                     85: int
                     86: sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group)
                     87: {
                     88:     struct sudoers_policy_open_info *info = v;
                     89:     char * const *cur;
                     90:     const char *p, *groups = NULL;
                     91:     const char *debug_flags = NULL;
                     92:     int flags = 0;
                     93:     debug_decl(sudoers_policy_deserialize_info, SUDO_DEBUG_PLUGIN)
                     94: 
                     95: #define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0)
                     96: 
                     97:     /* Parse sudo.conf plugin args. */
                     98:     if (info->plugin_args != NULL) {
                     99:        for (cur = info->plugin_args; *cur != NULL; cur++) {
                    100:            if (MATCHES(*cur, "sudoers_file=")) {
                    101:                sudoers_file = *cur + sizeof("sudoers_file=") - 1;
                    102:                continue;
                    103:            }
                    104:            if (MATCHES(*cur, "sudoers_uid=")) {
                    105:                sudoers_uid = (uid_t) atoi(*cur + sizeof("sudoers_uid=") - 1);
                    106:                continue;
                    107:            }
                    108:            if (MATCHES(*cur, "sudoers_gid=")) {
                    109:                sudoers_gid = (gid_t) atoi(*cur + sizeof("sudoers_gid=") - 1);
                    110:                continue;
                    111:            }
                    112:            if (MATCHES(*cur, "sudoers_mode=")) {
                    113:                sudoers_mode = (mode_t) strtol(*cur + sizeof("sudoers_mode=") - 1,
                    114:                    NULL, 8);
                    115:                continue;
                    116:            }
                    117:            if (MATCHES(*cur, "ldap_conf=")) {
                    118:                path_ldap_conf = *cur + sizeof("ldap_conf=") - 1;
                    119:                continue;
                    120:            }
                    121:            if (MATCHES(*cur, "ldap_secret=")) {
                    122:                path_ldap_secret = *cur + sizeof("ldap_secret=") - 1;
                    123:                continue;
                    124:            }
                    125:        }
                    126:     }
                    127: 
                    128:     /* Parse command line settings. */
                    129:     user_closefrom = -1;
                    130:     sudo_user.max_groups = -1;
                    131:     for (cur = info->settings; *cur != NULL; cur++) {
                    132:        if (MATCHES(*cur, "closefrom=")) {
                    133:            user_closefrom = atoi(*cur + sizeof("closefrom=") - 1);
                    134:            continue;
                    135:        }
                    136:        if (MATCHES(*cur, "debug_flags=")) {
                    137:            debug_flags = *cur + sizeof("debug_flags=") - 1;
                    138:            continue;
                    139:        }
                    140:        if (MATCHES(*cur, "runas_user=")) {
                    141:            *runas_user = *cur + sizeof("runas_user=") - 1;
                    142:            sudo_user.flags |= RUNAS_USER_SPECIFIED;
                    143:            continue;
                    144:        }
                    145:        if (MATCHES(*cur, "runas_group=")) {
                    146:            *runas_group = *cur + sizeof("runas_group=") - 1;
                    147:            sudo_user.flags |= RUNAS_GROUP_SPECIFIED;
                    148:            continue;
                    149:        }
                    150:        if (MATCHES(*cur, "prompt=")) {
                    151:            user_prompt = *cur + sizeof("prompt=") - 1;
                    152:            def_passprompt_override = true;
                    153:            continue;
                    154:        }
                    155:        if (MATCHES(*cur, "set_home=")) {
                    156:            if (atobool(*cur + sizeof("set_home=") - 1) == true)
                    157:                SET(flags, MODE_RESET_HOME);
                    158:            continue;
                    159:        }
                    160:        if (MATCHES(*cur, "preserve_environment=")) {
                    161:            if (atobool(*cur + sizeof("preserve_environment=") - 1) == true)
                    162:                SET(flags, MODE_PRESERVE_ENV);
                    163:            continue;
                    164:        }
                    165:        if (MATCHES(*cur, "run_shell=")) {
                    166:            if (atobool(*cur + sizeof("run_shell=") - 1) == true)
                    167:                SET(flags, MODE_SHELL);
                    168:            continue;
                    169:        }
                    170:        if (MATCHES(*cur, "login_shell=")) {
                    171:            if (atobool(*cur + sizeof("login_shell=") - 1) == true) {
                    172:                SET(flags, MODE_LOGIN_SHELL);
                    173:                def_env_reset = true;
                    174:            }
                    175:            continue;
                    176:        }
                    177:        if (MATCHES(*cur, "implied_shell=")) {
                    178:            if (atobool(*cur + sizeof("implied_shell=") - 1) == true)
                    179:                SET(flags, MODE_IMPLIED_SHELL);
                    180:            continue;
                    181:        }
                    182:        if (MATCHES(*cur, "preserve_groups=")) {
                    183:            if (atobool(*cur + sizeof("preserve_groups=") - 1) == true)
                    184:                SET(flags, MODE_PRESERVE_GROUPS);
                    185:            continue;
                    186:        }
                    187:        if (MATCHES(*cur, "ignore_ticket=")) {
                    188:            if (atobool(*cur + sizeof("ignore_ticket=") - 1) == true)
                    189:                SET(flags, MODE_IGNORE_TICKET);
                    190:            continue;
                    191:        }
                    192:        if (MATCHES(*cur, "noninteractive=")) {
                    193:            if (atobool(*cur + sizeof("noninteractive=") - 1) == true)
                    194:                SET(flags, MODE_NONINTERACTIVE);
                    195:            continue;
                    196:        }
                    197:        if (MATCHES(*cur, "sudoedit=")) {
                    198:            if (atobool(*cur + sizeof("sudoedit=") - 1) == true)
                    199:                SET(flags, MODE_EDIT);
                    200:            continue;
                    201:        }
                    202:        if (MATCHES(*cur, "login_class=")) {
                    203:            login_class = *cur + sizeof("login_class=") - 1;
                    204:            def_use_loginclass = true;
                    205:            continue;
                    206:        }
                    207: #ifdef HAVE_PRIV_SET
                    208:        if (MATCHES(*cur, "runas_privs=")) {
                    209:            def_privs = *cur + sizeof("runas_privs=") - 1;
                    210:            continue;
                    211:        }
                    212:        if (MATCHES(*cur, "runas_limitprivs=")) {
                    213:            def_limitprivs = *cur + sizeof("runas_limitprivs=") - 1;
                    214:            continue;
                    215:        }
                    216: #endif /* HAVE_PRIV_SET */
                    217: #ifdef HAVE_SELINUX
                    218:        if (MATCHES(*cur, "selinux_role=")) {
                    219:            user_role = *cur + sizeof("selinux_role=") - 1;
                    220:            continue;
                    221:        }
                    222:        if (MATCHES(*cur, "selinux_type=")) {
                    223:            user_type = *cur + sizeof("selinux_type=") - 1;
                    224:            continue;
                    225:        }
                    226: #endif /* HAVE_SELINUX */
                    227: #ifdef HAVE_BSD_AUTH_H
                    228:        if (MATCHES(*cur, "bsdauth_type=")) {
                    229:            login_style = *cur + sizeof("bsdauth_type=") - 1;
                    230:            continue;
                    231:        }
                    232: #endif /* HAVE_BSD_AUTH_H */
                    233: #if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME)
                    234:        if (MATCHES(*cur, "progname=")) {
                    235:            setprogname(*cur + sizeof("progname=") - 1);
                    236:            continue;
                    237:        }
                    238: #endif
                    239:        if (MATCHES(*cur, "network_addrs=")) {
                    240:            interfaces_string = *cur + sizeof("network_addrs=") - 1;
                    241:            set_interfaces(interfaces_string);
                    242:            continue;
                    243:        }
                    244:        if (MATCHES(*cur, "max_groups=")) {
                    245:            sudo_user.max_groups = atoi(*cur + sizeof("max_groups=") - 1);
                    246:            continue;
                    247:        }
                    248:     }
                    249: 
                    250:     for (cur = info->user_info; *cur != NULL; cur++) {
                    251:        if (MATCHES(*cur, "user=")) {
                    252:            user_name = estrdup(*cur + sizeof("user=") - 1);
                    253:            continue;
                    254:        }
                    255:        if (MATCHES(*cur, "uid=")) {
                    256:            user_uid = (uid_t) atoi(*cur + sizeof("uid=") - 1);
                    257:            continue;
                    258:        }
                    259:        if (MATCHES(*cur, "gid=")) {
                    260:            p = *cur + sizeof("gid=") - 1;
                    261:            user_gid = (gid_t) atoi(p);
                    262:            continue;
                    263:        }
                    264:        if (MATCHES(*cur, "groups=")) {
                    265:            groups = *cur + sizeof("groups=") - 1;
                    266:            continue;
                    267:        }
                    268:        if (MATCHES(*cur, "cwd=")) {
                    269:            user_cwd = estrdup(*cur + sizeof("cwd=") - 1);
                    270:            continue;
                    271:        }
                    272:        if (MATCHES(*cur, "tty=")) {
                    273:            user_tty = user_ttypath = estrdup(*cur + sizeof("tty=") - 1);
                    274:            if (strncmp(user_tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
                    275:                user_tty += sizeof(_PATH_DEV) - 1;
                    276:            continue;
                    277:        }
                    278:        if (MATCHES(*cur, "host=")) {
                    279:            user_host = user_shost = estrdup(*cur + sizeof("host=") - 1);
                    280:            if ((p = strchr(user_host, '.')))
                    281:                user_shost = estrndup(user_host, (size_t)(p - user_host));
                    282:            continue;
                    283:        }
                    284:        if (MATCHES(*cur, "lines=")) {
                    285:            sudo_user.lines = atoi(*cur + sizeof("lines=") - 1);
                    286:            continue;
                    287:        }
                    288:        if (MATCHES(*cur, "cols=")) {
                    289:            sudo_user.cols = atoi(*cur + sizeof("cols=") - 1);
                    290:            continue;
                    291:        }
                    292:        if (MATCHES(*cur, "sid=")) {
                    293:            sudo_user.sid = atoi(*cur + sizeof("sid=") - 1);
                    294:            continue;
                    295:        }
                    296:     }
                    297:     if (user_cwd == NULL)
                    298:        user_cwd = "unknown";
                    299:     if (user_tty == NULL)
                    300:        user_tty = "unknown"; /* user_ttypath remains NULL */
                    301: 
                    302:     if (groups != NULL && groups[0] != '\0') {
                    303:        const char *cp;
                    304:        GETGROUPS_T *gids;
                    305:        int ngids;
                    306: 
                    307:        /* Count number of groups, including passwd gid. */
                    308:        ngids = 2;
                    309:        for (cp = groups; *cp != '\0'; cp++) {
                    310:            if (*cp == ',')
                    311:                ngids++;
                    312:        }
                    313: 
                    314:        /* The first gid in the list is the passwd group gid. */
                    315:        gids = emalloc2(ngids, sizeof(GETGROUPS_T));
                    316:        gids[0] = user_gid;
                    317:        ngids = 1;
                    318:        cp = groups;
                    319:        for (;;) {
                    320:            gids[ngids] = atoi(cp);
                    321:            if (gids[0] != gids[ngids])
                    322:                ngids++;
                    323:            cp = strchr(cp, ',');
                    324:            if (cp == NULL)
                    325:                break;
                    326:            cp++; /* skip over comma */
                    327:        }
                    328:        user_gids = gids;
                    329:        user_ngids = ngids;
                    330:     }
                    331: 
                    332:     /* Stash initial umask for later use. */
                    333:     user_umask = umask(SUDO_UMASK);
                    334:     umask(user_umask);
                    335: 
                    336:     /* Setup debugging if indicated. */
                    337:     if (debug_flags != NULL) {
                    338:        sudo_debug_init(NULL, debug_flags);
                    339:        for (cur = info->settings; *cur != NULL; cur++)
                    340:            sudo_debug_printf(SUDO_DEBUG_INFO, "settings: %s", *cur);
                    341:        for (cur = info->user_info; *cur != NULL; cur++)
                    342:            sudo_debug_printf(SUDO_DEBUG_INFO, "user_info: %s", *cur);
                    343:     }
                    344: 
                    345: #undef MATCHES
                    346:     debug_return_int(flags);
                    347: }
                    348: 
                    349: /*
                    350:  * Setup the execution environment.
                    351:  * Builds up the command_info list and sets argv and envp.
                    352:  * Returns 1 on success and -1 on error.
                    353:  */
                    354: int
                    355: sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask,
                    356:     char *iolog_path, void *v)
                    357: {
                    358:     struct sudoers_exec_args *exec_args = v;
                    359:     char **command_info;
                    360:     int info_len = 0;
                    361:     debug_decl(sudoers_policy_exec_setup, SUDO_DEBUG_PLUGIN)
                    362: 
                    363:     /* Increase the length of command_info as needed, it is *not* checked. */
                    364:     command_info = ecalloc(32, sizeof(char **));
                    365: 
                    366:     command_info[info_len++] = fmt_string("command", safe_cmnd);
                    367:     if (def_log_input || def_log_output) {
                    368:        if (iolog_path)
                    369:            command_info[info_len++] = iolog_path;
                    370:        if (def_log_input) {
                    371:            command_info[info_len++] = estrdup("iolog_stdin=true");
                    372:            command_info[info_len++] = estrdup("iolog_ttyin=true");
                    373:        }
                    374:        if (def_log_output) {
                    375:            command_info[info_len++] = estrdup("iolog_stdout=true");
                    376:            command_info[info_len++] = estrdup("iolog_stderr=true");
                    377:            command_info[info_len++] = estrdup("iolog_ttyout=true");
                    378:        }
                    379:        if (def_compress_io) {
                    380:            command_info[info_len++] = estrdup("iolog_compress=true");
                    381:        }
                    382:        if (def_maxseq) {
                    383:            easprintf(&command_info[info_len++], "maxseq=%u", def_maxseq);
                    384:        }
                    385:     }
                    386:     if (ISSET(sudo_mode, MODE_EDIT))
                    387:        command_info[info_len++] = estrdup("sudoedit=true");
                    388:     if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
                    389:        /* Set cwd to run user's homedir. */
                    390:        command_info[info_len++] = fmt_string("cwd", runas_pw->pw_dir);
                    391:     }
                    392:     if (def_stay_setuid) {
                    393:        easprintf(&command_info[info_len++], "runas_uid=%u",
                    394:            (unsigned int)user_uid);
                    395:        easprintf(&command_info[info_len++], "runas_gid=%u",
                    396:            (unsigned int)user_gid);
                    397:        easprintf(&command_info[info_len++], "runas_euid=%u",
                    398:            (unsigned int)runas_pw->pw_uid);
                    399:        easprintf(&command_info[info_len++], "runas_egid=%u",
                    400:            runas_gr ? (unsigned int)runas_gr->gr_gid :
                    401:            (unsigned int)runas_pw->pw_gid);
                    402:     } else {
                    403:        easprintf(&command_info[info_len++], "runas_uid=%u",
                    404:            (unsigned int)runas_pw->pw_uid);
                    405:        easprintf(&command_info[info_len++], "runas_gid=%u",
                    406:            runas_gr ? (unsigned int)runas_gr->gr_gid :
                    407:            (unsigned int)runas_pw->pw_gid);
                    408:     }
                    409:     if (def_preserve_groups) {
                    410:        command_info[info_len++] = "preserve_groups=true";
                    411:     } else {
                    412:        int i, len;
                    413:        gid_t egid;
                    414:        size_t glsize;
                    415:        char *cp, *gid_list;
                    416:        struct group_list *grlist = sudo_get_grlist(runas_pw);
                    417: 
                    418:        /* We reserve an extra spot in the list for the effective gid. */
                    419:        glsize = sizeof("runas_groups=") - 1 +
                    420:            ((grlist->ngids + 1) * (MAX_UID_T_LEN + 1));
                    421:        gid_list = emalloc(glsize);
                    422:        memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1);
                    423:        cp = gid_list + sizeof("runas_groups=") - 1;
                    424: 
                    425:        /* On BSD systems the effective gid is the first group in the list. */
                    426:        egid = runas_gr ? (unsigned int)runas_gr->gr_gid :
                    427:            (unsigned int)runas_pw->pw_gid;
                    428:        len = snprintf(cp, glsize - (cp - gid_list), "%u", egid);
                    429:        if (len < 0 || len >= glsize - (cp - gid_list))
                    430:            fatalx(_("internal error, %s overflow"), "runas_groups");
                    431:        cp += len;
                    432:        for (i = 0; i < grlist->ngids; i++) {
                    433:            if (grlist->gids[i] != egid) {
                    434:                len = snprintf(cp, glsize - (cp - gid_list), ",%u",
                    435:                     (unsigned int) grlist->gids[i]);
                    436:                if (len < 0 || len >= glsize - (cp - gid_list))
                    437:                    fatalx(_("internal error, %s overflow"), "runas_groups");
                    438:                cp += len;
                    439:            }
                    440:        }
                    441:        command_info[info_len++] = gid_list;
                    442:        sudo_grlist_delref(grlist);
                    443:     }
                    444:     if (def_closefrom >= 0)
                    445:        easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom);
                    446:     if (def_noexec)
                    447:        command_info[info_len++] = estrdup("noexec=true");
                    448:     if (def_exec_background)
                    449:        command_info[info_len++] = estrdup("exec_background=true");
                    450:     if (def_set_utmp)
                    451:        command_info[info_len++] = estrdup("set_utmp=true");
                    452:     if (def_use_pty)
                    453:        command_info[info_len++] = estrdup("use_pty=true");
                    454:     if (def_utmp_runas)
                    455:        command_info[info_len++] = fmt_string("utmp_user", runas_pw->pw_name);
                    456:     if (cmnd_umask != 0777)
                    457:        easprintf(&command_info[info_len++], "umask=0%o", (unsigned int)cmnd_umask);
                    458: #ifdef HAVE_LOGIN_CAP_H
                    459:     if (def_use_loginclass)
                    460:        command_info[info_len++] = fmt_string("login_class", login_class);
                    461: #endif /* HAVE_LOGIN_CAP_H */
                    462: #ifdef HAVE_SELINUX
                    463:     if (user_role != NULL)
                    464:        command_info[info_len++] = fmt_string("selinux_role", user_role);
                    465:     if (user_type != NULL)
                    466:        command_info[info_len++] = fmt_string("selinux_type", user_type);
                    467: #endif /* HAVE_SELINUX */
                    468: #ifdef HAVE_PRIV_SET
                    469:     if (runas_privs != NULL)
                    470:        command_info[info_len++] = fmt_string("runas_privs", runas_privs);
                    471:     if (runas_limitprivs != NULL)
                    472:        command_info[info_len++] = fmt_string("runas_limitprivs", runas_limitprivs);
                    473: #endif /* HAVE_SELINUX */
                    474: 
                    475:     /* Fill in exec environment info */
                    476:     *(exec_args->argv) = argv;
                    477:     *(exec_args->envp) = envp;
                    478:     *(exec_args->info) = command_info;
                    479: 
                    480:     debug_return_bool(true);
                    481: }
                    482: 
                    483: static int
                    484: sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
                    485:     sudo_printf_t plugin_printf, char * const settings[],
                    486:     char * const user_info[], char * const envp[], char * const args[])
                    487: {
                    488:     struct sudoers_policy_open_info info;
                    489:     debug_decl(sudoers_policy_open, SUDO_DEBUG_PLUGIN)
                    490: 
                    491:     sudo_version = version;
                    492:     sudo_conv = conversation;
                    493:     sudo_printf = plugin_printf;
                    494: 
                    495:     /* Plugin args are only specified for API version 1.2 and higher. */
                    496:     if (sudo_version < SUDO_API_MKVERSION(1, 2))
                    497:        args = NULL;
                    498: 
                    499:     if (fatal_setjmp() != 0) {
                    500:        /* called via fatal(), fatalx() or log_fatal() */
                    501:        rewind_perms();
                    502:        fatal_disable_setjmp();
                    503:        debug_return_bool(-1);
                    504:     }
                    505: 
                    506:     /* Call the sudoers init function. */
                    507:     info.settings = settings;
                    508:     info.user_info = user_info;
                    509:     info.plugin_args = args;
                    510:     debug_return_bool(sudoers_policy_init(&info, envp));
                    511: }
                    512: 
                    513: static void
                    514: sudoers_policy_close(int exit_status, int error_code)
                    515: {
                    516:     debug_decl(sudoers_policy_close, SUDO_DEBUG_PLUGIN)
                    517: 
                    518:     if (fatal_setjmp() != 0) {
                    519:        /* called via fatal(), fatalx() or log_fatal() */
                    520:        fatal_disable_setjmp();
                    521:        debug_return;
                    522:     }
                    523: 
                    524:     /* We do not currently log the exit status. */
                    525:     if (error_code) {
                    526:        errno = error_code;
                    527:        warning(_("unable to execute %s"), safe_cmnd);
                    528:     }
                    529: 
                    530:     /* Close the session we opened in sudoers_policy_init_session(). */
                    531:     if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT))
                    532:        (void)sudo_auth_end_session(runas_pw);
                    533: 
                    534:     /* Free remaining references to password and group entries. */
                    535:     /* XXX - move cleanup to function in sudoers.c */
                    536:     sudo_pw_delref(sudo_user.pw);
                    537:     sudo_user.pw = NULL;
                    538:     sudo_pw_delref(runas_pw);
                    539:     runas_pw = NULL;
                    540:     if (runas_gr != NULL) {
                    541:        sudo_gr_delref(runas_gr);
                    542:        runas_gr = NULL;
                    543:     }
                    544:     if (user_group_list != NULL) {
                    545:        sudo_grlist_delref(user_group_list);
                    546:        user_group_list = NULL;
                    547:     }
                    548:     efree(user_gids);
                    549:     user_gids = NULL;
                    550: 
                    551:     debug_return;
                    552: }
                    553: 
                    554: /*
                    555:  * The init_session function is called before executing the command
                    556:  * and before uid/gid changes occur.
                    557:  * Returns 1 on success, 0 on failure and -1 on error.
                    558:  */
                    559: static int
                    560: sudoers_policy_init_session(struct passwd *pwd, char **user_env[])
                    561: {
                    562:     debug_decl(sudoers_policy_init_session, SUDO_DEBUG_PLUGIN)
                    563: 
                    564:     /* user_env is only specified for API version 1.2 and higher. */
                    565:     if (sudo_version < SUDO_API_MKVERSION(1, 2))
                    566:        user_env = NULL;
                    567: 
                    568:     if (fatal_setjmp() != 0) {
                    569:        /* called via fatal(), fatalx() or log_fatal() */
                    570:        fatal_disable_setjmp();
                    571:        debug_return_bool(-1);
                    572:     }
                    573: 
                    574:     debug_return_bool(sudo_auth_begin_session(pwd, user_env));
                    575: }
                    576: 
                    577: static int
                    578: sudoers_policy_check(int argc, char * const argv[], char *env_add[],
                    579:     char **command_infop[], char **argv_out[], char **user_env_out[])
                    580: {
                    581:     struct sudoers_exec_args exec_args;
                    582:     int rval;
                    583:     debug_decl(sudoers_policy_check, SUDO_DEBUG_PLUGIN)
                    584: 
                    585:     if (!ISSET(sudo_mode, MODE_EDIT))
                    586:        SET(sudo_mode, MODE_RUN);
                    587: 
                    588:     exec_args.argv = argv_out;
                    589:     exec_args.envp = user_env_out;
                    590:     exec_args.info = command_infop;
                    591: 
                    592:     rval = sudoers_policy_main(argc, argv, 0, env_add, &exec_args);
                    593:     if (rval == true && sudo_version >= SUDO_API_MKVERSION(1, 3)) {
                    594:        /* Unset close function if we don't need it to avoid extra process. */
                    595:        if (!def_log_input && !def_log_output && !def_use_pty &&
                    596:            !sudo_auth_needs_end_session())
                    597:            sudoers_policy.close = NULL;
                    598:     }
                    599:     debug_return_bool(rval);
                    600: }
                    601: 
                    602: static int
                    603: sudoers_policy_validate(void)
                    604: {
                    605:     debug_decl(sudoers_policy_validate, SUDO_DEBUG_PLUGIN)
                    606: 
                    607:     user_cmnd = "validate";
                    608:     SET(sudo_mode, MODE_VALIDATE);
                    609: 
                    610:     debug_return_bool(sudoers_policy_main(0, NULL, I_VERIFYPW, NULL, NULL));
                    611: }
                    612: 
                    613: static void
                    614: sudoers_policy_invalidate(int remove)
                    615: {
                    616:     debug_decl(sudoers_policy_invalidate, SUDO_DEBUG_PLUGIN)
                    617: 
                    618:     user_cmnd = "kill";
                    619:     if (fatal_setjmp() == 0) {
                    620:        remove_timestamp(remove);
                    621:        sudoers_cleanup();
                    622:     }
                    623:     fatal_disable_setjmp();
                    624: 
                    625:     debug_return;
                    626: }
                    627: 
                    628: static int
                    629: sudoers_policy_list(int argc, char * const argv[], int verbose,
                    630:     const char *list_user)
                    631: {
                    632:     int rval;
                    633:     debug_decl(sudoers_policy_list, SUDO_DEBUG_PLUGIN)
                    634: 
                    635:     user_cmnd = "list";
                    636:     if (argc)
                    637:        SET(sudo_mode, MODE_CHECK);
                    638:     else
                    639:        SET(sudo_mode, MODE_LIST);
                    640:     if (verbose)
                    641:        long_list = 1;
                    642:     if (list_user) {
                    643:        list_pw = sudo_getpwnam(list_user);
                    644:        if (list_pw == NULL) {
                    645:            warningx(_("unknown user: %s"), list_user);
                    646:            debug_return_bool(-1);
                    647:        }
                    648:     }
                    649:     rval = sudoers_policy_main(argc, argv, I_LISTPW, NULL, NULL);
                    650:     if (list_user) {
                    651:        sudo_pw_delref(list_pw);
                    652:        list_pw = NULL;
                    653:     }
                    654: 
                    655:     debug_return_bool(rval);
                    656: }
                    657: 
                    658: static int
                    659: sudoers_policy_version(int verbose)
                    660: {
                    661:     debug_decl(sudoers_policy_version, SUDO_DEBUG_PLUGIN)
                    662: 
                    663:     if (fatal_setjmp() != 0) {
                    664:        /* error recovery via fatal(), fatalx() or log_fatal() */
                    665:        fatal_disable_setjmp();
                    666:        debug_return_bool(-1);
                    667:     }
                    668: 
                    669:     sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers policy plugin version %s\n"),
                    670:        PACKAGE_VERSION);
                    671:     sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers file grammar version %d\n"),
                    672:        SUDOERS_GRAMMAR_VERSION);
                    673: 
                    674:     if (verbose) {
                    675:        sudo_printf(SUDO_CONV_INFO_MSG, _("\nSudoers path: %s\n"), sudoers_file);
                    676: #ifdef HAVE_LDAP
                    677: # ifdef _PATH_NSSWITCH_CONF
                    678:        sudo_printf(SUDO_CONV_INFO_MSG, _("nsswitch path: %s\n"), _PATH_NSSWITCH_CONF);
                    679: # endif
                    680:        sudo_printf(SUDO_CONV_INFO_MSG, _("ldap.conf path: %s\n"), path_ldap_conf);
                    681:        sudo_printf(SUDO_CONV_INFO_MSG, _("ldap.secret path: %s\n"), path_ldap_secret);
                    682: #endif
                    683:        dump_auth_methods();
                    684:        dump_defaults();
                    685:        sudo_printf(SUDO_CONV_INFO_MSG, "\n");
                    686:        if (interfaces_string != NULL) {
                    687:            dump_interfaces(interfaces_string);
                    688:            sudo_printf(SUDO_CONV_INFO_MSG, "\n");
                    689:        }
                    690:     }
                    691:     debug_return_bool(true);
                    692: }
                    693: 
                    694: static void
                    695: sudoers_policy_register_hooks(int version, int (*register_hook)(struct sudo_hook *hook))
                    696: {
                    697:     struct sudo_hook hook;
                    698: 
                    699:     memset(&hook, 0, sizeof(hook));
                    700:     hook.hook_version = SUDO_HOOK_VERSION;
                    701: 
                    702:     hook.hook_type = SUDO_HOOK_SETENV;
                    703:     hook.hook_fn = sudoers_hook_setenv;
                    704:     register_hook(&hook);
                    705: 
                    706:     hook.hook_type = SUDO_HOOK_UNSETENV;
                    707:     hook.hook_fn = sudoers_hook_unsetenv;
                    708:     register_hook(&hook);
                    709: 
                    710:     hook.hook_type = SUDO_HOOK_GETENV;
                    711:     hook.hook_fn = sudoers_hook_getenv;
                    712:     register_hook(&hook);
                    713: 
                    714:     hook.hook_type = SUDO_HOOK_PUTENV;
                    715:     hook.hook_fn = sudoers_hook_putenv;
                    716:     register_hook(&hook);
                    717: }
                    718: 
                    719: __dso_public struct policy_plugin sudoers_policy = {
                    720:     SUDO_POLICY_PLUGIN,
                    721:     SUDO_API_VERSION,
                    722:     sudoers_policy_open,
                    723:     sudoers_policy_close,
                    724:     sudoers_policy_version,
                    725:     sudoers_policy_check,
                    726:     sudoers_policy_list,
                    727:     sudoers_policy_validate,
                    728:     sudoers_policy_invalidate,
                    729:     sudoers_policy_init_session,
                    730:     sudoers_policy_register_hooks
                    731: };

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