Fix #6130: Don't crash in winbindd_rpc lookup_groupmem() on unmapped members
[ira/wip.git] / source3 / winbindd / winbindd_rpc.c
index edcdd5f0491f34026564ee1cd6b37730764a1c4c..2c0222e7c58e256e926aebf106a428d7c08f0c0f 100644 (file)
@@ -6,6 +6,7 @@
    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
@@ -150,19 +151,22 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
                return status;
 
        do {
-               struct acct_info *info2 = NULL;
+               struct samr_SamArray *sam_array = NULL;
                uint32 count = 0;
                TALLOC_CTX *mem_ctx2;
+               int g;
 
                mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
 
                /* start is updated by this call. */
-               status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol,
-                                                    &start,
-                                                    0xFFFF, /* buffer size? */
-                                                    &info2, &count);
+               status = rpccli_samr_EnumDomainGroups(cli, mem_ctx2,
+                                                     &dom_pol,
+                                                     &start,
+                                                     &sam_array,
+                                                     0xFFFF, /* buffer size? */
+                                                     &count);
 
-               if (!NT_STATUS_IS_OK(status) && 
+               if (!NT_STATUS_IS_OK(status) &&
                    !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
                        talloc_destroy(mem_ctx2);
                        break;
@@ -176,7 +180,13 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
                        return NT_STATUS_NO_MEMORY;
                }
 
-               memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
+               for (g=0; g < count; g++) {
+
+                       fstrcpy((*info)[*num_entries + g].acct_name,
+                               sam_array->entries[g].name.string);
+                       (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
+               }
+
                (*num_entries) += count;
                talloc_destroy(mem_ctx2);
        } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
@@ -211,18 +221,21 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
                return result;
 
        do {
-               struct acct_info *info2 = NULL;
+               struct samr_SamArray *sam_array = NULL;
                uint32 count = 0, start = *num_entries;
                TALLOC_CTX *mem_ctx2;
+               int g;
 
                mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
 
-               result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
-                                                     &start, 0xFFFF, &info2,
-                                                     &count);
-                                         
+               result = rpccli_samr_EnumDomainAliases(cli, mem_ctx2,
+                                                      &dom_pol,
+                                                      &start,
+                                                      &sam_array,
+                                                      0xFFFF, /* buffer size? */
+                                                      &count);
                if (!NT_STATUS_IS_OK(result) &&
-                   !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) 
+                   !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
                {
                        talloc_destroy(mem_ctx2);
                        return result;
@@ -236,7 +249,13 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
                        return NT_STATUS_NO_MEMORY;
                }
 
-               memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
+               for (g=0; g < count; g++) {
+
+                       fstrcpy((*info)[*num_entries + g].acct_name,
+                               sam_array->entries[g].name.string);
+                       (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
+               }
+
                (*num_entries) += count;
                talloc_destroy(mem_ctx2);
 
@@ -246,13 +265,13 @@ 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,
+                                 enum winbindd_cmd original_cmd,
+                                 const char *domain_name,
+                                 const char *name,
+                                 DOM_SID *sid,
+                                 enum lsa_SidType *type)
 {
        NTSTATUS result;
        DOM_SID *sids = NULL;
@@ -260,6 +279,8 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
        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);
@@ -275,9 +296,19 @@ 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);
+
+       /* Reset the full_name pointer if we mapped anytthing */
+
+       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 ));
+       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))
@@ -300,12 +331,12 @@ 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;
@@ -313,6 +344,8 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
        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 ));
@@ -337,20 +370,28 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
        *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;
@@ -392,8 +433,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];
                }
        }
@@ -409,9 +462,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        POLICY_HND dom_pol, user_pol;
-       SAM_USERINFO_CTR *ctr;
+       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)));
@@ -431,14 +484,14 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
                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->base.primary_gid);
                                
-               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_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);
                                                
@@ -480,8 +533,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
                return result;
 
        /* Get user info */
-       result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
-                                           0x15, &ctr);
+       result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
+                                          &user_pol,
+                                          0x15,
+                                          &info);
 
        rpccli_samr_Close(cli, mem_ctx, &user_pol);
 
