s3: Fix a bogus uninitialized variable warning
[samba.git] / source3 / winbindd / winbindd_rpc.c
index 585923410ff505e9740f7d451a902d18587b4fb7..f504b907034dbcdd585557753c5dc75cc23a6403 100644 (file)
@@ -6,23 +6,26 @@
    Copyright (C) Tim Potter 2000-2001,2003
    Copyright (C) Andrew Tridgell 2001
    Copyright (C) Volker Lendecke 2005
-   
+   Copyright (C) Guenther Deschner 2008 (pidl conversion)
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "winbindd.h"
+#include "../librpc/gen_ndr/cli_samr.h"
+#include "../librpc/gen_ndr/cli_lsa.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 static NTSTATUS query_user_list(struct winbindd_domain *domain,
                               TALLOC_CTX *mem_ctx,
                               uint32 *num_entries, 
-                              WINBIND_USERINFO **info)
+                              struct wbint_userinfo **info)
 {
        NTSTATUS result;
-       POLICY_HND dom_pol;
+       struct policy_handle dom_pol;
        unsigned int i, start_idx;
        uint32 loop_count;
        struct rpc_pipe_client *cli;
@@ -87,7 +90,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
 
                *num_entries += num_dom_users;
 
-               *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
+               *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
+                                            struct wbint_userinfo,
                                             *num_entries);
 
                if (!(*info)) {
@@ -105,7 +109,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
                        (*info)[i].homedir = NULL;
                        (*info)[i].shell = NULL;
                        sid_compose(&(*info)[i].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
@@ -113,7 +117,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
                           This should really be made into a 'winbind
                           force group' smb.conf parameter or
                           something like that. */
-                          
+
                        sid_compose(&(*info)[i].group_sid, &domain->sid, 
                                    DOMAIN_GROUP_RID_USERS);
                }
@@ -129,7 +133,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
                                uint32 *num_entries, 
                                struct acct_info **info)
 {
-       POLICY_HND dom_pol;
+       struct policy_handle dom_pol;
        NTSTATUS status;
        uint32 start = 0;
        struct rpc_pipe_client *cli;
@@ -200,7 +204,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
                                uint32 *num_entries, 
                                struct acct_info **info)
 {
-       POLICY_HND dom_pol;
+       struct policy_handle dom_pol;
        NTSTATUS result;
        struct rpc_pipe_client *cli;
 
@@ -264,20 +268,20 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
 }
 
 /* convert a single name to a sid in a domain */
-NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
-                          TALLOC_CTX *mem_ctx,
-                          enum winbindd_cmd original_cmd,
-                          const char *domain_name,
-                          const char *name,
-                          DOM_SID *sid,
-                          enum lsa_SidType *type)
+static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
+                                 TALLOC_CTX *mem_ctx,
+                                 const char *domain_name,
+                                 const char *name,
+                                 uint32_t flags,
+                                 DOM_SID *sid,
+                                 enum lsa_SidType *type)
 {
        NTSTATUS result;
        DOM_SID *sids = NULL;
        enum lsa_SidType *types = NULL;
        char *full_name = NULL;
-       struct rpc_pipe_client *cli;
-       POLICY_HND lsa_policy;
+       NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
+       char *mapped_name = NULL;
 
        if (name == NULL || *name=='\0') {
                full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
@@ -293,17 +297,23 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
 
        DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
 
-       ws_name_return( full_name, WB_REPLACE_CHAR );
+       name_map_status = normalize_name_unmap(mem_ctx, full_name,
+                                              &mapped_name);
 
-       DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
+       /* Reset the full_name pointer if we mapped anytthing */
 
-       result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
-       if (!NT_STATUS_IS_OK(result))
-               return result;
+       if (NT_STATUS_IS_OK(name_map_status) ||
+           NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
+       {
+               full_name = mapped_name;
+       }
+
+       DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
+                full_name?full_name:"", domain_name ));
 
-       result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1, 
-                                        (const char**) &full_name, NULL, 1, &sids, &types);
-        
+       result = winbindd_lookup_names(mem_ctx, domain, 1,
+                                      (const char **)&full_name, NULL,
+                                      &sids, &types);
        if (!NT_STATUS_IS_OK(result))
                return result;
 
@@ -318,62 +328,66 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
 /*
   convert a domain SID to a user or group name
 */
-NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
-                           TALLOC_CTX *mem_ctx,
-                           const DOM_SID *sid,
-                           char **domain_name,
-                           char **name,
-                           enum lsa_SidType *type)
+static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
+                                 TALLOC_CTX *mem_ctx,
+                                 const DOM_SID *sid,
+                                 char **domain_name,
+                                 char **name,
+                                 enum lsa_SidType *type)
 {
        char **domains;
        char **names;
        enum lsa_SidType *types = NULL;
        NTSTATUS result;
-       struct rpc_pipe_client *cli;
-       POLICY_HND lsa_policy;
+       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),
                 domain->name ));
 
