Fix winbindd crash bug with trusted domains. Bug #5736
[ira/wip.git] / source3 / winbindd / winbindd_ads.c
index 9bc310474cdb75e82d92426300773c39a50cb8b3..c7f730e3974b0f4c8b92e2c8a29ee09e4dea3ca4 100644 (file)
@@ -393,7 +393,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
         * using LDAP.
         *
         * if we ever need to enumerate domain local groups separately, 
-        * then this the optimization in enum_dom_groups() will need 
+        * then this optimization in enum_dom_groups() will need
         * to be split out
         */
        *num_entries = 0;
@@ -421,7 +421,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
        char *sidstr;
        uint32 group_rid;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-       NET_USER_INFO_3 *user;
+       struct netr_SamInfo3 *user = NULL;
 
        DEBUG(3,("ads: query_user\n"));
 
@@ -437,11 +437,11 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
                DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
                         sid_string_dbg(sid)));
 
-               sid_compose(&info->user_sid, &domain->sid, user->user_rid);
-               sid_compose(&info->group_sid, &domain->sid, user->group_rid);
+               sid_compose(&info->user_sid, &domain->sid, user->base.rid);
+               sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid);
                                
-               info->acct_name = unistr2_to_ascii_talloc(mem_ctx, &user->uni_user_name);
-               info->full_name = unistr2_to_ascii_talloc(mem_ctx, &user->uni_full_name);
+               info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string);
+               info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string);
                
                nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL, 
                              &info->homedir, &info->shell, &info->full_name, 
@@ -1161,7 +1161,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        int                     i;
        uint32                  flags;  
        struct rpc_pipe_client *cli;
-       uint32                 fr_flags = (DS_DOMAIN_IN_FOREST | DS_DOMAIN_TREE_ROOT);  
+       uint32                 fr_flags = (NETR_TRUST_FLAG_IN_FOREST | NETR_TRUST_FLAG_TREEROOT);
        int ret_count;
        
        DEBUG(3,("ads: trusted_domains\n"));
@@ -1178,11 +1178,11 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        if ( domain->primary ||
                ((domain->domain_flags&fr_flags) == fr_flags) ) 
        {
-               flags = DS_DOMAIN_DIRECT_OUTBOUND | 
-                       DS_DOMAIN_DIRECT_INBOUND | 
-                       DS_DOMAIN_IN_FOREST;
+               flags = NETR_TRUST_FLAG_OUTBOUND |
+                       NETR_TRUST_FLAG_INBOUND |
+                       NETR_TRUST_FLAG_IN_FOREST;
        } else {
-               flags = DS_DOMAIN_IN_FOREST;
+               flags = NETR_TRUST_FLAG_IN_FOREST;
        }       
 
        result = cm_connect_netlogon(domain, &cli);
@@ -1195,7 +1195,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        }
 
        result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
-                                                     cli->cli->desthost,
+                                                     cli->desthost,
                                                      flags,
                                                      &trusts,
                                                      NULL);
