[BACK]Return to defaults.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Annotation of src/usr.bin/sudo/defaults.c, Revision 1.15

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