From d418d0ca33afb41a793a2fff19ca68871aa5e9ef Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 21 Mar 2018 20:43:10 +1300 Subject: [PATCH] winbindd: Add a cache of the samr and lsa handles for the passdb domain This domain is very close, in AD DC configurations over a internal ncacn_np pipe and otherwise in the same process via C linking. It is however very expensive to re-create the binding handle per SID->name lookup, so keep a cache. Signed-off-by: Andrew Bartlett Reviewed-by: Ralph Boehme --- source3/winbindd/winbindd_samr.c | 267 ++++++++++++++++++------------- 1 file changed, 159 insertions(+), 108 deletions(-) diff --git a/source3/winbindd/winbindd_samr.c b/source3/winbindd/winbindd_samr.c index aedb77bdee9b..da54d6979090 100644 --- a/source3/winbindd/winbindd_samr.c +++ b/source3/winbindd/winbindd_samr.c @@ -40,6 +40,20 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +/* + * The other end of this won't go away easily, so we can trust it + * + * It is either a long-lived process with the same lifetime as + * winbindd or a part of this process + */ +struct winbind_internal_pipes { + struct rpc_pipe_client *samr_pipe; + struct policy_handle samr_domain_hnd; + struct rpc_pipe_client *lsa_pipe; + struct policy_handle lsa_hnd; +}; + + NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, struct rpc_pipe_client **samr_pipe, @@ -101,6 +115,70 @@ NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx, return status; } + +static NTSTATUS open_cached_internal_pipe_conn( + struct winbindd_domain *domain, + struct rpc_pipe_client **samr_pipe, + struct policy_handle *samr_domain_hnd, + struct rpc_pipe_client **lsa_pipe, + struct policy_handle *lsa_hnd) +{ + struct winbind_internal_pipes *internal_pipes = NULL; + + if (domain->private_data == NULL) { + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + + internal_pipes = talloc_zero(frame, + struct winbind_internal_pipes); + + status = open_internal_samr_conn( + internal_pipes, + domain, + &internal_pipes->samr_pipe, + &internal_pipes->samr_domain_hnd); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + status = open_internal_lsa_conn(internal_pipes, + &internal_pipes->lsa_pipe, + &internal_pipes->lsa_hnd); + + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + domain->private_data = talloc_move(domain, &internal_pipes); + + TALLOC_FREE(frame); + + } + + internal_pipes = talloc_get_type_abort( + domain->private_data, struct winbind_internal_pipes); + + if (samr_domain_hnd) { + *samr_domain_hnd = internal_pipes->samr_domain_hnd; + } + + if (samr_pipe) { + *samr_pipe = internal_pipes->samr_pipe; + } + + if (lsa_hnd) { + *lsa_hnd = internal_pipes->lsa_hnd; + } + + if (lsa_pipe) { + *lsa_pipe = internal_pipes->lsa_pipe; + } + + return NT_STATUS_OK; +} + /********************************************************************* SAM specific functions. *********************************************************************/ @@ -116,8 +194,7 @@ static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain, struct wb_acct_info *info = NULL; uint32_t num_info = 0; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("sam_enum_dom_groups\n")); @@ -130,20 +207,24 @@ static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); if (!NT_STATUS_IS_OK(status)) { - goto error; + TALLOC_FREE(tmp_ctx); + return status; } - b = samr_pipe->binding_handle; - status = rpc_enum_dom_groups(tmp_ctx, samr_pipe, &dom_pol, &num_info, &info); if (!NT_STATUS_IS_OK(status)) { - goto error; + TALLOC_FREE(tmp_ctx); + return status; } if (pnum_info) { @@ -154,10 +235,6 @@ static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain, *pinfo = talloc_move(mem_ctx, &info); } -error: - if (b && is_valid_policy_hnd(&dom_pol)) { - dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); - } TALLOC_FREE(tmp_ctx); return status; } @@ -171,8 +248,7 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain, struct policy_handle dom_pol = { 0 }; uint32_t *rids = NULL; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("samr_query_user_list\n")); @@ -181,13 +257,15 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = samr_pipe->binding_handle; - status = rpc_query_user_list(tmp_ctx, samr_pipe, &dom_pol, @@ -202,10 +280,6 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain, } done: - if (b && is_valid_policy_hnd(&dom_pol)) { - dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); - } - TALLOC_FREE(rids); TALLOC_FREE(tmp_ctx); return status; @@ -221,8 +295,7 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain, struct netr_DomainTrust *trusts = NULL; uint32_t num_trusts = 0; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("samr: trusted domains\n")); @@ -235,13 +308,15 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); + status = open_cached_internal_pipe_conn(domain, + NULL, + NULL, + &lsa_pipe, + &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = lsa_pipe->binding_handle; - status = rpc_trusted_domains(tmp_ctx, lsa_pipe, &lsa_policy, @@ -257,10 +332,6 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain, } done: - if (b && is_valid_policy_hnd(&lsa_policy)) { - dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); - } - TALLOC_FREE(tmp_ctx); return status; } @@ -284,8 +355,7 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain, uint32_t *name_types = NULL; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("sam_lookup_groupmem\n")); @@ -304,13 +374,15 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = samr_pipe->binding_handle; - status = rpc_lookup_groupmem(tmp_ctx, samr_pipe, &dom_pol, @@ -340,10 +412,6 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain, } done: - if (b && is_valid_policy_hnd(&dom_pol)) { - dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); - } - TALLOC_FREE(tmp_ctx); return status; } @@ -398,8 +466,7 @@ static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain, struct wb_acct_info *info = NULL; uint32_t num_info = 0; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("samr: enum local groups\n")); @@ -412,13 +479,15 @@ static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = samr_pipe->binding_handle; - status = rpc_enum_local_groups(mem_ctx, samr_pipe, &dom_pol, @@ -437,10 +506,6 @@ static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain, } done: - if (b && is_valid_policy_hnd(&dom_pol)) { - dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); - } - TALLOC_FREE(tmp_ctx); return status; } @@ -459,8 +524,7 @@ static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain, struct dom_sid sid; enum lsa_SidType type; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("sam_name_to_sid\n")); @@ -469,13 +533,15 @@ static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); + status = open_cached_internal_pipe_conn(domain, + NULL, + NULL, + &lsa_pipe, + &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = lsa_pipe->binding_handle; - status = rpc_name_to_sid(tmp_ctx, lsa_pipe, &lsa_policy, @@ -496,10 +562,6 @@ static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain, } done: - if (b && is_valid_policy_hnd(&lsa_policy)) { - dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); - } - TALLOC_FREE(tmp_ctx); return status; } @@ -518,8 +580,7 @@ static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain, char *name = NULL; enum lsa_SidType type; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("sam_sid_to_name\n")); @@ -543,13 +604,15 @@ static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); + status = open_cached_internal_pipe_conn(domain, + NULL, + NULL, + &lsa_pipe, + &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = lsa_pipe->binding_handle; - status = rpc_sid_to_name(tmp_ctx, lsa_pipe, &lsa_policy, @@ -572,9 +635,6 @@ static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain, } done: - if (b && is_valid_policy_hnd(&lsa_policy)) { - dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); - } TALLOC_FREE(tmp_ctx); return status; @@ -595,8 +655,7 @@ static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain, char *domain_name = NULL; char **names = NULL; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("sam_rids_to_names for %s\n", domain->name)); @@ -616,13 +675,15 @@ static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); + status = open_cached_internal_pipe_conn(domain, + NULL, + NULL, + &lsa_pipe, + &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = lsa_pipe->binding_handle; - status = rpc_rids_to_names(tmp_ctx, lsa_pipe, &lsa_policy, @@ -650,10 +711,6 @@ static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain, } done: - if (b && is_valid_policy_hnd(&lsa_policy)) { - dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); - } - TALLOC_FREE(tmp_ctx); return status; } @@ -676,7 +733,11 @@ static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); if (!NT_STATUS_IS_OK(status)) { goto error; } @@ -700,10 +761,6 @@ static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain, *lockout_policy = info->info12; error: - if (b && is_valid_policy_hnd(&dom_pol)) { - dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); - } - TALLOC_FREE(tmp_ctx); return status; } @@ -726,7 +783,11 @@ static NTSTATUS sam_password_policy(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); if (!NT_STATUS_IS_OK(status)) { goto error; } @@ -750,10 +811,6 @@ static NTSTATUS sam_password_policy(struct winbindd_domain *domain, *passwd_policy = info->info1; error: - if (b && is_valid_policy_hnd(&dom_pol)) { - dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); - } - TALLOC_FREE(tmp_ctx); return status; } @@ -770,8 +827,7 @@ static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain, struct dom_sid *user_grpsids = NULL; uint32_t num_groups = 0; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("sam_lookup_usergroups\n")); @@ -786,13 +842,15 @@ static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = samr_pipe->binding_handle; - status = rpc_lookup_usergroups(tmp_ctx, samr_pipe, &dom_pol, @@ -813,9 +871,6 @@ static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain, } done: - if (b && is_valid_policy_hnd(&dom_pol)) { - dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); - } TALLOC_FREE(tmp_ctx); return status; @@ -833,8 +888,7 @@ static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain, uint32_t num_aliases = 0; uint32_t *alias_rids = NULL; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("sam_lookup_useraliases\n")); @@ -847,13 +901,15 @@ static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = samr_pipe->binding_handle; - status = rpc_lookup_useraliases(tmp_ctx, samr_pipe, &dom_pol, @@ -874,9 +930,6 @@ static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain, } done: - if (b && is_valid_policy_hnd(&dom_pol)) { - dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); - } TALLOC_FREE(tmp_ctx); return status; @@ -890,8 +943,7 @@ static NTSTATUS sam_sequence_number(struct winbindd_domain *domain, struct policy_handle dom_pol = { 0 }; uint32_t seq = DOM_SEQUENCE_NONE; TALLOC_CTX *tmp_ctx; - NTSTATUS status, result; - struct dcerpc_binding_handle *b = NULL; + NTSTATUS status; DEBUG(3,("samr: sequence number\n")); @@ -904,13 +956,15 @@ static NTSTATUS sam_sequence_number(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); + status = open_cached_internal_pipe_conn(domain, + &samr_pipe, + &dom_pol, + NULL, + NULL); if (!NT_STATUS_IS_OK(status)) { goto done; } - b = samr_pipe->binding_handle; - status = rpc_sequence_number(tmp_ctx, samr_pipe, &dom_pol, @@ -923,11 +977,8 @@ static NTSTATUS sam_sequence_number(struct winbindd_domain *domain, if (pseq) { *pseq = seq; } -done: - if (b && is_valid_policy_hnd(&dom_pol)) { - dcerpc_samr_Close(b, tmp_ctx, &dom_pol, &result); - } +done: TALLOC_FREE(tmp_ctx); return status; } -- 2.34.1