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

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