s3-winbind: We need to use internal rpc connections in winbind.
[idra/samba.git] / source3 / winbindd / winbindd_samr.c
index e4faaef1191f899720420ce7ee1af01af4bf1928..582e2a696207cbc9ead82cb2e752c7b8b70d78cd 100644 (file)
 
 #include "includes.h"
 #include "winbindd.h"
-#include "../librpc/gen_ndr/cli_samr.h"
+#include "winbindd_rpc.h"
+#include "rpc_client/rpc_client.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)
 {
-       static struct rpc_pipe_client *cli = NULL;
-       struct auth_serversupplied_info *server_info = NULL;
+       struct rpc_pipe_client *cli = NULL;
+       struct auth_session_info *session_info = NULL;
        NTSTATUS status;
 
-       if (cli != NULL) {
-               goto done;
-       }
-
-       if (server_info == NULL) {
-               status = make_server_info_system(mem_ctx, &server_info);
+       if (session_info == NULL) {
+               status = make_session_info_system(mem_ctx, &session_info);
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
+                       DEBUG(0, ("open_samr_pipe: Could not create auth_session_info: %s\n",
                                  nt_errstr(status)));
                        return status;
                }
        }
 
        /* create a samr connection */
-       status = rpc_pipe_open_internal(talloc_autofree_context(),
+       status = rpc_pipe_open_internal(mem_ctx,
                                        &ndr_table_samr.syntax_id,
-                                       rpc_samr_dispatch,
-                                       server_info,
+                                       session_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",
@@ -67,7 +68,6 @@ static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx,
                return status;
        }
 
-done:
        if (samr_pipe) {
                *samr_pipe = cli;
        }
@@ -75,71 +75,76 @@ done:
        return NT_STATUS_OK;
 }
 
-static 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 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);
        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)
 {
-       static struct rpc_pipe_client *cli = NULL;
-       struct auth_serversupplied_info *server_info = NULL;
+       struct rpc_pipe_client *cli = NULL;
+       struct auth_session_info *session_info = NULL;
        NTSTATUS status;
 
-       if (cli != NULL) {
-               goto done;
-       }
-
-       if (server_info == NULL) {
-               status = make_server_info_system(mem_ctx, &server_info);
+       if (session_info == NULL) {
+               status = make_session_info_system(mem_ctx, &session_info);
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
+                       DEBUG(0, ("open_lsa_pipe: Could not create auth_session_info: %s\n",
                                  nt_errstr(status)));
                        return status;
                }
        }
 
-       /* create a samr connection */
-       status = rpc_pipe_open_internal(talloc_autofree_context(),
+       /* create a lsa connection */
+       status = rpc_pipe_open_internal(mem_ctx,
                                        &ndr_table_lsarpc.syntax_id,
-                                       rpc_lsarpc_dispatch,
-                                       server_info,
+                                       session_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",
+               DEBUG(0, ("open_lsa_pipe: Could not connect to lsa_pipe: %s\n",
                          nt_errstr(status)));
                return status;
        }
 
-done:
        if (lsa_pipe) {
                *lsa_pipe = cli;
        }
@@ -174,11 +179,60 @@ static NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
 /* List all domain groups */
 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
                                    TALLOC_CTX *mem_ctx,
-                                   uint32_t *num_entries,
-                                   struct acct_info **info)
+                                   uint32_t *pnum_info,
+                                   struct wb_acct_info **pinfo)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle dom_pol;
+       struct wb_acct_info *info = NULL;
+       uint32_t num_info = 0;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       DEBUG(3,("sam_enum_dom_groups\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);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto error;
+       }
+
+       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;
+       }
+
+       if (pnum_info) {
+               *pnum_info = num_info;
+       }
+
+       if (pinfo) {
+               *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;
 }
 
 /* Query display info for a domain */
