Add support for multiple sudoers_base entries in ldap.conf.

From Joachim Henke
This commit is contained in:
Todd C. Miller
2010-06-15 10:33:30 -04:00
parent 54ffb19ccb
commit d92c82ea3f
5 changed files with 174 additions and 120 deletions

View File

@@ -22,6 +22,10 @@ What's new in Sudo 1.7.3?
Mac OS X, and Linux systems with the devpts filesystem (pseudo-ttys Mac OS X, and Linux systems with the devpts filesystem (pseudo-ttys
only). only).
* Support for multiple 'sudoers_base' entries in ldap.conf. When
multiple bases are listed, sudo will try each one in the order
that they are specified.
* Sudo's SELinux support should now function correctly when running * Sudo's SELinux support should now function correctly when running
commands as a non-root user and when one of stdin, stdout or stderr commands as a non-root user and when one of stdin, stdout or stderr
is not a terminal. is not a terminal.

View File

@@ -61,7 +61,7 @@ DDEESSCCRRIIPPTTIIOONN
1.8.0b1 June 11, 2010 1 1.8.0b1 June 15, 2010 1
@@ -127,7 +127,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
1.8.0b1 June 11, 2010 2 1.8.0b1 June 15, 2010 2
@@ -193,7 +193,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
1.8.0b1 June 11, 2010 3 1.8.0b1 June 15, 2010 3
@@ -259,7 +259,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
1.8.0b1 June 11, 2010 4 1.8.0b1 June 15, 2010 4
@@ -301,7 +301,8 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
SSUUDDOOEERRSS__BBAASSEE base SSUUDDOOEERRSS__BBAASSEE base
The base DN to use when performing ssuuddoo LDAP queries. Typically The base DN to use when performing ssuuddoo LDAP queries. Typically
this is of the form ou=SUDOers,dc=example,dc=com for the domain this is of the form ou=SUDOers,dc=example,dc=com for the domain
example.com. example.com. Multiple SSUUDDOOEERRSS__BBAASSEE lines may be specified, in
which case they are queried in the order specified.
SSUUDDOOEERRSS__DDEEBBUUGG debug_level SSUUDDOOEERRSS__DDEEBBUUGG debug_level
This sets the debug level for ssuuddoo LDAP queries. Debugging This sets the debug level for ssuuddoo LDAP queries. Debugging
@@ -321,11 +322,10 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
BBIINNDDPPWW secret BBIINNDDPPWW secret
The BBIINNDDPPWW parameter specifies the password to use when performing The BBIINNDDPPWW parameter specifies the password to use when performing
LDAP operations. This is typically used in conjunction with the LDAP operations. This is typically used in conjunction with the
BBIINNDDDDNN parameter.
1.8.0b1 June 11, 2010 5 1.8.0b1 June 15, 2010 5
@@ -334,6 +334,8 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
BBIINNDDDDNN parameter.
RROOOOTTBBIINNDDDDNN DN RROOOOTTBBIINNDDDDNN DN
The RROOOOTTBBIINNDDDDNN parameter specifies the identity, in the form of a The RROOOOTTBBIINNDDDDNN parameter specifies the identity, in the form of a
Distinguished Name (DN), to use when performing privileged LDAP Distinguished Name (DN), to use when performing privileged LDAP
@@ -387,11 +389,9 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
OpenLDAP: OpenLDAP:
tls_cert /etc/ssl/client_cert.pem tls_cert /etc/ssl/client_cert.pem
Netscape-derived:
1.8.0b1 June 15, 2010 6
1.8.0b1 June 11, 2010 6
@@ -400,6 +400,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
Netscape-derived:
tls_cert /var/ldap/cert7.db tls_cert /var/ldap/cert7.db
When using Netscape-derived libraries, this file may also contain When using Netscape-derived libraries, this file may also contain
@@ -456,8 +457,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
1.8.0b1 June 15, 2010 7
1.8.0b1 June 11, 2010 7
@@ -523,7 +523,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
1.8.0b1 June 11, 2010 8 1.8.0b1 June 15, 2010 8
@@ -569,7 +569,7 @@ EEXXAAMMPPLLEESS
# The amount of time, in seconds, to wait while performing an LDAP query. # The amount of time, in seconds, to wait while performing an LDAP query.
timelimit 30 timelimit 30
# #
# must be set or sudo will ignore LDAP # Must be set or sudo will ignore LDAP; may be specified multiple times.
sudoers_base ou=SUDOers,dc=example,dc=com sudoers_base ou=SUDOers,dc=example,dc=com
# #
# verbose sudoers matching from ldap # verbose sudoers matching from ldap
@@ -589,7 +589,7 @@ EEXXAAMMPPLLEESS
1.8.0b1 June 11, 2010 9 1.8.0b1 June 15, 2010 9
@@ -655,7 +655,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
1.8.0b1 June 11, 2010 10 1.8.0b1 June 15, 2010 10
@@ -721,7 +721,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4)
1.8.0b1 June 11, 2010 11 1.8.0b1 June 15, 2010 11
@@ -787,6 +787,6 @@ DDIISSCCLLAAIIMMEERR
1.8.0b1 June 11, 2010 12 1.8.0b1 June 15, 2010 12

