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

Volker Lendecke vl at samba.org
Thu Mar 9 18:48:04 UTC 2017


On Fri, Mar 10, 2017 at 07:30:27AM +1300, Andrew Bartlett wrote:
> On Thu, 2017-03-09 at 13:36 +0100, Volker Lendecke wrote:
> > Hi!
> > 
> > This is independently correct, but is quite ineffective so far. The
> > core auth backend loops don't do this yet, but I want to make the
> > final patchset smaller.
> > 
> > Review appreciated!
> 
> Looks good to me!
> 
> Reviewed-by: Andrew Bartlett <abartlet at samba.org>
> 
> Thanks!

Thank you for looking :-)

Because you asked earlier: Attached find the whole patchset I'm
working on. The local netlogond use of winbind makes it easier in the
rodc case. The routing is clear, we don't need to special-case in the
auth methods for that. This version has not yet survived a full
autobuild. Without the last 3 ones it failed at the very end in the
rodc tests, so I added them again. Now those tests pass individually.

BTW, there's already precedence for connecting to netlogond locally:
In 5602377fc we've added that for a different call, but it's there.

We need to talk about full bisectability with make test. That will be
difficult to achieve for this patchset. We need to mark many tests as
failing in between and unmark them again. Or one big patch.

Volker
-------------- next part --------------
>From e5d39e1cf2074c242ffe03d92ef337d5ff32119b Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 11 Feb 2017 10:25:44 +0100
Subject: [PATCH 01/25] auth_winbind3: Correctly handle !authoritative

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/auth/auth_winbind.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c
index 2b5c84d..e6a6296 100644
--- a/source3/auth/auth_winbind.c
+++ b/source3/auth/auth_winbind.c
@@ -121,6 +121,15 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
 
 	if (wbc_status == WBC_ERR_AUTH_ERROR) {
 		nt_status = NT_STATUS(err->nt_status);
+
+		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
+		    (err->authoritative == 0)) {
+			/*
+			 * Trigger a fallback to local SAM
+			 */
+			nt_status = NT_STATUS_NOT_IMPLEMENTED;
+		}
+
 		wbcFreeMemory(err);
 		return nt_status;
 	}
-- 
2.7.4


>From f3aa2d67deef4de437ffeb4e7e34584408343666 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 25 Feb 2017 09:55:28 +0000
Subject: [PATCH 02/25] auth_winbind4: Correctly handle !authoritative

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source4/auth/ntlm/auth_winbind.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/source4/auth/ntlm/auth_winbind.c b/source4/auth/ntlm/auth_winbind.c
index 8b9a1ef..6f1976d 100644
--- a/source4/auth/ntlm/auth_winbind.c
+++ b/source4/auth/ntlm/auth_winbind.c
@@ -141,6 +141,11 @@ static NTSTATUS winbind_check_password(struct auth_method_context *ctx,
 	status = dcerpc_winbind_SamLogon_r(irpc_handle, s, &s->req);
 	NT_STATUS_NOT_OK_RETURN(status);
 
+	if (NT_STATUS_EQUAL(s->req.out.result, NT_STATUS_NO_SUCH_USER) &&
+	    !s->req.out.authoritative) {
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
 	status = make_user_info_dc_netlogon_validation(mem_ctx,
 						      user_info->client.account_name,
 						      s->req.in.validation_level,
-- 
2.7.4


>From 5395b7de86fe30d150399cd06f09666147df932e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 12 Feb 2017 19:20:07 +0100
Subject: [PATCH 03/25] auth_ntdomain3: Correctly handle !authoritative

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/auth/auth_domain.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index d663923..b3ff518 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -229,6 +229,10 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
 		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) {
 			nt_status = NT_STATUS_NO_LOGON_SERVERS;
 		}
+		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
+		    (authoritative == 0)) {
+			nt_status = NT_STATUS_NOT_IMPLEMENTED;
+		}
 	} else {
 		nt_status = make_server_info_info3(mem_ctx,
 						   user_info->client.account_name,
-- 
2.7.4


>From c576afebe40c0646aa4e1f6b27e7b25acf2c3092 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 6 Mar 2017 14:32:18 +0100
Subject: [PATCH 04/25] wbinfo: Add "authoritative" to wbinfo -a output

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 nsswitch/wbinfo.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/nsswitch/wbinfo.c b/nsswitch/wbinfo.c
index 80b245a..57f2b3b 100644
--- a/nsswitch/wbinfo.c
+++ b/nsswitch/wbinfo.c
@@ -1823,13 +1823,15 @@ static bool wbinfo_auth_crap(char *username, bool use_ntlmv2, bool use_lanman)
 
 	if (wbc_status == WBC_ERR_AUTH_ERROR) {
 		d_fprintf(stderr,
-			 "wbcAuthenticateUserEx(%s%c%s): error code was %s (0x%x)\n"
+			 "wbcAuthenticateUserEx(%s%c%s): error code was "
+			  "%s (0x%x, authoritative=%"PRIu8")\n"
 			 "error message was: %s\n",
 			 name_domain,
 			 winbind_separator(),
 			 name_user,
 			 err->nt_string,
 			 err->nt_status,
+			 err->authoritative,
 			 err->display_string);
 		wbcFreeMemory(err);
 	} else if (WBC_ERROR_IS_OK(wbc_status)) {
-- 
2.7.4


>From 94a6b8ecc8df076c6a77840c4c0f7371bf8f73d1 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 11 Feb 2017 15:05:52 +0100
Subject: [PATCH 05/25] auth3: Don't try other auth modules on any error

So far if any kind of error has happened, we just tried further auth
modules. An auth module should have the chance to definitely say "no,
this is a valid error, no further attempts anywhere else". The protocol
so far was for an auth module to return NT_STATUS_NOT_IMPLEMENTED if it
wanted to pass on to other modules, but any error led to the next auth
modules also being given a try.

This patch makes any auth module return code except NOT_IMPLEMENTED to
terminate the loop, such that every module has to explicitly request to
pass on to the next module via NOT_IMPLEMENTED.

All modules we reference in make_auth_context_subsystem() have code to
explicitly say "not for me please" with NOT_IMPLEMENTED.

This *might* break existing setups which fail in for example "guest" or
"winbind" due to other reasons. I prefer it this way though, because
adding another parameter like "This is a real authoritative failure,
don't go looking somewhere else" will only add to the mess.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/auth/auth.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 1cbe46e..61e8ce6 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -250,9 +250,7 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 				  auth_method->name, user_info->client.account_name, nt_errstr(nt_status)));
 		}
 
-		if (NT_STATUS_IS_OK(nt_status)) {
-			break;
-		}
+		break;
 	}
 
 	/* successful authentication */
-- 
2.7.4


>From 53496e78f3463da3abfd25e7a0ba89f7a4cef515 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 11 Feb 2017 15:44:01 +0100
Subject: [PATCH 06/25] auth3: Simplify the logic in auth_check_ntlm_password

Move everything but the strict loop logic outside. This makes the
loop exit condition clearer to me: Anything but NOT_IMPLEMENTED breaks
the loop.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/auth/auth.c | 58 ++++++++++++++++++++++++++---------------------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 61e8ce6..104b0aa 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -170,6 +170,7 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 	NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER;
 	const char *unix_username;
 	auth_methods *auth_method;
+	const char *auth_method_name = "";
 	struct auth_serversupplied_info *server_info;
 
 	if (user_info == NULL || auth_context == NULL || pserver_info == NULL) {
@@ -214,51 +215,50 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 	}
 
 	for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) {
-		NTSTATUS result;
+
+		auth_method_name = auth_method->name;
 
 		if (user_info->flags & USER_INFO_LOCAL_SAM_ONLY
 		    && !(auth_method->flags & AUTH_METHOD_LOCAL_SAM)) {
 			continue;
 		}
 
-		result = auth_method->auth(auth_context,
-					   auth_method->private_data,
-					   talloc_tos(),
-					   user_info,
-					   &server_info);
-
-		/* check if the module did anything */
-		if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
-			DEBUG(10,("check_ntlm_password: %s had nothing to say\n", auth_method->name));
-			if (user_info->flags & USER_INFO_LOCAL_SAM_ONLY) {
-				/* we don't expose the NT_STATUS_NOT_IMPLEMENTED
-				 * internals, except when the caller is only probing
-				 * one method, as they may do the fallback 
-				 */
-				nt_status = result;
-			}
-			continue;
-		}
-
-		nt_status = result;
+		nt_status = auth_method->auth(auth_context,
+					      auth_method->private_data,
+					      talloc_tos(),
+					      user_info,
+					      &server_info);
 