@@ -188,16 +242,16 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
                                    struct wbint_userinfo **pinfo)
 {
        struct rpc_pipe_client *samr_pipe = NULL;
-       struct wbint_userinfo *info = NULL;
        struct policy_handle dom_pol;
+       struct wbint_userinfo *info = NULL;
        uint32_t num_info = 0;
-       uint32_t loop_count = 0;
-       uint32_t start_idx = 0;
-       uint32_t i = 0;
        TALLOC_CTX *tmp_ctx;
-       NTSTATUS status;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
 
-       DEBUG(3,("samr: query_user_list\n"));
+       DEBUG(3,("samr_query_user_list\n"));
+
+       ZERO_STRUCT(dom_pol);
 
        if (pnum_info) {
                *pnum_info = 0;
@@ -210,89 +264,20 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
 
        status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
-               goto error;
+               goto done;
        }
 
-       do {
-               uint32_t j;
-               uint32_t num_dom_users;
-               uint32_t max_entries, max_size;
-               uint32_t total_size, returned_size;
-               union samr_DispInfo disp_info;
-
-               get_query_dispinfo_params(loop_count,
-                                         &max_entries,
-                                         &max_size);
-
-               status = rpccli_samr_QueryDisplayInfo(samr_pipe,
-                                                     tmp_ctx,
-                                                     &dom_pol,
-                                                     1, /* level */
-                                                     start_idx,
-                                                     max_entries,
-                                                     max_size,
-                                                     &total_size,
-                                                     &returned_size,
-                                                     &disp_info);
-               if (!NT_STATUS_IS_OK(status)) {
-                       if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
-                               goto error;
-                       }
-               }
-
-               /* increment required start query values */
-               start_idx += disp_info.info1.count;
-               loop_count++;
-               num_dom_users = disp_info.info1.count;
-
-               num_info += num_dom_users;
+       b = samr_pipe->binding_handle;
 
-               info = TALLOC_REALLOC_ARRAY(tmp_ctx,
-                                           info,
-                                           struct wbint_userinfo,
-                                           num_info);
-               if (info == NULL) {
-                       status = NT_STATUS_NO_MEMORY;
-                       goto error;
-               }
-
-               for (j = 0; j < num_dom_users; i++, j++) {
-                       uint32_t rid = disp_info.info1.entries[j].rid;
-                       struct samr_DispEntryGeneral *src;
-                       struct wbint_userinfo *dst;
-
-                       src = &(disp_info.info1.entries[j]);
-                       dst = &(info[i]);
-
-                       dst->acct_name = talloc_strdup(info,
-                                                      src->account_name.string);
-                       if (dst->acct_name == NULL) {
-                               status = NT_STATUS_NO_MEMORY;
-                               goto error;
-                       }
-
-                       dst->full_name = talloc_strdup(info, src->full_name.string);
-                       if (dst->full_name == NULL) {
-                               status = NT_STATUS_NO_MEMORY;
-                               goto error;
-                       }
-
-                       dst->homedir = NULL;
-                       dst->shell = NULL;
-
-                       sid_compose(&dst->user_sid, &domain->sid, rid);
-
-                       /* For the moment we set the primary group for
-                          every user to be the Domain Users group.
-                          There are serious problems with determining
-                          the actual primary group for large domains.
-                          This should really be made into a 'winbind
-                          force group' smb.conf parameter or
-                          something like that. */
-                       sid_compose(&dst->group_sid, &domain->sid,
-                                   DOMAIN_RID_USERS);
-               }
-       } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
+       status = rpc_query_user_list(tmp_ctx,
+                                    samr_pipe,
+                                    &dom_pol,
+                                    &domain->sid,
+                                    &num_info,
+                                    &info);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
 
        if (pnum_info) {
                *pnum_info = num_info;
@@ -302,7 +287,11 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
                *pinfo = talloc_move(mem_ctx, &info);
        }
 
-error:
+done:
+       if (b && is_valid_policy_hnd(&dom_pol)) {
+               dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
+       }
+
        TALLOC_FREE(tmp_ctx);
        return status;
 }
@@ -313,17 +302,109 @@ static NTSTATUS sam_query_user(struct winbindd_domain *domain,
                               const struct dom_sid *user_sid,
                               struct wbint_userinfo *user_info)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle dom_pol;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       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;
