Add support for querying netgroups directly via LDAP since there
is no other way to look up all the netgroups for a user (unlike regular groups). This introduces netgroup_base and netgroup_search_filter options to ldap.conf. Based on a diff from Steven Soulen.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2014 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* Copyright (c) 2003-2015 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* This code is derived from software contributed by Aaron Spangler.
|
||||
*
|
||||
@@ -162,6 +162,9 @@ extern int ldapssl_set_strength(LDAP *ldap, int strength);
|
||||
/* Default search filter. */
|
||||
#define DEFAULT_SEARCH_FILTER "(objectClass=sudoRole)"
|
||||
|
||||
/* Default netgroup search filter. */
|
||||
#define DEFAULT_NETGROUP_SEARCH_FILTER "(objectClass=nisNetgroup)"
|
||||
|
||||
/* The TIMEFILTER_LENGTH is the length of the filter when timed entries
|
||||
are used. The length is computed as follows:
|
||||
81 for the filter itself
|
||||
@@ -207,6 +210,16 @@ struct ldap_result {
|
||||
};
|
||||
#define ALLOCATION_INCREMENT 100
|
||||
|
||||
/*
|
||||
* The ldap_netgroup structure implements a singly-linked tail queue of
|
||||
* netgroups a user is a member of when querying netgroups directly.
|
||||
*/
|
||||
struct ldap_netgroup {
|
||||
STAILQ_ENTRY(ldap_netgroup) entries;
|
||||
char *name;
|
||||
};
|
||||
STAILQ_HEAD(ldap_netgroup_list, ldap_netgroup);
|
||||
|
||||
struct ldap_config_table {
|
||||
const char *conf_str; /* config file string */
|
||||
int type; /* CONF_BOOL, CONF_INT, CONF_STR */
|
||||
@@ -218,7 +231,6 @@ struct ldap_config_str {
|
||||
STAILQ_ENTRY(ldap_config_str) entries;
|
||||
char val[1];
|
||||
};
|
||||
|
||||
STAILQ_HEAD(ldap_config_str_list, ldap_config_str);
|
||||
|
||||
/* LDAP configuration structure */
|
||||
@@ -242,7 +254,9 @@ static struct ldap_config {
|
||||
char *bindpw;
|
||||
char *rootbinddn;
|
||||
struct ldap_config_str_list base;
|
||||
struct ldap_config_str_list netgroup_base;
|
||||
char *search_filter;
|
||||
char *netgroup_search_filter;
|
||||
char *ssl;
|
||||
char *tls_cacertfile;
|
||||
char *tls_cacertdir;
|
||||
@@ -315,6 +329,8 @@ static struct ldap_config_table ldap_conf_global[] = {
|
||||
{ "sudoers_base", CONF_LIST_STR, -1, &ldap_conf.base },
|
||||
{ "sudoers_timed", CONF_BOOL, -1, &ldap_conf.timed },
|
||||
{ "sudoers_search_filter", CONF_STR, -1, &ldap_conf.search_filter },
|
||||
{ "netgroup_base", CONF_LIST_STR, -1, &ldap_conf.netgroup_base },
|
||||
{ "netgroup_search_filter", CONF_STR, -1, &ldap_conf.netgroup_search_filter },
|
||||
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
|
||||
{ "use_sasl", CONF_BOOL, -1, &ldap_conf.use_sasl },
|
||||
{ "sasl_auth_id", CONF_STR, -1, &ldap_conf.sasl_auth_id },
|
||||
@@ -408,7 +424,6 @@ struct sudo_nss sudo_nss_ldap = {
|
||||
static bool
|
||||
sudo_ldap_conf_add_ports(void)
|
||||
{
|
||||
|
||||
char *host, *port, defport[13];
|
||||
char hostbuf[LINE_MAX * 2];
|
||||
int len;
|
||||
@@ -744,18 +759,18 @@ sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entry)
|
||||
|
||||
/*
|
||||
* BUG:
|
||||
*
|
||||
*
|
||||
* if runas is not specified on the command line, the only information
|
||||
* as to which user to run as is in the runas_default option. We should
|
||||
* check to see if we have the local option present. Unfortunately we
|
||||
* don't parse these options until after this routine says yes or no.
|
||||
* The query has already returned, so we could peek at the attribute
|
||||
* values here though.
|
||||
*
|
||||
*
|
||||
* For now just require users to always use -u option unless its set
|
||||
* in the global defaults. This behaviour is no different than the global
|
||||
* /etc/sudoers.
|
||||
*
|
||||
*
|
||||
* Sigh - maybe add this feature later
|
||||
*/
|
||||
|
||||
@@ -1227,19 +1242,198 @@ done:
|
||||
return dlen + (s - src); /* count does not include NUL */
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the netgroups list beginning at "start" for nesting.
|
||||
* Parent nodes with a memberNisNetgroup that match one of the
|
||||
* netgroups are added to the list and checked for further nesting.
|
||||
* Return true on success or false if there was an internal overflow.
|
||||
*/
|
||||
static bool
|
||||
sudo_netgroup_lookup_nested(LDAP *ld, char *base, struct timeval *timeout,
|
||||
struct ldap_netgroup_list *netgroups, struct ldap_netgroup *start)
|
||||
{
|
||||
struct ldap_netgroup *ng, *old_tail;
|
||||
LDAPMessage *entry, *result;
|
||||
size_t filt_len;
|
||||
char *filt;
|
||||
int rc;
|
||||
debug_decl(sudo_netgroup_lookup_nested, SUDOERS_DEBUG_LDAP, sudoers_debug_instance);
|
||||
|
||||
DPRINTF1("Checking for nested netgroups from netgroup_base '%s'", base);
|
||||
do {
|
||||
old_tail = STAILQ_LAST(netgroups, ldap_netgroup, entries);
|
||||
filt_len = strlen(ldap_conf.netgroup_search_filter) + 7;
|
||||
for (ng = start; ng != NULL; ng = STAILQ_NEXT(ng, entries)) {
|
||||
filt_len += sudo_ldap_value_len(ng->name) + 20;
|
||||
}
|
||||
filt = sudo_emalloc(filt_len);
|
||||
CHECK_STRLCPY(filt, "(&", filt_len);
|
||||
CHECK_STRLCAT(filt, ldap_conf.netgroup_search_filter, filt_len);
|
||||
CHECK_STRLCAT(filt, "(|", filt_len);
|
||||
for (ng = start; ng != NULL; ng = STAILQ_NEXT(ng, entries)) {
|
||||
CHECK_STRLCAT(filt, "(memberNisNetgroup=", filt_len);
|
||||
CHECK_LDAP_VCAT(filt, ng->name, filt_len);
|
||||
CHECK_STRLCAT(filt, ")", filt_len);
|
||||
}
|
||||
CHECK_STRLCAT(filt, "))", filt_len);
|
||||
DPRINTF1("ldap netgroup search filter: '%s'", filt);
|
||||
result = NULL;
|
||||
rc = ldap_search_ext_s(ld, base, LDAP_SCOPE_SUBTREE, filt,
|
||||
NULL, 0, NULL, NULL, timeout, 0, &result);
|
||||
if (rc == LDAP_SUCCESS) {
|
||||
LDAP_FOREACH(entry, ld, result) {
|
||||
struct berval **bv;
|
||||
|
||||
bv = ldap_get_values_len(ld, entry, "cn");
|
||||
if (bv != NULL) {
|
||||
/* Don't add a netgroup twice. */
|
||||
STAILQ_FOREACH(ng, netgroups, entries) {
|
||||
/* Assumes only one cn per entry. */
|
||||
if (strcasecmp(ng->name, (*bv)->bv_val) == 0)
|
||||
break;
|
||||
}
|
||||
if (ng == NULL) {
|
||||
ng = sudo_emalloc(sizeof(*ng));
|
||||
ng->name = sudo_estrdup((*bv)->bv_val);
|
||||
STAILQ_INSERT_TAIL(netgroups, ng, entries);
|
||||
DPRINTF1("Found new netgroup %s for %s", ng->name, base);
|
||||
}
|
||||
ldap_value_free_len(bv);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
ldap_msgfree(result);
|
||||
sudo_efree(filt);
|
||||
|
||||
/* Check for nested netgroups in what we added. */
|
||||
start = old_tail ? STAILQ_NEXT(old_tail, entries) : STAILQ_FIRST(netgroups);
|
||||
} while (start != NULL);
|
||||
|
||||
debug_return_bool(true);
|
||||
overflow:
|
||||
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up netgroups that the specified user is a member of.
|
||||
* Appends new entries to the netgroups list.
|
||||
* Return true on success or false if there was an internal overflow.
|
||||
*/
|
||||
static bool
|
||||
sudo_netgroup_lookup(LDAP *ld, struct passwd *pw,
|
||||
struct ldap_netgroup_list *netgroups)
|
||||
{
|
||||
struct ldap_config_str *base;
|
||||
struct ldap_netgroup *ng, *old_tail;
|
||||
struct timeval tv, *tvp = NULL;
|
||||
LDAPMessage *entry, *result;
|
||||
size_t filt_len;
|
||||
char *filt;
|
||||
int rc;
|
||||
debug_decl(sudo_netgroup_lookup, SUDOERS_DEBUG_LDAP, sudoers_debug_instance);
|
||||
|
||||
if (ldap_conf.timeout > 0) {
|
||||
tv.tv_sec = ldap_conf.timeout;
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
|
||||
STAILQ_FOREACH(base, &ldap_conf.netgroup_base, entries) {
|
||||
/* Build query. */
|
||||
filt_len = 2 + strlen(ldap_conf.netgroup_search_filter) +
|
||||
24 + (2 * sudo_ldap_value_len(pw->pw_name)) + 26 +
|
||||
sudo_ldap_value_len(user_shost) + 1 + 7 + 1;
|
||||
if (user_host != user_shost) {
|
||||
filt_len += 26 + sudo_ldap_value_len(user_host) + 1 +
|
||||
sudo_ldap_value_len(pw->pw_name);
|
||||
}
|
||||
filt = sudo_emalloc(filt_len);
|
||||
DPRINTF1("searching from netgroup_base '%s'", base->val);
|
||||
CHECK_STRLCPY(filt, "(&", filt_len);
|
||||
CHECK_STRLCAT(filt, ldap_conf.netgroup_search_filter, filt_len);
|
||||
CHECK_STRLCAT(filt, "(|(nisNetgroupTriple=\\(,", filt_len);
|
||||
CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
|
||||
CHECK_STRLCAT(filt, ",*\\))(nisNetgroupTriple=\\(", filt_len);
|
||||
CHECK_LDAP_VCAT(filt, user_shost, filt_len);
|
||||
CHECK_STRLCAT(filt, ",", filt_len);
|
||||
CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
|
||||
if (user_host != user_shost) {
|
||||
CHECK_STRLCAT(filt, ",*\\))(nisNetgroupTriple=\\(", filt_len);
|
||||
CHECK_LDAP_VCAT(filt, user_host, filt_len);
|
||||
CHECK_STRLCAT(filt, ",", filt_len);
|
||||
CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
|
||||
}
|
||||
CHECK_STRLCAT(filt, ",*\\))))", filt_len);
|
||||
|
||||
DPRINTF1("ldap netgroup search filter: '%s'", filt);
|
||||
result = NULL;
|
||||
rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
|
||||
NULL, 0, NULL, NULL, tvp, 0, &result);
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
DPRINTF1("nothing found for '%s'", filt);
|
||||
if (result)
|
||||
ldap_msgfree(result);
|
||||
sudo_efree(filt);
|
||||
continue;
|
||||
}
|
||||
sudo_efree(filt);
|
||||
|
||||
old_tail = STAILQ_LAST(netgroups, ldap_netgroup, entries);
|
||||
LDAP_FOREACH(entry, ld, result) {
|
||||
struct berval **bv;
|
||||
|
||||
bv = ldap_get_values_len(ld, entry, "cn");
|
||||
if (bv != NULL) {
|
||||
/* Don't add a netgroup twice. */
|
||||
STAILQ_FOREACH(ng, netgroups, entries) {
|
||||
/* Assumes only one cn per entry. */
|
||||
if (strcasecmp(ng->name, (*bv)->bv_val) == 0)
|
||||
break;
|
||||
}
|
||||
if (ng == NULL) {
|
||||
ng = sudo_emalloc(sizeof(*ng));
|
||||
ng->name = sudo_estrdup((*bv)->bv_val);
|
||||
STAILQ_INSERT_TAIL(netgroups, ng, entries);
|
||||
DPRINTF1("Found new netgroup %s for %s", ng->name,
|
||||
base->val);
|
||||
}
|
||||
ldap_value_free_len(bv);
|
||||
}
|
||||
}
|
||||
ldap_msgfree(result);
|
||||
|
||||
/* Check for nested netgroups in what we added. */
|
||||
ng = old_tail ? STAILQ_NEXT(old_tail, entries) : STAILQ_FIRST(netgroups);
|
||||
if (ng != NULL) {
|
||||
if (!sudo_netgroup_lookup_nested(ld, base->val, tvp, netgroups, ng))
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
debug_return_bool(true);
|
||||
overflow:
|
||||
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Builds up a filter to check against LDAP.
|
||||
*/
|
||||
static char *
|
||||
sudo_ldap_build_pass1(struct passwd *pw)
|
||||
sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw)
|
||||
{
|
||||
struct group *grp;
|
||||
char *buf, timebuffer[TIMEFILTER_LENGTH + 1], gidbuf[MAX_UID_T_LEN + 1];
|
||||
struct ldap_netgroup_list netgroups;
|
||||
struct ldap_netgroup *ng, *nextng;
|
||||
struct group_list *grlist;
|
||||
struct group *grp;
|
||||
size_t sz = 0;
|
||||
int i;
|
||||
debug_decl(sudo_ldap_build_pass1, SUDOERS_DEBUG_LDAP, sudoers_debug_instance)
|
||||
|
||||
STAILQ_INIT(&netgroups);
|
||||
|
||||
/* If there is a filter, allocate space for the global AND. */
|
||||
if (ldap_conf.timed || ldap_conf.search_filter)
|
||||
sz += 3;
|
||||
@@ -1269,6 +1463,23 @@ sudo_ldap_build_pass1(struct passwd *pw)
|
||||
}
|
||||
}
|
||||
|
||||
/* Add space for user netgroups if netgroup_base specified. */
|
||||
if (!STAILQ_EMPTY(&ldap_conf.netgroup_base)) {
|
||||
DPRINTF1("Looking up netgroups for %s", pw->pw_name);
|
||||
if (sudo_netgroup_lookup(ld, pw, &netgroups)) {
|
||||
STAILQ_FOREACH(ng, &netgroups, entries) {
|
||||
sz += 14 + strlen(ng->name);
|
||||
}
|
||||
} else {
|
||||
/* sudo_netgroup_lookup() failed, clean up. */
|
||||
STAILQ_FOREACH_SAFE(ng, &netgroups, entries, nextng) {
|
||||
sudo_efree(ng->name);
|
||||
sudo_efree(ng);
|
||||
}
|
||||
STAILQ_INIT(&netgroups);
|
||||
}
|
||||
}
|
||||
|
||||
/* If timed, add space for time limits. */
|
||||
if (ldap_conf.timed)
|
||||
sz += TIMEFILTER_LENGTH;
|
||||
@@ -1327,7 +1538,16 @@ sudo_ldap_build_pass1(struct passwd *pw)
|
||||
if (grp != NULL)
|
||||
sudo_gr_delref(grp);
|
||||
|
||||
/* Add ALL to list and end the global OR */
|
||||
/* Add netgroups (if any), freeing the list as we go. */
|
||||
STAILQ_FOREACH_SAFE(ng, &netgroups, entries, nextng) {
|
||||
CHECK_STRLCAT(buf, "(sudoUser=+", sz);
|
||||
CHECK_LDAP_VCAT(buf, ng->name, sz);
|
||||
CHECK_STRLCAT(buf, ")", sz);
|
||||
sudo_efree(ng->name);
|
||||
sudo_efree(ng);
|
||||
}
|
||||
|
||||
/* Add ALL to list and end the global OR. */
|
||||
CHECK_STRLCAT(buf, "(sudoUser=ALL)", sz);
|
||||
|
||||
/* Add the time restriction, or simply end the global OR. */
|
||||
@@ -1354,32 +1574,36 @@ static char *
|
||||
sudo_ldap_build_pass2(void)
|
||||
{
|
||||
char *filt, timebuffer[TIMEFILTER_LENGTH + 1];
|
||||
bool query_netgroups = def_use_netgroups;
|
||||
debug_decl(sudo_ldap_build_pass2, SUDOERS_DEBUG_LDAP, sudoers_debug_instance)
|
||||
|
||||
/* Short circuit if no non-Unix group support. */
|
||||
if (!def_use_netgroups && !def_group_plugin) {
|
||||
/* No need to query netgroups if using netgroup_base. */
|
||||
if (!STAILQ_EMPTY(&ldap_conf.netgroup_base))
|
||||
query_netgroups = false;
|
||||
|
||||
/* Short circuit if no netgroups and no non-Unix groups. */
|
||||
if (!query_netgroups && !def_group_plugin)
|
||||
debug_return_str(NULL);
|
||||
}
|
||||
|
||||
if (ldap_conf.timed)
|
||||
sudo_ldap_timefilter(timebuffer, sizeof(timebuffer));
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (def_group_plugin) {
|
||||
sudo_easprintf(&filt, "%s%s(|(sudoUser=%s*)(sudoUser=%%:*))%s%s",
|
||||
if (query_netgroups && def_group_plugin) {
|
||||
sudo_easprintf(&filt, "%s%s(|(sudoUser=+*)(sudoUser=%%:*))%s%s",
|
||||
(ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "",
|
||||
ldap_conf.search_filter ? ldap_conf.search_filter : "",
|
||||
def_use_netgroups ? "+" : "",
|
||||
ldap_conf.timed ? timebuffer : "",
|
||||
(ldap_conf.timed || ldap_conf.search_filter) ? ")" : "");
|
||||
} else {
|
||||
sudo_easprintf(&filt, "%s%s(sudoUser=*)(sudoUser=+*)%s%s",
|
||||
sudo_easprintf(&filt, "%s%s(sudoUser=*)(sudoUser=%s*)%s%s",
|
||||
(ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "",
|
||||
ldap_conf.search_filter ? ldap_conf.search_filter : "",
|
||||
query_netgroups ? "+" : "%:",
|
||||
ldap_conf.timed ? timebuffer : "",
|
||||
(ldap_conf.timed || ldap_conf.search_filter) ? ")" : "");
|
||||
}
|
||||
@@ -1559,9 +1783,10 @@ sudo_check_krb5_ccname(const char *ccname)
|
||||
static bool
|
||||
sudo_ldap_read_config(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char *cp, *keyword, *value, *line = NULL;
|
||||
struct ldap_config_str *conf_str;
|
||||
size_t linesize = 0;
|
||||
FILE *fp;
|
||||
debug_decl(sudo_ldap_read_config, SUDOERS_DEBUG_LDAP, sudoers_debug_instance)
|
||||
|
||||
/* defaults */
|
||||
@@ -1575,8 +1800,10 @@ sudo_ldap_read_config(void)
|
||||
ldap_conf.rootuse_sasl = -1;
|
||||
ldap_conf.deref = -1;
|
||||
ldap_conf.search_filter = sudo_estrdup(DEFAULT_SEARCH_FILTER);
|
||||
ldap_conf.netgroup_search_filter = sudo_estrdup(DEFAULT_NETGROUP_SEARCH_FILTER);
|
||||
STAILQ_INIT(&ldap_conf.uri);
|
||||
STAILQ_INIT(&ldap_conf.base);
|
||||
STAILQ_INIT(&ldap_conf.netgroup_base);
|
||||
|
||||
if ((fp = fopen(path_ldap_conf, "r")) == NULL)
|
||||
debug_return_bool(false);
|
||||
@@ -1610,10 +1837,8 @@ sudo_ldap_read_config(void)
|
||||
DPRINTF1("LDAP Config Summary");
|
||||
DPRINTF1("===================");
|
||||
if (!STAILQ_EMPTY(&ldap_conf.uri)) {
|
||||
struct ldap_config_str *uri;
|
||||
|
||||
STAILQ_FOREACH(uri, &ldap_conf.uri, entries) {
|
||||
DPRINTF1("uri %s", uri->val);
|
||||
STAILQ_FOREACH(conf_str, &ldap_conf.uri, entries) {
|
||||
DPRINTF1("uri %s", conf_str->val);
|
||||
}
|
||||
} else {
|
||||
DPRINTF1("host %s",
|
||||
@@ -1623,9 +1848,8 @@ sudo_ldap_read_config(void)
|
||||
DPRINTF1("ldap_version %d", ldap_conf.version);
|
||||
|
||||
if (!STAILQ_EMPTY(&ldap_conf.base)) {
|
||||
struct ldap_config_str *base;
|
||||
STAILQ_FOREACH(base, &ldap_conf.base, entries) {
|
||||
DPRINTF1("sudoers_base %s", base->val);
|
||||
STAILQ_FOREACH(conf_str, &ldap_conf.base, entries) {
|
||||
DPRINTF1("sudoers_base %s", conf_str->val);
|
||||
}
|
||||
} else {
|
||||
DPRINTF1("sudoers_base %s", "(NONE: LDAP disabled)");
|
||||
@@ -1633,6 +1857,16 @@ sudo_ldap_read_config(void)
|
||||
if (ldap_conf.search_filter) {
|
||||
DPRINTF1("search_filter %s", ldap_conf.search_filter);
|
||||
}
|
||||
if (!STAILQ_EMPTY(&ldap_conf.netgroup_base)) {
|
||||
STAILQ_FOREACH(conf_str, &ldap_conf.netgroup_base, entries) {
|
||||
DPRINTF1("netgroup_base %s", conf_str->val);
|
||||
}
|
||||
} else {
|
||||
DPRINTF1("netgroup_base %s", "(NONE: will use nsswitch)");
|
||||
}
|
||||
if (ldap_conf.netgroup_search_filter) {
|
||||
DPRINTF1("netgroup_search_filter %s", ldap_conf.netgroup_search_filter);
|
||||
}
|
||||
DPRINTF1("binddn %s",
|
||||
ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)");
|
||||
DPRINTF1("bindpw %s",
|
||||
@@ -2706,7 +2940,7 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
|
||||
if (pwflag) {
|
||||
int doauth = UNSPEC;
|
||||
int matched = UNSPEC;
|
||||
enum def_tuple pwcheck =
|
||||
enum def_tuple pwcheck =
|
||||
(pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
|
||||
|
||||
DPRINTF1("perform search for pwflag %d", pwflag);
|
||||
@@ -2949,7 +3183,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
|
||||
*/
|
||||
lres = sudo_ldap_result_alloc();
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(pw);
|
||||
filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(ld, pw);
|
||||
if (filt != NULL) {
|
||||
DPRINTF1("ldap search '%s'", filt);
|
||||
STAILQ_FOREACH(base, &ldap_conf.base, entries) {
|
||||
|
Reference in New Issue
Block a user