working on transtive trusts issue:
authorGerald Carter <jerry@samba.org>
Thu, 31 Jul 2003 05:43:47 +0000 (05:43 +0000)
committerGerald Carter <jerry@samba.org>
Thu, 31 Jul 2003 05:43:47 +0000 (05:43 +0000)
  * use DsEnumerateDomainTrusts() instead of LDAP search.
    wbinfo -m now lists all trusted downlevel domains and
    all domains in the forest.

Thnigs to do:

  o Look at Krb5 connection trusted domains
  o make sure to initial the trusted domain cache as soon
    as possible
(This used to be commit 0ab00ccaedf204b39c86a9e1c2fcac5f15d0e033)

source3/include/rpc_ds.h
source3/libads/ldap.c
source3/nsswitch/winbindd_ads.c
source3/nsswitch/winbindd_cache.c
source3/nsswitch/winbindd_cm.c
source3/nsswitch/winbindd_pam.c
source3/nsswitch/winbindd_util.c
source3/rpc_client/cli_ds.c
source3/rpc_parse/parse_ds.c

index 22b2430595894051fb0dea6962a118cf2fe92b67..7350fdba1f9a7f52146a57596f067c0230a3d04e 100644 (file)
@@ -54,10 +54,9 @@ typedef struct
        GUID            domain_guid;
        
        UNISTR2 netbios_domain;
-       /* these 2 might be reversed in order.  I can't tell from 
-          my tests as both values are the same --jerry */
-       UNISTR2 dns_domain;
-       UNISTR2 forest_domain;
+
+       UNISTR2 dns_domain;     /* our dns domain */
+       UNISTR2 forest_domain;  /* root domain of the forest to which we belong */
 } DSROLE_PRIMARY_DOMAIN_INFO_BASIC;
 
 typedef struct
@@ -114,6 +113,15 @@ typedef struct {
        
 } DS_DOMAIN_TRUSTS_CTR;
 
+#define DS_DOMAIN_IN_FOREST           0x0001   /* domains in the forest to which 
+                                                  we belong; even different domain trees */
+#define DS_DOMAIN_DIRECT_OUTBOUND     0x0002   /* trusted domains */
+#define DS_DOMAIN_TREE_ROOT           0x0004   /* root of our forest; also available in
+                                                  DsRoleGetPrimaryDomainInfo() */
+#define DS_DOMAIN_PRIMARY             0x0008   /* our domain */
+#define DS_DOMAIN_NATIVE_MODE         0x0010   /* native mode AD servers */
+#define DS_DOMAIN_DIRECT_INBOUND      0x0020   /* trusting domains */
+
 /* DS_Q_ENUM_DOM_TRUSTS - DsEnumerateDomainTrusts() request */
 typedef struct 
 {
index 62520d5001c4f953ed176b38d31fc8fb546c72fc..dd93502056958f0d093a3c11b6827ac058c14362 100644 (file)
@@ -1888,77 +1888,6 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
        return ADS_SUCCESS;
 }
 
