winbindd: winbindd_priv_pipe_dir() -> bool_dispatch_table
[samba.git] / source3 / winbindd / winbindd_samr.c
index c7528d1c66f8064b76830dd23bd416b68bd8adf7..31720d54997082b4847d5fd6bdf1923ff3c8cf39 100644 (file)
 #include "includes.h"
 #include "winbindd.h"
 #include "winbindd_rpc.h"
-
-#include "../librpc/gen_ndr/cli_samr.h"
+#include "lib/util_unixsids.h"
+#include "rpc_client/rpc_client.h"
+#include "rpc_client/cli_pipe.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
 #include "rpc_client/cli_samr.h"
-#include "../librpc/gen_ndr/srv_samr.h"
-#include "../librpc/gen_ndr/cli_lsa.h"
+#include "../librpc/gen_ndr/ndr_lsa_c.h"
 #include "rpc_client/cli_lsarpc.h"
-#include "../librpc/gen_ndr/srv_lsa.h"
 #include "rpc_server/rpc_ncacn_np.h"
 #include "../libcli/security/security.h"
+#include "passdb/machine_sid.h"
+#include "auth.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx,
-                                       struct rpc_pipe_client **samr_pipe)
-{
-       struct rpc_pipe_client *cli = NULL;
-       struct auth_serversupplied_info *server_info = NULL;
-       NTSTATUS status;
-
-       if (cli != NULL) {
-               goto done;
-       }
-
-       if (server_info == NULL) {
-               status = make_server_info_system(mem_ctx, &server_info);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
-                                 nt_errstr(status)));
-                       return status;
-               }
-       }
-
-       /* create a samr connection */
-       status = rpc_pipe_open_interface(mem_ctx,
-                                       &ndr_table_samr.syntax_id,
-                                       server_info,
-                                       NULL,
-                                       winbind_messaging_context(),
-                                       &cli);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
-                         nt_errstr(status)));
-               return status;
-       }
-
-done:
-       if (samr_pipe) {
-               *samr_pipe = cli;
-       }
+/*
+ * 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;
+};
 
-       return NT_STATUS_OK;
-}
 
 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
                                 struct winbindd_domain *domain,
                                 struct rpc_pipe_client **samr_pipe,
                                 struct policy_handle *samr_domain_hnd)
 {
-       NTSTATUS status;
+       NTSTATUS status, result;
        struct policy_handle samr_connect_hnd;
+       struct dcerpc_binding_handle *b;
 
-       status = open_internal_samr_pipe(mem_ctx, samr_pipe);
+       status = wb_open_internal_pipe(mem_ctx, &ndr_table_samr, samr_pipe);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       status = rpccli_samr_Connect2((*samr_pipe),
-                                     mem_ctx,
+       b = (*samr_pipe)->binding_handle;
+
+       status = dcerpc_samr_Connect2(b, mem_ctx,
                                      (*samr_pipe)->desthost,
                                      SEC_FLAG_MAXIMUM_ALLOWED,
-                                     &samr_connect_hnd);
+                                     &samr_connect_hnd,
+                                     &result);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
 
-       status = rpccli_samr_OpenDomain((*samr_pipe),
-                                       mem_ctx,
+       status = dcerpc_samr_OpenDomain(b, mem_ctx,
                                        &samr_connect_hnd,
                                        SEC_FLAG_MAXIMUM_ALLOWED,
                                        &domain->sid,
-                                       samr_domain_hnd);
+                                       samr_domain_hnd,
+                                       &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-       return status;
+       return result;
 }
 
-static NTSTATUS open_internal_lsa_pipe(TALLOC_CTX *mem_ctx,
-                                      struct rpc_pipe_client **lsa_pipe)
+NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
+                               struct rpc_pipe_client **lsa_pipe,
+                               struct policy_handle *lsa_hnd)
 {
-       struct rpc_pipe_client *cli = NULL;
-       struct auth_serversupplied_info *server_info = NULL;
        NTSTATUS status;
 
-       if (cli != NULL) {
-               goto done;
+       status = wb_open_internal_pipe(mem_ctx, &ndr_table_lsarpc, lsa_pipe);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       if (server_info == NULL) {
-               status = make_server_info_system(mem_ctx, &server_info);
+       status = rpccli_lsa_open_policy((*lsa_pipe),
+                                       mem_ctx,
+                                       true,
+                                       SEC_FLAG_MAXIMUM_ALLOWED,
+                                       lsa_hnd);
+
+       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)) {
-                       DEBUG(0, ("open_lsa_pipe: Could not create auth_serversupplied_info: %s\n",
-                                 nt_errstr(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);
+
        }
 
-       /* create a samr connection */
-       status = rpc_pipe_open_interface(mem_ctx,
-                                       &ndr_table_lsarpc.syntax_id,
-                                       server_info,
-                                       NULL,
-                                       winbind_messaging_context(),
-                                       &cli);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("open_lsa_pipe: Could not connect to lsa_pipe: %s\n",
-                         nt_errstr(status)));
-               return status;
+       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;
        }
 
