/*
 * Copyright (c) 2007-2010 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
 * 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 <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 /* STDC_HEADERS */
#ifdef HAVE_STRING_H
# include <string.h>
#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"

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)
/*
 * Read in /etc/nsswitch.conf
 * Returns a tail queue of matches.
 */
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) {
	/* Skip blank or comment lines */
	if (*cp == '\0')
	    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_if_notfound = TRUE;
		got_match = FALSE;
	    } else
		got_match = FALSE;
	}
	/* 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 /* 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.
 */
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 /* !HAVE_LDAP || !_PATH_NETSVC_CONF */

#endif /* HAVE_LDAP && _PATH_NSSWITCH_CONF */

/* Reset user_groups based on passwd entry. */
static void
reset_groups(pw)
    struct passwd *pw;
{
#if defined(HAVE_INITGROUPS) && defined(HAVE_GETGROUPS)
    if (pw != sudo_user.pw) {
# ifdef HAVE_SETAUTHDB
        aix_setauthdb(pw->pw_name);
# endif
	(void) initgroups(pw->pw_name, pw->pw_gid);
	efree(user_groups);
	user_groups = NULL;
	if ((user_ngroups = getgroups(0, NULL)) > 0) {
	    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");
	}
# ifdef HAVE_SETAUTHDB
        aix_restoreauthdb();
# endif
    }
#endif /* HAVE_INITGROUPS && HAVE_GETGROUPS */
}

static int
output(buf)
    const char *buf;
{
    return fputs(buf, stdout);
}

/*
 * Print out privileges for the specified user.
 * We only get here if the user is allowed to run something on this host.
 */
void
display_privs(snl, pw)
    struct sudo_nss_list *snl;
    struct passwd *pw;
{
    struct sudo_nss *nss;
    struct lbuf lbuf;
    int count;

    /* Reset group vector so group matching works correctly. */
    reset_groups(pw);

    lbuf_init(&lbuf, output, 4, NULL);

    /* Display defaults from all sources. */
    lbuf_append(&lbuf, "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) {
	lbuf_append(&lbuf, "\n\n", NULL);
	lbuf_print(&lbuf);
    }

    /* Display Runas and Cmnd-specific defaults from all sources. */
    lbuf.len = 0;
    lbuf_append(&lbuf, "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) {
	lbuf_append(&lbuf, "\n\n", NULL);
	lbuf_print(&lbuf);
    }

    /* Display privileges from all sources. */
    lbuf.len = 0;
    lbuf_append(&lbuf, "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, &lbuf);
    }
    if (count) {
	lbuf_print(&lbuf);
    }

    lbuf_destroy(&lbuf);
}

/*
 * Check user_cmnd against sudoers and print the matching entry if the
 * command is allowed.
 */
int
display_cmnd(snl, pw)
    struct sudo_nss_list *snl;
    struct passwd *pw;
{
    struct sudo_nss *nss;

    /* Reset group vector so group matching works correctly. */
    reset_groups(pw);

    tq_foreach_fwd(snl, nss) {
	if (nss->display_cmnd(nss, pw) == 0)
	    return(0);
    }
    return(1);
}
