s3-winbindd: no reason to call winbindd_can_contact_domain() three times in query_user().
[ira/wip.git] / source3 / winbindd / winbindd_rpc.c
index df80ad80297c8c3a2e5f18152aa0174581ba834f..ac5c3d2d93a66339406c82b8c97c68fa63e26373 100644 (file)
@@ -7,17 +7,17 @@
    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/>.
 */
 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;
@@ -88,7 +88,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)) {
@@ -106,7 +107,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
@@ -114,7 +115,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);
                }
@@ -130,7 +131,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;
@@ -201,7 +202,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;
 
@@ -265,20 +266,18 @@ 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;
 
@@ -310,13 +309,9 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
        DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
                 full_name?full_name:"", domain_name ));
 
-       result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
-       if (!NT_STATUS_IS_OK(result))
-               return result;
-
-       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;
 
@@ -331,40 +326,36 @@ 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];
@@ -384,19 +375,17 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
        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;
@@ -418,14 +407,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;
@@ -458,10 +447,10 @@ 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;
        struct netr_SamInfo3 *user;
@@ -471,53 +460,41 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
 
        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->base.rid);
                sid_compose(&user_info->group_sid, &domain->sid,
                            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;
@@ -525,7 +502,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);
 
@@ -564,8 +541,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;
@@ -597,7 +574,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;
@@ -636,13 +613,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;
@@ -736,14 +716,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;
@@ -821,7 +803,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;
 
@@ -854,11 +836,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;
@@ -946,7 +932,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;
 
@@ -1015,7 +1001,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;
        }
 
@@ -1047,7 +1033,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"));
 
@@ -1099,13 +1085,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));
@@ -1140,13 +1126,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));
@@ -1180,6 +1166,136 @@ 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;
+       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.
+        */
+       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. */
+       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 = {