-done:
        if (lsa_pipe) {
-               *lsa_pipe = cli;
+               *lsa_pipe = internal_pipes->lsa_pipe;
        }
 
        return NT_STATUS_OK;
 }
 
-static NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
-                                      struct rpc_pipe_client **lsa_pipe,
-                                      struct policy_handle *lsa_hnd)
+static bool reset_connection_on_error(struct winbindd_domain *domain,
+                                     struct rpc_pipe_client *p,
+                                     NTSTATUS status)
 {
-       NTSTATUS status;
+       struct winbind_internal_pipes *internal_pipes = NULL;
 
-       status = open_internal_lsa_pipe(mem_ctx, lsa_pipe);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
+       internal_pipes = talloc_get_type_abort(
+               domain->private_data, struct winbind_internal_pipes);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR))
+       {
+               TALLOC_FREE(internal_pipes);
+               domain->private_data = NULL;
+               return true;
        }
 
-       status = rpccli_lsa_open_policy((*lsa_pipe),
-                                       mem_ctx,
-                                       true,
-                                       SEC_FLAG_MAXIMUM_ALLOWED,
-                                       lsa_hnd);
+       if (!rpccli_is_connected(p)) {
+               TALLOC_FREE(internal_pipes);
+               domain->private_data = NULL;
+               return true;
+       }
 
-       return status;
+       return false;
 }
 
 /*********************************************************************
@@ -181,19 +214,18 @@ static NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
                                    TALLOC_CTX *mem_ctx,
                                    uint32_t *pnum_info,
-                                   struct acct_info **pinfo)
+                                   struct wb_acct_info **pinfo)
 {
        struct rpc_pipe_client *samr_pipe;
-       struct policy_handle dom_pol;
-       struct acct_info *info = NULL;
+       struct policy_handle dom_pol = { 0 };
+       struct wb_acct_info *info = NULL;
        uint32_t num_info = 0;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("sam_enum_dom_groups\n"));
 
-       ZERO_STRUCT(dom_pol);
-
        if (pnum_info) {
                *pnum_info = 0;
        }
@@ -203,9 +235,15 @@ 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);
+again:
+       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;
        }
 
        status = rpc_enum_dom_groups(tmp_ctx,
@@ -213,8 +251,15 @@ static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
                                     &dom_pol,
                                     &num_info,
                                     &info);
+
+       if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
-               goto error;
+               TALLOC_FREE(tmp_ctx);
+               return status;
        }
 
        if (pnum_info) {
@@ -225,10 +270,6 @@ static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
                *pinfo = talloc_move(mem_ctx, &info);
        }
 
-error:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, mem_ctx, &dom_pol);
-       }
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -236,30 +277,28 @@ error:
 /* Query display info for a domain */
 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
                                    TALLOC_CTX *mem_ctx,
-                                   uint32_t *pnum_info,
-                                   struct wbint_userinfo **pinfo)
+                                   uint32_t **prids)
 {
        struct rpc_pipe_client *samr_pipe = NULL;
-       struct policy_handle dom_pol;
-       struct wbint_userinfo *info = NULL;
-       uint32_t num_info = 0;
+       struct policy_handle dom_pol = { 0 };
+       uint32_t *rids = NULL;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("samr_query_user_list\n"));
 
