s3-talloc Change TALLOC_ARRAY() to talloc_array()
[samba.git] / source3 / winbindd / winbindd_msrpc.c
index 5e897ebbac2bc048f0f13b7f8c5384633c7166ec..699320206a231a577e5982a1affde62f3a3e028d 100644 (file)
 #include "winbindd.h"
 #include "winbindd_rpc.h"
 
-#include "../librpc/gen_ndr/cli_samr.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
+#include "rpc_client/cli_pipe.h"
 #include "rpc_client/cli_samr.h"
-#include "../librpc/gen_ndr/cli_lsa.h"
 #include "rpc_client/cli_lsarpc.h"
+#include "../libcli/security/security.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
@@ -50,7 +51,7 @@ static NTSTATUS msrpc_query_user_list(struct winbindd_domain *domain,
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
 
-       DEBUG(3,("rpc_query_user_list\n"));
+       DEBUG(3, ("msrpc_query_user_list\n"));
 
        if (pnum_info) {
                *pnum_info = 0;
@@ -100,11 +101,11 @@ done:
 static NTSTATUS msrpc_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 wb_acct_info *info = NULL;
        uint32_t num_info = 0;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
@@ -159,11 +160,11 @@ done:
 static NTSTATUS msrpc_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 wb_acct_info *info = NULL;
        uint32_t num_info = 0;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
@@ -241,7 +242,7 @@ static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
                return NT_STATUS_NO_MEMORY;
        }
 
-       DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
+       DEBUG(3, ("msrpc_name_to_sid: name=%s\n", full_name));
 
        name_map_status = normalize_name_unmap(mem_ctx, full_name,
                                               &mapped_name);
@@ -288,7 +289,7 @@ static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
        NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
        char *mapped_name = NULL;
 
-       DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
+       DEBUG(3, ("msrpc_sid_to_name: %s for domain %s\n", sid_string_dbg(sid),
                 domain->name ));
 
        result = winbindd_lookup_sids(mem_ctx,
@@ -338,10 +339,10 @@ static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
        size_t i;
        char **ret_names;
 
-       DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
+       DEBUG(3, ("msrpc_rids_to_names: domain %s\n", domain->name ));
 
        if (num_rids) {
-               sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, num_rids);
+               sids = talloc_array(mem_ctx, struct dom_sid, num_rids);
                if (sids == NULL) {
                        return NT_STATUS_NO_MEMORY;
                }
@@ -392,124 +393,108 @@ static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
 }
 
 /* Lookup user information from a rid or username. */
-static NTSTATUS query_user(struct winbindd_domain *domain, 
+static NTSTATUS msrpc_query_user(struct winbindd_domain *domain,
                           TALLOC_CTX *mem_ctx, 
                           const struct dom_sid *user_sid,
                           struct wbint_userinfo *user_info)
 {
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       struct policy_handle dom_pol, user_pol;
-       union samr_UserInfo *info = NULL;
-       uint32 user_rid;
-       struct netr_SamInfo3 *user;
-       struct rpc_pipe_client *cli;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle dom_pol;
+       struct netr_SamInfo3 *user = NULL;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status;
 
-       DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
+       DEBUG(3,("msrpc_query_user sid=%s\n", sid_string_dbg(user_sid)));
 
-       if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
-               return NT_STATUS_UNSUCCESSFUL;
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       user_info->homedir = NULL;
-       user_info->shell = NULL;
-       user_info->primary_gid = (gid_t)-1;
+       if (user_info) {
+               user_info->homedir = NULL;
+               user_info->shell = NULL;
+               user_info->primary_gid = (gid_t)-1;
+       }
 
        /* try netsamlogon cache first */
-
-       if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) 
-       {
-
-               DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
+       if (winbindd_use_cache()) {
+               user = netsamlogon_cache_get(tmp_ctx, user_sid);
+       }
+       if (user != NULL) {
+               DEBUG(5,("msrpc_query_user: Cache lookup succeeded for %s\n",
                        sid_string_dbg(user_sid)));
 
                sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
                sid_compose(&user_info->group_sid, &domain->sid,
                            user->base.primary_gid);
 
-               user_info->acct_name = talloc_strdup(mem_ctx,
+               user_info->acct_name = talloc_strdup(user_info,
                                                     user->base.account_name.string);
-               user_info->full_name = talloc_strdup(mem_ctx,
+               user_info->full_name = talloc_strdup(user_info,
                                                     user->base.full_name.string);
 
-               TALLOC_FREE(user);
-
-               return NT_STATUS_OK;
+               status = NT_STATUS_OK;
+               goto done;
        }
 
        if ( !winbindd_can_contact_domain( domain ) ) {
                DEBUG(10,("query_user: No incoming trust for domain %s\n",
                          domain->name));
-               return NT_STATUS_OK;
+               /* Tell the cache manager not to remember this one */
+               status = NT_STATUS_SYNCHRONIZATION_REQUIRED;
+               goto done;
        }
 
        /* no cache; hit the wire */
+       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
 
-       result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
-       if (!NT_STATUS_IS_OK(result))
-               return result;
-
-       /* Get user handle */
-       result = rpccli_samr_OpenUser(cli, mem_ctx,
-                                     &dom_pol,
-                                     SEC_FLAG_MAXIMUM_ALLOWED,
-                                     user_rid,
-                                     &user_pol);
-
-       if (!NT_STATUS_IS_OK(result))
-               return result;
-
-       /* Get user info */
-       result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
-                                          &user_pol,
-                                          0x15,
-                                          &info);
-
-       rpccli_samr_Close(cli, mem_ctx, &user_pol);
-
-       if (!NT_STATUS_IS_OK(result))
-               return result;
-
-       sid_compose(&user_info->user_sid, &domain->sid, user_rid);
-       sid_compose(&user_info->group_sid, &domain->sid,
-                   info->info21.primary_gid);
-       user_info->acct_name = talloc_strdup(mem_ctx,
-                                            info->info21.account_name.string);
-       user_info->full_name = talloc_strdup(mem_ctx,
-                                            info->info21.full_name.string);
-       user_info->homedir = NULL;
-       user_info->shell = NULL;
-       user_info->primary_gid = (gid_t)-1;
+       status = rpc_query_user(tmp_ctx,
+                               samr_pipe,
+                               &dom_pol,
+                               &domain->sid,
+                               user_sid,
+                               user_info);
 
-       return NT_STATUS_OK;
-}                                   
+done:
+       TALLOC_FREE(tmp_ctx);
+       return status;
+}
 
 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
-static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
-                                 TALLOC_CTX *mem_ctx,
-                                 const struct dom_sid *user_sid,
-                                 uint32 *num_groups, struct dom_sid **user_grpsids)
+static NTSTATUS msrpc_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)
 {
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       struct policy_handle dom_pol, user_pol;
-       uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
-       struct samr_RidWithAttributeArray *rid_array = NULL;
-       unsigned int i;
-       uint32 user_rid;
-       struct rpc_pipe_client *cli;
-
-       DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
+       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;
 
-       if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
-               return NT_STATUS_UNSUCCESSFUL;
+       DEBUG(3,("msrpc_lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
 
-       *num_groups = 0;
-       *user_grpsids = NULL;
+       *pnum_groups = 0;
 
-       /* so lets see if we have a cached user_info_3 */
-       result = lookup_usergroups_cached(domain, mem_ctx, user_sid, 
-                                         num_groups, user_grpsids);
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       if (NT_STATUS_IS_OK(result)) {
-               return NT_STATUS_OK;
+       /* Check if we have a cached user_info_3 */
+       status = lookup_usergroups_cached(domain,
+                                         tmp_ctx,
+                                         user_sid,
+                                         &num_groups,
+                                         &user_grpsids);
+       if (NT_STATUS_IS_OK(status)) {
+               goto cached;
        }
 
        if ( !winbindd_can_contact_domain( domain ) ) {
@@ -517,46 +502,37 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
                          domain->name));
 
                /* Tell the cache manager not to remember this one */
-
-               return NT_STATUS_SYNCHRONIZATION_REQUIRED;
+               status = NT_STATUS_SYNCHRONIZATION_REQUIRED;
+               goto done;
        }
 
        /* no cache; hit the wire */
+       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
 
-       result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
-       if (!NT_STATUS_IS_OK(result))
-               return result;
-
-       /* Get user handle */
-       result = rpccli_samr_OpenUser(cli, mem_ctx,
-                                     &dom_pol,
-                                     des_access,
-                                     user_rid,
-                                     &user_pol);
-
-       if (!NT_STATUS_IS_OK(result))
-               return result;
-
-       /* Query user rids */
-       result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
-                                             &user_pol,
-                                             &rid_array);
-       *num_groups = rid_array->count;
-
-       rpccli_samr_Close(cli, mem_ctx, &user_pol);
-
-       if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
-               return result;
+       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;
+       }
 
