summaryrefslogtreecommitdiff
path: root/source3/nsswitch/winbindd_ads.c
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2004-01-01 20:33:45 +0000
committerVolker Lendecke <vlendec@samba.org>2004-01-01 20:33:45 +0000
commit1c13660eebdc905c2df819aa273737c179452957 (patch)
treec5222ec6d0e66450b1f09176fbf03c40118f897a /source3/nsswitch/winbindd_ads.c
parent6eb471e11e596bc27d2d42ff457d6bd772eed228 (diff)
downloadsamba-1c13660eebdc905c2df819aa273737c179452957.tar.gz
samba-1c13660eebdc905c2df819aa273737c179452957.tar.bz2
samba-1c13660eebdc905c2df819aa273737c179452957.zip
Fix for bug 707, getent group for huge ads groups (>1500 members)
This introduces range retrieval of ADS attributes. I've rewritten most of Günther's patch, partly to remove code duplication and partly to get the retrieval of members in one rush, not interrupted by the lookups for the DN. Andrew, you told me that you would like to see a check whether the AD sequence number is the same before and after the retrieval to achieve atomicity. This would be trivial to add, but I'm not sure that we want this, as this adds two roundtrips to every membership query. We can not know before the first query whether we get additional range values, and at that point it's too late to ask for the USN. Tested with a group of 4000 members along with lots of small groups. Volker (This used to be commit a2aa6e41e552abfb6d1056ab3a7c75e8fd0a150c)
Diffstat (limited to 'source3/nsswitch/winbindd_ads.c')
-rw-r--r--source3/nsswitch/winbindd_ads.c69
1 files changed, 48 insertions, 21 deletions
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index 5d0f924d8f..11767504c1 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -689,10 +689,11 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
char *ldap_exp;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
char *sidstr;
- const char *attrs[] = {"member", NULL};
char **members;
int i, num_members;
fstring sid_string;
+ const char *attr = "member";
+ BOOL more_values;
DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name, sid_string_static(group_sid)));
@@ -709,33 +710,56 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
/* search for all members of the group */
asprintf(&ldap_exp, "(objectSid=%s)",sidstr);
- rc = ads_search_retry(ads, &res, ldap_exp, attrs);
- free(ldap_exp);
- free(sidstr);
- if (!ADS_ERR_OK(rc) || !res) {
- DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
- goto done;
- }
+ members = NULL;
+ num_members = 0;
+ more_values = True;
- count = ads_count_replies(ads, res);
- if (count == 0) {
- status = NT_STATUS_OK;
- goto done;
- }
+ while (more_values) {
- members = ads_pull_strings(ads, mem_ctx, res, "member");
- if (!members) {
- /* no members? ok ... */
- status = NT_STATUS_OK;
- goto done;
- }
+ int num_this_time;
+ char **new_members;
+ const char *attrs[] = {attr, NULL};
+
+ rc = ads_search_retry(ads, &res, ldap_exp, attrs);
+ if (!ADS_ERR_OK(rc) || !res) {
+ DEBUG(1,("query_user_list ads_search: %s\n",
+ ads_errstr(rc)));
+ goto done;
+ }
+
+ count = ads_count_replies(ads, res);
+ if (count == 0)
+ break;
+
+ new_members = ads_pull_strings_range(ads, mem_ctx, res,
+ "member",
+ &num_this_time,
+ &more_values);
+
+ if ((new_members == NULL) || (num_this_time == 0))
+ break;
+
+ members = talloc_realloc(mem_ctx, members,
+ sizeof(*members) *
+ (num_members+num_this_time));
+
+ if (members == NULL)
+ break;
+
+ memcpy(members+num_members, new_members,
+ sizeof(new_members)*num_this_time);
+
+ num_members += num_this_time;
+
+ attr = talloc_asprintf(mem_ctx,
+ "member;range=%d-*", num_members);
+ }
+
/* 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
*/
- for (i=0;members[i];i++) /* noop */ ;
- num_members = i;
(*sid_mem) = talloc_zero(mem_ctx, sizeof(**sid_mem) * num_members);
(*name_types) = talloc_zero(mem_ctx, sizeof(**name_types) * num_members);
@@ -762,6 +786,9 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
status = NT_STATUS_OK;
DEBUG(3,("ads lookup_groupmem for sid=%s\n", sid_to_string(sid_string, group_sid)));
done:
+ SAFE_FREE(ldap_exp);
+ SAFE_FREE(sidstr);
+
if (res)
ads_msgfree(ads, res);