-       ZERO_STRUCT(dom_pol);
-
-       if (pnum_info) {
-               *pnum_info = 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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               &samr_pipe,
+                                               &dom_pol,
+                                               NULL,
+                                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -268,77 +307,22 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
                                     samr_pipe,
                                     &dom_pol,
                                     &domain->sid,
-                                    &num_info,
-                                    &info);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto done;
-       }
-
-       if (pnum_info) {
-               *pnum_info = num_info;
-       }
-
-       if (pinfo) {
-               *pinfo = talloc_move(mem_ctx, &info);
-       }
-
-done:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, mem_ctx, &dom_pol);
-       }
-
-       TALLOC_FREE(tmp_ctx);
-       return status;
-}
-
-/* Lookup user information from a rid or username. */
-static NTSTATUS sam_query_user(struct winbindd_domain *domain,
-                              TALLOC_CTX *mem_ctx,
-                              const struct dom_sid *user_sid,
-                              struct wbint_userinfo *user_info)
-{
-       struct rpc_pipe_client *samr_pipe;
-       struct policy_handle dom_pol;
-       TALLOC_CTX *tmp_ctx;
-       NTSTATUS status;
-
-       DEBUG(3,("sam_query_user\n"));
-
-       ZERO_STRUCT(dom_pol);
-
-       /* Paranoia check */
-       if (!sid_check_is_in_our_domain(user_sid)) {
-               return NT_STATUS_NO_SUCH_USER;
-       }
-
-       if (user_info) {
-               user_info->homedir = NULL;
-               user_info->shell = NULL;
-               user_info->primary_gid = (gid_t) -1;
-       }
-
-       tmp_ctx = talloc_stackframe();
-       if (tmp_ctx == NULL) {
-               return NT_STATUS_NO_MEMORY;
+                                    &rids);
+       if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+               retry = true;
+               goto again;
        }
 
-       status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
 
-       status = rpc_query_user(tmp_ctx,
-                               samr_pipe,
-                               &dom_pol,
-                               &domain->sid,
-                               user_sid,
-                               user_info);
-
-done:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, mem_ctx, &dom_pol);
+       if (prids != NULL) {
+               *prids = talloc_move(mem_ctx, &rids);
        }
 
+done:
+       TALLOC_FREE(rids);
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -349,16 +333,15 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
                                    struct netr_DomainTrustList *ptrust_list)
 {
        struct rpc_pipe_client *lsa_pipe;
-       struct policy_handle lsa_policy;
+       struct policy_handle lsa_policy = { 0 };
        struct netr_DomainTrust *trusts = NULL;
        uint32_t num_trusts = 0;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("samr: trusted domains\n"));
 
-       ZERO_STRUCT(lsa_policy);
-
        if (ptrust_list) {
                ZERO_STRUCTP(ptrust_list);
        }
@@ -368,7 +351,12 @@ 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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               NULL,
+                                               NULL,
+                                               &lsa_pipe,
+                                               &lsa_policy);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -378,6 +366,12 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
                                     &lsa_policy,
                                     &num_trusts,
                                     &trusts);
+
+       if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -388,10 +382,6 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
        }
 
 done:
-       if (is_valid_policy_hnd(&lsa_policy)) {
-               rpccli_lsa_Close(lsa_pipe, mem_ctx, &lsa_policy);
-       }
-
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -407,7 +397,7 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
                                    uint32_t **pname_types)
 {
        struct rpc_pipe_client *samr_pipe;
-       struct policy_handle dom_pol;
+       struct policy_handle dom_pol = { 0 };
 
        uint32_t num_names = 0;
        struct dom_sid *sid_mem = NULL;
@@ -416,11 +406,10 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
 
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("sam_lookup_groupmem\n"));
 
-       ZERO_STRUCT(dom_pol);
-
        /* Paranoia check */
        if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
                /* There's no groups, only aliases in BUILTIN */
@@ -428,7 +417,7 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
        }
 
        if (pnum_names) {
-               pnum_names = 0;
+               *pnum_names = 0;
        }
 
        tmp_ctx = talloc_stackframe();
@@ -436,7 +425,12 @@ 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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               &samr_pipe,
+                                               &dom_pol,
+                                               NULL,
+                                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -453,6 +447,11 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
                                     &names,
                                     &name_types);
 
+       if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (pnum_names) {
                *pnum_names = num_names;
        }
@@ -470,10 +469,6 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
        }
 
 done:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, mem_ctx, &dom_pol);
