diff options
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index f11f151428..6b170c3330 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -220,19 +220,51 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, { ADS_STRUCT *ads = NULL; const char *attrs[] = {"userPrincipalName", "sAMAccountName", - "name", "objectSid", - "sAMAccountType", NULL}; + "name", "objectSid", NULL}; int i, count; ADS_STATUS rc; void *res = NULL; void *msg = NULL; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - uint32 group_flags; + const char *filter; + BOOL enum_dom_local_groups = False; *num_entries = 0; DEBUG(3,("ads: enum_dom_groups\n")); + /* only grab domain local groups for our domain */ + if ( domain->native_mode && strequal(lp_realm(), domain->alt_name) ) { + enum_dom_local_groups = True; + } + + /* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o + * rollup-fixes: + * + * According to Section 5.1(4) of RFC 2251 if a value of a type is it's + * default value, it MUST be absent. In case of extensible matching the + * "dnattr" boolean defaults to FALSE and so it must be only be present + * when set to TRUE. + * + * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a + * filter using bitwise matching rule then the buggy AD fails to decode + * the extensible match. As a workaround set it to TRUE and thereby add + * the dnAttributes "dn" field to cope with those older AD versions. + * It should not harm and won't put any additional load on the AD since + * none of the dn components have a bitmask-attribute. + * + * Thanks to Ralf Haferkamp for input and testing - Guenther */ + + filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))", + ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED, + ADS_LDAP_MATCHING_RULE_BIT_AND, + enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP); + + if (filter == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + ads = ads_cached_connection(domain); if (!ads) { @@ -240,7 +272,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, goto done; } - rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs); + rc = ads_search_retry(ads, &res, filter, attrs); if (!ADS_ERR_OK(rc) || !res) { DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc))); goto done; @@ -260,21 +292,11 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, i = 0; - group_flags = ATYPE_GLOBAL_GROUP; - - /* only grab domain local groups for our domain */ - if ( domain->native_mode && strequal(lp_realm(), domain->alt_name) ) - group_flags |= ATYPE_LOCAL_GROUP; - for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { char *name, *gecos; DOM_SID sid; uint32 rid; - uint32 account_type; - if (!ads_pull_uint32(ads, msg, "sAMAccountType", &account_type) || !(account_type & group_flags) ) - continue; - name = ads_pull_username(ads, mem_ctx, msg); gecos = ads_pull_string(ads, mem_ctx, msg, "name"); if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { @@ -282,9 +304,6 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, continue; } - if (sid_check_is_in_builtin(&sid)) - continue; - if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) { DEBUG(1,("No rid for %s !?\n", name)); continue; |