-       (*user_grpsids) = TALLOC_ARRAY(mem_ctx, struct dom_sid, *num_groups);
-       if (!(*user_grpsids))
-               return NT_STATUS_NO_MEMORY;
+cached:
+       *pnum_groups = num_groups;
 
-       for (i=0;i<(*num_groups);i++) {
-               sid_compose(&((*user_grpsids)[i]), &domain->sid,
-                           rid_array->rids[i].rid);
+       if (puser_grpsids) {
+               *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
        }
 
+done:
+       TALLOC_FREE(tmp_ctx);
+       return status;
        return NT_STATUS_OK;
 }
 
@@ -565,111 +541,76 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
                                         TALLOC_CTX *mem_ctx,
                                         uint32 num_sids, const struct dom_sid *sids,
-                                        uint32 *num_aliases,
-                                        uint32 **alias_rids)
+                                        uint32 *pnum_aliases,
+                                        uint32 **palias_rids)
 {
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       struct rpc_pipe_client *samr_pipe;
        struct policy_handle dom_pol;
-       uint32 num_query_sids = 0;
-       int i;
-       struct rpc_pipe_client *cli;
-       struct samr_Ids alias_rids_query;
-       int rangesize = MAX_SAM_ENTRIES_W2K;
-       uint32 total_sids = 0;
-       int num_queries = 1;
+       uint32_t num_aliases = 0;
+       uint32_t *alias_rids = NULL;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status;
 
-       *num_aliases = 0;
-       *alias_rids = NULL;
+       DEBUG(3,("msrpc_lookup_useraliases\n"));
 
-       DEBUG(3,("rpc: lookup_useraliases\n"));
+       if (pnum_aliases) {
+               *pnum_aliases = 0;
+       }
 
-       if ( !winbindd_can_contact_domain( domain ) ) {
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!winbindd_can_contact_domain(domain)) {
                DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
                          domain->name));
