Return to sudo_nss.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers |
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: }