-		if (NT_STATUS_IS_OK(nt_status)) {
-			DEBUG(3, ("check_ntlm_password: %s authentication for user [%s] succeeded\n", 
-				  auth_method->name, user_info->client.account_name));
-		} else {
-			DEBUG(5, ("check_ntlm_password: %s authentication for user [%s] FAILED with error %s\n", 
-				  auth_method->name, user_info->client.account_name, nt_errstr(nt_status)));
+		if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
+			break;
 		}
 
-		break;
+		DBG_DEBUG("%s had nothing to say\n", auth_method->name);
 	}
 
-	/* successful authentication */
+	/* check if the module did anything */
+	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED) &&
+	    ((user_info->flags & USER_INFO_LOCAL_SAM_ONLY) == 0)) {
+		/*
+		 * we don't expose the NT_STATUS_NOT_IMPLEMENTED
+		 * internals, except when the caller is only probing
+		 * one method, as they may do the fallback
+		 */
+		nt_status = NT_STATUS_NO_SUCH_USER;
+	}
 
 	if (!NT_STATUS_IS_OK(nt_status)) {
+		DBG_INFO("%s authentication for user [%s] FAILED with "
+			 "error %s\n",
+			 auth_method_name,
+			 user_info->client.account_name,
+			 nt_errstr(nt_status));
 		goto fail;
 	}
 
+	DBG_NOTICE("%s authentication for user [%s] succeeded\n",
+		   auth_method_name, user_info->client.account_name);
+
 	unix_username = server_info->unix_name;
 
 	/* We skip doing this step if the caller asked us not to */
-- 
2.7.4


>From a5e526ed618bf96c62d5735d30c9f4ddb1df08ef 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 07/25] auth3: Implement local sam fallback for !authoritative
 error

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.

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

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 104b0aa..e733817 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -481,7 +481,8 @@ NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx,
 		case ROLE_DOMAIN_MEMBER:
 			DEBUG(5,("Making default auth method list for server role = 'domain member'\n"));
 			auth_method_list = str_list_make_v3(
-				talloc_tos(), "guest sam winbind:ntdomain",
+				talloc_tos(),
+				"guest winbind:ntdomain sam_ignoredomain",
 				NULL);
 			break;
 		case ROLE_DOMAIN_BDC:
@@ -489,7 +490,7 @@ NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx,
 			DEBUG(5,("Making default auth method list for DC\n"));
 			auth_method_list = str_list_make_v3(
 				talloc_tos(),
-				"guest sam winbind:trustdomain",
+				"guest winbind:trustdomain sam_ignoredomain",
 				NULL);
 			break;
 		case ROLE_STANDALONE:
-- 
2.7.4


>From e441ff5db80857136bccd76df0c951dbfe5196af Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 19 Feb 2017 15:40:00 +0100
Subject: [PATCH 08/25] auth3: Remove the "map untrusted to domain" parameter

This was a flawed parameter:

We can't know whether a domain is trusted or not. The only way
we reliably know about this is to ask the DC and get a non-authoritative
NO_SUCH_USER.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 .../smbdotconf/security/mapuntrustedtodomain.xml   | 31 ----------------------
 source3/auth/auth.c                                |  3 ++-
 source3/auth/auth_util.c                           | 25 -----------------
 source3/param/loadparm.c                           |  1 -
 4 files changed, 2 insertions(+), 58 deletions(-)
 delete mode 100644 docs-xml/smbdotconf/security/mapuntrustedtodomain.xml

