Winbind changes in 4.6/Change for 4.6.0?
Stefan Metzmacher
metze at samba.org
Mon Mar 6 12:12:15 UTC 2017
Am 06.03.2017 um 09:57 schrieb Andrew Bartlett:
> On Mon, 2017-03-06 at 07:33 +0100, Stefan Metzmacher wrote:
>> Am 03.03.2017 um 19:09 schrieb Andrew Bartlett:
>>> On Fri, 2017-03-03 at 12:12 +0100, Karolin Seeger wrote:
>>>> Hi,
>>>>
>>>> we just had some internal discussions about the winbind changes
>>>> in
>>>> Samba
>>>> 4.6.0. The removal of the token groups fallback will break
>>>> exististing
>>>> setups (e.g. domain members where people access files without
>>>> Samba
>>>> (nfs, ...). There is no workaround!
>>>>
>>>> What about re-adding this feature cleanly and for local domains
>>>> only
>>>> and
>>>> disable it by default?
>>>>
>>>> Please find attached a patchset from Volker.
>>>> "winbind : ask token groups = yes" would restore the old
>>>> behaviour.
>>>> (I would prefer a documented parameter, but that could be
>>>> changed.)
>>>>
>>>> Unfortunately, it's pretty late in the release process, but since
>>>> the
>>>> code is disabled by default, it should not be a big deal...
>>>>
>>>> The planned release date for the final release still is Tuesday,
>>>> March 7.
>>>> Some patches have been added sinc rc4, but it seems to be ok to
>>>> go
>>>> ahead
>>>> with rc5.
>>>>
>>>> Opinions?
>>>
>>> I really appreciated the move to push this up in the WHATSNEW
>>> earlier
>>> in the week, and it certainly gave me the same gut feeling of
>>> 'ouch,
>>> did we really break this with no workaround?'.
>>>
>>> I would put it back without the smb.conf option myself, but I'll
>>> take
>>> anything to avoid dropping sites into unsupported.
>>
>> I'd also think we should restore the whole old behavior, also
>> returning
>> the broken values for trusted domains.
>>
>> I don't really care if we have no option at all, one option to enable
>> the old behavior or even 2 options to enable it for the primary
>> domain
>> and other domains separately. If we add options we should add them as
>> fully
>> documented options (and mark them as deprecated similar to "lsa over
>> netlogon").
>>
>> But I guess restoring this without option would be the simplest way
>> of doing it...
>
> We can always try again for 4.7. The case about NFS is really
> persuasive to me. I think going back to how things were for 4.5 sounds
> the least disruptive, and we think about options to control this in the
> 4.7 release for September.
So what about the following patch.
While testing I found https://bugzilla.samba.org/show_bug.cgi?id=12613,
the autorid module requires a valid stamp in netsamlogon_cache.tdb
in order to allocate a new domain range. But the following will
allow admins to work around the problem, if there're add a new domain
which doesn't already have an autorid range and no user will authenticate
against samba:
### get the existing ranges:
#> net idmap get ranges
RANGE 0: ALLOC
RANGE 1: S-1-5-21-2072033271-969857664-807811056
### use the next free range
#> net idmap set range 2 S-1-5-21-4053568372-2049667917-3384589010
#> net idmap get ranges
RANGE 0: ALLOC
RANGE 2: S-1-5-21-4053568372-2049667917-3384589010
RANGE 1: S-1-5-21-2072033271-969857664-807811056
I also have a patch (attached to the bug report) to improve
the autorid verification check, but that might be able to
wait for the first maintenance release of 4.6.
metze
-------------- next part --------------
From 62cbf261e2fbb08c447df2a23ed76794ebefabdc Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Mar 2017 14:52:49 +0100
Subject: [PATCH 1/9] Revert "winbind: Remove rpc_lookup_usergroups"
This reverts commit 91b73b1e93bb8fb38e2f1cea6c1cbd012c952542.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12612
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
source3/winbindd/winbindd_rpc.c | 74 +++++++++++++++++++++++++++++++++++++++++
source3/winbindd/winbindd_rpc.h | 9 +++++
2 files changed, 83 insertions(+)
diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c
index 261906f..3dd4f77 100644
--- a/source3/winbindd/winbindd_rpc.c
+++ b/source3/winbindd/winbindd_rpc.c
@@ -424,6 +424,80 @@ NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
+/* Lookup groups a user is a member of. */
+NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *samr_pipe,
+ struct policy_handle *samr_policy,
+ const struct dom_sid *domain_sid,
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_groups,
+ struct dom_sid **puser_grpsids)
+{
+ struct policy_handle user_policy;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ struct dom_sid *user_grpsids = NULL;
+ uint32_t num_groups = 0, i;
+ uint32_t user_rid;
+ NTSTATUS status, result;
+ struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
+
+ if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Get user handle */
+ status = dcerpc_samr_OpenUser(b,
+ mem_ctx,
+ samr_policy,
+ SEC_FLAG_MAXIMUM_ALLOWED,
+ user_rid,
+ &user_policy,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ /* Query user rids */
+ status = dcerpc_samr_GetGroupsForUser(b,
+ mem_ctx,
+ &user_policy,
+ &rid_array,
+ &result);
+ {
+ NTSTATUS _result;
+ dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ num_groups = rid_array->count;
+
+ user_grpsids = talloc_array(mem_ctx, struct dom_sid, num_groups);
+ if (user_grpsids == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ return status;
+ }
+
+ for (i = 0; i < num_groups; i++) {
+ sid_compose(&(user_grpsids[i]), domain_sid,
+ rid_array->rids[i].rid);
+ }
+
+ *pnum_groups = num_groups;
+
+ *puser_grpsids = user_grpsids;
+
+ return NT_STATUS_OK;
+}
+
NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
struct rpc_pipe_client *samr_pipe,
struct policy_handle *samr_policy,
diff --git a/source3/winbindd/winbindd_rpc.h b/source3/winbindd/winbindd_rpc.h
index ee4b210..162f1ef 100644
--- a/source3/winbindd/winbindd_rpc.h
+++ b/source3/winbindd/winbindd_rpc.h
@@ -78,6 +78,15 @@ NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
char ***pnames,
enum lsa_SidType **ptypes);
+/* Lookup groups a user is a member of. */
+NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *samr_pipe,
+ struct policy_handle *samr_policy,
+ const struct dom_sid *domain_sid,
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_groups,
+ struct dom_sid **puser_grpsids);
+
NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
struct rpc_pipe_client *samr_pipe,
struct policy_handle *samr_policy,
--
1.9.1
From 15189b24b44f3a383d65a8f6e9c7b491dcedd190 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Mar 2017 14:53:47 +0100
Subject: [PATCH 2/9] Revert "winbind: Remove "lookup_usergroups" winbind
method"
This reverts commit b231814c6b0ad17255139bc8934f269610348b2b.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12612
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
source3/winbindd/winbindd.h | 8 +
source3/winbindd/winbindd_ads.c | 377 ++++++++++++++++++++++++++++++
source3/winbindd/winbindd_msrpc.c | 72 ++++++
source3/winbindd/winbindd_reconnect.c | 21 ++
source3/winbindd/winbindd_reconnect_ads.c | 22 ++
source3/winbindd/winbindd_samr.c | 65 ++++++
6 files changed, 565 insertions(+)
diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index 0f95703..c220573 100644
--- a/source3/winbindd/winbindd.h
+++ b/source3/winbindd/winbindd.h
@@ -262,6 +262,14 @@ struct winbindd_methods {
char ***names,
enum lsa_SidType **types);
+ /* lookup all groups that a user is a member of. The backend
+ can also choose to lookup by username or rid for this
+ function */
+ NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *num_groups, struct dom_sid **user_gids);
+
/* Lookup all aliases that the sids delivered are member of. This is
* to implement 'domain local groups' correctly */
NTSTATUS (*lookup_useraliases)(struct winbindd_domain *domain,
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index cde9099..d2e1ac4 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -574,6 +574,382 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
domain_name, names, types);
}
+/* Lookup groups a user is a member of - alternate method, for when
+ tokenGroups are not available. */
+static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user_dn,
+ struct dom_sid *primary_group,
+ uint32_t *p_num_groups, struct dom_sid **user_sids)
+{
+ ADS_STATUS rc;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ int count;
+ LDAPMessage *res = NULL;
+ LDAPMessage *msg = NULL;
+ char *ldap_exp;
+ ADS_STRUCT *ads;
+ const char *group_attrs[] = {"objectSid", NULL};
+ char *escaped_dn;
+ uint32_t num_groups = 0;
+
+ DEBUG(3,("ads: lookup_usergroups_member\n"));
+
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
+ ads = ads_cached_connection(domain);
+
+ if (!ads) {
+ domain->last_status = NT_STATUS_SERVER_DISABLED;
+ goto done;
+ }
+
+ if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ ldap_exp = talloc_asprintf(mem_ctx,
+ "(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
+ escaped_dn,
+ ADS_LDAP_MATCHING_RULE_BIT_AND,
+ GROUP_TYPE_SECURITY_ENABLED);
+ if (!ldap_exp) {
+ DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
+ TALLOC_FREE(escaped_dn);
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ TALLOC_FREE(escaped_dn);
+
+ rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
+
+ if (!ADS_ERR_OK(rc)) {
+ DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
+ return ads_ntstatus(rc);
+ } else if (!res) {
+ DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+
+ count = ads_count_replies(ads, res);
+
+ *user_sids = NULL;
+ num_groups = 0;
+
+ /* always add the primary group to the sid array */
+ status = add_sid_to_array(mem_ctx, primary_group, user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ if (count > 0) {
+ for (msg = ads_first_entry(ads, res); msg;
+ msg = ads_next_entry(ads, msg)) {
+ struct dom_sid group_sid;
+
+ if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
+ DEBUG(1,("No sid for this group ?!?\n"));
+ continue;
+ }
+
+ /* ignore Builtin groups from ADS - Guenther */
+ if (sid_check_is_in_builtin(&group_sid)) {
+ continue;
+ }
+
+ status = add_sid_to_array(mem_ctx, &group_sid,
+ user_sids, &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+ }
+
+ }
+
+ *p_num_groups = num_groups;
+ status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
+
+ DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
+done:
+ if (res)
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
+/* Lookup groups a user is a member of - alternate method, for when
+ tokenGroups are not available. */
+static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user_dn,
+ struct dom_sid *primary_group,
+ uint32_t *p_num_groups,
+ struct dom_sid **user_sids)
+{
+ ADS_STATUS rc;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ ADS_STRUCT *ads;
+ const char *attrs[] = {"memberOf", NULL};
+ uint32_t num_groups = 0;
+ struct dom_sid *group_sids = NULL;
+ int i;
+ char **strings = NULL;
+ size_t num_strings = 0, num_sids = 0;
+
+
+ DEBUG(3,("ads: lookup_usergroups_memberof\n"));
+
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_usergroups_memberof: No incoming trust for "
+ "domain %s\n", domain->name));
+ return NT_STATUS_OK;
+ }
+
+ ads = ads_cached_connection(domain);
+
+ if (!ads) {
+ domain->last_status = NT_STATUS_SERVER_DISABLED;
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs,
+ ADS_EXTENDED_DN_HEX_STRING,
+ &strings, &num_strings);
+
+ if (!ADS_ERR_OK(rc)) {
+ DEBUG(1,("lookup_usergroups_memberof ads_search "
+ "member=%s: %s\n", user_dn, ads_errstr(rc)));
+ return ads_ntstatus(rc);
+ }
+
+ *user_sids = NULL;
+ num_groups = 0;
+
+ /* always add the primary group to the sid array */
+ status = add_sid_to_array(mem_ctx, primary_group, user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
+ if (!group_sids) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i<num_strings; i++) {
+ rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i],
+ ADS_EXTENDED_DN_HEX_STRING,
+ &(group_sids)[i]);
+ if (!ADS_ERR_OK(rc)) {
+ /* ignore members without SIDs */
+ if (NT_STATUS_EQUAL(ads_ntstatus(rc),
+ NT_STATUS_NOT_FOUND)) {
+ continue;
+ }
+ else {
+ status = ads_ntstatus(rc);
+ goto done;
+ }
+ }
+ num_sids++;
+ }
+
+ if (i == 0) {
+ DEBUG(1,("No memberOf for this user?!?\n"));
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i<num_sids; i++) {
+
+ /* ignore Builtin groups from ADS - Guenther */
+ if (sid_check_is_in_builtin(&group_sids[i])) {
+ continue;
+ }
+
+ status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ }
+
+ *p_num_groups = num_groups;
+ status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
+
+ DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n",
+ user_dn));
+
+done:
+ TALLOC_FREE(strings);
+ TALLOC_FREE(group_sids);
+
+ return status;
+}
+
+
+/* Lookup groups a user is a member of. */
+static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *sid,
+ uint32_t *p_num_groups, struct dom_sid **user_sids)
+{
+ ADS_STRUCT *ads = NULL;
+ const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
+ ADS_STATUS rc;
+ int count;
+ LDAPMessage *msg = NULL;
+ char *user_dn = NULL;
+ struct dom_sid *sids;
+ int i;
+ struct dom_sid primary_group;
+ uint32_t primary_group_rid;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ uint32_t num_groups = 0;
+
+ DEBUG(3,("ads: lookup_usergroups\n"));
+ *p_num_groups = 0;
+
+ status = lookup_usergroups_cached(mem_ctx, sid,
+ p_num_groups, user_sids);
+ if (NT_STATUS_IS_OK(status)) {
+ return NT_STATUS_OK;
+ }
+
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
+ domain->name));
+
+ /* Tell the cache manager not to remember this one */
+
+ return NT_STATUS_SYNCHRONIZATION_REQUIRED;
+ }
+
+ ads = ads_cached_connection(domain);
+
+ if (!ads) {
+ domain->last_status = NT_STATUS_SERVER_DISABLED;
+ status = NT_STATUS_SERVER_DISABLED;
+ goto done;
+ }
+
+ rc = ads_search_retry_sid(ads, &msg, sid, attrs);
+
+ if (!ADS_ERR_OK(rc)) {
+ status = ads_ntstatus(rc);
+ DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
+ "%s\n", sid_string_dbg(sid), ads_errstr(rc)));
+ goto done;
+ }
+
+ count = ads_count_replies(ads, msg);
+ if (count != 1) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
+ "invalid number of results (count=%d)\n",
+ sid_string_dbg(sid), count));
+ goto done;
+ }
+
+ if (!msg) {
+ DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
+ sid_string_dbg(sid)));
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ user_dn = ads_get_dn(ads, mem_ctx, msg);
+ if (user_dn == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
+ DEBUG(1,("%s: No primary group for sid=%s !?\n",
+ domain->name, sid_string_dbg(sid)));
+ goto done;
+ }
+
+ sid_compose(&primary_group, &domain->sid, primary_group_rid);
+
+ count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
+
+ /* there must always be at least one group in the token,
+ unless we are talking to a buggy Win2k server */
+
+ /* actually this only happens when the machine account has no read
+ * permissions on the tokenGroup attribute - gd */
+
+ if (count == 0) {
+
+ /* no tokenGroups */
+
+ /* lookup what groups this user is a member of by DN search on
+ * "memberOf" */
+
+ status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
+ &primary_group,
+ &num_groups, user_sids);
+ *p_num_groups = num_groups;
+ if (NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ /* lookup what groups this user is a member of by DN search on
+ * "member" */
+
+ status = lookup_usergroups_member(domain, mem_ctx, user_dn,
+ &primary_group,
+ &num_groups, user_sids);
+ *p_num_groups = num_groups;
+ goto done;
+ }
+
+ *user_sids = NULL;
+ num_groups = 0;
+
+ status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ for (i=0;i<count;i++) {
+
+ /* ignore Builtin groups from ADS - Guenther */
+ if (sid_check_is_in_builtin(&sids[i])) {
+ continue;
+ }
+
+ status = add_sid_to_array_unique(mem_ctx, &sids[i],
+ user_sids, &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+ }
+
+ *p_num_groups = (uint32_t)num_groups;
+ status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
+
+ DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
+ sid_string_dbg(sid)));
+done:
+ TALLOC_FREE(user_dn);
+ ads_msgfree(ads, msg);
+ return status;
+}
+
/* Lookup aliases a user is member of - use rpc methods */
static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -1157,6 +1533,7 @@ struct winbindd_methods ads_methods = {
name_to_sid,
sid_to_name,
rids_to_names,
+ lookup_usergroups,
lookup_useraliases,
lookup_groupmem,
sequence_number,
diff --git a/source3/winbindd/winbindd_msrpc.c b/source3/winbindd/winbindd_msrpc.c
index 5ace4d1..cd7dfbc 100644
--- a/source3/winbindd/winbindd_msrpc.c
+++ b/source3/winbindd/winbindd_msrpc.c
@@ -393,6 +393,77 @@ static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
return result;
}
+/* Lookup groups a user is a member of. I wish Unix had a call like this! */
+static NTSTATUS msrpc_lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_groups,
+ struct dom_sid **puser_grpsids)
+{
+ struct rpc_pipe_client *samr_pipe;
+ struct policy_handle dom_pol;
+ struct dom_sid *user_grpsids = NULL;
+ uint32_t num_groups = 0;
+ TALLOC_CTX *tmp_ctx;
+ NTSTATUS status;
+
+ DEBUG(3,("msrpc_lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
+
+ *pnum_groups = 0;
+
+ tmp_ctx = talloc_stackframe();
+ if (tmp_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Check if we have a cached user_info_3 */
+ status = lookup_usergroups_cached(tmp_ctx,
+ user_sid,
+ &num_groups,
+ &user_grpsids);
+ if (NT_STATUS_IS_OK(status)) {
+ goto cached;
+ }
+
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
+ domain->name));
+
+ /* Tell the cache manager not to remember this one */
+ status = NT_STATUS_SYNCHRONIZATION_REQUIRED;
+ goto done;
+ }
+
+ /* no cache; hit the wire */
+ status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ status = rpc_lookup_usergroups(tmp_ctx,
+ samr_pipe,
+ &dom_pol,
+ &domain->sid,
+ user_sid,
+ &num_groups,
+ &user_grpsids);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+cached:
+ *pnum_groups = num_groups;
+
+ if (puser_grpsids) {
+ *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
+ }
+
+done:
+ TALLOC_FREE(tmp_ctx);
+ return status;
+ return NT_STATUS_OK;
+}
+
#define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
@@ -1090,6 +1161,7 @@ struct winbindd_methods msrpc_methods = {
msrpc_name_to_sid,
msrpc_sid_to_name,
msrpc_rids_to_names,
+ msrpc_lookup_usergroups,
msrpc_lookup_useraliases,
msrpc_lookup_groupmem,
msrpc_sequence_number,
diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect.c
index d23ffcf..bbb5a37 100644
--- a/source3/winbindd/winbindd_reconnect.c
+++ b/source3/winbindd/winbindd_reconnect.c
@@ -199,6 +199,26 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
return result;
}
+/* Lookup groups a user is a member of. I wish Unix had a call like this! */
+static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *num_groups, struct dom_sid **user_gids)
+{
+ NTSTATUS result;
+
+ result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
+ user_sid, num_groups,
+ user_gids);
+
+ if (reconnect_need_retry(result, domain))
+ result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
+ user_sid, num_groups,
+ user_gids);
+
+ return result;
+}
+
static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32_t num_sids, const struct dom_sid *sids,
@@ -314,6 +334,7 @@ struct winbindd_methods reconnect_methods = {
name_to_sid,
sid_to_name,
rids_to_names,
+ lookup_usergroups,
lookup_useraliases,
lookup_groupmem,
sequence_number,
diff --git a/source3/winbindd/winbindd_reconnect_ads.c b/source3/winbindd/winbindd_reconnect_ads.c
index 17ea9d2..3bb8b5e 100644
--- a/source3/winbindd/winbindd_reconnect_ads.c
+++ b/source3/winbindd/winbindd_reconnect_ads.c
@@ -153,6 +153,27 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
return result;
}
+/* Lookup groups a user is a member of. I wish Unix had a call like this! */
+static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *num_groups,
+ struct dom_sid **user_gids)
+{
+ NTSTATUS result;
+
+ result = ads_methods.lookup_usergroups(domain, mem_ctx, user_sid,
+ num_groups, user_gids);
+
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.lookup_usergroups(domain, mem_ctx,
+ user_sid, num_groups,
+ user_gids);
+ }
+
+ return result;
+}
+
static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32_t num_sids,
@@ -269,6 +290,7 @@ struct winbindd_methods reconnect_ads_methods = {
name_to_sid,
sid_to_name,
rids_to_names,
+ lookup_usergroups,
lookup_useraliases,
lookup_groupmem,
sequence_number,
diff --git a/source3/winbindd/winbindd_samr.c b/source3/winbindd/winbindd_samr.c
index 1a73fc4..aedb77b 100644
--- a/source3/winbindd/winbindd_samr.c
+++ b/source3/winbindd/winbindd_samr.c
@@ -758,6 +758,69 @@ error:
return status;
}
+/* Lookup groups a user is a member of. */
+static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_groups,
+ struct dom_sid **puser_grpsids)
+{
+ struct rpc_pipe_client *samr_pipe;
+ struct policy_handle dom_pol;
+ struct dom_sid *user_grpsids = NULL;
+ uint32_t num_groups = 0;
+ TALLOC_CTX *tmp_ctx;
+ NTSTATUS status, result;
+ struct dcerpc_binding_handle *b = NULL;
+
+ DEBUG(3,("sam_lookup_usergroups\n"));
+
+ ZERO_STRUCT(dom_pol);
+
+ if (pnum_groups) {
+ *pnum_groups = 0;
+ }
+
+ tmp_ctx = talloc_stackframe();
+ if (tmp_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ b = samr_pipe->binding_handle;
+
+ status = rpc_lookup_usergroups(tmp_ctx,
+ samr_pipe,
+ &dom_pol,
+ &domain->sid,
+ user_sid,
+ &num_groups,
+ &user_grpsids);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ if (pnum_groups) {
+ *pnum_groups = num_groups;
+ }
+
+ if (puser_grpsids) {
+ *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
+ }
+
+done:
+ if (b && is_valid_policy_hnd(&dom_pol)) {
+ dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
+ }
+
+ TALLOC_FREE(tmp_ctx);
+ return status;
+}
+
static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32_t num_sids,
@@ -879,6 +942,7 @@ struct winbindd_methods builtin_passdb_methods = {
.name_to_sid = sam_name_to_sid,
.sid_to_name = sam_sid_to_name,
.rids_to_names = sam_rids_to_names,
+ .lookup_usergroups = sam_lookup_usergroups,
.lookup_useraliases = sam_lookup_useraliases,
.lookup_groupmem = sam_lookup_groupmem,
.sequence_number = sam_sequence_number,
@@ -897,6 +961,7 @@ struct winbindd_methods sam_passdb_methods = {
.name_to_sid = sam_name_to_sid,
.sid_to_name = sam_sid_to_name,
.rids_to_names = sam_rids_to_names,
+ .lookup_usergroups = sam_lookup_usergroups,
.lookup_useraliases = sam_lookup_useraliases,
.lookup_groupmem = sam_lookup_groupmem,
.sequence_number = sam_sequence_number,
--
1.9.1
From 246ec690c2074ece7d4a96004d08ff5e1415e292 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Mar 2017 14:54:09 +0100
Subject: [PATCH 3/9] Revert "winbind: Remove validate_ug"
This reverts commit 3f58a8cabab75a594cff9088d5dd8ea439b36178.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12612
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
source3/winbindd/winbindd_cache.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index 4431cb5..a343ad1 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -2917,6 +2917,11 @@ void wcache_invalidate_samlogon(struct winbindd_domain *domain,
DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str));
tdb_delete(cache->tdb, string_tdb_data(key_str));
+ /* Clear UG/SID cache entry */
+ fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, sid));
+ DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str));
+ tdb_delete(cache->tdb, string_tdb_data(key_str));
+
/* Samba/winbindd never needs this. */
netsamlogon_clear_cached_user(sid);
}
@@ -3679,6 +3684,32 @@ static int validate_gl(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
return 0;
}
+static int validate_ug(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
+ struct tdb_validation_status *state)
+{
+ struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
+ int32_t num_groups, i;
+
+ if (!centry) {
+ return 1;
+ }
+
+ num_groups = centry_uint32(centry);
+
+ for (i=0; i< num_groups; i++) {
+ struct dom_sid sid;
+ centry_sid(centry, &sid);
+ }
+
+ centry_free(centry);
+
+ if (!(state->success)) {
+ return 1;
+ }
+ DEBUG(10,("validate_ug: %s ok\n", keystr));
+ return 0;
+}
+
static int validate_ua(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
struct tdb_validation_status *state)
{
@@ -3881,6 +3912,7 @@ struct key_val_struct {
{"CRED/", validate_cred},
{"UL/", validate_ul},
{"GL/", validate_gl},
+ {"UG/", validate_ug},
{"UA", validate_ua},
{"GM/", validate_gm},
{"DR/", validate_dr},
--
1.9.1
From 0d22bdf1b1f3d1cd740fdba00bda8ab10500fb53 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Mar 2017 14:54:23 +0100
Subject: [PATCH 4/9] Revert "winbind: Remove wcache_lookup_usergroups"
This reverts commit 876dc28b9cf13343a2962b1a1b035fe78c1858a6.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12612
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
source3/winbindd/winbindd_cache.c | 59 +++++++++++++++++++++++++++++++++++++++
source3/winbindd/winbindd_proto.h | 5 ++++
2 files changed, 64 insertions(+)
diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index a343ad1..e05e048 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -2320,6 +2320,65 @@ NTSTATUS wcache_query_user_fullname(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
+NTSTATUS wcache_lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_sids,
+ struct dom_sid **psids)
+{
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ uint32_t i, num_sids;
+ struct dom_sid *sids;
+ fstring sid_string;
+
+ if (cache->tdb == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ centry = wcache_fetch(cache, domain, "UG/%s",
+ sid_to_fstring(sid_string, user_sid));
+ if (centry == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ /* If we have an access denied cache entry and a cached info3 in the
+ samlogon cache then do a query. This will force the rpc back end
+ to return the info3 data. */
+
+ if (NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED)
+ && netsamlogon_cache_have(user_sid)) {
+ DEBUG(10, ("lookup_usergroups: cached access denied and have "
+ "cached info3\n"));
+ domain->last_status = NT_STATUS_OK;
+ centry_free(centry);
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ num_sids = centry_uint32(centry);
+ sids = talloc_array(mem_ctx, struct dom_sid, num_sids);
+ if (sids == NULL) {
+ centry_free(centry);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<num_sids; i++) {
+ centry_sid(centry, &sids[i]);
+ }
+
+ status = centry->status;
+
+ DEBUG(10,("lookup_usergroups: [Cached] - cached info for domain %s "
+ "status: %s\n", domain->name, nt_errstr(status)));
+
+ centry_free(centry);
+
+ *pnum_sids = num_sids;
+ *psids = sids;
+ return status;
+}
+
static char *wcache_make_sidlist(TALLOC_CTX *mem_ctx, uint32_t num_sids,
const struct dom_sid *sids)
{
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index d7dec3a..e1ded99 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -169,6 +169,11 @@ NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32_t num_sids, const struct dom_sid *sids,
uint32_t *pnum_aliases, uint32_t **paliases);
+NTSTATUS wcache_lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_sids,
+ struct dom_sid **psids);
void wcache_flush_cache(void);
NTSTATUS wcache_count_cached_creds(struct winbindd_domain *domain, int *count);
--
1.9.1
From 224e2c448991d6df88f88005d64ebffd1e4a9a7e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Mar 2017 14:54:46 +0100
Subject: [PATCH 5/9] Revert "winbind: Remove wb_cache_lookup_usergroups"
This reverts commit f83863b4d1510a9519d15934c960fd1675235812.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12612
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
source3/winbindd/winbindd_cache.c | 71 +++++++++++++++++++++++++++++++++++++++
source3/winbindd/winbindd_proto.h | 5 +++
2 files changed, 76 insertions(+)
diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index e05e048..5787441 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -2379,6 +2379,77 @@ NTSTATUS wcache_lookup_usergroups(struct winbindd_domain *domain,
return status;
}
+/* Lookup groups a user is a member of. */
+NTSTATUS wb_cache_lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *num_groups,
+ struct dom_sid **user_gids)
+{
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ unsigned int i;
+ fstring sid_string;
+ bool old_status;
+
+ old_status = domain->online;
+ status = wcache_lookup_usergroups(domain, mem_ctx, user_sid,
+ num_groups, user_gids);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ return status;
+ }
+
+ (*num_groups) = 0;
+ (*user_gids) = NULL;
+
+ /* Return status value returned by seq number check */
+
+ if (!NT_STATUS_IS_OK(domain->last_status))
+ return domain->last_status;
+
+ DEBUG(10,("lookup_usergroups: [Cached] - doing backend query for info for domain %s\n",
+ domain->name ));
+
+ status = domain->backend->lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
+ if (!domain->internal && old_status) {
+ set_domain_offline(domain);
+ }
+ if (!domain->internal &&
+ !domain->online &&
+ old_status) {
+ NTSTATUS cache_status;
+ cache_status = wcache_lookup_usergroups(domain, mem_ctx, user_sid,
+ num_groups, user_gids);
+ return cache_status;
+ }
+ }
+ if ( NT_STATUS_EQUAL(status, NT_STATUS_SYNCHRONIZATION_REQUIRED) )
+ goto skip_save;
+
+ /* and save it */
+ refresh_sequence_number(domain);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ centry = centry_start(domain, status);
+ if (!centry)
+ goto skip_save;
+
+ centry_put_uint32(centry, *num_groups);
+ for (i=0; i<(*num_groups); i++) {
+ centry_put_sid(centry, &(*user_gids)[i]);
+ }
+
+ centry_end(centry, "UG/%s", sid_to_fstring(sid_string, user_sid));
+ centry_free(centry);
+
+skip_save:
+ return status;
+}
+
static char *wcache_make_sidlist(TALLOC_CTX *mem_ctx, uint32_t num_sids,
const struct dom_sid *sids)
{
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index e1ded99..ca9897a 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -89,6 +89,11 @@ NTSTATUS wb_cache_rids_to_names(struct winbindd_domain *domain,
char **domain_name,
char ***names,
enum lsa_SidType **types);
+NTSTATUS wb_cache_lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_sids,
+ struct dom_sid **psids);
NTSTATUS wb_cache_lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32_t num_sids,
--
1.9.1
From 6cab3bbf2898c400140134677767330535b5e6d4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Mar 2017 14:55:15 +0100
Subject: [PATCH 6/9] Revert "winbind: Remove wbint_LookupUserGroups"
This reverts commit 256632ed3cc724bab0fc22132ca6b52faf680ab2.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12612
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
librpc/idl/winbind.idl | 5 +++++
source3/winbindd/winbindd_dual_srv.c | 17 +++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/librpc/idl/winbind.idl b/librpc/idl/winbind.idl
index 6245e13..05db6b9 100644
--- a/librpc/idl/winbind.idl
+++ b/librpc/idl/winbind.idl
@@ -103,6 +103,11 @@ interface winbind
[out] wbint_RidArray *rids
);
+ NTSTATUS wbint_LookupUserGroups(
+ [in] dom_sid *sid,
+ [out] wbint_SidArray *sids
+ );
+
NTSTATUS wbint_QuerySequenceNumber(
[out] uint32 *sequence
);
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index b0b38a6..7b97f33 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -301,6 +301,23 @@ NTSTATUS _wbint_LookupUserAliases(struct pipes_struct *p,
return status;
}
+NTSTATUS _wbint_LookupUserGroups(struct pipes_struct *p,
+ struct wbint_LookupUserGroups *r)
+{
+ struct winbindd_domain *domain = wb_child_domain();
+ NTSTATUS status;
+
+ if (domain == NULL) {
+ return NT_STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ status = wb_cache_lookup_usergroups(domain, p->mem_ctx, r->in.sid,
+ &r->out.sids->num_sids,
+ &r->out.sids->sids);
+ reset_cm_connection_on_error(domain, status);
+ return status;
+}
+
NTSTATUS _wbint_QuerySequenceNumber(struct pipes_struct *p,
struct wbint_QuerySequenceNumber *r)
{
--
1.9.1
From 4e76ce92441e83491399e8acb4caff39c459d9a3 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Mar 2017 14:56:09 +0100
Subject: [PATCH 7/9] Revert "winbind: Remove wb_lookupusergroups"
This reverts commit c0570e6ae8f8f0057ece48d764580897ff2b6f62.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12612
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
source3/winbindd/wb_lookupusergroups.c | 97 ++++++++++++++++++++++++++++++++++
source3/winbindd/winbindd_proto.h | 6 +++
source3/winbindd/wscript_build | 1 +
3 files changed, 104 insertions(+)
create mode 100644 source3/winbindd/wb_lookupusergroups.c
diff --git a/source3/winbindd/wb_lookupusergroups.c b/source3/winbindd/wb_lookupusergroups.c
new file mode 100644
index 0000000..2d39692
--- /dev/null
+++ b/source3/winbindd/wb_lookupusergroups.c
@@ -0,0 +1,97 @@
+/*
+ Unix SMB/CIFS implementation.
+ async lookupusergroups
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/ndr_winbind_c.h"
+#include "../libcli/security/security.h"
+
+struct wb_lookupusergroups_state {
+ struct tevent_context *ev;
+ struct dom_sid sid;
+ struct wbint_SidArray sids;
+};
+
+static void wb_lookupusergroups_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_domain *domain,
+ const struct dom_sid *sid)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_lookupusergroups_state *state;
+ NTSTATUS status;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct wb_lookupusergroups_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ sid_copy(&state->sid, sid);
+
+ status = lookup_usergroups_cached(state,
+ &state->sid,
+ &state->sids.num_sids,
+ &state->sids.sids);
+ if (NT_STATUS_IS_OK(status)) {
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = dcerpc_wbint_LookupUserGroups_send(
+ state, ev, dom_child_handle(domain), &state->sid, &state->sids);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_lookupusergroups_done, req);
+ return req;
+}
+
+static void wb_lookupusergroups_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_lookupusergroups_state *state = tevent_req_data(
+ req, struct wb_lookupusergroups_state);
+ NTSTATUS status, result;
+
+ status = dcerpc_wbint_LookupUserGroups_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_lookupusergroups_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ int *num_sids, struct dom_sid **sids)
+{
+ struct wb_lookupusergroups_state *state = tevent_req_data(
+ req, struct wb_lookupusergroups_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *num_sids = state->sids.num_sids;
+ *sids = talloc_move(mem_ctx, &state->sids.sids);
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index ca9897a..0faf0c6 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -663,6 +663,12 @@ struct tevent_req *winbindd_getsidaliases_send(TALLOC_CTX *mem_ctx,
struct winbindd_request *request);
NTSTATUS winbindd_getsidaliases_recv(struct tevent_req *req,
struct winbindd_response *response);
+struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_domain *domain,
+ const struct dom_sid *sid);
+NTSTATUS wb_lookupusergroups_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ int *num_sids, struct dom_sid **sids);
struct tevent_req *winbindd_getuserdomgroups_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
diff --git a/source3/winbindd/wscript_build b/source3/winbindd/wscript_build
index a5d0dd6..51264e9 100644
--- a/source3/winbindd/wscript_build
+++ b/source3/winbindd/wscript_build
@@ -206,6 +206,7 @@ bld.SAMBA3_BINARY('winbindd',
wb_xids2sids.c
wb_queryuser.c
wb_lookupuseraliases.c
+ wb_lookupusergroups.c
wb_getpwsid.c
wb_gettoken.c
wb_seqnum.c
--
1.9.1
From 947ec5981c30898c005e2be3d598504a48ff82db Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 6 Mar 2017 10:30:52 +0100
Subject: [PATCH 8/9] winbindd: find the domain based on the sid within
wb_lookupusergroups_send()
That simplifies the potential caller.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
source3/winbindd/wb_lookupusergroups.c | 11 ++++++++++-
source3/winbindd/winbindd_proto.h | 1 -
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/source3/winbindd/wb_lookupusergroups.c b/source3/winbindd/wb_lookupusergroups.c
index 2d39692..7647fbd 100644
--- a/source3/winbindd/wb_lookupusergroups.c
+++ b/source3/winbindd/wb_lookupusergroups.c
@@ -32,11 +32,11 @@ static void wb_lookupusergroups_done(struct tevent_req *subreq);
struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
- struct winbindd_domain *domain,
const struct dom_sid *sid)
{
struct tevent_req *req, *subreq;
struct wb_lookupusergroups_state *state;
+ struct winbindd_domain *domain;
NTSTATUS status;
req = tevent_req_create(mem_ctx, &state,
@@ -55,6 +55,15 @@ struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
+ domain = find_domain_from_sid_noinit(&state->sid);
+ if (domain == NULL) {
+ char buf[DOM_SID_STR_BUFLEN];
+ dom_sid_string_buf(&state->sid, buf, sizeof(buf));
+ DEBUG(1,("could not find domain entry for sid %s\n", buf));
+ tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN);
+ return tevent_req_post(req, ev);
+ }
+
subreq = dcerpc_wbint_LookupUserGroups_send(
state, ev, dom_child_handle(domain), &state->sid, &state->sids);
if (tevent_req_nomem(subreq, req)) {
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 0faf0c6..46fb600 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -665,7 +665,6 @@ NTSTATUS winbindd_getsidaliases_recv(struct tevent_req *req,
struct winbindd_response *response);
struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
- struct winbindd_domain *domain,
const struct dom_sid *sid);
NTSTATUS wb_lookupusergroups_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
int *num_sids, struct dom_sid **sids);
--
1.9.1
From 21bb55ef0982078f0c2187ae6773f7683146ee16 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Mar 2017 15:14:51 +0100
Subject: [PATCH 9/9] Re-enable token groups fallback
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12612
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
source3/winbindd/wb_gettoken.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/source3/winbindd/wb_gettoken.c b/source3/winbindd/wb_gettoken.c
index 07c7fc7..a393b0f 100644
--- a/source3/winbindd/wb_gettoken.c
+++ b/source3/winbindd/wb_gettoken.c
@@ -38,6 +38,7 @@ static NTSTATUS wb_add_rids_to_sids(TALLOC_CTX *mem_ctx,
int num_rids, uint32_t *rids);
static void wb_gettoken_gotuser(struct tevent_req *subreq);
+static void wb_gettoken_gotgroups(struct tevent_req *subreq);
static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq);
static void wb_gettoken_gotbuiltins(struct tevent_req *subreq);
@@ -71,10 +72,7 @@ static void wb_gettoken_gotuser(struct tevent_req *subreq)
subreq, struct tevent_req);
struct wb_gettoken_state *state = tevent_req_data(
req, struct wb_gettoken_state);
- struct winbindd_domain *domain;
struct wbint_userinfo *info;
- uint32_t i, num_groups;
- struct dom_sid *groups;
NTSTATUS status;
status = wb_queryuser_recv(subreq, state, &info);
@@ -92,11 +90,27 @@ static void wb_gettoken_gotuser(struct tevent_req *subreq)
sid_copy(&state->sids[0], &info->user_sid);
sid_copy(&state->sids[1], &info->group_sid);
- status = lookup_usergroups_cached(
- state, &info->user_sid, &num_groups, &groups);
+ subreq = wb_lookupusergroups_send(state, state->ev, &info->user_sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_gettoken_gotgroups, req);
+}
+
+static void wb_gettoken_gotgroups(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_gettoken_state *state = tevent_req_data(
+ req, struct wb_gettoken_state);
+ int i, num_groups;
+ struct dom_sid *groups;
+ struct winbindd_domain *domain;
+ NTSTATUS status;
+
+ status = wb_lookupusergroups_recv(subreq, state, &num_groups, &groups);
+ TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- DBG_DEBUG("lookup_usergroups_cached failed (%s), not doing "
- "supplementary group lookups\n", nt_errstr(status));
tevent_req_done(req);
return;
}
--
1.9.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20170306/746a88fa/signature.sig>
More information about the samba-technical
mailing list