File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / policy.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:12:54 2014 UTC (10 years, 1 month ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_10p3_0, v1_8_10p3, HEAD
sudo v 1.8.10p3

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

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