mirror of
https://github.com/sudo-project/sudo.git
synced 2025-09-02 07:15:27 +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:
@@ -157,8 +157,8 @@ BINFILES= ChangeLog HISTORY LICENSE README TODO TROUBLESHOOTING \
|
||||
BINSPECIAL= INSTALL.binary Makefile.binary.in libtool
|
||||
|
||||
SUDODEP = $(srcdir)/sudo.h $(srcdir)/compat.h $(srcdir)/defaults.h \
|
||||
$(srcdir)/error.h $(srcdir)/logging.h $(devdir)/def_data.h \
|
||||
pathnames.h config.h
|
||||
$(srcdir)/error.h $(srcdir)/list.h $(srcdir)/logging.h \
|
||||
$(srcdir)/sudo_nss.h $(devdir)/def_data.h pathnames.h config.h
|
||||
|
||||
AUTHDEP = $(SUDODEP) $(authdir)/sudo_auth.h
|
||||
|
||||
|
81
ldap.c
81
ldap.c
@@ -115,7 +115,7 @@ struct ldap_config_table {
|
||||
};
|
||||
|
||||
/* ldap configuration structure */
|
||||
struct ldap_config {
|
||||
static struct ldap_config {
|
||||
int port;
|
||||
int version;
|
||||
int debug;
|
||||
@@ -145,7 +145,7 @@ struct ldap_config {
|
||||
char *krb5_ccname;
|
||||
} 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 },
|
||||
{ "host", CONF_STR, FALSE, -1, &ldap_conf.host },
|
||||
{ "port", CONF_INT, FALSE, -1, &ldap_conf.port },
|
||||
@@ -217,6 +217,17 @@ struct ldap_config_table ldap_conf_table[] = {
|
||||
{ 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
|
||||
* netgroup, else FALSE.
|
||||
@@ -1146,9 +1157,11 @@ sudo_ldap_set_options(ld)
|
||||
|
||||
/*
|
||||
* Open a connection to the LDAP server.
|
||||
* Returns 0 on success and non-zero on failure.
|
||||
*/
|
||||
void *
|
||||
sudo_ldap_open()
|
||||
int
|
||||
sudo_ldap_open(nss)
|
||||
struct sudo_nss *nss;
|
||||
{
|
||||
LDAP *ld;
|
||||
const char *old_ccname = user_ccname;
|
||||
@@ -1158,7 +1171,7 @@ sudo_ldap_open()
|
||||
#endif
|
||||
|
||||
if (!sudo_ldap_read_config())
|
||||
return(NULL);
|
||||
return(-1);
|
||||
|
||||
#ifdef HAVE_LDAPSSL_INIT
|
||||
if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) {
|
||||
@@ -1170,7 +1183,7 @@ sudo_ldap_open()
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
warningx("unable to initialize SSL cert and key db: %s",
|
||||
ldapssl_err2string(rc));
|
||||
return(NULL);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LDAPSSL_INIT */
|
||||
@@ -1182,7 +1195,7 @@ sudo_ldap_open()
|
||||
rc = ldap_initialize(&ld, ldap_conf.uri);
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
warningx("unable to initialize LDAP: %s", ldap_err2string(rc));
|
||||
return(NULL);
|
||||
return(-1);
|
||||
}
|
||||
} else
|
||||
#endif /* HAVE_LDAP_INITIALIZE */
|
||||
@@ -1198,20 +1211,20 @@ sudo_ldap_open()
|
||||
#endif
|
||||
if (ld == NULL) {
|
||||
warning("unable to initialize LDAP");
|
||||
return(NULL);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set LDAP options */
|
||||
if (sudo_ldap_set_options(ld) < 0)
|
||||
return(NULL);
|
||||
return(-1);
|
||||
|
||||
if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) {
|
||||
#ifdef HAVE_LDAP_START_TLS_S
|
||||
rc = ldap_start_tls_s(ld, NULL, NULL);
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
warningx("ldap_start_tls_s(): %s", ldap_err2string(rc));
|
||||
return(NULL);
|
||||
return(-1);
|
||||
}
|
||||
DPRINTF(("ldap_start_tls_s() ok"), 1);
|
||||
#else
|
||||
@@ -1251,7 +1264,7 @@ sudo_ldap_open()
|
||||
}
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
warningx("ldap_sasl_interactive_bind_s(): %s", ldap_err2string(rc));
|
||||
return(NULL);
|
||||
return(-1);
|
||||
}
|
||||
DPRINTF(("ldap_sasl_interactive_bind_s() ok"), 1);
|
||||
} else
|
||||
@@ -1260,22 +1273,26 @@ sudo_ldap_open()
|
||||
/* Actually connect */
|
||||
if ((rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw))) {
|
||||
warningx("ldap_simple_bind_s(): %s", ldap_err2string(rc));
|
||||
return(NULL);
|
||||
return(-1);
|
||||
}
|
||||
DPRINTF(("ldap_simple_bind_s() ok"), 1);
|
||||
}
|
||||
|
||||
return((void *) ld);
|
||||
nss->handle = ld;
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
sudo_ldap_update_defaults(v)
|
||||
void *v;
|
||||
int
|
||||
sudo_ldap_setdefs(nss)
|
||||
struct sudo_nss *nss;
|
||||
{
|
||||
LDAP *ld = (LDAP *) v;
|
||||
LDAP *ld = (LDAP *) nss->handle;
|
||||
LDAPMessage *entry = NULL, *result = NULL; /* used for searches */
|
||||
int rc; /* temp return value */
|
||||
|
||||
if (ld == NULL)
|
||||
return(-1);
|
||||
|
||||
rc = ldap_search_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE,
|
||||
"cn=defaults", NULL, 0, &result);
|
||||
if (rc == 0 && (entry = ldap_first_entry(ld, result))) {
|
||||
@@ -1286,17 +1303,19 @@ sudo_ldap_update_defaults(v)
|
||||
|
||||
if (result)
|
||||
ldap_msgfree(result);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* like sudoers_lookup() - only LDAP style
|
||||
*/
|
||||
int
|
||||
sudo_ldap_check(v, pwflag)
|
||||
void *v;
|
||||
sudo_ldap_lookup(nss, pwflag)
|
||||
struct sudo_nss *nss;
|
||||
int pwflag;
|
||||
{
|
||||
LDAP *ld = (LDAP *) v;
|
||||
LDAP *ld = (LDAP *) nss->handle;
|
||||
LDAPMessage *entry = NULL, *result = NULL; /* used for searches */
|
||||
char *filt; /* used to parse attributes */
|
||||
int do_netgr, rc, ret; /* temp/final return values */
|
||||
@@ -1452,10 +1471,22 @@ done:
|
||||
/*
|
||||
* shut down LDAP connection
|
||||
*/
|
||||
void
|
||||
sudo_ldap_close(v)
|
||||
void *v;
|
||||
int
|
||||
sudo_ldap_close(nss)
|
||||
struct sudo_nss *nss;
|
||||
{
|
||||
if (v != NULL)
|
||||
ldap_unbind_s((LDAP *) v);
|
||||
if (nss->handle != NULL)
|
||||
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
1
list.c
@@ -30,7 +30,6 @@
|
||||
#endif /* STDC_HEADERS */
|
||||
|
||||
#include "sudo.h"
|
||||
#include "list.h"
|
||||
|
||||
#ifndef lint
|
||||
__unused static const char rcsid[] = "$Sudo$";
|
||||
|
74
parse.c
74
parse.c
@@ -55,6 +55,24 @@ __unused static const char rcsid[] = "$Sudo$";
|
||||
/* Characters that must be quoted in sudoers */
|
||||
#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.
|
||||
*/
|
||||
@@ -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_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.
|
||||
*/
|
||||
int
|
||||
parse_sudoers(path)
|
||||
const char *path;
|
||||
sudo_file_parse(nss)
|
||||
struct sudo_nss *nss;
|
||||
{
|
||||
extern FILE *yyin;
|
||||
if (nss->handle == NULL)
|
||||
return(-1);
|
||||
|
||||
yyin = open_sudoers(_PATH_SUDOERS, NULL);
|
||||
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.
|
||||
*/
|
||||
int
|
||||
sudoers_lookup(pwflag)
|
||||
sudo_file_lookup(nss, pwflag)
|
||||
struct sudo_nss *nss;
|
||||
int pwflag;
|
||||
{
|
||||
int validated, match, host_match, runas_match, cmnd_match;
|
||||
@@ -285,6 +345,7 @@ display_privs(v, pw)
|
||||
}
|
||||
lbuf_destroy(&lbuf);
|
||||
}
|
||||
/* XXX - nss */
|
||||
#ifdef HAVE_LDAP
|
||||
if (v != NULL)
|
||||
sudo_ldap_display_privs(v, pw);
|
||||
@@ -434,6 +495,7 @@ display_cmnd(v, pw)
|
||||
int rval = 1;
|
||||
int host_match, runas_match, cmnd_match;
|
||||
|
||||
/* XXX - nss */
|
||||
#ifdef HAVE_LDAP
|
||||
if (v != NULL)
|
||||
rval = sudo_ldap_display_cmnd(v, pw);
|
||||
|
2
parse.h
2
parse.h
@@ -20,8 +20,6 @@
|
||||
#ifndef _SUDO_PARSE_H
|
||||
#define _SUDO_PARSE_H
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#undef UNSPEC
|
||||
#define UNSPEC -1
|
||||
#undef DENY
|
||||
|
71
sudo.c
71
sudo.c
@@ -150,7 +150,7 @@ char *login_style;
|
||||
sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld;
|
||||
static char *runas_user;
|
||||
static char *runas_group;
|
||||
static void *ldap_conn;
|
||||
static struct sudo_nss_list *snl;
|
||||
|
||||
int
|
||||
main(argc, argv, envp)
|
||||
@@ -165,7 +165,7 @@ main(argc, argv, envp)
|
||||
extern char *malloc_options;
|
||||
malloc_options = "AFGJPR";
|
||||
#endif
|
||||
const unsigned char *nss, *nss_base;
|
||||
struct sudo_nss *nss;
|
||||
|
||||
#ifdef HAVE_SETLOCALE
|
||||
setlocale(LC_ALL, "");
|
||||
@@ -267,31 +267,14 @@ main(argc, argv, envp)
|
||||
init_vars(sudo_mode, envp); /* XXX - move this later? */
|
||||
|
||||
/* Parse nsswitch.conf for sudoers order. */
|
||||
nss_base = read_nss(_PATH_NSSWITCH_CONF);
|
||||
if (*nss_base == SUDO_NSS_LAST)
|
||||
log_error(0, "No valid sudoers sources in nsswitch.conf");
|
||||
snl = read_nss(_PATH_NSSWITCH_CONF);
|
||||
|
||||
/* Set global defaults */
|
||||
/* XXX - error out early if no sources can be opened */
|
||||
for (nss = nss_base; *nss != SUDO_NSS_LAST; nss++) {
|
||||
#ifdef HAVE_LDAP
|
||||
/* LDAP defaults must come first due to def_ignore_local_sudoers */
|
||||
if (ldap_conn == NULL && ISSET(*nss, SUDO_NSS_LDAP)) {
|
||||
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");
|
||||
}
|
||||
tq_foreach_fwd(snl, nss) {
|
||||
/* XXX - remove from tailq if open or parse fails? */
|
||||
if (nss->open(nss) == 0 && nss->parse(nss) == 0)
|
||||
nss->setdefs(nss);
|
||||
}
|
||||
|
||||
/* XXX - collect post-sudoers parse settings into a function */
|
||||
@@ -340,16 +323,11 @@ main(argc, argv, envp)
|
||||
|
||||
cmnd_status = set_cmnd(sudo_mode);
|
||||
|
||||
for (nss = nss_base; *nss != SUDO_NSS_LAST; nss++) {
|
||||
if (ISSET(*nss, SUDO_NSS_FILES)) {
|
||||
if (def_ignore_local_sudoers)
|
||||
continue;
|
||||
rc = sudoers_lookup(pwflag);
|
||||
}
|
||||
#ifdef HAVE_LDAP
|
||||
else if (ISSET(*nss, SUDO_NSS_LDAP))
|
||||
rc = sudo_ldap_check(ldap_conn, pwflag);
|
||||
#endif
|
||||
tq_foreach_fwd(snl, nss) {
|
||||
/* XXX - should lookup check handle instead? */
|
||||
if (!nss->handle)
|
||||
continue;
|
||||
rc = nss->lookup(nss, pwflag);
|
||||
|
||||
/* XXX - rethink this logic */
|
||||
if (validated == 0 || ISSET(rc, VALIDATE_OK))
|
||||
@@ -358,7 +336,7 @@ main(argc, argv, envp)
|
||||
validated |= rc;
|
||||
|
||||
/* Handle [NOTFOUND=return] */
|
||||
if (!ISSET(rc, VALIDATE_OK) && ISSET(*nss, SUDO_NSS_RETURN))
|
||||
if (!ISSET(rc, VALIDATE_OK) && nss->ret_notfound)
|
||||
break;
|
||||
}
|
||||
if (safe_cmnd == NULL)
|
||||
@@ -443,16 +421,13 @@ main(argc, argv, envp)
|
||||
|
||||
log_auth(validated, 1);
|
||||
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)
|
||||
display_privs(ldap_conn, list_pw ? list_pw : sudo_user.pw);
|
||||
display_privs(NULL, list_pw ? list_pw : sudo_user.pw);
|
||||
|
||||
#ifdef HAVE_LDAP
|
||||
if (ldap_conn != NULL) {
|
||||
sudo_ldap_close(ldap_conn);
|
||||
ldap_conn = NULL;
|
||||
}
|
||||
#endif
|
||||
/* Cleanup sudoers sources */
|
||||
tq_foreach_fwd(snl, nss)
|
||||
nss->close(nss);
|
||||
|
||||
/* Deferred exit due to sudo_ldap_close() */
|
||||
if (sudo_mode == MODE_VALIDATE || sudo_mode == MODE_CHECK ||
|
||||
@@ -1382,16 +1357,14 @@ void
|
||||
cleanup(gotsignal)
|
||||
int gotsignal;
|
||||
{
|
||||
struct sudo_nss *nss;
|
||||
|
||||
if (!gotsignal) {
|
||||
tq_foreach_fwd(snl, nss)
|
||||
nss->close(nss);
|
||||
sudo_endpwent();
|
||||
sudo_endgrent();
|
||||
}
|
||||
#ifdef HAVE_LDAP
|
||||
if (ldap_conn != NULL) {
|
||||
sudo_ldap_close(ldap_conn);
|
||||
ldap_conn = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
21
sudo.h
21
sudo.h
@@ -27,8 +27,9 @@
|
||||
#include <pathnames.h>
|
||||
#include <limits.h>
|
||||
#include "compat.h"
|
||||
#include "error.h"
|
||||
#include "defaults.h"
|
||||
#include "error.h"
|
||||
#include "list.h"
|
||||
#include "logging.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 *));
|
||||
void check_user __P((int));
|
||||
void verify_user __P((struct passwd *, char *));
|
||||
int sudoers_lookup __P((int));
|
||||
int parse_sudoers __P((const char *));
|
||||
#ifdef HAVE_LDAP
|
||||
int sudo_ldap_check __P((void *, int));
|
||||
void sudo_ldap_display_privs __P((void *, struct passwd *));
|
||||
int sudo_ldap_display_cmnd __P((void *, struct passwd *));
|
||||
void sudo_ldap_update_defaults __P((void *));
|
||||
void *sudo_ldap_open __P((void));
|
||||
void sudo_ldap_close __P((void *));
|
||||
int sudo_ldap_open __P((struct sudo_nss *));
|
||||
int sudo_ldap_close __P((struct sudo_nss *));
|
||||
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
|
||||
void set_perms __P((int));
|
||||
void remove_timestamp __P((int));
|
||||
|
Reference in New Issue
Block a user