+       }
+
+       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_query_user(tmp_ctx,
+                               samr_pipe,
+                               &dom_pol,
+                               &domain->sid,
+                               user_sid,
+                               user_info);
+
+done:
+       if (b && is_valid_policy_hnd(&dom_pol)) {
+               dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
 /* get a list of trusted domains - builtin domain */
 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
                                    TALLOC_CTX *mem_ctx,
-                                   struct netr_DomainTrustList *trusts)
+                                   struct netr_DomainTrustList *ptrust_list)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *lsa_pipe;
+       struct policy_handle lsa_policy;
+       struct netr_DomainTrust *trusts = NULL;
+       uint32_t num_trusts = 0;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       DEBUG(3,("samr: trusted domains\n"));
+
+       ZERO_STRUCT(lsa_policy);
+
+       if (ptrust_list) {
+               ZERO_STRUCTP(ptrust_list);
+       }
+
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = open_internal_lsa_conn(tmp_ctx, &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,
+                                    &num_trusts,
+                                    &trusts);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       if (ptrust_list) {
+               ptrust_list->count = num_trusts;
+               ptrust_list->array = talloc_move(mem_ctx, &trusts);
+       }
+
+done:
+       if (b && is_valid_policy_hnd(&lsa_policy)) {
+               dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
 /* Lookup group membership given a rid.   */
@@ -331,13 +412,84 @@ static NTSTATUS sam_lookup_groupmem(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,
-                                   char ***names,
-                                   uint32_t **name_types)
+                                   uint32_t *pnum_names,
+                                   struct dom_sid **psid_mem,
+                                   char ***pnames,
+                                   uint32_t **pname_types)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle dom_pol;
+
+       uint32_t num_names = 0;
+       struct dom_sid *sid_mem = NULL;
+       char **names = NULL;
+       uint32_t *name_types = NULL;
+
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       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 */
+               return NT_STATUS_NO_SUCH_GROUP;
+       }
+
+       if (pnum_names) {
+               *pnum_names = 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_groupmem(tmp_ctx,
+                                    samr_pipe,
+                                    &dom_pol,
+                                    domain->name,
+                                    &domain->sid,
+                                    group_sid,
+                                    type,
+                                    &num_names,
+                                    &sid_mem,
+                                    &names,
+                                    &name_types);
+
+       if (pnum_names) {
+               *pnum_names = num_names;
+       }
+
+       if (pnames) {
+               *pnames = talloc_move(mem_ctx, &names);
+       }
+
+       if (pname_types) {
+               *pname_types = talloc_move(mem_ctx, &name_types);
+       }
+
+       if (psid_mem) {
+               *psid_mem = talloc_move(mem_ctx, &sid_mem);
+       }
+
+done:
+       if (b && is_valid_policy_hnd(&dom_pol)) {
+               dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
 /*********************************************************************
@@ -348,7 +500,7 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
                                uint32 *num_entries,
-                               struct acct_info **info)
+                               struct wb_acct_info **info)
 {
        /* BUILTIN doesn't have domain groups */
        *num_entries = 0;
@@ -391,117 +543,581 @@ static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
 *********************************************************************/
 
 /* List all local groups (aliases) */
-static NTSTATUS common_enum_local_groups(struct winbindd_domain *domain,
-                                        TALLOC_CTX *mem_ctx,
-                                        uint32_t *num_entries,
-                                        struct acct_info **info)
+static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
+                                     TALLOC_CTX *mem_ctx,
+                                     uint32_t *pnum_info,
+                                     struct wb_acct_info **pinfo)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle dom_pol;
+       struct wb_acct_info *info = NULL;
+       uint32_t num_info = 0;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       DEBUG(3,("samr: enum local groups\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);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       b = samr_pipe->binding_handle;
+
+       status = rpc_enum_local_groups(mem_ctx,
+                                      samr_pipe,
+                                      &dom_pol,
+                                      &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 (b && is_valid_policy_hnd(&dom_pol)) {
+               dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
 /* convert a single name to a sid in a domain */
-static NTSTATUS common_name_to_sid(struct winbindd_domain *domain,
+static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
                                   TALLOC_CTX *mem_ctx,
                                   const char *domain_name,
                                   const char *name,
                                   uint32_t flags,
-                                  struct dom_sid *sid,
-                                  enum lsa_SidType *type)
+                                  struct dom_sid *psid,
+                                  enum lsa_SidType *ptype)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *lsa_pipe;
+       struct policy_handle lsa_policy;
+       struct dom_sid sid;
+       enum lsa_SidType type;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       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);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       b = lsa_pipe->binding_handle;
+
+       status = rpc_name_to_sid(tmp_ctx,
+                                lsa_pipe,
+                                &lsa_policy,
+                                domain_name,
+                                name,
+                                flags,
+                                &sid,
+                                &type);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       if (psid) {
+               sid_copy(psid, &sid);
+       }
+       if (ptype) {
+               *ptype = type;
+       }
+
+done:
+       if (b && is_valid_policy_hnd(&lsa_policy)) {
+               dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
 /* convert a domain SID to a user or group name */
-static NTSTATUS common_sid_to_name(struct winbindd_domain *domain,
-                                  TALLOC_CTX *mem_ctx,
-                                  const struct dom_sid *sid,
-                                  char **domain_name,
-                                  char **name,
-                                  enum lsa_SidType *type)
+static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
+                               TALLOC_CTX *mem_ctx,
+                               const struct dom_sid *sid,
+                               char **pdomain_name,
+                               char **pname,
+                               enum lsa_SidType *ptype)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *lsa_pipe;
+       struct policy_handle lsa_policy;
+       char *domain_name = NULL;
+       char *name = NULL;
+       enum lsa_SidType type;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       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_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)) {
+               DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to "
+                         "lookup SID %s\n", sid_string_dbg(sid)));
+               return NT_STATUS_NONE_MAPPED;
+       }
+
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = open_internal_lsa_conn(tmp_ctx, &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,
+                                domain,
+                                sid,
+                                &domain_name,
+                                &name,
+                                &type);
+
+       if (ptype) {
+               *ptype = type;
+       }
+
+       if (pname) {
+               *pname = talloc_move(mem_ctx, &name);
+       }
+
+       if (pdomain_name) {
+               *pdomain_name = talloc_move(mem_ctx, &domain_name);
+       }
+
+done:
+       if (b && is_valid_policy_hnd(&lsa_policy)) {
+               dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
-static NTSTATUS common_rids_to_names(struct winbindd_domain *domain,
-                                    TALLOC_CTX *mem_ctx,
-                                    const struct dom_sid *sid,
-                                    uint32 *rids,
-                                    size_t num_rids,
-                                    char **domain_name,
-                                    char ***names,
-                                    enum lsa_SidType **types)
+static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
+                                 TALLOC_CTX *mem_ctx,
+                                 const struct dom_sid *domain_sid,
+                                 uint32 *rids,
+                                 size_t num_rids,
+                                 char **pdomain_name,
+                                 char ***pnames,
+                                 enum lsa_SidType **ptypes)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *lsa_pipe;
+       struct policy_handle lsa_policy;
+       enum lsa_SidType *types = NULL;
+       char *domain_name = NULL;
+       char **names = NULL;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
+
+       ZERO_STRUCT(lsa_policy);
+
+       /* Paranoia check */
+       if (!sid_check_is_builtin(domain_sid) &&
+           !sid_check_is_domain(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(domain_sid)));
+               return NT_STATUS_NONE_MAPPED;
+       }
+
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = open_internal_lsa_conn(tmp_ctx, &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,
+                                  domain,
+                                  domain_sid,
+                                  rids,
+                                  num_rids,
+                                  &domain_name,
+                                  &names,
+                                  &types);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       if (pdomain_name) {
+               *pdomain_name = talloc_move(mem_ctx, &domain_name);
+       }
+
+       if (ptypes) {
+               *ptypes = talloc_move(mem_ctx, &types);
+       }
+
+       if (pnames) {
+               *pnames = talloc_move(mem_ctx, &names);
+       }
+
+done:
+       if (b && is_valid_policy_hnd(&lsa_policy)) {
+               dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
-static NTSTATUS common_lockout_policy(struct winbindd_domain *domain,
-                                     TALLOC_CTX *mem_ctx,
-                                     struct samr_DomInfo12 *policy)
+static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct samr_DomInfo12 *lockout_policy)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle dom_pol;
+       union samr_DomainInfo *info = NULL;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       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);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto error;
+       }
+
+       b = samr_pipe->binding_handle;
+
+       status = dcerpc_samr_QueryDomainInfo(b,
+                                            mem_ctx,
+                                            &dom_pol,
+                                            12,
+                                            &info,
+                                            &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto error;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto error;
+       }
+
+       *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;
 }
 
