r22705: Implement new set_dc_type_and_flags() called based on the
authorGerald Carter <jerry@samba.org>
Sun, 6 May 2007 19:37:13 +0000 (19:37 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:21:47 +0000 (12:21 -0500)
information return from our DC in the DsEnumerateDomainTrusts()
call.   If the fails, we callback ot the older
connect-to-the-remote-domain method.

Note that this means we can only reliably expect the native_mode
flag to be set for our own domain as this information in not
available outside our primary domain from the trusted information.
This is ok as we only really need the flag when trying to
determine to enumerate domain local groups via RPC.

Use the AD flag rather than the native_mode flag when using
ldap to obtain the seq_num for a domain.
(This used to be commit 4b4148a9642f03b8f27dda2132708bcc0cbb3b8e)

source3/nsswitch/winbindd_cm.c
source3/nsswitch/winbindd_rpc.c
source3/nsswitch/winbindd_util.c

index 010d38fde97b2c870663e77a89f6d035959ad4e8..fb290e2ba7458f750f6bd3f9fdd01570347e1cba 100644 (file)
@@ -1503,6 +1503,106 @@ NTSTATUS init_dc_connection(struct winbindd_domain *domain)
        return init_dc_connection_network(domain);
 }
 
+/******************************************************************************
+ Set the trust flags (direction and forest location) for a domain
+******************************************************************************/
+
+static BOOL set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
+{
+       struct winbindd_domain *our_domain;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       struct ds_domain_trust *domains = NULL;
+       int count = 0;
+       int i;
+       uint32 flags = (DS_DOMAIN_IN_FOREST | 
+                       DS_DOMAIN_DIRECT_OUTBOUND | 
+                       DS_DOMAIN_DIRECT_INBOUND);
+       struct rpc_pipe_client *cli;
+       TALLOC_CTX *mem_ctx = NULL;
+
+       DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
+       
+       /* Our primary domain doesn't need to worry about trust flags.
+          Force it to go through the network setup */
+       if ( domain->primary ) {                
+               return False;           
+       }
+       
+       our_domain = find_our_domain();
+       
+       if ( !connection_ok(our_domain) ) {
+               DEBUG(3,("set_dc_type_and_flags_trustinfo: No connection to our domain!\n"));           
+               return False;
+       }
+
+       /* This won't work unless our domain is AD */
+        
+       if ( !our_domain->active_directory ) {
+               return False;
+       }
+       
+       /* Use DsEnumerateDomainTrusts to get us the trust direction
+          and type */
+
+       result = cm_connect_netlogon(our_domain, &cli);
+
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(5, ("set_dc_type_and_flags_trustinfo: Could not open "
+                         "a connection to %s for PIPE_NETLOGON (%s)\n", 
+                         domain->name, nt_errstr(result)));
+               return False;
+       }
+
+       if ( (mem_ctx = talloc_init("set_dc_type_and_flags_trustinfo")) == NULL ) {
+               DEBUG(0,("set_dc_type_and_flags_trustinfo: talloc_init() failed!\n"));
+               return False;
+       }       
+
+       result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
+                                             cli->cli->desthost, 
+                                             flags, &domains,
+                                             (unsigned int *)&count);
+
+       /* Now find the domain name and get the flags */
+
+       for ( i=0; i<count; i++ ) {
+               if ( strequal( domain->name, domains[i].netbios_domain ) ) {                    
+                       domain->domain_flags          = domains[i].flags;
+                       domain->domain_type           = domains[i].trust_type;
+                       domain->domain_trust_attribs  = domains[i].trust_attributes;
+                                               
+                       if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
+                               domain->active_directory = True;
+
+                       /* This flag is only set if the domain is *our* 
+                          primary domain and the primary domain is in
+                          native mode */
+
+                       domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
+
+                       DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
+                                 "native mode.\n", domain->name, 
+                                 domain->native_mode ? "" : "NOT "));
+
+                       DEBUG(5,("set_dc_type_and_flags_trustinfo: domain %s is %s"
+                                "running active directory.\n", domain->name, 
+                                domain->active_directory ? "" : "NOT "));
+
+
+                       domain->initialized = True;
+
+                       if ( !winbindd_can_contact_domain( domain) )
+                               domain->internal = True;
+                       
+                       break;
+               }               
+       }
+       
+       talloc_destroy( mem_ctx );
+       
+       return domain->initialized;     
+}
+
 /******************************************************************************
  We can 'sense' certain things about the DC by it's replies to certain
  questions.
@@ -1511,7 +1611,7 @@ NTSTATUS init_dc_connection(struct winbindd_domain *domain)
  is native mode.
 ******************************************************************************/
 