-       }
-
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -485,8 +480,8 @@ done:
 /* List all domain groups */
 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
-                               uint32 *num_entries,
-                               struct acct_info **info)
+                               uint32_t *num_entries,
+                               struct wb_acct_info **info)
 {
        /* BUILTIN doesn't have domain groups */
        *num_entries = 0;
@@ -497,24 +492,13 @@ static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
 /* Query display info for a domain */
 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
-                               uint32 *num_entries,
-                               struct wbint_userinfo **info)
+                               uint32_t **rids)
 {
        /* We don't have users */
-       *num_entries = 0;
-       *info = NULL;
+       *rids = NULL;
        return NT_STATUS_OK;
 }
 
-/* Lookup user information from a rid or username. */
-static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
-                               TALLOC_CTX *mem_ctx,
-                               const struct dom_sid *user_sid,
-                               struct wbint_userinfo *user_info)
-{
-       return NT_STATUS_NO_SUCH_USER;
-}
-
 /* get a list of trusted domains - builtin domain */
 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
                                        TALLOC_CTX *mem_ctx,
@@ -532,19 +516,18 @@ static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
 static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
                                      TALLOC_CTX *mem_ctx,
                                      uint32_t *pnum_info,
-                                     struct acct_info **pinfo)
+                                     struct wb_acct_info **pinfo)
 {
        struct rpc_pipe_client *samr_pipe;
-       struct policy_handle dom_pol;
-       struct acct_info *info = NULL;
+       struct policy_handle dom_pol = { 0 };
+       struct wb_acct_info *info = NULL;
        uint32_t num_info = 0;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("samr: enum local groups\n"));
 
-       ZERO_STRUCT(dom_pol);
-
        if (pnum_info) {
                *pnum_info = 0;
        }
@@ -554,7 +537,12 @@ 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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               &samr_pipe,
+                                               &dom_pol,
+                                               NULL,
+                                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -563,7 +551,13 @@ static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
                                       samr_pipe,
                                       &dom_pol,
                                       &num_info,
+
                                       &info);
+       if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -577,10 +571,6 @@ static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
        }
 
 done:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, mem_ctx, &dom_pol);
-       }
-
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -595,22 +585,26 @@ static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
                                   enum lsa_SidType *ptype)
 {
        struct rpc_pipe_client *lsa_pipe;
-       struct policy_handle lsa_policy;
+       struct policy_handle lsa_policy = { 0 };
        struct dom_sid sid;
        enum lsa_SidType type;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("sam_name_to_sid\n"));
 
-       ZERO_STRUCT(lsa_policy);
-
        tmp_ctx = talloc_stackframe();
        if (tmp_ctx == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               NULL,
+                                               NULL,
+                                               &lsa_pipe,
+                                               &lsa_policy);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -623,6 +617,12 @@ static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
                                 flags,
                                 &sid,
                                 &type);
+
+       if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -635,10 +635,6 @@ static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
        }
 
 done:
-       if (is_valid_policy_hnd(&lsa_policy)) {
-               rpccli_lsa_Close(lsa_pipe, mem_ctx, &lsa_policy);
-       }
-
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -652,20 +648,21 @@ static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
                                enum lsa_SidType *ptype)
 {
        struct rpc_pipe_client *lsa_pipe;
-       struct policy_handle lsa_policy;
+       struct policy_handle lsa_policy = { 0 };
        char *domain_name = NULL;
        char *name = NULL;
        enum lsa_SidType type;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("sam_sid_to_name\n"));
 
-       ZERO_STRUCT(lsa_policy);
-
        /* Paranoia check */
        if (!sid_check_is_in_builtin(sid) &&
-           !sid_check_is_in_our_domain(sid) &&
+           !sid_check_is_builtin(sid) &&
+           !sid_check_is_in_our_sam(sid) &&
+           !sid_check_is_our_sam(sid) &&
            !sid_check_is_in_unix_users(sid) &&
            !sid_check_is_unix_users(sid) &&
            !sid_check_is_in_unix_groups(sid) &&
@@ -681,7 +678,12 @@ 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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               NULL,
+                                               NULL,
+                                               &lsa_pipe,
+                                               &lsa_policy);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -695,6 +697,11 @@ static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
                                 &name,
                                 &type);
 
