I think the problem with these functions is that lookup_usergroups
[kai/samba.git] / source3 / winbindd / winbindd_util.c
index 724cce25124977ae3ff85d071ee7afe555be2396..77b17787c999d7f6032fb71f53e96a18c324e71d 100644 (file)
@@ -27,7 +27,9 @@
 #define DBGC_CLASS DBGC_WINBIND
 
 extern struct winbindd_methods cache_methods;
-extern struct winbindd_methods passdb_methods;
+extern struct winbindd_methods builtin_passdb_methods;
+extern struct winbindd_methods sam_passdb_methods;
+
 
 /**
  * @file winbindd_util.c
@@ -107,6 +109,8 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 {
        struct winbindd_domain *domain;
        const char *alternative_name = NULL;
+       char *idmap_config_option;
+       const char *param;
        
        /* ignore alt_name if we are not in an AD domain */
        
@@ -163,15 +167,9 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
         
        ZERO_STRUCTP(domain);
 
-       /* prioritise the short name */
-       if (strchr_m(domain_name, '.') && alternative_name && *alternative_name) {
-               fstrcpy(domain->name, alternative_name);
-               fstrcpy(domain->alt_name, domain_name);
-       } else {
-               fstrcpy(domain->name, domain_name);
-               if (alternative_name) {
-                       fstrcpy(domain->alt_name, alternative_name);
-               }
+       fstrcpy(domain->name, domain_name);
+       if (alternative_name) {
+               fstrcpy(domain->alt_name, alternative_name);
        }
 
        domain->methods = methods;
@@ -185,12 +183,44 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
        if (sid) {
                sid_copy(&domain->sid, sid);
        }
+
        
        /* Link to domain list */
        DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *);
         
        wcache_tdc_add_domain( domain );
         
+       idmap_config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
+                                             domain->name);
+       if (idmap_config_option == NULL) {
+               DEBUG(0, ("talloc failed, not looking for idmap config\n"));
+               goto done;
+       }
+
+       param = lp_parm_const_string(-1, idmap_config_option, "range", NULL);
+
+       DEBUG(10, ("%s : range = %s\n", idmap_config_option,
+                  param ? param : "not defined"));
+
+       if (param != NULL) {
+               unsigned low_id, high_id;
+               if (sscanf(param, "%u - %u", &low_id, &high_id) != 2) {
+                       DEBUG(1, ("invalid range syntax in %s: %s\n",
+                                 idmap_config_option, param));
+                       goto done;
+               }
+               if (low_id > high_id) {
+                       DEBUG(1, ("invalid range in %s: %s\n",
+                                 idmap_config_option, param));
+                       goto done;
+               }
+               domain->have_idmap_config = true;
+               domain->id_range_low = low_id;
+               domain->id_range_high = high_id;
+       }
+
+done:
+
        DEBUG(2,("Added domain %s %s %s\n", 
                 domain->name, domain->alt_name,
                 &domain->sid?sid_string_dbg(&domain->sid):""));
@@ -218,7 +248,7 @@ static void add_trusted_domains( struct winbindd_domain *domain )
        TALLOC_CTX *mem_ctx;
        struct winbindd_request *request;
        struct winbindd_response *response;
-       uint32 fr_flags = (DS_DOMAIN_TREE_ROOT|DS_DOMAIN_IN_FOREST);    
+       uint32 fr_flags = (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
 
        struct trustdom_state *state;
 
@@ -345,7 +375,7 @@ static void trustdom_recv(void *private_data, bool success)
        */
 
        if ( state->primary ) {
-               /* If this is our primary domain and we are not the in the
+               /* If this is our primary domain and we are not in the
                   forest root, we have to scan the root trusts first */
 
                if ( !state->forest_root )
@@ -355,7 +385,7 @@ static void trustdom_recv(void *private_data, bool success)
 
        } else if ( state->forest_root ) {
                /* Once we have done root forest trust search, we can
-                  go on to search thing trusted forests */
+                  go on to search the trusted forests */
 
                rescan_forest_trusts();
        }
@@ -391,8 +421,8 @@ static void rescan_forest_root_trusts( void )
                   the domain_list() as our primary domain may not 
                   have been initialized. */
 
-               if ( !(dom_list[i].trust_flags & DS_DOMAIN_TREE_ROOT) ) {
-                       continue;                       
+               if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
+                       continue;
                }
        
                /* Here's the forest root */
@@ -425,7 +455,7 @@ static void rescan_forest_root_trusts( void )
 }
 
 /********************************************************************
- scan the transitive forest trists (not our own)
+ scan the transitive forest trusts (not our own)
 ********************************************************************/
 
 
@@ -456,10 +486,10 @@ static void rescan_forest_trusts( void )
 
                if ( d && (d->internal || d->primary ) )
                        continue;               