-               return NT_STATUS_OK;
+               /* Tell the cache manager not to remember this one */
+               status = NT_STATUS_SYNCHRONIZATION_REQUIRED;
+               goto done;
        }
 
-       result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
-       if (!NT_STATUS_IS_OK(result))
-               return result;
-
-       do {
-               /* prepare query */
-               struct lsa_SidArray sid_array;
-
-               ZERO_STRUCT(sid_array);
-
-               num_query_sids = MIN(num_sids - total_sids, rangesize);
-
-               DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n", 
-                       num_queries, num_query_sids));  
-
-               if (num_query_sids) {
-                       sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
-                       if (sid_array.sids == NULL) {
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               } else {
-                       sid_array.sids = NULL;
-               }
-
-               for (i=0; i<num_query_sids; i++) {
-                       sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
-                       if (!sid_array.sids[i].sid) {
-                               TALLOC_FREE(sid_array.sids);
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               }
-               sid_array.num_sids = num_query_sids;
-
-               /* do request */
-               result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
-                                                       &dom_pol,
-                                                       &sid_array,
-                                                       &alias_rids_query);
-
-               if (!NT_STATUS_IS_OK(result)) {
-                       *num_aliases = 0;
-                       *alias_rids = NULL;
-                       TALLOC_FREE(sid_array.sids);
-                       goto done;
-               }
-
-               /* process output */
-
-               for (i=0; i<alias_rids_query.count; i++) {
-                       size_t na = *num_aliases;
-                       if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
-                                               alias_rids, &na)) {
-                               return NT_STATUS_NO_MEMORY;
-                       }
-                       *num_aliases = na;
-               }
-
-               TALLOC_FREE(sid_array.sids);
+       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
 