-
-/**
- * find the list of trusted domains
- * @param ads connection to ads server
- * @param mem_ctx TALLOC_CTX for allocating results
- * @param num_trusts pointer to number of trusts
- * @param names pointer to trusted domain name list
- * @param sids pointer to list of sids of trusted domains
- * @return the count of SIDs pulled
- **/
-ADS_STATUS ads_trusted_domains(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, 
-                              int *num_trusts, 
-                              char ***names, 
-                              char ***alt_names,
-                              DOM_SID **sids)
-{
-       const char *attrs[] = {"name", "flatname", "securityIdentifier", 
-                              "trustDirection", NULL};
-       ADS_STATUS status;
-       void *res, *msg;
-       int count, i;
-
-       *num_trusts = 0;
-
-       status = ads_search(ads, &res, "(objectcategory=trustedDomain)", attrs);
-       if (!ADS_ERR_OK(status)) return status;
-
-       count = ads_count_replies(ads, res);
-       if (count == 0) {
-               ads_msgfree(ads, res);
-               return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
-       }
-
-       (*names) = talloc(mem_ctx, sizeof(char *) * count);
-       (*alt_names) = talloc(mem_ctx, sizeof(char *) * count);
-       (*sids) = talloc(mem_ctx, sizeof(DOM_SID) * count);
-       if (! *names || ! *sids) return ADS_ERROR(LDAP_NO_MEMORY);
-
-       for (i=0, msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
-               uint32 direction;
-
-               /* direction is a 2 bit bitfield, 1 means they trust us 
-                  but we don't trust them, so we should not list them
-                  as users from that domain can't login */
-               if (ads_pull_uint32(ads, msg, "trustDirection", &direction) &&
-                   direction == 1) {
-                       continue;
-               }
-               
-               (*names)[i] = ads_pull_string(ads, mem_ctx, msg, "name");
-               (*alt_names)[i] = ads_pull_string(ads, mem_ctx, msg, "flatname");
-
-               if ((*alt_names)[i] && (*alt_names)[i][0]) {
-                       /* we prefer the flatname as the primary name
-                          for consistency with RPC */
-                       char *name = (*alt_names)[i];
-                       (*alt_names)[i] = (*names)[i];
-                       (*names)[i] = name;
-               }
-               if (ads_pull_sid(ads, msg, "securityIdentifier", &(*sids)[i])) {
-                       i++;
-               }
-       }
-
-       ads_msgfree(ads, res);
-
-       *num_trusts = i;
-
-       return ADS_SUCCESS;
-}
-
 /**
  * find the domain sid for our domain
  * @param ads connection to ads server
index 462dd21531bf0428361f449110dff1a6d3dc245a..7140dc35a0dd95db41d70cc289c8b4612e8362e5 100644 (file)
@@ -801,24 +801,91 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                char ***alt_names,
                                DOM_SID **dom_sids)
 {
-       ADS_STRUCT *ads;
-       ADS_STATUS rc;
+       NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
+       DS_DOMAIN_TRUSTS        *domains = NULL;
+       int                     count = 0;
+       int                     i;
+       struct cli_state        *cli = NULL;
+                               /* i think we only need our forest and downlevel trusted domains */
+       uint32                  flags = DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND;
 
        DEBUG(3,("ads: trusted_domains\n"));
 
        *num_domains = 0;