+       if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (ptype) {
                *ptype = type;
        }
@@ -708,9 +715,6 @@ static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
        }
 
 done:
-       if (is_valid_policy_hnd(&lsa_policy)) {
-               rpccli_lsa_Close(lsa_pipe, mem_ctx, &lsa_policy);
-       }
 
        TALLOC_FREE(tmp_ctx);
        return status;
@@ -718,35 +722,32 @@ done:
 
 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
                                  TALLOC_CTX *mem_ctx,
-                                 const struct dom_sid *sid,
-                                 uint32 *rids,
+                                 const struct dom_sid *domain_sid,
+                                 uint32_t *rids,
                                  size_t num_rids,
                                  char **pdomain_name,
                                  char ***pnames,
                                  enum lsa_SidType **ptypes)
 {
        struct rpc_pipe_client *lsa_pipe;
-       struct policy_handle lsa_policy;
+       struct policy_handle lsa_policy = { 0 };
        enum lsa_SidType *types = NULL;
        char *domain_name = NULL;
        char **names = NULL;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
 
-       ZERO_STRUCT(lsa_policy);
-
        /* Paranoia check */
-       if (!sid_check_is_in_builtin(sid) &&
-           !sid_check_is_in_our_domain(sid) &&
-           !sid_check_is_in_unix_users(sid) &&
-           !sid_check_is_unix_users(sid) &&
-           !sid_check_is_in_unix_groups(sid) &&
-           !sid_check_is_unix_groups(sid) &&
-           !sid_check_is_in_wellknown_domain(sid)) {
+       if (!sid_check_is_builtin(domain_sid) &&
+           !sid_check_is_our_sam(domain_sid) &&
+           !sid_check_is_unix_users(domain_sid) &&
+           !sid_check_is_unix_groups(domain_sid) &&
+           !sid_check_is_in_wellknown_domain(domain_sid)) {
                DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to "
-                         "lookup SID %s\n", sid_string_dbg(sid)));
+                         "lookup SID %s\n", sid_string_dbg(domain_sid)));
                return NT_STATUS_NONE_MAPPED;
        }
 
@@ -755,7 +756,12 @@ 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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               NULL,
+                                               NULL,
+                                               &lsa_pipe,
+                                               &lsa_policy);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -764,12 +770,18 @@ static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
                                   lsa_pipe,
                                   &lsa_policy,
                                   domain,
-                                  sid,
+                                  domain_sid,
                                   rids,
                                   num_rids,
                                   &domain_name,
                                   &names,
                                   &types);
+
+       if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -787,10 +799,6 @@ static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
        }
 
 done:
-       if (is_valid_policy_hnd(&lsa_policy)) {
-               rpccli_lsa_Close(lsa_pipe, mem_ctx, &lsa_policy);
-       }
-
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -800,41 +808,55 @@ static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
                                   struct samr_DomInfo12 *lockout_policy)
 {
        struct rpc_pipe_client *samr_pipe;
-       struct policy_handle dom_pol;
+       struct policy_handle dom_pol = { 0 };
        union samr_DomainInfo *info = NULL;
        TALLOC_CTX *tmp_ctx;
-       NTSTATUS status;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+       bool retry = false;
 
        DEBUG(3,("sam_lockout_policy\n"));
 
-       ZERO_STRUCT(dom_pol);
-
        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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               &samr_pipe,
+                                               &dom_pol,
+                                               NULL,
+                                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
                goto error;
        }
 
-       status = rpccli_samr_QueryDomainInfo(samr_pipe,
+       b = samr_pipe->binding_handle;
+
+       status = dcerpc_samr_QueryDomainInfo(b,
                                             mem_ctx,
                                             &dom_pol,
-                                            12,
-                                            &info);
+                                            DomainLockoutInformation,
+                                            &info,
+                                            &result);
+
+       if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                goto error;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto error;
+       }
 
        *lockout_policy = info->info12;
 
 error:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, mem_ctx, &dom_pol);
