summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/ads.h28
-rw-r--r--source3/nsswitch/winbindd_ads.c53
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;