/*
- * Copyright (c) 2007-2008 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2007-2011 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#endif /* STDC_HEADERS */
#ifdef HAVE_STRING_H
# include <string.h>
-#else
-# ifdef HAVE_STRINGS_H
-# include <strings.h>
-# endif
#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <pwd.h>
#include <grp.h>
+#include <ctype.h>
#include "sudo.h"
#include "lbuf.h"
-#ifndef lint
-__unused static const char rcsid[] = "$Sudo: sudo_nss.c,v 1.6 2008/02/08 13:18:12 millert Exp $";
-#endif /* lint */
-
extern struct sudo_nss sudo_nss_file;
#ifdef HAVE_LDAP
extern struct sudo_nss 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;
+ tq_last(&snl)->ret_if_notfound = TRUE;
got_match = FALSE;
} else
got_match = FALSE;
if (tq_empty(&snl))
tq_append(&snl, &sudo_nss_file);
- return(&snl);
+ return &snl;
}
#else /* HAVE_LDAP && _PATH_NSSWITCH_CONF */
+# if defined(HAVE_LDAP) && defined(_PATH_NETSVC_CONF)
+
+/*
+ * Read in /etc/netsvc.conf (like nsswitch.conf on AIX)
+ * Returns a tail queue of matches.
+ */
+struct sudo_nss_list *
+sudo_read_nss()
+{
+ FILE *fp;
+ char *cp, *ep;
+ int saw_files = FALSE;
+ int saw_ldap = FALSE;
+ int got_match = FALSE;
+ static struct sudo_nss_list snl;
+
+ if ((fp = fopen(_PATH_NETSVC_CONF, "r")) == NULL)
+ goto nomatch;
+
+ while ((cp = sudo_parseln(fp)) != NULL) {
+ /* Skip blank or comment lines */
+ if (*cp == '\0')
+ continue;
+
+ /* Look for a line starting with "sudoers = " */
+ if (strncasecmp(cp, "sudoers", 7) != 0)
+ continue;
+ cp += 7;
+ while (isspace((unsigned char)*cp))
+ cp++;
+ if (*cp++ != '=')
+ continue;
+
+ /* Parse line */
+ for ((cp = strtok(cp, ",")); cp != NULL; (cp = strtok(NULL, ","))) {
+ /* Trim leading whitespace. */
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ if (!saw_files && strncasecmp(cp, "files", 5) == 0 &&
+ (isspace((unsigned char)cp[5]) || cp[5] == '\0')) {
+ tq_append(&snl, &sudo_nss_file);
+ got_match = TRUE;
+ ep = &cp[5];
+ } else if (!saw_ldap && strncasecmp(cp, "ldap", 4) == 0 &&
+ (isspace((unsigned char)cp[4]) || cp[4] == '\0')) {
+ tq_append(&snl, &sudo_nss_ldap);
+ got_match = TRUE;
+ ep = &cp[4];
+ } else {
+ got_match = FALSE;
+ }
+
+ /* check for = auth qualifier */
+ if (got_match && *ep) {
+ cp = ep;
+ while (isspace((unsigned char)*cp) || *cp == '=')
+ cp++;
+ if (strncasecmp(cp, "auth", 4) == 0 &&
+ (isspace((unsigned char)cp[4]) || cp[4] == '\0')) {
+ tq_last(&snl)->ret_if_found = TRUE;
+ }
+ }
+ }
+ /* Only parse the first "sudoers" line */
+ break;
+ }
+ fclose(fp);
+
+nomatch:
+ /* Default to files only if no matches */
+ if (tq_empty(&snl))
+ tq_append(&snl, &sudo_nss_file);
+
+ return &snl;
+}
+
+# else /* !_PATH_NETSVC_CONF && !_PATH_NSSWITCH_CONF */
+
/*
* Non-nsswitch.conf version with hard-coded order.
*/
{
static struct sudo_nss_list snl;
-# ifdef HAVE_LDAP
+# ifdef HAVE_LDAP
tq_append(&snl, &sudo_nss_ldap);
-# endif
+# endif
tq_append(&snl, &sudo_nss_file);
- return(&snl);
+ return &snl;
}
+# endif /* !HAVE_LDAP || !_PATH_NETSVC_CONF */
+
#endif /* HAVE_LDAP && _PATH_NSSWITCH_CONF */
/* Reset user_groups based on passwd entry. */
{
#if defined(HAVE_INITGROUPS) && defined(HAVE_GETGROUPS)
if (pw != sudo_user.pw) {
- (void) initgroups(pw->pw_name, pw->pw_gid);
+# ifdef HAVE_SETAUTHDB
+ aix_setauthdb(pw->pw_name);
+# endif
+ if (initgroups(pw->pw_name, pw->pw_gid) == -1)
+ log_error(USE_ERRNO|MSG_ONLY, "can't reset group vector");
+ efree(user_groups);
+ user_groups = NULL;
if ((user_ngroups = getgroups(0, NULL)) > 0) {
- user_groups = erealloc3(user_groups, user_ngroups,
- sizeof(GETGROUPS_T));
+ user_groups = emalloc2(user_ngroups, sizeof(GETGROUPS_T));
if (getgroups(user_ngroups, user_groups) < 0)
log_error(USE_ERRNO|MSG_ONLY, "can't get group vector");
- } else {
- user_ngroups = 0;
- efree(user_groups);
}
+# ifdef HAVE_SETAUTHDB
+ aix_restoreauthdb();
+# endif
}
-#endif
+#endif /* HAVE_INITGROUPS && HAVE_GETGROUPS */
+}
+
+static int
+output(buf)
+ const char *buf;
+{
+ return fputs(buf, stdout);
}
/*
struct passwd *pw;
{
struct sudo_nss *nss;
- struct lbuf lbuf;
- int count;
+ struct lbuf defs, privs;
+ int count, olen;
/* Reset group vector so group matching works correctly. */
reset_groups(pw);
- lbuf_init(&lbuf, NULL, 4, 0);
+ lbuf_init(&defs, output, 4, NULL);
+ lbuf_init(&privs, output, 4, NULL);
/* Display defaults from all sources. */
+ lbuf_append(&defs, "Matching Defaults entries for ", pw->pw_name,
+ " on this host:\n", NULL);
count = 0;
- tq_foreach_fwd(snl, nss)
- count += nss->display_defaults(nss, pw, &lbuf);
- if (count) {
- printf("Matching Defaults entries for %s on this host:\n", pw->pw_name);
- lbuf_print(&lbuf);
- putchar('\n');
+ tq_foreach_fwd(snl, nss) {
+ count += nss->display_defaults(nss, pw, &defs);
}
+ if (count)
+ lbuf_append(&defs, "\n\n", NULL);
+ else
+ defs.len = 0;
/* Display Runas and Cmnd-specific defaults from all sources. */
+ olen = defs.len;
+ lbuf_append(&defs, "Runas and Command-specific defaults for ", pw->pw_name,
+ ":\n", NULL);
count = 0;
- tq_foreach_fwd(snl, nss)
- count += nss->display_bound_defaults(nss, pw, &lbuf);
- if (count) {
- printf("Runas and Command-specific defaults for %s:\n", pw->pw_name);
- lbuf_print(&lbuf);
- putchar('\n');
+ tq_foreach_fwd(snl, nss) {
+ count += nss->display_bound_defaults(nss, pw, &defs);
}
+ if (count)
+ lbuf_append(&defs, "\n\n", NULL);
+ else
+ defs.len = olen;
/* Display privileges from all sources. */
- printf("User %s may run the following commands on this host:\n",
- pw->pw_name);
- tq_foreach_fwd(snl, nss)
- (void) nss->display_privs(nss, pw, &lbuf);
- if (lbuf.len != 0)
- lbuf_print(&lbuf); /* print remainder, if any */
- lbuf_destroy(&lbuf);
+ lbuf_append(&privs, "User ", pw->pw_name,
+ " may run the following commands on this host:\n", NULL);
+ count = 0;
+ tq_foreach_fwd(snl, nss) {
+ count += nss->display_privs(nss, pw, &privs);
+ }
+ if (count) {
+ lbuf_print(&defs);
+ lbuf_print(&privs);
+ } else {
+ printf("User %s is not allowed to run sudo on %s.\n", pw->pw_name,
+ user_shost);
+ }
+
+ lbuf_destroy(&defs);
+ lbuf_destroy(&privs);
}
/*
tq_foreach_fwd(snl, nss) {
if (nss->display_cmnd(nss, pw) == 0)
- return(0);
+ return 0;
}
- return(1);
+ return 1;
}