-               
-               if ( (flags & DS_DOMAIN_DIRECT_INBOUND) &&
-                    (type == DS_DOMAIN_TRUST_TYPE_UPLEVEL) &&
-                    (attribs == DS_DOMAIN_TRUST_ATTRIB_FOREST_TRANSITIVE) )
+
+               if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
+                    (type == NETR_TRUST_TYPE_UPLEVEL) &&
+                    (attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
                {
                        /* add the trusted domain if we don't know
                           about it */
@@ -695,7 +725,7 @@ bool init_domain_list(void)
 
        /* BUILTIN domain */
 
-       domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods,
+       domain = add_trusted_domain("BUILTIN", NULL, &builtin_passdb_methods,
                                    &global_sid_Builtin);
        if (domain) {
                setup_domain_child(domain,
@@ -705,7 +735,7 @@ bool init_domain_list(void)
        /* Local SAM */
 
        domain = add_trusted_domain(get_global_sam_name(), NULL,
-                                   &passdb_methods, get_global_sam_sid());
+                                   &sam_passdb_methods, get_global_sam_sid());
        if (domain) {
                if ( role != ROLE_DOMAIN_MEMBER ) {
                        domain->primary = True;
@@ -770,8 +800,8 @@ void check_domain_trusted( const char *name, const DOM_SID *user_sid )
           forest trust */
 
        domain->active_directory = True;
-       domain->domain_flags = DS_DOMAIN_DIRECT_OUTBOUND;
-       domain->domain_type  = DS_DOMAIN_TRUST_TYPE_UPLEVEL;
+       domain->domain_flags = NETR_TRUST_FLAG_OUTBOUND;
+       domain->domain_type  = NETR_TRUST_TYPE_UPLEVEL;
        domain->internal = False;
        domain->online = True;  
 
@@ -1278,16 +1308,13 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
                                  const DOM_SID *user_sid,
                                  uint32 *p_num_groups, DOM_SID **user_sids)
 {
-       NET_USER_INFO_3 *info3 = NULL;
+       struct netr_SamInfo3 *info3 = NULL;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
-       int i;
        size_t num_groups = 0;
-       DOM_SID group_sid, primary_group;
-       
+
        DEBUG(3,(": lookup_usergroups_cached\n"));
-       
+
        *user_sids = NULL;
-       num_groups = 0;
        *p_num_groups = 0;
 
        info3 = netsamlogon_cache_get(mem_ctx, user_sid);
@@ -1296,50 +1323,23 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       if (info3->num_groups == 0) {
+       if (info3->base.groups.count == 0) {
                TALLOC_FREE(info3);
                return NT_STATUS_UNSUCCESSFUL;
        }
-       
-       /* always add the primary group to the sid array */
-       sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid);
-       
-       status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
-                                 &num_groups);
+
+       /* Skip Domain local groups outside our domain.
+          We'll get these from the getsidaliases() RPC call. */
+       status = sid_array_from_info3(mem_ctx, info3,
+                                     user_sids,
+                                     &num_groups,
+                                     false, true);
+
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(info3);
                return status;
        }
 
-       for (i=0; i<info3->num_groups; i++) {
-               sid_copy(&group_sid, &info3->dom_sid.sid);
-               sid_append_rid(&group_sid, info3->gids[i].g_rid);
-
-               status = add_sid_to_array(mem_ctx, &group_sid, user_sids,
-                                         &num_groups);
-               if (!NT_STATUS_IS_OK(status)) {
-                       TALLOC_FREE(info3);
-                       return status;
-               }
-       }
-
-       /* Add any Universal groups in the other_sids list */
-
-       for (i=0; i<info3->num_other_sids; i++) {
-               /* Skip Domain local groups outside our domain.
-                  We'll get these from the getsidaliases() RPC call. */
-               if (info3->other_sids_attrib[i] & SE_GROUP_RESOURCE)
-                       continue;
-
-               status = add_sid_to_array(mem_ctx, &info3->other_sids[i].sid,
-                                         user_sids, &num_groups);
-               if (!NT_STATUS_IS_OK(status)) {
-                       TALLOC_FREE(info3);
-                       return status;
-               }
-       }
-       
-
        TALLOC_FREE(info3);
        *p_num_groups = num_groups;
        status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
@@ -1386,31 +1386,56 @@ void ws_name_return( char *name, char replace )
 /*********************************************************************
  ********************************************************************/
 
-bool winbindd_can_contact_domain( struct winbindd_domain *domain )
+bool winbindd_can_contact_domain(struct winbindd_domain *domain)
 {
+       struct winbindd_tdc_domain *tdc = NULL;
+       TALLOC_CTX *frame = talloc_stackframe();
+       bool ret = false;
+
        /* We can contact the domain if it is our primary domain */
 
-       if ( domain->primary )
-               return True;
+       if (domain->primary) {
+               return true;
+       }
 
-       /* Can always contact a domain that is in out forest */
+       /* Trust the TDC cache and not the winbindd_domain flags */
 
-       if ( domain->domain_flags & DS_DOMAIN_IN_FOREST )
-               return True;    
+       if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
+               DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
+                         domain->name));
+               return false;
+       }
 
-       /* We cannot contact the domain if it is running AD and
-          we have no inbound trust */
+       /* Can always contact a domain that is in out forest */
 
-       if ( domain->active_directory && 
-            ((domain->domain_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND) ) 
-       {
-               return False;
+       if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
+               ret = true;
+               goto done;
        }
        
+       /*
+        * On a _member_ server, we cannot contact the domain if it
+        * is running AD and we have no inbound trust.
+        */
+
+       if (!IS_DC && 
+            domain->active_directory &&
+           ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
+       {
+               DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
+                          "and we have no inbound trust.\n", domain->name));
+               goto done;
+       }
+
        /* Assume everything else is ok (probably not true but what
           can you do?) */
+
+       ret = true;     
+
+done:  
+       talloc_destroy(frame);
        
-       return True;    
+       return ret;     
 }
 
 /*********************************************************************