View File

@@ -140,7 +140,7 @@
.\" ======================================================================== .\" ========================================================================
.\" .\"
.IX Title "SUDOERS.LDAP @mansectform@" .IX Title "SUDOERS.LDAP @mansectform@"
.TH SUDOERS.LDAP @mansectform@ "June 11, 2010" "1.8.0b1" "MAINTENANCE COMMANDS" .TH SUDOERS.LDAP @mansectform@ "June 15, 2010" "1.8.0b1" "MAINTENANCE COMMANDS"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents. .\" way too many mistakes in technical documents.
.if n .ad l .if n .ad l
@@ -401,7 +401,8 @@ to wait for a response to an \s-1LDAP\s0 query.
.IX Item "SUDOERS_BASE base" .IX Item "SUDOERS_BASE base"
The base \s-1DN\s0 to use when performing \fBsudo\fR \s-1LDAP\s0 queries. Typically The base \s-1DN\s0 to use when performing \fBsudo\fR \s-1LDAP\s0 queries. Typically
this is of the form \f(CW\*(C`ou=SUDOers,dc=example,dc=com\*(C'\fR for the domain this is of the form \f(CW\*(C`ou=SUDOers,dc=example,dc=com\*(C'\fR for the domain
\&\f(CW\*(C`example.com\*(C'\fR. \&\f(CW\*(C`example.com\*(C'\fR. Multiple \fB\s-1SUDOERS_BASE\s0\fR lines may be specified,
in which case they are queried in the order specified.
.IP "\fB\s-1SUDOERS_DEBUG\s0\fR debug_level" 4 .IP "\fB\s-1SUDOERS_DEBUG\s0\fR debug_level" 4
.IX Item "SUDOERS_DEBUG debug_level" .IX Item "SUDOERS_DEBUG debug_level"
This sets the debug level for \fBsudo\fR \s-1LDAP\s0 queries. Debugging This sets the debug level for \fBsudo\fR \s-1LDAP\s0 queries. Debugging
@@ -647,7 +648,7 @@ determines sudoers source order on \s-1AIX\s0
\& # The amount of time, in seconds, to wait while performing an LDAP query. \& # The amount of time, in seconds, to wait while performing an LDAP query.
\& timelimit 30 \& timelimit 30
\& # \& #
\& # must be set or sudo will ignore LDAP \& # Must be set or sudo will ignore LDAP; may be specified multiple times.
\& sudoers_base ou=SUDOers,dc=example,dc=com \& sudoers_base ou=SUDOers,dc=example,dc=com
\& # \& #
\& # verbose sudoers matching from ldap \& # verbose sudoers matching from ldap

View File

@@ -301,7 +301,8 @@ to wait for a response to an LDAP query.
The base DN to use when performing B<sudo> LDAP queries. Typically The base DN to use when performing B<sudo> LDAP queries. Typically
this is of the form C<ou=SUDOers,dc=example,dc=com> for the domain this is of the form C<ou=SUDOers,dc=example,dc=com> for the domain
C<example.com>. C<example.com>. Multiple B<SUDOERS_BASE> lines may be specified,
in which case they are queried in the order specified.
=item B<SUDOERS_DEBUG> debug_level =item B<SUDOERS_DEBUG> debug_level
@@ -559,7 +560,7 @@ determines sudoers source order on AIX
# The amount of time, in seconds, to wait while performing an LDAP query. # The amount of time, in seconds, to wait while performing an LDAP query.
timelimit 30 timelimit 30
# #
# must be set or sudo will ignore LDAP # Must be set or sudo will ignore LDAP; may be specified multiple times.
sudoers_base ou=SUDOers,dc=example,dc=com sudoers_base ou=SUDOers,dc=example,dc=com
# #
# verbose sudoers matching from ldap # verbose sudoers matching from ldap

View File

@@ -112,6 +112,7 @@
#define CONF_BOOL 0 #define CONF_BOOL 0
#define CONF_INT 1 #define CONF_INT 1
#define CONF_STR 2 #define CONF_STR 2
#define CONF_LIST_STR 4
#define SUDO_LDAP_SSL 1 #define SUDO_LDAP_SSL 1
#define SUDO_LDAP_STARTTLS 2 #define SUDO_LDAP_STARTTLS 2
@@ -124,6 +125,11 @@ struct ldap_config_table {
void *valp; /* pointer into ldap_conf */ void *valp; /* pointer into ldap_conf */
}; };
struct ldap_config_list_str {
struct ldap_config_list_str *next;
char val[1];
};
/* ldap configuration structure */ /* ldap configuration structure */
static struct ldap_config { static struct ldap_config {
int port; int port;
@@ -141,7 +147,7 @@ static struct ldap_config {
char *binddn; char *binddn;
char *bindpw; char *bindpw;
char *rootbinddn; char *rootbinddn;
char *base; struct ldap_config_list_str *base;
char *ssl; char *ssl;
char *tls_cacertfile; char *tls_cacertfile;
char *tls_cacertdir; char *tls_cacertdir;
@@ -214,7 +220,7 @@ static struct ldap_config_table ldap_conf_table[] = {
{ "binddn", CONF_STR, FALSE, -1, &ldap_conf.binddn }, { "binddn", CONF_STR, FALSE, -1, &ldap_conf.binddn },
{ "bindpw", CONF_STR, FALSE, -1, &ldap_conf.bindpw }, { "bindpw", CONF_STR, FALSE, -1, &ldap_conf.bindpw },
{ "rootbinddn", CONF_STR, FALSE, -1, &ldap_conf.rootbinddn }, { "rootbinddn", CONF_STR, FALSE, -1, &ldap_conf.rootbinddn },
{ "sudoers_base", CONF_STR, FALSE, -1, &ldap_conf.base }, { "sudoers_base", CONF_LIST_STR, FALSE, -1, &ldap_conf.base },
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
{ "use_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.use_sasl }, { "use_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.use_sasl },
{ "sasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.sasl_auth_id }, { "sasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.sasl_auth_id },
@@ -904,6 +910,21 @@ sudo_ldap_read_config(void)
efree(*(char **)(cur->valp)); efree(*(char **)(cur->valp));
*(char **)(cur->valp) = estrdup(value); *(char **)(cur->valp) = estrdup(value);
break; break;
case CONF_LIST_STR:
{
struct ldap_config_list_str **p;
size_t len = strlen(value);
if (len > 0) {
p = (struct ldap_config_list_str **)cur->valp;
while (*p != NULL)
p = &(*p)->next;
*p = emalloc(sizeof(struct ldap_config_list_str) + len);
memcpy((*p)->val, value, len + 1);
(*p)->next = NULL;
}
}
break;
} }
break; break;
} }
@@ -932,8 +953,16 @@ sudo_ldap_read_config(void)
sudo_printf(SUDO_CONV_ERROR_MSG, "ldap_version %d\n", sudo_printf(SUDO_CONV_ERROR_MSG, "ldap_version %d\n",
ldap_conf.version); ldap_conf.version);
sudo_printf(SUDO_CONV_ERROR_MSG, "sudoers_base %s\n", if (ldap_conf.base) {
ldap_conf.base ? ldap_conf.base : "(NONE: LDAP disabled)"); struct ldap_config_list_str *base = ldap_conf.base;
do {
sudo_printf(SUDO_CONV_ERROR_MSG, "sudoers_base %s\n",
base->val);
} while ((base = base->next) != NULL);
} else {
sudo_printf(SUDO_CONV_ERROR_MSG, "sudoers_base %s\n",
"(NONE: LDAP disabled)");
}
sudo_printf(SUDO_CONV_ERROR_MSG, "binddn %s\n", sudo_printf(SUDO_CONV_ERROR_MSG, "binddn %s\n",
ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)"); ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)");
sudo_printf(SUDO_CONV_ERROR_MSG, "bindpw %s\n", sudo_printf(SUDO_CONV_ERROR_MSG, "bindpw %s\n",
@@ -1106,33 +1135,37 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw,
struct lbuf *lbuf) struct lbuf *lbuf)
{ {
struct berval **bv, **p; struct berval **bv, **p;
struct ldap_config_list_str *base;
LDAP *ld = (LDAP *) nss->handle; LDAP *ld = (LDAP *) nss->handle;
LDAPMessage *entry = NULL, *result = NULL; LDAPMessage *entry, *result;
char *prefix = NULL; char *prefix;
int rc, count = 0; int rc, count = 0;
if (ld == NULL) if (ld == NULL)
return(-1); return(-1);
rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, for (base = ldap_conf.base; base != NULL; base = base->next) {
"cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result); result = NULL;
if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) { rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE,
bv = ldap_get_values_len(ld, entry, "sudoOption"); "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result);
if (bv != NULL) { if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
if (lbuf->len == 0 || isspace((unsigned char)lbuf->buf[lbuf->len - 1])) bv = ldap_get_values_len(ld, entry, "sudoOption");
prefix = " "; if (bv != NULL) {
else if (lbuf->len == 0 || isspace((unsigned char)lbuf->buf[lbuf->len - 1]))
prefix = ", "; prefix = " ";
for (p = bv; *p != NULL; p++) { else
lbuf_append(lbuf, prefix, (*p)->bv_val, NULL); prefix = ", ";
prefix = ", "; for (p = bv; *p != NULL; p++) {
count++; lbuf_append(lbuf, prefix, (*p)->bv_val, NULL);
prefix = ", ";
count++;
}
ldap_value_free_len(bv);
} }
ldap_value_free_len(bv);
} }
if (result)
ldap_msgfree(result);
} }
if (result)
ldap_msgfree(result);
return(count); return(count);
} }
@@ -1305,8 +1338,9 @@ static int
sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw, sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw,
struct lbuf *lbuf) struct lbuf *lbuf)
{ {
struct ldap_config_list_str *base;
LDAP *ld = (LDAP *) nss->handle; LDAP *ld = (LDAP *) nss->handle;
LDAPMessage *entry = NULL, *result = NULL; LDAPMessage *entry, *result;
char *filt; char *filt;
int rc, do_netgr, count = 0; int rc, do_netgr, count = 0;
@@ -1330,26 +1364,28 @@ sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw,
for (do_netgr = 0; do_netgr < 2; do_netgr++) { for (do_netgr = 0; do_netgr < 2; do_netgr++) {
filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw); filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
DPRINTF(("ldap search '%s'", filt), 1); DPRINTF(("ldap search '%s'", filt), 1);
rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, for (base = ldap_conf.base; base != NULL; base = base->next) {
NULL, 0, NULL, NULL, NULL, 0, &result); result = NULL;
efree(filt); rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
if (rc != LDAP_SUCCESS) NULL, 0, NULL, NULL, NULL, 0, &result);
continue; /* no entries for this pass */ if (rc != LDAP_SUCCESS)
continue; /* no entries for this pass */
/* print each matching entry */ /* print each matching entry */
LDAP_FOREACH(entry, ld, result) { LDAP_FOREACH(entry, ld, result) {
if ((!do_netgr || if ((!do_netgr ||
sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) && sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
sudo_ldap_check_host(ld, entry)) { sudo_ldap_check_host(ld, entry)) {
if (long_list) if (long_list)
count += sudo_ldap_display_entry_long(ld, entry, lbuf); count += sudo_ldap_display_entry_long(ld, entry, lbuf);
else else
count += sudo_ldap_display_entry_short(ld, entry, lbuf); count += sudo_ldap_display_entry_short(ld, entry, lbuf);
}
} }
ldap_msgfree(result);
} }
ldap_msgfree(result); efree(filt);
result = NULL;
} }
return(count); return(count);
} }
@@ -1357,8 +1393,9 @@ sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw,
static int static int
sudo_ldap_display_cmnd(struct sudo_nss *nss, struct passwd *pw) sudo_ldap_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
{ {
struct ldap_config_list_str *base;
LDAP *ld = (LDAP *) nss->handle; LDAP *ld = (LDAP *) nss->handle;
LDAPMessage *entry = NULL, *result = NULL; /* used for searches */ LDAPMessage *entry, *result; /* used for searches */
char *filt; /* used to parse attributes */ char *filt; /* used to parse attributes */
int rc, found, do_netgr; /* temp/final return values */ int rc, found, do_netgr; /* temp/final return values */
@@ -1382,25 +1419,27 @@ sudo_ldap_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
for (found = FALSE, do_netgr = 0; !found && do_netgr < 2; do_netgr++) { for (found = FALSE, do_netgr = 0; !found && do_netgr < 2; do_netgr++) {
filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw); filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
DPRINTF(("ldap search '%s'", filt), 1); DPRINTF(("ldap search '%s'", filt), 1);
rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, for (base = ldap_conf.base; base != NULL; base = base->next) {
NULL, 0, NULL, NULL, NULL, 0, &result); result = NULL;
efree(filt); rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
if (rc != LDAP_SUCCESS) NULL, 0, NULL, NULL, NULL, 0, &result);
continue; /* no entries for this pass */ if (rc != LDAP_SUCCESS)
continue; /* no entries for this pass */
LDAP_FOREACH(entry, ld, result) { LDAP_FOREACH(entry, ld, result) {
if ((!do_netgr || if ((!do_netgr ||
sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) && sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
sudo_ldap_check_host(ld, entry) && sudo_ldap_check_host(ld, entry) &&
sudo_ldap_check_command(ld, entry, NULL) && sudo_ldap_check_command(ld, entry, NULL) &&
sudo_ldap_check_runas(ld, entry)) { sudo_ldap_check_runas(ld, entry)) {
found = TRUE; found = TRUE;
break; break;
}
} }
ldap_msgfree(result);
} }
ldap_msgfree(result); efree(filt);
result = NULL;
} }
if (found) if (found)
@@ -1676,23 +1715,27 @@ sudo_ldap_open(struct sudo_nss *nss)
static int static int
sudo_ldap_setdefs(struct sudo_nss *nss) sudo_ldap_setdefs(struct sudo_nss *nss)
{ {
struct ldap_config_list_str *base;
LDAP *ld = (LDAP *) nss->handle; LDAP *ld = (LDAP *) nss->handle;
LDAPMessage *entry = NULL, *result = NULL; /* used for searches */ LDAPMessage *entry, *result; /* used for searches */
int rc; /* temp return value */ int rc; /* temp return value */
if (ld == NULL) if (ld == NULL)
return(-1); return(-1);
rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, for (base = ldap_conf.base; base != NULL; base = base->next) {
"cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result); result = NULL;
if (rc == 0 && (entry = ldap_first_entry(ld, result))) { rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE,
DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1); "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result);
sudo_ldap_parse_options(ld, entry); if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
} else DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1);
DPRINTF(("no default options found!"), 1); sudo_ldap_parse_options(ld, entry);
} else
DPRINTF(("no default options found in %s", base->val), 1);
if (result) if (result)
ldap_msgfree(result); ldap_msgfree(result);
}
return(0); return(0);
} }
@@ -1703,8 +1746,9 @@ sudo_ldap_setdefs(struct sudo_nss *nss)
static int static int
sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag) sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
{ {
struct ldap_config_list_str *base;
LDAP *ld = (LDAP *) nss->handle; LDAP *ld = (LDAP *) nss->handle;
LDAPMessage *entry = NULL, *result = NULL; LDAPMessage *entry, *result;
char *filt; char *filt;
int do_netgr, rc, matched; int do_netgr, rc, matched;
int setenv_implied; int setenv_implied;
@@ -1721,34 +1765,36 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) { for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) {
filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw); filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, for (base = ldap_conf.base; base != NULL; base = base->next) {
NULL, 0, NULL, NULL, NULL, 0, &result); result = NULL;
efree(filt); rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
if (rc != LDAP_SUCCESS) NULL, 0, NULL, NULL, NULL, 0, &result);
continue; if (rc != LDAP_SUCCESS)
LDAP_FOREACH(entry, ld, result) {
/* only verify netgroup matches in pass 2 */
if (do_netgr && !sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name))
continue; continue;
ldap_user_matches = TRUE; LDAP_FOREACH(entry, ld, result) {
if (sudo_ldap_check_host(ld, entry)) { /* only verify netgroup matches in pass 2 */
ldap_host_matches = TRUE; if (do_netgr && !sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name))
if ((pwcheck == any && doauth != FALSE) || continue;
(pwcheck == all && doauth == FALSE))
doauth = sudo_ldap_check_bool(ld, entry, "authenticate"); ldap_user_matches = TRUE;
/* Only check the command when listing another user. */ if (sudo_ldap_check_host(ld, entry)) {
if (user_uid == 0 || list_pw == NULL || ldap_host_matches = TRUE;
user_uid == list_pw->pw_uid || if ((pwcheck == any && doauth != FALSE) ||
sudo_ldap_check_command(ld, entry, NULL)) { (pwcheck == all && doauth == FALSE))
matched = 1; doauth = sudo_ldap_check_bool(ld, entry, "authenticate");
break; /* end foreach */ /* Only check the command when listing another user. */
if (user_uid == 0 || list_pw == NULL ||
user_uid == list_pw->pw_uid ||
sudo_ldap_check_command(ld, entry, NULL)) {
matched = 1;
break; /* end foreach */
}
} }
} }
ldap_msgfree(result);
} }
ldap_msgfree(result); efree(filt);
result = NULL;
} }
if (matched || user_uid == 0) { if (matched || user_uid == 0) {
SET(ret, VALIDATE_OK); SET(ret, VALIDATE_OK);
@@ -1792,14 +1838,16 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) { for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) {
filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw); filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
DPRINTF(("ldap search '%s'", filt), 1); DPRINTF(("ldap search '%s'", filt), 1);
rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, for (base = ldap_conf.base; base != NULL; base = base->next) {
NULL, 0, NULL, NULL, NULL, 0, &result); result = NULL;
if (rc != LDAP_SUCCESS) rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
DPRINTF(("nothing found for '%s'", filt), 1); NULL, 0, NULL, NULL, NULL, 0, &result);
efree(filt); if (rc != LDAP_SUCCESS) {
DPRINTF(("nothing found for '%s'", filt), 1);
continue;
}
/* parse each entry returned from this most recent search */ /* parse each entry returned from this most recent search */
if (rc == LDAP_SUCCESS) {
LDAP_FOREACH(entry, ld, result) { LDAP_FOREACH(entry, ld, result) {
DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1); DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1);
if ( if (
@@ -1843,8 +1891,8 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
} }
} }
ldap_msgfree(result); ldap_msgfree(result);
result = NULL;
} }
efree(filt);
} }
done: done: