Annotation of embedaddon/sudo/plugins/sudoers/sudo_nss.c, revision 1.1.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>