-       result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
+       result = winbindd_lookup_sids(mem_ctx,
+                                     domain,
+                                     1,
+                                     sid,
+                                     &domains,
+                                     &names,
+                                     &types);
        if (!NT_STATUS_IS_OK(result)) {
-               DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n",
-                        nt_errstr(result)));           
+               DEBUG(2,("msrpc_sid_to_name: failed to lookup sids: %s\n",
+                       nt_errstr(result)));
                return result;
        }
-       
 
-       result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
-                                       1, sid, &domains, &names, &types);
-       if (!NT_STATUS_IS_OK(result)) {         
-               DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids()  failed (%s)\n",
-                        nt_errstr(result)));           
-               return result;
-       }
 
        *type = (enum lsa_SidType)types[0];
        *domain_name = domains[0];
        *name = names[0];
 
-       ws_name_replace( *name, WB_REPLACE_CHAR );      
-               
        DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
+
+       name_map_status = normalize_name_map(mem_ctx, domain, *name,
+                                            &mapped_name);
+       if (NT_STATUS_IS_OK(name_map_status) ||
+           NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
+       {
+               *name = mapped_name;
+               DEBUG(5,("returning mapped name -- %s\n", *name));
+       }
+
        return NT_STATUS_OK;
 }
 
-NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
-                            TALLOC_CTX *mem_ctx,
-                            const DOM_SID *sid,
-                            uint32 *rids,
-                            size_t num_rids,
-                            char **domain_name,
-                            char ***names,
-                            enum lsa_SidType **types)
+static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
+                                   TALLOC_CTX *mem_ctx,
+                                   const DOM_SID *sid,
+                                   uint32 *rids,
+                                   size_t num_rids,
+                                   char **domain_name,
+                                   char ***names,
+                                   enum lsa_SidType **types)
 {
        char **domains;
        NTSTATUS result;
-       struct rpc_pipe_client *cli;
-       POLICY_HND lsa_policy;
        DOM_SID *sids;
        size_t i;
        char **ret_names;
@@ -395,14 +409,14 @@ NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
                }
        }
 
-       result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
-       if (!NT_STATUS_IS_OK(result)) {
-               return result;
-       }
+       result = winbindd_lookup_sids(mem_ctx,
+                                     domain,
+                                     num_rids,
+                                     sids,
+                                     &domains,
+                                     names,
+                                     types);
 
-       result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
-                                       num_rids, sids, &domains,
-                                       names, types);
        if (!NT_STATUS_IS_OK(result) &&
            !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
                return result;
@@ -410,8 +424,20 @@ NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
 
        ret_names = *names;
        for (i=0; i<num_rids; i++) {
+               NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
+               char *mapped_name = NULL;
+
                if ((*types)[i] != SID_NAME_UNKNOWN) {
-                       ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
+                       name_map_status = normalize_name_map(mem_ctx,
+                                                            domain,
+                                                            ret_names[i],
+                                                            &mapped_name);
+                       if (NT_STATUS_IS_OK(name_map_status) ||
+                           NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
+                       {
+                               ret_names[i] = mapped_name;
+                       }
+
                        *domain_name = domains[i];
                }
        }
@@ -423,66 +449,54 @@ NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
 static NTSTATUS query_user(struct winbindd_domain *domain, 
                           TALLOC_CTX *mem_ctx, 
                           const DOM_SID *user_sid, 
-                          WINBIND_USERINFO *user_info)
+                          struct wbint_userinfo *user_info)
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       POLICY_HND dom_pol, user_pol;
+       struct policy_handle dom_pol, user_pol;
        union samr_UserInfo *info = NULL;
        uint32 user_rid;
-       NET_USER_INFO_3 *user;
+       struct netr_SamInfo3 *user;
        struct rpc_pipe_client *cli;
 
        DEBUG(3,("rpc: 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;
-       
+
        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", 
                        sid_string_dbg(user_sid)));
 
-               sid_compose(&user_info->user_sid, &domain->sid, user->user_rid);
+               sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
                sid_compose(&user_info->group_sid, &domain->sid,
-                           user->group_rid);
-                               
-               user_info->acct_name = unistr2_to_ascii_talloc(mem_ctx,
-                                                   &user->uni_user_name);
-               user_info->full_name = unistr2_to_ascii_talloc(mem_ctx,
-                                                   &user->uni_full_name);
-               
+                           user->base.primary_gid);
+
+               user_info->acct_name = talloc_strdup(mem_ctx,
+                                                    user->base.account_name.string);
+               user_info->full_name = talloc_strdup(mem_ctx,
+                                                    user->base.full_name.string);
+
                TALLOC_FREE(user);