@@ -1225,12 +1225,14 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                for (i = 0; i < trusts.count; i++) {
                        struct winbindd_domain d;
                        
+                       ZERO_STRUCT(d);
+
                        /* drop external trusts if this is not our primary 
                           domain.  This means that the returned number of 
                           domains may be less that the ones actually trusted
                           by the DC. */
 
-                       if ( (trusts.array[i].trust_attributes == DS_DOMAIN_TRUST_ATTRIB_QUARANTINED_DOMAIN) &&
+                       if ( (trusts.array[i].trust_attributes == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
                             !domain->primary ) 
                        {
                                DEBUG(10,("trusted_domains: Skipping external trusted domain "
@@ -1239,42 +1241,76 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                continue;                               
                        }
                        
-                       (*names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].netbios_name);
-                       (*alt_names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].dns_name);
-                       sid_copy(&(*dom_sids)[ret_count], trusts.array[i].sid);
+                       (*names)[ret_count] = talloc_strdup(mem_ctx, trusts.array[i].netbios_name);
+                       (*alt_names)[ret_count] = talloc_strdup(mem_ctx, trusts.array[i].dns_name);
+                       if ((*names)[ret_count] == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       if (trusts.array[i].sid) {
+                               sid_copy(&(*dom_sids)[ret_count], trusts.array[i].sid);
+                       } else {
+                               sid_copy(&(*dom_sids)[ret_count], &global_sid_NULL);
+                       }
 
                        /* add to the trusted domain cache */
 
                        fstrcpy( d.name,  trusts.array[i].netbios_name);
                        fstrcpy( d.alt_name, trusts.array[i].dns_name);
-                       sid_copy( &d.sid, trusts.array[i].sid);
-
-                       /* This gets a little tricky.  If we are
-                          following a transitive forest trust, then
-                          innerit the flags, type, and attrins from
-                          the domain we queried to make sure we don't
-                          record the view of the trust from the wrong
-                          side.  Always view it from the side of our
-                          primary domain.   --jerry */
-                       if ( domain->primary ||
-                            ((domain->domain_flags&fr_flags) == fr_flags) ) 
-                       {
-                               DEBUG(10,("trusted_domains(ads):  Storing trust "
-                                         "flags for domain %s\n", d.alt_name));
+                       if (trusts.array[i].sid) {
+                               sid_copy( &d.sid, trusts.array[i].sid);
+                       } else {
+                               sid_copy(&d.sid, &global_sid_NULL);
+                       }
 
-                               /* Look this up in cache to make sure
-                                  we have the current trust flags and
-                                  attributes */
+                       if ( domain->primary ) {
+                               DEBUG(10,("trusted_domains(ads):  Searching "
+                                         "trusted domain list of %s and storing "
+                                         "trust flags for domain %s\n", 
+                                         domain->name, d.alt_name));
 
                                d.domain_flags = trusts.array[i].trust_flags;
                                d.domain_type = trusts.array[i].trust_type;
                                d.domain_trust_attribs = trusts.array[i].trust_attributes;
-                       } else {
-                               /* Look up the record in the cache */
-                               struct winbindd_tdc_domain *parent;
 
-                               DEBUG(10,("trusted_domains(ads):  Inheriting trust "
-                                         "flags for domain %s\n", d.alt_name));                                
+                               wcache_tdc_add_domain( &d );
+                               ret_count++;
+                       } else if ( (domain->domain_flags&fr_flags) == fr_flags ) {
+                               /* Check if we already have this record. If
+                                * we are following our forest root that is not
+                                * our primary domain, we want to keep trust
+                                * flags from the perspective of our primary
+                                * domain not our forest root. */
+                               struct winbindd_tdc_domain *exist = NULL;
+
+                               exist = 
+                                   wcache_tdc_fetch_domain(NULL, trusts.array[i].netbios_name);
+                               if (!exist) {
+                                       DEBUG(10,("trusted_domains(ads):  Searching "
+                                                 "trusted domain list of %s and storing "
+                                                 "trust flags for domain %s\n", 
+                                                 domain->name, d.alt_name));
+                                       d.domain_flags = trusts.array[i].trust_flags;
+                                       d.domain_type = trusts.array[i].trust_type;
+                                       d.domain_trust_attribs = trusts.array[i].trust_attributes;
+
+                                       wcache_tdc_add_domain( &d );
+                                       ret_count++;
+                               }
+                               TALLOC_FREE(exist);
+                       } else {
+                               /* This gets a little tricky.  If we are
+                                  following a transitive forest trust, then
+                                  innerit the flags, type, and attribs from
+                                  the domain we queried to make sure we don't
+                                  record the view of the trust from the wrong
+                                  side.  Always view it from the side of our
+                                  primary domain.   --jerry */
+                               struct winbindd_tdc_domain *parent = NULL;
+
+                               DEBUG(10,("trusted_domains(ads):  Searching "
+                                         "trusted domain list of %s and inheriting "
+                                         "trust flags for domain %s\n", 
+                                         domain->name, d.alt_name));
 
                                parent = wcache_tdc_fetch_domain(NULL, domain->name);
                                if (parent) {
@@ -1282,17 +1318,15 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                        d.domain_type  = parent->trust_type;
                                        d.domain_trust_attribs = parent->trust_attribs;
                                } else {
-                               d.domain_flags = domain->domain_flags;                          
-                               d.domain_type  = domain->domain_type;
-                               d.domain_trust_attribs = domain->domain_trust_attribs;
-                       }
+                                       d.domain_flags = domain->domain_flags;
+                                       d.domain_type  = domain->domain_type;
+                                       d.domain_trust_attribs = domain->domain_trust_attribs;
+                               }
                                TALLOC_FREE(parent);
+                               
+                               wcache_tdc_add_domain( &d );
+                               ret_count++;
                        }
-
-                       wcache_tdc_add_domain( &d );
-
-                       ret_count++;
-
                }
 
                *num_domains = ret_count;