File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / defaults.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 07:56:34 2013 UTC (10 years, 10 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_8p0, v1_8_8, HEAD
v 1.8.8

    1: /*
    2:  * Copyright (c) 1999-2005, 2007-2013
    3:  *	Todd C. Miller <Todd.Miller@courtesan.com>
    4:  *
    5:  * Permission to use, copy, modify, and distribute this software for any
    6:  * purpose with or without fee is hereby granted, provided that the above
    7:  * copyright notice and this permission notice appear in all copies.
    8:  *
    9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16:  *
   17:  * Sponsored in part by the Defense Advanced Research Projects
   18:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
   19:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
   20:  */
   21: 
   22: #include <config.h>
   23: 
   24: #include <sys/types.h>
   25: #include <stdio.h>
   26: #ifdef STDC_HEADERS
   27: # include <stdlib.h>
   28: # include <stddef.h>
   29: #else
   30: # ifdef HAVE_STDLIB_H
   31: #  include <stdlib.h>
   32: # endif
   33: #endif /* STDC_HEADERS */
   34: #ifdef HAVE_STRING_H
   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 <pwd.h>
   44: #include <ctype.h>
   45: 
   46: #include "sudoers.h"
   47: #include "parse.h"
   48: #include <gram.h>
   49: 
   50: /*
   51:  * For converting between syslog numbers and strings.
   52:  */
   53: struct strmap {
   54:     char *name;
   55:     int num;
   56: };
   57: 
   58: #ifdef LOG_NFACILITIES
   59: static struct strmap facilities[] = {
   60: #ifdef LOG_AUTHPRIV
   61: 	{ "authpriv",	LOG_AUTHPRIV },
   62: #endif
   63: 	{ "auth",	LOG_AUTH },
   64: 	{ "daemon",	LOG_DAEMON },
   65: 	{ "user",	LOG_USER },
   66: 	{ "local0",	LOG_LOCAL0 },
   67: 	{ "local1",	LOG_LOCAL1 },
   68: 	{ "local2",	LOG_LOCAL2 },
   69: 	{ "local3",	LOG_LOCAL3 },
   70: 	{ "local4",	LOG_LOCAL4 },
   71: 	{ "local5",	LOG_LOCAL5 },
   72: 	{ "local6",	LOG_LOCAL6 },
   73: 	{ "local7",	LOG_LOCAL7 },
   74: 	{ NULL,		-1 }
   75: };
   76: #endif /* LOG_NFACILITIES */
   77: 
   78: static struct strmap priorities[] = {
   79: 	{ "alert",	LOG_ALERT },
   80: 	{ "crit",	LOG_CRIT },
   81: 	{ "debug",	LOG_DEBUG },
   82: 	{ "emerg",	LOG_EMERG },
   83: 	{ "err",	LOG_ERR },
   84: 	{ "info",	LOG_INFO },
   85: 	{ "notice",	LOG_NOTICE },
   86: 	{ "warning",	LOG_WARNING },
   87: 	{ NULL,		-1 }
   88: };
   89: 
   90: /*
   91:  * Local prototypes.
   92:  */
   93: static bool store_int(char *, struct sudo_defs_types *, int);
   94: static bool store_list(char *, struct sudo_defs_types *, int);
   95: static bool store_mode(char *, struct sudo_defs_types *, int);
   96: static bool store_str(char *, struct sudo_defs_types *, int);
   97: static bool store_syslogfac(char *, struct sudo_defs_types *, int);
   98: static bool store_syslogpri(char *, struct sudo_defs_types *, int);
   99: static bool store_tuple(char *, struct sudo_defs_types *, int);
  100: static bool store_uint(char *, struct sudo_defs_types *, int);
  101: static bool store_float(char *, struct sudo_defs_types *, int);
  102: static void list_op(char *, size_t, struct sudo_defs_types *, enum list_ops);
  103: static const char *logfac2str(int);
  104: static const char *logpri2str(int);
  105: 
  106: /*
  107:  * Table describing compile-time and run-time options.
  108:  */
  109: #include <def_data.c>
  110: 
  111: /*
  112:  * Print version and configure info.
  113:  */
  114: void
  115: dump_defaults(void)
  116: {
  117:     struct sudo_defs_types *cur;
  118:     struct list_member *item;
  119:     struct def_values *def;
  120:     char *desc;
  121:     debug_decl(dump_defaults, SUDO_DEBUG_DEFAULTS)
  122: 
  123:     for (cur = sudo_defs_table; cur->name; cur++) {
  124: 	if (cur->desc) {
  125: 	    desc = _(cur->desc);
  126: 	    switch (cur->type & T_MASK) {
  127: 		case T_FLAG:
  128: 		    if (cur->sd_un.flag)
  129: 			sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
  130: 		    break;
  131: 		case T_STR:
  132: 		    if (cur->sd_un.str) {
  133: 			sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.str);
  134: 			sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  135: 		    }
  136: 		    break;
  137: 		case T_LOGFAC:
  138: 		    if (cur->sd_un.ival) {
  139: 			sudo_printf(SUDO_CONV_INFO_MSG, desc,
  140: 			    logfac2str(cur->sd_un.ival));
  141: 			sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  142: 		    }
  143: 		    break;
  144: 		case T_LOGPRI:
  145: 		    if (cur->sd_un.ival) {
  146: 			sudo_printf(SUDO_CONV_INFO_MSG, desc,
  147: 			    logpri2str(cur->sd_un.ival));
  148: 			sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  149: 		    }
  150: 		    break;
  151: 		case T_UINT:
  152: 		case T_INT:
  153: 		    sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.ival);
  154: 		    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  155: 		    break;
  156: 		case T_FLOAT:
  157: 		    sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.fval);
  158: 		    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  159: 		    break;
  160: 		case T_MODE:
  161: 		    sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.mode);
  162: 		    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  163: 		    break;
  164: 		case T_LIST:
  165: 		    if (cur->sd_un.list) {
  166: 			sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
  167: 			for (item = cur->sd_un.list; item; item = item->next) {
  168: 			    sudo_printf(SUDO_CONV_INFO_MSG,
  169: 				"\t%s\n", item->value);
  170: 			}
  171: 		    }
  172: 		    break;
  173: 		case T_TUPLE:
  174: 		    for (def = cur->values; def->sval; def++) {
  175: 			if (cur->sd_un.ival == def->ival) {
  176: 			    sudo_printf(SUDO_CONV_INFO_MSG, desc, def->sval);
  177: 			    break;
  178: 			}
  179: 		    }
  180: 		    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  181: 		    break;
  182: 	    }
  183: 	}
  184:     }
  185:     debug_return;
  186: }
  187: 
  188: /*
  189:  * Sets/clears an entry in the defaults structure
  190:  * If a variable that takes a value is used in a boolean
  191:  * context with op == 0, disable that variable.
  192:  * Eg. you may want to turn off logging to a file for some hosts.
  193:  * This is only meaningful for variables that are *optional*.
  194:  */
  195: bool
  196: set_default(char *var, char *val, int op)
  197: {
  198:     struct sudo_defs_types *cur;
  199:     int num;
  200:     debug_decl(set_default, SUDO_DEBUG_DEFAULTS)
  201: 
  202:     for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
  203: 	if (strcmp(var, cur->name) == 0)
  204: 	    break;
  205:     }
  206:     if (!cur->name) {
  207: 	warningx(_("unknown defaults entry `%s'"), var);
  208: 	debug_return_bool(false);
  209:     }
  210: 
  211:     switch (cur->type & T_MASK) {
  212: 	case T_LOGFAC:
  213: 	    if (!store_syslogfac(val, cur, op)) {
  214: 		if (val)
  215: 		    warningx(_("value `%s' is invalid for option `%s'"),
  216: 			val, var);
  217: 		else
  218: 		    warningx(_("no value specified for `%s'"), var);
  219: 		debug_return_bool(false);
  220: 	    }
  221: 	    break;
  222: 	case T_LOGPRI:
  223: 	    if (!store_syslogpri(val, cur, op)) {
  224: 		if (val)
  225: 		    warningx(_("value `%s' is invalid for option `%s'"),
  226: 			val, var);
  227: 		else
  228: 		    warningx(_("no value specified for `%s'"), var);
  229: 		debug_return_bool(false);
  230: 	    }
  231: 	    break;
  232: 	case T_STR:
  233: 	    if (!val) {
  234: 		/* Check for bogus boolean usage or lack of a value. */
  235: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  236: 		    warningx(_("no value specified for `%s'"), var);
  237: 		    debug_return_bool(false);
  238: 		}
  239: 	    }
  240: 	    if (ISSET(cur->type, T_PATH) && val && *val != '/') {
  241: 		warningx(_("values for `%s' must start with a '/'"), var);
  242: 		debug_return_bool(false);
  243: 	    }
  244: 	    if (!store_str(val, cur, op)) {
  245: 		warningx(_("value `%s' is invalid for option `%s'"), val, var);
  246: 		debug_return_bool(false);
  247: 	    }
  248: 	    break;
  249: 	case T_INT:
  250: 	    if (!val) {
  251: 		/* Check for bogus boolean usage or lack of a value. */
  252: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  253: 		    warningx(_("no value specified for `%s'"), var);
  254: 		    debug_return_bool(false);
  255: 		}
  256: 	    }
  257: 	    if (!store_int(val, cur, op)) {
  258: 		warningx(_("value `%s' is invalid for option `%s'"), val, var);
  259: 		debug_return_bool(false);
  260: 	    }
  261: 	    break;
  262: 	case T_UINT:
  263: 	    if (!val) {
  264: 		/* Check for bogus boolean usage or lack of a value. */
  265: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  266: 		    warningx(_("no value specified for `%s'"), var);
  267: 		    debug_return_bool(false);
  268: 		}
  269: 	    }
  270: 	    if (!store_uint(val, cur, op)) {
  271: 		warningx(_("value `%s' is invalid for option `%s'"), val, var);
  272: 		debug_return_bool(false);
  273: 	    }
  274: 	    break;
  275: 	case T_FLOAT:
  276: 	    if (!val) {
  277: 		/* Check for bogus boolean usage or lack of a value. */
  278: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  279: 		    warningx(_("no value specified for `%s'"), var);
  280: 		    debug_return_bool(false);
  281: 		}
  282: 	    }
  283: 	    if (!store_float(val, cur, op)) {
  284: 		warningx(_("value `%s' is invalid for option `%s'"), val, var);
  285: 		debug_return_bool(false);
  286: 	    }
  287: 	    break;
  288: 	case T_MODE:
  289: 	    if (!val) {
  290: 		/* Check for bogus boolean usage or lack of a value. */
  291: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  292: 		    warningx(_("no value specified for `%s'"), var);
  293: 		    debug_return_bool(false);
  294: 		}
  295: 	    }
  296: 	    if (!store_mode(val, cur, op)) {
  297: 		warningx(_("value `%s' is invalid for option `%s'"), val, var);
  298: 		debug_return_bool(false);
  299: 	    }
  300: 	    break;
  301: 	case T_FLAG:
  302: 	    if (val) {
  303: 		warningx(_("option `%s' does not take a value"), var);
  304: 		debug_return_bool(false);
  305: 	    }
  306: 	    cur->sd_un.flag = op;
  307: 	    break;
  308: 	case T_LIST:
  309: 	    if (!val) {
  310: 		/* Check for bogus boolean usage or lack of a value. */
  311: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  312: 		    warningx(_("no value specified for `%s'"), var);
  313: 		    debug_return_bool(false);
  314: 		}
  315: 	    }
  316: 	    if (!store_list(val, cur, op)) {
  317: 		warningx(_("value `%s' is invalid for option `%s'"), val, var);
  318: 		debug_return_bool(false);
  319: 	    }
  320: 	    break;
  321: 	case T_TUPLE:
  322: 	    if (!val && !ISSET(cur->type, T_BOOL)) {
  323: 		warningx(_("no value specified for `%s'"), var);
  324: 		debug_return_bool(false);
  325: 	    }
  326: 	    if (!store_tuple(val, cur, op)) {
  327: 		warningx(_("value `%s' is invalid for option `%s'"), val, var);
  328: 		debug_return_bool(false);
  329: 	    }
  330: 	    break;
  331:     }
  332: 
  333:     debug_return_bool(true);
  334: }
  335: 
  336: /*
  337:  * Set default options to compiled-in values.
  338:  * Any of these may be overridden at runtime by a "Defaults" file.
  339:  */
  340: void
  341: init_defaults(void)
  342: {
  343:     static int firsttime = 1;
  344:     struct sudo_defs_types *def;
  345:     debug_decl(init_defaults, SUDO_DEBUG_DEFAULTS)
  346: 
  347:     /* Clear any old settings. */
  348:     if (!firsttime) {
  349: 	for (def = sudo_defs_table; def->name; def++) {
  350: 	    switch (def->type & T_MASK) {
  351: 		case T_STR:
  352: 		    efree(def->sd_un.str);
  353: 		    def->sd_un.str = NULL;
  354: 		    break;
  355: 		case T_LIST:
  356: 		    list_op(NULL, 0, def, freeall);
  357: 		    break;
  358: 	    }
  359: 	    memset(&def->sd_un, 0, sizeof(def->sd_un));
  360: 	}
  361:     }
  362: 
  363:     /* First initialize the flags. */
  364: #ifdef LONG_OTP_PROMPT
  365:     def_long_otp_prompt = true;
  366: #endif
  367: #ifdef IGNORE_DOT_PATH
  368:     def_ignore_dot = true;
  369: #endif
  370: #ifdef ALWAYS_SEND_MAIL
  371:     def_mail_always = true;
  372: #endif
  373: #ifdef SEND_MAIL_WHEN_NO_USER
  374:     def_mail_no_user = true;
  375: #endif
  376: #ifdef SEND_MAIL_WHEN_NO_HOST
  377:     def_mail_no_host = true;
  378: #endif
  379: #ifdef SEND_MAIL_WHEN_NOT_OK
  380:     def_mail_no_perms = true;
  381: #endif
  382: #ifndef NO_TTY_TICKETS
  383:     def_tty_tickets = true;
  384: #endif
  385: #ifndef NO_LECTURE
  386:     def_lecture = once;
  387: #endif
  388: #ifndef NO_AUTHENTICATION
  389:     def_authenticate = true;
  390: #endif
  391: #ifndef NO_ROOT_SUDO
  392:     def_root_sudo = true;
  393: #endif
  394: #ifdef HOST_IN_LOG
  395:     def_log_host = true;
  396: #endif
  397: #ifdef SHELL_IF_NO_ARGS
  398:     def_shell_noargs = true;
  399: #endif
  400: #ifdef SHELL_SETS_HOME
  401:     def_set_home = true;
  402: #endif
  403: #ifndef DONT_LEAK_PATH_INFO
  404:     def_path_info = true;
  405: #endif
  406: #ifdef FQDN
  407:     def_fqdn = true;
  408: #endif
  409: #ifdef USE_INSULTS
  410:     def_insults = true;
  411: #endif
  412: #ifdef ENV_EDITOR
  413:     def_env_editor = true;
  414: #endif
  415: #ifdef UMASK_OVERRIDE
  416:     def_umask_override = true;
  417: #endif
  418:     def_iolog_file = estrdup("%{seq}");
  419:     def_iolog_dir = estrdup(_PATH_SUDO_IO_LOGDIR);
  420:     def_sudoers_locale = estrdup("C");
  421:     def_env_reset = ENV_RESET;
  422:     def_set_logname = true;
  423:     def_closefrom = STDERR_FILENO + 1;
  424:     def_pam_service = estrdup("sudo");
  425: #ifdef HAVE_PAM_LOGIN
  426:     def_pam_login_service = estrdup("sudo-i");
  427: #else
  428:     def_pam_login_service = estrdup("sudo");
  429: #endif
  430: #ifdef NO_PAM_SESSION
  431:     def_pam_session = false;
  432: #else
  433:     def_pam_session = true;
  434: #endif
  435: 
  436:     /* Syslog options need special care since they both strings and ints */
  437: #if (LOGGING & SLOG_SYSLOG)
  438:     (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG], true);
  439:     (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI],
  440: 	true);
  441:     (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI],
  442: 	true);
  443: #endif
  444: 
  445:     /* Password flags also have a string and integer component. */
  446:     (void) store_tuple("any", &sudo_defs_table[I_LISTPW], true);
  447:     (void) store_tuple("all", &sudo_defs_table[I_VERIFYPW], true);
  448: 
  449:     /* Then initialize the int-like things. */
  450: #ifdef SUDO_UMASK
  451:     def_umask = SUDO_UMASK;
  452: #else
  453:     def_umask = 0777;
  454: #endif
  455:     def_loglinelen = MAXLOGFILELEN;
  456:     def_timestamp_timeout = TIMEOUT;
  457:     def_passwd_timeout = PASSWORD_TIMEOUT;
  458:     def_passwd_tries = TRIES_FOR_PASSWORD;
  459: #ifdef HAVE_ZLIB_H
  460:     def_compress_io = true;
  461: #endif
  462: 
  463:     /* Now do the strings */
  464:     def_mailto = estrdup(MAILTO);
  465:     def_mailsub = estrdup(N_(MAILSUBJECT));
  466:     def_badpass_message = estrdup(_(INCORRECT_PASSWORD));
  467:     def_timestampdir = estrdup(_PATH_SUDO_TIMEDIR);
  468:     def_passprompt = estrdup(_(PASSPROMPT));
  469:     def_runas_default = estrdup(RUNAS_DEFAULT);
  470: #ifdef _PATH_SUDO_SENDMAIL
  471:     def_mailerpath = estrdup(_PATH_SUDO_SENDMAIL);
  472:     def_mailerflags = estrdup("-t");
  473: #endif
  474: #if (LOGGING & SLOG_FILE)
  475:     def_logfile = estrdup(_PATH_SUDO_LOGFILE);
  476: #endif
  477: #ifdef EXEMPTGROUP
  478:     def_exempt_group = estrdup(EXEMPTGROUP);
  479: #endif
  480: #ifdef SECURE_PATH
  481:     def_secure_path = estrdup(SECURE_PATH);
  482: #endif
  483:     def_editor = estrdup(EDITOR);
  484:     def_set_utmp = true;
  485: 
  486:     /* Finally do the lists (currently just environment tables). */
  487:     init_envtables();
  488: 
  489:     firsttime = 0;
  490: 
  491:     debug_return;
  492: }
  493: 
  494: /*
  495:  * Update the defaults based on what was set by sudoers.
  496:  * Pass in an OR'd list of which default types to update.
  497:  */
  498: bool
  499: update_defaults(int what)
  500: {
  501:     struct defaults *def;
  502:     bool rc = true;
  503:     debug_decl(update_defaults, SUDO_DEBUG_DEFAULTS)
  504: 
  505:     tq_foreach_fwd(&defaults, def) {
  506: 	switch (def->type) {
  507: 	    case DEFAULTS:
  508: 		if (ISSET(what, SETDEF_GENERIC) &&
  509: 		    !set_default(def->var, def->val, def->op))
  510: 		    rc = false;
  511: 		break;
  512: 	    case DEFAULTS_USER:
  513: #if 1
  514: 		if (ISSET(what, SETDEF_USER)) {
  515: 		    int m;
  516: 		    m = userlist_matches(sudo_user.pw, &def->binding);
  517: 		    if (m == ALLOW) {
  518: 			if (!set_default(def->var, def->val, def->op))
  519: 			    rc = false;
  520: 		    }
  521: 		}
  522: #else
  523: 		if (ISSET(what, SETDEF_USER) &&
  524: 		    userlist_matches(sudo_user.pw, &def->binding) == ALLOW &&
  525: 		    !set_default(def->var, def->val, def->op))
  526: 		    rc = false;
  527: #endif
  528: 		break;
  529: 	    case DEFAULTS_RUNAS:
  530: 		if (ISSET(what, SETDEF_RUNAS) &&
  531: 		    runaslist_matches(&def->binding, NULL, NULL, NULL) == ALLOW &&
  532: 		    !set_default(def->var, def->val, def->op))
  533: 		    rc = false;
  534: 		break;
  535: 	    case DEFAULTS_HOST:
  536: 		if (ISSET(what, SETDEF_HOST) &&
  537: 		    hostlist_matches(&def->binding) == ALLOW &&
  538: 		    !set_default(def->var, def->val, def->op))
  539: 		    rc = false;
  540: 		break;
  541: 	    case DEFAULTS_CMND:
  542: 		if (ISSET(what, SETDEF_CMND) &&
  543: 		    cmndlist_matches(&def->binding) == ALLOW &&
  544: 		    !set_default(def->var, def->val, def->op))
  545: 		    rc = false;
  546: 		break;
  547: 	}
  548:     }
  549:     debug_return_bool(rc);
  550: }
  551: 
  552: /*
  553:  * Check the defaults entries without actually setting them.
  554:  * Pass in an OR'd list of which default types to check.
  555:  */
  556: bool
  557: check_defaults(int what, bool quiet)
  558: {
  559:     struct sudo_defs_types *cur;
  560:     struct defaults *def;
  561:     bool rc = true;
  562:     debug_decl(check_defaults, SUDO_DEBUG_DEFAULTS)
  563: 
  564:     tq_foreach_fwd(&defaults, def) {
  565: 	switch (def->type) {
  566: 	    case DEFAULTS:
  567: 		if (!ISSET(what, SETDEF_GENERIC))
  568: 		    continue;
  569: 		break;
  570: 	    case DEFAULTS_USER:
  571: 		if (!ISSET(what, SETDEF_USER))
  572: 		    continue;
  573: 		break;
  574: 	    case DEFAULTS_RUNAS:
  575: 		if (!ISSET(what, SETDEF_RUNAS))
  576: 		    continue;
  577: 		break;
  578: 	    case DEFAULTS_HOST:
  579: 		if (!ISSET(what, SETDEF_HOST))
  580: 		    continue;
  581: 		break;
  582: 	    case DEFAULTS_CMND:
  583: 		if (!ISSET(what, SETDEF_CMND))
  584: 		    continue;
  585: 		break;
  586: 	}
  587: 	for (cur = sudo_defs_table; cur->name != NULL; cur++) {
  588: 	    if (strcmp(def->var, cur->name) == 0)
  589: 		break;
  590: 	}
  591: 	if (cur->name == NULL) {
  592: 	    if (!quiet)
  593: 		warningx(_("unknown defaults entry `%s'"), def->var);
  594: 	    rc = false;
  595: 	}
  596:     }
  597:     debug_return_bool(rc);
  598: }
  599: 
  600: static bool
  601: store_int(char *val, struct sudo_defs_types *def, int op)
  602: {
  603:     char *endp;
  604:     long l;
  605:     debug_decl(store_int, SUDO_DEBUG_DEFAULTS)
  606: 
  607:     if (op == false) {
  608: 	def->sd_un.ival = 0;
  609:     } else {
  610: 	l = strtol(val, &endp, 10);
  611: 	if (*endp != '\0')
  612: 	    debug_return_bool(false);
  613: 	/* XXX - should check against INT_MAX */
  614: 	def->sd_un.ival = (int)l;
  615:     }
  616:     if (def->callback)
  617: 	debug_return_bool(def->callback(val));
  618:     debug_return_bool(true);
  619: }
  620: 
  621: static bool
  622: store_uint(char *val, struct sudo_defs_types *def, int op)
  623: {
  624:     char *endp;
  625:     long l;
  626:     debug_decl(store_uint, SUDO_DEBUG_DEFAULTS)
  627: 
  628:     if (op == false) {
  629: 	def->sd_un.ival = 0;
  630:     } else {
  631: 	l = strtol(val, &endp, 10);
  632: 	if (*endp != '\0' || l < 0)
  633: 	    debug_return_bool(false);
  634: 	/* XXX - should check against INT_MAX */
  635: 	def->sd_un.ival = (unsigned int)l;
  636:     }
  637:     if (def->callback)
  638: 	debug_return_bool(def->callback(val));
  639:     debug_return_bool(true);
  640: }
  641: 
  642: static bool
  643: store_float(char *val, struct sudo_defs_types *def, int op)
  644: {
  645:     char *endp;
  646:     double d;
  647:     debug_decl(store_float, SUDO_DEBUG_DEFAULTS)
  648: 
  649:     if (op == false) {
  650: 	def->sd_un.fval = 0.0;
  651:     } else {
  652: 	d = strtod(val, &endp);
  653: 	if (*endp != '\0')
  654: 	    debug_return_bool(false);
  655: 	/* XXX - should check against HUGE_VAL */
  656: 	def->sd_un.fval = d;
  657:     }
  658:     if (def->callback)
  659: 	debug_return_bool(def->callback(val));
  660:     debug_return_bool(true);
  661: }
  662: 
  663: static bool
  664: store_tuple(char *val, struct sudo_defs_types *def, int op)
  665: {
  666:     struct def_values *v;
  667:     debug_decl(store_tuple, SUDO_DEBUG_DEFAULTS)
  668: 
  669:     /*
  670:      * Since enums are really just ints we store the value as an ival.
  671:      * In the future, there may be multiple enums for different tuple
  672:      * types we want to avoid and special knowledge of the tuple type.
  673:      * This does assume that the first entry in the tuple enum will
  674:      * be the equivalent to a boolean "false".
  675:      */
  676:     if (!val) {
  677: 	def->sd_un.ival = (op == false) ? 0 : 1;
  678:     } else {
  679: 	for (v = def->values; v->sval != NULL; v++) {
  680: 	    if (strcmp(v->sval, val) == 0) {
  681: 		def->sd_un.ival = v->ival;
  682: 		break;
  683: 	    }
  684: 	}
  685: 	if (v->sval == NULL)
  686: 	    debug_return_bool(false);
  687:     }
  688:     if (def->callback)
  689: 	debug_return_bool(def->callback(val));
  690:     debug_return_bool(true);
  691: }
  692: 
  693: static bool
  694: store_str(char *val, struct sudo_defs_types *def, int op)
  695: {
  696:     debug_decl(store_str, SUDO_DEBUG_DEFAULTS)
  697: 
  698:     efree(def->sd_un.str);
  699:     if (op == false)
  700: 	def->sd_un.str = NULL;
  701:     else
  702: 	def->sd_un.str = estrdup(val);
  703:     if (def->callback)
  704: 	debug_return_bool(def->callback(val));
  705:     debug_return_bool(true);
  706: }
  707: 
  708: static bool
  709: store_list(char *str, struct sudo_defs_types *def, int op)
  710: {
  711:     char *start, *end;
  712:     debug_decl(store_list, SUDO_DEBUG_DEFAULTS)
  713: 
  714:     /* Remove all old members. */
  715:     if (op == false || op == true)
  716: 	list_op(NULL, 0, def, freeall);
  717: 
  718:     /* Split str into multiple space-separated words and act on each one. */
  719:     if (op != false) {
  720: 	end = str;
  721: 	do {
  722: 	    /* Remove leading blanks, if nothing but blanks we are done. */
  723: 	    for (start = end; isblank((unsigned char)*start); start++)
  724: 		;
  725: 	    if (*start == '\0')
  726: 		break;
  727: 
  728: 	    /* Find end position and perform operation. */
  729: 	    for (end = start; *end && !isblank((unsigned char)*end); end++)
  730: 		;
  731: 	    list_op(start, end - start, def, op == '-' ? delete : add);
  732: 	} while (*end++ != '\0');
  733:     }
  734:     debug_return_bool(true);
  735: }
  736: 
  737: static bool
  738: store_syslogfac(char *val, struct sudo_defs_types *def, int op)
  739: {
  740:     struct strmap *fac;
  741:     debug_decl(store_syslogfac, SUDO_DEBUG_DEFAULTS)
  742: 
  743:     if (op == false) {
  744: 	def->sd_un.ival = false;
  745: 	debug_return_bool(true);
  746:     }
  747: #ifdef LOG_NFACILITIES
  748:     if (!val)
  749: 	debug_return_bool(false);
  750:     for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
  751: 	;
  752:     if (fac->name == NULL)
  753: 	debug_return_bool(false);		/* not found */
  754: 
  755:     def->sd_un.ival = fac->num;
  756: #else
  757:     def->sd_un.ival = -1;
  758: #endif /* LOG_NFACILITIES */
  759:     debug_return_bool(true);
  760: }
  761: 
  762: static const char *
  763: logfac2str(int n)
  764: {
  765: #ifdef LOG_NFACILITIES
  766:     struct strmap *fac;
  767:     debug_decl(logfac2str, SUDO_DEBUG_DEFAULTS)
  768: 
  769:     for (fac = facilities; fac->name && fac->num != n; fac++)
  770: 	;
  771:     debug_return_str(fac->name);
  772: #else
  773:     return "default";
  774: #endif /* LOG_NFACILITIES */
  775: }
  776: 
  777: static bool
  778: store_syslogpri(char *val, struct sudo_defs_types *def, int op)
  779: {
  780:     struct strmap *pri;
  781:     debug_decl(store_syslogpri, SUDO_DEBUG_DEFAULTS)
  782: 
  783:     if (op == false || !val)
  784: 	debug_return_bool(false);
  785: 
  786:     for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
  787: 	;
  788:     if (pri->name == NULL)
  789: 	debug_return_bool(false); 	/* not found */
  790: 
  791:     def->sd_un.ival = pri->num;
  792:     debug_return_bool(true);
  793: }
  794: 
  795: static const char *
  796: logpri2str(int n)
  797: {
  798:     struct strmap *pri;
  799:     debug_decl(logpri2str, SUDO_DEBUG_DEFAULTS)
  800: 
  801:     for (pri = priorities; pri->name && pri->num != n; pri++)
  802: 	;
  803:     debug_return_str(pri->name);
  804: }
  805: 
  806: static bool
  807: store_mode(char *val, struct sudo_defs_types *def, int op)
  808: {
  809:     char *endp;
  810:     long l;
  811:     debug_decl(store_mode, SUDO_DEBUG_DEFAULTS)
  812: 
  813:     if (op == false) {
  814: 	def->sd_un.mode = (mode_t)0777;
  815:     } else {
  816: 	l = strtol(val, &endp, 8);
  817: 	if (*endp != '\0' || l < 0 || l > 0777)
  818: 	    debug_return_bool(false);
  819: 	def->sd_un.mode = (mode_t)l;
  820:     }
  821:     if (def->callback)
  822: 	debug_return_bool(def->callback(val));
  823:     debug_return_bool(true);
  824: }
  825: 
  826: static void
  827: list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op)
  828: {
  829:     struct list_member *cur, *prev, *tmp;
  830:     debug_decl(list_op, SUDO_DEBUG_DEFAULTS)
  831: 
  832:     if (op == freeall) {
  833: 	for (cur = def->sd_un.list; cur; ) {
  834: 	    tmp = cur;
  835: 	    cur = tmp->next;
  836: 	    efree(tmp->value);
  837: 	    efree(tmp);
  838: 	}
  839: 	def->sd_un.list = NULL;
  840: 	debug_return;
  841:     }
  842: 
  843:     for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) {
  844: 	if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
  845: 
  846: 	    if (op == add)
  847: 		debug_return;		/* already exists */
  848: 
  849: 	    /* Delete node */
  850: 	    if (prev != NULL)
  851: 		prev->next = cur->next;
  852: 	    else
  853: 		def->sd_un.list = cur->next;
  854: 	    efree(cur->value);
  855: 	    efree(cur);
  856: 	    break;
  857: 	}
  858:     }
  859: 
  860:     /* Add new node to the head of the list. */
  861:     if (op == add) {
  862: 	cur = ecalloc(1, sizeof(struct list_member));
  863: 	cur->value = estrndup(val, len);
  864: 	cur->next = def->sd_un.list;
  865: 	def->sd_un.list = cur;
  866:     }
  867:     debug_return;
  868: }

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