File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / defaults.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:29:52 2012 UTC (11 years, 9 months ago) by misho
Branches: sudo, MAIN
CVS tags: HEAD
sudo

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

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