diff --git a/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml b/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml
deleted file mode 100644
index 126411a..0000000
--- a/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<samba:parameter name="map untrusted to domain"
-                 context="G"
-                 type="boolean"
-                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
-<description>
-    <para>
-    If a client connects to smbd using an untrusted domain name, such as
-    BOGUS\user, smbd replaces the BOGUS domain with it's SAM name before
-    attempting to authenticate that user.  In the case where smbd is acting as
-    a PDC this will be DOMAIN\user.  In the case where smbd is acting as a
-    domain member server or a standalone server this will be WORKSTATION\user.
-    </para>
-
-    <para>
-    In previous versions of Samba (pre 3.4), if smbd was acting as a domain
-    member server, the BOGUS domain name would instead be replaced by the
-    primary domain which smbd was a member of.  In this case authentication
-    would be deferred off to a DC using the credentials DOMAIN\user.
-    </para>
-
-    <para>
-    When this parameter is set to <constant>yes</constant> 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>
-
-</description>
-
-<value type="default">no</value>
-</samba:parameter>
diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index e733817..6dbcebb 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -497,7 +497,8 @@ NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx,
 			DEBUG(5,("Making default auth method list for server role = 'standalone server', encrypt passwords = yes\n"));
 			if (lp_encrypt_passwords()) {
 				auth_method_list = str_list_make_v3(
-						talloc_tos(), "guest sam",
+						talloc_tos(),
+						"guest sam_ignoredomain",
 						NULL);
 			} else {
 				DEBUG(5,("Making default auth method list for server role = 'standalone server', encrypt passwords = no\n"));
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 5d9f0e0..f380d6d 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -108,11 +108,6 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 	NTSTATUS result;
 	bool was_mapped;
 	char *internal_username = NULL;
-	bool upn_form = false;
-
-	if (client_domain[0] == '\0' && strchr(smb_name, '@')) {
-		upn_form = true;
-	}
 
 	was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
 	if (!internal_username) {
@@ -124,26 +119,6 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 
 	domain = client_domain;
 
-	/* If you connect to a Windows domain member using a bogus domain name,
-	 * the Windows box will map the BOGUS\user to SAMNAME\user.  Thus, if
-	 * the Windows box is a DC the name will become DOMAIN\user and be
-	 * authenticated against AD, if the Windows box is a member server but
-	 * not a DC the name will become WORKSTATION\user.  A standalone
-	 * 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) &&
-	    !strequal(domain, my_sam_name()) &&
-	    !strequal(domain, get_global_sam_name())) {
-		if (lp_map_untrusted_to_domain())
-			domain = my_sam_name();
-		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));
-	}
-
 	/* We know that the given domain is trusted (and we are allowing them),
 	 * it is our global SAM name, or for legacy behavior it is our
 	 * primary domain name */
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index c65e613..15071e2 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -856,7 +856,6 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
 	Globals.min_receivefile_size = 0;
 
-	Globals.map_untrusted_to_domain = false;
 	Globals.multicast_dns_register = true;
 
 	Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
-- 
2.7.4


>From c495445498c101c7a84a7abe26b98c736bf6cd28 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 1 Mar 2017 16:41:53 +0100
Subject: [PATCH 09/25] auth3: Only ask the local domain on a PDC

We do the fallback via sam_ignoredomain later.

This is needed so that in a later commit netlogond3 can return !authoritative
correctly.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/auth/auth_sam.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
index c4100d5..e03bdb0 100644
--- a/source3/auth/auth_sam.c
+++ b/source3/auth/auth_sam.c
@@ -90,7 +90,7 @@ static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context,
 			}
 		case ROLE_DOMAIN_PDC:
 		case ROLE_DOMAIN_BDC:
-			if ( !is_local_name && !is_my_domain ) {
+			if ( !is_my_domain ) {
 				DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n",
 					user_info->mapped.domain_name));
 				return NT_STATUS_NOT_IMPLEMENTED;
-- 
2.7.4


>From ae0635f7e4bdc08b517e121a89df6170b30cf79f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 1 Mar 2017 17:08:18 +0100
Subject: [PATCH 10/25] auth3: Add "methods" to make_auth_context_fixed

Both relevant callers have different unique needs:

winbind only needs to look at the sam.

netlogond3 must not do the sam_ignoredomain fallback, but for
trusted domains must do the winbind fallback.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/auth/auth.c                         | 12 +++++++++++-
 source3/auth/proto.h                        |  2 +-
 source3/rpc_server/netlogon/srv_netlog_nt.c |  3 ++-
 source3/torture/pdbtest.c                   |  3 ++-
 source3/winbindd/winbindd_pam.c             |  3 ++-
 5 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 6dbcebb..73310d9 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -532,12 +532,22 @@ NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx,
  Make a auth_info struct with a fixed challenge
 ***************************************************************************/
 
-NTSTATUS make_auth_context_fixed(TALLOC_CTX *mem_ctx,
+NTSTATUS make_auth_context_fixed(TALLOC_CTX *mem_ctx, const char *methods,
 				 struct auth_context **auth_context,
 				 uchar chal[8])
 {
 	NTSTATUS nt_status;
+	char **method_list;
+
+	method_list = str_list_make_v3(talloc_tos(), methods, NULL);
+	if (method_list == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	nt_status = make_auth_context_subsystem(mem_ctx, auth_context);
+
+	TALLOC_FREE(method_list);
+
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		return nt_status;
 	}
diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index 5fd3158..d55b134 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -40,7 +40,7 @@ bool load_auth_module(struct auth_context *auth_context,
 		      const char *module, auth_methods **ret) ;
 NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx,
 				     struct auth_context **auth_context);
-NTSTATUS make_auth_context_fixed(TALLOC_CTX *mem_ctx,
+NTSTATUS make_auth_context_fixed(TALLOC_CTX *mem_ctx, const char *methods,
 				 struct auth_context **auth_context,
 				 uchar chal[8]) ;
 
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index ef2c827..5bccde3 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1587,7 +1587,8 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 		const char *wksname = nt_workstation;
 		const char *workgroup = lp_workgroup();
 
-		status = make_auth_context_fixed(talloc_tos(), &auth_context,
+		status = make_auth_context_fixed(talloc_tos(), "sam winbind",
+						 &auth_context,
 						 logon->network->challenge);
 		if (!NT_STATUS_IS_OK(status)) {
 			return status;
diff --git a/source3/torture/pdbtest.c b/source3/torture/pdbtest.c
index fe51a76..b58187f 100644
--- a/source3/torture/pdbtest.c
+++ b/source3/torture/pdbtest.c
@@ -298,7 +298,8 @@ static bool test_auth(TALLOC_CTX *mem_ctx, struct samu *pdb_entry)
 		return False;
 	}
 
-	status = make_auth_context_fixed(NULL, &auth_context, challenge.data);
+	status = make_auth_context_fixed(NULL, "sam", &auth_context,
+					 challenge.data);
 
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status)));
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 5d1da16..0f0646a 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1268,7 +1268,8 @@ static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
 		user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
 	}
 