-       *names = NULL;
+       *alt_names   = NULL;
+       *names       = NULL;
+       *dom_sids    = NULL;
+               
+       if ( !NT_STATUS_IS_OK(result = cm_fresh_connection(domain->name, PI_NETLOGON, &cli)) ) {
+               DEBUG(5, ("trusted_domains: Could not open a connection to %s for PIPE_NETLOGON (%s)\n", 
+                         domain->name, nt_errstr(result)));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+       
+       if ( NT_STATUS_IS_OK(result) )
+               result = cli_ds_enum_domain_trusts( cli, mem_ctx, cli->desthost, flags, &domains, &count );
+       
+       if ( NT_STATUS_IS_OK(result) && count) {
+       
+               /* Allocate memory for trusted domain names and sids */
 
-       ads = ads_cached_connection(domain);
+               if ( !(*names = (char **)talloc(mem_ctx, sizeof(char *) * count)) ) {
+                       DEBUG(0, ("trusted_domains: out of memory\n"));
+                       result = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
 
-       if (!ads) {
-               domain->last_status = NT_STATUS_SERVER_DISABLED;
-               return NT_STATUS_UNSUCCESSFUL;
+               if ( !(*alt_names = (char **)talloc(mem_ctx, sizeof(char *) * count)) ) {
+                       DEBUG(0, ("trusted_domains: out of memory\n"));
+                       result = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
+
+               if ( !(*dom_sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) * count)) ) {
+                       DEBUG(0, ("trusted_domains: out of memory\n"));
+                       result = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
+
+               /* Copy across names and sids */
+
+               for (i = 0; i < count; i++) {
+                       fstring tmp;
+                       fstring tmp2;
+
+                       (*names)[i] = NULL;
+                       (*alt_names)[i] = NULL;
+                       ZERO_STRUCT( (*dom_sids)[i] );
+
+                       if ( domains[i].netbios_ptr ) {
+                               unistr2_to_ascii(tmp, &domains[i].netbios_domain, sizeof(tmp) - 1);
+                               (*names)[i] = talloc_strdup(mem_ctx, tmp);
+                       }
+                       
+                       if ( domains[i].dns_ptr ) {
+                               unistr2_to_ascii(tmp2, &domains[i].dns_domain, sizeof(tmp2) - 1);
+                               (*alt_names)[i] = talloc_strdup(mem_ctx, tmp2);
+                       }
+                       
+                       /* sometimes we will get back a NULL SID from this call */
+                       
+                       if ( domains[i].sid_ptr )
+                               sid_copy(&(*dom_sids)[i], &domains[i].sid.sid);
+               }
+
+               *num_domains = count;   
        }
 
-       rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids);
+done:
+
+       SAFE_FREE( domains );
+       
+       /* remove connection;  This is a special case to the \NETLOGON pipe */
+       
+       if ( cli )
+               cli_shutdown( cli );
 
-       return ads_ntstatus(rc);
+       return result;
 }
 
 /* find the domain sid for a domain */
index f1c85428153047861585920d197e72faf5fccd6f..af4ccabadeda854e005aac6cd0d21be537466381 100644 (file)
@@ -106,7 +106,7 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
                case SEC_ADS: {
                        extern struct winbindd_methods ads_methods;
                        /* always obey the lp_security parameter for our domain */
-                       if ( strequal(lp_realm(), domain->alt_name) ) {
+                       if ( strequal(lp_realm(), domain->alt_name) || strequal(lp_workgroup(), domain->name) ) {
                                domain->backend = &ads_methods;
                                break;
                        }
index dbc3062edd6798a04c7c2dd492d751895c4e6b1f..f07117b5ab8680b9a38ce7d044f0d564f569aafc 100644 (file)
@@ -152,7 +152,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
                
                result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller, 
                                             &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, 
-                                            ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK,
+                                            ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, 
                                             Undefined, &retry);
                
                secrets_named_mutex_release(new_conn->controller);
@@ -194,6 +194,25 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
        return NT_STATUS_OK;
 }
 
+/************************************************************************
+ Wrapper around statuc cm_open_connection to retreive a freshly
+ setup cli_state struct
+************************************************************************/
+
+NTSTATUS cm_fresh_connection(const char *domain, const int pipe_index,
+                              struct cli_state **cli)
+{
+       NTSTATUS result;
+       struct winbindd_cm_conn conn;
+       
+       result = cm_open_connection( domain, pipe_index, &conn );
+       
+       if ( NT_STATUS_IS_OK(result) ) 
+               *cli = conn.cli;
+
+       return result;
+}
+
 /* Return true if a connection is still alive */
 
 static BOOL connection_ok(struct winbindd_cm_conn *conn)
@@ -326,13 +345,11 @@ BOOL cm_check_for_native_mode_win2k( const char *domain )
 
 done:
 
-#if 0
-       /*
-        * I don't think we need to shutdown here ? JRA.
-        */
+       /* close the connection;  no other cals use this pipe and it is called only
+          on reestablishing the domain list   --jerry */
+
        if ( conn.cli )
                cli_shutdown( conn.cli );
-#endif
        
        return ret;
 }
index 8edd00f806e1e41f9eddb4325e2e03726c26f8bd..a8908487c1b566d93914ea66cf28ea3f9c01dc5b 100644 (file)
@@ -53,55 +53,6 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-/*******************************************************************
- wrapper around retrieving the trust account password
-*******************************************************************/
-
-static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16],
-                          time_t *pass_last_set_time, uint32 *channel)
-{
-       DOM_SID sid;
-       char *pwd;
-
-       /* if we are a DC and this is not our domain, then lookup an account
-          for the domain trust */
-          
-       if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) 
-       {
-               if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, 
-                       pass_last_set_time) ) 
-               {
-                       DEBUG(0, ("get_trust_pw: could not fetch trust account "
-                                 "password for trusted domain %s\n", domain));
-                       return False;
-               }
-               
-               *channel = SEC_CHAN_DOMAIN;
-               E_md4hash(pwd, ret_pwd);
-               SAFE_FREE(pwd);
-
-               return True;
-       }
-       else    /* just get the account for our domain (covers 
-                  ROLE_DOMAIN_MEMBER as well */
-       {
-               /* get the machine trust account for our domain */
-
-               if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd,
-                       pass_last_set_time, channel) ) 
-               {
-                       DEBUG(0, ("get_trust_pw: could not fetch trust account "
-                                 "password for my domain %s\n", domain));
-                       return False;
-               }
-               
-               return True;
-       }
-       
-       /* Failure */
-       return False;
-}
-
 /**********************************************************************
  Authenticate a user with a clear test password
 **********************************************************************/
