[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.8

1.1       millert     1: /*
1.8     ! millert     2:  * Copyright (c) 1999-2001 Todd C. Miller <Todd.Miller@courtesan.com>
1.1       millert     3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  *
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  *
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * 3. The name of the author may not be used to endorse or promote products
                     17:  *    derived from this software without specific prior written permission.
                     18:  *
                     19:  * 4. Products derived from this software may not be called "Sudo" nor
                     20:  *    may "Sudo" appear in their names without specific prior written
                     21:  *    permission from the author.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     24:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     25:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
                     26:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     27:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     28:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     29:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     30:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     31:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     32:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34:
                     35: #include "config.h"
                     36:
1.8     ! millert    37: #include <sys/types.h>
        !            38: #include <sys/param.h>
1.1       millert    39: #include <stdio.h>
                     40: #ifdef STDC_HEADERS
1.8     ! millert    41: # include <stdlib.h>
        !            42: # include <stddef.h>
        !            43: #else
        !            44: # ifdef HAVE_STDLIB_H
        !            45: #  include <stdlib.h>
        !            46: # endif
1.1       millert    47: #endif /* STDC_HEADERS */
1.8     ! millert    48: #ifdef HAVE_STRING_H
        !            49: # include <string.h>
        !            50: #else
        !            51: # ifdef HAVE_STRINGS_H
        !            52: #  include <strings.h>
        !            53: # endif
        !            54: #endif /* HAVE_STRING_H */
        !            55: # ifdef HAVE_UNISTD_H
1.1       millert    56: #include <unistd.h>
                     57: #endif /* HAVE_UNISTD_H */
1.8     ! millert    58: #include <ctype.h>
1.1       millert    59:
                     60: #include "sudo.h"
                     61:
                     62: #ifndef lint
1.8     ! millert    63: static const char rcsid[] = "$Sudo: defaults.c,v 1.38 2001/12/30 18:40:09 millert Exp $";
1.1       millert    64: #endif /* lint */
                     65:
                     66: /*
                     67:  * For converting between syslog numbers and strings.
                     68:  */
                     69: struct strmap {
                     70:     char *name;
                     71:     int num;
                     72: };
                     73:
                     74: #ifdef LOG_NFACILITIES
                     75: static struct strmap facilities[] = {
                     76: #ifdef LOG_AUTHPRIV
                     77:        { "authpriv",   LOG_AUTHPRIV },
                     78: #endif
                     79:        { "auth",       LOG_AUTH },
                     80:        { "daemon",     LOG_DAEMON },
                     81:        { "user",       LOG_USER },
                     82:        { "local0",     LOG_LOCAL0 },
                     83:        { "local1",     LOG_LOCAL1 },
                     84:        { "local2",     LOG_LOCAL2 },
                     85:        { "local3",     LOG_LOCAL3 },
                     86:        { "local4",     LOG_LOCAL4 },
                     87:        { "local5",     LOG_LOCAL5 },
                     88:        { "local6",     LOG_LOCAL6 },
                     89:        { "local7",     LOG_LOCAL7 },
                     90:        { NULL,         -1 }
                     91: };
                     92: #endif /* LOG_NFACILITIES */
                     93:
                     94: static struct strmap priorities[] = {
                     95:        { "alert",      LOG_ALERT },
                     96:        { "crit",       LOG_CRIT },
                     97:        { "debug",      LOG_DEBUG },
                     98:        { "emerg",      LOG_EMERG },
                     99:        { "err",        LOG_ERR },
                    100:        { "info",       LOG_INFO },
                    101:        { "notice",     LOG_NOTICE },
                    102:        { "warning",    LOG_WARNING },
                    103:        { NULL,         -1 }
                    104: };
                    105:
                    106: extern int sudolineno;
                    107:
                    108: /*
                    109:  * Local prototypes.
                    110:  */
                    111: static int store_int __P((char *, struct sudo_defs_types *, int));
1.8     ! millert   112: static int store_uint __P((char *, struct sudo_defs_types *, int));
1.1       millert   113: static int store_str __P((char *, struct sudo_defs_types *, int));
                    114: static int store_syslogfac __P((char *, struct sudo_defs_types *, int));
                    115: static int store_syslogpri __P((char *, struct sudo_defs_types *, int));
                    116: static int store_mode __P((char *, struct sudo_defs_types *, int));
1.3       millert   117: static int store_pwflag __P((char *, struct sudo_defs_types *, int));
1.8     ! millert   118: static int store_list __P((char *, struct sudo_defs_types *, int));
        !           119: static void list_op __P((char *, size_t, struct sudo_defs_types *, enum list_ops));
1.1       millert   120:
                    121: /*
                    122:  * Table describing compile-time and run-time options.
                    123:  */
1.8     ! millert   124: #include <def_data.c>
1.1       millert   125:
                    126: /*
                    127:  * Print version and configure info.
                    128:  */
                    129: void
                    130: dump_defaults()
                    131: {
                    132:     struct sudo_defs_types *cur;
1.8     ! millert   133:     struct list_member *item;
1.1       millert   134:
                    135:     for (cur = sudo_defs_table; cur->name; cur++) {
                    136:        if (cur->desc) {
                    137:            switch (cur->type & T_MASK) {
                    138:                case T_FLAG:
                    139:                    if (cur->sd_un.flag)
                    140:                        puts(cur->desc);
                    141:                    break;
                    142:                case T_STR:
                    143:                case T_LOGFAC:
                    144:                case T_LOGPRI:
1.3       millert   145:                case T_PWFLAG:
1.1       millert   146:                    if (cur->sd_un.str) {
                    147:                        (void) printf(cur->desc, cur->sd_un.str);
                    148:                        putchar('\n');
                    149:                    }
                    150:                    break;
1.8     ! millert   151:                case T_UINT:
1.1       millert   152:                case T_INT:
                    153:                    (void) printf(cur->desc, cur->sd_un.ival);
                    154:                    putchar('\n');
                    155:                    break;
                    156:                case T_MODE:
                    157:                    (void) printf(cur->desc, cur->sd_un.mode);
                    158:                    putchar('\n');
                    159:                    break;
1.8     ! millert   160:                case T_LIST:
        !           161:                    if (cur->sd_un.list) {
        !           162:                        puts(cur->desc);
        !           163:                        for (item = cur->sd_un.list; item; item = item->next)
        !           164:                            printf("\t%s\n", item->value);
        !           165:                    }
        !           166:                    break;
1.1       millert   167:            }
                    168:        }
                    169:     }
                    170: }
                    171:
                    172: /*
                    173:  * List each option along with its description.
                    174:  */
                    175: void
                    176: list_options()
                    177: {
                    178:     struct sudo_defs_types *cur;
                    179:     char *p;
                    180:
                    181:     (void) puts("Available options in a sudoers ``Defaults'' line:\n");
                    182:     for (cur = sudo_defs_table; cur->name; cur++) {
                    183:        if (cur->name && cur->desc) {
                    184:            switch (cur->type & T_MASK) {
                    185:                case T_FLAG:
                    186:                    (void) printf("%s: %s\n", cur->name, cur->desc);
                    187:                    break;
                    188:                default:
                    189:                    p = strrchr(cur->desc, ':');
                    190:                    if (p)
1.8     ! millert   191:                        (void) printf("%s: %.*s\n", cur->name,
        !           192:                            (int) (p - cur->desc), cur->desc);
1.1       millert   193:                    else
                    194:                        (void) printf("%s: %s\n", cur->name, cur->desc);
                    195:                    break;
                    196:            }
                    197:        }
                    198:     }
                    199: }
                    200:
                    201: /*
                    202:  * Sets/clears an entry in the defaults structure
                    203:  * If a variable that takes a value is used in a boolean
                    204:  * context with op == 0, disable that variable.
                    205:  * Eg. you may want to turn off logging to a file for some hosts.
                    206:  * This is only meaningful for variables that are *optional*.
                    207:  */
                    208: int
                    209: set_default(var, val, op)
                    210:     char *var;
                    211:     char *val;
                    212:     int op;     /* TRUE or FALSE */
                    213: {
                    214:     struct sudo_defs_types *cur;
1.2       millert   215:     int num;
1.1       millert   216:
1.2       millert   217:     for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
1.1       millert   218:        if (strcmp(var, cur->name) == 0)
                    219:            break;
                    220:     }
                    221:     if (!cur->name) {
                    222:        (void) fprintf(stderr,
                    223:            "%s: unknown defaults entry `%s' referenced near line %d\n", Argv[0],
                    224:            var, sudolineno);
                    225:        return(FALSE);
                    226:     }
                    227:
                    228:     switch (cur->type & T_MASK) {
                    229:        case T_LOGFAC:
                    230:            if (!store_syslogfac(val, cur, op)) {
                    231:                if (val)
                    232:                    (void) fprintf(stderr,
                    233:                        "%s: value '%s' is invalid for option '%s'\n", Argv[0],
                    234:                        val, var);
                    235:                else
                    236:                    (void) fprintf(stderr,
                    237:                        "%s: no value specified for `%s' on line %d\n", Argv[0],
                    238:                        var, sudolineno);
                    239:                return(FALSE);
                    240:            }
                    241:            break;
                    242:        case T_LOGPRI:
                    243:            if (!store_syslogpri(val, cur, op)) {
                    244:                if (val)
                    245:                    (void) fprintf(stderr,
                    246:                        "%s: value '%s' is invalid for option '%s'\n", Argv[0],
                    247:                        val, var);
                    248:                else
                    249:                    (void) fprintf(stderr,
                    250:                        "%s: no value specified for `%s' on line %d\n", Argv[0],
                    251:                        var, sudolineno);
                    252:                return(FALSE);
                    253:            }
                    254:            break;
1.3       millert   255:        case T_PWFLAG:
                    256:            if (!store_pwflag(val, cur, op)) {
                    257:                if (val)
                    258:                    (void) fprintf(stderr,
                    259:                        "%s: value '%s' is invalid for option '%s'\n", Argv[0],
                    260:                        val, var);
                    261:                else
                    262:                    (void) fprintf(stderr,
                    263:                        "%s: no value specified for `%s' on line %d\n", Argv[0],
                    264:                        var, sudolineno);
                    265:                return(FALSE);
                    266:            }
                    267:            break;
1.1       millert   268:        case T_STR:
                    269:            if (!val) {
                    270:                /* Check for bogus boolean usage or lack of a value. */
                    271:                if (!(cur->type & T_BOOL) || op != FALSE) {
                    272:                    (void) fprintf(stderr,
                    273:                        "%s: no value specified for `%s' on line %d\n", Argv[0],
                    274:                        var, sudolineno);
                    275:                    return(FALSE);
                    276:                }
                    277:            }
1.7       millert   278:            if ((cur->type & T_PATH) && val && *val != '/') {
1.1       millert   279:                (void) fprintf(stderr,
                    280:                    "%s: values for `%s' must start with a '/'\n", Argv[0],
                    281:                    var);
                    282:                return(FALSE);
                    283:            }
                    284:            if (!store_str(val, cur, op)) {
                    285:                (void) fprintf(stderr,
                    286:                    "%s: value '%s' is invalid for option '%s'\n", Argv[0],
                    287:                    val, var);
                    288:                return(FALSE);
                    289:            }
                    290:            break;
                    291:        case T_INT:
                    292:            if (!val) {
                    293:                /* Check for bogus boolean usage or lack of a value. */
                    294:                if (!(cur->type & T_BOOL) || op != FALSE) {
                    295:                    (void) fprintf(stderr,
                    296:                        "%s: no value specified for `%s' on line %d\n", Argv[0],
                    297:                        var, sudolineno);
                    298:                    return(FALSE);
                    299:                }
                    300:            }
                    301:            if (!store_int(val, cur, op)) {
                    302:                (void) fprintf(stderr,
                    303:                    "%s: value '%s' is invalid for option '%s'\n", Argv[0],
                    304:                    val, var);
                    305:                return(FALSE);
                    306:            }
                    307:            break;
1.8     ! millert   308:        case T_UINT:
        !           309:            if (!val) {
        !           310:                /* Check for bogus boolean usage or lack of a value. */
        !           311:                if (!(cur->type & T_BOOL) || op != FALSE) {
        !           312:                    (void) fprintf(stderr,
        !           313:                        "%s: no value specified for `%s' on line %d\n", Argv[0],
        !           314:                        var, sudolineno);
        !           315:                    return(FALSE);
        !           316:                }
        !           317:            }
        !           318:            if (!store_uint(val, cur, op)) {
        !           319:                (void) fprintf(stderr,
        !           320:                    "%s: value '%s' is invalid for option '%s'\n", Argv[0],
        !           321:                    val, var);
        !           322:                return(FALSE);
        !           323:            }
        !           324:            break;
1.1       millert   325:        case T_MODE:
                    326:            if (!val) {
                    327:                /* Check for bogus boolean usage or lack of a value. */
                    328:                if (!(cur->type & T_BOOL) || op != FALSE) {
                    329:                    (void) fprintf(stderr,
                    330:                        "%s: no value specified for `%s' on line %d\n", Argv[0],
                    331:                        var, sudolineno);
                    332:                    return(FALSE);
                    333:                }
                    334:            }
                    335:            if (!store_mode(val, cur, op)) {
                    336:                (void) fprintf(stderr,
                    337:                    "%s: value '%s' is invalid for option '%s'\n", Argv[0],
                    338:                    val, var);
                    339:                return(FALSE);
                    340:            }
                    341:            break;
                    342:        case T_FLAG:
                    343:            if (val) {
                    344:                (void) fprintf(stderr,
                    345:                    "%s: option `%s' does not take a value on line %d\n",
                    346:                    Argv[0], var, sudolineno);
                    347:                return(FALSE);
                    348:            }
                    349:            cur->sd_un.flag = op;
1.2       millert   350:
                    351:            /* Special action for I_FQDN.  Move to own switch if we get more */
                    352:            if (num == I_FQDN && op)
                    353:                set_fqdn();
1.1       millert   354:            break;
1.8     ! millert   355:        case T_LIST:
        !           356:            if (!val) {
        !           357:                /* Check for bogus boolean usage or lack of a value. */
        !           358:                if (!(cur->type & T_BOOL) || op != FALSE) {
        !           359:                    (void) fprintf(stderr,
        !           360:                        "%s: no value specified for `%s' on line %d\n", Argv[0],
        !           361:                        var, sudolineno);
        !           362:                    return(FALSE);
        !           363:                }
        !           364:            }
        !           365:            if (!store_list(val, cur, op)) {
        !           366:                (void) fprintf(stderr,
        !           367:                    "%s: value '%s' is invalid for option '%s'\n", Argv[0],
        !           368:                    val, var);
        !           369:                return(FALSE);
        !           370:            }
1.1       millert   371:     }
                    372:
                    373:     return(TRUE);
                    374: }
                    375:
                    376: /*
                    377:  * Set default options to compiled-in values.
                    378:  * Any of these may be overridden at runtime by a "Defaults" file.
                    379:  */
                    380: void
                    381: init_defaults()
                    382: {
                    383:     static int firsttime = 1;
                    384:     struct sudo_defs_types *def;
                    385:
                    386:     /* Free any strings that were set. */
                    387:     if (!firsttime) {
                    388:        for (def = sudo_defs_table; def->name; def++)
                    389:            switch (def->type & T_MASK) {
                    390:                case T_STR:
                    391:                case T_LOGFAC:
                    392:                case T_LOGPRI:
1.3       millert   393:                case T_PWFLAG:
1.1       millert   394:                    if (def->sd_un.str) {
                    395:                        free(def->sd_un.str);
                    396:                        def->sd_un.str = NULL;
                    397:                    }
                    398:                    break;
1.8     ! millert   399:                case T_LIST:
        !           400:                    list_op(NULL, 0, def, freeall);
        !           401:                    break;
1.1       millert   402:            }
                    403:     }
                    404:
                    405:     /* First initialize the flags. */
                    406: #ifdef LONG_OTP_PROMPT
                    407:     def_flag(I_LONG_OTP_PROMPT) = TRUE;
                    408: #endif
                    409: #ifdef IGNORE_DOT_PATH
                    410:     def_flag(I_IGNORE_DOT) = TRUE;
                    411: #endif
                    412: #ifdef ALWAYS_SEND_MAIL
                    413:     def_flag(I_MAIL_ALWAYS) = TRUE;
                    414: #endif
                    415: #ifdef SEND_MAIL_WHEN_NO_USER
1.8     ! millert   416:     def_flag(I_MAIL_NO_USER) = TRUE;
1.1       millert   417: #endif
                    418: #ifdef SEND_MAIL_WHEN_NO_HOST
1.8     ! millert   419:     def_flag(I_MAIL_NO_HOST) = TRUE;
1.1       millert   420: #endif
                    421: #ifdef SEND_MAIL_WHEN_NOT_OK
1.8     ! millert   422:     def_flag(I_MAIL_NO_PERMS) = TRUE;
1.1       millert   423: #endif
                    424: #ifdef USE_TTY_TICKETS
                    425:     def_flag(I_TTY_TICKETS) = TRUE;
                    426: #endif
                    427: #ifndef NO_LECTURE
                    428:     def_flag(I_LECTURE) = TRUE;
                    429: #endif
                    430: #ifndef NO_AUTHENTICATION
                    431:     def_flag(I_AUTHENTICATE) = TRUE;
                    432: #endif
                    433: #ifndef NO_ROOT_SUDO
                    434:     def_flag(I_ROOT_SUDO) = TRUE;
                    435: #endif
                    436: #ifdef HOST_IN_LOG
                    437:     def_flag(I_LOG_HOST) = TRUE;
                    438: #endif
1.3       millert   439: #ifdef SHELL_IF_NO_ARGS
                    440:     def_flag(I_SHELL_NOARGS) = TRUE;
                    441: #endif
1.1       millert   442: #ifdef SHELL_SETS_HOME
                    443:     def_flag(I_SET_HOME) = TRUE;
                    444: #endif
                    445: #ifndef DONT_LEAK_PATH_INFO
                    446:     def_flag(I_PATH_INFO) = TRUE;
                    447: #endif
                    448: #ifdef FQDN
                    449:     def_flag(I_FQDN) = TRUE;
                    450: #endif
                    451: #ifdef USE_INSULTS
                    452:     def_flag(I_INSULTS) = TRUE;
                    453: #endif
1.4       millert   454: #ifdef ENV_EDITOR
                    455:     def_flag(I_ENV_EDITOR) = TRUE;
                    456: #endif
1.8     ! millert   457:     def_flag(I_SET_LOGNAME) = TRUE;
1.1       millert   458:
                    459:     /* Syslog options need special care since they both strings and ints */
                    460: #if (LOGGING & SLOG_SYSLOG)
1.8     ! millert   461:     (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG], TRUE);
        !           462:     (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI],
        !           463:        TRUE);
        !           464:     (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI],
        !           465:        TRUE);