-               num_queries++;
+       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;
+       }
 
-       } while (total_sids < num_sids);
+       if (pnum_aliases) {
+               *pnum_aliases = num_aliases;
+       }
 
- done:
-       DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
-               "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
+       if (palias_rids) {
+               *palias_rids = talloc_move(mem_ctx, &alias_rids);
+       }
 
-       return result;
+done:
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
 
 /* Lookup group membership given a rid.   */
-static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
-                               TALLOC_CTX *mem_ctx,
-                               const struct dom_sid *group_sid,
-                               enum lsa_SidType type,
-                               uint32 *num_names,
-                               struct dom_sid **sid_mem, char ***names,
-                               uint32 **name_types)
+static NTSTATUS msrpc_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)
 {
-        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS status, result;
         uint32 i, total_names = 0;
         struct policy_handle dom_pol, group_pol;
         uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
@@ -678,9 +619,10 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
        unsigned int j, r;
        struct rpc_pipe_client *cli;
        unsigned int orig_timeout;
-       struct samr_RidTypeArray *rids = NULL;
+       struct samr_RidAttrArray *rids = NULL;
+       struct dcerpc_binding_handle *b;
 
-       DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
+       DEBUG(3,("msrpc_lookup_groupmem: %s sid=%s\n", domain->name,
                  sid_string_dbg(group_sid)));
 
        if ( !winbindd_can_contact_domain( domain ) ) {
@@ -698,14 +640,20 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
        if (!NT_STATUS_IS_OK(result))
                return result;
 
-        result = rpccli_samr_OpenGroup(cli, mem_ctx,
+       b = cli->binding_handle;
+
+       status = dcerpc_samr_OpenGroup(b, mem_ctx,
                                       &dom_pol,
                                       des_access,
                                       group_rid,
-                                      &group_pol);
-
-        if (!NT_STATUS_IS_OK(result))
+                                      &group_pol,
+                                      &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
                return result;
+       }
 
         /* Step #1: Get a list of user rids that are the members of the
            group. */
@@ -715,17 +663,26 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
 
        orig_timeout = rpccli_set_timeout(cli, 35000);
 
-        result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
+       status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
                                              &group_pol,
-                                             &rids);
+                                             &rids,
+                                             &result);
 
        /* And restore our original timeout. */
        rpccli_set_timeout(cli, orig_timeout);
 
-       rpccli_samr_Close(cli, mem_ctx, &group_pol);
+       {
+               NTSTATUS _result;
+               dcerpc_samr_Close(b, mem_ctx, &group_pol, &_result);
+       }
 
-        if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!NT_STATUS_IS_OK(result)) {
                return result;
+       }
 
        if (!rids || !rids->count) {
                names = NULL;
@@ -761,12 +718,16 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
 
                /* Lookup a chunk of rids */
 
-               result = rpccli_samr_LookupRids(cli, mem_ctx,
+               status = dcerpc_samr_LookupRids(b, mem_ctx,
                                                &dom_pol,
                                                num_lookup_rids,
                                                &rid_mem[i],
                                                &tmp_names,
-                                               &tmp_types);
+                                               &tmp_types,
+                                               &result);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
 
                /* see if we have a real error (and yes the
                   STATUS_SOME_UNMAPPED is the one returned from 2k) */
@@ -803,7 +764,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
 
 #include <ldap.h>
 
-static int get_ldap_seq(const char *server, int port, uint32 *seq)
+static int get_ldap_seq(const char *server, struct sockaddr_storage *ss, int port, uint32 *seq)
 {
        int ret = -1;
        struct timeval to;
@@ -819,7 +780,7 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq)
         * search timeout doesn't seem to apply to doing an open as well. JRA.
         */
 
-       ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
+       ldp = ldap_open_with_timeout(server, ss, port, lp_ldap_timeout());
        if (ldp == NULL)
                return -1;
 
@@ -828,7 +789,7 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq)
        to.tv_usec = 0;
 
        if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