-	status = make_auth_context_fixed(frame, &auth_context, challenge->data);
+	status = make_auth_context_fixed(frame, "sam", &auth_context,
+					 challenge->data);
 
 	if (!NT_STATUS_IS_OK(status)) {
 		DBG_ERR("make_auth_context_fixed failed: %s\n",
-- 
2.7.4


>From 48c7da211949653176fe3015bf300215a3a1e909 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 1 Mar 2017 16:46:38 +0100
Subject: [PATCH 11/25] auth3: Make make_auth_context_text_list public

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/auth/auth.c  | 6 +++---
 source3/auth/proto.h | 3 +++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 73310d9..352f8b9 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -420,9 +420,9 @@ bool load_auth_module(struct auth_context *auth_context,
  Make a auth_info struct for the auth subsystem
 ***************************************************************************/
 
-static NTSTATUS make_auth_context_text_list(TALLOC_CTX *mem_ctx,
-					    struct auth_context **auth_context,
-					    char **text_list)
+NTSTATUS make_auth_context_text_list(TALLOC_CTX *mem_ctx,
+				     struct auth_context **auth_context,
+				     char **text_list)
 {
 	auth_methods *list = NULL;
 	auth_methods *t, *method = NULL;
diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index d55b134..c41a3d7 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -40,6 +40,9 @@ bool load_auth_module(struct auth_context *auth_context,
 		      const char *module, auth_methods **ret) ;
 NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx,
 				     struct auth_context **auth_context);
+NTSTATUS make_auth_context_text_list(TALLOC_CTX *mem_ctx,
+				     struct auth_context **auth_context,
+				     char **text_list);
 NTSTATUS make_auth_context_fixed(TALLOC_CTX *mem_ctx, const char *methods,
 				 struct auth_context **auth_context,
 				 uchar chal[8]) ;
-- 
2.7.4


>From 560361b3aa8fabfa1dc4910169ffe2dafbec08ea Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 1 Mar 2017 17:15:13 +0100
Subject: [PATCH 12/25] netlogond3: Do not fall back to local for interactive
 login

This the same as the "make_auth_context_fixed" for network logins
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 5bccde3..9002f23 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1634,6 +1634,12 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 		   on */
 	{
 		uint8_t chal[8];
+		char **methods;
+
+		methods = str_list_make_v3(talloc_tos(), "sam winbind", NULL);
+		if (methods == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
 
 #ifdef DEBUG_PASSWORD
 		if (logon != r->in.logon) {
@@ -1652,8 +1658,9 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 		DEBUG(100,("decrypt of nt owf password:"));
 		dump_data(100, logon->password->ntpassword.hash, 16);
 #endif
-		status = make_auth_context_subsystem(talloc_tos(),
-						     &auth_context);
+		status = make_auth_context_text_list(
+			talloc_tos(), &auth_context, methods);
+		TALLOC_FREE(methods);
 		if (!NT_STATUS_IS_OK(status)) {
 			return status;
 		}
-- 
2.7.4


>From 47558246e3abfa90240db4a2ea66e77822b3e914 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 9 Mar 2017 15:19:06 +0100
Subject: [PATCH 13/25] netlogond3: "authorititative" is a uint8

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 9002f23..f2fbb77 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1510,7 +1510,7 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 			return NT_STATUS_INTERNAL_ERROR;
 	}
 
-	*r->out.authoritative = true; /* authoritative response */
+	*r->out.authoritative = 1; /* authoritative response */
 
 	switch (r->in.validation_level) {
 	case 2:
-- 
2.7.4


>From 30991e890ec7121e3a72a9e1c89fea12c7f15d2b Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 9 Mar 2017 15:22:51 +0100
Subject: [PATCH 14/25] auth3: Return NT_STATUS_NOT_IMPLEMENTED from
 auth_check_ntlm_password

There are 3 callers: winbindd sam auth, netlogond3 and auth_ntlmssp. winbind
sam auth and netlogond3 need to return !authoritative on NOT_IMPLEMENTED,
auth_ntlmssp needs to drop that info. So I think it's better that we better not
use the USER_INFO_LOCAL_SAM_ONLY flag to indicate special behaviour. In winbind
and netlogond we have a special auth_methods list now.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/auth/auth.c                         | 16 ----------------
 source3/auth/auth_ntlmssp.c                 |  4 ++++
 source3/rpc_server/netlogon/srv_netlog_nt.c | 13 +++++--------
 source3/winbindd/winbindd_pam.c             |  2 +-
 4 files changed, 10 insertions(+), 25 deletions(-)

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 352f8b9..15eecb0 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -218,11 +218,6 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 
 		auth_method_name = auth_method->name;
 
-		if (user_info->flags & USER_INFO_LOCAL_SAM_ONLY
-		    && !(auth_method->flags & AUTH_METHOD_LOCAL_SAM)) {
-			continue;
-		}
-
 		nt_status = auth_method->auth(auth_context,
 					      auth_method->private_data,
 					      talloc_tos(),
@@ -236,17 +231,6 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 		DBG_DEBUG("%s had nothing to say\n", auth_method->name);
 	}
 
-	/* check if the module did anything */
-	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED) &&
-	    ((user_info->flags & USER_INFO_LOCAL_SAM_ONLY) == 0)) {
-		/*
-		 * we don't expose the NT_STATUS_NOT_IMPLEMENTED
-		 * internals, except when the caller is only probing
-		 * one method, as they may do the fallback
-		 */
-		nt_status = NT_STATUS_NO_SUCH_USER;
-	}
-
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		DBG_INFO("%s authentication for user [%s] FAILED with "
 			 "error %s\n",
diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c
index a0e4902..b7a2318 100644
--- a/source3/auth/auth_ntlmssp.c
+++ b/source3/auth/auth_ntlmssp.c
@@ -186,6 +186,10 @@ NTSTATUS auth3_check_password(struct auth4_context *auth4_context,
 			 user_info->client.domain_name,
 			 user_info->client.account_name,
 			 nt_errstr(nt_status)));
+
+		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
+			nt_status = NT_STATUS_NO_SUCH_USER;
+		}
 	}
 
 	username_was_mapped = mapped_user_info->was_mapped;
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index f2fbb77..820f0de 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1701,14 +1701,11 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 	/* Check account and password */
 
 	if (!NT_STATUS_IS_OK(status)) {
-		/* If we don't know what this domain is, we need to
-		   indicate that we are not authoritative.  This
-		   allows the client to decide if it needs to try
-		   a local user.  Fix by jpjanosi at us.ibm.com, #2976 */
-                if ( NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
-		     && !strequal(nt_domain, get_global_sam_name())
-		     && !is_trusted_domain(nt_domain) )
-			*r->out.authoritative = false; /* We are not authoritative */
+
+		if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
+			status = NT_STATUS_NO_SUCH_USER;
+			r->out.authoritative = 0;
+		}
 
 		TALLOC_FREE(server_info);
 		return status;
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 0f0646a..bd674b6 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1262,7 +1262,7 @@ static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
 	user_info->mapped_state = True;
 
 	/* We don't want to come back to winbindd or to do PAM account checks */
-	user_info->flags |= USER_INFO_LOCAL_SAM_ONLY | USER_INFO_INFO3_AND_NO_AUTHZ;
+	user_info->flags |= USER_INFO_INFO3_AND_NO_AUTHZ;
 
 	if (interactive) {
 		user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
-- 
2.7.4


>From 273accc4e835878c16264d36ede54ea6f5dfff72 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 26 Feb 2017 14:56:24 +0100
Subject: [PATCH 15/25] map_user_info: Factor out
 map_userinfo_crack_user_principal

---
 source4/auth/ntlm/auth_util.c | 131 ++++++++++++++++++++++--------------------
 1 file changed, 69 insertions(+), 62 deletions(-)

diff --git a/source4/auth/ntlm/auth_util.c b/source4/auth/ntlm/auth_util.c
index e3d196c..ea06f59 100644
--- a/source4/auth/ntlm/auth_util.c
+++ b/source4/auth/ntlm/auth_util.c
@@ -26,7 +26,7 @@
 #include "libcli/auth/libcli_auth.h"
 #include "param/param.h"
 #include "auth/ntlm/auth_proto.h"
-#include "librpc/gen_ndr/drsuapi.h"
+#include "librpc/gen_ndr/ndr_drsuapi.h"
 #include "dsdb/samdb/samdb.h"
 
 /* this default function can be used by mostly all backends
@@ -38,6 +38,67 @@ NTSTATUS auth_get_challenge_not_implemented(struct auth_method_context *ctx, TAL
 	return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS map_userinfo_crack_user_principal(
+	struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
+	const char *account, char **res_domain, char **res_account)
+{
+	WERROR werr;
+	TALLOC_CTX *tmp_ctx;
+	struct drsuapi_DsNameInfo1 info1;
+	NTSTATUS status = NT_STATUS_NO_SUCH_USER;
+	char *backslash, *domain, *account_name;
+
+	tmp_ctx = talloc_new(mem_ctx);
+
+	werr = DsCrackNameOneName(sam_ctx, tmp_ctx, 0,
+				  DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
+				  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+				  account,
+				  &info1);
+	if (!W_ERROR_IS_OK(werr)) {
+		DBG_NOTICE("Failed cracknames of account '%s': %s\n",
+			   account, win_errstr(werr));
+		status = werror_to_ntstatus(werr);
+		goto fail;
+	}
+
+	if (info1.status != DRSUAPI_DS_NAME_STATUS_OK) {
+		char *err = NDR_PRINT_STRUCT_STRING(
+			tmp_ctx, drsuapi_DsNameStatus, (void *)info1.status);
+		DBG_NOTICE("Cracknames of account '%s' -> %s\n",
+			   account, err);
+		goto fail;
+	}
+
+	/* info1.result_name is in DOMAIN\username
+	 * form, which we need to split up into the
+	 * user_info_mapped structure
+	 */
+	backslash = strchr_m(info1.result_name, '\\');
+	if (backslash == NULL) {
+		DBG_NOTICE("Cracknames of account '%s' "
+			   "gave invalid result '%s'\n",
+			   account, info1.result_name);
+		goto fail;
+	}
+
+	domain = talloc_strndup(tmp_ctx, info1.result_name,
+				backslash - info1.result_name);
+	account_name = talloc_strdup(tmp_ctx, backslash+1);
+
+	if ((domain == NULL) || (account_name == NULL)) {
+		status = NT_STATUS_NO_MEMORY;
+		goto fail;
+	}
+
+	*res_domain = talloc_move(mem_ctx, &domain);
+	*res_account = talloc_move(mem_ctx, &account_name);
+	status = NT_STATUS_OK;
+fail:
+	TALLOC_FREE(tmp_ctx);
+	return status;
+}
+
 /****************************************************************************
  Create an auth_usersupplied_data structure after appropriate mapping.
 ****************************************************************************/
@@ -65,67 +126,13 @@ static NTSTATUS map_user_info_cracknames(struct ldb_context *sam_ctx,
 	/* 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;
+		NTSTATUS status;
+
+		status = map_userinfo_crack_user_principal(
+			sam_ctx, tmp_ctx, user_info->client.account_name,
+			&domain, &account_name);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
 		}
 	} else {
 		const char *domain_name = default_domain;
-- 
2.7.4


>From aa1749a8827f834f899a92a60d5f363ed629617c Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 26 Feb 2017 15:26:47 +0100
Subject: [PATCH 16/25] map_user_info: Factor out map_userinfo_crack_domain

---
 source4/auth/ntlm/auth_util.c | 131 +++++++++++++++++++++++-------------------
 1 file changed, 73 insertions(+), 58 deletions(-)

diff --git a/source4/auth/ntlm/auth_util.c b/source4/auth/ntlm/auth_util.c
index ea06f59..d9d9639 100644
--- a/source4/auth/ntlm/auth_util.c
+++ b/source4/auth/ntlm/auth_util.c
@@ -99,6 +99,72 @@ fail:
 	return status;
 }
 
+static NTSTATUS map_userinfo_crack_domain(
+	struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
+	const char *domain, char **pres_domain)
+{
+	WERROR werr;
+	TALLOC_CTX *tmp_ctx;
+	struct drsuapi_DsNameInfo1 info1;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
+	char *backslash, *res_domain;
+
+	tmp_ctx = talloc_new(mem_ctx);
+	if (tmp_ctx == NULL) {
+		goto fail;
+	}
+
+	domain = talloc_asprintf(tmp_ctx, "%s\\", domain);
+	if (domain == NULL) {
+		goto fail;
+	}
+
+	werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
+				  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+				  DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
+				  domain,
+				  &info1);
+	if (!W_ERROR_IS_OK(werr)) {
+		DBG_NOTICE("Failed cracknames of domain '%s': %s\n",
+			   domain, win_errstr(werr));
+		status = werror_to_ntstatus(werr);
+		goto fail;
+	}
+
+	if ((info1.status != DRSUAPI_DS_NAME_STATUS_OK) &&
+	    (info1.status != DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY)) {
+		char *err = NDR_PRINT_STRUCT_STRING(
+			tmp_ctx, drsuapi_DsNameStatus, (void *)info1.status);
+		DBG_NOTICE("Cracknames of domain '%s' -> %s\n",
+			   domain, err);
+		status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+		goto fail;
+	}
+
+	backslash = strchr_m(info1.result_name, '\\');
+	if (backslash == NULL) {
+		DBG_NOTICE("Cracknames of domain '%s' "
+			   "gave invalid result '%s'\n",
+			   domain, info1.result_name);
+		status = NT_STATUS_NO_SUCH_USER;
+		goto fail;
+	}
+
+	res_domain = talloc_strndup(tmp_ctx, info1.result_name,
+				    backslash - info1.result_name);
+	if (res_domain == NULL) {
+		goto fail;
+	}
+
+	*pres_domain = talloc_move(mem_ctx, &res_domain);
+	status = NT_STATUS_OK;
+
+fail:
+	talloc_free(tmp_ctx);
+	return status;
+}
+
+
 /****************************************************************************
  Create an auth_usersupplied_data structure after appropriate mapping.
 ****************************************************************************/
@@ -111,8 +177,6 @@ static NTSTATUS map_user_info_cracknames(struct ldb_context *sam_ctx,
 	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));
@@ -132,72 +196,23 @@ static NTSTATUS map_user_info_cracknames(struct ldb_context *sam_ctx,
 			sam_ctx, tmp_ctx, user_info->client.account_name,
 			&domain, &account_name);
 		if (!NT_STATUS_IS_OK(status)) {
+			talloc_free(tmp_ctx);
 			return status;
 		}
 	} else {
+		NTSTATUS status;
 		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));
+		status = map_userinfo_crack_domain(
+			sam_ctx, tmp_ctx, domain_name, &domain);
+		if (!NT_STATUS_IS_OK(status)) {
 			talloc_free(tmp_ctx);
-			return NT_STATUS_NO_SUCH_USER;
+			return status;
 		}
-		/* domain and account_name are filled in above */
 	}
 
 	*user_info_mapped = talloc_zero(mem_ctx, struct auth_usersupplied_info);
-- 
2.7.4


>From 464babf91e25e479fd5fac89b86db612a60b2d19 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 26 Feb 2017 16:17:48 +0100
Subject: [PATCH 17/25] map_user_info: Retry user at domain

---
 source4/auth/ntlm/auth_util.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/source4/auth/ntlm/auth_util.c b/source4/auth/ntlm/auth_util.c
index d9d9639..09d6db1 100644
--- a/source4/auth/ntlm/auth_util.c
+++ b/source4/auth/ntlm/auth_util.c
@@ -209,6 +209,28 @@ static NTSTATUS map_user_info_cracknames(struct ldb_context *sam_ctx,
 
 		status = map_userinfo_crack_domain(
 			sam_ctx, tmp_ctx, domain_name, &domain);
+
+		if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER) ||
+		    NT_STATUS_EQUAL(status, NT_STATUS_CANT_ACCESS_DOMAIN_INFO))
+		{
+			char *princ;
+
+			princ = talloc_asprintf(
+				tmp_ctx, "%s@%s",
+				user_info->client.account_name,
+				user_info->client.domain_name);
+			if (princ == NULL) {
+				talloc_free(tmp_ctx);
+				return NT_STATUS_NO_MEMORY;
+			}
+
+			DBG_DEBUG("Retrying with principal %s\n", princ);
+
+			status = map_userinfo_crack_user_principal(
+				sam_ctx, tmp_ctx, princ,
+				&domain, &account_name);
+		}
+
 		if (!NT_STATUS_IS_OK(status)) {
 			talloc_free(tmp_ctx);
 			return status;
-- 
2.7.4


>From 3aa051db76da19c7abeb0edd4792bdebc8a6a4e4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Mar 2017 11:28:18 +0100
Subject: [PATCH 18/25] winbindd: NT_STATUS_CANT_ACCESS_DOMAIN_INFO means
 "Dunno"

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/winbindd/winbindd_pam.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index bd674b6..fa364df 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1338,6 +1338,16 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 
 		result = cm_connect_netlogon(domain, &netlogon_pipe);
 
+		if (NT_STATUS_EQUAL(result,
+				    NT_STATUS_CANT_ACCESS_DOMAIN_INFO)) {
+			/*
+			 * This means we don't have a trust account.
+			 */
+			*authoritative = 0;
+			result = NT_STATUS_NO_SUCH_USER;
+			break;
+		}
+
 		if (!NT_STATUS_IS_OK(result)) {
 			DEBUG(3,("Could not open handle to NETLOGON pipe "
 				 "(error: %s, attempts: %d)\n",
-- 
2.7.4


>From fa41bd5a8f23c771651dd8f40bb8538355412704 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 1 Mar 2017 17:25:51 +0100
Subject: [PATCH 19/25] netlogond4: Implement !authoritative

---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index afa9b1c..6e08be2 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -984,8 +984,26 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
+	/*
+	 * For the moment this is missing trusted domain support. We
+	 * only look at the local dsdb. This flag makes
+	 * auth_check_password pass up NT_STATUS_NOT_IMPLEMENTED
+	 * properly to us so that we can return !authoritative
+	 * correctly.
+	 */
+
+	user_info->flags |= USER_INFO_LOCAL_SAM_ONLY;
+
 	nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
-	/* TODO: set *r->out.authoritative = 0 on specific errors */
+	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
+		*r->out.authoritative = 0;
+		nt_status = NT_STATUS_NO_SUCH_USER;
+
+		/*
+		 * This is the place to asynchronously do a winbind
+		 * trusted domain query
+		 */
+	}
 	NT_STATUS_NOT_OK_RETURN(nt_status);
 
 	switch (r->in.validation_level) {
-- 
2.7.4


>From 6fbfd413f49b9987bfd811d5e24d6da0947e7574 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 4 Mar 2017 22:02:58 +0100
Subject: [PATCH 20/25] netlogond4: Only look at samstrict

sam_ignoredomain also counts as AUTH_METHOD_LOCAL_SAM,
which makes queries to a bogus domain an authoritative failure
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 6e08be2..2f49e93 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -852,6 +852,14 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 	struct netr_SamInfo2 *sam2 = NULL;
 	struct netr_SamInfo3 *sam3 = NULL;
 	struct netr_SamInfo6 *sam6 = NULL;
+	char **tmp;
+	const char **auth_methods;
+
+	tmp = str_list_make(mem_ctx, "sam", NULL);
+	if (tmp == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	auth_methods = discard_const_p(const char *, tmp);
 
 	*r->out.authoritative = 1;
 
@@ -869,10 +877,11 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 	case NetlogonServiceTransitiveInformation:
 
 		/* TODO: we need to deny anonymous access here */
-		nt_status = auth_context_create(mem_ctx,
-						dce_call->event_ctx, dce_call->msg_ctx,
-						dce_call->conn->dce_ctx->lp_ctx,
-						&auth_context);
+		nt_status = auth_context_create_methods(
+			mem_ctx, auth_methods,
+			dce_call->event_ctx, dce_call->msg_ctx,
+			dce_call->conn->dce_ctx->lp_ctx, NULL,
+			&auth_context);
 		NT_STATUS_NOT_OK_RETURN(nt_status);
 
 		user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
@@ -896,10 +905,11 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 	case NetlogonNetworkTransitiveInformation:
 
 		/* TODO: we need to deny anonymous access here */
-		nt_status = auth_context_create(mem_ctx,
-						dce_call->event_ctx, dce_call->msg_ctx,
-						dce_call->conn->dce_ctx->lp_ctx,
-						&auth_context);
+		nt_status = auth_context_create_methods(
+			mem_ctx, auth_methods,
+			dce_call->event_ctx, dce_call->msg_ctx,
+			dce_call->conn->dce_ctx->lp_ctx, NULL,
+			&auth_context);
 		NT_STATUS_NOT_OK_RETURN(nt_status);
 
 		nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
-- 
2.7.4


>From e07f4060b8d9cb6d78ad6f0304babfa8ed0ecb6f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 5 Mar 2017 19:13:04 +0100
Subject: [PATCH 21/25] auth4: Implement !authoritative

Doing the map_user_info in auth_check_password_send is wrong: At that point we
don't know if we are doing sam_strict or sam_ignoredomain. Defaulting to a
domain in map_user_info makes sam_strict impossible. Move the map_user_info
into the backends.
---
 source4/auth/ntlm/auth.c         |  27 +------
 source4/auth/ntlm/auth_sam.c     | 154 ++++++++++++++++++++++++++++-----------
 source4/auth/ntlm/auth_winbind.c |   2 +-
 3 files changed, 116 insertions(+), 67 deletions(-)

diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index 05d6c3c..fadfe60 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -282,29 +282,6 @@ _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
 	state->auth_ctx		= auth_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);
-		}
-		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_info->mapped.domain_name,
-		    user_info->mapped.account_name,
-		    user_info->workstation_name));
-
 	nt_status = auth_get_challenge(auth_ctx, chal);
 	if (tevent_req_nterror(req, nt_status)) {
 		DEBUG(0,("auth_check_password_send: "
@@ -608,12 +585,12 @@ 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:
 	case ROLE_ACTIVE_DIRECTORY_DC:
-		auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain winbind", NULL);
+		auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
 		break;
 	}
 	return discard_const_p(const char *, auth_methods);
diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c
index 90eabca..277b0d5 100644
--- a/source4/auth/ntlm/auth_sam.c
+++ b/source4/auth/ntlm/auth_sam.c
@@ -629,59 +629,131 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx
 	return NT_STATUS_OK;
 }
 
-static NTSTATUS authsam_ignoredomain_want_check(struct auth_method_context *ctx,
-						TALLOC_CTX *mem_ctx,
-						const struct auth_usersupplied_info *user_info)
+static NTSTATUS authsam_check_password_ignoredomain(
+	struct auth_method_context *ctx,
+	TALLOC_CTX *mem_ctx,
+	const struct auth_usersupplied_info *user_info,
+	struct auth_user_info_dc **user_info_dc)
 {
-	if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
+	if (!user_info->client.account_name || !*user_info->client.account_name) {
 		return NT_STATUS_NOT_IMPLEMENTED;
 	}
 
-	return NT_STATUS_OK;
+	if (!user_info->mapped_state) {
+		struct auth4_context *auth_ctx = ctx->auth_ctx;
+		struct auth_usersupplied_info *user_info_tmp;
+		NTSTATUS status;
+
+		status = map_user_info(
+			auth_ctx->sam_ctx, mem_ctx,
+			false, /* no cracknames please */
+			lpcfg_workgroup(auth_ctx->lp_ctx),
+			user_info, &user_info_tmp);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+
+		user_info_tmp->mapped.domain_name = talloc_strdup(
+			user_info_tmp, lpcfg_workgroup(auth_ctx->lp_ctx));
+		if (user_info_tmp->mapped.domain_name == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		user_info = user_info_tmp;
+	}
+
+	DBG_DEBUG("%s\\%s\n", user_info->mapped.domain_name,
+		  user_info->client.account_name);
+
+	return authsam_check_password_internals(ctx, mem_ctx, user_info,
+						user_info_dc);
 }
 
-/****************************************************************************
-Check SAM security (above) but with a few extra checks.
-****************************************************************************/
-static NTSTATUS authsam_want_check(struct auth_method_context *ctx,
-				   TALLOC_CTX *mem_ctx,
-				   const struct auth_usersupplied_info *user_info)
+static NTSTATUS authsam_check_password_strict(
+	struct auth_method_context *ctx,
+	TALLOC_CTX *mem_ctx,
+	const struct auth_usersupplied_info *user_info,
+	struct auth_user_info_dc **user_info_dc)
 {
-	bool is_local_name, is_my_domain;
+	struct auth4_context *auth_ctx = ctx->auth_ctx;
 
-	if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
-		return NT_STATUS_NOT_IMPLEMENTED;
+	if (!user_info->mapped_state) {
+		int server_role = lpcfg_server_role(auth_ctx->lp_ctx);
+		struct auth_usersupplied_info *user_info_tmp;
+		NTSTATUS status;
+
+		status = map_user_info(
+			auth_ctx->sam_ctx, mem_ctx,
+			server_role == ROLE_ACTIVE_DIRECTORY_DC,
+			lpcfg_workgroup(auth_ctx->lp_ctx),
+			user_info, &user_info_tmp);
+
+		if (NT_STATUS_EQUAL(status,
+				    NT_STATUS_CANT_ACCESS_DOMAIN_INFO)) {
+			return NT_STATUS_NOT_IMPLEMENTED;
+		}
+
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+
+		user_info = user_info_tmp;
 	}
 
-	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); 
+	DBG_DEBUG("%s\\%s\n", user_info->mapped.domain_name,
+		  user_info->client.account_name);
 
-	/* 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_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;
-			}
-			return NT_STATUS_OK;
+	    case ROLE_STANDALONE:
+		    break;
+
+	    case ROLE_DOMAIN_MEMBER: {
+		    bool is_local_name;
+
+		    is_local_name = lpcfg_is_myname(
+			    auth_ctx->lp_ctx, user_info->mapped.domain_name);
+		    if (!is_local_name) {
+			    DBG_INFO("%s is not one of my local names "
+				     "(DOMAIN_MEMBER)\n",
+				     user_info->mapped.domain_name);
+			    return NT_STATUS_NOT_IMPLEMENTED;
+		    }
+		    break;
+	    }
+
+	    case ROLE_ACTIVE_DIRECTORY_DC: {
+		    bool is_my_domain;
+
+		    is_my_domain = lpcfg_is_mydomain(
+			    auth_ctx->lp_ctx, user_info->mapped.domain_name);
+		    if (!is_my_domain) {
+			    DBG_INFO("%s is not my domain name (DC)\n",
+				     user_info->mapped.domain_name);
+			    return NT_STATUS_NOT_IMPLEMENTED;
+		    }
+		    break;
+	    }
+	}
+
+	return authsam_check_password_internals(ctx, mem_ctx, user_info,
+						user_info_dc);
+}
 
-		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;
-			}
-			return NT_STATUS_OK;
-	}
+static NTSTATUS authsam_ignoredomain_want_check(struct auth_method_context *ctx,
+						TALLOC_CTX *mem_ctx,
+						const struct auth_usersupplied_info *user_info)
+{
+	return NT_STATUS_OK;
+}
 
-	DEBUG(6,("authsam_check_password: lpcfg_server_role() has an undefined value\n"));
-	return NT_STATUS_NOT_IMPLEMENTED;
+/****************************************************************************
+Check SAM security (above) but with a few extra checks.
+****************************************************************************/
+static NTSTATUS authsam_want_check(struct auth_method_context *ctx,
+				   TALLOC_CTX *mem_ctx,
+				   const struct auth_usersupplied_info *user_info)
+{
+	return NT_STATUS_OK;
 }
 
 				   
@@ -698,7 +770,7 @@ static NTSTATUS authsam_get_user_info_dc_principal_wrapper(TALLOC_CTX *mem_ctx,
 static const struct auth_operations sam_ignoredomain_ops = {
 	.name		           = "sam_ignoredomain",
 	.want_check	           = authsam_ignoredomain_want_check,
-	.check_password	           = authsam_check_password_internals,
+	.check_password	           = authsam_check_password_ignoredomain,
 	.get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper,
 	.flags                     = AUTH_METHOD_LOCAL_SAM
 };
@@ -706,7 +778,7 @@ static const struct auth_operations sam_ignoredomain_ops = {
 static const struct auth_operations sam_ops = {
 	.name		           = "sam",
 	.want_check	           = authsam_want_check,
-	.check_password	           = authsam_check_password_internals,
+	.check_password	           = authsam_check_password_strict,
 	.get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper,
 	.flags                     = AUTH_METHOD_LOCAL_SAM
 };
diff --git a/source4/auth/ntlm/auth_winbind.c b/source4/auth/ntlm/auth_winbind.c
index 6f1976d..a3a129c 100644
--- a/source4/auth/ntlm/auth_winbind.c
+++ b/source4/auth/ntlm/auth_winbind.c
@@ -37,7 +37,7 @@ static NTSTATUS winbind_want_check(struct auth_method_context *ctx,
 				   TALLOC_CTX *mem_ctx,
 				   const struct auth_usersupplied_info *user_info)
 {
-	if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
+	if (!user_info->client.account_name || !*user_info->client.account_name) {
 		return NT_STATUS_NOT_IMPLEMENTED;
 	}
 
-- 
2.7.4


>From 4bbc0451f720d820e3a38189eff2dcd611f867e5 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 6 Mar 2017 08:30:07 +0100
Subject: [PATCH 22/25] auth4: Handle DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY in
 map_userinfo_crack_user_principal

---
 source4/auth/ntlm/auth_util.c | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/source4/auth/ntlm/auth_util.c b/source4/auth/ntlm/auth_util.c
index 09d6db1..439a492 100644
--- a/source4/auth/ntlm/auth_util.c
+++ b/source4/auth/ntlm/auth_util.c
@@ -62,6 +62,18 @@ static NTSTATUS map_userinfo_crack_user_principal(
 		goto fail;
 	}
 
+	if (info1.status == DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY) {
+		*res_account = NULL;
+		*res_domain = talloc_strdup(
+			mem_ctx, info1.dns_domain_name);
+		if (*res_domain == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto fail;
+		}
+		status = NT_STATUS_OK;
+		goto fail;
+	}
+
 	if (info1.status != DRSUAPI_DS_NAME_STATUS_OK) {
 		char *err = NDR_PRINT_STRUCT_STRING(
 			tmp_ctx, drsuapi_DsNameStatus, (void *)info1.status);
@@ -175,18 +187,12 @@ static NTSTATUS map_user_info_cracknames(struct ldb_context *sam_ctx,
 					 struct auth_usersupplied_info **user_info_mapped)
 {
 	char *domain;
-	char *account_name;
+	char *account_name = NULL;
 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 
 	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) {
@@ -237,6 +243,16 @@ static NTSTATUS map_user_info_cracknames(struct ldb_context *sam_ctx,
 		}
 	}
 
+	if (account_name == NULL) {
+		account_name = talloc_strdup(
+			tmp_ctx, user_info->client.account_name);
+	}
+
+	if (account_name == 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);
-- 
2.7.4


>From 3b0d57ce3ac1064e5896a3af4dbde99dd2bde887 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 1 Mar 2017 13:53:39 +0100
Subject: [PATCH 23/25] rpc_client3: Fix some crashes for NULL cli_state in
 cli_pipe

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

diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index 634c78b..9f1d952 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -174,7 +174,7 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli,
 		DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n",
 			 __FUNCTION__, action,
 			 creds->account_name, creds->computer_name,
-			 smbXcli_conn_remote_name(cli->conn)));
+			 cli ? smbXcli_conn_remote_name(cli->conn) : "local"));
 		if (!force_reauth) {
 			TALLOC_FREE(frame);
 			return NT_STATUS_OK;
@@ -189,7 +189,7 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli,
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n",
 			 __FUNCTION__,
-			 smbXcli_conn_remote_name(cli->conn),
+			 cli ? smbXcli_conn_remote_name(cli->conn) : "local",
 			 nt_errstr(status)));
 		TALLOC_FREE(frame);
 		return status;
@@ -215,7 +215,7 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli,
 	DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n",
 		 __FUNCTION__,
 		 creds->account_name, creds->computer_name,
-		 smbXcli_conn_remote_name(cli->conn)));
+		 cli ? smbXcli_conn_remote_name(cli->conn) : "local"));
 
 	TALLOC_FREE(frame);
 	return NT_STATUS_OK;
-- 
2.7.4


>From 1173be504e6c4930f1de8f16cc2f15f1c2ff9a22 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 1 Mar 2017 13:54:53 +0100
Subject: [PATCH 24/25] rpc_client3: Allow to connect to local unix socket

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/rpc_client/cli_pipe.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 14f7fbc..176345e 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -3057,6 +3057,26 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
 					 table, presult);
 	case NCACN_NP:
 		return rpc_pipe_open_np(cli, table, presult);
+	case NCACN_UNIX_STREAM: {
+		char *socket_path;
+		NTSTATUS status;
+
+		socket_path = talloc_asprintf(talloc_tos(), "%s/DEFAULT",
+					      lp_ncalrpc_dir());
+		if (socket_path == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		status = rpc_pipe_open_ncalrpc(
+			NULL, socket_path, table, presult);
+
+		DBG_DEBUG("rpc_pipe_open_ncalrpc(%s) returned %s\n",
+			  socket_path, nt_errstr(status));
+
+		TALLOC_FREE(socket_path);
+
+		return status;
+	}
 	default:
 		return NT_STATUS_NOT_IMPLEMENTED;
 	}
-- 
2.7.4


>From 4b27e39acca38b28253ea30b85e59d88d17428a7 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 1 Mar 2017 13:56:19 +0100
Subject: [PATCH 25/25] winbind3: On a AD DC, ask the local netlogon pipe for
 local auth

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/winbindd/winbindd_cm.c  | 10 ++++++++++
 source3/winbindd/winbindd_pam.c |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 3df4af3..64fda34 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -3357,6 +3357,16 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
 		return status;
 	}
 
+	if (domain->primary && !domain->rodc &&
+	    (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)) {
+		if (domain->dcname == NULL) {
+			domain->dcname = talloc_strdup(
+				domain, lp_netbios_name());
+		}
+		return cm_connect_netlogon_transport(
+			domain, NCACN_UNIX_STREAM, cli);
+	}
+
 	if (domain->active_directory && domain->can_do_ncacn_ip_tcp) {
 		status = cm_connect_netlogon_transport(domain, NCACN_IP_TCP, cli);
 		if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index fa364df..7bb7c82 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1238,6 +1238,11 @@ static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
 	int rc;
 	TALLOC_CTX *frame = talloc_stackframe();
 
+	if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
 	rc = tsocket_address_inet_from_strings(frame,
 					       "ip",
 					       "127.0.0.1",
-- 
2.7.4



More information about the samba-technical mailing list