#include <config.h>
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#else
# ifdef HAVE_STRINGS_H
# include <strings.h>
# endif
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <pwd.h>
#include <grp.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
extern struct sudo_nss sudo_nss_file;
#ifdef HAVE_LDAP
extern struct sudo_nss sudo_nss_ldap;
#endif
#if defined(HAVE_LDAP) && defined(_PATH_NSSWITCH_CONF)
struct sudo_nss_list *
sudo_read_nss()
{
FILE *fp;
char *cp;
int saw_files = FALSE;
int saw_ldap = FALSE;
int got_match = FALSE;
static struct sudo_nss_list snl;
if ((fp = fopen(_PATH_NSSWITCH_CONF, "r")) == NULL)
goto nomatch;
while ((cp = sudo_parseln(fp)) != NULL) {
if (*cp == '\0')
continue;
if (strncasecmp(cp, "sudoers:", 8) != 0)
continue;
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) {
tq_last(&snl)->ret_notfound = TRUE;
got_match = FALSE;
} else
got_match = FALSE;
}
break;
}
fclose(fp);
nomatch:
if (tq_empty(&snl))
tq_append(&snl, &sudo_nss_file);
return(&snl);
}
#else
struct sudo_nss_list *
sudo_read_nss()
{
static struct sudo_nss_list snl;
# ifdef HAVE_LDAP
tq_append(&snl, &sudo_nss_ldap);
# endif
tq_append(&snl, &sudo_nss_file);
return(&snl);
}
#endif
static void
reset_groups(pw)
struct passwd *pw;
{
#if defined(HAVE_INITGROUPS) && defined(HAVE_GETGROUPS)
if (pw != sudo_user.pw) {
(void) initgroups(pw->pw_name, pw->pw_gid);
if ((user_ngroups = getgroups(0, NULL)) > 0) {
user_groups = erealloc3(user_groups, 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);
}
}
#endif
}
void
display_privs(snl, pw)
struct sudo_nss_list *snl;
struct passwd *pw;
{
struct sudo_nss *nss;
struct lbuf lbuf;
int count;
reset_groups(pw);
lbuf_init(&lbuf, NULL, 4, 0);
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');
}
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');
}
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);
lbuf_destroy(&lbuf);
}
int
display_cmnd(snl, pw)
struct sudo_nss_list *snl;
struct passwd *pw;
{
struct sudo_nss *nss;
reset_groups(pw);
tq_foreach_fwd(snl, nss) {
if (nss->display_cmnd(nss, pw) == 0)
return(0);
}
return(1);
}