1.1       millert   466: #endif
                    467:
1.3       millert   468:     /* Password flags also have a string and integer component. */
1.8     ! millert   469:     (void) store_pwflag("any", &sudo_defs_table[I_LISTPW], TRUE);
        !           470:     (void) store_pwflag("all", &sudo_defs_table[I_VERIFYPW], TRUE);
1.3       millert   471:
1.1       millert   472:     /* Then initialize the int-like things. */
                    473: #ifdef SUDO_UMASK
                    474:     def_mode(I_UMASK) = SUDO_UMASK;
                    475: #else
                    476:     def_mode(I_UMASK) = 0777;
                    477: #endif
1.8     ! millert   478:     def_ival(I_LOGLINELEN) = MAXLOGFILELEN;
        !           479:     def_ival(I_TIMESTAMP_TIMEOUT) = TIMEOUT;
        !           480:     def_ival(I_PASSWD_TIMEOUT) = PASSWORD_TIMEOUT;
        !           481:     def_ival(I_PASSWD_TRIES) = TRIES_FOR_PASSWORD;
1.1       millert   482:
1.8     ! millert   483:     /* Now do the strings */
1.1       millert   484:     def_str(I_MAILTO) = estrdup(MAILTO);
                    485:     def_str(I_MAILSUB) = estrdup(MAILSUBJECT);