-static NTSTATUS common_password_policy(struct winbindd_domain *domain,
-                                      TALLOC_CTX *mem_ctx,
-                                      struct samr_DomInfo1 *policy)
+static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
+                                   TALLOC_CTX *mem_ctx,
+                                   struct samr_DomInfo1 *passwd_policy)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle dom_pol;
+       union samr_DomainInfo *info = NULL;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       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);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto error;
+       }
+
+       b = samr_pipe->binding_handle;
+
+       status = dcerpc_samr_QueryDomainInfo(b,
+                                            mem_ctx,
+                                            &dom_pol,
+                                            1,
+                                            &info,
+                                            &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto error;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto error;
+       }
+
+       *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;
 }
 
-/* Lookup groups a user is a member of.  I wish Unix had a call like this! */
-static NTSTATUS common_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 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)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       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 common_lookup_useraliases(struct winbindd_domain *domain,
-                                         TALLOC_CTX *mem_ctx,
-                                         uint32_t num_sids,
-                                         const struct dom_sid *sids,
-                                         uint32_t *p_num_aliases,
-                                         uint32_t **rids)
+static NTSTATUS sam_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 **palias_rids)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle dom_pol;
+       uint32_t num_aliases = 0;
+       uint32_t *alias_rids = NULL;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       DEBUG(3,("sam_lookup_useraliases\n"));
+
+       ZERO_STRUCT(dom_pol);
+
+       if (pnum_aliases) {
+               *pnum_aliases = 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_useraliases(tmp_ctx,
+                                       samr_pipe,
+                                       &dom_pol,
+                                       num_sids,
+                                       sids,
+                                       &num_aliases,
+                                       &alias_rids);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       if (pnum_aliases) {
+               *pnum_aliases = num_aliases;
+       }
+
+       if (palias_rids) {
+               *palias_rids = talloc_move(mem_ctx, &alias_rids);
+       }
+
+done:
+       if (b && is_valid_policy_hnd(&dom_pol)) {
+               dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
 /* find the sequence number for a domain */
-static NTSTATUS common_sequence_number(struct winbindd_domain *domain,
-                                      uint32_t *seq)
+static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
+                                   uint32_t *pseq)
 {
-       /* TODO FIXME */
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle dom_pol;
+       uint32_t seq;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b = NULL;
+
+       DEBUG(3,("samr: sequence number\n"));
+
+       ZERO_STRUCT(dom_pol);
+
+       if (pseq) {
+               *pseq = DOM_SEQUENCE_NONE;
+       }
+
+       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_sequence_number(tmp_ctx,
+                                    samr_pipe,
+                                    &dom_pol,
+                                    domain->name,
+                                    &seq);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       if (pseq) {
+               *pseq = seq;
+       }
+done:
+       if (b && is_valid_policy_hnd(&dom_pol)) {
+               dcerpc_samr_Close(b, tmp_ctx, &dom_pol, &result);
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
-#if 0
 /* the rpc backend methods are exposed via this structure */
 struct winbindd_methods builtin_passdb_methods = {
        .consistent            = false,
 
        .query_user_list       = builtin_query_user_list,
        .enum_dom_groups       = builtin_enum_dom_groups,
-       .enum_local_groups     = common_enum_local_groups,
-       .name_to_sid           = common_name_to_sid,
-       .sid_to_name           = common_sid_to_name,
-       .rids_to_names         = common_rids_to_names,
+       .enum_local_groups     = sam_enum_local_groups,
+       .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     = common_lookup_usergroups,
-       .lookup_useraliases    = common_lookup_useraliases,
+       .lookup_usergroups     = sam_lookup_usergroups,
+       .lookup_useraliases    = sam_lookup_useraliases,
        .lookup_groupmem       = sam_lookup_groupmem,
-       .sequence_number       = common_sequence_number,
-       .lockout_policy        = common_lockout_policy,
-       .password_policy       = common_password_policy,
+       .sequence_number       = sam_sequence_number,
+       .lockout_policy        = sam_lockout_policy,
+       .password_policy       = sam_password_policy,
        .trusted_domains       = builtin_trusted_domains
 };
 
@@ -511,17 +1127,16 @@ struct winbindd_methods sam_passdb_methods = {
 
        .query_user_list       = sam_query_user_list,
        .enum_dom_groups       = sam_enum_dom_groups,
-       .enum_local_groups     = common_enum_local_groups,
-       .name_to_sid           = common_name_to_sid,
-       .sid_to_name           = common_sid_to_name,
-       .rids_to_names         = common_rids_to_names,
+       .enum_local_groups     = sam_enum_local_groups,
+       .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     = common_lookup_usergroups,
-       .lookup_useraliases    = common_lookup_useraliases,
+       .lookup_usergroups     = sam_lookup_usergroups,
+       .lookup_useraliases    = sam_lookup_useraliases,
        .lookup_groupmem       = sam_lookup_groupmem,
-       .sequence_number       = common_sequence_number,
-       .lockout_policy        = common_lockout_policy,
-       .password_policy       = common_password_policy,
+       .sequence_number       = sam_sequence_number,
+       .lockout_policy        = sam_lockout_policy,
+       .password_policy       = sam_password_policy,
        .trusted_domains       = sam_trusted_domains
 };
-#endif