Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
authorSimo Sorce <idra@samba.org>
Fri, 1 Feb 2008 19:24:31 +0000 (14:24 -0500)
committerSimo Sorce <idra@samba.org>
Fri, 1 Feb 2008 19:24:31 +0000 (14:24 -0500)
(This used to be commit 7dbfc7bdc65314466a83e8121b35c9bcb24b2631)

1  2 
source3/winbindd/winbindd_dual.c
source3/winbindd/winbindd_util.c

index 2739ab542e2cf988fa2c5d5d4a38bba44dd75fb8,15ca564c6ac1ff2e63bba81dbffe99033c003057..1f2972f9b2be5b3a6c9dd7c47f7e109b98f3ca34
@@@ -34,7 -34,6 +34,7 @@@
  #define DBGC_CLASS DBGC_WINBIND
  
  extern bool override_logfile;
 +extern struct winbindd_methods cache_methods;
  
  /* Read some data from a client connection */
  
@@@ -481,7 -480,6 +481,6 @@@ void winbind_child_died(pid_t pid
        child->event.fd = 0;
        child->event.flags = 0;
        child->pid = 0;
-       SAFE_FREE(child->logfilename);
  
        schedule_async_request(child);
  }
@@@ -678,6 -676,88 +677,88 @@@ void winbind_msg_dump_event_list(struc
  
  }
  
