From 92b2eb9c3f20bc95a66b95a1244c008bb40cb7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= Date: Wed, 8 Mar 2023 08:40:58 +0100 Subject: [PATCH] s3:winbind: Add lookup_aliasmem to winbindd_methods and implement it in all backends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pavel Filipenský Reviewed-by: Andreas Schneider --- source3/winbindd/winbindd.h | 8 +++ source3/winbindd/winbindd_ads.c | 26 ++++++++ source3/winbindd/winbindd_msrpc.c | 55 +++++++++++++++++ source3/winbindd/winbindd_reconnect.c | 29 +++++++++ source3/winbindd/winbindd_reconnect_ads.c | 28 +++++++++ source3/winbindd/winbindd_rpc.c | 75 +++++++++++++++++++++++ source3/winbindd/winbindd_rpc.h | 9 +++ source3/winbindd/winbindd_samr.c | 69 +++++++++++++++++++++ 8 files changed, 299 insertions(+) diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 8a40208e378..eae2ea9584f 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -279,6 +279,14 @@ struct winbindd_methods { struct dom_sid **sid_mem, char ***names, uint32_t **name_types); + /* find all members of the alias with the specified alias_sid */ + NTSTATUS (*lookup_aliasmem)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *alias_sid, + enum lsa_SidType type, + uint32_t *num_sids, + struct dom_sid **sid_mem); + /* return the lockout policy */ NTSTATUS (*lockout_policy)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 814dd52cdfd..f9f9dc4f823 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1371,6 +1371,31 @@ done: return status; } +static NTSTATUS lookup_aliasmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *sid, + enum lsa_SidType type, + uint32_t *num_sids, + struct dom_sid **sids) +{ + char **names = NULL; + uint32_t *name_types = NULL; + struct dom_sid_buf buf; + + DBG_DEBUG("ads: lookup_aliasmem %s sid=%s\n", + domain->name, + dom_sid_str_buf(sid, &buf)); + /* Search for alias and group membership uses the same LDAP command. */ + return lookup_groupmem(domain, + mem_ctx, + sid, + type, + num_sids, + sids, + &names, + &name_types); +} + /* find the lockout policy of a domain - use rpc methods */ static NTSTATUS lockout_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -1568,6 +1593,7 @@ struct winbindd_methods ads_methods = { lookup_usergroups, lookup_useraliases, lookup_groupmem, + lookup_aliasmem, lockout_policy, password_policy, trusted_domains, diff --git a/source3/winbindd/winbindd_msrpc.c b/source3/winbindd/winbindd_msrpc.c index 6a6caa7a498..3233846ca3f 100644 --- a/source3/winbindd/winbindd_msrpc.c +++ b/source3/winbindd/winbindd_msrpc.c @@ -544,6 +544,60 @@ done: return status; } +/* lookup alias membership */ +static NTSTATUS msrpc_lookup_aliasmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *alias_sid, + enum lsa_SidType type, + uint32_t *pnum_sids, + struct dom_sid **sid_mem) +{ + struct rpc_pipe_client *samr_pipe = NULL; + struct policy_handle dom_pol; + struct dom_sid *alias_members = NULL; + struct dom_sid_buf buf; + uint32_t num_groups = 0; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + NTSTATUS status; + + D_INFO("Lookup alias members in domain=%s for sid=%s.\n", + domain->name, + dom_sid_str_buf(alias_sid, &buf)); + + *pnum_sids = 0; + + if (!winbindd_can_contact_domain(domain)) { + D_DEBUG("No incoming trust for domain %s\n", domain->name); + status = NT_STATUS_OK; + goto done; + } + + status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpc_lookup_aliasmem(tmp_ctx, + samr_pipe, + &dom_pol, + &domain->sid, + alias_sid, + type, + &num_groups, + &alias_members); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + *pnum_sids = num_groups; + if (sid_mem) { + *sid_mem = talloc_move(mem_ctx, &alias_members); + } + +done: + talloc_free(tmp_ctx); + return status; +} /* Lookup group membership given a rid. */ static NTSTATUS msrpc_lookup_groupmem(struct winbindd_domain *domain, @@ -1069,6 +1123,7 @@ struct winbindd_methods msrpc_methods = { msrpc_lookup_usergroups, msrpc_lookup_useraliases, msrpc_lookup_groupmem, + msrpc_lookup_aliasmem, msrpc_lockout_policy, msrpc_password_policy, msrpc_trusted_domains, diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect.c index 9086c40ba57..c49831b3c13 100644 --- a/source3/winbindd/winbindd_reconnect.c +++ b/source3/winbindd/winbindd_reconnect.c @@ -235,6 +235,34 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, return result; } +/* Lookup alias membership given */ +static NTSTATUS lookup_aliasmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *sid, + enum lsa_SidType type, + uint32_t *num_sids, + struct dom_sid **sids) +{ + NTSTATUS result; + + result = msrpc_methods.lookup_aliasmem(domain, + mem_ctx, + sid, + type, + num_sids, + sids); + + if (reconnect_need_retry(result, domain)) + result = msrpc_methods.lookup_aliasmem(domain, + mem_ctx, + sid, + type, + num_sids, + sids); + + return result; +} + /* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -319,6 +347,7 @@ struct winbindd_methods reconnect_methods = { lookup_usergroups, lookup_useraliases, lookup_groupmem, + lookup_aliasmem, lockout_policy, password_policy, trusted_domains, diff --git a/source3/winbindd/winbindd_reconnect_ads.c b/source3/winbindd/winbindd_reconnect_ads.c index dbea90caded..367f4c68e88 100644 --- a/source3/winbindd/winbindd_reconnect_ads.c +++ b/source3/winbindd/winbindd_reconnect_ads.c @@ -266,6 +266,33 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, return result; } +static NTSTATUS lookup_aliasmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *group_sid, + enum lsa_SidType type, + uint32_t *num_names, + struct dom_sid **sid_mem) +{ + NTSTATUS result = NT_STATUS_OK; + + result = ads_methods.lookup_aliasmem(domain, + mem_ctx, + group_sid, + type, + num_names, + sid_mem); + + if (ldap_reconnect_need_retry(result, domain)) { + result = ads_methods.lookup_aliasmem(domain, + mem_ctx, + group_sid, + type, + num_names, + sid_mem); + } + return result; +} + /* find the lockout policy of a domain */ static NTSTATUS lockout_policy(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -326,6 +353,7 @@ struct winbindd_methods reconnect_ads_methods = { lookup_usergroups, lookup_useraliases, lookup_groupmem, + lookup_aliasmem, lockout_policy, password_policy, trusted_domains, diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index d1c2f05ac53..6a0f2b2e7aa 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -606,6 +606,81 @@ NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/* Lookup alias membership using a rid taken from alias_sid. */ +NTSTATUS rpc_lookup_aliasmem(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 *alias_sid, + enum lsa_SidType type, + uint32_t *pnum_sids, + struct dom_sid **psids) +{ + uint32_t alias_rid; + struct dom_sid *sid_mem = NULL; + struct lsa_SidArray sid_array; + uint32_t i; + NTSTATUS status, result; + struct dcerpc_binding_handle *b = samr_pipe->binding_handle; + + if (!sid_peek_check_rid(domain_sid, alias_sid, &alias_rid)) { + return NT_STATUS_UNSUCCESSFUL; + } + + switch (type) { + case SID_NAME_ALIAS: { + struct policy_handle alias_policy; + + status = dcerpc_samr_OpenAlias(b, + mem_ctx, + samr_policy, + SEC_FLAG_MAXIMUM_ALLOWED, + alias_rid, + &alias_policy, + &result); + if (any_nt_status_not_ok(status, result, &status)) { + return status; + } + + status = dcerpc_samr_GetMembersInAlias(b, + mem_ctx, + &alias_policy, + &sid_array, + &result); + { + NTSTATUS _result; + dcerpc_samr_Close(b, mem_ctx, &alias_policy, &_result); + } + if (any_nt_status_not_ok(status, result, &status)) { + return status; + } + + sid_mem = talloc_zero_array(mem_ctx, + struct dom_sid, + sid_array.num_sids); + if (sid_mem == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* + * We cannot just simply assign '*psids = sid_array.sids;' + * we need to copy every sid since these are incompatible types: + * 'struct dom_sid *' vs 'struct lsa_SidPtr *' + */ + for (i = 0; i < sid_array.num_sids; i++) { + sid_copy(&sid_mem[i], sid_array.sids[i].sid); + } + + *pnum_sids = sid_array.num_sids; + *psids = sid_mem; + + return NT_STATUS_OK; + } + default: + return NT_STATUS_UNSUCCESSFUL; + } +} + /* Get a list of trusted domains */ NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *lsa_pipe, diff --git a/source3/winbindd/winbindd_rpc.h b/source3/winbindd/winbindd_rpc.h index 67d4ac67433..020958f4489 100644 --- a/source3/winbindd/winbindd_rpc.h +++ b/source3/winbindd/winbindd_rpc.h @@ -76,6 +76,15 @@ NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx, char ***pnames, uint32_t **pname_types); +NTSTATUS rpc_lookup_aliasmem(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 *group_sid, + enum lsa_SidType type, + uint32_t *pnum_sids, + struct dom_sid **psids); + /* Get a list of trusted domains */ NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *lsa_pipe, diff --git a/source3/winbindd/winbindd_samr.c b/source3/winbindd/winbindd_samr.c index 92dd1851abd..83bffb13481 100644 --- a/source3/winbindd/winbindd_samr.c +++ b/source3/winbindd/winbindd_samr.c @@ -488,6 +488,73 @@ done: return status; } +/* Lookup alias membership */ +static NTSTATUS sam_lookup_aliasmem(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *group_sid, + enum lsa_SidType type, + uint32_t *pnum_sids, + struct dom_sid **psid_mem) +{ + struct rpc_pipe_client *samr_pipe; + struct policy_handle dom_pol = {0}; + + uint32_t num_sids = 0; + struct dom_sid *sid_mem = NULL; + + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + NTSTATUS status; + bool retry = false; + + DBG_INFO("sam_lookup_aliasmem\n"); + + /* Paranoia check */ + if (type != SID_NAME_ALIAS) { + status = NT_STATUS_NO_SUCH_ALIAS; + goto done; + } + + if (pnum_sids) { + *pnum_sids = 0; + } + +again: + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpc_lookup_aliasmem(tmp_ctx, + samr_pipe, + &dom_pol, + &domain->sid, + group_sid, + type, + &num_sids, + &sid_mem); + + if (!retry && reset_connection_on_error(domain, samr_pipe, status)) { + retry = true; + goto again; + } + + if (pnum_sids) { + *pnum_sids = num_sids; + } + + if (psid_mem) { + *psid_mem = talloc_move(mem_ctx, &sid_mem); + } + +done: + TALLOC_FREE(tmp_ctx); + return status; +} + /********************************************************************* BUILTIN specific functions. *********************************************************************/ @@ -1331,6 +1398,7 @@ struct winbindd_methods builtin_passdb_methods = { .lookup_usergroups = sam_lookup_usergroups, .lookup_useraliases = sam_lookup_useraliases, .lookup_groupmem = sam_lookup_groupmem, + .lookup_aliasmem = sam_lookup_aliasmem, .lockout_policy = sam_lockout_policy, .password_policy = sam_password_policy, .trusted_domains = builtin_trusted_domains @@ -1349,6 +1417,7 @@ struct winbindd_methods sam_passdb_methods = { .lookup_usergroups = sam_lookup_usergroups, .lookup_useraliases = sam_lookup_useraliases, .lookup_groupmem = sam_lookup_groupmem, + .lookup_aliasmem = sam_lookup_aliasmem, .lockout_policy = sam_lockout_policy, .password_policy = sam_password_policy, .trusted_domains = sam_trusted_domains