Annotation of embedaddon/sudo/plugins/sudoers/sudo_nss.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2007-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 <stdio.h>
        !            22: #ifdef STDC_HEADERS
        !            23: # include <stdlib.h>
        !            24: # include <stddef.h>
        !            25: #else
        !            26: # ifdef HAVE_STDLIB_H
        !            27: #  include <stdlib.h>
        !            28: # endif
        !            29: #endif /* STDC_HEADERS */
        !            30: #ifdef HAVE_STRING_H
        !            31: # include <string.h>
        !            32: #endif /* HAVE_STRING_H */
        !            33: #ifdef HAVE_STRINGS_H
        !            34: # include <strings.h>
        !            35: #endif /* HAVE_STRINGS_H */
        !            36: #ifdef HAVE_UNISTD_H
        !            37: # include <unistd.h>
        !            38: #endif /* HAVE_UNISTD_H */
        !            39: #include <pwd.h>
        !            40: #include <grp.h>
        !            41: #include <ctype.h>
        !            42: 
        !            43: #include "sudoers.h"
        !            44: #include "lbuf.h"
        !            45: 
        !            46: extern struct sudo_nss sudo_nss_file;
        !            47: #ifdef HAVE_LDAP
        !            48: extern struct sudo_nss sudo_nss_ldap;
        !            49: #endif
        !            50: 
        !            51: #if defined(HAVE_LDAP) && defined(_PATH_NSSWITCH_CONF)
        !            52: /*
        !            53:  * Read in /etc/nsswitch.conf
        !            54:  * Returns a tail queue of matches.
        !            55:  */
        !            56: struct sudo_nss_list *
        !            57: sudo_read_nss(void)
        !            58: {
        !            59:     FILE *fp;
        !            60:     char *cp;
        !            61:     int saw_files = FALSE;
        !            62:     int saw_ldap = FALSE;
        !            63:     int got_match = FALSE;
        !            64:     static struct sudo_nss_list snl;
        !            65: 
        !            66:     if ((fp = fopen(_PATH_NSSWITCH_CONF, "r")) == NULL)
        !            67:        goto nomatch;
        !            68: 
        !            69:     while ((cp = sudo_parseln(fp)) != NULL) {
        !            70:        /* Skip blank or comment lines */
        !            71:        if (*cp == '\0')
        !            72:            continue;
        !            73: 
        !            74:        /* Look for a line starting with "sudoers:" */
        !            75:        if (strncasecmp(cp, "sudoers:", 8) != 0)
        !            76:            continue;
        !            77: 
        !            78:        /* Parse line */
        !            79:        for ((cp = strtok(cp + 8, " \t")); cp != NULL; (cp = strtok(NULL, " \t"))) {
        !            80:            if (strcasecmp(cp, "files") == 0 && !saw_files) {
        !            81:                tq_append(&snl, &sudo_nss_file);
        !            82:                got_match = TRUE;
        !            83:            } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) {
        !            84:                tq_append(&snl, &sudo_nss_ldap);
        !            85:                got_match = TRUE;
        !            86:            } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) {
        !            87:                /* NOTFOUND affects the most recent entry */
        !            88:                tq_last(&snl)->ret_if_notfound = TRUE;
        !            89:                got_match = FALSE;
        !            90:            } else
        !            91:                got_match = FALSE;
        !            92:        }
        !            93:        /* Only parse the first "sudoers:" line */
        !            94:        break;
        !            95:     }
        !            96:     fclose(fp);
        !            97: 
        !            98: nomatch:
        !            99:     /* Default to files only if no matches */
        !           100:     if (tq_empty(&snl))
        !           101:        tq_append(&snl, &sudo_nss_file);
        !           102: 
        !           103:     return &snl;
        !           104: }
        !           105: 
        !           106: #else /* HAVE_LDAP && _PATH_NSSWITCH_CONF */
        !           107: 
        !           108: # if defined(HAVE_LDAP) && defined(_PATH_NETSVC_CONF)
        !           109: 
        !           110: /*
        !           111:  * Read in /etc/netsvc.conf (like nsswitch.conf on AIX)
        !           112:  * Returns a tail queue of matches.
        !           113:  */
        !           114: struct sudo_nss_list *
        !           115: sudo_read_nss(void)
        !           116: {
        !           117:     FILE *fp;
        !           118:     char *cp, *ep;
        !           119:     int saw_files = FALSE;
        !           120:     int saw_ldap = FALSE;
        !           121:     int got_match = FALSE;
        !           122:     static struct sudo_nss_list snl;
        !           123: 
        !           124:     if ((fp = fopen(_PATH_NETSVC_CONF, "r")) == NULL)
        !           125:        goto nomatch;
        !           126: 
        !           127:     while ((cp = sudo_parseln(fp)) != NULL) {
        !           128:        /* Skip blank or comment lines */
        !           129:        if (*cp == '\0')
        !           130:            continue;
        !           131: 
        !           132:        /* Look for a line starting with "sudoers = " */
        !           133:        if (strncasecmp(cp, "sudoers", 7) != 0)
        !           134:            continue;
        !           135:        cp += 7;
        !           136:        while (isspace((unsigned char)*cp))
        !           137:            cp++;
        !           138:        if (*cp++ != '=')
        !           139:            continue;
        !           140: 
        !           141:        /* Parse line */
        !           142:        for ((cp = strtok(cp, ",")); cp != NULL; (cp = strtok(NULL, ","))) {
        !           143:            /* Trim leading whitespace. */
        !           144:            while (isspace((unsigned char)*cp))
        !           145:                cp++;
        !           146: 
        !           147:            if (!saw_files && strncasecmp(cp, "files", 5) == 0 &&
        !           148:                (isspace((unsigned char)cp[5]) || cp[5] == '\0')) {
        !           149:                tq_append(&snl, &sudo_nss_file);
        !           150:                got_match = TRUE;
        !           151:                ep = &cp[5];
        !           152:            } else if (!saw_ldap && strncasecmp(cp, "ldap", 4) == 0 &&
        !           153:                (isspace((unsigned char)cp[4]) || cp[4] == '\0')) {
        !           154:                tq_append(&snl, &sudo_nss_ldap);
        !           155:                got_match = TRUE;
        !           156:                ep = &cp[4];
        !           157:            } else {
        !           158:                got_match = FALSE;
        !           159:            }
        !           160: 
        !           161:            /* check for = auth qualifier */
        !           162:            if (got_match && *ep) {
        !           163:                cp = ep;
        !           164:                while (isspace((unsigned char)*cp) || *cp == '=')
        !           165:                    cp++;
        !           166:                if (strncasecmp(cp, "auth", 4) == 0 &&
        !           167:                    (isspace((unsigned char)cp[4]) || cp[4] == '\0')) {
        !           168:                    tq_last(&snl)->ret_if_found = TRUE;
        !           169:                }
        !           170:            }
        !           171:        }
        !           172:        /* Only parse the first "sudoers" line */
        !           173:        break;
        !           174:     }
        !           175:     fclose(fp);
        !           176: 
        !           177: nomatch:
        !           178:     /* Default to files only if no matches */
        !           179:     if (tq_empty(&snl))
        !           180:        tq_append(&snl, &sudo_nss_file);
        !           181: 
        !           182:     return &snl;
        !           183: }
        !           184: 
        !           185: # else /* !_PATH_NETSVC_CONF && !_PATH_NSSWITCH_CONF */
        !           186: 
        !           187: /*
        !           188:  * Non-nsswitch.conf version with hard-coded order.
        !           189:  */
        !           190: struct sudo_nss_list *
        !           191: sudo_read_nss(void)
        !           192: {
        !           193:     static struct sudo_nss_list snl;
        !           194: 
        !           195: #  ifdef HAVE_LDAP
        !           196:     tq_append(&snl, &sudo_nss_ldap);
        !           197: #  endif
        !           198:     tq_append(&snl, &sudo_nss_file);
        !           199: 
        !           200:     return &snl;
        !           201: }
        !           202: 
        !           203: # endif /* !HAVE_LDAP || !_PATH_NETSVC_CONF */
        !           204: 
        !           205: #endif /* HAVE_LDAP && _PATH_NSSWITCH_CONF */
        !           206: 
        !           207: static int
        !           208: output(const char *buf)
        !           209: {
        !           210:     struct sudo_conv_message msg;
        !           211:     struct sudo_conv_reply repl;
        !           212: 
        !           213:     /* Call conversation function */
        !           214:     memset(&msg, 0, sizeof(msg));
        !           215:     msg.msg_type = SUDO_CONV_INFO_MSG;
        !           216:     msg.msg = buf;
        !           217:     memset(&repl, 0, sizeof(repl));
        !           218:     if (sudo_conv(1, &msg, &repl) == -1)
        !           219:        return 0;
        !           220:     return (int)strlen(buf);
        !           221: }
        !           222: 
        !           223: /*
        !           224:  * Print out privileges for the specified user.
        !           225:  * We only get here if the user is allowed to run something on this host.
        !           226:  */
        !           227: void
        !           228: display_privs(struct sudo_nss_list *snl, struct passwd *pw)
        !           229: {
        !           230:     struct sudo_nss *nss;
        !           231:     struct lbuf defs, privs;
        !           232:     int count, olen;
        !           233: 
        !           234:     lbuf_init(&defs, output, 4, NULL, sudo_user.cols);
        !           235:     lbuf_init(&privs, output, 4, NULL, sudo_user.cols);
        !           236: 
        !           237:     /* Display defaults from all sources. */
        !           238:     lbuf_append(&defs, _("Matching Defaults entries for %s on this host:\n"),
        !           239:        pw->pw_name);
        !           240:     count = 0;
        !           241:     tq_foreach_fwd(snl, nss) {
        !           242:        count += nss->display_defaults(nss, pw, &defs);
        !           243:     }
        !           244:     if (count)
        !           245:        lbuf_append(&defs, "\n\n");
        !           246:     else
        !           247:        defs.len = 0;
        !           248: 
        !           249:     /* Display Runas and Cmnd-specific defaults from all sources. */
        !           250:     olen = defs.len;
        !           251:     lbuf_append(&defs, _("Runas and Command-specific defaults for %s:\n"),
        !           252:        pw->pw_name);
        !           253:     count = 0;
        !           254:     tq_foreach_fwd(snl, nss) {
        !           255:        count += nss->display_bound_defaults(nss, pw, &defs);
        !           256:     }
        !           257:     if (count)
        !           258:        lbuf_append(&defs, "\n\n");
        !           259:     else
        !           260:        defs.len = olen;
        !           261: 
        !           262:     /* Display privileges from all sources. */
        !           263:     lbuf_append(&privs,
        !           264:        _("User %s may run the following commands on this host:\n"),
        !           265:        pw->pw_name);
        !           266:     count = 0;
        !           267:     tq_foreach_fwd(snl, nss) {
        !           268:        count += nss->display_privs(nss, pw, &privs);
        !           269:     }
        !           270:     if (count) {
        !           271:        lbuf_print(&defs);
        !           272:        lbuf_print(&privs);
        !           273:     } else {
        !           274:        printf(_("User %s is not allowed to run sudo on %s.\n"), pw->pw_name,
        !           275:            user_shost);
        !           276:     }
        !           277: 
        !           278:     lbuf_destroy(&defs);
        !           279:     lbuf_destroy(&privs);
        !           280: }
        !           281: 
        !           282: /*
        !           283:  * Check user_cmnd against sudoers and print the matching entry if the
        !           284:  * command is allowed.
        !           285:  * Returns TRUE if the command is allowed, else FALSE.
        !           286:  */
        !           287: int
        !           288: display_cmnd(struct sudo_nss_list *snl, struct passwd *pw)
        !           289: {
        !           290:     struct sudo_nss *nss;
        !           291: 
        !           292:     tq_foreach_fwd(snl, nss) {
        !           293:        if (nss->display_cmnd(nss, pw) == 0)
        !           294:            return TRUE;
        !           295:     }
        !           296:     return FALSE;
        !           297: }

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