2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-09-01 14:55:12 +00:00

Use nsswitch to hide some sudoers vs. ldap implementation details

and reduce the number of #ifdef LDAP
TODO: fix display routines and error handling
This commit is contained in:
Todd C. Miller
2007-12-31 12:39:52 +00:00
parent 7f323157a2
commit ae2ae34528
7 changed files with 162 additions and 92 deletions

View File

@@ -157,8 +157,8 @@ BINFILES= ChangeLog HISTORY LICENSE README TODO TROUBLESHOOTING \
BINSPECIAL= INSTALL.binary Makefile.binary.in libtool BINSPECIAL= INSTALL.binary Makefile.binary.in libtool
SUDODEP = $(srcdir)/sudo.h $(srcdir)/compat.h $(srcdir)/defaults.h \ SUDODEP = $(srcdir)/sudo.h $(srcdir)/compat.h $(srcdir)/defaults.h \
$(srcdir)/error.h $(srcdir)/logging.h $(devdir)/def_data.h \ $(srcdir)/error.h $(srcdir)/list.h $(srcdir)/logging.h \
pathnames.h config.h $(srcdir)/sudo_nss.h $(devdir)/def_data.h pathnames.h config.h
AUTHDEP = $(SUDODEP) $(authdir)/sudo_auth.h AUTHDEP = $(SUDODEP) $(authdir)/sudo_auth.h

81
ldap.c
View File

