File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / defaults.c
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:12:54 2014 UTC (10 years 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) 1999-2005, 2007-2014
    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_INT:
  152: 		    sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.ival);
  153: 		    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  154: 		    break;
  155: 		case T_UINT:
  156: 		    sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.uival);
  157: 		    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  158: 		    break;
  159: 		case T_FLOAT:
  160: 		    sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.fval);
  161: 		    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  162: 		    break;
  163: 		case T_MODE:
  164: 		    sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.mode);
  165: 		    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  166: 		    break;
  167: 		case T_LIST:
  168: 		    if (!SLIST_EMPTY(&cur->sd_un.list)) {
  169: 			sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
  170: 			SLIST_FOREACH(item, &cur->sd_un.list, entries) {
  171: 			    sudo_printf(SUDO_CONV_INFO_MSG,
  172: 				"\t%s\n", item->value);
  173: 			}
  174: 		    }
  175: 		    break;
  176: 		case T_TUPLE:
  177: 		    for (def = cur->values; def->sval; def++) {
  178: 			if (cur->sd_un.tuple == def->nval) {
  179: 			    sudo_printf(SUDO_CONV_INFO_MSG, desc, def->sval);
  180: 			    break;
  181: 			}
  182: 		    }
  183: 		    sudo_printf(SUDO_CONV_INFO_MSG, "\n");
  184: 		    break;
  185: 	    }
  186: 	}
  187:     }
  188:     debug_return;
  189: }
  190: 
  191: /*
  192:  * Sets/clears an entry in the defaults structure
  193:  * If a variable that takes a value is used in a boolean
  194:  * context with op == 0, disable that variable.
  195:  * Eg. you may want to turn off logging to a file for some hosts.
  196:  * This is only meaningful for variables that are *optional*.
  197:  */
  198: bool
  199: set_default(char *var, char *val, int op)
  200: {
  201:     struct sudo_defs_types *cur;
  202:     int num;
  203:     debug_decl(set_default, SUDO_DEBUG_DEFAULTS)
  204: 
  205:     for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
  206: 	if (strcmp(var, cur->name) == 0)
  207: 	    break;
  208:     }
  209:     if (!cur->name) {
  210: 	warningx(U_("unknown defaults entry `%s'"), var);
  211: 	debug_return_bool(false);
  212:     }
  213: 
  214:     switch (cur->type & T_MASK) {
  215: 	case T_LOGFAC:
  216: 	    if (!store_syslogfac(val, cur, op)) {
  217: 		if (val)
  218: 		    warningx(U_("value `%s' is invalid for option `%s'"),
  219: 			val, var);
  220: 		else
  221: 		    warningx(U_("no value specified for `%s'"), var);
  222: 		debug_return_bool(false);
  223: 	    }
  224: 	    break;
  225: 	case T_LOGPRI:
  226: 	    if (!store_syslogpri(val, cur, op)) {
  227: 		if (val)
  228: 		    warningx(U_("value `%s' is invalid for option `%s'"),
  229: 			val, var);
  230: 		else
  231: 		    warningx(U_("no value specified for `%s'"), var);
  232: 		debug_return_bool(false);
  233: 	    }
  234: 	    break;
  235: 	case T_STR:
  236: 	    if (!val) {
  237: 		/* Check for bogus boolean usage or lack of a value. */
  238: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  239: 		    warningx(U_("no value specified for `%s'"), var);
  240: 		    debug_return_bool(false);
  241: 		}
  242: 	    }
  243: 	    if (ISSET(cur->type, T_PATH) && val && *val != '/') {
  244: 		warningx(U_("values for `%s' must start with a '/'"), var);
  245: 		debug_return_bool(false);
  246: 	    }
  247: 	    if (!store_str(val, cur, op)) {
  248: 		warningx(U_("value `%s' is invalid for option `%s'"), val, var);
  249: 		debug_return_bool(false);
  250: 	    }
  251: 	    break;
  252: 	case T_INT:
  253: 	    if (!val) {
  254: 		/* Check for bogus boolean usage or lack of a value. */
  255: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  256: 		    warningx(U_("no value specified for `%s'"), var);
  257: 		    debug_return_bool(false);
  258: 		}
  259: 	    }
  260: 	    if (!store_int(val, cur, op)) {
  261: 		warningx(U_("value `%s' is invalid for option `%s'"), val, var);
  262: 		debug_return_bool(false);
  263: 	    }
  264: 	    break;
  265: 	case T_UINT:
  266: 	    if (!val) {
  267: 		/* Check for bogus boolean usage or lack of a value. */
  268: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  269: 		    warningx(U_("no value specified for `%s'"), var);
  270: 		    debug_return_bool(false);
  271: 		}
  272: 	    }
  273: 	    if (!store_uint(val, cur, op)) {
  274: 		warningx(U_("value `%s' is invalid for option `%s'"), val, var);
  275: 		debug_return_bool(false);
  276: 	    }
  277: 	    break;
  278: 	case T_FLOAT:
  279: 	    if (!val) {
  280: 		/* Check for bogus boolean usage or lack of a value. */
  281: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  282: 		    warningx(U_("no value specified for `%s'"), var);
  283: 		    debug_return_bool(false);
  284: 		}
  285: 	    }
  286: 	    if (!store_float(val, cur, op)) {
  287: 		warningx(U_("value `%s' is invalid for option `%s'"), val, var);
  288: 		debug_return_bool(false);
  289: 	    }
  290: 	    break;
  291: 	case T_MODE:
  292: 	    if (!val) {
  293: 		/* Check for bogus boolean usage or lack of a value. */
  294: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  295: 		    warningx(U_("no value specified for `%s'"), var);
  296: 		    debug_return_bool(false);
  297: 		}
  298: 	    }
  299: 	    if (!store_mode(val, cur, op)) {
  300: 		warningx(U_("value `%s' is invalid for option `%s'"), val, var);
  301: 		debug_return_bool(false);
  302: 	    }
  303: 	    break;
  304: 	case T_FLAG:
  305: 	    if (val) {
  306: 		warningx(U_("option `%s' does not take a value"), var);
  307: 		debug_return_bool(false);
  308: 	    }
  309: 	    cur->sd_un.flag = op;
  310: 	    break;
  311: 	case T_LIST:
  312: 	    if (!val) {
  313: 		/* Check for bogus boolean usage or lack of a value. */
  314: 		if (!ISSET(cur->type, T_BOOL) || op != false) {
  315: 		    warningx(U_("no value specified for `%s'"), var);
  316: 		    debug_return_bool(false);
  317: 		}
  318: 	    }
  319: 	    if (!store_list(val, cur, op)) {
  320: 		warningx(U_("value `%s' is invalid for option `%s'"), val, var);
  321: 		debug_return_bool(false);
  322: 	    }
  323: 	    break;
  324: 	case T_TUPLE:
  325: 	    if (!val && !ISSET(cur->type, T_BOOL)) {
  326: 		warningx(U_("no value specified for `%s'"), var);
  327: 		debug_return_bool(false);
  328: 	    }
  329: 	    if (!store_tuple(val, cur, op)) {
  330: 		warningx(U_("value `%s' is invalid for option `%s'"), val, var);
  331: 		debug_return_bool(false);
  332: 	    }
  333: 	    break;
  334:     }
  335: 
  336:     debug_return_bool(true);
  337: }
  338: 
  339: /*
  340:  * Set default options to compiled-in values.
  341:  * Any of these may be overridden at runtime by a "Defaults" file.
  342:  */
  343: void
  344: init_defaults(void)
  345: {
  346:     static int firsttime = 1;
  347:     struct sudo_defs_types *def;
  348:     debug_decl(init_defaults, SUDO_DEBUG_DEFAULTS)
  349: 
  350:     /* Clear any old settings. */
  351:     if (!firsttime) {
  352: 	for (def = sudo_defs_table; def->name; def++) {
  353: 	    switch (def->type & T_MASK) {
  354: 		case T_STR:
  355: 		    efree(def->sd_un.str);
  356: 		    def->sd_un.str = NULL;
  357: 		    break;
  358: 		case T_LIST:
  359: 		    list_op(NULL, 0, def, freeall);
  360: 		    break;
  361: 	    }
  362: 	    memset(&def->sd_un, 0, sizeof(def->sd_un));
  363: 	}
  364:     }
  365: 
  366:     /* First initialize the flags. */
  367: #ifdef LONG_OTP_PROMPT
  368:     def_long_otp_prompt = true;
  369: #endif
  370: #ifdef IGNORE_DOT_PATH
  371:     def_ignore_dot = true;
  372: #endif
  373: #ifdef ALWAYS_SEND_MAIL
  374:     def_mail_always = true;
  375: #endif
  376: #ifdef SEND_MAIL_WHEN_NO_USER
  377:     def_mail_no_user = true;
  378: #endif
  379: #ifdef SEND_MAIL_WHEN_NO_HOST
  380:     def_mail_no_host = true;
  381: #endif
  382: #ifdef SEND_MAIL_WHEN_NOT_OK
  383:     def_mail_no_perms = true;
  384: #endif
  385: #ifndef NO_TTY_TICKETS
  386:     def_tty_tickets = true;
  387: #endif
  388: #ifndef NO_LECTURE
  389:     def_lecture = once;
  390: #endif
  391: #ifndef NO_AUTHENTICATION
  392:     def_authenticate = true;
  393: #endif
  394: #ifndef NO_ROOT_SUDO
  395:     def_root_sudo = true;
  396: #endif
  397: #ifdef HOST_IN_LOG
  398:     def_log_host = true;
  399: #endif
  400: #ifdef SHELL_IF_NO_ARGS
  401:     def_shell_noargs = true;
  402: #endif
  403: #ifdef SHELL_SETS_HOME
  404:     def_set_home = true;
  405: #endif
  406: #ifndef DONT_LEAK_PATH_INFO
  407:     def_path_info = true;
  408: #endif
  409: #ifdef FQDN
  410:     def_fqdn = true;
  411: #endif
  412: #ifdef USE_INSULTS
  413:     def_insults = true;
  414: #endif
  415: #ifdef ENV_EDITOR
  416:     def_env_editor = true;
  417: #endif
  418: #ifdef UMASK_OVERRIDE
  419:     def_umask_override = true;
  420: #endif
  421:     def_iolog_file = estrdup("%{seq}");
  422:     def_iolog_dir = estrdup(_PATH_SUDO_IO_LOGDIR);
  423:     def_sudoers_locale = estrdup("C");
  424:     def_env_reset = ENV_RESET;
  425:     def_set_logname = true;
  426:     def_closefrom = STDERR_FILENO + 1;
  427:     def_pam_service = estrdup("sudo");
  428: #ifdef HAVE_PAM_LOGIN
  429:     def_pam_login_service = estrdup("sudo-i");
  430: #else
  431:     def_pam_login_service = estrdup("sudo");
  432: #endif
  433: #ifdef NO_PAM_SESSION
  434:     def_pam_session = false;
  435: #else
  436:     def_pam_session = true;
  437: #endif
  438: #ifdef HAVE_INNETGR
  439:     def_use_netgroups = true;
  440: #endif
  441: 
  442:     /* Syslog options need special care since they both strings and ints */
  443: #if (LOGGING & SLOG_SYSLOG)
  444:     (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG], true);
  445:     (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI],
  446: 	true);
  447:     (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI],
  448: 	true);
  449: #endif
  450: 
  451:     /* Password flags also have a string and integer component. */
  452:     (void) store_tuple("any", &sudo_defs_table[I_LISTPW], true);
  453:     (void) store_tuple("all", &sudo_defs_table[I_VERIFYPW], true);
  454: 
  455:     /* Then initialize the int-like things. */
  456: #ifdef SUDO_UMASK
  457:     def_umask = SUDO_UMASK;
  458: #else
  459:     def_umask = 0777;
  460: #endif
  461:     def_loglinelen = MAXLOGFILELEN;
  462:     def_timestamp_timeout = TIMEOUT;
  463:     def_passwd_timeout = PASSWORD_TIMEOUT;
  464:     def_passwd_tries = TRIES_FOR_PASSWORD;
  465: #ifdef HAVE_ZLIB_H
  466:     def_compress_io = true;
  467: #endif
  468: 
  469:     /* Now do the strings */
  470:     def_mailto = estrdup(MAILTO);
  471:     def_mailsub = estrdup(N_(MAILSUBJECT));
  472:     def_badpass_message = estrdup(_(INCORRECT_PASSWORD));
  473:     def_lecture_status_dir = estrdup(_PATH_SUDO_LECTURE_DIR);
  474:     def_timestampdir = estrdup(_PATH_SUDO_TIMEDIR);
  475:     def_passprompt = estrdup(_(PASSPROMPT));
  476:     def_runas_default = estrdup(RUNAS_DEFAULT);
  477: #ifdef _PATH_SUDO_SENDMAIL
  478:     def_mailerpath = estrdup(_PATH_SUDO_SENDMAIL);
  479:     def_mailerflags = estrdup("-t");
  480: #endif
  481: #if (LOGGING & SLOG_FILE)
  482:     def_logfile = estrdup(_PATH_SUDO_LOGFILE);
  483: #endif
  484: #ifdef EXEMPTGROUP
  485:     def_exempt_group = estrdup(EXEMPTGROUP);
  486: #endif
  487: #ifdef SECURE_PATH
  488:     def_secure_path = estrdup(SECURE_PATH);
  489: #endif
  490:     def_editor = estrdup(EDITOR);
  491:     def_set_utmp = true;
  492:     def_pam_setcred = true;
  493: 
  494:     /* Finally do the lists (currently just environment tables). */
  495:     init_envtables();
  496: 
  497:     firsttime = 0;
  498: 
  499:     debug_return;
  500: }
  501: 
  502: /*
  503:  * Update the defaults based on what was set by sudoers.
  504:  * Pass in an OR'd list of which default types to update.
  505:  */
  506: bool
  507: update_defaults(int what)
  508: {
  509:     struct defaults *def;
  510:     bool rc = true;
  511:     debug_decl(update_defaults, SUDO_DEBUG_DEFAULTS)
  512: 
  513:     TAILQ_FOREACH(def, &defaults, entries) {
  514: 	switch (def->type) {
  515: 	    case DEFAULTS:
  516: 		if (ISSET(what, SETDEF_GENERIC) &&
  517: 		    !set_default(def->var, def->val, def->op))
  518: 		    rc = false;
  519: 		break;
  520: 	    case DEFAULTS_USER:
  521: #if 1
  522: 		if (ISSET(what, SETDEF_USER)) {
  523: 		    int m;
  524: 		    m = userlist_matches(sudo_user.pw, def->binding);
  525: 		    if (m == ALLOW) {
  526: 			if (!set_default(def->var, def->val, def->op))
  527: 			    rc = false;
  528: 		    }
  529: 		}
  530: #else
  531: 		if (ISSET(what, SETDEF_USER) &&
  532: 		    userlist_matches(sudo_user.pw, def->binding) == ALLOW &&
  533: 		    !set_default(def->var, def->val, def->op))
  534: 		    rc = false;
  535: #endif
  536: 		break;
  537: 	    case DEFAULTS_RUNAS:
  538: 		if (ISSET(what, SETDEF_RUNAS) &&
  539: 		    runaslist_matches(def->binding, NULL, NULL, NULL) == ALLOW &&
  540: 		    !set_default(def->var, def->val, def->op))
  541: 		    rc = false;
  542: 		break;
  543: 	    case DEFAULTS_HOST:
  544: 		if (ISSET(what, SETDEF_HOST) &&
  545: 		    hostlist_matches(def->binding) == ALLOW &&
  546: 		    !set_default(def->var, def->val, def->op))
  547: 		    rc = false;
  548: 		break;
  549: 	    case DEFAULTS_CMND:
  550: 		if (ISSET(what, SETDEF_CMND) &&
  551: 		    cmndlist_matches(def->binding) == ALLOW &&
  552: 		    !set_default(def->var, def->val, def->op))
  553: 		    rc = false;
  554: 		break;
  555: 	}
  556:     }
  557:     debug_return_bool(rc);
  558: }
  559: 
  560: /*
  561:  * Check the defaults entries without actually setting them.
  562:  * Pass in an OR'd list of which default types to check.
  563:  */
  564: bool
  565: check_defaults(int what, bool quiet)
  566: {
  567:     struct sudo_defs_types *cur;
  568:     struct defaults *def;
  569:     bool rc = true;
  570:     debug_decl(check_defaults, SUDO_DEBUG_DEFAULTS)
  571: 
  572:     TAILQ_FOREACH(def, &defaults, entries) {
  573: 	switch (def->type) {
  574: 	    case DEFAULTS:
  575: 		if (!ISSET(what, SETDEF_GENERIC))
  576: 		    continue;
  577: 		break;
  578: 	    case DEFAULTS_USER:
  579: 		if (!ISSET(what, SETDEF_USER))
  580: 		    continue;
  581: 		break;
  582: 	    case DEFAULTS_RUNAS:
  583: 		if (!ISSET(what, SETDEF_RUNAS))
  584: 		    continue;
  585: 		break;
  586: 	    case DEFAULTS_HOST:
  587: 		if (!ISSET(what, SETDEF_HOST))
  588: 		    continue;
  589: 		break;
  590: 	    case DEFAULTS_CMND:
  591: 		if (!ISSET(what, SETDEF_CMND))
  592: 		    continue;
  593: 		break;
  594: 	}
  595: 	for (cur = sudo_defs_table; cur->name != NULL; cur++) {
  596: 	    if (strcmp(def->var, cur->name) == 0)
  597: 		break;
  598: 	}
  599: 	if (cur->name == NULL) {
  600: 	    if (!quiet)
  601: 		warningx(U_("unknown defaults entry `%s'"), def->var);
  602: 	    rc = false;
  603: 	}
  604:     }
  605:     debug_return_bool(rc);
  606: }
  607: 
  608: static bool
  609: store_int(char *val, struct sudo_defs_types *def, int op)
  610: {
  611:     const char *errstr;
  612:     int i;
  613:     debug_decl(store_int, SUDO_DEBUG_DEFAULTS)
  614: 
  615:     if (op == false) {
  616: 	def->sd_un.ival = 0;
  617:     } else {
  618: 	i = strtonum(val, INT_MIN, INT_MAX, &errstr);
  619: 	if (errstr != NULL) {
  620: 	    sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
  621: 		"%s: %s", val, errstr);
  622: 	    debug_return_bool(false);
  623: 	}
  624: 	def->sd_un.ival = i;
  625:     }
  626:     if (def->callback)
  627: 	debug_return_bool(def->callback(val));
  628:     debug_return_bool(true);
  629: }
  630: 
  631: static bool
  632: store_uint(char *val, struct sudo_defs_types *def, int op)
  633: {
  634:     const char *errstr;
  635:     unsigned int u;
  636:     debug_decl(store_uint, SUDO_DEBUG_DEFAULTS)
  637: 
  638:     if (op == false) {
  639: 	def->sd_un.uival = 0;
  640:     } else {
  641: 	u = strtonum(val, 0, UINT_MAX, &errstr);
  642: 	if (errstr != NULL) {
  643: 	    sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
  644: 		"%s: %s", val, errstr);
  645: 	    debug_return_bool(false);
  646: 	}
  647: 	def->sd_un.uival = u;
  648:     }
  649:     if (def->callback)
  650: 	debug_return_bool(def->callback(val));
  651:     debug_return_bool(true);
  652: }
  653: 
  654: static bool
  655: store_float(char *val, struct sudo_defs_types *def, int op)
  656: {
  657:     char *endp;
  658:     double d;
  659:     debug_decl(store_float, SUDO_DEBUG_DEFAULTS)
  660: 
  661:     if (op == false) {
  662: 	def->sd_un.fval = 0.0;
  663:     } else {
  664: 	d = strtod(val, &endp);
  665: 	if (*endp != '\0')
  666: 	    debug_return_bool(false);
  667: 	/* XXX - should check against HUGE_VAL */
  668: 	def->sd_un.fval = d;
  669:     }
  670:     if (def->callback)
  671: 	debug_return_bool(def->callback(val));
  672:     debug_return_bool(true);
  673: }
  674: 
  675: static bool
  676: store_tuple(char *val, struct sudo_defs_types *def, int op)
  677: {
  678:     struct def_values *v;
  679:     debug_decl(store_tuple, SUDO_DEBUG_DEFAULTS)
  680: 
  681:     /*
  682:      * Look up tuple value by name to find enum def_tuple value.
  683:      * For negation to work the first element of enum def_tuple
  684:      * must be equivalent to boolean false.
  685:      */
  686:     if (!val) {
  687: 	def->sd_un.ival = (op == false) ? 0 : 1;
  688:     } else {
  689: 	for (v = def->values; v->sval != NULL; v++) {
  690: 	    if (strcmp(v->sval, val) == 0) {
  691: 		def->sd_un.tuple = v->nval;
  692: 		break;
  693: 	    }
  694: 	}
  695: 	if (v->sval == NULL)
  696: 	    debug_return_bool(false);
  697:     }
  698:     if (def->callback)
  699: 	debug_return_bool(def->callback(val));
  700:     debug_return_bool(true);
  701: }
  702: 
  703: static bool
  704: store_str(char *val, struct sudo_defs_types *def, int op)
  705: {
  706:     debug_decl(store_str, SUDO_DEBUG_DEFAULTS)
  707: 
  708:     efree(def->sd_un.str);
  709:     if (op == false)
  710: 	def->sd_un.str = NULL;
  711:     else
  712: 	def->sd_un.str = estrdup(val);
  713:     if (def->callback)
  714: 	debug_return_bool(def->callback(val));
  715:     debug_return_bool(true);
  716: }
  717: 
  718: static bool
  719: store_list(char *str, struct sudo_defs_types *def, int op)
  720: {
  721:     char *start, *end;
  722:     debug_decl(store_list, SUDO_DEBUG_DEFAULTS)
  723: 
  724:     /* Remove all old members. */
  725:     if (op == false || op == true)
  726: 	list_op(NULL, 0, def, freeall);
  727: 
  728:     /* Split str into multiple space-separated words and act on each one. */
  729:     if (op != false) {
  730: 	end = str;
  731: 	do {
  732: 	    /* Remove leading blanks, if nothing but blanks we are done. */
  733: 	    for (start = end; isblank((unsigned char)*start); start++)
  734: 		;
  735: 	    if (*start == '\0')
  736: 		break;
  737: 
  738: 	    /* Find end position and perform operation. */
  739: 	    for (end = start; *end && !isblank((unsigned char)*end); end++)
  740: 		;
  741: 	    list_op(start, end - start, def, op == '-' ? delete : add);
  742: 	} while (*end++ != '\0');
  743:     }
  744:     debug_return_bool(true);
  745: }
  746: 
  747: static bool
  748: store_syslogfac(char *val, struct sudo_defs_types *def, int op)
  749: {
  750:     struct strmap *fac;
  751:     debug_decl(store_syslogfac, SUDO_DEBUG_DEFAULTS)
  752: 
  753:     if (op == false) {
  754: 	def->sd_un.ival = false;
  755: 	debug_return_bool(true);
  756:     }
  757: #ifdef LOG_NFACILITIES
  758:     if (!val)
  759: 	debug_return_bool(false);
  760:     for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
  761: 	;
  762:     if (fac->name == NULL)
  763: 	debug_return_bool(false);		/* not found */
  764: 
  765:     def->sd_un.ival = fac->num;
  766: #else
  767:     def->sd_un.ival = -1;
  768: #endif /* LOG_NFACILITIES */
  769:     debug_return_bool(true);
  770: }
  771: 
  772: static const char *
  773: logfac2str(int n)
  774: {
  775: #ifdef LOG_NFACILITIES
  776:     struct strmap *fac;
  777:     debug_decl(logfac2str, SUDO_DEBUG_DEFAULTS)
  778: 
  779:     for (fac = facilities; fac->name && fac->num != n; fac++)
  780: 	;
  781:     debug_return_const_str(fac->name);
  782: #else
  783:     return "default";
  784: #endif /* LOG_NFACILITIES */
  785: }
  786: 
  787: static bool
  788: store_syslogpri(char *val, struct sudo_defs_types *def, int op)
  789: {
  790:     struct strmap *pri;
  791:     debug_decl(store_syslogpri, SUDO_DEBUG_DEFAULTS)
  792: 
  793:     if (op == false || !val)
  794: 	debug_return_bool(false);
  795: 
  796:     for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
  797: 	;
  798:     if (pri->name == NULL)
  799: 	debug_return_bool(false); 	/* not found */
  800: 
  801:     def->sd_un.ival = pri->num;
  802:     debug_return_bool(true);
  803: }
  804: 
  805: static const char *
  806: logpri2str(int n)
  807: {
  808:     struct strmap *pri;
  809:     debug_decl(logpri2str, SUDO_DEBUG_DEFAULTS)
  810: 
  811:     for (pri = priorities; pri->name && pri->num != n; pri++)
  812: 	;
  813:     debug_return_const_str(pri->name);
  814: }
  815: 
  816: static bool
  817: store_mode(char *val, struct sudo_defs_types *def, int op)
  818: {
  819:     mode_t mode;
  820:     const char *errstr;
  821:     debug_decl(store_mode, SUDO_DEBUG_DEFAULTS)
  822: 
  823:     if (op == false) {
  824: 	def->sd_un.mode = 0777;
  825:     } else {
  826: 	mode = atomode(val, &errstr);
  827: 	if (errstr != NULL) {
  828: 	    sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
  829: 		"%s is %s", val, errstr);
  830: 	    debug_return_bool(false);
  831: 	}
  832: 	def->sd_un.mode = mode;
  833:     }
  834:     if (def->callback)
  835: 	debug_return_bool(def->callback(val));
  836:     debug_return_bool(true);
  837: }
  838: 
  839: static void
  840: list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op)
  841: {
  842:     struct list_member *cur, *prev = NULL;
  843:     debug_decl(list_op, SUDO_DEBUG_DEFAULTS)
  844: 
  845:     if (op == freeall) {
  846: 	while ((cur = SLIST_FIRST(&def->sd_un.list)) != NULL) {
  847: 	    SLIST_REMOVE_HEAD(&def->sd_un.list, entries);
  848: 	    efree(cur->value);
  849: 	    efree(cur);
  850: 	}
  851: 	debug_return;
  852:     }
  853: 
  854:     SLIST_FOREACH(cur, &def->sd_un.list, entries) {
  855: 	if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
  856: 
  857: 	    if (op == add)
  858: 		debug_return;		/* already exists */
  859: 
  860: 	    /* Delete node */
  861: 	    if (prev == NULL)
  862: 		SLIST_REMOVE_HEAD(&def->sd_un.list, entries);
  863: 	    else
  864: 		SLIST_REMOVE_AFTER(prev, entries);
  865: 	    efree(cur->value);
  866: 	    efree(cur);
  867: 	    break;
  868: 	}
  869: 	prev = cur;
  870:     }
  871: 
  872:     /* Add new node to the head of the list. */
  873:     if (op == add) {
  874: 	cur = ecalloc(1, sizeof(struct list_member));
  875: 	cur->value = estrndup(val, len);
  876: 	SLIST_INSERT_HEAD(&def->sd_un.list, cur, entries);
  877:     }
  878:     debug_return;
  879: }

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