diff options
author | Günther Deschner <gd@samba.org> | 2007-04-22 15:25:54 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:19:35 -0500 |
commit | fa2756c944b0316b2fef33646d15d13670dcfb49 (patch) | |
tree | e233366e46d01e163bb2a8a8c6399685a934de89 /source3/nsswitch | |
parent | 56f6336fd4a8e929bf18f1c1c3b3f8f54ee341f5 (diff) | |
download | samba-fa2756c944b0316b2fef33646d15d13670dcfb49.tar.gz samba-fa2756c944b0316b2fef33646d15d13670dcfb49.tar.bz2 samba-fa2756c944b0316b2fef33646d15d13670dcfb49.zip |
r22461: Use ranged LDAP queries in lookup_usergroups_member() and start to optinmize
lookup_groupmem(). In the later, at least try to avoid those massive LDAP
dn_lookups by looking in the cache before.
Guenther
(This used to be commit eb1566869c5493f2a1d1ff9fcaaa45c143ad12a0)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 174 |
1 files changed, 75 insertions, 99 deletions
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index 8391a985fc..f189123d7d 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -609,13 +609,15 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain, { ADS_STATUS rc; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - int count; LDAPMessage *res = NULL; ADS_STRUCT *ads; const char *attrs[] = {"memberOf", NULL}; size_t num_groups = 0; DOM_SID *group_sids = NULL; int i; + char **strings; + size_t num_strings = 0; + DEBUG(3,("ads: lookup_usergroups_memberof\n")); @@ -626,22 +628,16 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain, goto done; } - rc = ads_search_retry_extended_dn(ads, &res, user_dn, attrs, - ADS_EXTENDED_DN_HEX_STRING); - - if (!ADS_ERR_OK(rc) || !res) { + rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs, + ADS_EXTENDED_DN_HEX_STRING, + &strings, &num_strings); + + if (!ADS_ERR_OK(rc)) { DEBUG(1,("lookup_usergroups_memberof ads_search member=%s: %s\n", user_dn, ads_errstr(rc))); return ads_ntstatus(rc); } - count = ads_count_replies(ads, res); - - if (count == 0) { - status = NT_STATUS_NO_SUCH_USER; - goto done; - } - *user_sids = NULL; num_groups = 0; @@ -651,16 +647,32 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain, goto done; } - count = ads_pull_sids_from_extendeddn(ads, mem_ctx, res, "memberOf", - ADS_EXTENDED_DN_HEX_STRING, - &group_sids); - if (count == 0) { + group_sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_strings + 1); + if (!group_sids) { + TALLOC_FREE(strings); + status = NT_STATUS_NO_MEMORY; + goto done; + } + + for (i=0; i<num_strings; i++) { + + if (!ads_get_sid_from_extended_dn(mem_ctx, strings[i], + ADS_EXTENDED_DN_HEX_STRING, + &(group_sids)[i])) { + TALLOC_FREE(group_sids); + TALLOC_FREE(strings); + status = NT_STATUS_NO_MEMORY; + goto done; + } + } + + if (i == 0) { DEBUG(1,("No memberOf for this user?!?\n")); status = NT_STATUS_NO_MEMORY; goto done; } - for (i=0; i<count; i++) { + for (i=0; i<num_strings; i++) { /* ignore Builtin groups from ADS - Guenther */ if (sid_check_is_in_builtin(&group_sids[i])) { @@ -841,7 +853,6 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, uint32 **name_types) { ADS_STATUS rc; - int count; LDAPMessage *res=NULL; ADS_STRUCT *ads = NULL; char *ldap_exp; @@ -851,11 +862,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, int i; size_t num_members; fstring sid_string; - BOOL more_values; - const char **attrs; - uint32 first_usn; - uint32 current_usn; - int num_retries = 0; + ads_control args; DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name, sid_string_static(group_sid))); @@ -886,77 +893,19 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, members = NULL; num_members = 0; - if ((attrs = TALLOC_ARRAY(mem_ctx, const char *, 3)) == NULL) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - attrs[1] = talloc_strdup(mem_ctx, "usnChanged"); - attrs[2] = NULL; - - do { - if (num_members == 0) - attrs[0] = talloc_strdup(mem_ctx, "member"); - - DEBUG(10, ("Searching for attrs[0] = %s, attrs[1] = %s\n", attrs[0], attrs[1])); - - rc = ads_search_retry(ads, &res, ldap_exp, attrs); - - if (!ADS_ERR_OK(rc) || !res) { - DEBUG(1,("ads: lookup_groupmem ads_search: %s\n", - ads_errstr(rc))); - status = ads_ntstatus(rc); - goto done; - } + args.control = ADS_EXTENDED_DN_OID; + args.val = ADS_EXTENDED_DN_HEX_STRING; + args.critical = True; - count = ads_count_replies(ads, res); - if (count == 0) - break; + rc = ads_ranged_search(ads, mem_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path, + ldap_exp, &args, "member", &members, &num_members); - if (num_members == 0) { - if (!ads_pull_uint32(ads, res, "usnChanged", &first_usn)) { - DEBUG(1, ("ads: lookup_groupmem could not pull usnChanged!\n")); - goto done; - } - } - - if (!ads_pull_uint32(ads, res, "usnChanged", ¤t_usn)) { - DEBUG(1, ("ads: lookup_groupmem could not pull usnChanged!\n")); - goto done; - } - - if (first_usn != current_usn) { - DEBUG(5, ("ads: lookup_groupmem USN on this record changed" - " - restarting search\n")); - if (num_retries < 5) { - num_retries++; - num_members = 0; - ads_msgfree(ads, res); - res = NULL; - continue; - } else { - DEBUG(5, ("ads: lookup_groupmem USN on this record changed" - " - restarted search too many times, aborting!\n")); - status = NT_STATUS_UNSUCCESSFUL; - goto done; - } - } - - members = ads_pull_strings_range(ads, mem_ctx, res, - "member", - members, - &attrs[0], - &num_members, - &more_values); - - ads_msgfree(ads, res); - res = NULL; - - if ((members == NULL) || (num_members == 0)) - break; - - } while (more_values); - + if (!ADS_ERR_OK(rc)) { + DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc))); + status = NT_STATUS_UNSUCCESSFUL; + goto done; + } + /* now we need to turn a list of members into rids, names and name types the problem is that the members are in the form of distinguised names */ @@ -975,19 +924,46 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, for (i=0;i<num_members;i++) { uint32 name_type; - char *name; + char *name, *domain_name, *dn; DOM_SID sid; - if (dn_lookup(ads, mem_ctx, members[i], &name, &name_type, &sid)) { - (*names)[*num_names] = name; - (*name_types)[*num_names] = name_type; - sid_copy(&(*sid_mem)[*num_names], &sid); - (*num_names)++; + if ((!ads_get_sid_from_extended_dn(mem_ctx, members[i], ADS_EXTENDED_DN_HEX_STRING, &sid)) || + (!ads_get_dn_from_extended_dn(mem_ctx, members[i], &dn))) + { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name, &name_type)) { + + DEBUG(10,("ads: lookup_groupmem: got sid %s from cache\n", + sid_string_static(&sid))); + + (*names)[*num_names] = CONST_DISCARD(char *,name); + (*name_types)[*num_names] = name_type; + sid_copy(&(*sid_mem)[*num_names], &sid); + + (*num_names)++; + + continue; + } + + if (dn_lookup(ads, mem_ctx, dn, &name, &name_type, &sid)) { + + DEBUG(10,("ads: lookup_groupmem: got sid %s from dn_lookup\n", + sid_string_static(&sid))); + + (*names)[*num_names] = name; + (*name_types)[*num_names] = name_type; + sid_copy(&(*sid_mem)[*num_names], &sid); + + (*num_names)++; + } } status = NT_STATUS_OK; - DEBUG(3,("ads lookup_groupmem for sid=%s\n", sid_to_string(sid_string, group_sid))); + DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n", sid_to_string(sid_string, group_sid))); done: if (res) |