-                          CONST_DISCARD(char **, attrs), 0, &to, &res))
+                          discard_const_p(char *, attrs), 0, &to, &res))
                goto done;
 
        if (ldap_count_entries(ldp, res) != 1)
@@ -863,7 +824,7 @@ static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
        char addr[INET6_ADDRSTRLEN];
 
        print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
-       if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
+       if ((ret = get_ldap_seq(addr, &domain->dcaddr, LDAP_PORT, seq)) == 0) {
                DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
                          "number for Domain (%s) from DC (%s)\n",
                        domain->name, addr));
@@ -874,44 +835,54 @@ static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
 #endif /* HAVE_LDAP */
 
 /* find the sequence number for a domain */
-static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
+static NTSTATUS msrpc_sequence_number(struct winbindd_domain *domain,
+                                     uint32_t *pseq)
 {
-       TALLOC_CTX *mem_ctx;
-       union samr_DomainInfo *info = NULL;
-       NTSTATUS result;
+       struct rpc_pipe_client *samr_pipe;
        struct policy_handle dom_pol;
-       bool got_seq_num = False;
-       struct rpc_pipe_client *cli;
+       uint32_t seq;
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS status;
+
+       DEBUG(3, ("msrpc_sequence_number: fetch sequence_number for %s\n", domain->name));
+
+       if (pseq) {
+               *pseq = DOM_SEQUENCE_NONE;
+       }
 
-       DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        if ( !winbindd_can_contact_domain( domain ) ) {
                DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
                          domain->name));
-               *seq = time(NULL);
-               return NT_STATUS_OK;
+               if (pseq) {
+                       *pseq = time(NULL);
+               }
+               status = NT_STATUS_OK;
+               goto done;
        }
 
-       *seq = DOM_SEQUENCE_NONE;
-
-       if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
-               return NT_STATUS_NO_MEMORY;
-
 #ifdef HAVE_LDAP
-       if ( domain->active_directory ) 
-       {
-               int res;
+       if (domain->active_directory) {
+               int rc;
 
                DEBUG(8,("using get_ldap_seq() to retrieve the "
                         "sequence number\n"));
 
-               res =  get_ldap_sequence_number( domain, seq );
-               if (res == 0)
-               {                       
-                       result = NT_STATUS_OK;
+               rc =  get_ldap_sequence_number(domain, &seq);
+               if (rc == 0) {
                        DEBUG(10,("domain_sequence_number: LDAP for "
                                  "domain %s is %u\n",
-                                 domain->name, *seq));
+                                 domain->name, seq));
+
+                       if (pseq) {
+                               *pseq = seq;
+                       }
+
+                       status = NT_STATUS_OK;
                        goto done;
                }
 
@@ -921,119 +892,73 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
        }
 #endif /* HAVE_LDAP */
 
-       result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
-       if (!NT_STATUS_IS_OK(result)) {
+       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
 
-       /* Query domain info */
-
-       result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
-                                            &dom_pol,
-                                            8,
-                                            &info);
-
-       if (NT_STATUS_IS_OK(result)) {
-               *seq = info->info8.sequence_num;
-               got_seq_num = True;
-               goto seq_num;
-       }
-
-       /* retry with info-level 2 in case the dc does not support info-level 8
-        * (like all older samba2 and samba3 dc's) - Guenther */
-
-       result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
-                                            &dom_pol,
-                                            2,
-                                            &info);
-
-       if (NT_STATUS_IS_OK(result)) {
-               *seq = info->general.sequence_num;
-               got_seq_num = True;
+       status = rpc_sequence_number(tmp_ctx,
+                                    samr_pipe,
+                                    &dom_pol,
+                                    domain->name,
+                                    &seq);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
        }
 
