The Samba-Bugzilla – Attachment 438 Details for
Bug 1184
[patch] RFC2307bis Naming Contexts and Group Recursion
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
The enhancement patch.
ads_filters_and_recursion (text/plain), 32.55 KB, created by
John Klinger
on 2004-03-12 12:11:43 UTC
(
hide
)
Description:
The enhancement patch.
Filename:
MIME Type:
Creator:
John Klinger
Created:
2004-03-12 12:11:43 UTC
Size:
32.55 KB
patch
obsolete
>--- 3.0.1/include/ads.h Thu Aug 28 21:42:42 2003 >+++ 3.0.1/include/ads.h Mon Feb 2 17:06:16 2004 >@@ -4,6 +4,11 @@ > basically this is a wrapper around ldap > */ > >+/* there are 3 possible types of errors the ads subsystem can produce */ >+enum nss_group_recursion {NSS_NO_GROUP_RECURSION, >+ NSS_CONTEXT_GROUP_RECURSION, >+ NSS_FULL_GROUP_RECURSION}; >+ > typedef struct { > void *ld; /* the active ldap structure */ > struct in_addr ldap_ip; /* the ip of the active connection, if any */ >@@ -35,6 +40,18 @@ > char *bind_path; > char *ldap_server_name; > time_t current_time; >+ /* nss info derived from the servers config and smb.conf */ >+ struct { >+ enum nss_group_recursion group_recursion; >+ int groups_limited; >+ char *group_bind_path; >+ int group_scope; >+ char *group_filter; >+ int passwds_limited; >+ char *passwd_bind_path; >+ int passwd_scope; >+ char *passwd_filter; >+ } nss; > } config; > } ADS_STRUCT; > >--- 3.0.1/libads/ads_ldap.c Tue Jul 1 20:44:25 2003 >+++ 3.0.1/libads/ads_ldap.c Mon Feb 2 21:23:50 2004 >@@ -55,28 +55,33 @@ > rc = ads_search_retry(ads, &res, ldap_exp, attrs); > free(ldap_exp); > if (!ADS_ERR_OK(rc)) { >- DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc))); >+ DEBUG(1,("ads_name_to_sid ads_search: %s\n", ads_errstr(rc))); > goto done; > } > > count = ads_count_replies(ads, res); > if (count != 1) { >- DEBUG(1,("name_to_sid: %s not found\n", name)); >+ DEBUG(1,("ads_name_to_sid: %s not found\n", name)); > goto done; > } > > if (!ads_pull_sid(ads, res, "objectSid", sid)) { >- DEBUG(1,("No sid for %s !?\n", name)); >+ DEBUG(1,("ads_name_to_sid: No sid for %s !?\n", name)); > goto done; > } > > if (!ads_pull_uint32(ads, res, "sAMAccountType", &t)) { >- DEBUG(1,("No sAMAccountType for %s !?\n", name)); >+ DEBUG(1,("ads_name_to_sid: No sAMAccountType for %s !?\n", name)); > goto done; > } > > *type = ads_atype_map(t); > >+ if (! ads_sid_in_context(ads, *type, sid)) { >+ DEBUG(5,("ads_name_to_sid: Name %s found, but outside context.\n", name)); >+ goto done; >+ } >+ > status = NT_STATUS_OK; > > DEBUG(3,("ads name_to_sid mapped %s\n", name)); >@@ -127,6 +132,7 @@ > } > > if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) { >+ DEBUG(1,("ads_sid_to_name: No sAMAccountType for %s !?\n", name)); > goto done; > } > >@@ -139,6 +145,11 @@ > > *type = ads_atype_map(atype); > >+ if (! ads_name_in_context(ads, *type, *name)) { >+ DEBUG(5,("ads_sid_to_name: Name %s found, but outside context.\n", name)); >+ goto done; >+ } >+ > status = NT_STATUS_OK; > > DEBUG(3,("ads sid_to_name mapped %s\n", *name)); >@@ -152,4 +163,113 @@ > return status; > } > >+/* determine if a name of a given type is within the context defined by >+ the configuration file "nss group ..." and "nss passwd ..." options. */ >+BOOL ads_name_in_context(ADS_STRUCT *ads, enum SID_NAME_USE type, char *name) >+{ >+ ADS_STATUS rc; >+ BOOL in_context = True; >+ char *ldap_exp = NULL; >+ char *bind_path = NULL; >+ char *filter = NULL; >+ const char *attrs[] = {"sAMAccountName", NULL}; >+ void *res = NULL; >+ int scope; >+ int check; >+ >+ if (! name) >+ return False; >+ >+ if (type == SID_NAME_USER) { >+ bind_path = ads->config.nss.passwd_bind_path; >+ scope = ads->config.nss.passwd_scope; >+ filter = ads->config.nss.passwd_filter; >+ check = ads->config.nss.passwds_limited; >+ } else { >+ bind_path = ads->config.nss.group_bind_path; >+ scope = ads->config.nss.group_scope; >+ filter = ads->config.nss.group_filter; >+ check = ads->config.nss.groups_limited; >+ } >+ >+ if (check) { >+ if (asprintf(&ldap_exp, "(&(sAMAccountName=%s)%s)", name, filter) == -1) { >+ DEBUG(1,("ads_name_in_context (name=%s): asprintf failed!\n", name)); >+ goto done; >+ } >+ >+ rc = ads_do_search_retry(ads, bind_path, scope, ldap_exp, attrs, &res); >+ if (!ADS_ERR_OK(rc) || !res) { >+ DEBUG(1,("ads_name_in_context (name=%s) ads_search: %s\n", name, ads_errstr(rc))); >+ goto done; >+ } >+ >+ in_context = (ads_count_replies(ads, res) > 0); >+ } >+ >+done: >+ if (res) ads_msgfree(ads, res); >+ >+ SAFE_FREE(ldap_exp); >+ >+ return in_context; >+} >+ >+/* determine if a sid of a given type is within the context defined by >+ the configuration file "nss group ..." and "nss passwd ..." options. */ >+BOOL ads_sid_in_context(ADS_STRUCT *ads, enum SID_NAME_USE type, DOM_SID *sid) >+{ >+ ADS_STATUS rc; >+ BOOL in_context = True; >+ char *sid_string = NULL; >+ char *ldap_exp = NULL; >+ char *sidstr = NULL; >+ char *bind_path = NULL; >+ char *filter = NULL; >+ const char *attrs[] = {"sAMAccountName", NULL}; >+ void *res = NULL; >+ int scope; >+ int check; >+ >+ if (type == SID_NAME_USER) { >+ bind_path = ads->config.nss.passwd_bind_path; >+ scope = ads->config.nss.passwd_scope; >+ filter = ads->config.nss.passwd_filter; >+ check = ads->config.nss.passwds_limited; >+ } else { >+ bind_path = ads->config.nss.group_bind_path; >+ scope = ads->config.nss.group_scope; >+ filter = ads->config.nss.group_filter; >+ check = ads->config.nss.groups_limited; >+ } >+ >+ if (check) { >+ if (!(sidstr = sid_binstring(sid))) { >+ DEBUG(1,("ads_sid_in_context: sid_binstring failed!\n")); >+ goto done; >+ } >+ >+ if (asprintf(&ldap_exp, "(&(objectSid=%s)%s)", sidstr, filter) == -1) { >+ DEBUG(1,("ads_sid_in_context (sidstr=%s): asprintf failed!\n", sid_to_string(sid_string, sid))); >+ goto done; >+ } >+ >+ rc = ads_do_search_retry(ads, bind_path, scope, ldap_exp, attrs, &res); >+ >+ if (!ADS_ERR_OK(rc) || !res) { >+ DEBUG(1,("ads_sid_in_context (sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); >+ goto done; >+ } >+ >+ in_context = (ads_count_replies(ads, res) > 0); >+ } >+ >+done: >+ if (res) ads_msgfree(ads, res); >+ >+ SAFE_FREE(ldap_exp); >+ SAFE_FREE(sidstr); >+ >+ return in_context; >+} > #endif >--- 3.0.1/libads/ads_struct.c Fri Nov 7 17:37:35 2003 >+++ 3.0.1/libads/ads_struct.c Tue Jan 27 20:37:34 2004 >@@ -134,6 +134,11 @@ > SAFE_FREE((*ads)->config.bind_path); > SAFE_FREE((*ads)->config.ldap_server_name); > >+ SAFE_FREE((*ads)->config.nss.group_bind_path); >+ SAFE_FREE((*ads)->config.nss.group_filter); >+ SAFE_FREE((*ads)->config.nss.passwd_bind_path); >+ SAFE_FREE((*ads)->config.nss.passwd_filter); >+ > ZERO_STRUCTP(*ads); > SAFE_FREE(*ads); > } >--- 3.0.1/libads/ldap.c Thu Dec 4 21:38:37 2003 >+++ 3.0.1/libads/ldap.c Fri Jan 30 07:43:26 2004 >@@ -1893,6 +1893,62 @@ > DEBUG(4,("time offset is %d seconds\n", ads->auth.time_offset)); > } > >+ SAFE_FREE(ads->config.nss.group_bind_path); >+ SAFE_FREE(ads->config.nss.group_filter); >+ >+ p = lp_nss_group_bind_path(); >+ if (p[0]) >+ { >+ if (strstr(p, ads->config.bind_path)) >+ ads->config.nss.group_bind_path = strdup(p); >+ else >+ asprintf(&ads->config.nss.group_bind_path, "%s,%s", p, ads->config.bind_path); >+ } >+ else >+ ads->config.nss.group_bind_path = strdup(ads->config.bind_path); >+ >+ ads->config.nss.group_filter = strdup(lp_nss_group_filter()); >+ ads->config.nss.group_scope = lp_nss_group_scope(); >+ ads->config.nss.group_recursion = lp_nss_group_recursion(); >+ >+ ads->config.nss.groups_limited >+ = ads->config.nss.group_scope != LDAP_SCOPE_SUBTREE >+ || ads->config.nss.group_filter[0] >+ || StrCaseCmp(ads->config.nss.group_bind_path, ads->config.bind_path); >+ >+ DEBUG(3,("got ldap group recursion \"%d\", bind path \"%s\", scope %i, and filter \"%s\".\n", >+ ads->config.nss.group_recursion, >+ ads->config.nss.group_bind_path, >+ ads->config.nss.group_scope, >+ ads->config.nss.group_filter)); >+ >+ SAFE_FREE(ads->config.nss.passwd_bind_path); >+ SAFE_FREE(ads->config.nss.passwd_filter); >+ >+ p = lp_nss_passwd_bind_path(); >+ if (p[0]) >+ { >+ if (strstr(p, ads->config.bind_path)) >+ ads->config.nss.passwd_bind_path = strdup(p); >+ else >+ asprintf(&ads->config.nss.passwd_bind_path, "%s,%s", p, ads->config.bind_path); >+ } >+ else >+ ads->config.nss.passwd_bind_path = strdup(ads->config.bind_path); >+ >+ ads->config.nss.passwd_filter = strdup(lp_nss_passwd_filter()); >+ ads->config.nss.passwd_scope = lp_nss_passwd_scope(); >+ >+ ads->config.nss.passwds_limited >+ = ads->config.nss.passwd_scope != LDAP_SCOPE_SUBTREE >+ || ads->config.nss.passwd_filter[0] >+ || StrCaseCmp(ads->config.nss.passwd_bind_path, ads->config.bind_path); >+ >+ DEBUG(3,("got ldap passwd bind path \"%s\", scope %i, and filter \"%s\".\n", >+ ads->config.nss.passwd_bind_path, >+ ads->config.nss.passwd_scope, >+ ads->config.nss.passwd_filter)); >+ > talloc_destroy(ctx); > > return ADS_SUCCESS; >--- 3.0.1/nsswitch/winbindd.h Fri Nov 14 03:40:36 2003 >+++ 3.0.1/nsswitch/winbindd.h Fri Jan 30 08:52:11 2004 >@@ -196,6 +196,10 @@ > > /* setup the list of alternate names for the domain, if any */ > NTSTATUS (*alternate_name)(struct winbindd_domain *domain); >+ >+ /* Determines if the netsamlogon_cache can used for group >+ membership determination. */ >+ BOOL (*use_netsamlogon_cache)(struct winbindd_domain *domain); > }; > > /* Used to glue a policy handle and cli_state together */ >--- 3.0.1/nsswitch/winbindd_ads.c Fri Nov 14 03:40:36 2003 >+++ 3.0.1/nsswitch/winbindd_ads.c Mon Feb 2 21:17:05 2004 >@@ -97,6 +97,7 @@ > "sAMAccountType", NULL}; > int i, count; > ADS_STATUS rc; >+ char *ldap_exp; > void *res = NULL; > void *msg = NULL; > NTSTATUS status = NT_STATUS_UNSUCCESSFUL; >@@ -112,7 +113,13 @@ > goto done; > } > >- rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs); >+ if (asprintf(&ldap_exp, "(&(objectCategory=user)%s)", ads->config.nss.passwd_filter) == -1) { >+ DEBUG(1,("query_user_list: asprintf failed!\n")); >+ return NT_STATUS_NO_MEMORY; >+ } >+ rc = ads_do_search_retry(ads, ads->config.nss.passwd_bind_path, ads->config.nss.passwd_scope, ldap_exp, attrs, &res); >+ SAFE_FREE(ldap_exp); >+ > if (!ADS_ERR_OK(rc) || !res) { > DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); > goto done; >@@ -193,6 +200,7 @@ > struct acct_info **info) > { > ADS_STRUCT *ads = NULL; >+ char *ldap_exp; > const char *attrs[] = {"userPrincipalName", "sAMAccountName", > "name", "objectSid", > "sAMAccountType", NULL}; >@@ -214,7 +222,13 @@ > goto done; > } > >- rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs); >+ if (asprintf(&ldap_exp, "(&(objectCategory=group)%s)", ads->config.nss.group_filter) == -1) { >+ DEBUG(1,("enum_dom_groups: asprintf failed!\n")); >+ return NT_STATUS_NO_MEMORY; >+ } >+ rc = ads_do_search_retry(ads, ads->config.nss.group_bind_path, ads->config.nss.group_scope, ldap_exp, attrs, &res); >+ SAFE_FREE(ldap_exp); >+ > if (!ADS_ERR_OK(rc) || !res) { > DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc))); > goto done; >@@ -411,8 +425,8 @@ > ADS_STATUS rc; > int count; > void *msg = NULL; >- char *ldap_exp; >- char *sidstr; >+ char *ldap_exp = NULL; >+ char *sidstr = NULL; > uint32 group_rid; > NTSTATUS status = NT_STATUS_UNSUCCESSFUL; > DOM_SID *sid2; >@@ -427,11 +441,19 @@ > goto done; > } > >- sidstr = sid_binstring(sid); >- asprintf(&ldap_exp, "(objectSid=%s)", sidstr); >- rc = ads_search_retry(ads, &msg, ldap_exp, attrs); >- free(ldap_exp); >- free(sidstr); >+ if (!(sidstr = sid_binstring(sid))) { >+ DEBUG(1,("query_user: sid_binstring failed!\n")); >+ status = NT_STATUS_NO_MEMORY; >+ goto done; >+ } >+ >+ if (asprintf(&ldap_exp, "(&(objectSid=%s)%s)", sidstr, ads->config.nss.passwd_filter) == -1) { >+ DEBUG(1,("query_user (sidstr=%s): asprintf failed!\n", sidstr)); >+ status = NT_STATUS_NO_MEMORY; >+ goto done; >+ } >+ rc = ads_do_search_retry(ads, ads->config.nss.passwd_bind_path, ads->config.nss.passwd_scope, ldap_exp, attrs, &msg); >+ > if (!ADS_ERR_OK(rc) || !msg) { > DEBUG(1,("query_user(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); > goto done; >@@ -469,63 +491,91 @@ > if (msg) > ads_msgfree(ads, msg); > >+ SAFE_FREE(ldap_exp); >+ SAFE_FREE(sidstr); >+ > return status; > } > >-/* Lookup groups a user is a member of - alternate method, for when >- tokenGroups are not available. */ >-static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, >- TALLOC_CTX *mem_ctx, >- const char *user_dn, >- DOM_SID *primary_group, >- uint32 *num_groups, DOM_SID ***user_gids) >+static NTSTATUS lookup_usergroups_alt_recursion(ADS_STRUCT *ads, >+ TALLOC_CTX *mem_ctx, >+ const char *member_dn, >+ DOM_SID *primary_group, >+ uint32 *num_groups, >+ DOM_SID ***user_gids, >+ int *talloc_cnt, >+ hash_table *group_hash) > { >- ADS_STATUS rc; >- NTSTATUS status = NT_STATUS_UNSUCCESSFUL; >- int count; >+ const char *no_recursion_attrs[] = {"objectSid", NULL}; >+ const char *recursion_attrs[] = {"objectSid", "distinguishedName", NULL}; >+ const char *chk_attrs[] = {"name", NULL}; >+ const char **attrs; >+ ADS_STATUS rc; >+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL; > void *res = NULL; > void *msg = NULL; >+ void *chk = NULL; > char *ldap_exp; >- ADS_STRUCT *ads; >- const char *group_attrs[] = {"objectSid", NULL}; >+ char *ldap_exp_str; >+ char *bind_path; >+ char *dn; >+ int count; >+ int gbp_len; >+ int dn_len; >+ int store_group; >+ int scope; >+ int recurse; >+ >+ DEBUG(3,("ads: lookup_usergroups_alt_recursion\n")); >+ >+ /* Define the initial search attributes based on recursion type */ >+ if (ads->config.nss.group_recursion == NSS_FULL_GROUP_RECURSION) { >+ ldap_exp_str = "(&(member=%s)(objectClass=group))"; >+ bind_path = ads->config.bind_path; >+ scope = LDAP_SCOPE_SUBTREE; >+ gbp_len = strlen(ads->config.nss.group_bind_path); >+ } else { >+ ldap_exp_str = "(&(member=%s)(objectClass=group)%s)"; >+ bind_path = ads->config.nss.group_bind_path; >+ scope = ads->config.nss.group_scope; >+ } >+ if (ads->config.nss.group_recursion == NSS_NO_GROUP_RECURSION) >+ attrs = no_recursion_attrs; >+ else >+ attrs = recursion_attrs; > >- DEBUG(3,("ads: lookup_usergroups_alt\n")); >+ if (asprintf(&ldap_exp, ldap_exp_str, member_dn, ads->config.nss.group_filter) == -1) { >+ DEBUG(1,("lookup_usergroups_recursion(dn=%s) asprintf failed!\n", member_dn)); >+ return NT_STATUS_NO_MEMORY; >+ } > >- ads = ads_cached_connection(domain); >+ rc = ads_do_search_retry(ads, bind_path, scope, ldap_exp, attrs, &res); > >- if (!ads) { >- domain->last_status = NT_STATUS_SERVER_DISABLED; >- goto done; >- } >+ SAFE_FREE(ldap_exp); > >- /* buggy server, no tokenGroups. Instead lookup what groups this user >- is a member of by DN search on member*/ >- if (asprintf(&ldap_exp, "(&(member=%s)(objectClass=group))", user_dn) == -1) { >- DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn)); >- return NT_STATUS_NO_MEMORY; >- } >- >- rc = ads_search_retry(ads, &res, ldap_exp, group_attrs); >- free(ldap_exp); >- > if (!ADS_ERR_OK(rc) || !res) { >- DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc))); >+ DEBUG(1,("lookup_usergroups_recursion ads_search member=%s: %s\n", member_dn, ads_errstr(rc))); > return ads_ntstatus(rc); > } > > count = ads_count_replies(ads, res); > if (count == 0) { >- DEBUG(5,("lookup_usergroups: No supp groups found\n")); >- > status = ads_ntstatus(rc); > goto done; > } > >- (*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (count + 1)); >- (*user_gids)[0] = primary_group; >+ if (*talloc_cnt == 0) { >+ (*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (1 + count)); >+ (*user_gids)[0] = primary_group; > >- *num_groups = 1; >+ *num_groups = 1; >+ *talloc_cnt = 1; >+ } else { >+ (*user_gids) = talloc_realloc(mem_ctx, (*user_gids), sizeof(**user_gids) * (count + *talloc_cnt)); >+ } > >+ *talloc_cnt += count; >+ > for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { > DOM_SID group_sid; > >@@ -536,21 +586,79 @@ > > if (sid_equal(&group_sid, primary_group)) continue; > >- (*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids)); >- if (!(*user_gids)[*num_groups]) { >- status = NT_STATUS_NO_MEMORY; >- goto done; >+ store_group = 1; >+ recurse = 0; >+ >+ if (ads->config.nss.group_recursion != NSS_NO_GROUP_RECURSION) { >+ dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName"); >+ if (dn == 0 || hash_lookup(group_hash, dn)) >+ store_group = 0; >+ else { >+ hash_insert(group_hash, strdup(dn), dn); >+ recurse = 1; >+ >+ if (ads->config.nss.group_recursion == NSS_FULL_GROUP_RECURSION) { >+ /* >+ * Since this group is potentially outside the >+ * specified "nss group" context, we must ensure >+ * it should be added before doing so. >+ */ >+ >+ /* Save an ADs lookup, if we can */ >+ dn_len = strlen(dn); >+ store_group = (dn_len >= gbp_len) && (StrCaseCmp(dn+(dn_len-gbp_len), ads->config.nss.group_bind_path) == 0); >+ >+ /* If still possibly in the group context, now check with AD */ >+ if (store_group) { >+ if (asprintf(&ldap_exp, "(&(distinguishedName=%s)%s)", dn, ads->config.nss.group_filter) == -1) { >+ DEBUG(1,("lookup_usergroups_recursion(dn=%s) asprintf failed!\n", member_dn)); >+ return NT_STATUS_NO_MEMORY; >+ } >+ rc = ads_do_search_retry(ads, ads->config.nss.group_bind_path, ads->config.nss.group_scope, ldap_exp, chk_attrs, &chk); >+ SAFE_FREE(ldap_exp); >+ >+ if (!ADS_ERR_OK(rc) || !res) { >+ DEBUG(1,("lookup_usergroups_recursion context check dn=%s\n", dn)); >+ store_group = 0; >+ } >+ else >+ store_group = ads_count_replies(ads, chk); >+ >+ if (chk) >+ ads_msgfree(ads, chk); >+ } >+ } >+ } > } > >- sid_copy((*user_gids)[*num_groups], &group_sid); >+ /* The hash lookup prevents going down circular references */ >+ if (store_group) { >+ (*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids)); >+ if (!(*user_gids)[*num_groups]) { >+ status = NT_STATUS_NO_MEMORY; >+ goto done; >+ } > >- (*num_groups)++; >- >+ sid_copy((*user_gids)[*num_groups], &group_sid); >+ >+ (*num_groups)++; >+ } >+ >+ if (recurse) { >+ status = lookup_usergroups_alt_recursion(ads, >+ mem_ctx, >+ dn, >+ primary_group, >+ num_groups, >+ user_gids, >+ talloc_cnt, >+ group_hash); >+ } > } > > status = NT_STATUS_OK; > >- DEBUG(3,("ads lookup_usergroups (alt) for dn=%s\n", user_dn)); >+ DEBUG(3,("ads lookup_usergroups (alt_context_recursion) for dn=%s\n", member_dn)); > done: > if (res) > ads_msgfree(ads, res); >@@ -560,6 +668,45 @@ > return status; > } > >+/* Lookup groups a user is a member of - alternate method, for when >+ tokenGroups are not available. */ >+static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, >+ TALLOC_CTX *mem_ctx, >+ const char *user_dn, >+ DOM_SID *primary_group, >+ uint32 *num_groups, DOM_SID ***user_gids) >+{ >+ ADS_STRUCT *ads; >+ hash_table group_hash; >+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL; >+ int talloc_cnt = 0; >+ >+ DEBUG(3,("ads: lookup_usergroups_alt\n")); >+ >+ ads = ads_cached_connection(domain); >+ >+ if (ads) { >+ hash_table_init (&group_hash, 512, (compare_function)(strcmp)); >+ >+ status = lookup_usergroups_alt_recursion(ads, >+ mem_ctx, >+ user_dn, >+ primary_group, >+ num_groups, >+ user_gids, >+ &talloc_cnt, >+ &group_hash); >+ >+ if (NT_STATUS_EQUAL(status, NT_STATUS_OK) && *num_groups == 0) >+ DEBUG(5,("lookup_usergroups_alt: No supp groups found\n")); >+ >+ hash_clear(&group_hash); >+ } else >+ domain->last_status = NT_STATUS_SERVER_DISABLED; >+ >+ return status; >+} >+ > /* Lookup groups a user is a member of. */ > static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, > TALLOC_CTX *mem_ctx, >@@ -569,13 +716,18 @@ > ADS_STRUCT *ads = NULL; > const char *attrs[] = {"distinguishedName", NULL}; > const char *attrs2[] = {"tokenGroups", "primaryGroupID", NULL}; >+ const char *attrs3[] = {"name", NULL}; >+ const char *attrs4[] = {"primaryGroupID", NULL}; > ADS_STATUS rc; >- int count; >+ int count = 0; >+ void *res = NULL; > void *msg = NULL; > char *ldap_exp; > char *user_dn; > DOM_SID *sids; > int i; >+ int group_found; >+ int use_tokenGroups; > DOM_SID *primary_group; > uint32 primary_group_rid; > char *sidstr; >@@ -624,7 +776,22 @@ > if (msg) > ads_msgfree(ads, msg); > >- rc = ads_search_retry_dn(ads, &msg, user_dn, attrs2); >+ /* >+ * tokenGroups are requested from the ADs if full recursion is >+ * specified in the configuration file, or if limited recursion is >+ * requested, but no group limitations exist (which is the same >+ * as full recursion). Otherwise, tokenGroups are not requested, >+ * significantly lowering the overhead in the LDAP call. >+ */ >+ use_tokenGroups = (ads->config.nss.group_recursion == NSS_FULL_GROUP_RECURSION >+ || (! ads->config.nss.groups_limited >+ && ads->config.nss.group_recursion == NSS_CONTEXT_GROUP_RECURSION)); >+ >+ if (use_tokenGroups) >+ rc = ads_search_retry_dn(ads, &msg, user_dn, attrs2); >+ else >+ rc = ads_search_retry_dn(ads, &msg, user_dn, attrs4); >+ > if (!ADS_ERR_OK(rc) || !msg) { > DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); > goto done; >@@ -637,14 +804,19 @@ > > primary_group = rid_to_talloced_sid(domain, mem_ctx, primary_group_rid); > >- count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids); >+ if (use_tokenGroups) >+ count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids); > > if (msg) > ads_msgfree(ads, msg); > >- /* there must always be at least one group in the token, >- unless we are talking to a buggy Win2k server */ >- if (count == 0) { >+ /* >+ * If there are no tokenGroups in the AD for this user, or we can't >+ * use the tokenGroups due to the group recursion method or context, >+ * we call lookup_usergroups_alt to manually find the user's groups. >+ */ >+ if (!use_tokenGroups || count == 0) >+ { > return lookup_usergroups_alt(domain, mem_ctx, user_dn, > primary_group, > num_groups, user_gids); >@@ -658,6 +830,41 @@ > for (i=0;i<count;i++) { > if (sid_equal(&sids[i], primary_group)) continue; > >+ /* >+ * If the group bind_path, scope, or filter was explicitly >+ * specified in the configuration file, we only return >+ * tokenGroups that are within these parameters. >+ */ >+ if (ads->config.nss.groups_limited) { >+ DEBUG(5,("lookup_usergroups (sid=%s): Limited Groups - checking inclusion rules.\n", sid_to_string(sid_string, &sids[i]))); >+ if (!(sidstr = sid_binstring(&sids[i]))) { >+ DEBUG(1,("lookup_usergroups(sid=%s) sid_binstring returned NULL\n", sid_to_string(sid_string, &sids[i]))); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ if (asprintf(&ldap_exp, "(&(objectSid=%s)%s)", sidstr, ads->config.nss.group_filter) == -1) { >+ DEBUG(1,("lookup_usergroups (sid=%s [%s]): asprintf failed!\n", sidstr, sid_to_string(sid_string, &sids[i]))); >+ return NT_STATUS_NO_MEMORY; >+ } >+ rc = ads_do_search_retry(ads, ads->config.nss.group_bind_path, ads->config.nss.group_scope, ldap_exp, attrs3, &res); >+ SAFE_FREE(ldap_exp); >+ >+ if (!ADS_ERR_OK(rc) || !res) { >+ DEBUG(1,("lookup_usergroups ads_search: %s\n", ads_errstr(rc))); >+ continue; >+ } >+ >+ group_found = ads_count_replies(ads, res); >+ >+ if (res) >+ ads_msgfree(ads, res); >+ >+ if (group_found == 0) { >+ DEBUG(7,("lookup_usergroups (sid=%s): Group Excluded.\n", sid_to_string(sid_string, &sids[i]))); >+ continue; >+ } >+ } >+ > (*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids)); > if (!(*user_gids)[*num_groups]) { > status = NT_STATUS_NO_MEMORY; >@@ -709,10 +916,13 @@ > sidstr = sid_binstring(group_sid); > > /* 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 (asprintf(&ldap_exp, "(&(objectSid=%s)%s)", sidstr, ads->config.nss.group_filter) == -1) { >+ DEBUG(1,("lookup_groupmem (sidstr=%s): asprintf failed!\n", sidstr)); >+ return NT_STATUS_NO_MEMORY; >+ } >+ rc = ads_do_search_retry(ads, ads->config.nss.group_bind_path, ads->config.nss.group_scope, ldap_exp, attrs, &res); >+ SAFE_FREE(ldap_exp); >+ SAFE_FREE(sidstr); > > if (!ADS_ERR_OK(rc) || !res) { > DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); >@@ -963,6 +1173,20 @@ > return ads_ntstatus(rc); > } > >+/* The netsamlogon_cache can only be used if group limitations do >+ not exist and group recursion is not turned off. */ >+static BOOL use_netsamlogon_cache(struct winbindd_domain *domain) >+{ >+ ADS_STRUCT *ads = ads_cached_connection(domain); >+ >+ if (!ads) >+ domain->last_status = NT_STATUS_SERVER_DISABLED; >+ >+ return (!ads >+ || (!ads->config.nss.groups_limited >+ && ads->config.nss.group_recursion != NSS_NO_GROUP_RECURSION)); >+} >+ > /* the ADS backend methods are exposed via this structure */ > struct winbindd_methods ads_methods = { > True, >@@ -977,7 +1201,8 @@ > sequence_number, > trusted_domains, > domain_sid, >- alternate_name >+ alternate_name, >+ use_netsamlogon_cache > }; > > #endif >--- 3.0.1/nsswitch/winbindd_cache.c Fri Nov 14 03:40:36 2003 >+++ 3.0.1/nsswitch/winbindd_cache.c Fri Jan 30 08:55:29 2004 >@@ -1349,6 +1349,12 @@ > } > } > >+/* The netsamlogon_cache can always be queried for user groups */ >+static BOOL use_netsamlogon_cache(struct winbindd_domain *domain) >+{ >+ return True; >+} >+ > /* the ADS backend methods are exposed via this structure */ > struct winbindd_methods cache_methods = { > True, >@@ -1363,5 +1369,6 @@ > sequence_number, > trusted_domains, > domain_sid, >- alternate_name >+ alternate_name, >+ use_netsamlogon_cache > }; >--- 3.0.1/nsswitch/winbindd_group.c Thu Dec 4 21:38:37 2003 >+++ 3.0.1/nsswitch/winbindd_group.c Mon Feb 2 17:16:23 2004 >@@ -25,6 +25,8 @@ > #include "includes.h" > #include "winbindd.h" > >+extern BOOL opt_nocache; >+ > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_WINBIND > >@@ -967,10 +969,14 @@ > goto done; > } > >- /* Treat the info3 cache as authoritative as the >- lookup_usergroups() function may return cached data. */ >- >- if ((info3 = netsamlogon_cache_get(mem_ctx, &user_sid))) { >+ /* >+ * Treat the info3 cache as authoritative as the >+ * lookup_usergroups() function may return cached data, >+ * unless the domain's backend does not want to use the cache. >+ */ >+ if (! opt_nocache >+ && domain->backend->use_netsamlogon_cache(domain) >+ && (info3 = netsamlogon_cache_get(mem_ctx, &user_sid))) { > > DEBUG(10, ("winbindd_getgroups: info3 has %d groups, %d other sids\n", > info3->num_groups2, info3->num_other_sids)); >--- 3.0.1/nsswitch/winbindd_rpc.c Thu Dec 4 21:38:37 2003 >+++ 3.0.1/nsswitch/winbindd_rpc.c Fri Jan 30 08:56:00 2004 >@@ -972,6 +972,12 @@ > return NT_STATUS_OK; > } > >+/* The netsamlogon_cache can always be queried for user groups */ >+static BOOL use_netsamlogon_cache(struct winbindd_domain *domain) >+{ >+ return True; >+} >+ > > /* the rpc backend methods are exposed via this structure */ > struct winbindd_methods msrpc_methods = { >@@ -987,5 +993,6 @@ > sequence_number, > trusted_domains, > domain_sid, >- alternate_name >+ alternate_name, >+ use_netsamlogon_cache > }; >--- 3.0.1/param/loadparm.c Thu Dec 4 21:38:38 2003 >+++ 3.0.1/param/loadparm.c Fri Jan 30 23:18:39 2004 >@@ -177,6 +177,13 @@ > BOOL bWinbindTrustedDomainsOnly; > char *szWinbindBackend; > char *szIdmapBackend; >+ int NssGroupRecursion; >+ char *szNssGroupBindPath; >+ int NssGroupScope; >+ char *szNssGroupFilter; >+ char *szNssPasswdBindPath; >+ int NssPasswdScope; >+ char *szNssPasswdFilter; > char *szAddShareCommand; > char *szChangeShareCommand; > char *szDeleteShareCommand; >@@ -564,6 +571,9 @@ > static BOOL handle_netbios_aliases( const char *pszParmValue, char **ptr ); > static BOOL handle_netbios_scope( const char *pszParmValue, char **ptr ); > static BOOL handle_charset( const char *pszParmValue, char **ptr ); >+static BOOL handle_nss_group_scope( const char *pszParmValue, char **ptr ); >+static BOOL handle_nss_group_recursion( const char *pszParmValue, char **ptr ); >+static BOOL handle_nss_passwd_scope( const char *pszParmValue, char **ptr ); > > static BOOL handle_acl_compatibility(const char *pszParmValue, char **ptr); > >@@ -1152,6 +1162,13 @@ > > {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED}, > {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED}, >+ {"nss group recursion", P_INTEGER, P_GLOBAL, &Globals.NssGroupRecursion, handle_nss_group_recursion, NULL, FLAG_ADVANCED}, >+ {"nss group bind path", P_STRING, P_GLOBAL, &Globals.szNssGroupBindPath, NULL, NULL, FLAG_ADVANCED}, >+ {"nss group scope", P_INTEGER, P_GLOBAL, &Globals.NssGroupScope, handle_nss_group_scope, NULL, FLAG_ADVANCED}, >+ {"nss group filter", P_STRING, P_GLOBAL, &Globals.szNssGroupFilter, NULL, NULL, FLAG_ADVANCED}, >+ {"nss passwd bind path", P_STRING, P_GLOBAL, &Globals.szNssPasswdBindPath, NULL, NULL, FLAG_ADVANCED}, >+ {"nss passwd scope", P_INTEGER, P_GLOBAL, &Globals.NssPasswdScope, handle_nss_passwd_scope, NULL, FLAG_ADVANCED}, >+ {"nss passwd filter", P_STRING, P_GLOBAL, &Globals.szNssPasswdFilter, NULL, NULL, FLAG_ADVANCED}, > {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED}, > {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE}, > {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED}, >@@ -1470,6 +1487,14 @@ > Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF; > Globals.ldap_delete_dn = False; > >+ string_set(&Globals.szNssGroupBindPath, ""); >+ string_set(&Globals.szNssGroupFilter, ""); >+ Globals.NssGroupScope = LDAP_SCOPE_SUBTREE; >+ Globals.NssGroupRecursion = NSS_FULL_GROUP_RECURSION; >+ string_set(&Globals.szNssPasswdBindPath, ""); >+ Globals.NssPasswdScope = LDAP_SCOPE_SUBTREE; >+ string_set(&Globals.szNssPasswdFilter, ""); >+ > /* these parameters are set to defaults that are more appropriate > for the increasing samba install base: > >@@ -1688,6 +1713,14 @@ > FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIdmapBackend) > FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm) > >+FN_GLOBAL_STRING(lp_nss_group_bind_path, &Globals.szNssGroupBindPath) >+FN_GLOBAL_STRING(lp_nss_group_filter, &Globals.szNssGroupFilter) >+FN_GLOBAL_INTEGER(lp_nss_group_scope, &Globals.NssGroupScope) >+FN_GLOBAL_INTEGER(lp_nss_group_recursion, &Globals.NssGroupRecursion) >+FN_GLOBAL_STRING(lp_nss_passwd_bind_path, &Globals.szNssPasswdBindPath) >+FN_GLOBAL_STRING(lp_nss_passwd_filter, &Globals.szNssPasswdFilter) >+FN_GLOBAL_INTEGER(lp_nss_passwd_scope, &Globals.NssPasswdScope) >+ > #ifdef WITH_LDAP_SAMCONFIG > FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer) > FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port) >@@ -3042,6 +3075,76 @@ > return append_ldap_suffix(Globals.szLdapIdmapSuffix); > > return lp_string(Globals.szLdapSuffix); >+} >+ >+/*************************************************************************** >+ * Convert the group recursion string to the appropriate enum value. >+ * Unknown or empty values default to full group recursion. >+ **************************************************************************/ >+static BOOL handle_nss_group_recursion (const char *pszParmValue, char **ptr) >+{ >+ if (strequal(pszParmValue, "context")) >+ Globals.NssGroupRecursion = NSS_CONTEXT_GROUP_RECURSION; >+ else if (strequal(pszParmValue, "none")) >+ Globals.NssGroupRecursion = NSS_NO_GROUP_RECURSION; >+ else >+ Globals.NssGroupRecursion = NSS_FULL_GROUP_RECURSION; >+ >+ return True; >+} >+ >+/*************************************************************************** >+ * Convert the group scope string to the appropriate LDAP value. An >+ * empty string defaults to LDAP_SCOPE_SUBTREE. Tests "sub" first, since >+ * it is the most likely to occur. >+ **************************************************************************/ >+static BOOL handle_nss_group_scope(const char *pszParmValue, char **ptr) >+{ >+ if (!pszParmValue[0] || strequal(pszParmValue, "sub")) >+ Globals.NssGroupScope = LDAP_SCOPE_SUBTREE; >+ else if (strequal(pszParmValue, "base")) >+ Globals.NssGroupScope = LDAP_SCOPE_BASE; >+ else if (strequal(pszParmValue, "one")) >+ Globals.NssGroupScope = LDAP_SCOPE_ONELEVEL; >+ else >+#ifdef LDAP_SCOPE_UNKNOWN >+ Globals.NssGroupScope = LDAP_SCOPE_UNKNOWN; >+#else >+ #ifdef LDAP_SCOPE_DEFAULT >+ Globals.NssGroupScope = LDAP_SCOPE_DEFAULT; >+ #else >+ Globals.NssGroupScope = LDAP_SCOPE_BASE; >+ #endif >+#endif >+ >+ return True; >+} >+ >+/*************************************************************************** >+ * Convert the passwd scope string to the appropriate LDAP value. An >+ * empty string defaults to LDAP_SCOPE_SUBTREE. Tests "sub" first, since >+ * it is the most likely to occur. >+ **************************************************************************/ >+static BOOL handle_nss_passwd_scope(const char *pszParmValue, char **ptr) >+{ >+ if (!pszParmValue[0] || strequal(pszParmValue, "sub")) >+ Globals.NssPasswdScope = LDAP_SCOPE_SUBTREE; >+ else if (strequal(pszParmValue, "base")) >+ Globals.NssPasswdScope = LDAP_SCOPE_BASE; >+ else if (strequal(pszParmValue, "one")) >+ Globals.NssPasswdScope = LDAP_SCOPE_ONELEVEL; >+ else >+#ifdef LDAP_SCOPE_UNKNOWN >+ Globals.NssPasswdScope = LDAP_SCOPE_UNKNOWN; >+#else >+ #ifdef LDAP_SCOPE_DEFAULT >+ Globals.NssPasswdScope = LDAP_SCOPE_DEFAULT; >+ #else >+ Globals.NssPasswdScope = LDAP_SCOPE_BASE; >+ #endif >+#endif >+ >+ return True; > } > > /***************************************************************************
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 1184
: 438