summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-07-31 05:43:47 +0000
committerGerald Carter <jerry@samba.org>2003-07-31 05:43:47 +0000
commit0d087e3ba28a9061529c95799624ccc4686eb1e9 (patch)
tree6284d9b57fc77694b6967fc76ce90eadadb5a40b
parent48c01deb300b51c97865ec0d738c64c7722da0d7 (diff)
downloadsamba-0d087e3ba28a9061529c95799624ccc4686eb1e9.tar.gz
samba-0d087e3ba28a9061529c95799624ccc4686eb1e9.tar.bz2
samba-0d087e3ba28a9061529c95799624ccc4686eb1e9.zip
working on transtive trusts issue:
* 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)
-rw-r--r--source3/include/rpc_ds.h16
-rw-r--r--source3/libads/ldap.c71
-rw-r--r--source3/nsswitch/winbindd_ads.c85
-rw-r--r--source3/nsswitch/winbindd_cache.c2
-rw-r--r--source3/nsswitch/winbindd_cm.c29
-rw-r--r--source3/nsswitch/winbindd_pam.c49
-rw-r--r--source3/nsswitch/winbindd_util.c58
-rw-r--r--source3/rpc_client/cli_ds.c5
-rw-r--r--source3/rpc_parse/parse_ds.c3
9 files changed, 174 insertions, 144 deletions
diff --git a/source3/include/rpc_ds.h b/source3/include/rpc_ds.h
index 22b2430595..7350fdba1f 100644
--- a/source3/include/rpc_ds.h
+++ b/source3/include/rpc_ds.h
@@ -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
{
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 62520d5001..dd93502056 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -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
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index 462dd21531..7140dc35a0 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -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 */
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index f1c8542815..af4ccabade 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -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;
}
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index dbc3062edd..f07117b5ab 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -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;
}
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index 8edd00f806..a8908487c1 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -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
**********************************************************************/
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 6177c46aef..ca5146fc56 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -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;
+}
+
diff --git a/source3/rpc_client/cli_ds.c b/source3/rpc_client/cli_ds.c
index 2f2111e963..a7a093328c 100644
--- a/source3/rpc_client/cli_ds.c
+++ b/source3/rpc_client/cli_ds.c
@@ -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:
diff --git a/source3/rpc_parse/parse_ds.c b/source3/rpc_parse/parse_ds.c
index 8edd38226b..f954806036 100644
--- a/source3/rpc_parse/parse_ds.c
+++ b/source3/rpc_parse/parse_ds.c
@@ -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;