- seq_num:
-       if (got_seq_num) {
-               DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
-                         domain->name, (unsigned)*seq));
-       } else {
-               DEBUG(10,("domain_sequence_number: failed to get sequence "
-                         "number (%u) for domain %s\n",
-                         (unsigned)*seq, domain->name ));
+       if (pseq) {
+               *pseq = seq;
        }
 
-  done:
-
-       talloc_destroy(mem_ctx);
-
-       return result;
+done:
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
 /* get a list of trusted domains */
-static NTSTATUS trusted_domains(struct winbindd_domain *domain,
-                               TALLOC_CTX *mem_ctx,
-                               struct netr_DomainTrustList *trusts)
+static NTSTATUS msrpc_trusted_domains(struct winbindd_domain *domain,
+                                     TALLOC_CTX *mem_ctx,
+                                     struct netr_DomainTrustList *ptrust_list)
 {
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       uint32 enum_ctx = 0;
-       struct rpc_pipe_client *cli;
+       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;
 
-       DEBUG(3,("rpc: trusted_domains\n"));
-
-       ZERO_STRUCTP(trusts);
-
-       result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
-       if (!NT_STATUS_IS_OK(result))
-               return result;
-
-       result = STATUS_MORE_ENTRIES;
-
-       while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
-               uint32 start_idx;
-               int i;
-               struct lsa_DomainList dom_list;
-
-               result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
-                                                &lsa_policy,
-                                                &enum_ctx,
-                                                &dom_list,
-                                                (uint32_t)-1);
-
-               if (!NT_STATUS_IS_OK(result) &&
-                   !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
-                       break;
-
-               start_idx = trusts->count;
-               trusts->count += dom_list.count;
+       DEBUG(3,("msrpc_trusted_domains\n"));
 
-               trusts->array = talloc_realloc(
-                       mem_ctx, trusts->array, struct netr_DomainTrust,
-                       trusts->count);
-               if (trusts->array == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
+       if (ptrust_list) {
+               ZERO_STRUCTP(ptrust_list);
+       }
 
-               for (i=0; i<dom_list.count; i++) {
-                       struct netr_DomainTrust *trust = &trusts->array[i];
-                       struct dom_sid *sid;
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-                       ZERO_STRUCTP(trust);
+       status = cm_connect_lsa(domain, tmp_ctx, &lsa_pipe, &lsa_policy);
+       if (!NT_STATUS_IS_OK(status))
+               return status;
 
-                       trust->netbios_name = talloc_move(
-                               trusts->array,
-                               &dom_list.domains[i].name.string);
-                       trust->dns_name = NULL;
+       status = rpc_trusted_domains(tmp_ctx,
+                                    lsa_pipe,
+                                    &lsa_policy,
+                                    &num_trusts,
+                                    &trusts);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
 
-                       sid = talloc(trusts->array, struct dom_sid);
-                       if (sid == NULL) {
-                               return NT_STATUS_NO_MEMORY;
-                       }
-                       sid_copy(sid, dom_list.domains[i].sid);
-                       trust->sid = sid;
-               }
+       if (ptrust_list) {
+               ptrust_list->count = num_trusts;
+               ptrust_list->array = talloc_move(mem_ctx, &trusts);
        }
-       return result;
+
+done:
+       TALLOC_FREE(tmp_ctx);
+       return status;
 }
 
 /* find the lockout policy for a domain */
@@ -1041,12 +966,13 @@ static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
                                     TALLOC_CTX *mem_ctx,
                                     struct samr_DomInfo12 *lockout_policy)
 {
-       NTSTATUS result;
+       NTSTATUS status, result;
        struct rpc_pipe_client *cli;
        struct policy_handle dom_pol;
        union samr_DomainInfo *info = NULL;
+       struct dcerpc_binding_handle *b;
 
-       DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
+       DEBUG(3, ("msrpc_lockout_policy: fetch lockout policy for %s\n", domain->name));
 
        if ( !winbindd_can_contact_domain( domain ) ) {
                DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
@@ -1054,16 +980,23 @@ static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
                return NT_STATUS_NOT_SUPPORTED;
        }
 
-       result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
-       if (!NT_STATUS_IS_OK(result)) {
+       status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
+       if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
 
-       result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
+       b = cli->binding_handle;
+
+       status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
                                             &dom_pol,
-                                            12,
-                                            &info);
+                                            DomainLockoutInformation,
+                                            &info,
+                                            &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
        if (!NT_STATUS_IS_OK(result)) {
+               status = result;
                goto done;
        }
 
@@ -1074,7 +1007,7 @@ static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
 
   done:
 
-       return result;
+       return status;
 }
 
 /* find the password policy for a domain */
@@ -1082,12 +1015,14 @@ static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
                                      TALLOC_CTX *mem_ctx,
                                      struct samr_DomInfo1 *password_policy)
 {
-       NTSTATUS result;
+       NTSTATUS status, result;
        struct rpc_pipe_client *cli;
        struct policy_handle dom_pol;
        union samr_DomainInfo *info = NULL;
+       struct dcerpc_binding_handle *b;
 
-       DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
+       DEBUG(3, ("msrpc_password_policy: fetch password policy for %s\n",
+                 domain->name));
 
        if ( !winbindd_can_contact_domain( domain ) ) {
                DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
@@ -1095,15 +1030,21 @@ static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
                return NT_STATUS_NOT_SUPPORTED;
        }
 
-       result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
-       if (!NT_STATUS_IS_OK(result)) {
+       status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
+       if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
 
-       result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
+       b = cli->binding_handle;
+
+       status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
                                             &dom_pol,
-                                            1,
-                                            &info);
+                                            DomainPasswordInformation,
+                                            &info,
+                                            &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
@@ -1115,17 +1056,18 @@ static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
 
   done:
 
-       return result;
+       return status;
 }
 