@@ -115,7 +115,7 @@ struct ldap_config_table {
}; };
/* ldap configuration structure */ /* ldap configuration structure */
struct ldap_config { static struct ldap_config {
int port; int port;
int version; int version;
int debug; int debug;
@@ -145,7 +145,7 @@ struct ldap_config {
char *krb5_ccname; char *krb5_ccname;
} ldap_conf; } ldap_conf;
struct ldap_config_table ldap_conf_table[] = { static struct ldap_config_table ldap_conf_table[] = {
{ "sudoers_debug", CONF_INT, FALSE, -1, &ldap_conf.debug }, { "sudoers_debug", CONF_INT, FALSE, -1, &ldap_conf.debug },
{ "host", CONF_STR, FALSE, -1, &ldap_conf.host }, { "host", CONF_STR, FALSE, -1, &ldap_conf.host },
{ "port", CONF_INT, FALSE, -1, &ldap_conf.port }, { "port", CONF_INT, FALSE, -1, &ldap_conf.port },
@@ -217,6 +217,17 @@ struct ldap_config_table ldap_conf_table[] = {
{ NULL } { NULL }
}; };
/* XXX - add display_cmnd and display_privs */
struct sudo_nss sudo_nss_ldap = {
&sudo_nss_ldap,
NULL,
sudo_ldap_open,
sudo_ldap_close,
sudo_ldap_parse,
sudo_ldap_setdefs,
sudo_ldap_lookup
};
/* /*
* Walk through search results and return TRUE if we have a matching * Walk through search results and return TRUE if we have a matching
* netgroup, else FALSE. * netgroup, else FALSE.
@@ -1146,9 +1157,11 @@ sudo_ldap_set_options(ld)
/* /*
* Open a connection to the LDAP server. * Open a connection to the LDAP server.
* Returns 0 on success and non-zero on failure.
*/ */
void * int
sudo_ldap_open() sudo_ldap_open(nss)
struct sudo_nss *nss;
{ {
LDAP *ld; LDAP *ld;
const char *old_ccname = user_ccname; const char *old_ccname = user_ccname;
@@ -1158,7 +1171,7 @@ sudo_ldap_open()
#endif #endif
if (!sudo_ldap_read_config()) if (!sudo_ldap_read_config())
return(NULL); return(-1);
#ifdef HAVE_LDAPSSL_INIT #ifdef HAVE_LDAPSSL_INIT
if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) { if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) {
@@ -1170,7 +1183,7 @@ sudo_ldap_open()
if (rc != LDAP_SUCCESS) { if (rc != LDAP_SUCCESS) {
warningx("unable to initialize SSL cert and key db: %s", warningx("unable to initialize SSL cert and key db: %s",
ldapssl_err2string(rc)); ldapssl_err2string(rc));
return(NULL); return(-1);
} }
} }
#endif /* HAVE_LDAPSSL_INIT */ #endif /* HAVE_LDAPSSL_INIT */
@@ -1182,7 +1195,7 @@ sudo_ldap_open()
rc = ldap_initialize(&ld, ldap_conf.uri); rc = ldap_initialize(&ld, ldap_conf.uri);
if (rc != LDAP_SUCCESS) { if (rc != LDAP_SUCCESS) {
warningx("unable to initialize LDAP: %s", ldap_err2string(rc)); warningx("unable to initialize LDAP: %s", ldap_err2string(rc));
return(NULL); return(-1);
} }
} else } else
#endif /* HAVE_LDAP_INITIALIZE */ #endif /* HAVE_LDAP_INITIALIZE */
@@ -1198,20 +1211,20 @@ sudo_ldap_open()
#endif #endif
if (ld == NULL) { if (ld == NULL) {
warning("unable to initialize LDAP"); warning("unable to initialize LDAP");
return(NULL); return(-1);
} }
} }
/* Set LDAP options */ /* Set LDAP options */
if (sudo_ldap_set_options(ld) < 0) if (sudo_ldap_set_options(ld) < 0)
return(NULL); return(-1);
if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) { if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) {
#ifdef HAVE_LDAP_START_TLS_S #ifdef HAVE_LDAP_START_TLS_S
rc = ldap_start_tls_s(ld, NULL, NULL); rc = ldap_start_tls_s(ld, NULL, NULL);
if (rc != LDAP_SUCCESS) { if (rc != LDAP_SUCCESS) {
warningx("ldap_start_tls_s(): %s", ldap_err2string(rc)); warningx("ldap_start_tls_s(): %s", ldap_err2string(rc));
return(NULL); return(-1);
} }
DPRINTF(("ldap_start_tls_s() ok"), 1); DPRINTF(("ldap_start_tls_s() ok"), 1);
#else #else
@@ -1251,7 +1264,7 @@ sudo_ldap_open()
} }
if (rc != LDAP_SUCCESS) { if (rc != LDAP_SUCCESS) {
warningx("ldap_sasl_interactive_bind_s(): %s", ldap_err2string(rc)); warningx("ldap_sasl_interactive_bind_s(): %s", ldap_err2string(rc));
return(NULL); return(-1);
} }
DPRINTF(("ldap_sasl_interactive_bind_s() ok"), 1); DPRINTF(("ldap_sasl_interactive_bind_s() ok"), 1);
} else } else
@@ -1260,22 +1273,26 @@ sudo_ldap_open()
/* Actually connect */ /* Actually connect */
if ((rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw))) { if ((rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw))) {
warningx("ldap_simple_bind_s(): %s", ldap_err2string(rc)); warningx("ldap_simple_bind_s(): %s", ldap_err2string(rc));
return(NULL); return(-1);
} }
DPRINTF(("ldap_simple_bind_s() ok"), 1); DPRINTF(("ldap_simple_bind_s() ok"), 1);
} }
return((void *) ld); nss->handle = ld;
return(0);
} }
void int
sudo_ldap_update_defaults(v) sudo_ldap_setdefs(nss)
void *v; struct sudo_nss *nss;
{ {
LDAP *ld = (LDAP *) v; LDAP *ld = (LDAP *) nss->handle;
LDAPMessage *entry = NULL, *result = NULL; /* used for searches */ LDAPMessage *entry = NULL, *result = NULL; /* used for searches */
int rc; /* temp return value */ int rc; /* temp return value */
if (ld == NULL)
return(-1);
rc = ldap_search_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, rc = ldap_search_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE,
"cn=defaults", NULL, 0, &result); "cn=defaults", NULL, 0, &result);
if (rc == 0 && (entry = ldap_first_entry(ld, result))) { if (rc == 0 && (entry = ldap_first_entry(ld, result))) {
@@ -1286,17 +1303,19 @@ sudo_ldap_update_defaults(v)
if (result) if (result)
ldap_msgfree(result); ldap_msgfree(result);
return(0);
} }
/* /*
* like sudoers_lookup() - only LDAP style * like sudoers_lookup() - only LDAP style
*/ */
int int
sudo_ldap_check(v, pwflag) sudo_ldap_lookup(nss, pwflag)
void *v; struct sudo_nss *nss;
int pwflag; int pwflag;
{ {
LDAP *ld = (LDAP *) v; LDAP *ld = (LDAP *) nss->handle;
LDAPMessage *entry = NULL, *result = NULL; /* used for searches */ LDAPMessage *entry = NULL, *result = NULL; /* used for searches */
char *filt; /* used to parse attributes */ char *filt; /* used to parse attributes */
int do_netgr, rc, ret; /* temp/final return values */ int do_netgr, rc, ret; /* temp/final return values */
@@ -1452,10 +1471,22 @@ done:
/* /*
* shut down LDAP connection * shut down LDAP connection
*/ */
void int
sudo_ldap_close(v) sudo_ldap_close(nss)
void *v; struct sudo_nss *nss;
{ {
if (v != NULL) if (nss->handle != NULL)
ldap_unbind_s((LDAP *) v); ldap_unbind_s((LDAP *) nss->handle);
nss->handle = NULL;
return(0);
}
/*
* STUB
*/
int
sudo_ldap_parse(nss)
struct sudo_nss *nss;
{
return(0);
} }

1
list.c
View File

@@ -30,7 +30,6 @@
#endif /* STDC_HEADERS */ #endif /* STDC_HEADERS */
#include "sudo.h" #include "sudo.h"
#include "list.h"
#ifndef lint #ifndef lint
__unused static const char rcsid[] = "$Sudo$"; __unused static const char rcsid[] = "$Sudo$";

74
parse.c
View File

@@ -55,6 +55,24 @@ __unused static const char rcsid[] = "$Sudo$";
/* Characters that must be quoted in sudoers */ /* Characters that must be quoted in sudoers */
#define SUDOERS_QUOTED ":\\,=#\"" #define SUDOERS_QUOTED ":\\,=#\""
/* sudoers nsswitch routines */
struct sudo_nss sudo_nss_file = {
&sudo_nss_file,
NULL,
sudo_file_open,
sudo_file_close,
sudo_file_parse,
sudo_file_setdefs,
sudo_file_lookup
};
/*
* Parser externs.
*/
extern FILE *yyin;
extern char *errorfile;
extern int errorlineno, parse_error;
/* /*
* Local prototypes. * Local prototypes.
*/ */
@@ -62,18 +80,59 @@ static void print_member __P((struct lbuf *, char *, int, int, int));
static void display_defaults __P((struct passwd *)); static void display_defaults __P((struct passwd *));
static void display_bound_defaults __P((int)); static void display_bound_defaults __P((int));
int
sudo_file_open(nss)
struct sudo_nss *nss;
{
/* XXX - open_sudoers() errors out if cannot open */
nss->handle = open_sudoers(_PATH_SUDOERS, NULL);
return(nss->handle ? 0 : -1);
}
int
sudo_file_close(nss)
struct sudo_nss *nss;
{
/* XXX - free up data structures */
if (nss->handle != NULL) {
fclose(nss->handle);
nss->handle = NULL;
yyin = NULL;
}
return(0);
}
/* /*
* Parse the specified sudoers file. * Parse the specified sudoers file.
*/ */
int int
parse_sudoers(path) sudo_file_parse(nss)
const char *path; struct sudo_nss *nss;
{ {
extern FILE *yyin; if (nss->handle == NULL)
return(-1);
yyin = open_sudoers(_PATH_SUDOERS, NULL);
init_parser(_PATH_SUDOERS, 0); init_parser(_PATH_SUDOERS, 0);
return(yyparse()); yyin = nss->handle;
/* XXX - log_error() is terminal */
if (yyparse() != 0 || parse_error) {
log_error(0, "parse error in %s near line %d", errorfile, errorlineno);
return(-1);
}
return(0);
}
int
sudo_file_setdefs(nss)
struct sudo_nss *nss;
{
if (nss->handle == NULL)
return(-1);
/* XXX - move guts of update_defaults here */
if (!update_defaults(SKIP_CMND))
return(-1);
return(0);
} }
/* /*
@@ -81,7 +140,8 @@ parse_sudoers(path)
* allowed to run the specified command on this host as the target user. * allowed to run the specified command on this host as the target user.
*/ */
int int
sudoers_lookup(pwflag) sudo_file_lookup(nss, pwflag)
struct sudo_nss *nss;
int pwflag; int pwflag;
{ {
int validated, match, host_match, runas_match, cmnd_match; int validated, match, host_match, runas_match, cmnd_match;
@@ -285,6 +345,7 @@ display_privs(v, pw)
} }
lbuf_destroy(&lbuf); lbuf_destroy(&lbuf);
} }
/* XXX - nss */
#ifdef HAVE_LDAP #ifdef HAVE_LDAP
if (v != NULL) if (v != NULL)
sudo_ldap_display_privs(v, pw); sudo_ldap_display_privs(v, pw);
@@ -434,6 +495,7 @@ display_cmnd(v, pw)
int rval = 1; int rval = 1;
int host_match, runas_match, cmnd_match; int host_match, runas_match, cmnd_match;
/* XXX - nss */
#ifdef HAVE_LDAP #ifdef HAVE_LDAP
if (v != NULL) if (v != NULL)
rval = sudo_ldap_display_cmnd(v, pw); rval = sudo_ldap_display_cmnd(v, pw);

