Annotation of embedaddon/sudo/common/sudo_conf.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2009-2011 Todd C. Miller <Todd.Miller@courtesan.com>
        !             3:  *
        !             4:  * Permission to use, copy, modify, and distribute this software for any
        !             5:  * purpose with or without fee is hereby granted, provided that the above
        !             6:  * copyright notice and this permission notice appear in all copies.
        !             7:  *
        !             8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !             9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            15:  */
        !            16: 
        !            17: #include <config.h>
        !            18: 
        !            19: #include <sys/types.h>
        !            20: #include <sys/param.h>
        !            21: #include <sys/stat.h>
        !            22: #include <stdio.h>
        !            23: #ifdef STDC_HEADERS
        !            24: # include <stdlib.h>
        !            25: # include <stddef.h>
        !            26: #else
        !            27: # ifdef HAVE_STDLIB_H
        !            28: #  include <stdlib.h>
        !            29: # endif
        !            30: #endif /* STDC_HEADERS */
        !            31: #ifdef HAVE_STDBOOL_H
        !            32: # include <stdbool.h>
        !            33: #else
        !            34: # include "compat/stdbool.h"
        !            35: #endif
        !            36: #ifdef HAVE_STRING_H
        !            37: # include <string.h>
        !            38: #endif /* HAVE_STRING_H */
        !            39: #ifdef HAVE_STRINGS_H
        !            40: # include <strings.h>
        !            41: #endif /* HAVE_STRINGS_H */
        !            42: #ifdef HAVE_UNISTD_H
        !            43: # include <unistd.h>
        !            44: #endif /* HAVE_UNISTD_H */
        !            45: #include <ctype.h>
        !            46: #include <errno.h>
        !            47: 
        !            48: #define SUDO_ERROR_WRAP        0
        !            49: 
        !            50: #include "missing.h"
        !            51: #include "alloc.h"
        !            52: #include "error.h"
        !            53: #include "fileops.h"
        !            54: #include "pathnames.h"
        !            55: #include "sudo_plugin.h"
        !            56: #include "sudo_conf.h"
        !            57: #include "sudo_debug.h"
        !            58: #include "secure_path.h"
        !            59: #include "gettext.h"
        !            60: 
        !            61: #ifdef __TANDEM
        !            62: # define ROOT_UID      65535
        !            63: #else
        !            64: # define ROOT_UID      0
        !            65: #endif
        !            66: 
        !            67: #ifndef _PATH_SUDO_ASKPASS
        !            68: # define _PATH_SUDO_ASKPASS    NULL
        !            69: #endif
        !            70: 
        !            71: extern bool atobool(const char *str); /* atobool.c */
        !            72: 
        !            73: struct sudo_conf_table {
        !            74:     const char *name;
        !            75:     unsigned int namelen;
        !            76:     bool (*setter)(const char *entry);
        !            77: };
        !            78: 
        !            79: struct sudo_conf_paths {
        !            80:     const char *pname;
        !            81:     unsigned int pnamelen;
        !            82:     const char *pval;
        !            83: };
        !            84: 
        !            85: static bool set_debug(const char *entry);
        !            86: static bool set_path(const char *entry);
        !            87: static bool set_plugin(const char *entry);
        !            88: static bool set_variable(const char *entry);
        !            89: 
        !            90: static struct sudo_conf_table sudo_conf_table[] = {
        !            91:     { "Debug", sizeof("Debug") - 1, set_debug },
        !            92:     { "Path", sizeof("Path") - 1, set_path },
        !            93:     { "Plugin", sizeof("Plugin") - 1, set_plugin },
        !            94:     { "Set", sizeof("Set") - 1, set_variable },
        !            95:     { NULL }
        !            96: };
        !            97: 
        !            98: static struct sudo_conf_data {
        !            99:     bool disable_coredump;
        !           100:     const char *debug_flags;
        !           101:     struct sudo_conf_paths paths[3];
        !           102:     struct plugin_info_list plugins;
        !           103: } sudo_conf_data = {
        !           104:     true,
        !           105:     NULL,
        !           106:     {
        !           107: #define SUDO_CONF_ASKPASS_IDX  0
        !           108:        { "askpass", sizeof("askpass") - 1, _PATH_SUDO_ASKPASS },
        !           109: #ifdef _PATH_SUDO_NOEXEC
        !           110: #define SUDO_CONF_NOEXEC_IDX   1
        !           111:        { "noexec", sizeof("noexec") - 1, _PATH_SUDO_NOEXEC },
        !           112: #endif
        !           113:        { NULL }
        !           114:     }
        !           115: };
        !           116: 
        !           117: /*
        !           118:  * "Set variable_name value"
        !           119:  */
        !           120: static bool
        !           121: set_variable(const char *entry)
        !           122: {
        !           123: #undef DC_LEN
        !           124: #define DC_LEN (sizeof("disable_coredump") - 1)
        !           125:     /* Currently the only variable supported is "disable_coredump". */
        !           126:     if (strncmp(entry, "disable_coredump", DC_LEN) == 0 &&
        !           127:        isblank((unsigned char)entry[DC_LEN])) {
        !           128:        entry += DC_LEN + 1;
        !           129:        while (isblank((unsigned char)*entry))
        !           130:            entry++;
        !           131:        sudo_conf_data.disable_coredump = atobool(entry);
        !           132:     }
        !           133: #undef DC_LEN
        !           134:     return true;
        !           135: }
        !           136: 
        !           137: /*
        !           138:  * "Debug progname debug_file debug_flags"
        !           139:  */
        !           140: static bool
        !           141: set_debug(const char *entry)
        !           142: {
        !           143:     size_t filelen, proglen;
        !           144:     const char *progname;
        !           145:     char *debug_file, *debug_flags;
        !           146: 
        !           147:     /* Is this debug setting for me? */
        !           148:     progname = getprogname();
        !           149:     if (strcmp(progname, "sudoedit") == 0)
        !           150:        progname = "sudo";
        !           151:     proglen = strlen(progname);
        !           152:     if (strncmp(entry, progname, proglen) != 0 ||
        !           153:        !isblank((unsigned char)entry[proglen]))
        !           154:        return false;
        !           155:     entry += proglen + 1;
        !           156:     while (isblank((unsigned char)*entry))
        !           157:        entry++;
        !           158: 
        !           159:     debug_flags = strpbrk(entry, " \t");
        !           160:     if (debug_flags == NULL)
        !           161:        return false;
        !           162:     filelen = (size_t)(debug_flags - entry);
        !           163:     while (isblank((unsigned char)*debug_flags))
        !           164:        debug_flags++;
        !           165: 
        !           166:     /* Set debug file and parse the flags (init debug as soon as possible). */
        !           167:     debug_file = estrndup(entry, filelen);
        !           168:     debug_flags = estrdup(debug_flags);
        !           169:     sudo_debug_init(debug_file, debug_flags);
        !           170:     efree(debug_file);
        !           171: 
        !           172:     sudo_conf_data.debug_flags = debug_flags;
        !           173: 
        !           174:     return true;
        !           175: }
        !           176: 
        !           177: static bool
        !           178: set_path(const char *entry)
        !           179: {
        !           180:     const char *name, *path;
        !           181:     struct sudo_conf_paths *cur;
        !           182: 
        !           183:     /* Parse Path line */
        !           184:     name = entry;
        !           185:     path = strpbrk(entry, " \t");
        !           186:     if (path == NULL)
        !           187:        return false;
        !           188:     while (isblank((unsigned char)*path))
        !           189:        path++;
        !           190: 
        !           191:     /* Match supported paths, ignore the rest. */
        !           192:     for (cur = sudo_conf_data.paths; cur->pname != NULL; cur++) {
        !           193:        if (strncasecmp(name, cur->pname, cur->pnamelen) == 0 &&
        !           194:            isblank((unsigned char)name[cur->pnamelen])) {
        !           195:            cur->pval = estrdup(path);
        !           196:            break;
        !           197:        }
        !           198:     }
        !           199: 
        !           200:     return true;
        !           201: }
        !           202: 
        !           203: static bool
        !           204: set_plugin(const char *entry)
        !           205: {
        !           206:     struct plugin_info *info;
        !           207:     const char *name, *path, *cp, *ep;
        !           208:     char **options = NULL;
        !           209:     size_t namelen, pathlen;
        !           210:     unsigned int nopts;
        !           211: 
        !           212:     /* Parse Plugin line */
        !           213:     name = entry;
        !           214:     path = strpbrk(entry, " \t");
        !           215:     if (path == NULL)
        !           216:        return false;
        !           217:     namelen = (size_t)(path - name);
        !           218:     while (isblank((unsigned char)*path))
        !           219:        path++;
        !           220:     if ((cp = strpbrk(path, " \t")) != NULL) {
        !           221:        /* Convert any options to an array. */
        !           222:        pathlen = (size_t)(cp - path);
        !           223:        while (isblank((unsigned char)*cp))
        !           224:            cp++;
        !           225:        /* Count number of options and allocate array. */
        !           226:        for (ep = cp, nopts = 1; (ep = strpbrk(ep, " \t")) != NULL; nopts++) {
        !           227:            while (isblank((unsigned char)*ep))
        !           228:                ep++;
        !           229:        }
        !           230:        options = emalloc2(nopts + 1, sizeof(*options));
        !           231:        /* Fill in options array, there is at least one element. */
        !           232:        for (nopts = 0; (ep = strpbrk(cp, " \t")) != NULL; ) {
        !           233:            options[nopts++] = estrndup(cp, (size_t)(ep - cp));
        !           234:            while (isblank((unsigned char)*ep))
        !           235:                ep++;
        !           236:            cp = ep;
        !           237:        }
        !           238:        options[nopts++] = estrdup(cp);
        !           239:        options[nopts] = NULL;
        !           240:     } else {
        !           241:        /* No extra options. */
        !           242:        pathlen = strlen(path);
        !           243:     }
        !           244: 
        !           245:     info = ecalloc(1, sizeof(*info));
        !           246:     info->symbol_name = estrndup(name, namelen);
        !           247:     info->path = estrndup(path, pathlen);
        !           248:     info->options = options;
        !           249:     info->prev = info;
        !           250:     /* info->next = NULL; */
        !           251:     tq_append(&sudo_conf_data.plugins, info);
        !           252: 
        !           253:     return true;
        !           254: }
        !           255: 
        !           256: const char *
        !           257: sudo_conf_askpass_path(void)
        !           258: {
        !           259:     return sudo_conf_data.paths[SUDO_CONF_ASKPASS_IDX].pval;
        !           260: }
        !           261: 
        !           262: #ifdef _PATH_SUDO_NOEXEC
        !           263: const char *
        !           264: sudo_conf_noexec_path(void)
        !           265: {
        !           266:     return sudo_conf_data.paths[SUDO_CONF_NOEXEC_IDX].pval;
        !           267: }
        !           268: #endif
        !           269: 
        !           270: const char *
        !           271: sudo_conf_debug_flags(void)
        !           272: {
        !           273:     return sudo_conf_data.debug_flags;
        !           274: }
        !           275: 
        !           276: struct plugin_info_list *
        !           277: sudo_conf_plugins(void)
        !           278: {
        !           279:     return &sudo_conf_data.plugins;
        !           280: }
        !           281: 
        !           282: bool
        !           283: sudo_conf_disable_coredump(void)
        !           284: {
        !           285:     return sudo_conf_data.disable_coredump;
        !           286: }
        !           287: 
        !           288: /*
        !           289:  * Reads in /etc/sudo.conf and populates sudo_conf_data.
        !           290:  */
        !           291: void
        !           292: sudo_conf_read(void)
        !           293: {
        !           294:     struct sudo_conf_table *cur;
        !           295:     struct plugin_info *info;
        !           296:     struct stat sb;
        !           297:     FILE *fp;
        !           298:     char *cp;
        !           299: 
        !           300:     switch (sudo_secure_file(_PATH_SUDO_CONF, ROOT_UID, -1, &sb)) {
        !           301:        case SUDO_PATH_SECURE:
        !           302:            break;
        !           303:        case SUDO_PATH_MISSING:
        !           304:            /* Root should always be able to read sudo.conf. */
        !           305:            if (errno != ENOENT && geteuid() == ROOT_UID)
        !           306:                warning(_("unable to stat %s"), _PATH_SUDO_CONF);
        !           307:            goto done;
        !           308:        case SUDO_PATH_BAD_TYPE:
        !           309:            warningx(_("%s is not a regular file"), _PATH_SUDO_CONF);
        !           310:            goto done;
        !           311:        case SUDO_PATH_WRONG_OWNER:
        !           312:            warningx(_("%s is owned by uid %u, should be %u"),
        !           313:                _PATH_SUDO_CONF, (unsigned int) sb.st_uid, ROOT_UID);
        !           314:            goto done;
        !           315:        case SUDO_PATH_WORLD_WRITABLE:
        !           316:            warningx(_("%s is world writable"), _PATH_SUDO_CONF);
        !           317:            goto done;
        !           318:        case SUDO_PATH_GROUP_WRITABLE:
        !           319:            warningx(_("%s is group writable"), _PATH_SUDO_CONF);
        !           320:            goto done;
        !           321:        default:
        !           322:            /* NOTREACHED */
        !           323:            goto done;
        !           324:     }
        !           325: 
        !           326:     if ((fp = fopen(_PATH_SUDO_CONF, "r")) == NULL) {
        !           327:        if (errno != ENOENT && geteuid() == ROOT_UID)
        !           328:            warning(_("unable to open %s"), _PATH_SUDO_CONF);
        !           329:        goto done;
        !           330:     }
        !           331: 
        !           332:     while ((cp = sudo_parseln(fp)) != NULL) {
        !           333:        /* Skip blank or comment lines */
        !           334:        if (*cp == '\0')
        !           335:            continue;
        !           336: 
        !           337:        for (cur = sudo_conf_table; cur->name != NULL; cur++) {
        !           338:            if (strncasecmp(cp, cur->name, cur->namelen) == 0 &&
        !           339:                isblank((unsigned char)cp[cur->namelen])) {
        !           340:                cp += cur->namelen;
        !           341:                while (isblank((unsigned char)*cp))
        !           342:                    cp++;
        !           343:                if (cur->setter(cp))
        !           344:                    break;
        !           345:            }
        !           346:        }
        !           347:     }
        !           348:     fclose(fp);
        !           349: 
        !           350: done:
        !           351:     if (tq_empty(&sudo_conf_data.plugins)) {
        !           352:        /* Default policy plugin */
        !           353:        info = ecalloc(1, sizeof(*info));
        !           354:        info->symbol_name = "sudoers_policy";
        !           355:        info->path = SUDOERS_PLUGIN;
        !           356:        /* info->options = NULL; */
        !           357:        info->prev = info;
        !           358:        /* info->next = NULL; */
        !           359:        tq_append(&sudo_conf_data.plugins, info);
        !           360: 
        !           361:        /* Default I/O plugin */
        !           362:        info = ecalloc(1, sizeof(*info));
        !           363:        info->symbol_name = "sudoers_io";
        !           364:        info->path = SUDOERS_PLUGIN;
        !           365:        /* info->options = NULL; */
        !           366:        info->prev = info;
        !           367:        /* info->next = NULL; */
        !           368:        tq_append(&sudo_conf_data.plugins, info);
        !           369:     }
        !           370: }

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