1.8     ! millert   486:     def_str(I_BADPASS_MESSAGE) = estrdup(INCORRECT_PASSWORD);
1.1       millert   487:     def_str(I_TIMESTAMPDIR) = estrdup(_PATH_SUDO_TIMEDIR);
                    488:     def_str(I_PASSPROMPT) = estrdup(PASSPROMPT);
1.8     ! millert   489:     def_str(I_RUNAS_DEFAULT) = estrdup(RUNAS_DEFAULT);
        !           490: #ifdef _PATH_SUDO_SENDMAIL
        !           491:     def_str(I_MAILERPATH) = estrdup(_PATH_SUDO_SENDMAIL);
1.1       millert   492:     def_str(I_MAILERFLAGS) = estrdup("-t");
                    493: #endif
                    494: #if (LOGGING & SLOG_FILE)
                    495:     def_str(I_LOGFILE) = estrdup(_PATH_SUDO_LOGFILE);
                    496: #endif
                    497: #ifdef EXEMPTGROUP
1.8     ! millert   498:     def_str(I_EXEMPT_GROUP) = estrdup(EXEMPTGROUP);
1.1       millert   499: #endif
1.4       millert   500:     def_str(I_EDITOR) = estrdup(EDITOR);
1.1       millert   501:
1.8     ! millert   502:     /* Finally do the lists (currently just environment tables). */
        !           503:     init_envtables();
        !           504:
1.1       millert   505:     /*
                    506:      * The following depend on the above values.
                    507:      * We use a pointer to the string so that if its
                    508:      * value changes we get the change.
                    509:      */
                    510:     if (user_runas == NULL)
1.8     ! millert   511:        user_runas = &def_str(I_RUNAS_DEFAULT);
1.1       millert   512:
                    513:     firsttime = 0;
                    514: }
                    515:
                    516: static int
                    517: store_int(val, def, op)
                    518:     char *val;
                    519:     struct sudo_defs_types *def;
                    520:     int op;
                    521: {
                    522:     char *endp;
                    523:     long l;
                    524:
                    525:     if (op == FALSE) {
                    526:        def->sd_un.ival = 0;
                    527:     } else {
                    528:        l = strtol(val, &endp, 10);
1.8     ! millert   529:        if (*endp != '\0')
        !           530:            return(FALSE);
        !           531:        /* XXX - should check against INT_MAX */
        !           532:        def->sd_un.ival = (unsigned int)l;
        !           533:     }
        !           534:     return(TRUE);
        !           535: }
        !           536:
        !           537: static int
        !           538: store_uint(val, def, op)
        !           539:     char *val;
        !           540:     struct sudo_defs_types *def;
        !           541:     int op;
        !           542: {
        !           543:     char *endp;
        !           544:     long l;
        !           545:
        !           546:     if (op == FALSE) {
        !           547:        def->sd_un.ival = 0;
        !           548:     } else {
        !           549:        l = strtol(val, &endp, 10);
1.1       millert   550:        if (*endp != '\0' || l < 0)
                    551:            return(FALSE);
                    552:        /* XXX - should check against INT_MAX */
                    553:        def->sd_un.ival = (unsigned int)l;
                    554:     }
                    555:     return(TRUE);
                    556: }
                    557:
                    558: static int
                    559: store_str(val, def, op)
                    560:     char *val;
                    561:     struct sudo_defs_types *def;
                    562:     int op;
                    563: {
                    564:
                    565:     if (def->sd_un.str)
                    566:        free(def->sd_un.str);
                    567:     if (op == FALSE)
                    568:        def->sd_un.str = NULL;
                    569:     else
                    570:        def->sd_un.str = estrdup(val);
                    571:     return(TRUE);
                    572: }
                    573:
                    574: static int