index 6177c46aefda04c4b6e669727d54dc6d912801bf..ca5146fc5647d61616bc97357771c8d9777e5b07 100644 (file)
@@ -111,7 +111,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
                fstrcpy(domain->name, alt_name);
                fstrcpy(domain->alt_name, domain_name);
        } else {
-       fstrcpy(domain->name, domain_name);
+               fstrcpy(domain->name, domain_name);
                if (alt_name) {
                        fstrcpy(domain->alt_name, alt_name);
                }
@@ -183,8 +183,8 @@ void rescan_trusted_domains(BOOL force)
                        continue;
                }
 
-               /* Add each domain to the trusted domain list. Each domain inherits
-                  the access methods of its parent */
+               /* Add each domain to the trusted domain list */
+               
                for(i = 0; i < num_domains; i++) {
                        DEBUG(10,("Found domain %s\n", names[i]));
                        add_trusted_domain(names[i], alt_names?alt_names[i]:NULL,
@@ -209,7 +209,7 @@ BOOL init_domain_list(void)
        free_domain_list();
 
        /* Add ourselves as the first entry */
-       domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL);
+       domain = add_trusted_domain( lp_workgroup(), NULL, &cache_methods, NULL);
        if (!secrets_fetch_domain_sid(domain->name, &domain->sid)) {
                DEBUG(1, ("Could not fetch sid for our domain %s\n",
                          domain->name));
@@ -782,3 +782,53 @@ BOOL winbindd_upgrade_idmap(void)
 
        return idmap_convert(idmap_name);
 }
+
+/*******************************************************************
+ wrapper around retrieving the trust account password
+*******************************************************************/
+
+BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16],
+                          time_t *pass_last_set_time, uint32 *channel)
+{
+       DOM_SID sid;
+       char *pwd;
+
+       /* if we are a DC and this is not our domain, then lookup an account
+          for the domain trust */
+          
+       if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) 
+       {
+               if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, 
+                       pass_last_set_time) ) 
+               {
+                       DEBUG(0, ("get_trust_pw: could not fetch trust account "
+                                 "password for trusted domain %s\n", domain));
+                       return False;
+               }
+               
+               *channel = SEC_CHAN_DOMAIN;
+               E_md4hash(pwd, ret_pwd);
+               SAFE_FREE(pwd);
+
+               return True;
+       }
+       else    /* just get the account for our domain (covers 
+                  ROLE_DOMAIN_MEMBER as well */
+       {
+               /* get the machine trust account for our domain */
+
+               if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd,
+                       pass_last_set_time, channel) ) 
+               {
+                       DEBUG(0, ("get_trust_pw: could not fetch trust account "
+                                 "password for my domain %s\n", domain));
+                       return False;
+               }
+               
+               return True;
+       }
+       
+       /* Failure */
+       return False;
+}
+
index 2f2111e9635b04468e1624a673f5c1adfaaabbe3..a7a093328c972ed6febbcd5e3c9fb15dd625cb3f 100644 (file)
@@ -115,11 +115,16 @@ NTSTATUS cli_ds_enum_domain_trusts(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        result = r.status;
        
        if ( NT_STATUS_IS_OK(result) ) {
+               int i;
        
                *num_domains = r.num_domains;
                *trusts = (DS_DOMAIN_TRUSTS*)smb_xmalloc(r.num_domains*sizeof(DS_DOMAIN_TRUSTS));
                
                memcpy( *trusts, r.domains.trusts, r.num_domains*sizeof(DS_DOMAIN_TRUSTS) );
+               for ( i=0; i<r.num_domains; i++ ) {
+                       copy_unistr2( &(*trusts)[i].netbios_domain, &r.domains.trusts[i].netbios_domain );
+                       copy_unistr2( &(*trusts)[i].dns_domain,     &r.domains.trusts[i].dns_domain );
+               }
        }
        
 done:
index 8edd38226bd30b13d7c39a58b0886571005d1449..f954806036b45b64fad7da871beaeceb7ab9e297 100644 (file)
@@ -266,6 +266,9 @@ BOOL ds_io_q_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS
        if ( !smb_io_unistr2("server", &q_u->server, q_u->server_ptr, ps, depth) )
                        return False;
        
+       if ( !prs_align(ps) )
+               return False;
+       
        if ( !prs_uint32( "flags", ps, depth, &q_u->flags ) )
                return False;