winbindd: Add a cache of the samr and lsa handles for the passdb domain
authorAndrew Bartlett <abartlet@samba.org>
Wed, 21 Mar 2018 07:43:10 +0000 (20:43 +1300)
committerKarolin Seeger <kseeger@samba.org>
Mon, 14 May 2018 07:58:07 +0000 (09:58 +0200)
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.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13430

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit d418d0ca33afb41a793a2fff19ca68871aa5e9ef)

source3/winbindd/winbindd_samr.c

index aedb77bdee9b425e222860ae1e8a4c212200b49b..da54d6979090f203b820affd26e5621daac6d72e 100644 (file)
 #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;
 }