File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / defaults.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 10:46:12 2013 UTC (10 years, 11 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_7p0, v1_8_7, HEAD
1.8.7

    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: 	    zero_bytes(&def->sd_un, 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: #ifdef NO_PAM_SESSION
  425:     def_pam_session = false;
  426: #else
  427:     def_pam_session = true;
  428: #endif
  429: 
  430:     /* Syslog options need special care since they both strings and ints */
  431: #if (LOGGING & SLOG_SYSLOG)
  432:     (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG], true);
  433:     (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI],
  434: 	true);
  435:     (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI],
  436: 	true);
  437: #endif
  438: 
  439:     /* Password flags also have a string and integer component. */
  440:     (void) store_tuple("any", &sudo_defs_table[I_LISTPW], true);
  441:     (void) store_tuple("all", &sudo_defs_table[I_VERIFYPW], true);
  442: 
  443:     /* Then initialize the int-like things. */
  444: #ifdef SUDO_UMASK
  445:     def_umask = SUDO_UMASK;
  446: #else
  447:     def_umask = 0777;
  448: #endif
  449:     def_loglinelen = MAXLOGFILELEN;
  450:     def_timestamp_timeout = TIMEOUT;
  451:     def_passwd_timeout = PASSWORD_TIMEOUT;
  452:     def_passwd_tries = TRIES_FOR_PASSWORD;
  453: #ifdef HAVE_ZLIB_H
  454:     def_compress_io = true;
  455: #endif
  456: 
  457:     /* Now do the strings */
  458:     def_mailto = estrdup(MAILTO);
  459:     def_mailsub = estrdup(N_(MAILSUBJECT));
  460:     def_badpass_message = estrdup(_(INCORRECT_PASSWORD));
  461:     def_timestampdir = estrdup(_PATH_SUDO_TIMEDIR);
  462:     def_passprompt = estrdup(_(PASSPROMPT));
  463:     def_runas_default = estrdup(RUNAS_DEFAULT);
  464: #ifdef _PATH_SUDO_SENDMAIL
  465:     def_mailerpath = estrdup(_PATH_SUDO_SENDMAIL);
  466:     def_mailerflags = estrdup("-t");
  467: #endif
  468: #if (LOGGING & SLOG_FILE)
  469:     def_logfile = estrdup(_PATH_SUDO_LOGFILE);
  470: #endif
  471: #ifdef EXEMPTGROUP
  472:     def_exempt_group = estrdup(EXEMPTGROUP);
  473: #endif
  474: #ifdef SECURE_PATH
  475:     def_secure_path = estrdup(SECURE_PATH);
  476: #endif
  477:     def_editor = estrdup(EDITOR);
  478:     def_set_utmp = true;
  479: 
  480:     /* Finally do the lists (currently just environment tables). */
  481:     init_envtables();
  482: 
  483:     firsttime = 0;
  484: 
  485:     debug_return;
  486: }
  487: 
  488: /*
  489:  * Update the defaults based on what was set by sudoers.
  490:  * Pass in an OR'd list of which default types to update.
  491:  */
  492: bool
  493: update_defaults(int what)
  494: {
  495:     struct defaults *def;
  496:     bool rc = true;
  497:     debug_decl(update_defaults, SUDO_DEBUG_DEFAULTS)
  498: 
  499:     tq_foreach_fwd(&defaults, def) {
  500: 	switch (def->type) {
  501: 	    case DEFAULTS:
  502: 		if (ISSET(what, SETDEF_GENERIC) &&
  503: 		    !set_default(def->var, def->val, def->op))
  504: 		    rc = false;
  505: 		break;
  506: 	    case DEFAULTS_USER:
  507: #if 1
  508: 		if (ISSET(what, SETDEF_USER)) {
  509: 		    int m;
  510: 		    m = userlist_matches(sudo_user.pw, &def->binding);
  511: 		    if (m == ALLOW) {
  512: 			if (!set_default(def->var, def->val, def->op))
  513: 			    rc = false;
  514: 		    }
  515: 		}
  516: #else
  517: 		if (ISSET(what, SETDEF_USER) &&
  518: 		    userlist_matches(sudo_user.pw, &def->binding) == ALLOW &&
  519: 		    !set_default(def->var, def->val, def->op))
  520: 		    rc = false;
  521: #endif
  522: 		break;
  523: 	    case DEFAULTS_RUNAS:
  524: 		if (ISSET(what, SETDEF_RUNAS) &&
  525: 		    runaslist_matches(&def->binding, NULL, NULL, NULL) == ALLOW &&
  526: 		    !set_default(def->var, def->val, def->op))
  527: 		    rc = false;
  528: 		break;
  529: 	    case DEFAULTS_HOST:
  530: 		if (ISSET(what, SETDEF_HOST) &&
  531: 		    hostlist_matches(&def->binding) == ALLOW &&
  532: 		    !set_default(def->var, def->val, def->op))
  533: 		    rc = false;
  534: 		break;
  535: 	    case DEFAULTS_CMND:
  536: 		if (ISSET(what, SETDEF_CMND) &&
  537: 		    cmndlist_matches(&def->binding) == ALLOW &&
  538: 		    !set_default(def->var, def->val, def->op))
  539: 		    rc = false;
  540: 		break;
  541: 	}
  542:     }
  543:     debug_return_bool(rc);
  544: }
  545: 
  546: /*
  547:  * Check the defaults entries without actually setting them.
  548:  * Pass in an OR'd list of which default types to check.
  549:  */
  550: bool
  551: check_defaults(int what, bool quiet)
  552: {
  553:     struct sudo_defs_types *cur;
  554:     struct defaults *def;
  555:     bool rc = true;
  556:     debug_decl(check_defaults, SUDO_DEBUG_DEFAULTS)
  557: 
  558:     tq_foreach_fwd(&defaults, def) {
  559: 	switch (def->type) {
  560: 	    case DEFAULTS:
  561: 		if (!ISSET(what, SETDEF_GENERIC))
  562: 		    continue;
  563: 		break;
  564: 	    case DEFAULTS_USER:
  565: 		if (!ISSET(what, SETDEF_USER))
  566: 		    continue;
  567: 		break;
  568: 	    case DEFAULTS_RUNAS:
  569: 		if (!ISSET(what, SETDEF_RUNAS))
  570: 		    continue;
  571: 		break;
  572: 	    case DEFAULTS_HOST:
  573: 		if (!ISSET(what, SETDEF_HOST))
  574: 		    continue;
  575: 		break;
  576: 	    case DEFAULTS_CMND:
  577: 		if (!ISSET(what, SETDEF_CMND))
  578: 		    continue;
  579: 		break;
  580: 	}
  581: 	for (cur = sudo_defs_table; cur->name != NULL; cur++) {
  582: 	    if (strcmp(def->var, cur->name) == 0)
  583: 		break;
  584: 	}
  585: 	if (cur->name == NULL) {
  586: 	    if (!quiet)
  587: 		warningx(_("unknown defaults entry `%s'"), def->var);
  588: 	    rc = false;
  589: 	}
  590:     }
  591:     debug_return_bool(rc);
  592: }
  593: 
  594: static bool
  595: store_int(char *val, struct sudo_defs_types *def, int op)
  596: {
  597:     char *endp;
  598:     long l;
  599:     debug_decl(store_int, SUDO_DEBUG_DEFAULTS)
  600: 
  601:     if (op == false) {
  602: 	def->sd_un.ival = 0;
  603:     } else {
  604: 	l = strtol(val, &endp, 10);
  605: 	if (*endp != '\0')
  606: 	    debug_return_bool(false);
  607: 	/* XXX - should check against INT_MAX */
  608: 	def->sd_un.ival = (int)l;
  609:     }
  610:     if (def->callback)
  611: 	debug_return_bool(def->callback(val));
  612:     debug_return_bool(true);
  613: }
  614: 
  615: static bool
  616: store_uint(char *val, struct sudo_defs_types *def, int op)
  617: {
  618:     char *endp;
  619:     long l;
  620:     debug_decl(store_uint, SUDO_DEBUG_DEFAULTS)
  621: 
  622:     if (op == false) {
  623: 	def->sd_un.ival = 0;
  624:     } else {
  625: 	l = strtol(val, &endp, 10);
  626: 	if (*endp != '\0' || l < 0)
  627: 	    debug_return_bool(false);
  628: 	/* XXX - should check against INT_MAX */
  629: 	def->sd_un.ival = (unsigned int)l;
  630:     }
  631:     if (def->callback)
  632: 	debug_return_bool(def->callback(val));
  633:     debug_return_bool(true);
  634: }
  635: 
  636: static bool
  637: store_float(char *val, struct sudo_defs_types *def, int op)
  638: {
  639:     char *endp;
  640:     double d;
  641:     debug_decl(store_float, SUDO_DEBUG_DEFAULTS)
  642: 
  643:     if (op == false) {
  644: 	def->sd_un.fval = 0.0;
  645:     } else {
  646: 	d = strtod(val, &endp);
  647: 	if (*endp != '\0')
  648: 	    debug_return_bool(false);
  649: 	/* XXX - should check against HUGE_VAL */
  650: 	def->sd_un.fval = d;
  651:     }
  652:     if (def->callback)
  653: 	debug_return_bool(def->callback(val));
  654:     debug_return_bool(true);
  655: }
  656: 
  657: static bool
  658: store_tuple(char *val, struct sudo_defs_types *def, int op)
  659: {
  660:     struct def_values *v;
  661:     debug_decl(store_tuple, SUDO_DEBUG_DEFAULTS)
  662: 
  663:     /*
  664:      * Since enums are really just ints we store the value as an ival.
  665:      * In the future, there may be multiple enums for different tuple
  666:      * types we want to avoid and special knowledge of the tuple type.
  667:      * This does assume that the first entry in the tuple enum will
  668:      * be the equivalent to a boolean "false".
  669:      */
  670:     if (!val) {
  671: 	def->sd_un.ival = (op == false) ? 0 : 1;
  672:     } else {
  673: 	for (v = def->values; v->sval != NULL; v++) {
  674: 	    if (strcmp(v->sval, val) == 0) {
  675: 		def->sd_un.ival = v->ival;
  676: 		break;
  677: 	    }
  678: 	}
  679: 	if (v->sval == NULL)
  680: 	    debug_return_bool(false);
  681:     }
  682:     if (def->callback)
  683: 	debug_return_bool(def->callback(val));
  684:     debug_return_bool(true);
  685: }
  686: 
  687: static bool
  688: store_str(char *val, struct sudo_defs_types *def, int op)
  689: {
  690:     debug_decl(store_str, SUDO_DEBUG_DEFAULTS)
  691: 
  692:     efree(def->sd_un.str);
  693:     if (op == false)
  694: 	def->sd_un.str = NULL;
  695:     else
  696: 	def->sd_un.str = estrdup(val);
  697:     if (def->callback)
  698: 	debug_return_bool(def->callback(val));
  699:     debug_return_bool(true);
  700: }
  701: 
  702: static bool
  703: store_list(char *str, struct sudo_defs_types *def, int op)
  704: {
  705:     char *start, *end;
  706:     debug_decl(store_list, SUDO_DEBUG_DEFAULTS)
  707: 
  708:     /* Remove all old members. */
  709:     if (op == false || op == true)
  710: 	list_op(NULL, 0, def, freeall);
  711: 
  712:     /* Split str into multiple space-separated words and act on each one. */
  713:     if (op != false) {
  714: 	end = str;
  715: 	do {
  716: 	    /* Remove leading blanks, if nothing but blanks we are done. */
  717: 	    for (start = end; isblank((unsigned char)*start); start++)
  718: 		;
  719: 	    if (*start == '\0')
  720: 		break;
  721: 
  722: 	    /* Find end position and perform operation. */
  723: 	    for (end = start; *end && !isblank((unsigned char)*end); end++)
  724: 		;
  725: 	    list_op(start, end - start, def, op == '-' ? delete : add);
  726: 	} while (*end++ != '\0');
  727:     }
  728:     debug_return_bool(true);
  729: }
  730: 
  731: static bool
  732: store_syslogfac(char *val, struct sudo_defs_types *def, int op)
  733: {
  734:     struct strmap *fac;
  735:     debug_decl(store_syslogfac, SUDO_DEBUG_DEFAULTS)
  736: 
  737:     if (op == false) {
  738: 	def->sd_un.ival = false;
  739: 	debug_return_bool(true);
  740:     }
  741: #ifdef LOG_NFACILITIES
  742:     if (!val)
  743: 	debug_return_bool(false);
  744:     for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
  745: 	;
  746:     if (fac->name == NULL)
  747: 	debug_return_bool(false);		/* not found */
  748: 
  749:     def->sd_un.ival = fac->num;
  750: #else
  751:     def->sd_un.ival = -1;
  752: #endif /* LOG_NFACILITIES */
  753:     debug_return_bool(true);
  754: }
  755: 
  756: static const char *
  757: logfac2str(int n)
  758: {
  759: #ifdef LOG_NFACILITIES
  760:     struct strmap *fac;
  761:     debug_decl(logfac2str, SUDO_DEBUG_DEFAULTS)
  762: 
  763:     for (fac = facilities; fac->name && fac->num != n; fac++)
  764: 	;
  765:     debug_return_str(fac->name);
  766: #else
  767:     return "default";
  768: #endif /* LOG_NFACILITIES */
  769: }
  770: 
  771: static bool
  772: store_syslogpri(char *val, struct sudo_defs_types *def, int op)
  773: {
  774:     struct strmap *pri;
  775:     debug_decl(store_syslogpri, SUDO_DEBUG_DEFAULTS)
  776: 
  777:     if (op == false || !val)
  778: 	debug_return_bool(false);
  779: 
  780:     for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
  781: 	;
  782:     if (pri->name == NULL)
  783: 	debug_return_bool(false); 	/* not found */
  784: 
  785:     def->sd_un.ival = pri->num;
  786:     debug_return_bool(true);
  787: }
  788: 
  789: static const char *
  790: logpri2str(int n)
  791: {
  792:     struct strmap *pri;
  793:     debug_decl(logpri2str, SUDO_DEBUG_DEFAULTS)
  794: 
  795:     for (pri = priorities; pri->name && pri->num != n; pri++)
  796: 	;
  797:     debug_return_str(pri->name);
  798: }
  799: 
  800: static bool
  801: store_mode(char *val, struct sudo_defs_types *def, int op)
  802: {
  803:     char *endp;
  804:     long l;
  805:     debug_decl(store_mode, SUDO_DEBUG_DEFAULTS)
  806: 
  807:     if (op == false) {
  808: 	def->sd_un.mode = (mode_t)0777;
  809:     } else {
  810: 	l = strtol(val, &endp, 8);
  811: 	if (*endp != '\0' || l < 0 || l > 0777)
  812: 	    debug_return_bool(false);
  813: 	def->sd_un.mode = (mode_t)l;
  814:     }
  815:     if (def->callback)
  816: 	debug_return_bool(def->callback(val));
  817:     debug_return_bool(true);
  818: }
  819: 
  820: static void
  821: list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op)
  822: {
  823:     struct list_member *cur, *prev, *tmp;
  824:     debug_decl(list_op, SUDO_DEBUG_DEFAULTS)
  825: 
  826:     if (op == freeall) {
  827: 	for (cur = def->sd_un.list; cur; ) {
  828: 	    tmp = cur;
  829: 	    cur = tmp->next;
  830: 	    efree(tmp->value);
  831: 	    efree(tmp);
  832: 	}
  833: 	def->sd_un.list = NULL;
  834: 	debug_return;
  835:     }
  836: 
  837:     for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) {
  838: 	if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
  839: 
  840: 	    if (op == add)
  841: 		debug_return;		/* already exists */
  842: 
  843: 	    /* Delete node */
  844: 	    if (prev != NULL)
  845: 		prev->next = cur->next;
  846: 	    else
  847: 		def->sd_un.list = cur->next;
  848: 	    efree(cur->value);
  849: 	    efree(cur);
  850: 	    break;
  851: 	}
  852:     }
  853: 
  854:     /* Add new node to the head of the list. */
  855:     if (op == add) {
  856: 	cur = ecalloc(1, sizeof(struct list_member));
  857: 	cur->value = estrndup(val, len);
  858: 	cur->next = def->sd_un.list;
  859: 	def->sd_un.list = cur;
  860:     }
  861:     debug_return;
  862: }

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