summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/winbindd_ads.c53
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;