-typedef NTSTATUS (*lookup_sids_fn_t)(struct rpc_pipe_client *cli,
+typedef NTSTATUS (*lookup_sids_fn_t)(struct dcerpc_binding_handle *h,
                                     TALLOC_CTX *mem_ctx,
                                     struct policy_handle *pol,
                                     int num_sids,
                                     const struct dom_sid *sids,
                                     char ***pdomains,
                                     char ***pnames,
-                                    enum lsa_SidType **ptypes);
+                                    enum lsa_SidType **ptypes,
+                                    NTSTATUS *result);
 
 NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
                              struct winbindd_domain *domain,
@@ -1136,15 +1078,17 @@ NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
                              enum lsa_SidType **types)
 {
        NTSTATUS status;
+       NTSTATUS result;
        struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
        struct policy_handle lsa_policy;
        unsigned int orig_timeout;
-       lookup_sids_fn_t lookup_sids_fn = rpccli_lsa_lookup_sids;
+       lookup_sids_fn_t lookup_sids_fn = dcerpc_lsa_lookup_sids;
 
        if (domain->can_do_ncacn_ip_tcp) {
                status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
                if (NT_STATUS_IS_OK(status)) {
-                       lookup_sids_fn = rpccli_lsa_lookup_sids3;
+                       lookup_sids_fn = dcerpc_lsa_lookup_sids3;
                        goto lookup;
                }
                domain->can_do_ncacn_ip_tcp = false;
@@ -1156,41 +1100,61 @@ NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
        }
 
  lookup:
+       b = cli->binding_handle;
+
        /*
         * This call can take a long time
         * allow the server to time out.
         * 35 seconds should do it.
         */
-       orig_timeout = rpccli_set_timeout(cli, 35000);
+       orig_timeout = dcerpc_binding_handle_set_timeout(b, 35000);
 
-       status = lookup_sids_fn(cli,
+       status = lookup_sids_fn(b,
                                mem_ctx,
                                &lsa_policy,
                                num_sids,
                                sids,
                                domains,
                                names,
-                               types);
+                               types,
+                               &result);
 
        /* And restore our original timeout. */
-       rpccli_set_timeout(cli, orig_timeout);
+       dcerpc_binding_handle_set_timeout(b, orig_timeout);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
+               /*
+                * This can happen if the schannel key is not
+                * valid anymore, we need to invalidate the
+                * all connections to the dc and reestablish
+                * a netlogon connection first.
+                */
+               invalidate_cm_connection(&domain->conn);
+               status = NT_STATUS_ACCESS_DENIED;
+       }
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       return status;
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       return NT_STATUS_OK;
 }
 