View File

@@ -20,8 +20,6 @@
#ifndef _SUDO_PARSE_H #ifndef _SUDO_PARSE_H
#define _SUDO_PARSE_H #define _SUDO_PARSE_H
#include "list.h"
#undef UNSPEC #undef UNSPEC
#define UNSPEC -1 #define UNSPEC -1
#undef DENY #undef DENY

71
sudo.c
View File

@@ -150,7 +150,7 @@ char *login_style;
sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld; sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld;
static char *runas_user; static char *runas_user;
static char *runas_group; static char *runas_group;
static void *ldap_conn; static struct sudo_nss_list *snl;
int int
main(argc, argv, envp) main(argc, argv, envp)
@@ -165,7 +165,7 @@ main(argc, argv, envp)
extern char *malloc_options; extern char *malloc_options;
malloc_options = "AFGJPR"; malloc_options = "AFGJPR";
#endif #endif
const unsigned char *nss, *nss_base; struct sudo_nss *nss;
#ifdef HAVE_SETLOCALE #ifdef HAVE_SETLOCALE
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
@@ -267,31 +267,14 @@ main(argc, argv, envp)
init_vars(sudo_mode, envp); /* XXX - move this later? */ init_vars(sudo_mode, envp); /* XXX - move this later? */
/* Parse nsswitch.conf for sudoers order. */ /* Parse nsswitch.conf for sudoers order. */
nss_base = read_nss(_PATH_NSSWITCH_CONF); snl = read_nss(_PATH_NSSWITCH_CONF);
if (*nss_base == SUDO_NSS_LAST)
log_error(0, "No valid sudoers sources in nsswitch.conf");
/* Set global defaults */ /* Set global defaults */
/* XXX - error out early if no sources can be opened */ /* XXX - error out early if no sources can be opened */
for (nss = nss_base; *nss != SUDO_NSS_LAST; nss++) { tq_foreach_fwd(snl, nss) {
#ifdef HAVE_LDAP /* XXX - remove from tailq if open or parse fails? */
/* LDAP defaults must come first due to def_ignore_local_sudoers */ if (nss->open(nss) == 0 && nss->parse(nss) == 0)
if (ldap_conn == NULL && ISSET(*nss, SUDO_NSS_LDAP)) { nss->setdefs(nss);
if ((ldap_conn = sudo_ldap_open()) != NULL)
sudo_ldap_update_defaults(ldap_conn);
/* XXX - was: break; */
} else
#endif
if (ISSET(*nss, SUDO_NSS_FILES)) {
if (def_ignore_local_sudoers)
continue;
/* Parse sudoers and upate defaults from it. */
if (parse_sudoers(_PATH_SUDOERS) || parse_error)
log_error(0, "parse error in %s near line %d", errorfile,
errorlineno);
if (!update_defaults(SKIP_CMND))
log_error(NO_STDERR|NO_EXIT, "problem with defaults entries");
}
} }
/* XXX - collect post-sudoers parse settings into a function */ /* XXX - collect post-sudoers parse settings into a function */
@@ -340,16 +323,11 @@ main(argc, argv, envp)
cmnd_status = set_cmnd(sudo_mode); cmnd_status = set_cmnd(sudo_mode);
for (nss = nss_base; *nss != SUDO_NSS_LAST; nss++) { tq_foreach_fwd(snl, nss) {
if (ISSET(*nss, SUDO_NSS_FILES)) { /* XXX - should lookup check handle instead? */
if (def_ignore_local_sudoers) if (!nss->handle)
continue; continue;
rc = sudoers_lookup(pwflag); rc = nss->lookup(nss, pwflag);
}
#ifdef HAVE_LDAP
else if (ISSET(*nss, SUDO_NSS_LDAP))
rc = sudo_ldap_check(ldap_conn, pwflag);
#endif
/* XXX - rethink this logic */ /* XXX - rethink this logic */
if (validated == 0 || ISSET(rc, VALIDATE_OK)) if (validated == 0 || ISSET(rc, VALIDATE_OK))
@@ -358,7 +336,7 @@ main(argc, argv, envp)
validated |= rc; validated |= rc;
/* Handle [NOTFOUND=return] */ /* Handle [NOTFOUND=return] */
if (!ISSET(rc, VALIDATE_OK) && ISSET(*nss, SUDO_NSS_RETURN)) if (!ISSET(rc, VALIDATE_OK) && nss->ret_notfound)
break; break;
} }
if (safe_cmnd == NULL) if (safe_cmnd == NULL)
@@ -443,16 +421,13 @@ main(argc, argv, envp)
log_auth(validated, 1); log_auth(validated, 1);
if (sudo_mode == MODE_CHECK) if (sudo_mode == MODE_CHECK)
rc = display_cmnd(ldap_conn, list_pw ? list_pw : sudo_user.pw); rc = display_cmnd(NULL, list_pw ? list_pw : sudo_user.pw);
else if (sudo_mode == MODE_LIST) else if (sudo_mode == MODE_LIST)
display_privs(ldap_conn, list_pw ? list_pw : sudo_user.pw); display_privs(NULL, list_pw ? list_pw : sudo_user.pw);
#ifdef HAVE_LDAP /* Cleanup sudoers sources */
if (ldap_conn != NULL) { tq_foreach_fwd(snl, nss)
sudo_ldap_close(ldap_conn); nss->close(nss);
ldap_conn = NULL;
}
#endif
/* Deferred exit due to sudo_ldap_close() */ /* Deferred exit due to sudo_ldap_close() */
if (sudo_mode == MODE_VALIDATE || sudo_mode == MODE_CHECK || if (sudo_mode == MODE_VALIDATE || sudo_mode == MODE_CHECK ||
@@ -1382,16 +1357,14 @@ void
cleanup(gotsignal) cleanup(gotsignal)
int gotsignal; int gotsignal;
{ {
struct sudo_nss *nss;
if (!gotsignal) { if (!gotsignal) {
tq_foreach_fwd(snl, nss)
nss->close(nss);
sudo_endpwent(); sudo_endpwent();
sudo_endgrent(); sudo_endgrent();
} }
#ifdef HAVE_LDAP
if (ldap_conn != NULL) {
sudo_ldap_close(ldap_conn);
ldap_conn = NULL;
}
#endif
} }
/* /*

21
sudo.h
View File

@@ -27,8 +27,9 @@
#include <pathnames.h> #include <pathnames.h>
#include <limits.h> #include <limits.h>
#include "compat.h" #include "compat.h"
#include "error.h"
#include "defaults.h" #include "defaults.h"
#include "error.h"
#include "list.h"
#include "logging.h" #include "logging.h"
#include "sudo_nss.h" #include "sudo_nss.h"
@@ -225,15 +226,21 @@ char *tgetpass __P((const char *, int, int));
int find_path __P((char *, char **, struct stat *, char *)); int find_path __P((char *, char **, struct stat *, char *));
void check_user __P((int)); void check_user __P((int));
void verify_user __P((struct passwd *, char *)); void verify_user __P((struct passwd *, char *));
int sudoers_lookup __P((int));
int parse_sudoers __P((const char *));
#ifdef HAVE_LDAP #ifdef HAVE_LDAP
int sudo_ldap_check __P((void *, int));
void sudo_ldap_display_privs __P((void *, struct passwd *)); void sudo_ldap_display_privs __P((void *, struct passwd *));
int sudo_ldap_display_cmnd __P((void *, struct passwd *)); int sudo_ldap_display_cmnd __P((void *, struct passwd *));
void sudo_ldap_update_defaults __P((void *)); int sudo_ldap_open __P((struct sudo_nss *));
void *sudo_ldap_open __P((void)); int sudo_ldap_close __P((struct sudo_nss *));
void sudo_ldap_close __P((void *)); int sudo_ldap_setdefs __P((struct sudo_nss *));
int sudo_ldap_lookup __P((struct sudo_nss *, int));
int sudo_ldap_parse __P((struct sudo_nss *));
#endif
#if 1
int sudo_file_open __P((struct sudo_nss *));
int sudo_file_close __P((struct sudo_nss *));
int sudo_file_setdefs __P((struct sudo_nss *));
int sudo_file_lookup __P((struct sudo_nss *, int));
int sudo_file_parse __P((struct sudo_nss *));
#endif #endif
void set_perms __P((int)); void set_perms __P((int));
void remove_timestamp __P((int)); void remove_timestamp __P((int));