-       }
-
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -844,41 +866,55 @@ static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
                                    struct samr_DomInfo1 *passwd_policy)
 {
        struct rpc_pipe_client *samr_pipe;
-       struct policy_handle dom_pol;
+       struct policy_handle dom_pol = { 0 };
        union samr_DomainInfo *info = NULL;
        TALLOC_CTX *tmp_ctx;
-       NTSTATUS status;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+       bool retry = false;
 
        DEBUG(3,("sam_password_policy\n"));
 
-       ZERO_STRUCT(dom_pol);
-
        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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               &samr_pipe,
+                                               &dom_pol,
+                                               NULL,
+                                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
                goto error;
        }
 
-       status = rpccli_samr_QueryDomainInfo(samr_pipe,
+       b = samr_pipe->binding_handle;
+
+       status = dcerpc_samr_QueryDomainInfo(b,
                                             mem_ctx,
                                             &dom_pol,
-                                            1,
-                                            &info);
+                                            DomainPasswordInformation,
+                                            &info,
+                                            &result);
+
+       if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                goto error;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto error;
+       }
 
        *passwd_policy = info->info1;
 
 error:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, mem_ctx, &dom_pol);
-       }
-
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -896,6 +932,7 @@ static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
        uint32_t num_groups = 0;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("sam_lookup_usergroups\n"));
 
@@ -910,7 +947,12 @@ 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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               &samr_pipe,
+                                               &dom_pol,
+                                               NULL,
+                                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -922,6 +964,12 @@ static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
                                       user_sid,
                                       &num_groups,
                                       &user_grpsids);
+
+       if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -935,9 +983,6 @@ static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
        }
 
 done:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, mem_ctx, &dom_pol);
-       }
 
        TALLOC_FREE(tmp_ctx);
        return status;
@@ -951,16 +996,15 @@ static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
                                       uint32_t **palias_rids)
 {
        struct rpc_pipe_client *samr_pipe;
-       struct policy_handle dom_pol;
+       struct policy_handle dom_pol = { 0 };
        uint32_t num_aliases = 0;
        uint32_t *alias_rids = NULL;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("sam_lookup_useraliases\n"));
 
-       ZERO_STRUCT(dom_pol);
-
        if (pnum_aliases) {
                *pnum_aliases = 0;
        }
@@ -970,7 +1014,12 @@ 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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               &samr_pipe,
+                                               &dom_pol,
+                                               NULL,
+                                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -982,6 +1031,12 @@ static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
                                        sids,
                                        &num_aliases,
                                        &alias_rids);
+
+       if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -995,9 +1050,6 @@ static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
        }
 
 done:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, mem_ctx, &dom_pol);
-       }
 
        TALLOC_FREE(tmp_ctx);
        return status;
@@ -1008,15 +1060,14 @@ static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
                                    uint32_t *pseq)
 {
        struct rpc_pipe_client *samr_pipe;
-       struct policy_handle dom_pol;
-       uint32_t seq;
+       struct policy_handle dom_pol = { 0 };
+       uint32_t seq = DOM_SEQUENCE_NONE;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
+       bool retry = false;
 
        DEBUG(3,("samr: sequence number\n"));
 
-       ZERO_STRUCT(dom_pol);
-
        if (pseq) {
                *pseq = DOM_SEQUENCE_NONE;
        }
@@ -1026,7 +1077,12 @@ 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);
+again:
+       status = open_cached_internal_pipe_conn(domain,
+                                               &samr_pipe,
+                                               &dom_pol,
+                                               NULL,
+                                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -1036,6 +1092,12 @@ static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
                                     &dom_pol,
                                     domain->name,
                                     &seq);
+
+       if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+               retry = true;
+               goto again;
+       }
+
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -1043,11 +1105,8 @@ static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
        if (pseq) {
                *pseq = seq;
        }
-done:
-       if (is_valid_policy_hnd(&dom_pol)) {
-               rpccli_samr_Close(samr_pipe, tmp_ctx, &dom_pol);
-       }
 
+done:
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -1062,7 +1121,6 @@ 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,
-       .query_user            = builtin_query_user,
        .lookup_usergroups     = sam_lookup_usergroups,
        .lookup_useraliases    = sam_lookup_useraliases,
        .lookup_groupmem       = sam_lookup_groupmem,
@@ -1082,7 +1140,6 @@ 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,
-       .query_user            = sam_query_user,
        .lookup_usergroups     = sam_lookup_usergroups,
        .lookup_useraliases    = sam_lookup_useraliases,
        .lookup_groupmem       = sam_lookup_groupmem,