-                                               
-               return NT_STATUS_OK;
-       }
-                               
-       if ( !winbindd_can_contact_domain( domain ) ) {
-               DEBUG(10,("query_user: No incoming trust for domain %s\n",
-                         domain->name));
-               return NT_STATUS_OK;
-       }
-       
-       if ( !winbindd_can_contact_domain( domain ) ) {
-               DEBUG(10,("query_user: No incoming trust for domain %s\n",
-                         domain->name));
+
                return NT_STATUS_OK;
        }
-       
+
        if ( !winbindd_can_contact_domain( domain ) ) {
                DEBUG(10,("query_user: No incoming trust for domain %s\n",
                          domain->name));
                return NT_STATUS_OK;
        }
-       
+
        /* no cache; hit the wire */
-               
+
        result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
        if (!NT_STATUS_IS_OK(result))
                return result;
@@ -490,7 +504,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
        /* Get user handle */
        result = rpccli_samr_OpenUser(cli, mem_ctx,
                                      &dom_pol,
-                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                     SEC_FLAG_MAXIMUM_ALLOWED,
                                      user_rid,
                                      &user_pol);
 
@@ -529,8 +543,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
                                  uint32 *num_groups, DOM_SID **user_grpsids)
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       POLICY_HND dom_pol, user_pol;
-       uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       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;
@@ -562,7 +576,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
        }
 
        /* no cache; hit the wire */
-       
+
        result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
        if (!NT_STATUS_IS_OK(result))
                return result;
@@ -601,13 +615,16 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
        return NT_STATUS_OK;
 }
 
-NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
-                                 TALLOC_CTX *mem_ctx,
-                                 uint32 num_sids, const DOM_SID *sids,
-                                 uint32 *num_aliases, uint32 **alias_rids)
+#define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
+
+static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
+                                        TALLOC_CTX *mem_ctx,
+                                        uint32 num_sids, const DOM_SID *sids,
+                                        uint32 *num_aliases,
+                                        uint32 **alias_rids)
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       POLICY_HND dom_pol;
+       struct policy_handle dom_pol;
        uint32 num_query_sids = 0;
        int i;
        struct rpc_pipe_client *cli;
@@ -701,14 +718,16 @@ NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
 /* Lookup group membership given a rid.   */
 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
-                               const DOM_SID *group_sid, uint32 *num_names, 
+                               const DOM_SID *group_sid,
+                               enum lsa_SidType type,
+                               uint32 *num_names,
                                DOM_SID **sid_mem, char ***names, 
                                uint32 **name_types)
 {
         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
         uint32 i, total_names = 0;
-        POLICY_HND dom_pol, group_pol;
-        uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
+        struct policy_handle dom_pol, group_pol;
+        uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
        uint32 *rid_mem = NULL;
        uint32 group_rid;
        unsigned int j, r;
@@ -749,14 +768,14 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
        /* This call can take a long time - allow the server to time out.
           35 seconds should do it. */
 
-       orig_timeout = cli_set_timeout(cli->cli, 35000);
+       orig_timeout = rpccli_set_timeout(cli, 35000);
 
         result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
                                              &group_pol,
                                              &rids);
 
        /* And restore our original timeout. */
-       cli_set_timeout(cli->cli, orig_timeout);
+       rpccli_set_timeout(cli, orig_timeout);
 
        rpccli_samr_Close(cli, mem_ctx, &group_pol);
 
@@ -786,7 +805,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
 
        for (j=0;j<(*num_names);j++)
                sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
-       
+
        if (*num_names>0 && (!*names || !*name_types))
                return NT_STATUS_NO_MEMORY;
 
@@ -819,11 +838,15 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
                }
 
                for (r=0; r<tmp_names.count; r++) {
-                       (*names)[i+r] = CONST_DISCARD(char *, tmp_names.names[r].string);
-                       (*name_types)[i+r] = tmp_types.ids[r];
+                       if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
+                               continue;
+                       }
+                       (*names)[total_names] = fill_domain_username_talloc(
+                               mem_ctx, domain->name,
+                               tmp_names.names[r].string, true);
+                       (*name_types)[total_names] = tmp_types.ids[r];
+                       total_names += 1;
                }
-
-               total_names += tmp_names.count;
         }
 
         *num_names = total_names;
@@ -911,7 +934,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
        TALLOC_CTX *mem_ctx;
        union samr_DomainInfo *info = NULL;
        NTSTATUS result;
-       POLICY_HND dom_pol;
+       struct policy_handle dom_pol;
        bool got_seq_num = False;
        struct rpc_pipe_client *cli;
 