@@ -490,11 +545,11 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
 
        sid_compose(&user_info->user_sid, &domain->sid, user_rid);
        sid_compose(&user_info->group_sid, &domain->sid,
-                   ctr->info.id21->group_rid);
-       user_info->acct_name = unistr2_to_ascii_talloc(mem_ctx, 
-                                           &ctr->info.id21->uni_user_name);
-       user_info->full_name = unistr2_to_ascii_talloc(mem_ctx, 
-                                           &ctr->info.id21->uni_full_name);
+                   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;
@@ -581,10 +636,13 @@ 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;
@@ -633,7 +691,7 @@ NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
 
                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) {
+                       if (!sid_array.sids[i].sid) {
                                TALLOC_FREE(sid_array.sids);
                                return NT_STATUS_NO_MEMORY;
                        }
@@ -691,7 +749,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
        uint32 *rid_mem = NULL;
        uint32 group_rid;
-       unsigned int j;
+       unsigned int j, r;
        struct rpc_pipe_client *cli;
        unsigned int orig_timeout;
        struct samr_RidTypeArray *rids = NULL;
@@ -729,14 +787,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);
 
@@ -770,38 +828,44 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
        if (*num_names>0 && (!*names || !*name_types))
                return NT_STATUS_NO_MEMORY;
 
-        for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
-                int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
-                uint32 tmp_num_names = 0;
-                char **tmp_names = NULL;
-                uint32 *tmp_types = NULL;
+       for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
+               int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
+               struct lsa_Strings tmp_names;
+               struct samr_Ids tmp_types;
 
-                /* Lookup a chunk of rids */
+               /* Lookup a chunk of rids */
 
-                result = rpccli_samr_lookup_rids(cli, mem_ctx,
-                                                &dom_pol,
-                                                num_lookup_rids,
-                                                &rid_mem[i],
-                                                &tmp_num_names,
-                                                &tmp_names, &tmp_types);
+               result = rpccli_samr_LookupRids(cli, mem_ctx,
+                                               &dom_pol,
+                                               num_lookup_rids,
+                                               &rid_mem[i],
+                                               &tmp_names,
+                                               &tmp_types);
 
                /* see if we have a real error (and yes the
                   STATUS_SOME_UNMAPPED is the one returned from 2k) */
-               
+
                 if (!NT_STATUS_IS_OK(result) &&
                    !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
                        return result;
-                       
-                /* Copy result into array.  The talloc system will take
-                   care of freeing the temporary arrays later on. */
 
-                memcpy(&(*names)[i], tmp_names, sizeof(char *) * 
-                       tmp_num_names);
+               /* Copy result into array.  The talloc system will take
+                  care of freeing the temporary arrays later on. */
 
-                memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
-                       tmp_num_names);
-               
-                total_names += tmp_num_names;
+               if (tmp_names.count != tmp_types.count) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+
+               for (r=0; r<tmp_names.count; 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;
+               }
         }
 
         *num_names = total_names;
@@ -958,7 +1022,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;
        }
 
@@ -1006,22 +1070,22 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        result = STATUS_MORE_ENTRIES;
 
        while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
-               uint32 start_idx, num;
-               char **tmp_names;
-               DOM_SID *tmp_sids;
+               uint32 start_idx;
                int i;
+               struct lsa_DomainList dom_list;
 
-               result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
-                                                  &lsa_policy, &enum_ctx,
-                                                  &num, &tmp_names,
-                                                  &tmp_sids);
+               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 = *num_domains;
-               *num_domains += num;
+               *num_domains += dom_list.count;
                *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
                                              char *, *num_domains);
                *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
@@ -1032,9 +1096,9 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                    (*alt_names == NULL))
                        return NT_STATUS_NO_MEMORY;
 
-               for (i=0; i<num; i++) {
-                       (*names)[start_idx+i] = tmp_names[i];
-                       (*dom_sids)[start_idx+i] = tmp_sids[i];
+               for (i=0; i<dom_list.count; i++) {
+                       (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
+                       (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
                        (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
                }
        }
@@ -1042,9 +1106,9 @@ 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;
@@ -1083,9 +1147,9 @@ 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;