diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/ads.h | 28 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 53 |
2 files changed, 61 insertions, 20 deletions
diff --git a/source3/include/ads.h b/source3/include/ads.h index d2eeaab4d8..decb823ea9 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -98,6 +98,10 @@ typedef void **ADS_MODLIST; #define ADS_ATTR_SFU_HOMEDIR_OID "1.2.840.113556.1.6.18.1.344" #define ADS_ATTR_SFU_SHELL_OID "1.2.840.113556.1.6.18.1.312" +/* ldap bitwise searches */ +#define ADS_LDAP_MATCHING_RULE_BIT_AND "1.2.840.113556.1.4.803" +#define ADS_LDAP_MATCHING_RULE_BIT_OR "1.2.840.113556.1.4.804" + /* UserFlags for userAccountControl */ #define UF_SCRIPT 0x00000001 #define UF_ACCOUNTDISABLE 0x00000002 @@ -186,9 +190,27 @@ typedef void **ADS_MODLIST; #define ATYPE_LOCAL_GROUP ATYPE_SECURITY_LOCAL_GROUP /* 0x20000000 536870912 */ /* groupType */ -#define GTYPE_SECURITY_BUILTIN_LOCAL_GROUP 0x80000005 /* -2147483643 */ -#define GTYPE_SECURITY_DOMAIN_LOCAL_GROUP 0x80000004 /* -2147483644 */ -#define GTYPE_SECURITY_GLOBAL_GROUP 0x80000002 /* -2147483646 */ +#define GROUP_TYPE_BUILTIN_LOCAL_GROUP 0x00000001 +#define GROUP_TYPE_ACCOUNT_GROUP 0x00000002 +#define GROUP_TYPE_RESOURCE_GROUP 0x00000004 +#define GROUP_TYPE_UNIVERSAL_GROUP 0x00000008 +#define GROUP_TYPE_APP_BASIC_GROUP 0x00000010 +#define GROUP_TYPE_APP_QUERY_GROUP 0x00000020 +#define GROUP_TYPE_SECURITY_ENABLED 0x80000000 + +#define GTYPE_SECURITY_BUILTIN_LOCAL_GROUP ( /* 0x80000005 -2147483643 */ \ + GROUP_TYPE_BUILTIN_LOCAL_GROUP| \ + GROUP_TYPE_RESOURCE_GROUP| \ + GROUP_TYPE_SECURITY_ENABLED \ + ) +#define GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ( /* 0x80000004 -2147483644 */ \ + GROUP_TYPE_RESOURCE_GROUP| \ + GROUP_TYPE_SECURITY_ENABLED \ + ) +#define GTYPE_SECURITY_GLOBAL_GROUP ( /* 0x80000002 -2147483646 */ \ + GROUP_TYPE_ACCOUNT_GROUP| \ + GROUP_TYPE_SECURITY_ENABLED \ + ) #define GTYPE_DISTRIBUTION_GLOBAL_GROUP 0x00000002 /* 2 */ #define GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP 0x00000004 /* 4 */ #define GTYPE_DISTRIBUTION_UNIVERSAL_GROUP 0x00000008 /* 8 */ 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; |