[PATCH] Can't authenticate user from child-domain of trusted forest

Ralph Böhme slow at samba.org
Wed Nov 29 10:30:23 UTC 2017


Hi Volker,

On Tue, Nov 28, 2017 at 02:29:30PM +0100, Volker Lendecke wrote:
> On Tue, Nov 28, 2017 at 12:58:22PM +0100, Ralph Böhme wrote:
> > auth still fails because add_trusted_domain() will only be called in the domain
> > child, but not in the parent where we call find_domain_from_name_noinit().
> 
> What about that one?

what about this one? The first three patches are meant to fix wbinfo -m
--verbose output and don't affect anything else. The current code would denote
the added-on-the-fly domains as trust-type "Forest", transitive, in- and outgoing.

With those three wbinfo -m --verbose looks like this:

$ bin/wbinfo -m --verbose
Domain Name     DNS Domain            Trust Type  Transitive  In   Out
BUILTIN                               None        No          No   No
TITAN                                 None        No          No   No
WDOM2           wdom2.site            None        No          Yes  Yes
WDOM1           wdom1.site            Forest      Yes         Yes  Yes
WDOM3           wdom3.site            Forest      Yes         No   Yes
SUBDOM21        subdom21.wdom2.site   In-Forest   Yes         Yes  Yes
SUBDOM11                              None        No          No   No

SUBDOM11 was added on-the-fly after a successfull auth.

Fixes something different then the original bug, so I still believe we need my
initial patchset and eventually something like a add-domain-on-the-fly patchset.

How shall we proceed? You and metze are more familiar with this stuff.

-slow

-- 
Ralph Boehme, Samba Team       https://samba.org/
Samba Developer, SerNet GmbH   https://sernet.de/en/samba/
-------------- next part --------------
From 2652e9b85647d0a36fc16afa34338e0c9d4dea30 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 28 Nov 2017 17:32:59 +0100
Subject: [PATCH 1/5] winbindd: transitive trust logic in trust_is_transitive()

trust_is_transitive() currently defaults to transitive=true, unless
LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE, LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN or
LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL trust attribute is set.

This is not correct, for the trust to be transative,
LSA_TRUST_ATTRIBUTE_WITHIN_FOREST or LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE must
be set.

Logic taken from dsdb_trust_routing_by_name().
---
 source3/winbindd/winbindd_misc.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index 6cf3342..8c3278d 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -78,11 +78,25 @@ static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
 
 static bool trust_is_transitive(struct winbindd_tdc_domain *domain)
 {
-	if ((domain->trust_attribs == LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) ||
-	    (domain->trust_attribs == LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) ||
-	    (domain->trust_attribs == LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL))
-		return False;
-	return True;
+	bool transitive = false;
+
+	if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
+		transitive = true;
+	}
+
+	if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
+		transitive = true;
+	}
+
+	if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
+		transitive = false;
+	}
+
+	if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
+		transitive = false;
+	}
+
+	return transitive;
 }
 
 void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
-- 
2.7.4


From 3bcc44675220fcd2851681abfd3d6a0c71262f6a Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 28 Nov 2017 17:44:41 +0100
Subject: [PATCH 2/5] winbindd: fix trust_is_inbound()

A trust is only inbound if NETR_TRUST_FLAG_IN_FOREST or NETR_TRUST_FLAG_INBOUND
is set. Trust flags = 0x0 does not imply an inbound trust.
---
 source3/winbindd/winbindd_misc.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index 8c3278d..d31f5c3 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -60,11 +60,13 @@ static const char *get_trust_type_string(struct winbindd_tdc_domain *domain)
 
 static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
 {
-	return (domain->trust_flags == 0x0) ||
-	    ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) ==
-            NETR_TRUST_FLAG_IN_FOREST) ||           		
-	    ((domain->trust_flags & NETR_TRUST_FLAG_INBOUND) ==
-	    NETR_TRUST_FLAG_INBOUND);      	
+	if (domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
+		return true;
+	}
+	if (domain->trust_flags & NETR_TRUST_FLAG_INBOUND) {
+		return true;
+	}
+	return false;
 }
 
 static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
-- 
2.7.4


From cf3881f04f5a8cb9348de4c2b59ef5bd46ae9f12 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 28 Nov 2017 17:46:03 +0100
Subject: [PATCH 3/5] winbindd: fix trust_is_oubound()

A trust is only inbound if NETR_TRUST_FLAG_IN_FOREST or NETR_TRUST_FLAG_OUTBOUND
is set. Trust flags = 0x0 does not imply an outbound trust.
---
 source3/winbindd/winbindd_misc.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index d31f5c3..402409a 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -71,11 +71,13 @@ static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
 
 static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
 {
-	return (domain->trust_flags == 0x0) ||
-	    ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) ==
-            NETR_TRUST_FLAG_IN_FOREST) ||           		
-	    ((domain->trust_flags & NETR_TRUST_FLAG_OUTBOUND) ==
-	    NETR_TRUST_FLAG_OUTBOUND);      	
+	if (domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
+		return true;
+	}
+	if (domain->trust_flags & NETR_TRUST_FLAG_OUTBOUND) {
+		return true;
+	}
+	return false;
 }
 
 static bool trust_is_transitive(struct winbindd_tdc_domain *domain)
-- 
2.7.4


From 38924804412d760917d410dd43937b443a1707d3 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 29 Nov 2017 10:10:38 +0100
Subject: [PATCH 4/5] winbindd: add add_trusted_domain_from_auth

