Enable non-Unix group support for LDAP sudoers. We now check for

non-Unix groups and netgroups with the same query in the second
pass.  Bug #571
This commit is contained in:
Todd C. Miller
2012-09-15 13:41:24 -04:00
parent 5276ab3a5f
commit bdf93e8d3e

View File

@@ -613,15 +613,15 @@ done:
/* /*
* 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. * non-Unix group (including netgroups), else false.
*/ */
static bool static bool
sudo_ldap_check_user_netgroup(LDAP *ld, LDAPMessage *entry, char *user) sudo_ldap_check_non_unix_group(LDAP *ld, LDAPMessage *entry, struct passwd *pw)
{ {
struct berval **bv, **p; struct berval **bv, **p;
char *val; char *val;
int ret = false; int ret = false;
debug_decl(sudo_ldap_check_user_netgroup, SUDO_DEBUG_LDAP) debug_decl(sudo_ldap_check_non_unix_group, SUDO_DEBUG_LDAP)
if (!entry) if (!entry)
debug_return_bool(ret); debug_return_bool(ret);
@@ -634,11 +634,17 @@ sudo_ldap_check_user_netgroup(LDAP *ld, LDAPMessage *entry, char *user)
/* walk through values */ /* walk through values */
for (p = bv; *p != NULL && !ret; p++) { for (p = bv; *p != NULL && !ret; p++) {
val = (*p)->bv_val; val = (*p)->bv_val;
/* match any */ if (*val == '+') {
if (netgr_matches(val, NULL, NULL, user)) if (netgr_matches(val, NULL, NULL, pw->pw_name))
ret = true; ret = true;
DPRINTF(("ldap sudoUser netgroup '%s' ... %s", val, DPRINTF(("ldap sudoUser netgroup '%s' ... %s", val,
ret ? "MATCH!" : "not"), 2 + ((ret) ? 0 : 1)); ret ? "MATCH!" : "not"), 2 + ((ret) ? 0 : 1));
} else {
if (group_plugin_query(pw->pw_name, val + 2, pw))
ret = true;
DPRINTF(("ldap sudoUser non-Unix group '%s' ... %s", val,
ret ? "MATCH!" : "not"), 2 + ((ret) ? 0 : 1));
}
} }
ldap_value_free_len(bv); /* cleanup */ ldap_value_free_len(bv); /* cleanup */
@@ -1238,7 +1244,8 @@ sudo_ldap_build_pass1(struct passwd *pw)
} }
/* /*
* Builds up a filter to check against netgroup entries in LDAP. * Builds up a filter to check against non-Unix group
* entries in LDAP, including netgroups.
*/ */
static char * static char *
sudo_ldap_build_pass2(void) sudo_ldap_build_pass2(void)
@@ -1250,15 +1257,23 @@ sudo_ldap_build_pass2(void)
sudo_ldap_timefilter(timebuffer, sizeof(timebuffer)); sudo_ldap_timefilter(timebuffer, sizeof(timebuffer));
/* /*
* Match all sudoUsers beginning with a '+'. * Match all sudoUsers beginning with '+' or '%:'.
* If a search filter or time restriction is specified, * If a search filter or time restriction is specified,
* those get ANDed in to the expression. * those get ANDed in to the expression.
*/ */
easprintf(&filt, "%s%s(sudoUser=+*)%s%s", if (def_group_plugin) {
(ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "", easprintf(&filt, "%s%s(|(sudoUser=+*)(sudoUser=%%:*))%s%s",
ldap_conf.search_filter ? ldap_conf.search_filter : "", (ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "",
ldap_conf.timed ? timebuffer : "", ldap_conf.search_filter ? ldap_conf.search_filter : "",
(ldap_conf.timed || ldap_conf.search_filter) ? ")" : ""); ldap_conf.timed ? timebuffer : "",
(ldap_conf.timed || ldap_conf.search_filter) ? ")" : "");
} else {
easprintf(&filt, "%s%s(sudoUser=+*)%s%s",
(ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "",
ldap_conf.search_filter ? ldap_conf.search_filter : "",
ldap_conf.timed ? timebuffer : "",
(ldap_conf.timed || ldap_conf.search_filter) ? ")" : "");
}
debug_return_str(filt); debug_return_str(filt);
} }
@@ -2567,7 +2582,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
struct timeval tv, *tvp = NULL; struct timeval tv, *tvp = NULL;
LDAPMessage *entry, *result; LDAPMessage *entry, *result;
LDAP *ld = handle->ld; LDAP *ld = handle->ld;
int do_netgr, rc; int pass, rc;
char *filt; char *filt;
debug_decl(sudo_ldap_result_get, SUDO_DEBUG_LDAP) debug_decl(sudo_ldap_result_get, SUDO_DEBUG_LDAP)
@@ -2598,17 +2613,17 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
* sudoUser in this pass since the LDAP server already scanned * sudoUser in this pass since the LDAP server already scanned
* it for us. * it for us.
* *
* The second pass will return all the entries that contain * The second pass will return all the entries that contain non-
* user netgroups. Then we take the netgroups returned and * Unix groups, including netgroups. Then we take the non-Unix
* try to match them against the username. * groups returned and try to match them against the username.
* *
* Since we have to sort the possible entries before we make a * Since we have to sort the possible entries before we make a
* decision, we perform the queries and store all of the results in * decision, we perform the queries and store all of the results in
* an ldap_result object. The results are then sorted by sudoOrder. * an ldap_result object. The results are then sorted by sudoOrder.
*/ */
lres = sudo_ldap_result_alloc(); lres = sudo_ldap_result_alloc();
for (do_netgr = 0; do_netgr < 2; do_netgr++) { for (pass = 0; pass < 2; pass++) {
filt = do_netgr ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(pw); filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(pw);
DPRINTF(("ldap search '%s'", filt), 1); DPRINTF(("ldap search '%s'", filt), 1);
for (base = ldap_conf.base; base != NULL; base = base->next) { for (base = ldap_conf.base; base != NULL; base = base->next) {
DPRINTF(("searching from base '%s'", base->val), 1); DPRINTF(("searching from base '%s'", base->val), 1);
@@ -2630,8 +2645,8 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
DPRINTF(("adding search result"), 1); DPRINTF(("adding search result"), 1);
sudo_ldap_result_add_search(lres, ld, result); sudo_ldap_result_add_search(lres, ld, result);
LDAP_FOREACH(entry, ld, result) { LDAP_FOREACH(entry, ld, result) {
if ((!do_netgr || if ((!pass ||
sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) && sudo_ldap_check_non_unix_group(ld, entry, pw)) &&
sudo_ldap_check_host(ld, entry)) { sudo_ldap_check_host(ld, entry)) {
lres->host_matches = true; lres->host_matches = true;
sudo_ldap_result_add_entry(lres, entry); sudo_ldap_result_add_entry(lres, entry);