[PATCH] Correctly handle !authoritative in the rpc-based auth backends

Stefan Metzmacher metze at samba.org
Fri Apr 7 15:08:21 UTC 2017


Am 23.03.2017 um 17:51 schrieb Stefan Metzmacher via samba-technical:
> Hi,
> 
>>> To make progress, could we skip this part until we get a test to cover
>>> the different values, and keep this patch set to just the "no behaviour
>>> change"?
>>
>> Ok, here's part one for https://bugzilla.samba.org/show_bug.cgi?id=2976
> 
> Here's part 2 that also fixes
> https://bugzilla.samba.org/show_bug.cgi?id=12709
> https://bugzilla.samba.org/show_bug.cgi?id=12710

Version 3 of the patches is attached and can be found in
https://git.samba.org/?p=metze/samba/wip.git;a=shortlog;h=refs/heads/master3-auth-1

I've added some tests to show the key problem, the silent mapping from
users of trusted domain to local users for NTLM authentication.

Please review and push.

> And the fixes for (with the manpage change still TODO)
> https://bugzilla.samba.org/show_bug.cgi?id=8630

Version 3 of the patches is attached (but still WIP) and can be found in
https://git.samba.org/?p=metze/samba/wip.git;a=shortlog;h=refs/heads/master3-auth-2

Thanks!
metze
-------------- next part --------------
From fd3e04c9daf922bdc3b543e92aa8dfe707c1cfce Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Apr 2017 10:39:31 +0200
Subject: [PATCH 01/19] selftest: make sure we don't have any umask limitations
 for selftest

We create $prefix with 0700 (umask 0077), but everything else
should not have a umask limitation (by default).

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 selftest/selftest.pl | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/selftest/selftest.pl b/selftest/selftest.pl
index 45e0ae0..32fc845 100755
--- a/selftest/selftest.pl
+++ b/selftest/selftest.pl
@@ -307,8 +307,11 @@ die("using an empty prefix isn't allowed") unless $prefix ne "";
 # permissions on this as some subdirectories in this tree will have
 # wider permissions (ie 0777) and this would allow other users on the
 # host to subvert the test process.
+umask 0077;
 mkdir($prefix, 0700) unless -d $prefix;
 chmod 0700, $prefix;
+# We need to have no umask limitations for the tests.
+umask 0000;
 
 my $prefix_abs = abs_path($prefix);
 my $tmpdir_abs = abs_path("$prefix/tmp");
-- 
1.9.1


From d9a5d62c84913956c9d2aeeced4d9e029cf44c2a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 29 Mar 2017 11:53:18 +0200
Subject: [PATCH 02/19] testprogs/blackbox: use subunit_ helper functions in
 test_smbclient_*

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 testprogs/blackbox/common_test_fns.inc | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/testprogs/blackbox/common_test_fns.inc b/testprogs/blackbox/common_test_fns.inc
index aff1aa9..7e54c67 100755
--- a/testprogs/blackbox/common_test_fns.inc
+++ b/testprogs/blackbox/common_test_fns.inc
@@ -8,13 +8,13 @@ test_smbclient() {
 	shift
 	shift
 	shift
-	echo "test: $name"
-	$VALGRIND $smbclient $CONFIGURATION "$unc" -c "$cmd" $@
+	subunit_start_test "$name"
+	output=`$VALGRIND $smbclient $CONFIGURATION "$unc" -c "$cmd" $@ 2>&1`
 	status=$?
 	if [ x$status = x0 ]; then
-		echo "success: $name"
+		subunit_pass_test "$name"
 	else
-		echo "failure: $name"
+		echo "$output" | subunit_fail_test "$name"
 	fi
 	return $status
 }
@@ -26,13 +26,13 @@ test_smbclient_expect_failure() {
 	shift
 	shift
 	shift
-	echo "test: $name"
-	$VALGRIND $smbclient $CONFIGURATION "$unc" -c "$cmd" $@
+	subunit_start_test "$name"
+	output=`$VALGRIND $smbclient $CONFIGURATION "$unc" -c "$cmd" $@ 2>&1`
 	status=$?
 	if [ x$status = x0 ]; then
-		echo "failure: $name"
+		echo "$output" | subunit_fail_test "$name"
 	else
-		echo "success: $name"
+		subunit_pass_test "$name"
 	fi
 	return $status
 }
-- 
1.9.1


From cfabcf42fc6c91607130595f94714a1411e235e9 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 29 Mar 2017 11:53:41 +0200
Subject: [PATCH 03/19] testprogs/blackbox: add test_rpcclient_*_grep helper
 functions

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 testprogs/blackbox/common_test_fns.inc | 52 ++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/testprogs/blackbox/common_test_fns.inc b/testprogs/blackbox/common_test_fns.inc
index 7e54c67..f77879a 100755
--- a/testprogs/blackbox/common_test_fns.inc
+++ b/testprogs/blackbox/common_test_fns.inc
@@ -36,3 +36,55 @@ test_smbclient_expect_failure() {
 	fi
 	return $status
 }
+
+test_rpcclient_grep() {
+	name="$1"
+	cmd="$2"
+	srv="$3"
+	grep="$4"
+	shift
+	shift
+	shift
+	shift
+	subunit_start_test "$name"
+	output=`$VALGRIND $rpcclient $CONFIGURATION "$srv" -c "$cmd" $@ 2>&1`
+	status=$?
+	if [ x$status != x0 ]; then
+		echo "$output" | subunit_fail_test "$name"
+		return $status
+	fi
+	echo "$output" | grep -q "$grep"
+	gstatus=$?
+	if [ x$gstatus = x0 ]; then
+		subunit_pass_test "$name"
+	else
+		echo "$output" | subunit_fail_test "$name"
+	fi
+	return $status
+}
+
+test_rpcclient_expect_failure_grep() {
+	name="$1"
+	cmd="$2"
+	srv="$3"
+	grep="$4"
+	shift
+	shift
+	shift
+	shift
+	subunit_start_test "$name"
+	output=`$VALGRIND $rpcclient $CONFIGURATION "$srv" -c "$cmd" $@ 2>&1`
+	status=$?
+	if [ x$status = x0 ]; then
+		echo "$output" | subunit_fail_test "$name"
+		return $status
+	fi
+	echo "$output" | grep -q "$grep"
+	gstatus=$?
+	if [ x$gstatus = x0 ]; then
+		subunit_pass_test "$name"
+	else
+		echo "$output" | subunit_fail_test "$name"
+	fi
+	return $status
+}
-- 
1.9.1


From b95be631b04c28dc7e15aba755e049af177ba67c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 6 Apr 2017 15:34:01 +0200
Subject: [PATCH 04/19] auth4: use lpcfg_is_my_domain_or_realm() in
 authsam_want_check()

We also accept the domain to be the realm string.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/auth/ntlm/auth_sam.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c
index 391492a..f22aa30 100644
--- a/source4/auth/ntlm/auth_sam.c
+++ b/source4/auth/ntlm/auth_sam.c
@@ -660,8 +660,8 @@ static NTSTATUS authsam_want_check(struct auth_method_context *ctx,
 
 	is_local_name = lpcfg_is_myname(ctx->auth_ctx->lp_ctx,
 				  user_info->mapped.domain_name);
-	is_my_domain  = lpcfg_is_mydomain(ctx->auth_ctx->lp_ctx,
-				       user_info->mapped.domain_name); 
+	is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
+						 user_info->mapped.domain_name);
 
 	/* check whether or not we service this domain/workgroup name */
 	switch (lpcfg_server_role(ctx->auth_ctx->lp_ctx)) {
-- 
1.9.1


From 2928f1774a0db57522a7b1aa39f10bdd3c9c500c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 3 Apr 2017 00:19:48 +0200
Subject: [PATCH 05/19] winbindd: allow wbinfo -a REALM\\user to work on a DC

find_domain_from_name_noinit() find the correct domain based
on domain->alt_name, but the child for the local domain
fails to detect that winbindd_dual_auth_passdb() should be
used.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/winbindd/winbindd_pam.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index a466015..292f556 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1564,7 +1564,16 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx,
 
 	parse_domain_user(user, name_domain, name_user);
 
-	if (strequal(name_domain, get_global_sam_name())) {
+	/*
+	 * We check against domain->name instead of
+	 * name_domain, as find_auth_domain() ->
+	 * find_domain_from_name_noinit() already decided
+	 * that we are in a child for the correct domain.
+	 *
+	 * name_domain can also be lp_realm()
+	 * we need to check against domain->name.
+	 */
+	if (strequal(domain->name, get_global_sam_name())) {
 		DATA_BLOB chal_blob = data_blob_const(chal, sizeof(chal));
 
 		/* do password magic */
@@ -2004,7 +2013,16 @@ NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
 {
 	NTSTATUS result;
 
-	if (strequal(name_domain, get_global_sam_name())) {
+	/*
+	 * We check against domain->name instead of
+	 * name_domain, as find_auth_domain() ->
+	 * find_domain_from_name_noinit() already decided
+	 * that we are in a child for the correct domain.
+	 *
+	 * name_domain can also be lp_realm()
+	 * we need to check against domain->name.
+	 */
+	if (strequal(domain->name, get_global_sam_name())) {
 		DATA_BLOB chal_blob = data_blob_const(
 			chal, 8);
 
-- 
1.9.1


From b10c00b6a9fc88be0b1940f071bdcfdc54ddbe2b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 29 Mar 2017 11:41:31 +0200
Subject: [PATCH 06/19] testprogs/blackbox: add test_trust_ntlm.sh

This verifies that various domain/realm and username
combinations map to the correct user.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 testprogs/blackbox/test_trust_ntlm.sh | 164 ++++++++++++++++++++++++++++++++++
 1 file changed, 164 insertions(+)
 create mode 100755 testprogs/blackbox/test_trust_ntlm.sh

diff --git a/testprogs/blackbox/test_trust_ntlm.sh b/testprogs/blackbox/test_trust_ntlm.sh
new file mode 100755
index 0000000..44946bb
--- /dev/null
+++ b/testprogs/blackbox/test_trust_ntlm.sh
@@ -0,0 +1,164 @@
+#!/bin/sh
+# Copyright (C) 2017 Stefan Metzmacher <metze at samba.org>
+
+if [ $# -lt 12 ]; then
+cat <<EOF
+Usage: $# test_trust_ntlm.sh SERVER USERNAME PASSWORD REALM DOMAIN TRUST_USERNAME TRUST_PASSWORD TRUST_REALM TRUST_DOMAIN TYPE UNTRUSTED TRUST_ERROR
+EOF
+exit 1;
+fi
+
+SERVER=$1
+USERNAME=$2
+PASSWORD=$3
+REALM=$4
+DOMAIN=$5
+shift 5
+TRUST_USERNAME=$1
+TRUST_PASSWORD=$2
+TRUST_REALM=$3
+TRUST_DOMAIN=$4
+shift 4
+TYPE=$1
+UNTRUSTED=$2
+TRUST_ERROR=$3
+shift 3
+failed=0
+
+samba4bindir="$BINDIR"
+
+rpcclient="$samba4bindir/rpcclient"
+smbclient="$samba4bindir/smbclient"
+wbinfo="$samba4bindir/wbinfo"
+
+unc="//$SERVER/tmp"
+
+. `dirname $0`/subunit.sh
+. `dirname $0`/common_test_fns.inc
+
+CREDS="$DOMAIN\\$USERNAME%$PASSWORD"
+WBCREDS="$DOMAIN/$USERNAME%$PASSWORD"
+EXPCREDS="Account Name: $USERNAME, Authority Name: $DOMAIN"
+test_rpcclient_grep "Test01 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1`
+test_smbclient "Test01 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1`
+testit "Test01 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1`
+
+CREDS="$REALM\\$USERNAME%$PASSWORD"
+WBCREDS="$REALM/$USERNAME%$PASSWORD"
+EXPCREDS="Account Name: $USERNAME, Authority Name: $DOMAIN"
+test_rpcclient_grep "Test02 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1`
+test_smbclient "Test02 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1`
+testit "Test02 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1`
+
+CREDS="$USERNAME@$DOMAIN%$PASSWORD"
+WBCREDS="$USERNAME@$DOMAIN%$PASSWORD"
+if [ x"$TYPE" = x"member" ]; then
+	EXPFAIL="NT_STATUS_LOGON_FAILURE"
+	# rpcclient doesn't handle -Uuser at domain yet
+	#test_rpcclient_expect_failure_grep "Fail03 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPFAIL" -U$CREDS && failed=`expr $failed + 1`
+	test_smbclient_expect_failure "Fail03 smbclient with $CREDS" 'ls' "$unc" -U$CREDS && failed=`expr $failed + 1`
+	# winbindd doesn't handle user at domain yet
+	#testit_expect_failure "Fail03 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS && failed=`expr $failed + 1`
+else
+	EXPCREDS="Account Name: $USERNAME, Authority Name: $DOMAIN"
+	# rpcclient doesn't handle -Uuser at domain yet
+	#test_rpcclient_grep "Test03 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1`
+	test_smbclient "Test03 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1`
+	# winbindd doesn't handle user at domain yet
+	#testit "Test03 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1`
+fi
+
+CREDS="$USERNAME@$REALM%$PASSWORD"
+WBCREDS="$USERNAME@$REALM%$PASSWORD"
+if [ x"$TYPE" = x"member" ]; then
+	EXPFAIL="NT_STATUS_LOGON_FAILURE"
+	# rpcclient doesn't handle -Uuser at domain yet
+	#test_rpcclient_expect_failure_grep "Fail04 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPFAIL" -U$CREDS && failed=`expr $failed + 1`
+	test_smbclient_expect_failure "Fail04 smbclient with $CREDS" 'ls' "$unc" -U$CREDS && failed=`expr $failed + 1`
+	# winbindd doesn't handle user at domain yet
+	#testit_expect_failure "Fail04 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS && failed=`expr $failed + 1`
+else
+	EXPCREDS="Account Name: $USERNAME, Authority Name: $DOMAIN"
+	# rpcclient doesn't handle -Uuser at domain yet
+	#test_rpcclient_grep "Test04 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1`
+	test_smbclient "Test04 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1`
+	# winbindd doesn't handle user at domain yet
+	#testit "Test04 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1`
+fi
+
+CREDS="UNKNOWNDOMAIN\\$USERNAME%$PASSWORD"
+WBCREDS="UNKNOWNDOMAIN/$USERNAME%$PASSWORD"
+EXPCREDS="Account Name: $USERNAME, Authority Name: $DOMAIN"
+test_rpcclient_grep "Test05 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1`
+test_smbclient "Test05 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1`
+testit_expect_failure "Fail05 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1`
+
+CREDS="$TRUST_DOMAIN\\$USERNAME%$PASSWORD"
+WBCREDS="$TRUST_DOMAIN/$USERNAME%$PASSWORD"
+EXPFAIL="$TRUST_ERROR"
+test_rpcclient_expect_failure_grep "Fail06 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPFAIL" -U$CREDS && failed=`expr $failed + 1`
+test_smbclient_expect_failure "Fail06 smbclient with $CREDS" 'ls' "$unc" -U$CREDS && failed=`expr $failed + 1`
+testit_expect_failure "Fail06 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS && failed=`expr $failed + 1`
+
+CREDS="$TRUST_DOMAIN\\$TRUST_USERNAME%$TRUST_PASSWORD"
+WBCREDS="$TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD"
+EXPCREDS="Account Name: $TRUST_USERNAME, Authority Name: $TRUST_DOMAIN"
+test_rpcclient_grep "Test07 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1`
+test_smbclient "Test07 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1`
+testit "Test07 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1`
+
+CREDS="$TRUST_REALM\\$TRUST_USERNAME%$TRUST_PASSWORD"
+WBCREDS="$TRUST_REALM/$TRUST_USERNAME%$TRUST_PASSWORD"
+EXPCREDS="Account Name: $TRUST_USERNAME, Authority Name: $TRUST_DOMAIN"
+test_rpcclient_grep "Test08 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1`
+test_smbclient "Test08 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1`
+testit "Test08 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1`
+
+CREDS="$TRUST_USERNAME@$TRUST_DOMAIN%$TRUST_PASSWORD"
+WBCREDS="$TRUST_USERNAME@$TRUST_DOMAIN%$TRUST_PASSWORD"
+if [ x"$TRUST_REALM" = x"$TRUST_DOMAIN" ]; then
+	# NT4 domain
+	EXPFAIL="NT_STATUS_LOGON_FAILURE"
+	# rpcclient doesn't handle -Uuser at domain yet
+	#test_rpcclient_expect_failure_grep "Fail09 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPFAIL" -U$CREDS && failed=`expr $failed + 1`
+	test_smbclient_expect_failure "Fail09 smbclient with $CREDS" 'ls' "$unc" -U$CREDS && failed=`expr $failed + 1`
+	# winbindd doesn't handle user at domain yet
+	#testit_expect_failure "Fail09 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS && failed=`expr $failed + 1`
+else
+	EXPCREDS="Account Name: $TRUST_USERNAME, Authority Name: $TRUST_DOMAIN"
+	# rpcclient doesn't handle -Uuser at domain yet
+	#test_rpcclient_grep "Test09 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1`
+	test_smbclient "Test09 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1`
+	# winbindd doesn't handle user at domain yet
+	#testit "Test09 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1`
+fi
+
+CREDS="$TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD"
+WBCREDS="$TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD"
+if [ x"$TRUST_REALM" = x"$TRUST_DOMAIN" ]; then
+	# NT4 domain
+	EXPFAIL="NT_STATUS_LOGON_FAILURE"
+	# rpcclient doesn't handle -Uuser at domain yet
+	#test_rpcclient_expect_failure_grep "Fail10 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPFAIL" -U$CREDS && failed=`expr $failed + 1`
+	test_smbclient_expect_failure "Fail10 smbclient with $CREDS" 'ls' "$unc" -U$CREDS && failed=`expr $failed + 1`
+	# winbindd doesn't handle user at domain yet
+	#testit_expect_failure "Fail10 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS && failed=`expr $failed + 1`
+else
+	EXPCREDS="Account Name: $TRUST_USERNAME, Authority Name: $TRUST_DOMAIN"
+	# rpcclient doesn't handle -Uuser at domain yet, maybe smbclient for now?
+	#test_rpcclient_grep "Test10 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1`
+	test_smbclient "Test10 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1`
+	# winbindd doesn't handle user at domain yet
+	#testit "Test10 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1`
+fi
+
+lowerrealm=$(echo $TRUST_REALM | tr '[A-Z]' '[a-z]')
+
+if test x$TYPE = x"forest"; then
+
+fi
+
+if test x$UNTRUSTED = x"yes"; then
+
+fi
+exit $failed
-- 
1.9.1


From 5e813a8e0016ee822976e80869179e791e2ea95c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 6 Apr 2017 19:44:16 +0200
Subject: [PATCH 07/19] s4:selftest: run test_trust_ntlm.sh against various
 environments

This shows that NTLM authentication is currently completely broken
on an DCs of AD domains with trusts.

Currently we completely ignore the client provided domain
and try to authenticate against the username in our local sam.ldb.

If the same username/password combination exists in both domains,
the user of the trusted domain silenty impersonates the user
of the local domain.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 selftest/knownfail        | 14 ++++++++++++++
 source4/selftest/tests.py |  4 ++++
 2 files changed, 18 insertions(+)

diff --git a/selftest/knownfail b/selftest/knownfail
index 07b4cdb..0df493d 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -317,3 +317,17 @@
 # rap password tests don't function in the ad_dc_ntvfs:local environment
 #
 ^samba.tests.auth_log_pass_change.samba.tests.auth_log_pass_change.AuthLogPassChangeTests.test_rap_change_password\(ad_dc_ntvfs:local\)
+#
+# The following should pass once we have trust support
+^samba4.blackbox.trust_ntlm.Test07.*client.*with.ADDOMAIN\\Administrator%locDCpass1\(fl2008r2dc:local\)
+^samba4.blackbox.trust_ntlm.Test08.*client.*with.ADDOM.SAMBA.EXAMPLE.COM\\Administrator%locDCpass1\(fl2008r2dc:local\)
+^samba4.blackbox.trust_ntlm.Test09.*client.*with.Administrator at ADDOMAIN%locDCpass1\(fl2008r2dc:local\)
+^samba4.blackbox.trust_ntlm.Test10.*client.*with.Administrator at ADDOM.SAMBA.EXAMPLE.COM%locDCpass1\(fl2008r2dc:local\)
+^samba4.blackbox.trust_ntlm.Test07.*client.*with.ADDOMAIN\\Administrator%locDCpass1\(fl2003dc:local\)
+^samba4.blackbox.trust_ntlm.Test08.*client.*with.ADDOM.SAMBA.EXAMPLE.COM\\Administrator%locDCpass1\(fl2003dc:local\)
+^samba4.blackbox.trust_ntlm.Test09.*client.*with.Administrator at ADDOMAIN%locDCpass1\(fl2003dc:local\)
+^samba4.blackbox.trust_ntlm.Test10.*client.*with.Administrator at ADDOM.SAMBA.EXAMPLE.COM%locDCpass1\(fl2003dc:local\)
+#
+# The following should work once we don't map trusts to our domain
+^samba4.blackbox.trust_ntlm.Fail06.*client.*with.ADDOMAIN\\Administrator%locDCpass7\(fl2008r2dc:local\)
+^samba4.blackbox.trust_ntlm.Fail06.*client.*with.ADDOMAIN\\Administrator%locDCpass6\(fl2003dc:local\)
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 6564ac7..623aca7 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -398,6 +398,10 @@ if have_heimdal_support:
     plantestsuite("samba4.blackbox.export.keytab(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_export_keytab_heimdal.sh"), '$SERVER', '$USERNAME', '$REALM', '$DOMAIN', "$PREFIX", smbclient4])
     plantestsuite("samba4.blackbox.kpasswd(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kpasswd_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc_ntvfs"])
 
+plantestsuite("samba4.blackbox.trust_ntlm", "fl2008r2dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'forest', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
+plantestsuite("samba4.blackbox.trust_ntlm", "fl2003dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'external', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
+plantestsuite("samba4.blackbox.trust_ntlm", "ad_member:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$SERVER', '$SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$REALM', '$DOMAIN', 'member', 'auto', 'NT_STATUS_LOGON_FAILURE'])
+plantestsuite("samba4.blackbox.trust_ntlm", "nt4_member:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$SERVER', '$SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$DOMAIN', '$DOMAIN', 'member', 'auto', 'NT_STATUS_LOGON_FAILURE'])
 plantestsuite("samba4.blackbox.trust_utils(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_trust_utils.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "forest"])
 plantestsuite("samba4.blackbox.trust_utils(fl2003dc:local)", "fl2003dc:local", [os.path.join(bbdir, "test_trust_utils.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external"])
 plantestsuite("samba4.blackbox.ktpass(ad_dc_ntvfs)", "ad_dc_ntvfs", [os.path.join(bbdir, "test_ktpass.sh"), '$PREFIX/ad_dc_ntvfs'])
-- 
1.9.1


From 0d66cd93011aabd6e29f1569c66422fcc27002d1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 22 Mar 2017 10:37:22 +0100
Subject: [PATCH 08/19] auth4: add a "sam_failtrusts" module

This fails the authentication for any known domain with
NT_STATUS_NO_TRUST_LSA_SECRET.

This will be used on an AD_DC to fail authentication
for users of trusted domains sanely, instead of silently
mapping them to local users.

This is just a temporary solution, until we have full
async support in the gensec/auth4.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/auth/ntlm/auth_sam.c | 96 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 95 insertions(+), 1 deletion(-)

diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c
index f22aa30..17d66db 100644
--- a/source4/auth/ntlm/auth_sam.c
+++ b/source4/auth/ntlm/auth_sam.c
@@ -689,7 +689,89 @@ static NTSTATUS authsam_want_check(struct auth_method_context *ctx,
 	return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-				   
+static NTSTATUS authsam_failtrusts_want_check(struct auth_method_context *ctx,
+					      TALLOC_CTX *mem_ctx,
+					      const struct auth_usersupplied_info *user_info)
+{
+	const char *effective_domain = user_info->mapped.domain_name;
+	struct dsdb_trust_routing_table *trt = NULL;
+	const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
+	NTSTATUS status;
+
+	/* check whether or not we service this domain/workgroup name */
+	switch (lpcfg_server_role(ctx->auth_ctx->lp_ctx)) {
+	case ROLE_ACTIVE_DIRECTORY_DC:
+		/* handled later */
+		break;
+
+	default:
+		DBG_ERR("lpcfg_server_role() has an undefined value\n");
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	/*
+	 * Now we handle the AD DC case...
+	 */
+	if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	if (effective_domain == NULL || strequal(effective_domain, "")) {
+		const char *p = NULL;
+
+		p = strchr_m(user_info->mapped.account_name, '@');
+		if (p != NULL) {
+			effective_domain = p + 1;
+		}
+	}
+
+	if (effective_domain == NULL || strequal(effective_domain, "")) {
+		DBG_DEBUG("%s is not a trusted domain\n",
+			  effective_domain);
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	/*
+	 * as last option we check the routing table if the
+	 * domain is within our forest.
+	 */
+	status = dsdb_trust_routing_table_load(ctx->auth_ctx->sam_ctx,
+					       mem_ctx, &trt);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("authsam_check_password: dsdb_trust_routing_table_load() %s\n",
+			 nt_errstr(status));
+		return status;
+	}
+
+	tdo = dsdb_trust_routing_by_name(trt, effective_domain);
+	if (tdo == NULL) {
+		DBG_DEBUG("%s is not a known TLN (DC)\n",
+			  effective_domain);
+		TALLOC_FREE(trt);
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	/*
+	 * We now about the domain...
+	 */
+	TALLOC_FREE(trt);
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS authsam_failtrusts_check_password(struct auth_method_context *ctx,
+						  TALLOC_CTX *mem_ctx,
+						  const struct auth_usersupplied_info *user_info,
+						  struct auth_user_info_dc **user_info_dc)
+{
+	/*
+	 * This should a good error for now,
+	 * until this module gets removed
+	 * and we have a full async path
+	 * to winbind.
+	 */
+	return NT_STATUS_NO_TRUST_LSA_SECRET;
+}
+
 /* Wrapper for the auth subsystem pointer */
 static NTSTATUS authsam_get_user_info_dc_principal_wrapper(TALLOC_CTX *mem_ctx,
 							  struct auth4_context *auth_context,
@@ -714,6 +796,12 @@ static const struct auth_operations sam_ops = {
 	.get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper,
 };
 
+static const struct auth_operations sam_failtrusts_ops = {
+	.name		           = "sam_failtrusts",
+	.want_check	           = authsam_failtrusts_want_check,
+	.check_password	           = authsam_failtrusts_check_password,
+};
+
 _PUBLIC_ NTSTATUS auth4_sam_init(void);
 _PUBLIC_ NTSTATUS auth4_sam_init(void)
 {
@@ -731,5 +819,11 @@ _PUBLIC_ NTSTATUS auth4_sam_init(void)
 		return ret;
 	}
 
+	ret = auth_register(&sam_failtrusts_ops);
+	if (!NT_STATUS_IS_OK(ret)) {
+		DEBUG(0,("Failed to register 'sam_failtrusts' auth backend!\n"));
+		return ret;
+	}
+
 	return ret;
 }
-- 
1.9.1


From 61e89873bb1f3406a566a603ec81a7ff337294e3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 17 Mar 2017 14:54:16 +0100
Subject: [PATCH 09/19] auth4: use "anonymous sam winbind_rodc sam_failtrusts
 sam_ignoredomain" as AD_DC

It's better to consistently fail authentications for users
of trusted domains (on a RWDC) with NT_STATUS_NO_TRUST_LSA_SECRET,
instead of silently mapping them to local users, by accident.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/auth/ntlm/auth.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index ecb7d6b..f366fb1 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -650,7 +650,20 @@ const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *
 	case ROLE_DOMAIN_BDC:
 	case ROLE_DOMAIN_PDC:
 	case ROLE_ACTIVE_DIRECTORY_DC:
-		auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain winbind_rodc", NULL);
+		/*
+		 * TODO: we should replace "winbind_rodc sam_failtrusts" with "winbind"
+		 * if everything (gensec/auth4) is fully async without nested
+		 * event loops!
+		 *
+		 * But for now we'll fail authentications for trusted
+		 * domain consistently with NT_STATUS_NO_TRUST_LSA_SECRET,
+		 * instead of silently mapping to local users.
+		 */
+		auth_methods = str_list_make(mem_ctx,
+					     "anonymous sam "
+					     "winbind_rodc sam_failtrusts "
+					     "sam_ignoredomain",
+					     NULL);
 		break;
 	}
 	return discard_const_p(const char *, auth_methods);
-- 
1.9.1


From 4fdd3a67530f45eb641bb2a5522b67258b5357ab Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 22 Mar 2017 10:45:25 +0100
Subject: [PATCH 10/19] auth4: use "anonymous sam winbind sam_ignoredomain"
 with ROLE_DOMAIN_MEMBER

We hopefully remove this role in future, but for now we should do this
correct and fallback to sam_ignoredomain at the end of the auth chain.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/auth/ntlm/auth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index f366fb1..078b08b 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -645,7 +645,7 @@ const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *
 		auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
 		break;
 	case ROLE_DOMAIN_MEMBER:
-		auth_methods = str_list_make(mem_ctx, "anonymous sam winbind", NULL);
+		auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
 		break;
 	case ROLE_DOMAIN_BDC:
 	case ROLE_DOMAIN_PDC:
-- 
1.9.1


From 3ab6b43c678a31554cf9f6e2c3f659b1b1caf65b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 17 Mar 2017 14:57:33 +0100
Subject: [PATCH 11/19] auth4: let authsam_check_password_internals use
 crack_name_to_nt4_name() for upn's

Currently the caller does this before calling the auth backends,
but that should change in order to support trusted domains correctly.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/auth/ntlm/auth_sam.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c
index 17d66db..886371a 100644
--- a/source4/auth/ntlm/auth_sam.c
+++ b/source4/auth/ntlm/auth_sam.c
@@ -580,6 +580,7 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx
 	struct ldb_dn *domain_dn;
 	DATA_BLOB user_sess_key, lm_sess_key;
 	TALLOC_CTX *tmp_ctx;
+	const char *p = NULL;
 
 	if (ctx->auth_ctx->sam_ctx == NULL) {
 		DEBUG(0, ("No SAM available, cannot log in users\n"));
@@ -602,6 +603,43 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx
 		return NT_STATUS_NO_SUCH_DOMAIN;
 	}
 
+	p = strchr_m(account_name, '@');
+	if (p != NULL) {
+		const char *nt4_domain = NULL;
+		const char *nt4_account = NULL;
+		bool is_my_domain = false;
+
+		nt_status = crack_name_to_nt4_name(mem_ctx,
+						   ctx->auth_ctx->event_ctx,
+						   ctx->auth_ctx->lp_ctx,
+						   /*
+						    * DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON ?
+						    */
+						   DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
+						   account_name,
+						   &nt4_domain, &nt4_account);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			talloc_free(tmp_ctx);
+			return NT_STATUS_NO_SUCH_USER;
+		}
+
+		is_my_domain = lpcfg_is_mydomain(ctx->auth_ctx->lp_ctx, nt4_domain);
+		if (!is_my_domain) {
+			/*
+			 * This is a user within our forest,
+			 * but in a different domain,
+			 * we're not authoritative
+			 */
+			talloc_free(tmp_ctx);
+			return NT_STATUS_NOT_IMPLEMENTED;
+		}
+
+		/*
+		 * Let's use the NT4 account name for the lookup.
+		 */
+		account_name = nt4_account;
+	}
+
 	nt_status = authsam_search_account(tmp_ctx, ctx->auth_ctx->sam_ctx, account_name, domain_dn, &msg);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		talloc_free(tmp_ctx);
-- 
1.9.1


From c57bedf36bffe6478a0da2bb402dfd9ce25306ac Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 17 Mar 2017 16:31:02 +0100
Subject: [PATCH 12/19] auth4: improve authsam_want_check for upn
 authentication

We need to check if the upn suffix is within our forest.
The check if it's within our domain is done in
authsam_check_password_internals() after calling
crack_name_to_nt4_name().

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/auth/ntlm/auth_sam.c | 123 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 103 insertions(+), 20 deletions(-)

diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c
index 886371a..1c7fd90 100644
--- a/source4/auth/ntlm/auth_sam.c
+++ b/source4/auth/ntlm/auth_sam.c
@@ -690,41 +690,124 @@ static NTSTATUS authsam_want_check(struct auth_method_context *ctx,
 				   TALLOC_CTX *mem_ctx,
 				   const struct auth_usersupplied_info *user_info)
 {
-	bool is_local_name, is_my_domain;
+	const char *effective_domain = user_info->mapped.domain_name;
+	bool is_local_name = false;
+	bool is_my_domain = false;
+	const char *p = NULL;
+	struct dsdb_trust_routing_table *trt = NULL;
+	const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
+	NTSTATUS status;
 
 	if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
 		return NT_STATUS_NOT_IMPLEMENTED;
 	}
 
 	is_local_name = lpcfg_is_myname(ctx->auth_ctx->lp_ctx,
-				  user_info->mapped.domain_name);
-	is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
-						 user_info->mapped.domain_name);
+					effective_domain);
 
 	/* check whether or not we service this domain/workgroup name */
 	switch (lpcfg_server_role(ctx->auth_ctx->lp_ctx)) {
-		case ROLE_STANDALONE:
-			return NT_STATUS_OK;
+	case ROLE_STANDALONE:
+		return NT_STATUS_OK;
 
-		case ROLE_DOMAIN_MEMBER:
-			if (!is_local_name) {
-				DEBUG(6,("authsam_check_password: %s is not one of my local names (DOMAIN_MEMBER)\n",
-					user_info->mapped.domain_name));
-				return NT_STATUS_NOT_IMPLEMENTED;
-			}
+	case ROLE_DOMAIN_MEMBER:
+		if (is_local_name) {
 			return NT_STATUS_OK;
+		}
 
-		case ROLE_ACTIVE_DIRECTORY_DC:
-			if (!is_local_name && !is_my_domain) {
-				DEBUG(6,("authsam_check_password: %s is not one of my local names or domain name (DC)\n",
-					user_info->mapped.domain_name));
-				return NT_STATUS_NOT_IMPLEMENTED;
-			}
+		DBG_DEBUG("%s is not one of my local names (DOMAIN_MEMBER)\n",
+			  effective_domain);
+		return NT_STATUS_NOT_IMPLEMENTED;
+
+	case ROLE_ACTIVE_DIRECTORY_DC:
+		/* handled later */
+		break;
+
+	default:
+		DBG_ERR("lpcfg_server_role() has an undefined value\n");
+		return NT_STATUS_INVALID_SERVER_STATE;
+	}
+
+	/*
+	 * Now we handle the AD DC case...
+	 */
+
+	is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
+						   effective_domain);
+	if (is_my_domain) {
+		return NT_STATUS_OK;
+	}
+
+	if (user_info->mapped_state) {
+		/*
+		 * The caller already did a cracknames call.
+		 */
+		DBG_DEBUG("%s is not one domain name (DC)\n",
+			  effective_domain);
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	if (effective_domain != NULL && !strequal(effective_domain, "")) {
+		DBG_DEBUG("%s is not one domain name (DC)\n",
+			  effective_domain);
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	p = strchr_m(user_info->mapped.account_name, '@');
+	if (p == NULL) {
+		if (effective_domain == NULL) {
 			return NT_STATUS_OK;
+		}
+		DEBUG(6,("authsam_check_password: '' without upn not handled (DC)\n"));
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	effective_domain = p + 1;
+	is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
+						   effective_domain);
+	if (is_my_domain) {
+		return NT_STATUS_OK;
+	}
+
+	if (strequal(effective_domain, "")) {
+		DBG_DEBUG("authsam_check_password: upn without realm (DC)\n");
+		return NT_STATUS_NOT_IMPLEMENTED;
 	}
 
-	DEBUG(6,("authsam_check_password: lpcfg_server_role() has an undefined value\n"));
-	return NT_STATUS_NOT_IMPLEMENTED;
+	/*
+	 * as last option we check the routing table if the
+	 * domain is within our forest.
+	 */
+	status = dsdb_trust_routing_table_load(ctx->auth_ctx->sam_ctx,
+					       mem_ctx, &trt);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("authsam_check_password: dsdb_trust_routing_table_load() %s\n",
+			 nt_errstr(status));
+		return status;
+	}
+
+	tdo = dsdb_trust_routing_by_name(trt, effective_domain);
+	if (tdo == NULL) {
+		DBG_DEBUG("%s is not a known TLN (DC)\n",
+			  effective_domain);
+		TALLOC_FREE(trt);
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	if (!(tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
+		DBG_DEBUG("%s is not a TLN in our forest (DC)\n",
+			  effective_domain);
+		TALLOC_FREE(trt);
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	/*
+	 * This principal is within our forest.
+	 * we'll later do a crack_name_to_nt4_name()
+	 * to check if it's in our domain.
+	 */
+	TALLOC_FREE(trt);
+	return NT_STATUS_OK;
 }
 
 static NTSTATUS authsam_failtrusts_want_check(struct auth_method_context *ctx,
-- 
1.9.1


From 9166e582f8fd0d16db3053653a89256dfca8eb3b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 17 Mar 2017 16:19:10 +0100
Subject: [PATCH 13/19] auth4: avoid map_user_info() in
 auth_check_password_send()

The cracknames call is done in the "sam" backend now.

In order to support trusted domains correctly, the backends
need to get the raw values from the client.

This is the important change in order to no longer
silently map users from trusted domains to local users.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 selftest/knownfail       |  4 ----
 source4/auth/ntlm/auth.c | 35 +++++++++++++++++++++++++----------
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/selftest/knownfail b/selftest/knownfail
index 0df493d..98c9708 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -327,7 +327,3 @@
 ^samba4.blackbox.trust_ntlm.Test08.*client.*with.ADDOM.SAMBA.EXAMPLE.COM\\Administrator%locDCpass1\(fl2003dc:local\)
 ^samba4.blackbox.trust_ntlm.Test09.*client.*with.Administrator at ADDOMAIN%locDCpass1\(fl2003dc:local\)
 ^samba4.blackbox.trust_ntlm.Test10.*client.*with.Administrator at ADDOM.SAMBA.EXAMPLE.COM%locDCpass1\(fl2003dc:local\)
-#
-# The following should work once we don't map trusts to our domain
-^samba4.blackbox.trust_ntlm.Fail06.*client.*with.ADDOMAIN\\Administrator%locDCpass7\(fl2008r2dc:local\)
-^samba4.blackbox.trust_ntlm.Fail06.*client.*with.ADDOMAIN\\Administrator%locDCpass6\(fl2003dc:local\)
diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index 078b08b..0843f4a 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -291,24 +291,39 @@ _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
 	state->user_info	= user_info;
 
 	if (!user_info->mapped_state) {
-		int server_role = lpcfg_server_role(auth_ctx->lp_ctx);
 		struct auth_usersupplied_info *user_info_tmp;
 
-		nt_status = map_user_info(
-			auth_ctx->sam_ctx, req,
-			server_role == ROLE_ACTIVE_DIRECTORY_DC,
-			lpcfg_workgroup(auth_ctx->lp_ctx),
-			user_info, &user_info_tmp);
-
-		if (tevent_req_nterror(req, nt_status)) {
-			return tevent_req_post(req, ev);
+		/*
+		 * We don't really do any mapping here.
+		 *
+		 * So we don't set user_info->mapped_state,
+		 * but we set mapped.domain_name and
+		 * mapped.account_name to the client
+		 * provided values.
+		 *
+		 * It's up to the backends to do mappings
+		 * for their authentication.
+		 */
+		user_info_tmp = talloc_zero(state, struct auth_usersupplied_info);
+		if (tevent_req_nomem(user_info_tmp, req)) {
+			return tevent_req_post(req, ev);;
 		}
+
+		/*
+		 * The lifetime of user_info is longer than
+		 * user_info_tmp, so we don't need to copy the
+		 * strings.
+		 */
+		*user_info_tmp = *user_info;
+		user_info_tmp->mapped.domain_name = user_info->client.domain_name;
+		user_info_tmp->mapped.account_name = user_info->client.account_name;
+
 		user_info = user_info_tmp;
 		state->user_info = user_info_tmp;
 	}
 
 	DEBUGADD(3,("auth_check_password_send: "
-		    "mapped user is: [%s]\\[%s]@[%s]\n",
+		    "user is: [%s]\\[%s]@[%s]\n",
 		    user_info->mapped.domain_name,
 		    user_info->mapped.account_name,
 		    user_info->workstation_name));
-- 
1.9.1


From 79d1c6254da9e3b456b905d0b6aebf9c323a271a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 17 Mar 2017 16:21:05 +0100
Subject: [PATCH 14/19] auth4: remove unused map_user_info[_cracknames]()

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12709

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/auth/ntlm/auth_util.c | 259 ------------------------------------------
 1 file changed, 259 deletions(-)

diff --git a/source4/auth/ntlm/auth_util.c b/source4/auth/ntlm/auth_util.c
index e3d196c..7feb20b 100644
--- a/source4/auth/ntlm/auth_util.c
+++ b/source4/auth/ntlm/auth_util.c
@@ -41,265 +41,6 @@ NTSTATUS auth_get_challenge_not_implemented(struct auth_method_context *ctx, TAL
 /****************************************************************************
  Create an auth_usersupplied_data structure after appropriate mapping.
 ****************************************************************************/
-static NTSTATUS map_user_info_cracknames(struct ldb_context *sam_ctx,
-					 TALLOC_CTX *mem_ctx,
-					 const char *default_domain,
-					 const struct auth_usersupplied_info *user_info,
-					 struct auth_usersupplied_info **user_info_mapped)
-{
-	char *domain;
-	char *account_name;
-	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-	WERROR werr;
-	struct drsuapi_DsNameInfo1 info1;
-
-	DEBUG(5,("map_user_info_cracknames: Mapping user [%s]\\[%s] from workstation [%s]\n",
-		 user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name));
-
-	account_name = talloc_strdup(tmp_ctx, user_info->client.account_name);
-	if (!account_name) {
-		talloc_free(tmp_ctx);
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	/* use cracknames to work out what domain is being
-	   asked for */
-	if (strchr_m(user_info->client.account_name, '@') != NULL) {
-		werr = DsCrackNameOneName(sam_ctx, tmp_ctx, 0,
-					  DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
-					  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
-					  user_info->client.account_name,
-					  &info1);
-		if (!W_ERROR_IS_OK(werr)) {
-			DEBUG(2,("map_user_info: Failed cracknames of account '%s'\n",
-				 user_info->client.account_name));
-			talloc_free(tmp_ctx);
-			return werror_to_ntstatus(werr);
-		}
-		switch (info1.status) {
-		case DRSUAPI_DS_NAME_STATUS_OK:
-			break;
-		case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
-			DEBUG(2,("map_user_info: Cracknames of account '%s' -> NOT_FOUND\n",
-				 user_info->client.account_name));
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
-		case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
-			DEBUG(2,("map_user_info: Cracknames of account '%s' -> DOMAIN_ONLY\n",
-				 user_info->client.account_name));
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
-		case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
-			DEBUG(2,("map_user_info: Cracknames of account '%s' -> NOT_UNIQUE\n",
-				 user_info->client.account_name));
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
-		case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
-			DEBUG(2,("map_user_info: Cracknames of account '%s' -> RESOLVE_ERROR\n",
-				 user_info->client.account_name));
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
-		default:
-			DEBUG(2,("map_user_info: Cracknames of account '%s' -> unknown error %u\n",
-				 user_info->client.account_name, info1.status));
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
-		}
-		/* info1.result_name is in DOMAIN\username
-		 * form, which we need to split up into the
-		 * user_info_mapped structure
-		 */
-		domain = talloc_strdup(tmp_ctx, info1.result_name);
-		if (domain == NULL) {
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_MEMORY;
-		}
-		account_name = strchr_m(domain, '\\');
-		if (account_name == NULL) {
-			DEBUG(2,("map_user_info: Cracknames of account '%s' gave invalid result '%s'\n",
-				 user_info->client.account_name, info1.result_name));
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
-		}
-		*account_name = 0;
-		account_name = talloc_strdup(tmp_ctx, account_name+1);
-		if (account_name == NULL) {
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_MEMORY;
-		}
-	} else {
-		const char *domain_name = default_domain;
-		if (user_info->client.domain_name && *user_info->client.domain_name) {
-			domain_name = user_info->client.domain_name;
-		}
-		domain_name = talloc_asprintf(tmp_ctx, "%s\\", domain_name);
-		if (domain_name == NULL) {
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_MEMORY;
-		}
-		werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
-					  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
-					  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
-					  domain_name,
-					  &info1);
-		if (!W_ERROR_IS_OK(werr)) {
-			DEBUG(2,("map_user_info: Failed cracknames of domain '%s'\n",
-				 domain_name));
-			talloc_free(tmp_ctx);
-			return werror_to_ntstatus(werr);
-		}
-
-		/* we use the account_name as-is, but get the
-		 * domain name from cracknames if possible */
-		account_name = talloc_strdup(mem_ctx, user_info->client.account_name);
-		if (account_name == NULL) {
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_MEMORY;
-		}
-
-		switch (info1.status) {
-		case DRSUAPI_DS_NAME_STATUS_OK:
-		case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY:
-			domain = talloc_strdup(tmp_ctx, info1.result_name);
-			if (domain == NULL) {
-				talloc_free(tmp_ctx);
-				return NT_STATUS_NO_MEMORY;
-			}
-			if (domain[strlen_m(domain)-1] == '\\') {
-				domain[strlen_m(domain)-1] = 0;
-			}
-			break;
-		case DRSUAPI_DS_NAME_STATUS_NOT_FOUND:
-			/* the domain is unknown - use the
-			   default domain */
-			domain = talloc_strdup(tmp_ctx, default_domain);
-			break;
-		case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE:
-			DEBUG(2,("map_user_info: Cracknames of domain '%s' -> NOT_UNIQUE\n",
-				 domain_name));
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
-		case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR:
-			DEBUG(2,("map_user_info: Cracknames of domain '%s' -> RESOLVE_ERROR\n",
-				 domain_name));
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
-		default:
-			DEBUG(2,("map_user_info: Cracknames of account '%s' -> unknown error %u\n",
-				 domain_name, info1.status));
-			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
-		}
-		/* domain and account_name are filled in above */
-	}
-
-	*user_info_mapped = talloc_zero(mem_ctx, struct auth_usersupplied_info);
-	if (!*user_info_mapped) {
-		talloc_free(tmp_ctx);
-		return NT_STATUS_NO_MEMORY;
-	}
-	if (!talloc_reference(*user_info_mapped, user_info)) {
-		talloc_free(tmp_ctx);
-		return NT_STATUS_NO_MEMORY;
-	}
-	**user_info_mapped = *user_info;
-	(*user_info_mapped)->mapped_state = true;
-	(*user_info_mapped)->mapped.domain_name = talloc_strdup(*user_info_mapped, domain);
-	(*user_info_mapped)->mapped.account_name = talloc_strdup(*user_info_mapped, account_name);
-	talloc_free(tmp_ctx);
-	if (!(*user_info_mapped)->mapped.domain_name
-	    || !(*user_info_mapped)->mapped.account_name) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	return NT_STATUS_OK;
-}
-
-
-/****************************************************************************
- Create an auth_usersupplied_data structure after appropriate mapping.
-****************************************************************************/
-NTSTATUS map_user_info(struct ldb_context *sam_ctx,
-		       TALLOC_CTX *mem_ctx,
-		       bool is_ad_dc,
-		       const char *default_domain,
-		       const struct auth_usersupplied_info *user_info,
-		       struct auth_usersupplied_info **user_info_mapped)
-{
-	char *domain;
-	char *account_name;
-	char *d;
-	TALLOC_CTX *tmp_ctx;
-
-	if (is_ad_dc) {
-		/* if possible, use cracknames to parse the
-		   domain/account */
-		return map_user_info_cracknames(sam_ctx, mem_ctx, default_domain, user_info, user_info_mapped);
-	}
-
-	DEBUG(0,("map_user_info: Mapping user [%s]\\[%s] from workstation [%s] default_domain=%s\n",
-		 user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name,
-		 default_domain));
-
-	tmp_ctx = talloc_new(mem_ctx);
-
-	account_name = talloc_strdup(tmp_ctx, user_info->client.account_name);
-	if (!account_name) {
-		talloc_free(tmp_ctx);
-		return NT_STATUS_NO_MEMORY;
-	}
-	
-	/* don't allow "" as a domain, fixes a Win9X bug where it
-	   doesn't supply a domain for logon script 'net use'
-	   commands.  */
-
-	/* Split user at realm names into user and realm components.
-	 * This is TODO to fix with proper userprincipalname
-	 * support */
-	if (user_info->client.domain_name && *user_info->client.domain_name) {
-		domain = talloc_strdup(tmp_ctx, user_info->client.domain_name);
-	} else if (strchr_m(user_info->client.account_name, '@')) {
-		d = strchr_m(account_name, '@');
-		if (!d) {
-			talloc_free(tmp_ctx);
-			return NT_STATUS_INTERNAL_ERROR;
-		}
-		d[0] = '\0';
-		d++;
-		domain = d;
-	} else {
-		domain = talloc_strdup(tmp_ctx, default_domain);
-	}
-
-	if (domain == NULL) {
-		talloc_free(tmp_ctx);
-		return NT_STATUS_NO_MEMORY;
-	}
-	*user_info_mapped = talloc_zero(mem_ctx, struct auth_usersupplied_info);
-	if (!*user_info_mapped) {
-		talloc_free(tmp_ctx);
-		return NT_STATUS_NO_MEMORY;
-	}
-	if (!talloc_reference(*user_info_mapped, user_info)) {
-		talloc_free(tmp_ctx);
-		return NT_STATUS_NO_MEMORY;
-	}
-	**user_info_mapped = *user_info;
-	(*user_info_mapped)->mapped_state = true;
-	(*user_info_mapped)->mapped.domain_name = talloc_strdup(*user_info_mapped, domain);
-	(*user_info_mapped)->mapped.account_name = talloc_strdup(*user_info_mapped, account_name);
-	talloc_free(tmp_ctx);
-	if (!(*user_info_mapped)->mapped.domain_name 
-	    || !(*user_info_mapped)->mapped.account_name) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Create an auth_usersupplied_data structure after appropriate mapping.
-****************************************************************************/
 
 NTSTATUS encrypt_user_info(TALLOC_CTX *mem_ctx, struct auth4_context *auth_context, 
 			   enum auth_password_state to_state,
-- 
1.9.1


From e058e09110469e571dce1495a11e6acf6a86fb0f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 17 Mar 2017 19:35:24 +0100
Subject: [PATCH 15/19] auth4: use "sam winbind_rodc sam_failtrusts" for the
 netlogon authentication

We should not do anonymous authentication nor a fallback that
ignores the domain part.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12710

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/auth/ntlm/auth.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index 0843f4a..56676bb 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -716,7 +716,40 @@ _PUBLIC_ NTSTATUS auth_context_create_for_netlogon(TALLOC_CTX *mem_ctx,
 						   struct loadparm_context *lp_ctx,
 						   struct auth4_context **auth_ctx)
 {
-	return auth_context_create(mem_ctx, ev, msg, lp_ctx, auth_ctx);
+	NTSTATUS status;
+	char **_auth_methods = NULL;
+	const char **auth_methods = NULL;
+
+	/*
+	 * As 'auth methods' is deprecated it will be removed
+	 * in future releases again, but for now give
+	 * admins the flexibility to configure, the behavior
+	 * from Samba 4.6: "auth methods = anonymous sam_ignoredomain",
+	 * for a while.
+	 */
+	auth_methods = lpcfg_auth_methods(lp_ctx);
+	if (auth_methods != NULL) {
+		DBG_NOTICE("using deprecated 'auth methods' values.\n");
+	} else {
+		/*
+		 * We can remove "winbind_rodc sam_failtrusts",
+		 * when we made the netlogon retries to
+		 * to contact winbind via irpc.
+		 */
+		_auth_methods = str_list_make(mem_ctx,
+				"sam "
+				"winbind_rodc sam_failtrusts",
+				NULL);
+		if (_auth_methods == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		auth_methods = discard_const_p(const char *, _auth_methods);
+	}
+
+	status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg,
+					     lp_ctx, NULL, auth_ctx);
+	talloc_free(_auth_methods);
+	return status;
 }
 
 /* the list of currently registered AUTH backends */
-- 
1.9.1


From 3c2eaf0d50fe660000d78fb18fe8c29e0070a6cf Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 16 Mar 2017 15:45:32 +0100
Subject: [PATCH 16/19] auth3: add "sam_netlogon3" which only reacts on
 lp_workgroup() as NT4 PDC/BDC

This will be used in the s3 netlogon server in future.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12710

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/auth/auth_sam.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
index 5b53bca..634386f 100644
--- a/source3/auth/auth_sam.c
+++ b/source3/auth/auth_sam.c
@@ -125,9 +125,73 @@ static NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *par
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context,
+					void *my_private_data,
+					TALLOC_CTX *mem_ctx,
+					const struct auth_usersupplied_info *user_info,
+					struct auth_serversupplied_info **server_info)
+{
+	bool is_my_domain;
+
+	if (!user_info || !auth_context) {
+		return NT_STATUS_LOGON_FAILURE;
+	}
+
+	DBG_DEBUG("Check auth for: [%s]\\[%s]\n",
+		  user_info->mapped.domain_name,
+		  user_info->mapped.account_name);
+
+	/* check whether or not we service this domain/workgroup name */
+
+	switch (lp_server_role()) {
+	case ROLE_DOMAIN_PDC:
+	case ROLE_DOMAIN_BDC:
+		break;
+	default:
+		DBG_ERR("Invalid server role\n");
+		return NT_STATUS_INVALID_SERVER_STATE;
+	}
+
+	is_my_domain = strequal(user_info->mapped.domain_name, lp_workgroup());
+	if (!is_my_domain) {
+		DBG_INFO("%s is not our domain name (DC for %s)\n",
+			 user_info->mapped.domain_name, lp_workgroup());
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
+	return check_sam_security(&auth_context->challenge, mem_ctx,
+				  user_info, server_info);
+}
+
+/* module initialisation */
+static NTSTATUS auth_init_sam_netlogon3(struct auth_context *auth_context,
+					const char *param, auth_methods **auth_method)
+{
+	struct auth_methods *result;
+
+	if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
+	    && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
+		DEBUG(0, ("server role = 'active directory domain controller' "
+			  "not compatible with running the auth_sam module.\n"));
+		DEBUGADD(0, ("You should not set 'auth methods' when "
+			     "running the AD DC.\n"));
+		exit(1);
+	}
+
+	result = talloc_zero(auth_context, struct auth_methods);
+	if (result == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	result->auth = auth_sam_netlogon3_auth;
+	result->name = "sam_netlogon3";
+	*auth_method = result;
+	return NT_STATUS_OK;
+}
+
 NTSTATUS auth_sam_init(void)
 {
 	smb_register_auth(AUTH_INTERFACE_VERSION, "sam", auth_init_sam);
 	smb_register_auth(AUTH_INTERFACE_VERSION, "sam_ignoredomain", auth_init_sam_ignoredomain);
+	smb_register_auth(AUTH_INTERFACE_VERSION, "sam_netlogon3", auth_init_sam_netlogon3);
 	return NT_STATUS_OK;
 }
-- 
1.9.1


From f63d11f3fd757ea203adae9a3f684d9e7cae30a9 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 17 Mar 2017 16:51:45 +0100
Subject: [PATCH 17/19] auth3: only use "sam_netlogon3 winbind:trustdomain" in
 make_auth3_context_for_netlogon

If some needs the old behavior for a while, the deprecated
"auth methods = guest sam winbind:trustdomain" option can be used.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12710

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/auth/auth.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 28d0955..916c524 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -559,7 +559,36 @@ NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx,
 NTSTATUS make_auth3_context_for_netlogon(TALLOC_CTX *mem_ctx,
 					 struct auth_context **auth_context)
 {
-	return make_auth_context_subsystem(mem_ctx, auth_context);
+	const char *methods = NULL;
+	NTSTATUS nt_status;
+
+	/*
+	 * We do the lp_auth_methods check before
+	 * the lp_server_role check in order to
+	 * backward compatible. The "auth methods" option
+	 * is deprecated now, so this will go away in a future
+	 * release.
+	 */
+	if (lp_auth_methods()) {
+		DBG_INFO("Using specified auth order for netlogon\n");
+		nt_status = make_auth_context_text_list(
+			mem_ctx, auth_context,
+			discard_const_p(char *, lp_auth_methods()));
+		return nt_status;
+	}
+
+	switch (lp_server_role()) {
+	case ROLE_DOMAIN_BDC:
+	case ROLE_DOMAIN_PDC:
+		methods = "sam_netlogon3 winbind:trustdomain";
+		break;
+
+	default:
+		DBG_ERR("Invalid server role!\n");
+		return NT_STATUS_INVALID_SERVER_STATE;
+	}
+
+	return make_auth_context_specific(mem_ctx, auth_context, methods);
 }
 
 NTSTATUS make_auth3_context_for_winbind(TALLOC_CTX *mem_ctx,
-- 
1.9.1


From 5056d54edad5af7224683fa09ad0e3e587f92230 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 17 Mar 2017 16:53:27 +0100
Subject: [PATCH 18/19] auth3: merge make_auth_context_subsystem() into
 make_auth3_context_for_ntlm()

make_auth3_context_for_ntlm() was the only caller of
make_auth_context_subsystem().

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12710

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/auth/auth.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 916c524..2c92140 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -500,8 +500,8 @@ static NTSTATUS make_auth_context_specific(TALLOC_CTX *mem_ctx,
  Make a auth_context struct for the auth subsystem
 ***************************************************************************/
 
-static NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx,
-					    struct auth_context **auth_context)
+NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx,
+				     struct auth_context **auth_context)
 {
 	const char *methods = NULL;
 	NTSTATUS nt_status;
@@ -550,12 +550,6 @@ static NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx,
 	return make_auth_context_specific(mem_ctx, auth_context, methods);
 }
 
-NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx,
-				     struct auth_context **auth_context)
-{
-	return make_auth_context_subsystem(mem_ctx, auth_context);
-}
-
 NTSTATUS make_auth3_context_for_netlogon(TALLOC_CTX *mem_ctx,
 					 struct auth_context **auth_context)
 {
-- 
1.9.1


From e01c4f4237b27f75ac3c0a5931c0dc3fbe67b302 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 19 Feb 2017 15:37:51 +0100
Subject: [PATCH 19/19] auth3: fallback to "sam_ignoredomain" in
 make_auth3_context_for_ntlm()

This is in the spirit of the "map untrusted to domain" parameter: We
fall back to the local SAM when we get a non-authoritative NO_SUCH_USER
from our domain controller. With this change we can implement
"map untrusted to domain = auto".

We should not strictly need 'sam' before 'winbind', but it makes
it clearer to read and has the same effect.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=2976
BUG: https://bugzilla.samba.org/show_bug.cgi?id=8630

Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/auth/auth.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 2c92140..ba6245d 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -526,17 +526,17 @@ NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx,
 	switch (lp_server_role()) {
 	case ROLE_DOMAIN_MEMBER:
 		DEBUG(5,("Making default auth method list for server role = 'domain member'\n"));
-		methods = "guest sam winbind:ntdomain";
+		methods = "guest sam winbind:ntdomain sam_ignoredomain";
 		break;
 	case ROLE_DOMAIN_BDC:
 	case ROLE_DOMAIN_PDC:
 		DEBUG(5,("Making default auth method list for DC\n"));
-		methods = "guest sam winbind:trustdomain";
+		methods = "guest sam winbind:trustdomain sam_ignoredomain";
 		break;
 	case ROLE_STANDALONE:
 		DEBUG(5,("Making default auth method list for server role = 'standalone server', encrypt passwords = yes\n"));
 		if (lp_encrypt_passwords()) {
-			methods = "guest sam";
+			methods = "guest sam_ignoredomain";
 		} else {
 			DEBUG(5,("Making default auth method list for server role = 'standalone server', encrypt passwords = no\n"));
 			methods = "guest unix";
-- 
1.9.1

-------------- next part --------------
From 7f2a8894933c8da41d7da683186fe5b25415ad1b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 16 Mar 2017 15:09:26 +0100
Subject: [PATCH 1/5] auth3: call is_trusted_domain() as the last condition
 make_user_info_map()

We should avoid contacting winbind if we already know the domain is our
local sam or our primary domain.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=8630

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/auth/auth_util.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index ffd60e0..ec597e8 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -134,9 +134,11 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 	 * non-domain member box will also map to WORKSTATION\user.
 	 * This also deals with the client passing in a "" domain */
 
-	if (!upn_form && !is_trusted_domain(domain) &&
+	if (!upn_form &&
 	    !strequal(domain, my_sam_name()) &&
-	    !strequal(domain, get_global_sam_name())) {
+	    !strequal(domain, get_global_sam_name()) &&
+	    !is_trusted_domain(domain))
+	{
 		if (lp_map_untrusted_to_domain())
 			domain = my_sam_name();
 		else
-- 
1.9.1


From 4a1955d896f2746b883d2f6e716d9b34c7e169c5 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 22 Mar 2017 12:08:20 +0100
Subject: [PATCH 2/5] auth3: prepare the logic for "map untrusted to domain =
 auto"

This implements the same behavior as Windows,
we should pass the domain and account names given
by the client directly to the auth backends,
they can decide if they are able to process the
authentication pass it to the next backend.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=8630

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/auth/auth_util.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index ec597e8..1021f2a 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -111,6 +111,7 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 	bool was_mapped;
 	char *internal_username = NULL;
 	bool upn_form = false;
+	int map_untrusted = lp_map_untrusted_to_domain();
 
 	if (client_domain[0] == '\0' && strchr(smb_name, '@')) {
 		upn_form = true;
@@ -134,15 +135,16 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 	 * non-domain member box will also map to WORKSTATION\user.
 	 * This also deals with the client passing in a "" domain */
 
-	if (!upn_form &&
+	if (map_untrusted != Auto && !upn_form &&
 	    !strequal(domain, my_sam_name()) &&
 	    !strequal(domain, get_global_sam_name()) &&
 	    !is_trusted_domain(domain))
 	{
-		if (lp_map_untrusted_to_domain())
+		if (map_untrusted) {
 			domain = my_sam_name();
-		else
+		} else {
 			domain = get_global_sam_name();
+		}
 		DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
 			  "workstation [%s]\n",
 			  client_domain, domain, smb_name, workstation_name));
-- 
1.9.1


From 25fc39115580b764b6edc1719a9d61b5f9c6be6c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 22 Mar 2017 12:11:26 +0100
Subject: [PATCH 3/5] TODO docs-xml: document "map untrusted to domain = auto"

BUG: https://bugzilla.samba.org/show_bug.cgi?id=8630
---
 .../smbdotconf/security/mapuntrustedtodomain.xml   | 23 ++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml b/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml
index 496e7c2..7a2df9a 100644
--- a/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml
+++ b/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml
@@ -1,6 +1,7 @@
 <samba:parameter name="map untrusted to domain"
                  context="G"
-                 type="boolean"
+                 type="enum"
+                 enumlist="enum_bool_auto"
                  deprecated="1"
                  xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
@@ -20,13 +21,31 @@
     </para>
 
     <para>
-    When this parameter is set to <constant>yes</constant> smbd provides the
+    The above describes the situation with <smbconfoption name="map untrusted to domain">no</smbconfoption>,
+    which was the default up to Samba 4.6.
+    </para>
+
+    <para>
+    With <smbconfoption name="map untrusted to domain">yes</smbconfoption> smbd provides the
     legacy behavior of mapping untrusted domain names to the primary domain.
     When smbd is not acting as a domain member server, this parameter has no
     effect.
     </para>
 
+    <para>
+    With <smbconfoption name="map untrusted to domain">auto</smbconfoption> smbd will
+    defer the mapping decision to the stack of auth method backends.
+    Each auth method is able to say I'm not authoritative and the
+    next backend will be used. This is basically the same as the behavior
+    implemented in Windows.
+    </para>
+
+    <para>
+    <smbconfoption name="map untrusted to domain">auto</smbconfoption> was added
+    with Samba 4.7.0.
+    </para>
 </description>
 
 <value type="default">no</value>
+<value type="example">auto</value>
 </samba:parameter>
-- 
1.9.1


From f3d7530fe7144539080d24d0b460341be86d2036 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 22 Mar 2017 12:11:26 +0100
Subject: [PATCH 4/5] docs-xml: change the default for "map untrusted to
 domain" to "auto"

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 docs-xml/smbdotconf/security/mapuntrustedtodomain.xml | 7 ++++---
 lib/param/loadparm.c                                  | 2 ++
 source3/param/loadparm.c                              | 2 +-
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml b/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml
index 7a2df9a..fc2233f 100644
--- a/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml
+++ b/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml
@@ -42,10 +42,11 @@
 
     <para>
     <smbconfoption name="map untrusted to domain">auto</smbconfoption> was added
-    with Samba 4.7.0.
+    and become the default with Samba 4.7.0. As the option is marked as
+    <constant>deprecated</constant> it will be removed in a future release, while the behavior of
+    <smbconfoption name="map untrusted to domain">auto</smbconfoption> will be kept.
     </para>
 </description>
 
-<value type="default">no</value>
-<value type="example">auto</value>
+<value type="default">auto</value>
 </samba:parameter>
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index cedf8fa..8d47440 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -2794,6 +2794,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 
 	lpcfg_do_global_parameter(lp_ctx, "guest account", GUEST_ACCOUNT);
 
+	lpcfg_do_global_parameter(lp_ctx, "map untrusted to domain", "auto");
+
 	lpcfg_do_global_parameter(lp_ctx, "client schannel", "auto");
 
 	lpcfg_do_global_parameter(lp_ctx, "smb encrypt", "default");
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 57220a6..78ef47e 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -856,7 +856,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
 	Globals.min_receivefile_size = 0;
 
-	Globals.map_untrusted_to_domain = false;
+	Globals.map_untrusted_to_domain = Auto;
 	Globals.multicast_dns_register = true;
 
 	Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
-- 
1.9.1


From 4fa00ec8581c02b547f01dd2069a20cd6026da3f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Apr 2017 11:22:25 +0200
Subject: [PATCH 5/5] WHATSNEW: change the default for "map untrusted to
 domain" to "auto"

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 WHATSNEW.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index c276ce2..53ab287 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -47,7 +47,9 @@ smb.conf changes
   --------------                -----------             -------
   auth event notification       New parameter           no
   auth methods                  Deprecated
-  map untrusted to domain       Deprecated
+  map untrusted to domain       New value/              auto
+                                Default changed/
+                                Deprecated
   strict sync                   Default changed         yes
 
 KNOWN ISSUES
-- 
1.9.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20170407/b7638af1/signature-0001.sig>


More information about the samba-technical mailing list