@@ -980,7 +1003,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
                                             &info);
 
        if (NT_STATUS_IS_OK(result)) {
-               *seq = info->info2.sequence_num;
+               *seq = info->general.sequence_num;
                got_seq_num = True;
        }
 
@@ -1012,7 +1035,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        uint32 enum_ctx = 0;
        struct rpc_pipe_client *cli;
-       POLICY_HND lsa_policy;
+       struct policy_handle lsa_policy;
 
        DEBUG(3,("rpc: trusted_domains\n"));
 
@@ -1064,13 +1087,13 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
 }
 
 /* find the lockout policy for a domain */
-NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
-                             TALLOC_CTX *mem_ctx,
-                             struct samr_DomInfo12 *lockout_policy)
+static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
+                                    TALLOC_CTX *mem_ctx,
+                                    struct samr_DomInfo12 *lockout_policy)
 {
        NTSTATUS result;
        struct rpc_pipe_client *cli;
-       POLICY_HND dom_pol;
+       struct policy_handle dom_pol;
        union samr_DomainInfo *info = NULL;
 
        DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
@@ -1105,13 +1128,13 @@ NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
 }
 
 /* find the password policy for a domain */
-NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
-                              TALLOC_CTX *mem_ctx,
-                              struct samr_DomInfo1 *password_policy)
+static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
+                                     TALLOC_CTX *mem_ctx,
+                                     struct samr_DomInfo1 *password_policy)
 {
        NTSTATUS result;
        struct rpc_pipe_client *cli;
-       POLICY_HND dom_pol;
+       struct policy_handle dom_pol;
        union samr_DomainInfo *info = NULL;
 
        DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
@@ -1145,6 +1168,142 @@ NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
        return result;
 }
 
+typedef NTSTATUS (*lookup_sids_fn_t)(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx,
+                                    struct policy_handle *pol,
+                                    int num_sids,
+                                    const DOM_SID *sids,
+                                    char ***pdomains,
+                                    char ***pnames,
+                                    enum lsa_SidType **ptypes);
+
+NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
+                             struct winbindd_domain *domain,
+                             uint32_t num_sids,
+                             const struct dom_sid *sids,
+                             char ***domains,
+                             char ***names,
+                             enum lsa_SidType **types)
+{
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct policy_handle lsa_policy;
+       unsigned int orig_timeout;
+       lookup_sids_fn_t lookup_sids_fn = rpccli_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;
+                       goto lookup;
+               }
+               domain->can_do_ncacn_ip_tcp = false;
+       }
+       status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+ lookup:
+       /*
+        * 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);
+
+       status = lookup_sids_fn(cli,
+                               mem_ctx,
+                               &lsa_policy,
+                               num_sids,
+                               sids,
+                               domains,
+                               names,
+                               types);
+
+       /* And restore our original timeout. */
+       rpccli_set_timeout(cli, orig_timeout);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       return status;
+}
+
+typedef NTSTATUS (*lookup_names_fn_t)(struct rpc_pipe_client *cli,
+                                     TALLOC_CTX *mem_ctx,
+                                     struct policy_handle *pol,
+                                     int num_names,
+                                     const char **names,
+                                     const char ***dom_names,
+                                     int level,
+                                     struct dom_sid **sids,
+                                     enum lsa_SidType **types);
+
+NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
+                              struct winbindd_domain *domain,
+                              uint32_t num_names,
+                              const char **names,
+                              const char ***domains,
+                              struct dom_sid **sids,
+                              enum lsa_SidType **types)
+{
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct policy_handle lsa_policy;
+       unsigned int orig_timeout = 0;
+       lookup_names_fn_t lookup_names_fn = rpccli_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;
+                       goto lookup;
+               }
+               domain->can_do_ncacn_ip_tcp = false;
+       }
+       status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+ lookup:
+
+       /*
+        * This call can take a long time
+        * allow the server to time out.
+        * 35 seconds should do it.
+        * NB
+        * only do this when the undelying transport is named pipe.
+        */
+       if (cli->transport->transport == NCACN_NP) {
+               orig_timeout = rpccli_set_timeout(cli, 35000);
+       }
+
+       status = lookup_names_fn(cli,
+                                mem_ctx,
+                                &lsa_policy,
+                                num_names,
+                                (const char **) names,
+                                domains,
+                                1,
+                                sids,
+                                types);
+
+       /* And restore our original timeout. */
+       if (cli->transport->transport == NCACN_NP) {
+               rpccli_set_timeout(cli, orig_timeout);
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       return status;
+}
 
 /* the rpc backend methods are exposed via this structure */
 struct winbindd_methods msrpc_methods = {