-static void set_dc_type_and_flags( struct winbindd_domain *domain )
+static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
 {
        NTSTATUS                result;
        DS_DOMINFO_CTR          ctr;
@@ -1530,13 +1630,13 @@ static void set_dc_type_and_flags( struct winbindd_domain *domain )
                return;
        }
 
-       DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
+       DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
 
        cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
                                       &result);
 
        if (cli == NULL) {
-               DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
+               DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
                          "PI_LSARPC_DS on domain %s: (%s)\n",
                          domain->name, nt_errstr(result)));
 
@@ -1553,7 +1653,7 @@ static void set_dc_type_and_flags( struct winbindd_domain *domain )
        cli_rpc_pipe_close(cli);
 
        if (!NT_STATUS_IS_OK(result)) {
-               DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
+               DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
                          "on domain %s failed: (%s)\n",
                          domain->name, nt_errstr(result)));
                return;
@@ -1570,7 +1670,7 @@ no_lsarpc_ds:
        cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
 
        if (cli == NULL) {
-               DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
+               DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
                          "PI_LSARPC on domain %s: (%s)\n",
                          domain->name, nt_errstr(result)));
                cli_rpc_pipe_close(cli);
@@ -1580,7 +1680,7 @@ no_lsarpc_ds:
        mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
                              domain->name);
        if (!mem_ctx) {
-               DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
+               DEBUG(1, ("set_dc_type_and_flags_connect: talloc_init() failed\n"));
                cli_rpc_pipe_close(cli);
                return;
        }
@@ -1635,10 +1735,10 @@ no_lsarpc_ds:
        }
 done:
 
-       DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
+       DEBUG(5, ("set_dc_type_and_flags_connect: domain %s is %sin native mode.\n",
                  domain->name, domain->native_mode ? "" : "NOT "));
 
-       DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
+       DEBUG(5,("set_dc_type_and_flags_connect: domain %s is %srunning active directory.\n",
                  domain->name, domain->active_directory ? "" : "NOT "));
 
        cli_rpc_pipe_close(cli);
@@ -1648,6 +1748,37 @@ done:
        domain->initialized = True;
 }
 
+/**********************************************************************
+ Set the domain_flags (trust attributes, domain operating modes, etc... 
+***********************************************************************/
+
+static void set_dc_type_and_flags( struct winbindd_domain *domain )
+{
+       /* we always have to contact our primary domain */
+
+       if ( domain->primary ) {
+               DEBUG(10,("set_dc_type_and_flags: setting up flags for "
+                         "primary domain\n"));
+               set_dc_type_and_flags_connect( domain );
+               return;         
+       }
+
+       /* Use our DC to get the information if possible */
+
+       if ( !set_dc_type_and_flags_trustinfo( domain ) ) {
+               /* Otherwise, fallback to contacting the 
+                  domain directly */
+               set_dc_type_and_flags_connect( domain );
+       }
+
+       return;
+}
+
+
+
+/**********************************************************************
+***********************************************************************/
+
 static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
                                   struct dcinfo **ppdc)
 {
index f408e1e15eef6e761300e519e85cd03db9743462..a66b05b79177f7f1156a9496d49fd674dc5ca5a6 100644 (file)
@@ -828,7 +828,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
                return NT_STATUS_NO_MEMORY;
 
 #ifdef HAVE_LDAP
-       if ( domain->native_mode ) 
+       if ( domain->active_directory ) 
        {
                int res;
 
index 56de808c2dc56cf13764c04932272f92313f162b..d58fffd0dbe49fad00a756dfbf4624a424ccb1e8 100644 (file)
@@ -1233,3 +1233,33 @@ void ws_name_return( char *name, char replace )
 
        return; 
 }
+
+/*********************************************************************
+ ********************************************************************/
+
+BOOL winbindd_can_contact_domain( struct winbindd_domain *domain )
+{
+       /* We can contact the domain if it is our primary domain */
+
+       if ( domain->primary )
+               return True;
+
+       /* Can always contact a domain that is in out forest */
+
+       if ( domain->domain_flags & DS_DOMAIN_IN_FOREST )
+               return True;    
+
+       /* We cannot contact the domain if it is running AD and
+          we have no inbound trust */
+
+       if ( domain->active_directory && 
+            ((domain->domain_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND) ) 
+       {
+               return False;
+       }
+       
+       /* Assume everything else is ok (probably not true but what
+          can you do?) */
+       
+       return True;    
+}