Function to add a new trusted domain to the domain list and TDC after an
successfull authentication. On Member servers only, not on DCs though.
---
 source3/winbindd/winbindd_proto.h |  1 +
 source3/winbindd/winbindd_util.c  | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 8313699..d6526df 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -436,6 +436,7 @@ NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
 
 struct winbindd_domain *domain_list(void);
 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain);
+bool add_trusted_domain_from_auth(struct info3_text *info3);
 bool domain_is_forest_root(const struct winbindd_domain *domain);
 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
 			    struct timeval now, void *private_data);
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 7b443c7..e3d3fac 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -139,6 +139,42 @@ add_trusted_domain(const char *domain_name, const char *alt_name,
 	return add_trusted_domain_from_tdc(&tdc);
 }
 
+bool add_trusted_domain_from_auth(struct info3_text *info3)
+{
+	struct winbindd_domain *domain = NULL;
+	struct dom_sid domain_sid;
+	bool ok;
+
+	/*
+	 * We got a successfull auth from a domain that might not yet be in our
+	 * domain list. If we're a member we trust our DC who authenticated the
+	 * user from that domain and add the domain to our list on-the-fly. If
+	 * we're a DC we rely on configured trusts and don't add on-the-fly.
+	 */
+
+	if (IS_DC) {
+		return true;
+	}
+
+	ok = dom_sid_parse(info3->dom_sid, &domain_sid);
+	if (!ok) {
+		DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
+		return false;
+	}
+
+	domain = add_trusted_domain(info3->logon_dom, NULL, &domain_sid);
+	if (domain == NULL) {
+		/*
+		 * Could be an ignored domain
+		 */
+		DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
+			  info3->logon_dom, info3->dom_sid);
+		return false;
+	}
+
+	return true;
+}
+
 /* Add a trusted domain out of a trusted domain cache
    entry
 */
-- 
2.7.4


From 6ec9ea860ce0a231635481474f495058448aabad Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 29 Nov 2017 10:55:25 +0100
Subject: [PATCH 5/5] winbindd: use add_trusted_domain_from_auth

After a successfully authentication, ensure we have the users domain in our
domain list and the TDC.
---
 source3/winbindd/winbindd_pam_auth.c      | 13 +++++++++++++
 source3/winbindd/winbindd_pam_auth_crap.c | 32 +++++++++++++++++++++++++------
 2 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/source3/winbindd/winbindd_pam_auth.c b/source3/winbindd/winbindd_pam_auth.c
index 7ff4488..ccbcd7e 100644
--- a/source3/winbindd/winbindd_pam_auth.c
+++ b/source3/winbindd/winbindd_pam_auth.c
@@ -19,6 +19,7 @@
 
 #include "includes.h"
 #include "winbindd.h"
+#include "libcli/security/dom_sid.h"
 
 struct winbindd_pam_auth_state {
 	struct winbindd_request *request;
@@ -127,6 +128,18 @@ NTSTATUS winbindd_pam_auth_recv(struct tevent_req *req,
 		return status;
 	}
 
+	if (state->request->flags & WBFLAG_PAM_INFO3_TEXT) {
+		bool ok;
+
+		ok = add_trusted_domain_from_auth(
+			&state->response->data.auth.info3);
+		if (!ok) {
+			DBG_ERR("add_trusted_domain_from_auth failed\n");
+			set_auth_errors(response, NT_STATUS_LOGON_FAILURE);
+			return NT_STATUS_LOGON_FAILURE;
+		}
+	}
+
 	if (state->request->flags & WBFLAG_PAM_CACHED_LOGIN) {
 
 		/* Store in-memory creds for single-signon using ntlm_auth. */
diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c
index cfeafbc..f01d6c9 100644
--- a/source3/winbindd/winbindd_pam_auth_crap.c
+++ b/source3/winbindd/winbindd_pam_auth_crap.c
@@ -19,6 +19,7 @@
 
 #include "includes.h"
 #include "winbindd.h"
+#include "libcli/security/dom_sid.h"
 
 struct winbindd_pam_auth_crap_state {
 	struct winbindd_response *response;
@@ -45,10 +46,11 @@ struct tevent_req *winbindd_pam_auth_crap_send(
 		return NULL;
 	}
 
-	if (request->flags & WBFLAG_PAM_AUTH_PAC) {
+	state->flags = request->flags;
+
+	if (state->flags & WBFLAG_PAM_AUTH_PAC) {
 		NTSTATUS status;
 
-		state->flags = request->flags;
 		status = winbindd_pam_auth_pac_send(cli, &state->info3);
 		if (NT_STATUS_IS_OK(status)) {
 			/* Defer filling out response to recv */
@@ -131,13 +133,31 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req,
 		return status;
 	}
 
+	*response = *state->response;
+	response->result = WINBINDD_PENDING;
+	state->response = talloc_move(response, &state->response);
+
+	status = NT_STATUS(response->data.auth.nt_status);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	if (state->flags & WBFLAG_PAM_INFO3_TEXT) {
+		bool ok;
+
+		ok = add_trusted_domain_from_auth(
+			&state->response->data.auth.info3);
+		if (!ok) {
+			DBG_ERR("add_trusted_domain_from_auth failed\n");
+			set_auth_errors(response, NT_STATUS_LOGON_FAILURE);
+			return NT_STATUS_LOGON_FAILURE;
+		}
+	}
+
 	if (state->flags & WBFLAG_PAM_AUTH_PAC) {
 		return append_auth_data(response, response, state->flags,
 					state->info3, NULL, NULL);
 	}
 
-	*response = *state->response;
-	response->result = WINBINDD_PENDING;
-	state->response = talloc_move(response, &state->response);
-	return NT_STATUS(response->data.auth.nt_status);
+	return status;
 }
-- 
2.7.4



More information about the samba-technical mailing list