/* * Copyright (c) 2007 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif /* STDC_HEADERS */ #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif /* HAVE_STRING_H */ #include #include #include "sudo.h" #ifndef lint __unused static const char rcsid[] = "$Sudo$"; #endif /* lint */ #ifndef LINE_MAX # define LINE_MAX 2048 #endif extern struct sudo_nss sudo_nss_file; #ifdef HAVE_LDAP extern struct sudo_nss sudo_nss_ldap; /* * Read in /etc/nsswitch.conf * Returns a tail queue of matches. * XXX - refactor config reading (ldap.conf, /etc/environment too) */ struct sudo_nss_list * read_nss(path) const char *path; { size_t len; FILE *fp; char *cp, buf[LINE_MAX]; int saw_files = FALSE; int saw_ldap = FALSE; int got_match = FALSE; static struct sudo_nss_list snl; if ((fp = fopen(path, "r")) == NULL) goto nomatch; while (fgets(buf, sizeof(buf), fp) != NULL) { /* Remove comments */ if ((cp = strchr(buf, '#')) != NULL) *cp = '\0'; /* Trim leading and trailing whitespace/newline */ len = strlen(buf); while (len > 0 && isspace(buf[len - 1])) buf[--len] = '\0'; for (cp = buf; isblank(*cp); cp++) continue; /* Skip blank or comment lines */ if (*cp == '\0' || *cp == '#') continue; /* Look for a line starting with "sudoers:" */ if (strncasecmp(cp, "sudoers:", 8) != 0) continue; /* Parse line */ for ((cp = strtok(cp + 8, " \t")); cp != NULL; (cp = strtok(NULL, " \t"))) { if (strcasecmp(cp, "files") == 0 && !saw_files) { tq_append(&snl, &sudo_nss_file); got_match = TRUE; } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) { tq_append(&snl, &sudo_nss_ldap); got_match = TRUE; } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) { /* NOTFOUND affects the most recent entry */ tq_last(&snl)->ret_notfound = TRUE; got_match = FALSE; } else got_match = FALSE; } /* Only parse the first "sudoers:" line */ break; } fclose(fp); /* Default to fails only if no matches */ if (tq_empty(&snl)) { nomatch: snl.first = &sudo_nss_file; snl.last = &sudo_nss_file; } return(&snl); } #else /* HAVE_LDAP */ /* * Non-LDAP stub */ struct sudo_nss_list * read_nss(path) const char *path; { static struct sudo_nss_list snl = { &sudo_nss_file, &sudo_nss_file }; return(snl); } #endif /* HAVE_LDAP */