+ void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx,
+                                 void *private_data,
+                                 uint32_t msg_type,
+                                 struct server_id server_id,
+                                 DATA_BLOB *data)
+ {
+       TALLOC_CTX *mem_ctx;
+       const char *message = NULL;
+       struct server_id *sender = NULL;
+       const char *domain = NULL;
+       char *s = NULL;
+       NTSTATUS status;
+       struct winbindd_domain *dom = NULL;
+       DEBUG(5,("winbind_msg_dump_domain_list received.\n"));
+       if (!data || !data->data) {
+               return;
+       }
+       if (data->length < sizeof(struct server_id)) {
+               return;
+       }
+       mem_ctx = talloc_init("winbind_msg_dump_domain_list");
+       if (!mem_ctx) {
+               return;
+       }
+       sender = (struct server_id *)data->data;
+       if (data->length > sizeof(struct server_id)) {
+               domain = (const char *)data->data+sizeof(struct server_id);
+       }
+       if (domain) {
+               DEBUG(5,("winbind_msg_dump_domain_list for domain: %s\n",
+                       domain));
+               message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain,
+                                                 find_domain_from_name_noinit(domain));
+               if (!message) {
+                       talloc_destroy(mem_ctx);
+                       return;
+               }
+               messaging_send_buf(msg_ctx, *sender,
+                                  MSG_WINBIND_DUMP_DOMAIN_LIST,
+                                  (uint8_t *)message, strlen(message) + 1);
+               talloc_destroy(mem_ctx);
+               return;
+       }
+       DEBUG(5,("winbind_msg_dump_domain_list all domains\n"));
+       for (dom = domain_list(); dom; dom=dom->next) {
+               message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain, dom);
+               if (!message) {
+                       talloc_destroy(mem_ctx);
+                       return;
+               }
+               s = talloc_asprintf_append(s, "%s\n", message);
+               if (!s) {
+                       talloc_destroy(mem_ctx);
+                       return;
+               }
+       }
+       status = messaging_send_buf(msg_ctx, *sender,
+                                   MSG_WINBIND_DUMP_DOMAIN_LIST,
+                                   (uint8_t *)s, strlen(s) + 1);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("failed to send message: %s\n",
+               nt_errstr(status)));
+       }
+       talloc_destroy(mem_ctx);
+ }
  static void account_lockout_policy_handler(struct event_context *ctx,
                                           struct timed_event *te,
                                           const struct timeval *now,
@@@ -879,6 -959,13 +960,13 @@@ static bool fork_domain_child(struct wi
        struct winbindd_cli_state state;
        struct winbindd_domain *domain;
  
+       if (child->domain) {
+               DEBUG(10, ("fork_domain_child called for domain '%s'\n",
+                          child->domain->name));
+       } else {
+               DEBUG(10, ("fork_domain_child called without domain.\n"));
+       }
        if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
                DEBUG(0, ("Could not open child pipe: %s\n",
                          strerror(errno)));
                             MSG_WINBIND_ONLINESTATUS, NULL);
        messaging_deregister(winbind_messaging_context(),
                             MSG_DUMP_EVENT_LIST, NULL);
+       messaging_deregister(winbind_messaging_context(),
+                            MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
  
        /* Handle online/offline messages. */
        messaging_register(winbind_messaging_context(), NULL,
                        child);
        }
  
 +      /* Special case for Winbindd on a Samba DC,
 +       * We want to make sure the child can connect to smbd
 +       * but not the main daemon */
 +
 +      if (child->domain && child->domain->internal && IS_DC) {
 +              child->domain->internal = False;
 +              child->domain->methods = &cache_methods;
 +              child->domain->online = False;
 +      }
 +
        while (1) {
  
                int ret;
index 795209619ced8ffcb121ecec4e1dd65e9e2b3054,10779cd60a5b85e31ad267d2e62b664bedc3b14e..7933ecf63e42391729e6c7176cd5a3b72bc8001f
@@@ -41,7 -41,7 +41,7 @@@ extern struct winbindd_methods passdb_m
     individual winbindd_domain structures cannot be made.  Keep a copy of
     the domain name instead. */
  
- static struct winbindd_domain *_domain_list;
+ static struct winbindd_domain *_domain_list = NULL;
  
  /**
     When was the last scan of trusted domains done?
@@@ -82,6 -82,9 +82,6 @@@ static bool is_internal_domain(const DO
        if (sid == NULL)
                return False;
  
 -      if ( IS_DC )
 -              return sid_check_is_builtin(sid);
 -
        return (sid_check_is_domain(sid) || sid_check_is_builtin(sid));
  }
  
@@@ -90,6 -93,9 +90,6 @@@ static bool is_in_internal_domain(cons
        if (sid == NULL)
                return False;
  
 -      if ( IS_DC )
 -              return sid_check_is_in_builtin(sid);
 -
        return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid));
  }
  
@@@ -212,7 -218,7 +212,7 @@@ static void add_trusted_domains( struc
        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;
  
@@@ -385,8 -391,8 +385,8 @@@ static void rescan_forest_root_trusts( 
                   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 */
@@@ -450,10 -456,10 +450,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 */
@@@ -494,9 -500,13 +494,13 @@@ void rescan_trusted_domains( void 
            ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
                return;
                
-       /* clear the TRUSTDOM cache first */
-       wcache_tdc_clear();
+       /* I use to clear the cache here and start over but that
+          caused problems in child processes that needed the
+          trust dom list early on.  Removing it means we
+          could have some trusted domains listed that have been
+          removed from our primary domain's DC until a full
+          restart.  This should be ok since I think this is what
+          Windows does as well. */
  
        /* this will only add new domains we didn't already know about
           in the domain_list()*/
@@@ -561,7 -571,7 +565,7 @@@ enum winbindd_result init_child_connect
                /* The primary domain has to find the DC name itself */
                request->cmd = WINBINDD_INIT_CONNECTION;
                fstrcpy(request->domain_name, domain->name);
-               request->data.init_conn.is_primary = domain->internal ? False : True;
+               request->data.init_conn.is_primary = domain->primary ? true : false;
                fstrcpy(request->data.init_conn.dcname, "");
                async_request(mem_ctx, &domain->child, request, response,
                              init_child_recv, state);
@@@ -760,8 -770,8 +764,8 @@@ void check_domain_trusted( const char *
           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;  
  
@@@ -1294,19 -1304,22 +1298,22 @@@ NTSTATUS lookup_usergroups_cached(struc
        /* always add the primary group to the sid array */
        sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid);
        
-       if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) {
+       status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
+                                 &num_groups);
+       if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(info3);
-               return NT_STATUS_NO_MEMORY;
+               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);
  
-               if (!add_sid_to_array(mem_ctx, &group_sid, user_sids,
-                                &num_groups)) {
+               status = add_sid_to_array(mem_ctx, &group_sid, user_sids,
+                                         &num_groups);
+               if (!NT_STATUS_IS_OK(status)) {
                        TALLOC_FREE(info3);
-                       return NT_STATUS_NO_MEMORY;
+                       return status;
                }
        }
  
                if (info3->other_sids_attrib[i] & SE_GROUP_RESOURCE)
                        continue;
  
-               if (!add_sid_to_array(mem_ctx, &info3->other_sids[i].sid,
-                                     user_sids, &num_groups))
-               {
+               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 NT_STATUS_NO_MEMORY;                     
+                       return status;
                }
        }
        
@@@ -1373,31 -1386,56 +1380,56 @@@ void ws_name_return( char *name, char r
  /*********************************************************************
   ********************************************************************/
  
- 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;     
  }
  
  /*********************************************************************