-typedef NTSTATUS (*lookup_names_fn_t)(struct rpc_pipe_client *cli,
+typedef NTSTATUS (*lookup_names_fn_t)(struct dcerpc_binding_handle *h,
                                      TALLOC_CTX *mem_ctx,
                                      struct policy_handle *pol,
-                                     int num_names,
+                                     uint32_t num_names,
                                      const char **names,
                                      const char ***dom_names,
-                                     int level,
+                                     enum lsa_LookupNamesLevel level,
                                      struct dom_sid **sids,
-                                     enum lsa_SidType **types);
+                                     enum lsa_SidType **types,
+                                     NTSTATUS *result);
 
 NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
                               struct winbindd_domain *domain,
@@ -1201,15 +1165,17 @@ NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
                               enum lsa_SidType **types)
 {
        NTSTATUS status;
+       NTSTATUS result;
        struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
        struct policy_handle lsa_policy;
        unsigned int orig_timeout = 0;
-       lookup_names_fn_t lookup_names_fn = rpccli_lsa_lookup_names;
+       lookup_names_fn_t lookup_names_fn = dcerpc_lsa_lookup_names;
 
        if (domain->can_do_ncacn_ip_tcp) {
                status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
                if (NT_STATUS_IS_OK(status)) {
-                       lookup_names_fn = rpccli_lsa_lookup_names4;
+                       lookup_names_fn = dcerpc_lsa_lookup_names4;
                        goto lookup;
                }
                domain->can_do_ncacn_ip_tcp = false;
@@ -1221,15 +1187,16 @@ NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
        }
 
  lookup:
+       b = cli->binding_handle;
 
        /*
         * This call can take a long time
         * allow the server to time out.
         * 35 seconds should do it.
         */
-       orig_timeout = rpccli_set_timeout(cli, 35000);
+       orig_timeout = dcerpc_binding_handle_set_timeout(b, 35000);
 
-       status = lookup_names_fn(cli,
+       status = lookup_names_fn(b,
                                 mem_ctx,
                                 &lsa_policy,
                                 num_names,
@@ -1237,16 +1204,33 @@ NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
                                 domains,
                                 1,
                                 sids,
-                                types);
+                                types,
+                                &result);
 
        /* And restore our original timeout. */
-       rpccli_set_timeout(cli, orig_timeout);
+       dcerpc_binding_handle_set_timeout(b, orig_timeout);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
+               /*
+                * This can happen if the schannel key is not
+                * valid anymore, we need to invalidate the
+                * all connections to the dc and reestablish
+                * a netlogon connection first.
+                */
+               invalidate_cm_connection(&domain->conn);
+               status = NT_STATUS_ACCESS_DENIED;
+       }
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       return status;
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       return NT_STATUS_OK;
 }
 
 /* the rpc backend methods are exposed via this structure */
@@ -1258,12 +1242,12 @@ struct winbindd_methods msrpc_methods = {
        msrpc_name_to_sid,
        msrpc_sid_to_name,
        msrpc_rids_to_names,
-       query_user,
-       lookup_usergroups,
+       msrpc_query_user,
+       msrpc_lookup_usergroups,
        msrpc_lookup_useraliases,
-       lookup_groupmem,
-       sequence_number,
+       msrpc_lookup_groupmem,
+       msrpc_sequence_number,
        msrpc_lockout_policy,
        msrpc_password_policy,
-       trusted_domains,
+       msrpc_trusted_domains,
 };