Annotation of src/usr.bin/sudo/sudo_nss.c, Revision 1.1
1.1 ! millert 1: /*
! 2: * Copyright (c) 2007-2008 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: #else
! 33: # ifdef HAVE_STRINGS_H
! 34: # include <strings.h>
! 35: # endif
! 36: #endif /* HAVE_STRING_H */
! 37: #ifdef HAVE_UNISTD_H
! 38: # include <unistd.h>
! 39: #endif /* HAVE_UNISTD_H */
! 40: #include <pwd.h>
! 41: #include <grp.h>
! 42:
! 43: #include "sudo.h"
! 44: #include "lbuf.h"
! 45:
! 46: #ifndef lint
! 47: __unused static const char rcsid[] = "$Sudo: sudo_nss.c,v 1.6 2008/02/08 13:18:12 millert Exp $";
! 48: #endif /* lint */
! 49:
! 50: extern struct sudo_nss sudo_nss_file;
! 51: #ifdef HAVE_LDAP
! 52: extern struct sudo_nss sudo_nss_ldap;
! 53: #endif
! 54:
! 55: #if defined(HAVE_LDAP) && defined(_PATH_NSSWITCH_CONF)
! 56: /*
! 57: * Read in /etc/nsswitch.conf
! 58: * Returns a tail queue of matches.
! 59: */
! 60: struct sudo_nss_list *
! 61: sudo_read_nss()
! 62: {
! 63: FILE *fp;
! 64: char *cp;
! 65: int saw_files = FALSE;
! 66: int saw_ldap = FALSE;
! 67: int got_match = FALSE;
! 68: static struct sudo_nss_list snl;
! 69:
! 70: if ((fp = fopen(_PATH_NSSWITCH_CONF, "r")) == NULL)
! 71: goto nomatch;
! 72:
! 73: while ((cp = sudo_parseln(fp)) != NULL) {
! 74: /* Skip blank or comment lines */
! 75: if (*cp == '\0')
! 76: continue;
! 77:
! 78: /* Look for a line starting with "sudoers:" */
! 79: if (strncasecmp(cp, "sudoers:", 8) != 0)
! 80: continue;
! 81:
! 82: /* Parse line */
! 83: for ((cp = strtok(cp + 8, " \t")); cp != NULL; (cp = strtok(NULL, " \t"))) {
! 84: if (strcasecmp(cp, "files") == 0 && !saw_files) {
! 85: tq_append(&snl, &sudo_nss_file);
! 86: got_match = TRUE;
! 87: } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) {
! 88: tq_append(&snl, &sudo_nss_ldap);
! 89: got_match = TRUE;
! 90: } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) {
! 91: /* NOTFOUND affects the most recent entry */
! 92: tq_last(&snl)->ret_notfound = TRUE;
! 93: got_match = FALSE;
! 94: } else
! 95: got_match = FALSE;
! 96: }
! 97: /* Only parse the first "sudoers:" line */
! 98: break;
! 99: }
! 100: fclose(fp);
! 101:
! 102: nomatch:
! 103: /* Default to files only if no matches */
! 104: if (tq_empty(&snl))
! 105: tq_append(&snl, &sudo_nss_file);
! 106:
! 107: return(&snl);
! 108: }
! 109:
! 110: #else /* HAVE_LDAP && _PATH_NSSWITCH_CONF */
! 111:
! 112: /*
! 113: * Non-nsswitch.conf version with hard-coded order.
! 114: */
! 115: struct sudo_nss_list *
! 116: sudo_read_nss()
! 117: {
! 118: static struct sudo_nss_list snl;
! 119:
! 120: # ifdef HAVE_LDAP
! 121: tq_append(&snl, &sudo_nss_ldap);
! 122: # endif
! 123: tq_append(&snl, &sudo_nss_file);
! 124:
! 125: return(&snl);
! 126: }
! 127:
! 128: #endif /* HAVE_LDAP && _PATH_NSSWITCH_CONF */
! 129:
! 130: /* Reset user_groups based on passwd entry. */
! 131: static void
! 132: reset_groups(pw)
! 133: struct passwd *pw;
! 134: {
! 135: #if defined(HAVE_INITGROUPS) && defined(HAVE_GETGROUPS)
! 136: if (pw != sudo_user.pw) {
! 137: (void) initgroups(pw->pw_name, pw->pw_gid);
! 138: if ((user_ngroups = getgroups(0, NULL)) > 0) {
! 139: user_groups = erealloc3(user_groups, user_ngroups,
! 140: sizeof(GETGROUPS_T));
! 141: if (getgroups(user_ngroups, user_groups) < 0)
! 142: log_error(USE_ERRNO|MSG_ONLY, "can't get group vector");
! 143: } else {
! 144: user_ngroups = 0;
! 145: efree(user_groups);
! 146: }
! 147: }
! 148: #endif
! 149: }
! 150:
! 151: /*
! 152: * Print out privileges for the specified user.
! 153: * We only get here if the user is allowed to run something on this host.
! 154: */
! 155: void
! 156: display_privs(snl, pw)
! 157: struct sudo_nss_list *snl;
! 158: struct passwd *pw;
! 159: {
! 160: struct sudo_nss *nss;
! 161: struct lbuf lbuf;
! 162: int count;
! 163:
! 164: /* Reset group vector so group matching works correctly. */
! 165: reset_groups(pw);
! 166:
! 167: lbuf_init(&lbuf, NULL, 4, 0);
! 168:
! 169: /* Display defaults from all sources. */
! 170: count = 0;
! 171: tq_foreach_fwd(snl, nss)
! 172: count += nss->display_defaults(nss, pw, &lbuf);
! 173: if (count) {
! 174: printf("Matching Defaults entries for %s on this host:\n", pw->pw_name);
! 175: lbuf_print(&lbuf);
! 176: putchar('\n');
! 177: }
! 178:
! 179: /* Display Runas and Cmnd-specific defaults from all sources. */
! 180: count = 0;
! 181: tq_foreach_fwd(snl, nss)
! 182: count += nss->display_bound_defaults(nss, pw, &lbuf);
! 183: if (count) {
! 184: printf("Runas and Command-specific defaults for %s:\n", pw->pw_name);
! 185: lbuf_print(&lbuf);
! 186: putchar('\n');
! 187: }
! 188:
! 189: /* Display privileges from all sources. */
! 190: printf("User %s may run the following commands on this host:\n",
! 191: pw->pw_name);
! 192: tq_foreach_fwd(snl, nss)
! 193: (void) nss->display_privs(nss, pw, &lbuf);
! 194: if (lbuf.len != 0)
! 195: lbuf_print(&lbuf); /* print remainder, if any */
! 196: lbuf_destroy(&lbuf);
! 197: }
! 198:
! 199: /*
! 200: * Check user_cmnd against sudoers and print the matching entry if the
! 201: * command is allowed.
! 202: */
! 203: int
! 204: display_cmnd(snl, pw)
! 205: struct sudo_nss_list *snl;
! 206: struct passwd *pw;
! 207: {
! 208: struct sudo_nss *nss;
! 209:
! 210: /* Reset group vector so group matching works correctly. */
! 211: reset_groups(pw);
! 212:
! 213: tq_foreach_fwd(snl, nss) {
! 214: if (nss->display_cmnd(nss, pw) == 0)
! 215: return(0);
! 216: }
! 217: return(1);
! 218: }