1.8     ! millert   575: store_list(str, def, op)
        !           576:     char *str;
        !           577:     struct sudo_defs_types *def;
        !           578:     int op;
        !           579: {
        !           580:     char *start, *end;
        !           581:
        !           582:     /* Remove all old members. */
        !           583:     if (op == FALSE || op == TRUE)
        !           584:        list_op(NULL, 0, def, freeall);
        !           585:
        !           586:     /* Split str into multiple space-separated words and act on each one. */
        !           587:     if (op != FALSE) {
        !           588:        end = str;
        !           589:        do {
        !           590:            /* Remove leading blanks, if nothing but blanks we are done. */
        !           591:            for (start = end; isblank(*start); start++)
        !           592:                ;
        !           593:            if (*start == '\0')
        !           594:                break;
        !           595:
        !           596:            /* Find end position and perform operation. */
        !           597:            for (end = start; *end && !isblank(*end); end++)
        !           598:                ;
        !           599:            list_op(start, end - start, def, op == '-' ? delete : add);
        !           600:        } while (*end++ != '\0');
        !           601:     }
        !           602:     return(TRUE);
        !           603: }
        !           604:
        !           605: static int
1.1       millert   606: store_syslogfac(val, def, op)
                    607:     char *val;
                    608:     struct sudo_defs_types *def;
                    609:     int op;
                    610: {
                    611:     struct strmap *fac;
                    612:
                    613:     if (op == FALSE) {
1.3       millert   614:        if (def->sd_un.str) {
                    615:            free(def->sd_un.str);
                    616:            def->sd_un.str = NULL;
                    617:        }
1.1       millert   618:        return(TRUE);
                    619:     }
                    620: #ifdef LOG_NFACILITIES
                    621:     if (!val)
                    622:        return(FALSE);
                    623:     for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
                    624:        ;
                    625:     if (fac->name == NULL)
                    626:        return(FALSE);                          /* not found */
                    627:
                    628:     /* Store both name and number. */
1.8     ! millert   629:     if (def->sd_un.str)
1.1       millert   630:        free(def->sd_un.str);
                    631:     def->sd_un.str = estrdup(fac->name);
                    632:     sudo_defs_table[I_LOGFAC].sd_un.ival = fac->num;
                    633: #else
1.8     ! millert   634:     if (def->sd_un.str)
1.1       millert   635:        free(def->sd_un.str);
                    636:     def->sd_un.str = estrdup("default");
                    637: #endif /* LOG_NFACILITIES */
                    638:     return(TRUE);
                    639: }
                    640:
                    641: static int
                    642: store_syslogpri(val, def, op)
                    643:     char *val;
                    644:     struct sudo_defs_types *def;
                    645:     int op;
                    646: {
                    647:     struct strmap *pri;
                    648:     struct sudo_defs_types *idef;
                    649:
                    650:     if (op == FALSE || !val)
                    651:        return(FALSE);
1.8     ! millert   652:     if (def == &sudo_defs_table[I_SYSLOG_GOODPRI])
1.1       millert   653:        idef = &sudo_defs_table[I_GOODPRI];
1.8     ! millert   654:     else if (def == &sudo_defs_table[I_SYSLOG_BADPRI])
1.1       millert   655:        idef = &sudo_defs_table[I_BADPRI];
                    656:     else
                    657:        return(FALSE);
                    658:
                    659:     for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
                    660:        ;
                    661:     if (pri->name == NULL)
                    662:        return(FALSE);                          /* not found */
                    663:
                    664:     /* Store both name and number. */
                    665:     if (def->sd_un.str)
                    666:        free(def->sd_un.str);
                    667:     def->sd_un.str = estrdup(pri->name);
                    668:     idef->sd_un.ival = pri->num;
                    669:     return(TRUE);
                    670: }
                    671:
                    672: static int
                    673: store_mode(val, def, op)
                    674:     char *val;
                    675:     struct sudo_defs_types *def;
                    676:     int op;
                    677: {
                    678:     char *endp;
                    679:     long l;
                    680:
                    681:     if (op == FALSE) {
                    682:        def->sd_un.mode = (mode_t)0777;
                    683:     } else {
                    684:        l = strtol(val, &endp, 8);
1.5       millert   685:        if (*endp != '\0' || l < 0 || l > 0777)
1.1       millert   686:            return(FALSE);
                    687:        def->sd_un.mode = (mode_t)l;
                    688:     }
1.3       millert   689:     return(TRUE);
                    690: }
                    691:
                    692: static int
                    693: store_pwflag(val, def, op)
                    694:     char *val;
                    695:     struct sudo_defs_types *def;
                    696:     int op;
                    697: {
                    698:     int isub, flags;
                    699:
                    700:     if (strcmp(def->name, "verifypw") == 0)
1.8     ! millert   701:        isub = I_VERIFYPW_I;
1.3       millert   702:     else
1.8     ! millert   703:        isub = I_LISTPW_I;
1.3       millert   704:
                    705:     /* Handle !foo. */
                    706:     if (op == FALSE) {
                    707:        if (def->sd_un.str) {
                    708:            free(def->sd_un.str);
                    709:            def->sd_un.str = NULL;
                    710:        }
                    711:        def->sd_un.str = estrdup("never");
                    712:        sudo_defs_table[isub].sd_un.ival = PWCHECK_NEVER;
                    713:        return(TRUE);
                    714:     }
                    715:     if (!val)
                    716:        return(FALSE);
                    717:
                    718:     /* Convert strings to integer values. */
                    719:     if (strcmp(val, "all") == 0)
                    720:        flags = PWCHECK_ALL;
                    721:     else if (strcmp(val, "any") == 0)
                    722:        flags = PWCHECK_ANY;
                    723:     else if (strcmp(val, "never") == 0)
                    724:        flags = PWCHECK_NEVER;
                    725:     else if (strcmp(val, "always") == 0)
                    726:        flags = PWCHECK_ALWAYS;
                    727:     else
                    728:        return(FALSE);
                    729:
                    730:     /* Store both name and number. */
                    731:     if (def->sd_un.str)
                    732:        free(def->sd_un.str);
                    733:     def->sd_un.str = estrdup(val);
                    734:     sudo_defs_table[isub].sd_un.ival = flags;
                    735:
1.1       millert   736:     return(TRUE);
1.8     ! millert   737: }
        !           738:
        !           739: static void
        !           740: list_op(val, len, def, op)
        !           741:     char *val;
        !           742:     size_t len;
        !           743:     struct sudo_defs_types *def;
        !           744:     enum list_ops op;
        !           745: {
        !           746:     struct list_member *cur, *prev, *tmp;
        !           747:
        !           748:     if (op == freeall) {
        !           749:        for (cur = def->sd_un.list; cur; ) {
        !           750:            tmp = cur;
        !           751:            cur = tmp->next;
        !           752:            free(tmp->value);
        !           753:            free(tmp);
        !           754:        }
        !           755:        def->sd_un.list = NULL;
        !           756:        return;
        !           757:     }
        !           758:
        !           759:     for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) {
        !           760:        if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
        !           761:
        !           762:            if (op == add)
        !           763:                return;                 /* already exists */
        !           764:
        !           765:            /* Delete node */
        !           766:            if (prev != NULL)
        !           767:                prev->next = cur->next;
        !           768:            else
        !           769:                def->sd_un.list = cur->next;
        !           770:            free(cur->value);
        !           771:            free(cur);
        !           772:            break;
        !           773:        }
        !           774:     }
        !           775:
        !           776:     /* Add new node to the head of the list. */
        !           777:     if (op == add) {
        !           778:        cur = emalloc(sizeof(struct list_member));
        !           779:        cur->value = emalloc(len + 1);
        !           780:        (void) memcpy(cur->value, val, len);
        !           781:        cur->value[len] = '\0';
        !           782:        cur->next = def->sd_un.list;
        !           783:        def->sd_un.list = cur;
        !           784:     }
1.1       millert   785: }