[PATCH] Add detailed authentication logging for NTLM authentication.

Gary Lockyer gary at catalyst.net.nz
Tue Feb 28 03:26:34 UTC 2017


Produce detailed authentication logs for NTLM authentication, of both
successful and unsuccessful attempts.  Patch includes changes to ensure
that all the required fields are passed through to the logging routines.

Subsequent patches will log authorization, kerberos authentication, and
produce machine parsable json log entries.



-------------- next part --------------
From c618a20660ec7451ce52390758a1977789d0fb29 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 11:39:17 +1300
Subject: [PATCH 01/18] debug: Add debug class for auth_audit

This will be an audit stream of authentication and connection-level authorization

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 lib/util/debug.c | 1 +
 lib/util/debug.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/lib/util/debug.c b/lib/util/debug.c
index 8a04c25..009f362 100644
--- a/lib/util/debug.c
+++ b/lib/util/debug.c
@@ -537,6 +537,7 @@ static const char *default_classname_table[] = {
 	[DBGC_DNS] =		"dns",
 	[DBGC_LDB] =		"ldb",
 	[DBGC_TEVENT] =		"tevent",
+	[DBGC_AUTH_AUDIT] =	"auth_audit",
 };
 
 /*
diff --git a/lib/util/debug.h b/lib/util/debug.h
index 43c6aa0..786c809 100644
--- a/lib/util/debug.h
+++ b/lib/util/debug.h
@@ -89,6 +89,7 @@ bool dbghdr( int level, const char *location, const char *func);
 #define DBGC_DNS		21
 #define DBGC_LDB		22
 #define DBGC_TEVENT		23
+#define DBGC_AUTH_AUDIT		24
 
 /* So you can define DBGC_CLASS before including debug.h */
 #ifndef DBGC_CLASS
-- 
2.7.4


From 47a82ac312f4b6059f3a7ef02cd2f426a6e51d07 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 12:01:37 +1300
Subject: [PATCH 02/18] s4-smbd: Remember the original client and server IPs
 from the SMB connection

We need to know in the RPC server the original address the client came from
so that we can log this with the authentication audit information

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source4/smbd/service_named_pipe.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/source4/smbd/service_named_pipe.c b/source4/smbd/service_named_pipe.c
index b75a9fa..6cd71ff 100644
--- a/source4/smbd/service_named_pipe.c
+++ b/source4/smbd/service_named_pipe.c
@@ -119,6 +119,9 @@ static void named_pipe_accept_done(struct tevent_req *subreq)
 		goto out;
 	}
 
+	conn->local_address = talloc_steal(conn, server);
+	conn->remote_address = talloc_steal(conn, client);
+	
 	DEBUG(10, ("Accepted npa connection from %s. "
 		   "Client: %s (%s). Server: %s (%s)\n",
 		   tsocket_address_string(conn->remote_address, tmp_ctx),
-- 
2.7.4


From 0e4c4572643ecf7bfb246388db52ebcc7a645446 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 12:04:52 +1300
Subject: [PATCH 03/18] s4-netlogon: Remember many more details in the
 auth_usersupplied info for future logs

This will allow a very verbose JSON line to be logged that others can audit from in the future

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 auth/common_auth.h                            |  9 ++++
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 70 ++++++++++++++++++++-------
 2 files changed, 62 insertions(+), 17 deletions(-)

diff --git a/auth/common_auth.h b/auth/common_auth.h
index d1a775d..28b9bd7 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -44,6 +44,7 @@ struct auth_usersupplied_info
 {
 	const char *workstation_name;
 	const struct tsocket_address *remote_host;
+	const struct tsocket_address *local_host;
 
 	uint32_t logon_parameters;
 
@@ -70,6 +71,14 @@ struct auth_usersupplied_info
 		char *plaintext;
 	} password;
 	uint32_t flags;
+
+	struct {
+		uint32_t negotiate_flags;
+		enum netr_SchannelType secure_channel_type;
+		const char *computer_name;/* [charset(UTF8)] */
+		const char *account_name;/* [charset(UTF8)] */
+		struct dom_sid *sid;/* [unique] */
+	} netlogon_trust_account;
 };
 
 struct auth_method_context;
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index afa9b1c..60421f5 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -867,6 +867,8 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 	case NetlogonServiceInformation:
 	case NetlogonInteractiveTransitiveInformation:
 	case NetlogonServiceTransitiveInformation:
+	case NetlogonNetworkInformation:
+	case NetlogonNetworkTransitiveInformation:
 
 		/* TODO: we need to deny anonymous access here */
 		nt_status = auth_context_create(mem_ctx,
@@ -875,11 +877,46 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 						&auth_context);
 		NT_STATUS_NOT_OK_RETURN(nt_status);
 
-		user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
-		user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
-		user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
-		user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
+		user_info->remote_host = dce_call->conn->remote_address;
+		user_info->local_host = dce_call->conn->local_address;
+
+		user_info->netlogon_trust_account.secure_channel_type
+			= creds->secure_channel_type;
+		user_info->netlogon_trust_account.negotiate_flags
+			= creds->negotiate_flags;
+
+		/*
+		 * These two can be unrelated when the account is
+		 * actually that of a trusted domain, so we want to
+		 * know which DC in that trusted domain contacted
+		 * us
+		 */
+		user_info->netlogon_trust_account.computer_name
+			= creds->computer_name;
+		user_info->netlogon_trust_account.account_name
+			= creds->computer_name;
+		user_info->netlogon_trust_account.sid
+			= creds->sid;
+
+	default:
+		/* We do not need to set up the user_info in this case */
+		break;
+	}
+
+	switch (r->in.logon_level) {
+	case NetlogonInteractiveInformation:
+	case NetlogonServiceInformation:
+	case NetlogonInteractiveTransitiveInformation:
+	case NetlogonServiceTransitiveInformation:
 
+		user_info->logon_parameters
+			= r->in.logon->password->identity_info.parameter_control;
+		user_info->client.account_name
+			= r->in.logon->password->identity_info.account_name.string;
+		user_info->client.domain_name
+			= r->in.logon->password->identity_info.domain_name.string;
+		user_info->workstation_name
+			= r->in.logon->password->identity_info.workstation.string;
 		user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
 		user_info->password_state = AUTH_PASSWORD_HASH;
 
@@ -894,21 +931,20 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 		break;
 	case NetlogonNetworkInformation:
 	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_NOT_OK_RETURN(nt_status);
-
-		nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
+		nt_status = auth_context_set_challenge(
+			auth_context,
+			r->in.logon->network->challenge,
+			"netr_LogonSamLogonWithFlags");
 		NT_STATUS_NOT_OK_RETURN(nt_status);
 
-		user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
-		user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
-		user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
-		user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
+		user_info->logon_parameters
+			= r->in.logon->network->identity_info.parameter_control;
+		user_info->client.account_name
+			= r->in.logon->network->identity_info.account_name.string;
+		user_info->client.domain_name
+			= r->in.logon->network->identity_info.domain_name.string;
+		user_info->workstation_name
+			= r->in.logon->network->identity_info.workstation.string;
 
 		user_info->password_state = AUTH_PASSWORD_RESPONSE;
 		user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
-- 
2.7.4


From 55cd859ea46678a737f1b0444aa2041ab3d346fc Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 13:32:47 +1300
Subject: [PATCH 04/18] gensec: Add
 gensec_{get,set}_target_service_description()

This allows a free text description of what the server-side service is for logging
purposes where the various services may be using the same Kerberos service or not
use Kerberos.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 auth/gensec/gensec.c             | 29 +++++++++++++++++++++++++++++
 auth/gensec/gensec.h             | 17 +++++++++++++++++
 source4/auth/gensec/pygensec.c   | 25 +++++++++++++++++++++++--
 source4/rpc_server/dcesrv_auth.c | 13 +++++++++++++
 4 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index d623613..4615bd8 100644
--- a/auth/gensec/gensec.c
+++ b/auth/gensec/gensec.c
@@ -574,6 +574,7 @@ _PUBLIC_ struct cli_credentials *gensec_get_credentials(struct gensec_security *
 /**
  * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
  *
+ * This is used for Kerberos service principal name resolution.
  */
 
 _PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
@@ -595,6 +596,34 @@ _PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_se
 }
 
 /**
+ * Set the target service (such as 'samr') on an GENSEC context - ensures it is talloc()ed.
+ * 
+ * This is not the Kerberos service principal, instead this is a
+ * constant value that can be logged as part of authentication and
+ * authorization logging
+ */
+_PUBLIC_ NTSTATUS gensec_set_target_service_description(struct gensec_security *gensec_security,
+							const char *service)
+{
+	gensec_security->target.service_description = talloc_strdup(gensec_security, service);
+	if (!gensec_security->target.service_description) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ const char *gensec_get_target_service_description(struct gensec_security *gensec_security)
+{
+	if (gensec_security->target.service_description) {
+		return gensec_security->target.service_description;
+	} else if (gensec_security->target.service) {
+		return gensec_security->target.service;
+	}
+
+	return NULL;
+}
+
+/**
  * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
  *
  */
diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h
index e8bd7b1..7b5242c 100644
--- a/auth/gensec/gensec.h
+++ b/auth/gensec/gensec.h
@@ -50,6 +50,7 @@ struct gensec_target {
 	const char *principal;
 	const char *hostname;
 	const char *service;
+	const char *service_description;
 };
 
 #define GENSEC_FEATURE_SESSION_KEY	0x00000001
@@ -145,10 +146,26 @@ bool gensec_have_feature(struct gensec_security *gensec_security,
 			 uint32_t feature);
 NTTIME gensec_expire_time(struct gensec_security *gensec_security);
 NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials);
+/**
+ * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
+ *
+ * This is used for Kerberos service principal name resolution.
+ */
+
 NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service);
 const char *gensec_get_target_service(struct gensec_security *gensec_security);
 NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname);
 const char *gensec_get_target_hostname(struct gensec_security *gensec_security);
+/**
+ * Set the target service (such as 'samr') on an GENSEC context - ensures it is talloc()ed.
+ * 
+ * This is not the Kerberos service principal, instead this is a
+ * constant value that can be logged as part of authentication and
+ * authorization logging
+ */
+const char *gensec_get_target_service_description(struct gensec_security *gensec_security);
+NTSTATUS gensec_set_target_service_description(struct gensec_security *gensec_security,
+					       const char *service);
 NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
 			    TALLOC_CTX *mem_ctx,
 			    DATA_BLOB *session_key);
diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c
index eba84f0..5701b3b 100644
--- a/source4/auth/gensec/pygensec.c
+++ b/source4/auth/gensec/pygensec.c
@@ -240,6 +240,25 @@ static PyObject *py_gensec_set_target_service(PyObject *self, PyObject *args)
 	Py_RETURN_NONE;
 }
 
+static PyObject *py_gensec_set_target_service_description(PyObject *self, PyObject *args)
+{
+	struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
+	char *target_service_description;
+	NTSTATUS status;
+
+	if (!PyArg_ParseTuple(args, "s", &target_service_description))
+		return NULL;
+
+	status = gensec_set_target_service_description(security,
+						       target_service_description);
+	if (!NT_STATUS_IS_OK(status)) {
+		PyErr_SetNTSTATUS(status);
+		return NULL;
+	}
+	
+	Py_RETURN_NONE;
+}
+
 static PyObject *py_gensec_set_credentials(PyObject *self, PyObject *args)
 {
 	PyObject *py_creds = Py_None;
@@ -615,9 +634,11 @@ static PyMethodDef py_gensec_security_methods[] = {
 	{ "set_credentials", (PyCFunction)py_gensec_set_credentials, METH_VARARGS, 
 		"S.start_client(credentials)" },
 	{ "set_target_hostname", (PyCFunction)py_gensec_set_target_hostname, METH_VARARGS, 
-		"S.start_target_hostname(target_hostname)" },
+		"S.start_target_hostname(target_hostname) \n This sets the Kerberos target hostname to obtain a ticket for." },
 	{ "set_target_service", (PyCFunction)py_gensec_set_target_service, METH_VARARGS, 
-		"S.start_target_service(target_service)" },
+		"S.start_target_service(target_service) \n This sets the Kerberos target service to obtain a ticket for.  The default value is 'host'" },
+	{ "set_target_service_description", (PyCFunction)py_gensec_set_target_service_description, METH_VARARGS, 
+		"S.start_target_service_description(target_service_description) \n This description is set server-side and used in authentication and authorization logs.  The default value is that provided to set_target_service() or None."},
 	{ "session_info", (PyCFunction)py_gensec_session_info, METH_NOARGS,
 		"S.session_info() -> info" },
 	{ "session_key", (PyCFunction)py_gensec_session_key, METH_NOARGS,
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index af0079b..987fcf9 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -125,6 +125,19 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 		return false;
 	}
 
+	/* 
+	 * We have to call this because we set the target_service for
+	 * Kerberos to NULL above, and in any case we wish to log a
+	 * more specific service target.
+	 */
+	status = gensec_set_target_service_description(auth->gensec_security,
+						       call->conn->contexts->iface->name); 
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Failed to call gensec_set_target_service_description %s\n",
+			  nt_errstr(status)));
+		return false;
+	}
+	
 	if (call->conn->remote_address != NULL) {
 		status = gensec_set_remote_address(auth->gensec_security,
 						call->conn->remote_address);
-- 
2.7.4


From 0e5365ac37347c322fdd4e4a0143430205e11bc4 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 14:15:46 +1300
Subject: [PATCH 05/18] gensec: Pass service_description into
 auth_usersuppliedinfo during NTLMSSP

This allows the GENSEC service description to be read at authentication time
for logging, eg that the user authenticated to the SAMR server

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 auth/common_auth.h            | 2 ++
 auth/ntlmssp/ntlmssp_server.c | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/auth/common_auth.h b/auth/common_auth.h
index 28b9bd7..1e9ca29 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -79,6 +79,8 @@ struct auth_usersupplied_info
 		const char *account_name;/* [charset(UTF8)] */
 		struct dom_sid *sid;/* [unique] */
 	} netlogon_trust_account;
+
+	const char *service_description;
 };
 
 struct auth_method_context;
diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c
index ddee875..6d7cc2b 100644
--- a/auth/ntlmssp/ntlmssp_server.c
+++ b/auth/ntlmssp/ntlmssp_server.c
@@ -718,6 +718,8 @@ static NTSTATUS ntlmssp_server_check_password(struct gensec_security *gensec_sec
 	user_info->client.domain_name = ntlmssp_state->domain;
 	user_info->workstation_name = ntlmssp_state->client.netbios_name;
 	user_info->remote_host = gensec_get_remote_address(gensec_security);
+	user_info->service_description
+		= gensec_get_target_service_description(gensec_security);
 
 	user_info->password_state = AUTH_PASSWORD_RESPONSE;
 	user_info->password.response.lanman = ntlmssp_state->lm_resp;
-- 
2.7.4


From 106e75844c54aaad69e01063014a6391cbf51aa9 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 14:17:34 +1300
Subject: [PATCH 06/18] s3-auth: Pass service_description into gensec via
 auth_generic_prepare()

This allows the GENSEC service description to be set from the various callers
that go via this function.

The RPC service description is the name of the interface from the IDL.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source3/auth/auth_generic.c              | 9 +++++++++
 source3/auth/proto.h                     | 1 +
 source3/rpc_server/dcesrv_auth_generic.c | 7 ++++++-
 source3/rpc_server/dcesrv_auth_generic.h | 1 +
 source3/rpc_server/srv_pipe.c            | 6 +++++-
 source3/smbd/negprot.c                   | 8 ++++++++
 source3/smbd/seal.c                      | 1 +
 source3/smbd/sesssetup.c                 | 1 +
 source3/smbd/smb2_sesssetup.c            | 1 +
 9 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index f9b9184..629d202 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -233,6 +233,7 @@ NTSTATUS make_auth4_context(TALLOC_CTX *mem_ctx, struct auth4_context **auth4_co
 
 NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
 			      const struct tsocket_address *remote_address,
+			      const char *service_description,
 			      struct gensec_security **gensec_security_out)
 {
 	struct gensec_security *gensec_security;
@@ -377,6 +378,14 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
 		return nt_status;
 	}
 
+	nt_status = gensec_set_target_service_description(gensec_security,
+							  service_description);
+	
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		TALLOC_FREE(tmp_ctx);
+		return nt_status;
+	}
+
 	*gensec_security_out = talloc_steal(mem_ctx, gensec_security);
 	TALLOC_FREE(tmp_ctx);
 	return NT_STATUS_OK;
diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index 5fd3158..3697211 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -99,6 +99,7 @@ NTSTATUS auth_domain_init(void);
 
 NTSTATUS make_auth4_context(TALLOC_CTX *mem_ctx, struct auth4_context **auth4_context_out);
 NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, const struct tsocket_address *remote_address,
+			      const char *service_description,
 			      struct gensec_security **gensec_security_out);
 
 NTSTATUS auth_check_password_session_info(struct auth4_context *auth_context,
diff --git a/source3/rpc_server/dcesrv_auth_generic.c b/source3/rpc_server/dcesrv_auth_generic.c
index a338108..7bdfdee 100644
--- a/source3/rpc_server/dcesrv_auth_generic.c
+++ b/source3/rpc_server/dcesrv_auth_generic.c
@@ -29,12 +29,15 @@ static NTSTATUS auth_generic_server_authtype_start_as_root(TALLOC_CTX *mem_ctx,
 							   DATA_BLOB *token_in,
 							   DATA_BLOB *token_out,
 							   const struct tsocket_address *remote_address,
+							   const char *service_description,
 							   struct gensec_security **ctx)
 {
 	struct gensec_security *gensec_security = NULL;
 	NTSTATUS status;
 
-	status = auth_generic_prepare(talloc_tos(), remote_address, &gensec_security);
+	status = auth_generic_prepare(talloc_tos(), remote_address,
+				      service_description,
+				      &gensec_security);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(0, (__location__ ": auth_generic_prepare failed: %s\n",
 			  nt_errstr(status)));
@@ -67,6 +70,7 @@ NTSTATUS auth_generic_server_authtype_start(TALLOC_CTX *mem_ctx,
 					    DATA_BLOB *token_in,
 					    DATA_BLOB *token_out,
 					    const struct tsocket_address *remote_address,
+					    const char *service_description,
 					    struct gensec_security **ctx)
 {
 	NTSTATUS status;
@@ -78,6 +82,7 @@ NTSTATUS auth_generic_server_authtype_start(TALLOC_CTX *mem_ctx,
 							    token_in,
 							    token_out,
 							    remote_address,
+							    service_description,
 							    ctx);
 	unbecome_root();
 	return status;
diff --git a/source3/rpc_server/dcesrv_auth_generic.h b/source3/rpc_server/dcesrv_auth_generic.h
index f288c94..36e1a83 100644
--- a/source3/rpc_server/dcesrv_auth_generic.h
+++ b/source3/rpc_server/dcesrv_auth_generic.h
@@ -27,6 +27,7 @@ NTSTATUS auth_generic_server_authtype_start(TALLOC_CTX *mem_ctx,
 					    DATA_BLOB *token_in,
 					    DATA_BLOB *token_out,
 					    const struct tsocket_address *remote_address,
+					    const char *service_description,
 					    struct gensec_security **ctx);
 
 NTSTATUS auth_generic_server_step(struct gensec_security *ctx,
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 407d8d7..4a63dd7 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -517,6 +517,7 @@ bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax)
 static bool pipe_auth_generic_bind(struct pipes_struct *p,
 				   struct ncacn_packet *pkt,
 				   struct dcerpc_auth *auth_info,
+				   const char *service_description,
 				   DATA_BLOB *response)
 {
 	TALLOC_CTX *mem_ctx = pkt;
@@ -529,6 +530,7 @@ static bool pipe_auth_generic_bind(struct pipes_struct *p,
 						    &auth_info->credentials,
 						    response,
 						    p->remote_address,
+						    service_description,
 						    &gensec_security);
 	if (!NT_STATUS_IS_OK(status) &&
 	    !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
@@ -813,7 +815,9 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 		}
 
 		if (!pipe_auth_generic_bind(p, pkt,
-					    &auth_info, &auth_resp)) {
+					    &auth_info,
+					    table->name,
+					    &auth_resp)) {
 			goto err_exit;
 		}
 	} else {
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index cdde334..9a6373d 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -171,7 +171,15 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbXsrv_connection *xconn)
 	/* See if we can get an SPNEGO blob */
 	status = auth_generic_prepare(talloc_tos(),
 				      xconn->remote_address,
+				      "smb",
 				      &gensec_security);
+
+	/*
+	 * There is no need to set a remote address or similar as we
+	 * are just interested in the SPNEGO blob, we never keep this
+	 * context.
+	 */
+	
 	if (NT_STATUS_IS_OK(status)) {
 		status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
 		if (NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c
index d2c8951..cf6637d 100644
--- a/source3/smbd/seal.c
+++ b/source3/smbd/seal.c
@@ -77,6 +77,7 @@ static NTSTATUS make_auth_gensec(const struct tsocket_address *remote_address,
 	NTSTATUS status;
 
 	status = auth_generic_prepare(es, remote_address,
+				      "smb-enc",
 				      &es->gensec_security);
 	if (!NT_STATUS_IS_OK(status)) {
 		return nt_status_squash(status);
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 8ec6093..e3849c9 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -247,6 +247,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 
 	if (auth->gensec == NULL) {
 		status = auth_generic_prepare(session, xconn->remote_address,
+					      "smb",
 					      &auth->gensec);
 		if (!NT_STATUS_IS_OK(status)) {
 			TALLOC_FREE(session);
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index 6a0caac..3efdc9c 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -855,6 +855,7 @@ auth:
 	if (state->auth->gensec == NULL) {
 		status = auth_generic_prepare(state->auth,
 					      state->smb2req->xconn->remote_address,
+					      "smb2",
 					      &state->auth->gensec);
 		if (tevent_req_nterror(req, status)) {
 			return tevent_req_post(req, ev);
-- 
2.7.4


From 428754a9d0f63c97b98d33be237d63a76b9a0f17 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 14:18:57 +1300
Subject: [PATCH 07/18] ntlm_auth: Set ntlm_auth as the service_description
 into gensec

This allows this use case to be clearly found when logged.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source3/utils/ntlm_auth.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 829eb8f..1391053 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -1214,6 +1214,17 @@ static NTSTATUS ntlm_auth_prepare_gensec_server(TALLOC_CTX *mem_ctx,
 	
 	gensec_set_credentials(gensec_security, server_credentials);
 
+	/*
+	 * TODO: Allow the caller to pass their own description here
+	 * via a command-line option 
+	 */
+	nt_status = gensec_set_target_service_description(gensec_security,
+							  "ntlm_auth");
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		TALLOC_FREE(tmp_ctx);
+		return nt_status;
+	}
+	
 	talloc_unlink(tmp_ctx, lp_ctx);
 	talloc_unlink(tmp_ctx, server_credentials);
 	talloc_unlink(tmp_ctx, gensec_settings);
-- 
2.7.4


From c961af495f2c56ccfa603dfffaa16229eedec2d1 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 14:52:07 +1300
Subject: [PATCH 08/18] auth: Fill in user_info->service_description from all
 callers

This will allow the logging code to make clear which protocol an authentication was for.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source3/auth/auth_ntlmssp.c                   |  1 +
 source3/auth/auth_util.c                      | 20 +++++++++++++++-----
 source3/auth/proto.h                          |  5 +++++
 source3/auth/user_info.c                      |  7 +++++++
 source3/smbd/sesssetup.c                      |  5 ++++-
 source3/torture/pdbtest.c                     |  3 ++-
 source3/winbindd/winbindd_pam.c               | 10 +++++++++-
 source4/rpc_server/netlogon/dcerpc_netlogon.c |  2 ++
 source4/smb_server/smb/sesssetup.c            |  4 ++++
 9 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c
index a0e4902..71b8183 100644
--- a/source3/auth/auth_ntlmssp.c
+++ b/source3/auth/auth_ntlmssp.c
@@ -163,6 +163,7 @@ NTSTATUS auth3_check_password(struct auth4_context *auth4_context,
 				       user_info->client.domain_name,
 				       user_info->workstation_name,
 				       user_info->remote_host,
+				       user_info->service_description,
 	                               user_info->password.response.lanman.data ? &user_info->password.response.lanman : NULL,
 	                               user_info->password.response.nt.data ? &user_info->password.response.nt : NULL,
 				       NULL, NULL, NULL,
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 5d9f0e0..d015165 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -97,6 +97,7 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 			    const char *client_domain,
 			    const char *workstation_name,
 			    const struct tsocket_address *remote_address,
+			    const char *service_description,
 			    const DATA_BLOB *lm_pwd,
 			    const DATA_BLOB *nt_pwd,
 			    const struct samr_Password *lm_interactive_pwd,
@@ -149,10 +150,11 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 	 * primary domain name */
 
 	result = make_user_info(mem_ctx, user_info, smb_name, internal_username,
-			      client_domain, domain, workstation_name,
-			      remote_address, lm_pwd, nt_pwd,
-			      lm_interactive_pwd, nt_interactive_pwd,
-			      plaintext, password_state);
+				client_domain, domain, workstation_name,
+				remote_address, service_description,
+				lm_pwd, nt_pwd,
+				lm_interactive_pwd, nt_interactive_pwd,
+				plaintext, password_state);
 	if (NT_STATUS_IS_OK(result)) {
 		/* We have tried mapping */
 		(*user_info)->mapped_state = true;
@@ -188,6 +190,7 @@ bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
 				    smb_name, client_domain, 
 				    workstation_name,
 				    remote_address,
+				    "SamLogon",
 				    lm_pwd_len ? &lm_blob : NULL, 
 				    nt_pwd_len ? &nt_blob : NULL,
 				    NULL, NULL, NULL,
@@ -259,6 +262,7 @@ bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
 			user_info, 
 			smb_name, client_domain, workstation_name,
 			remote_address,
+			"SamLogon",
 			lm_interactive_pwd ? &local_lm_blob : NULL,
 			nt_interactive_pwd ? &local_nt_blob : NULL,
 			lm_interactive_pwd ? &lm_pwd : NULL,
@@ -286,6 +290,7 @@ bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
 			      const char *smb_name, 
 			      const char *client_domain,
 			      const struct tsocket_address *remote_address,
+			      const char *service_description,
 			      const uint8_t chal[8],
 			      DATA_BLOB plaintext_password)
 {
@@ -333,6 +338,7 @@ bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
 		user_info, smb_name, smb_name, client_domain, client_domain, 
 		get_remote_machine_name(),
 		remote_address,
+	        service_description,
 		local_lm_blob.data ? &local_lm_blob : NULL,
 		local_nt_blob.data ? &local_nt_blob : NULL,
 		NULL, NULL,
@@ -357,7 +363,8 @@ NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
                                       const char *smb_name,
                                       const char *client_domain,
 				      const struct tsocket_address *remote_address,
-                                      DATA_BLOB lm_resp, DATA_BLOB nt_resp)
+				      const char *service_description,
+				      DATA_BLOB lm_resp, DATA_BLOB nt_resp)
 {
 	bool allow_raw = lp_raw_ntlmv2_auth();
 
@@ -378,6 +385,7 @@ NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
 			      client_domain, client_domain, 
 			      get_remote_machine_name(),
 			      remote_address,
+			      service_description,
 			      lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
 			      nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
 			      NULL, NULL, NULL,
@@ -390,6 +398,7 @@ NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
 
 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
 			  const struct tsocket_address *remote_address,
+			  const char *service_description,
 			  struct auth_usersupplied_info **user_info)
 {
 	NTSTATUS nt_status;
@@ -400,6 +409,7 @@ bool make_user_info_guest(TALLOC_CTX *mem_ctx,
 				   "","", 
 				   "", 
 				   remote_address,
+				   service_description,
 				   NULL, NULL, 
 				   NULL, NULL, 
 				   NULL,
diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index 3697211..69fa20c 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -154,6 +154,7 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 			    const char *client_domain,
 			    const char *workstation_name,
 			    const struct tsocket_address *remote_address,
+			    const char *service_description,
 			    const DATA_BLOB *lm_pwd,
 			    const DATA_BLOB *nt_pwd,
 			    const struct samr_Password *lm_interactive_pwd,
@@ -186,6 +187,7 @@ bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
 			      const char *smb_name,
 			      const char *client_domain,
 			      const struct tsocket_address *remote_address,
+			      const char *service_description,
 			      const uint8_t chal[8],
 			      DATA_BLOB plaintext_password);
 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
@@ -193,9 +195,11 @@ NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
                                       const char *smb_name,
                                       const char *client_domain,
 				      const struct tsocket_address *remote_address,
+				      const char *service_description,
                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp);
 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
 			  const struct tsocket_address *remote_address,
+			  const char *service_description,
 			  struct auth_usersupplied_info **user_info);
 
 struct samu;
@@ -264,6 +268,7 @@ NTSTATUS make_user_info(TALLOC_CTX *mem_ctx,
 			const char *domain,
 			const char *workstation_name,
 			const struct tsocket_address *remote_address,
+			const char *service_description,
 			const DATA_BLOB *lm_pwd,
 			const DATA_BLOB *nt_pwd,
 			const struct samr_Password *lm_interactive_pwd,
diff --git a/source3/auth/user_info.c b/source3/auth/user_info.c
index 0d5176d..c410d22 100644
--- a/source3/auth/user_info.c
+++ b/source3/auth/user_info.c
@@ -49,6 +49,7 @@ NTSTATUS make_user_info(TALLOC_CTX *mem_ctx,
 			const char *domain,
 			const char *workstation_name,
 			const struct tsocket_address *remote_address,
+			const char *service_description,
 			const DATA_BLOB *lm_pwd,
 			const DATA_BLOB *nt_pwd,
 			const struct samr_Password *lm_interactive_pwd,
@@ -105,6 +106,12 @@ NTSTATUS make_user_info(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_NO_MEMORY;
 	}
 
+	user_info->service_description = talloc_strdup(user_info, service_description);
+	if (user_info->service_description == NULL) {
+		TALLOC_FREE(user_info);
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
 
 	if (lm_pwd && lm_pwd->data) {
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index e3849c9..2b920c7 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -97,7 +97,8 @@ static NTSTATUS check_guest_password(const struct tsocket_address *remote_addres
 	auth_context->get_ntlm_challenge(auth_context,
 					 chal);
 
-	if (!make_user_info_guest(talloc_tos(), remote_address, &user_info)) {
+	if (!make_user_info_guest(talloc_tos(), remote_address, "smb",
+				  &user_info)) {
 		TALLOC_FREE(auth_context);
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -896,6 +897,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
 							 &user_info, user,
 							 domain,
 							 sconn->remote_address,
+							 "smb",
 							 lm_resp, nt_resp);
 		if (NT_STATUS_IS_OK(nt_status)) {
 			nt_status = auth_check_password_session_info(negprot_auth_context, 
@@ -917,6 +919,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
 						      &user_info,
 						      user, domain,
 						      sconn->remote_address,
+						      "smb",
 						      chal,
 						      plaintext_password)) {
 				nt_status = NT_STATUS_NO_MEMORY;
diff --git a/source3/torture/pdbtest.c b/source3/torture/pdbtest.c
index fe51a76..d2b30ed 100644
--- a/source3/torture/pdbtest.c
+++ b/source3/torture/pdbtest.c
@@ -280,7 +280,8 @@ static bool test_auth(TALLOC_CTX *mem_ctx, struct samu *pdb_entry)
 	status = make_user_info(mem_ctx,
 				&user_info, pdb_get_username(pdb_entry), pdb_get_username(pdb_entry),
 				pdb_get_domain(pdb_entry), pdb_get_domain(pdb_entry), lp_netbios_name(), 
-				tsocket_address, NULL, &nt_resp, NULL, NULL, NULL, 
+				tsocket_address, "pdbtest",
+				NULL, &nt_resp, NULL, NULL, NULL, 
 				AUTH_PASSWORD_RESPONSE);
 	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 741a42f..4c2495c 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1247,8 +1247,16 @@ static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
 		TALLOC_FREE(frame);
 		return NT_STATUS_NO_MEMORY;
 	}
+
+	/* 
+	 * TODO: We should get the service description passed in from
+	 * the winbind client, so we can have "smb2", "squid" or "samr" logged
+	 * here. 
+	 */
 	status = make_user_info(frame, &user_info, user, user, domain, domain,
-				lp_netbios_name(), local, lm_resp, nt_resp, NULL, NULL,
+				lp_netbios_name(), local,
+				"winbind",
+				lm_resp, nt_resp, NULL, NULL,
 				NULL, AUTH_PASSWORD_RESPONSE);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(10, ("make_user_info failed: %s\n", nt_errstr(status)));
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 60421f5..b0f8eff 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -858,6 +858,8 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 	user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
 	NT_STATUS_HAVE_NO_MEMORY(user_info);
 
+	user_info->service_description = "SamLogon";
+	
 	netlogon_creds_decrypt_samlogon_logon(creds,
 					      r->in.logon_level,
 					      r->in.logon);
diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c
index e06853a..00e28c1 100644
--- a/source4/smb_server/smb/sesssetup.c
+++ b/source4/smb_server/smb/sesssetup.c
@@ -148,6 +148,8 @@ static void sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *sess)
 
 	user_info = talloc_zero(req, struct auth_usersupplied_info);
 	if (!user_info) goto nomem;
+
+	user_info->service_description = "smb";
 	
 	user_info->mapped_state = false;
 	user_info->logon_parameters = 0;
@@ -325,6 +327,8 @@ static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
 	user_info = talloc_zero(req, struct auth_usersupplied_info);
 	if (!user_info) goto nomem;
 
+	user_info->service_description = "smb";
+	
 	user_info->mapped_state = false;
 	user_info->logon_parameters = 0;
 	user_info->flags = 0;
-- 
2.7.4


From 6b4e00c75679382563e4ca059e31e0af57e45838 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 15:54:47 +1300
Subject: [PATCH 09/18] s4-ldap_server: Split gensec setup into a helper
 function

This makes the error handling simpler when we set more
details onto the gensec context.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source4/ldap_server/ldap_bind.c | 59 ++++++++++++++++++++++++++---------------
 1 file changed, 37 insertions(+), 22 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 1264d11..eab6cbe 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -148,6 +148,38 @@ static NTSTATUS ldapsrv_sasl_postprocess_recv(struct tevent_req *req)
 	return tevent_req_simple_recv_ntstatus(req);
 }
 
+static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn,
+				     const char *sasl_mech,
+				     struct gensec_security **_gensec_security)
+{
+	NTSTATUS status;
+
+	struct gensec_security *gensec_security;
+	
+	status = samba_server_gensec_start(conn,
+					   conn->connection->event.ctx,
+					   conn->connection->msg_ctx,
+					   conn->lp_ctx,
+					   conn->server_credentials,
+					   "ldap",
+					   &gensec_security);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+	
+	gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
+	gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAP_STYLE);
+	
+	status = gensec_start_mech_by_sasl_name(gensec_security, sasl_mech);
+	
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	*_gensec_security = gensec_security;
+	return status;
+}
+
 static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 {
 	struct ldap_BindRequest *req = &call->request->r.BindRequest;
@@ -177,32 +209,15 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	if (!conn->gensec) {
 		conn->session_info = NULL;
 
-		status = samba_server_gensec_start(conn,
-						   conn->connection->event.ctx,
-						   conn->connection->msg_ctx,
-						   conn->lp_ctx,
-						   conn->server_credentials,
-						   "ldap",
-						   &conn->gensec);
+		status = ldapsrv_setup_gensec(conn, req->creds.SASL.mechanism,
+					      &conn->gensec);
 		if (!NT_STATUS_IS_OK(status)) {
-			DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
+			DEBUG(1, ("Failed to start GENSEC server for [%s] code: %s\n",
+				  ldb_binary_encode_string(call, req->creds.SASL.mechanism),
+				  nt_errstr(status)));
 			result = LDAP_OPERATIONS_ERROR;
 			errstr = talloc_asprintf(reply, "SASL: Failed to start authentication system: %s", 
 						 nt_errstr(status));
-		} else {
-
-			gensec_want_feature(conn->gensec, GENSEC_FEATURE_ASYNC_REPLIES);
-			gensec_want_feature(conn->gensec, GENSEC_FEATURE_LDAP_STYLE);
-			
-			status = gensec_start_mech_by_sasl_name(conn->gensec, req->creds.SASL.mechanism);
-			
-			if (!NT_STATUS_IS_OK(status)) {
-				DEBUG(1, ("Failed to start GENSEC SASL[%s] server code: %s\n", 
-					  req->creds.SASL.mechanism, nt_errstr(status)));
-				result = LDAP_OPERATIONS_ERROR;
-				errstr = talloc_asprintf(reply, "SASL:[%s]: Failed to start authentication backend: %s", 
-							 req->creds.SASL.mechanism, nt_errstr(status));
-			}
 		}
 	}
 
-- 
2.7.4


From cd723496bbb5b478aaf57e3bdddcb264dd8fa3b0 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 21 Feb 2017 14:15:05 +1300
Subject: [PATCH 10/18] s4-ldap_server: Set remote and local address values
 into GENSEC

This will allow channel bindings and logging of the address values used during
authentication

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source4/ldap_server/ldap_bind.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index eab6cbe..1c7c628 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -167,6 +167,18 @@ static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn,
 		return status;
 	}
 	
+	status = gensec_set_remote_address(gensec_security,
+					   conn->connection->remote_address);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+	
+	status = gensec_set_local_address(gensec_security,
+					  conn->connection->local_address);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+	
 	gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
 	gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAP_STYLE);
 	
-- 
2.7.4


From fe674ce4800307b501ea488bd28af8e0e976d312 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 15:55:34 +1300
Subject: [PATCH 11/18] auth: Add a reminder about the strings currently used
 for auditing

We will soon have a much better replacement, but a note here may help some in the transition

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source3/auth/auth.c      | 4 ++++
 source4/auth/ntlm/auth.c | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 50d0188..c1e82a2 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -310,6 +310,10 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 
 	/* failed authentication; check for guest lapping */
 
+	/*
+	 * Please try not to change this string, it is probably in use
+	 * in audit logging tools
+	 */
 	DEBUG(2, ("check_ntlm_password:  Authentication for user [%s] -> [%s] FAILED with error %s\n",
 		  user_info->client.account_name, user_info->mapped.account_name,
 		  nt_errstr(nt_status)));
diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index eeb2336..02bd5e2 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -421,6 +421,10 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
 	NTSTATUS status;
 
 	if (tevent_req_is_nterror(req, &status)) {
+		/*
+		 * Please try not to change this string, it is probably in use
+		 * in audit logging tools
+		 */
 		DEBUG(2,("auth_check_password_recv: "
 			 "%s authentication for user [%s\\%s] "
 			 "FAILED with error %s\n",
-- 
2.7.4


From b9b9f66a183ed7f33e8d91d9805c557c2e1f2b95 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 20 Feb 2017 15:57:03 +1300
Subject: [PATCH 12/18] ldap_server: Move code into
 authenticate_ldap_simple_bind()

This function is only called for simple binds, and by moving the mapping into
the function call we allow the unmapped values to be included in the
user_info and so logged.

We also include the local address and the remote address of the client
for future logging

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source4/auth/auth.h             | 18 ++++++++---------
 source4/auth/ntlm/auth_simple.c | 43 +++++++++++++++++++++++++++--------------
 source4/ldap_server/ldap_bind.c | 22 +++++++++------------
 3 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/source4/auth/auth.h b/source4/auth/auth.h
index fb48694..f4c7507 100644
--- a/source4/auth/auth.h
+++ b/source4/auth/auth.h
@@ -159,15 +159,15 @@ NTSTATUS auth_check_password(struct auth4_context *auth_ctx,
 NTSTATUS auth4_init(void);
 NTSTATUS auth_register(const struct auth_operations *ops);
 NTSTATUS server_service_auth_init(void);
-NTSTATUS authenticate_username_pw(TALLOC_CTX *mem_ctx,
-				  struct tevent_context *ev,
-				  struct imessaging_context *msg,
-				  struct loadparm_context *lp_ctx,
-				  const char *nt4_domain,
-				  const char *nt4_username,
-				  const char *password,
-				  const uint32_t logon_parameters,
-				  struct auth_session_info **session_info);
+NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
+				       struct tevent_context *ev,
+				       struct imessaging_context *msg,
+				       struct loadparm_context *lp_ctx,
+				       struct tsocket_address *remote_address,
+				       struct tsocket_address *local_address,
+				       const char *dn,
+				       const char *password,
+				       struct auth_session_info **session_info);
 
 struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
 					    struct tevent_context *ev,
diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c
index f6dd9d0..125d490 100644
--- a/source4/auth/ntlm/auth_simple.c
+++ b/source4/auth/ntlm/auth_simple.c
@@ -23,31 +23,42 @@
 
 #include "includes.h"
 #include "auth/auth.h"
+#include "dsdb/samdb/samdb.h"
 
 /*
  It's allowed to pass NULL as session_info,
  when the caller doesn't need a session_info
 */
-_PUBLIC_ NTSTATUS authenticate_username_pw(TALLOC_CTX *mem_ctx,
-					   struct tevent_context *ev,
-					   struct imessaging_context *msg,
-					   struct loadparm_context *lp_ctx,
-					   const char *nt4_domain,
-					   const char *nt4_username,
-					   const char *password,
-					   const uint32_t logon_parameters,
-					   struct auth_session_info **session_info) 
+_PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
+						struct tevent_context *ev,
+						struct imessaging_context *msg,
+						struct loadparm_context *lp_ctx,
+						struct tsocket_address *remote_address,
+						struct tsocket_address *local_address,
+						const char *dn,
+						const char *password,
+						struct auth_session_info **session_info) 
 {
 	struct auth4_context *auth_context;
 	struct auth_usersupplied_info *user_info;
 	struct auth_user_info_dc *user_info_dc;
 	NTSTATUS nt_status;
 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-
+	const char *nt4_domain;
+	const char *nt4_username;
+	
 	if (!tmp_ctx) {
 		return NT_STATUS_NO_MEMORY;
 	}
 
+	nt_status = crack_auto_name_to_nt4_name(tmp_ctx, ev, lp_ctx, dn,
+						&nt4_domain, &nt4_username);
+	
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		talloc_free(tmp_ctx);
+		return nt_status;
+	}
+
 	nt_status = auth_context_create(tmp_ctx, 
 					ev, msg,
 					lp_ctx,
@@ -64,14 +75,16 @@ _PUBLIC_ NTSTATUS authenticate_username_pw(TALLOC_CTX *mem_ctx,
 	}
 
 	user_info->mapped_state = true;
-	user_info->client.account_name = nt4_username;
+	user_info->client.account_name = dn,
 	user_info->mapped.account_name = nt4_username;
-	user_info->client.domain_name = nt4_domain;
 	user_info->mapped.domain_name = nt4_domain;
 
 	user_info->workstation_name = NULL;
 
-	user_info->remote_host = NULL;
+	user_info->remote_host = remote_address;
+	user_info->local_host = local_address;
+
+	user_info->service_description = "ldap simple bind";
 
 	user_info->password_state = AUTH_PASSWORD_PLAIN;
 	user_info->password.plaintext = talloc_strdup(user_info, password);
@@ -79,7 +92,9 @@ _PUBLIC_ NTSTATUS authenticate_username_pw(TALLOC_CTX *mem_ctx,
 	user_info->flags = USER_INFO_CASE_INSENSITIVE_USERNAME |
 		USER_INFO_DONT_CHECK_UNIX_ACCOUNT;
 
-	user_info->logon_parameters = logon_parameters |
+	user_info->logon_parameters =
+		MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
+		MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT |
 		MSV1_0_CLEARTEXT_PASSWORD_ALLOWED |
 		MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED;
 
diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 1c7c628..2e050a8 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -37,7 +37,6 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 
 	int result;
 	const char *errstr;
-	const char *nt4_domain, *nt4_account;
 
 	struct auth_session_info *session_info;
 
@@ -62,18 +61,15 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 		goto do_reply;
 	}
 
-	status = crack_auto_name_to_nt4_name(call, call->conn->connection->event.ctx, call->conn->lp_ctx, req->dn, &nt4_domain, &nt4_account);
-	if (NT_STATUS_IS_OK(status)) {
-		status = authenticate_username_pw(call,
-						  call->conn->connection->event.ctx,
-						  call->conn->connection->msg_ctx,
-						  call->conn->lp_ctx,
-						  nt4_domain, nt4_account, 
-						  req->creds.password,
-						  MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
-						  MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT,
-						  &session_info);
-	}
+	status = authenticate_ldap_simple_bind(call,
+					       call->conn->connection->event.ctx,
+					       call->conn->connection->msg_ctx,
+					       call->conn->lp_ctx,
+					       call->conn->connection->remote_address,
+					       call->conn->connection->local_address,
+					       req->dn,
+					       req->creds.password,
+					       &session_info);
 
 	if (NT_STATUS_IS_OK(status)) {
 		result = LDAP_SUCCESS;
-- 
2.7.4


From 0d4e6ca1d8d740b7fad69a01963302832c3081bc Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 21 Feb 2017 11:57:57 +1300
Subject: [PATCH 13/18] auth: Add "auth_description" to allow logs to
 distinguish simple bind (etc)

This will allow the authentication log to indicate clearly how the password was
supplied to the server.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 auth/common_auth.h              | 1 +
 auth/ntlmssp/ntlmssp_server.c   | 3 ++-
 source3/smbd/sesssetup.c        | 6 ++++++
 source4/auth/ntlm/auth_simple.c | 4 +++-
 4 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/auth/common_auth.h b/auth/common_auth.h
index 1e9ca29..869f138 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -81,6 +81,7 @@ struct auth_usersupplied_info
 	} netlogon_trust_account;
 
 	const char *service_description;
+	const char *auth_description;
 };
 
 struct auth_method_context;
diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c
index 6d7cc2b..469a836 100644
--- a/auth/ntlmssp/ntlmssp_server.c
+++ b/auth/ntlmssp/ntlmssp_server.c
@@ -720,7 +720,8 @@ static NTSTATUS ntlmssp_server_check_password(struct gensec_security *gensec_sec
 	user_info->remote_host = gensec_get_remote_address(gensec_security);
 	user_info->service_description
 		= gensec_get_target_service_description(gensec_security);
-
+	user_info->auth_description = "NTLMSSP";
+	
 	user_info->password_state = AUTH_PASSWORD_RESPONSE;
 	user_info->password.response.lanman = ntlmssp_state->lm_resp;
 	user_info->password.response.lanman.data = talloc_steal(user_info, ntlmssp_state->lm_resp.data);
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 2b920c7..2032d40 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -103,6 +103,8 @@ static NTSTATUS check_guest_password(const struct tsocket_address *remote_addres
 		return NT_STATUS_NO_MEMORY;
 	}
 
+	user_info->auth_description = "guest";
+	
 	nt_status = auth_check_password_session_info(auth_context, 
 						     mem_ctx, user_info, session_info);
 	TALLOC_FREE(user_info);
@@ -899,6 +901,8 @@ void reply_sesssetup_and_X(struct smb_request *req)
 							 sconn->remote_address,
 							 "smb",
 							 lm_resp, nt_resp);
+		user_info->auth_description = "bare-NTLM";
+		
 		if (NT_STATUS_IS_OK(nt_status)) {
 			nt_status = auth_check_password_session_info(negprot_auth_context, 
 								     req, user_info, &session_info);
@@ -925,6 +929,8 @@ void reply_sesssetup_and_X(struct smb_request *req)
 				nt_status = NT_STATUS_NO_MEMORY;
 			}
 
+			user_info->auth_description = "plaintext";
+			
 			if (NT_STATUS_IS_OK(nt_status)) {
 				nt_status = auth_check_password_session_info(plaintext_auth_context, 
 									     req, user_info, &session_info);
diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c
index 125d490..6831f91 100644
--- a/source4/auth/ntlm/auth_simple.c
+++ b/source4/auth/ntlm/auth_simple.c
@@ -84,7 +84,9 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 	user_info->remote_host = remote_address;
 	user_info->local_host = local_address;
 
-	user_info->service_description = "ldap simple bind";
+	user_info->service_description = "ldap";
+
+	user_info->auth_description = "simple bind";
 
 	user_info->password_state = AUTH_PASSWORD_PLAIN;
 	user_info->password.plaintext = talloc_strdup(user_info, password);
-- 
2.7.4


From 7f11b256d6388b7f05372339ce4b5d0d33622fe1 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 21 Feb 2017 12:14:12 +1300
Subject: [PATCH 14/18] winbindd: Clarify that we do not pre-hash the password
 for rpccli_netlogon_password_logon()

rpccli_netlogon_password_logon() is called in winbind_samlogon_retry_loop() if interactive
is set, and does not use the hashed passwords.

This is only needed for winbindd_dual_auth_passdb(), and by moving the call we both
avoid the extra work and allow it to also be removed in this code path

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source3/winbindd/winbindd_pam.c | 78 ++++++++++++++++++++---------------------
 1 file changed, 39 insertions(+), 39 deletions(-)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 4c2495c..bc2a9f1 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1389,7 +1389,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
 			DBG_NOTICE("No security credentials available for "
 				  "domain [%s]\n", domainname);
 			result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-		} else if (interactive && username != NULL && password != NULL) {
+		} else if (interactive) {
 			result = rpccli_netlogon_password_logon(domain->conn.netlogon_creds,
 								netlogon_pipe->binding_handle,
 								mem_ctx,
@@ -1507,43 +1507,43 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx,
 
 	parse_domain_user(user, name_domain, name_user);
 
-	/* do password magic */
-
-	generate_random_buffer(chal, sizeof(chal));
-
-	if (lp_client_ntlmv2_auth()) {
-		DATA_BLOB server_chal;
-		DATA_BLOB names_blob;
-		server_chal = data_blob_const(chal, 8);
-
-		/* note that the 'workgroup' here is for the local
-		   machine.  The 'server name' must match the
-		   'workstation' passed to the actual SamLogon call.
-		*/
-		names_blob = NTLMv2_generate_names_blob(
-			mem_ctx, lp_netbios_name(), lp_workgroup());
+	if (strequal(name_domain, get_global_sam_name())) {
+		DATA_BLOB chal_blob = data_blob_const(chal, sizeof(chal));
 
-		if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain,
-				      pass,
-				      &server_chal,
-				      &names_blob,
-				      &lm_resp, &nt_resp, NULL, NULL)) {
+		/* do password magic */
+		
+		generate_random_buffer(chal, sizeof(chal));
+		
+		if (lp_client_ntlmv2_auth()) {
+			DATA_BLOB server_chal;
+			DATA_BLOB names_blob;
+			server_chal = data_blob_const(chal, 8);
+			
+			/* note that the 'workgroup' here is for the local
+			   machine.  The 'server name' must match the
+			   'workstation' passed to the actual SamLogon call.
+			*/
+			names_blob = NTLMv2_generate_names_blob(
+				mem_ctx, lp_netbios_name(), lp_workgroup());
+			
+			if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain,
+					      pass,
+					      &server_chal,
+					      &names_blob,
+					      &lm_resp, &nt_resp, NULL, NULL)) {
+				data_blob_free(&names_blob);
+				DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n"));
+				result = NT_STATUS_NO_MEMORY;
+				goto done;
+			}
 			data_blob_free(&names_blob);
-			DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n"));
-			result = NT_STATUS_NO_MEMORY;
-			goto done;
+		} else {
+			lm_resp = data_blob_null;
+			SMBNTencrypt(pass, chal, local_nt_response);
+			
+			nt_resp = data_blob_talloc(mem_ctx, local_nt_response,
+						   sizeof(local_nt_response));
 		}
-		data_blob_free(&names_blob);
-	} else {
-		lm_resp = data_blob_null;
-		SMBNTencrypt(pass, chal, local_nt_response);
-
-		nt_resp = data_blob_talloc(mem_ctx, local_nt_response,
-					   sizeof(local_nt_response));
-	}
-
-	if (strequal(name_domain, get_global_sam_name())) {
-		DATA_BLOB chal_blob = data_blob_const(chal, sizeof(chal));
 
 		result = winbindd_dual_auth_passdb(
 			mem_ctx, 0, name_domain, name_user,
@@ -1552,7 +1552,8 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx,
 			info3);
 
 		/* 
-		 * We need to try the remote NETLOGON server if this is NOT_IMPLEMENTED 
+		 * We need to try the remote NETLOGON server if this is 
+		 * NOT_IMPLEMENTED (for example on the RODC)
 		 */
 		if (!NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
 			goto done;
@@ -1568,9 +1569,8 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx,
 					     pass,
 					     name_domain,
 					     lp_netbios_name(),
-					     chal,
-					     lm_resp,
-					     nt_resp,
+					     NULL,
+					     data_blob_null, data_blob_null,
 					     true, /* interactive */
 					     &my_info3);
 	if (!NT_STATUS_IS_OK(result)) {
-- 
2.7.4


From d162c5d969f22111defa77aa79856881be37481c Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 21 Feb 2017 16:22:07 +1300
Subject: [PATCH 15/18] s4-rpc_server: Correct comment about where the current
 iface can be found

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source4/rpc_server/dcerpc_server.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index f7ec210..ce13fa0 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -940,8 +940,10 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 
 	/*
 	 * At this point we know which interface (eg netlogon, lsa,
-	 * drsuapi) the caller requested.  This is available on
-	 * call->conntext->iface.
+	 * drsuapi) the caller requested in this bind.  This (as the
+	 * most recently added context) is available as the first
+	 * element in the linked list at call->conn->contexts, that is
+	 * call->conn->contexts->iface
 	 */
 
 	if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
-- 
2.7.4


From 9f411e78e3f59396351213d5e0e1216a1fa179d8 Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary at catalyst.net.nz>
Date: Thu, 23 Feb 2017 13:50:14 +1300
Subject: [PATCH 16/18] auth: Generate a human readable Authentication log
 message.

Add a human readable authentication log line, to allow
verification that all required details are being passed.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 lib/util/tests/util_str_escape.c    |  90 ++++++++++++++++++++++++++
 lib/util/util_str_escape.c          | 126 ++++++++++++++++++++++++++++++++++++
 lib/util/util_str_escape.h          |  27 ++++++++
 lib/util/wscript_build              |   5 ++
 source4/auth/ntlm/auth.c            |  82 ++++++++++++++++++++++-
 source4/auth/ntlm/wscript_build     |   2 +-
 source4/torture/local/local.c       |   1 +
 source4/torture/local/wscript_build |   1 +
 8 files changed, 331 insertions(+), 3 deletions(-)
 create mode 100644 lib/util/tests/util_str_escape.c
 create mode 100644 lib/util/util_str_escape.c
 create mode 100644 lib/util/util_str_escape.h

diff --git a/lib/util/tests/util_str_escape.c b/lib/util/tests/util_str_escape.c
new file mode 100644
index 0000000..82e2209
--- /dev/null
+++ b/lib/util/tests/util_str_escape.c
@@ -0,0 +1,90 @@
+/*
+
+   util_str_escape testing
+
+   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2017
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "torture/torture.h"
+#include "torture/local/proto.h"
+#include "lib/util/util_str_escape.h"
+
+static bool test_log_escape_empty_string(struct torture_context *tctx)
+{
+	char *result = log_escape( tctx, "");
+	torture_assert_str_equal(tctx, result, "", "Empty string handling");
+	return true;
+}
+
+static bool test_log_escape_null_string(struct torture_context *tctx)
+{
+	char *result = log_escape( tctx, NULL);
+	torture_assert(tctx, (result == NULL), "Empty string handling");
+	return true;
+}
+
+static bool test_log_escape_plain_string(struct torture_context *tctx)
+{
+	const char *input    = "a plain string with no escapable characters";
+	const char *expected = "a plain string with no escapable characters";
+
+	char *result = log_escape( tctx, input);
+	torture_assert_str_equal(tctx, result, expected,
+				 "Plain string handling");
+	return true;
+}
+
+static bool test_log_escape_string(struct torture_context *tctx)
+{
+	const char *input    = "\a\b\f\n\r\t\v\\\x01";
+	const char *expected = "\\a\\b\\f\\n\\r\\t\\v\\\\\\x01";
+
+	char *result = log_escape( tctx, input);
+	torture_assert_str_equal(tctx, result, expected,
+				 "Escapable characters in string");
+	return true;
+}
+
+static bool test_log_escape_hex_string(struct torture_context *tctx)
+{
+	const char *input    = "\x01\x1F ";
+	const char *expected = "\\x01\\x1F ";
+
+	char *result = log_escape( tctx, input);
+	torture_assert_str_equal(tctx, result, expected,
+				 "hex escaping");
+	return true;
+}
+struct torture_suite *torture_local_util_str_escape(TALLOC_CTX *mem_ctx)
+{
+	struct torture_suite *suite = torture_suite_create(mem_ctx,
+							   "util_str_escape");
+
+	torture_suite_add_simple_test(suite, "log_escape_empty_string",
+				      test_log_escape_empty_string);
+	torture_suite_add_simple_test(suite, "log_escape_null_string",
+				      test_log_escape_null_string);
+	torture_suite_add_simple_test(suite, "log_escape_plain_string",
+				      test_log_escape_plain_string);
+	torture_suite_add_simple_test(suite, "log_escape_string",
+				      test_log_escape_string);
+	torture_suite_add_simple_test(suite, "log_escape_hex_string",
+				      test_log_escape_hex_string);
+
+
+	return suite;
+}
diff --git a/lib/util/util_str_escape.c b/lib/util/util_str_escape.c
new file mode 100644
index 0000000..0d8a871
--- /dev/null
+++ b/lib/util/util_str_escape.c
@@ -0,0 +1,126 @@
+/*
+   Samba string escaping routines
+
+   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2017
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/util/util_str_escape.h"
+
+
+/*
+ * Calculate the encoded length of a character for log_escape
+ *
+ */
+static size_t encoded_length(char c)
+{
+	if ( c != '\\' &&  c > 0x1F) {
+		return 1;
+	} else {
+		switch (c) {
+		case '\a':
+		case '\b':
+		case '\f':
+		case '\n':
+		case '\r':
+		case '\t':
+		case '\v':
+		case '\\':
+			return 2;  /* C escape sequence */
+		default:
+			return 4;  /* hex escape \xhh   */
+		}
+	}
+}
+
+/*
+ * Escape any control characters in the inputs to prevent them from
+ * interfering with the log output.
+ */
+char *log_escape(TALLOC_CTX *frame, const char *in)
+{
+	size_t size = 0;        /* Space to allocate for the escaped data */
+	char *encoded = NULL;   /* The encoded string                     */
+	const char *c;
+	char *e;
+
+	if (in == NULL) {
+		return NULL;
+	}
+
+	/* Calculate the size required for the escaped array */
+	c = in;
+	while (*c) {
+		size += encoded_length( *c);
+		c++;
+	}
+	size++;
+
+	encoded = talloc_array( frame, char, size);
+	if (encoded == NULL) {
+		DBG_ERR( "Out of memory allocating encoded string");
+		return NULL;
+	}
+
+	c = in;
+	e = encoded;
+	while (*c) {
+		if (*c != '\\' && *c > 0x1F) {
+			*e++ = *c++;
+		} else {
+			switch (*c) {
+			case '\a':
+				*e++ = '\\';
+				*e++ = 'a';
+				break;
+			case '\b':
+				*e++ = '\\';
+				*e++ = 'b';
+				break;
+			case '\f':
+				*e++ = '\\';
+				*e++ = 'f';
+				break;
+			case '\n':
+				*e++ = '\\';
+				*e++ = 'n';
+				break;
+			case '\r':
+				*e++ = '\\';
+				*e++ = 'r';
+				break;
+			case '\t':
+				*e++ = '\\';
+				*e++ = 't';
+				break;
+			case '\v':
+				*e++ = '\\';
+				*e++ = 'v';
+				break;
+			case '\\':
+				*e++ = '\\';
+				*e++ = '\\';
+				break;
+			default:
+				snprintf(e, 5, "\\x%02X", *c);
+				e += 4;
+			}
+			c++;
+		}
+	}
+	*e = '\0';
+	return encoded;
+}
diff --git a/lib/util/util_str_escape.h b/lib/util/util_str_escape.h
new file mode 100644
index 0000000..0b4c596
--- /dev/null
+++ b/lib/util/util_str_escape.h
@@ -0,0 +1,27 @@
+/*
+   Samba string escaping routines
+
+   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2017
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _SAMBA_UTIL_STR_ESCAPE_H
+#define _SAMBA_UTIL_STR_ESCAPE_H
+
+#include <talloc.h>
+
+char *log_escape(TALLOC_CTX *frame, const char *in);
+
+#endif
diff --git a/lib/util/wscript_build b/lib/util/wscript_build
index ddece0e..81178b8 100644
--- a/lib/util/wscript_build
+++ b/lib/util/wscript_build
@@ -204,3 +204,8 @@ else:
                         source='access.c',
                         deps='interfaces samba-util',
                         local_include=False)
+
+    bld.SAMBA_SUBSYSTEM('util_str_escape',
+                        source='util_str_escape.c',
+                        deps='talloc',
+                        local_include=False)
diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index 02bd5e2..d4023d9 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -21,6 +21,7 @@
 #include "includes.h"
 #include <tevent.h>
 #include "../lib/util/tevent_ntstatus.h"
+#include "../lib/tsocket/tsocket.h"
 #include "../lib/util/dlinklist.h"
 #include "auth/auth.h"
 #include "auth/ntlm/auth_proto.h"
@@ -28,12 +29,17 @@
 #include "dsdb/samdb/samdb.h"
 #include "libcli/wbclient/wbclient.h"
 #include "lib/util/samba_modules.h"
+#include "lib/util/util_str_escape.h"
 #include "auth/credentials/credentials.h"
 #include "system/kerberos.h"
 #include "auth/kerberos/kerberos.h"
 #include "auth/kerberos/kerberos_util.h"
 #include "libds/common/roles.h"
 
+/* Debug log levels for authentication logging */
+#define AUTH_SUCCESS_LEVEL 5
+#define AUTH_FAILURE_LEVEL 2
+
 static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
 						   TALLOC_CTX *mem_ctx,
                                                   void *server_returned_info,
@@ -392,6 +398,75 @@ static void auth_check_password_async_trigger(struct tevent_context *ev,
 	tevent_req_done(req);
 }
 
+/*
+ * Log details of an authentication attempt.
+ * Successful and unsuccessful attempts are logged.
+ *
+ * TODO: Currently using ldb_binary_encode_string to encode the user data
+ *       this is going to do unpleasant things to any non ascii data.
+ */
+static void log_authentication_event(bool err,
+				     struct auth_check_password_state *state,
+				     NTSTATUS status)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	char *ts;         /* formatted current time      */
+	char *remote;     /* formatted remote host       */
+	char *local;      /* formatted local host        */
+	char *nl = NULL;  /* NETLOGON details if present */
+	const struct auth_usersupplied_info *ui = NULL;
+	char *computer_name;
+	char *account_name;
+
+	/* set the log level */
+	int  level = err ? AUTH_FAILURE_LEVEL : AUTH_SUCCESS_LEVEL;
+
+	/* Get the current time */
+        ts = http_timestring(frame, time(NULL));
+
+	/* alias state->user_info to keep code lines < 80 chars */
+	ui = state->user_info;
+
+	/* Only log the NETLOGON details if they are present */
+	if (state->user_info->netlogon_trust_account.computer_name ||
+	    state->user_info->netlogon_trust_account.account_name) {
+		computer_name = log_escape(frame,
+			ui->netlogon_trust_account.computer_name);
+		account_name  = log_escape(frame,
+			ui->netlogon_trust_account.account_name);
+		nl = talloc_asprintf(frame,
+			" NETLOGON computer [%s] trust account [%s]",
+			computer_name, account_name);
+	}
+
+	remote = tsocket_address_string(state->user_info->remote_host, frame);
+	local  = tsocket_address_string(state->user_info->local_host, frame);
+	DEBUGC( DBGC_AUTH_AUDIT, level, (
+		"Auth: [%s,%s] user [%s\\%s]"
+		" at [%s] status [%s]."
+		" workstation [%s] remote host [%s]"
+		" supplied id [%s\\%s]."
+		" local host [%s]"
+		" %s\n",
+		ui->service_description,
+		ui->auth_description,
+		log_escape(frame, ui->mapped.domain_name),
+		log_escape(frame, ui->mapped.account_name),
+		ts,
+		nt_errstr( status),
+		log_escape(frame, ui->workstation_name),
+		remote,
+		log_escape(frame, ui->client.domain_name),
+		log_escape(frame, ui->client.account_name),
+		local,
+		nl ? nl : ""
+		));
+
+	talloc_free( frame);
+}
+
+
 /**
  * Check a user's Plaintext, LM or NTLM password.
  * async receive function
@@ -418,9 +493,12 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
 {
 	struct auth_check_password_state *state =
 		tevent_req_data(req, struct auth_check_password_state);
-	NTSTATUS status;
+	NTSTATUS status = NT_STATUS_OK;
 
-	if (tevent_req_is_nterror(req, &status)) {
+	bool err = tevent_req_is_nterror(req, &status);
+	if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, AUTH_SUCCESS_LEVEL))
+		log_authentication_event(err, state, status);
+	if (err) {
 		/*
 		 * Please try not to change this string, it is probably in use
 		 * in audit logging tools
diff --git a/source4/auth/ntlm/wscript_build b/source4/auth/ntlm/wscript_build
index 50d301d..5ee8ac5 100644
--- a/source4/auth/ntlm/wscript_build
+++ b/source4/auth/ntlm/wscript_build
@@ -43,7 +43,7 @@ bld.SAMBA_MODULE('auth4_unix',
 bld.SAMBA_LIBRARY('auth4',
 	source='auth.c auth_util.c auth_simple.c',
 	autoproto='auth_proto.h',
-	deps='samba-util samba-security samdb samba-credentials tevent-util LIBWBCLIENT_OLD auth_unix_token samba-modules KERBEROS_UTIL',
+	deps='samba-util samba-security samdb samba-credentials tevent-util LIBWBCLIENT_OLD auth_unix_token samba-modules KERBEROS_UTIL util_str_escape',
 	private_library=True
 	)
 
diff --git a/source4/torture/local/local.c b/source4/torture/local/local.c
index 6641f21..89066c5 100644
--- a/source4/torture/local/local.c
+++ b/source4/torture/local/local.c
@@ -74,6 +74,7 @@
 	torture_local_verif_trailer,
 	torture_local_nss,
 	torture_local_fsrvp,
+	torture_local_util_str_escape,
 	NULL
 };
 
diff --git a/source4/torture/local/wscript_build b/source4/torture/local/wscript_build
index 3a12b6b..34ce040 100644
--- a/source4/torture/local/wscript_build
+++ b/source4/torture/local/wscript_build
@@ -20,6 +20,7 @@ TORTURE_LOCAL_SOURCE = '''../../../lib/util/charset/tests/iconv.c
 	../../../lib/util/tests/strv.c
 	../../../lib/util/tests/strv_util.c
 	../../../lib/util/tests/util.c
+	../../../lib/util/tests/util_str_escape.c
 	verif_trailer.c
 	nss_tests.c
 	fsrvp_state.c'''
-- 
2.7.4


From 49da2e17d67953406f6a9dd0eefdb10bda9da44d Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 23 Feb 2017 14:31:52 +1300
Subject: [PATCH 17/18] auth: Always supply both the remote and local address
 to the auth subsystem

This ensures that gensec, and then the NTLM auth subsystem under it, always gets the
remote and local address pointers for potential logging.

The local address allows us to know which interface an authentication is on

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 auth/ntlmssp/ntlmssp_server.c            |  1 +
 source3/auth/auth_generic.c              |  8 +++++
 source3/auth/proto.h                     |  4 ++-
 source3/rpc_server/dcesrv_auth_generic.c |  7 ++++-
 source3/rpc_server/dcesrv_auth_generic.h |  1 +
 source3/rpc_server/srv_pipe.c            |  1 +
 source3/smbd/negprot.c                   |  7 +++--
 source3/smbd/seal.c                      |  5 +++
 source3/smbd/sesssetup.c                 |  4 ++-
 source3/smbd/smb2_sesssetup.c            |  1 +
 source4/smb_server/smb/sesssetup.c       | 53 ++++++++++++++++++++++++++++++--
 source4/smb_server/smb2/sesssetup.c      | 41 +++++++++++++++++++++++-
 12 files changed, 123 insertions(+), 10 deletions(-)

diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c
index 469a836..1a4e02b 100644
--- a/auth/ntlmssp/ntlmssp_server.c
+++ b/auth/ntlmssp/ntlmssp_server.c
@@ -718,6 +718,7 @@ static NTSTATUS ntlmssp_server_check_password(struct gensec_security *gensec_sec
 	user_info->client.domain_name = ntlmssp_state->domain;
 	user_info->workstation_name = ntlmssp_state->client.netbios_name;
 	user_info->remote_host = gensec_get_remote_address(gensec_security);
+	user_info->local_host = gensec_get_local_address(gensec_security);
 	user_info->service_description
 		= gensec_get_target_service_description(gensec_security);
 	user_info->auth_description = "NTLMSSP";
diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 629d202..52fbef6 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -233,6 +233,7 @@ NTSTATUS make_auth4_context(TALLOC_CTX *mem_ctx, struct auth4_context **auth4_co
 
 NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
 			      const struct tsocket_address *remote_address,
+			      const struct tsocket_address *local_address,
 			      const char *service_description,
 			      struct gensec_security **gensec_security_out)
 {
@@ -378,6 +379,13 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
 		return nt_status;
 	}
 
+	nt_status = gensec_set_local_address(gensec_security,
+					     local_address);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		TALLOC_FREE(tmp_ctx);
+		return nt_status;
+	}
+
 	nt_status = gensec_set_target_service_description(gensec_security,
 							  service_description);
 	
diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index 69fa20c..b3981d3 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -98,7 +98,9 @@ NTSTATUS auth_domain_init(void);
 /* The following definitions come from auth/auth_generic.c  */
 
 NTSTATUS make_auth4_context(TALLOC_CTX *mem_ctx, struct auth4_context **auth4_context_out);
-NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, const struct tsocket_address *remote_address,
+NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
+			      const struct tsocket_address *remote_address,
+			      const struct tsocket_address *local_address,
 			      const char *service_description,
 			      struct gensec_security **gensec_security_out);
 
diff --git a/source3/rpc_server/dcesrv_auth_generic.c b/source3/rpc_server/dcesrv_auth_generic.c
index 7bdfdee..1092cd3 100644
--- a/source3/rpc_server/dcesrv_auth_generic.c
+++ b/source3/rpc_server/dcesrv_auth_generic.c
@@ -29,13 +29,16 @@ static NTSTATUS auth_generic_server_authtype_start_as_root(TALLOC_CTX *mem_ctx,
 							   DATA_BLOB *token_in,
 							   DATA_BLOB *token_out,
 							   const struct tsocket_address *remote_address,
+							   const struct tsocket_address *local_address,
 							   const char *service_description,
 							   struct gensec_security **ctx)
 {
 	struct gensec_security *gensec_security = NULL;
 	NTSTATUS status;
 
-	status = auth_generic_prepare(talloc_tos(), remote_address,
+	status = auth_generic_prepare(talloc_tos(),
+				      remote_address,
+				      local_address,
 				      service_description,
 				      &gensec_security);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -70,6 +73,7 @@ NTSTATUS auth_generic_server_authtype_start(TALLOC_CTX *mem_ctx,
 					    DATA_BLOB *token_in,
 					    DATA_BLOB *token_out,
 					    const struct tsocket_address *remote_address,
+					    const struct tsocket_address *local_address,
 					    const char *service_description,
 					    struct gensec_security **ctx)
 {
@@ -82,6 +86,7 @@ NTSTATUS auth_generic_server_authtype_start(TALLOC_CTX *mem_ctx,
 							    token_in,
 							    token_out,
 							    remote_address,
+							    local_address,
 							    service_description,
 							    ctx);
 	unbecome_root();
diff --git a/source3/rpc_server/dcesrv_auth_generic.h b/source3/rpc_server/dcesrv_auth_generic.h
index 36e1a83..4e86eab 100644
--- a/source3/rpc_server/dcesrv_auth_generic.h
+++ b/source3/rpc_server/dcesrv_auth_generic.h
@@ -27,6 +27,7 @@ NTSTATUS auth_generic_server_authtype_start(TALLOC_CTX *mem_ctx,
 					    DATA_BLOB *token_in,
 					    DATA_BLOB *token_out,
 					    const struct tsocket_address *remote_address,
+					    const struct tsocket_address *local_address,
 					    const char *service_description,
 					    struct gensec_security **ctx);
 
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 4a63dd7..446679f 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -530,6 +530,7 @@ static bool pipe_auth_generic_bind(struct pipes_struct *p,
 						    &auth_info->credentials,
 						    response,
 						    p->remote_address,
+						    p->local_address,
 						    service_description,
 						    &gensec_security);
 	if (!NT_STATUS_IS_OK(status) &&
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 9a6373d..bd7291c 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -171,13 +171,14 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbXsrv_connection *xconn)
 	/* See if we can get an SPNEGO blob */
 	status = auth_generic_prepare(talloc_tos(),
 				      xconn->remote_address,
+				      xconn->local_address,
 				      "smb",
 				      &gensec_security);
 
 	/*
-	 * There is no need to set a remote address or similar as we
-	 * are just interested in the SPNEGO blob, we never keep this
-	 * context.
+	 * Despite including it above, there is no need to set a
+	 * remote address or similar as we are just interested in the
+	 * SPNEGO blob, we never keep this context.
 	 */
 	
 	if (NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c
index cf6637d..065419e 100644
--- a/source3/smbd/seal.c
+++ b/source3/smbd/seal.c
@@ -72,11 +72,13 @@ bool is_encrypted_packet(const uint8_t *inbuf)
 ******************************************************************************/
 
 static NTSTATUS make_auth_gensec(const struct tsocket_address *remote_address,
+				 const struct tsocket_address *local_address,
 				 struct smb_trans_enc_state *es)
 {
 	NTSTATUS status;
 
 	status = auth_generic_prepare(es, remote_address,
+				      local_address,
 				      "smb-enc",
 				      &es->gensec_security);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -107,6 +109,7 @@ static NTSTATUS make_auth_gensec(const struct tsocket_address *remote_address,
 ******************************************************************************/
 
 static NTSTATUS make_srv_encryption_context(const struct tsocket_address *remote_address,
+					    const struct tsocket_address *local_address,
 					    struct smb_trans_enc_state **pp_es)
 {
 	NTSTATUS status;
@@ -120,6 +123,7 @@ static NTSTATUS make_srv_encryption_context(const struct tsocket_address *remote
 		return NT_STATUS_NO_MEMORY;
 	}
 	status = make_auth_gensec(remote_address,
+				  local_address,
 				  es);
 	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(es);
@@ -208,6 +212,7 @@ NTSTATUS srv_request_encryption_setup(connection_struct *conn,
 	if (!partial_srv_trans_enc_ctx) {
 		/* This is the initial step. */
 		status = make_srv_encryption_context(conn->sconn->remote_address,
+						     conn->sconn->local_address,
 					&partial_srv_trans_enc_ctx);
 		if (!NT_STATUS_IS_OK(status)) {
 			return status;
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 2032d40..26ce9f0 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -249,7 +249,9 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 	}
 
 	if (auth->gensec == NULL) {
-		status = auth_generic_prepare(session, xconn->remote_address,
+		status = auth_generic_prepare(session,
+					      xconn->remote_address,
+					      xconn->local_address,
 					      "smb",
 					      &auth->gensec);
 		if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index 3efdc9c..056d807 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -855,6 +855,7 @@ auth:
 	if (state->auth->gensec == NULL) {
 		status = auth_generic_prepare(state->auth,
 					      state->smb2req->xconn->remote_address,
+					      state->smb2req->xconn->local_address,
 					      "smb2",
 					      &state->auth->gensec);
 		if (tevent_req_nterror(req, status)) {
diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c
index 00e28c1..3528548 100644
--- a/source4/smb_server/smb/sesssetup.c
+++ b/source4/smb_server/smb/sesssetup.c
@@ -117,7 +117,7 @@ failed:
 static void sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *sess)
 {
 	struct auth_usersupplied_info *user_info = NULL;
-	struct tsocket_address *remote_address;
+	struct tsocket_address *remote_address, *local_address;
 	const char *remote_machine = NULL;
 	struct tevent_req *subreq;
 	struct sesssetup_context *state;
@@ -146,6 +146,9 @@ static void sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *sess)
 		if (!remote_machine) goto nomem;
 	}
 
+	local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
+	if (!local_address) goto nomem;
+
 	user_info = talloc_zero(req, struct auth_usersupplied_info);
 	if (!user_info) goto nomem;
 
@@ -157,7 +160,9 @@ static void sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *sess)
 	user_info->client.account_name = sess->old.in.user;
 	user_info->client.domain_name = sess->old.in.domain;
 	user_info->workstation_name = remote_machine;
+
 	user_info->remote_host = talloc_steal(user_info, remote_address);
+	user_info->local_host = talloc_steal(user_info, local_address);
 	
 	user_info->password_state = AUTH_PASSWORD_RESPONSE;
 	user_info->password.response.lanman = sess->old.in.password;
@@ -261,7 +266,7 @@ static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
 {
 	NTSTATUS status;
 	struct auth_usersupplied_info *user_info = NULL;
-	struct tsocket_address *remote_address;
+	struct tsocket_address *remote_address, *local_address;
 	const char *remote_machine = NULL;
 	struct tevent_req *subreq;
 	struct sesssetup_context *state;
@@ -324,6 +329,9 @@ static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
 		if (!remote_machine) goto nomem;
 	}
 
+	local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
+	if (!local_address) goto nomem;
+
 	user_info = talloc_zero(req, struct auth_usersupplied_info);
 	if (!user_info) goto nomem;
 
@@ -336,6 +344,7 @@ static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
 	user_info->client.domain_name = sess->nt1.in.domain;
 	user_info->workstation_name = remote_machine;
 	user_info->remote_host = talloc_steal(user_info, remote_address);
+	user_info->local_host = talloc_steal(user_info, local_address);
 	
 	user_info->password_state = AUTH_PASSWORD_RESPONSE;
 	user_info->password.response.lanman = sess->nt1.in.password1;
@@ -452,7 +461,7 @@ static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *se
 	/* lookup an existing session */
 	if (vuid == 0) {
 		struct gensec_security *gensec_ctx;
-
+		struct tsocket_address *remote_address, *local_address;
 		status = samba_server_gensec_start(req,
 						   req->smb_conn->connection->event.ctx,
 						   req->smb_conn->connection->msg_ctx,
@@ -467,6 +476,44 @@ static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *se
 
 		gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
 
+		remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
+							req);
+		if (!remote_address) {
+			status = NT_STATUS_INTERNAL_ERROR;
+			DBG_ERR("Failed to obtain remote address");
+			goto failed;
+		}
+		
+		status = gensec_set_remote_address(gensec_ctx,
+						   remote_address);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("Failed to set remote address");
+			goto failed;
+		}
+
+		local_address = socket_get_local_addr(req->smb_conn->connection->socket,
+							req);
+		if (!local_address) {
+			status = NT_STATUS_INTERNAL_ERROR;
+			DBG_ERR("Failed to obtain local address");
+			goto failed;
+		}
+		
+		status = gensec_set_local_address(gensec_ctx,
+						   local_address);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("Failed to set local address");
+			goto failed;
+		}
+
+		status = gensec_set_target_service_description(gensec_ctx,
+							       "smb");
+	
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("Failed to set service description");
+			goto failed;
+		}
+
 		status = gensec_start_mech_by_oid(gensec_ctx, req->smb_conn->negotiate.oid);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(1, ("Failed to start GENSEC %s server code: %s\n", 
diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c
index 5e261a2..f3f0e79 100644
--- a/source4/smb_server/smb2/sesssetup.c
+++ b/source4/smb_server/smb2/sesssetup.c
@@ -130,6 +130,7 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses
 	 */
 	if (vuid == 0) {
 		struct gensec_security *gensec_ctx;
+		struct tsocket_address *remote_address, *local_address;
 
 		status = samba_server_gensec_start(req,
 						   req->smb_conn->connection->event.ctx,
@@ -142,9 +143,47 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses
 			DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
 			goto failed;
 		}
-
+		
 		gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
 
+		remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
+							req);
+		if (!remote_address) {
+			status = NT_STATUS_INTERNAL_ERROR;
+			DBG_ERR("Failed to obtain remote address");
+			goto failed;
+		}
+		
+		status = gensec_set_remote_address(gensec_ctx,
+						   remote_address);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("Failed to set remote address");
+			goto failed;
+		}
+
+		local_address = socket_get_local_addr(req->smb_conn->connection->socket,
+							req);
+		if (!local_address) {
+			status = NT_STATUS_INTERNAL_ERROR;
+			DBG_ERR("Failed to obtain local address");
+			goto failed;
+		}
+		
+		status = gensec_set_local_address(gensec_ctx,
+						   local_address);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("Failed to set local address");
+			goto failed;
+		}
+
+		status = gensec_set_target_service_description(gensec_ctx,
+							       "smb2");
+	
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("Failed to set service description");
+			goto failed;
+		}
+
 		status = gensec_start_mech_by_oid(gensec_ctx, GENSEC_OID_SPNEGO);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(1, ("Failed to start GENSEC SPNEGO server code: %s\n", nt_errstr(status)));
-- 
2.7.4


From 476f376e98ebbb917e18402268df09d3184183e6 Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary at catalyst.net.nz>
Date: Fri, 24 Feb 2017 13:29:12 +1300
Subject: [PATCH 18/18] rpc: Always supply both the remote and local address to
 the auth subsystem

This ensures that gensec, and then the NTLM auth subsystem under it, always gets the
remote and local address pointers for potential logging.

The local address allows us to know which interface an authentication is on

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source3/auth/auth_ntlmssp.c                     |  1 +
 source3/auth/auth_util.c                        | 17 +++++++--
 source3/auth/proto.h                            |  7 ++++
 source3/auth/user_info.c                        |  8 ++++
 source3/librpc/rpc/dcerpc_ep.c                  |  1 +
 source3/printing/nt_printing_migrate_internal.c |  1 +
 source3/printing/printspoolss.c                 |  2 +
 source3/rpc_client/cli_winreg_int.c             |  1 +
 source3/rpc_server/netlogon/srv_netlog_nt.c     |  5 +++
 source3/rpc_server/rpc_ncacn_np.c               | 15 ++++++--
 source3/rpc_server/rpc_ncacn_np.h               |  4 ++
 source3/rpc_server/rpc_server.c                 | 50 +++++++++++++++++++------
 source3/rpc_server/spoolss/srv_spoolss_util.c   |  1 +
 source3/smbd/lanman.c                           | 20 ++++++++--
 source3/smbd/reply.c                            |  1 +
 source3/smbd/sesssetup.c                        | 11 ++++--
 source3/torture/pdbtest.c                       | 13 +++++--
 source3/winbindd/winbindd_cm.c                  |  2 +
 source3/winbindd/winbindd_pam.c                 |  2 +-
 source4/rpc_server/dcesrv_auth.c                | 10 +++++
 20 files changed, 143 insertions(+), 29 deletions(-)

diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c
index 71b8183..f004c59 100644
--- a/source3/auth/auth_ntlmssp.c
+++ b/source3/auth/auth_ntlmssp.c
@@ -163,6 +163,7 @@ NTSTATUS auth3_check_password(struct auth4_context *auth4_context,
 				       user_info->client.domain_name,
 				       user_info->workstation_name,
 				       user_info->remote_host,
+				       user_info->local_host,
 				       user_info->service_description,
 	                               user_info->password.response.lanman.data ? &user_info->password.response.lanman : NULL,
 	                               user_info->password.response.nt.data ? &user_info->password.response.nt : NULL,
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index d015165..ffd60e0 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -97,6 +97,7 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 			    const char *client_domain,
 			    const char *workstation_name,
 			    const struct tsocket_address *remote_address,
+			    const struct tsocket_address *local_address,
 			    const char *service_description,
 			    const DATA_BLOB *lm_pwd,
 			    const DATA_BLOB *nt_pwd,
@@ -151,8 +152,8 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 
 	result = make_user_info(mem_ctx, user_info, smb_name, internal_username,
 				client_domain, domain, workstation_name,
-				remote_address, service_description,
-				lm_pwd, nt_pwd,
+				remote_address, local_address,
+				service_description, lm_pwd, nt_pwd,
 				lm_interactive_pwd, nt_interactive_pwd,
 				plaintext, password_state);
 	if (NT_STATUS_IS_OK(result)) {
@@ -175,6 +176,7 @@ bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
 				     const char *client_domain, 
 				     const char *workstation_name,
 				     const struct tsocket_address *remote_address,
+				     const struct tsocket_address *local_address,
 				     uint32_t logon_parameters,
 				     const uchar *lm_network_pwd,
 				     int lm_pwd_len,
@@ -190,6 +192,7 @@ bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
 				    smb_name, client_domain, 
 				    workstation_name,
 				    remote_address,
+				    local_address,
 				    "SamLogon",
 				    lm_pwd_len ? &lm_blob : NULL, 
 				    nt_pwd_len ? &nt_blob : NULL,
@@ -217,6 +220,7 @@ bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
 					 const char *client_domain, 
 					 const char *workstation_name,
 					 const struct tsocket_address *remote_address,
+					 const struct tsocket_address *local_address,
 					 uint32_t logon_parameters,
 					 const uchar chal[8], 
 					 const uchar lm_interactive_pwd[16], 
@@ -262,6 +266,7 @@ bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
 			user_info, 
 			smb_name, client_domain, workstation_name,
 			remote_address,
+			local_address,
 			"SamLogon",
 			lm_interactive_pwd ? &local_lm_blob : NULL,
 			nt_interactive_pwd ? &local_nt_blob : NULL,
@@ -290,6 +295,7 @@ bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
 			      const char *smb_name, 
 			      const char *client_domain,
 			      const struct tsocket_address *remote_address,
+			      const struct tsocket_address *local_address,
 			      const char *service_description,
 			      const uint8_t chal[8],
 			      DATA_BLOB plaintext_password)
@@ -338,6 +344,7 @@ bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
 		user_info, smb_name, smb_name, client_domain, client_domain, 
 		get_remote_machine_name(),
 		remote_address,
+		local_address,
 	        service_description,
 		local_lm_blob.data ? &local_lm_blob : NULL,
 		local_nt_blob.data ? &local_nt_blob : NULL,
@@ -363,6 +370,7 @@ NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
                                       const char *smb_name,
                                       const char *client_domain,
 				      const struct tsocket_address *remote_address,
+				      const struct tsocket_address *local_address,
 				      const char *service_description,
 				      DATA_BLOB lm_resp, DATA_BLOB nt_resp)
 {
@@ -382,9 +390,10 @@ NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
 
 	return make_user_info(mem_ctx,
 			      user_info, smb_name, smb_name,
-			      client_domain, client_domain, 
+			      client_domain, client_domain,
 			      get_remote_machine_name(),
 			      remote_address,
+			      local_address,
 			      service_description,
 			      lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
 			      nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
@@ -398,6 +407,7 @@ NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
 
 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
 			  const struct tsocket_address *remote_address,
+			  const struct tsocket_address *local_address,
 			  const char *service_description,
 			  struct auth_usersupplied_info **user_info)
 {
@@ -409,6 +419,7 @@ bool make_user_info_guest(TALLOC_CTX *mem_ctx,
 				   "","", 
 				   "", 
 				   remote_address,
+				   local_address,
 				   service_description,
 				   NULL, NULL, 
 				   NULL, NULL, 
diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index b3981d3..97506b6 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -156,6 +156,7 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
 			    const char *client_domain,
 			    const char *workstation_name,
 			    const struct tsocket_address *remote_address,
+			    const struct tsocket_address *local_address,
 			    const char *service_description,
 			    const DATA_BLOB *lm_pwd,
 			    const DATA_BLOB *nt_pwd,
@@ -169,6 +170,7 @@ bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
 				     const char *client_domain,
 				     const char *workstation_name,
 				     const struct tsocket_address *remote_address,
+				     const struct tsocket_address *local_address,
 				     uint32_t logon_parameters,
 				     const uchar *lm_network_pwd,
 				     int lm_pwd_len,
@@ -180,6 +182,7 @@ bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
 					 const char *client_domain,
 					 const char *workstation_name,
 					 const struct tsocket_address *remote_address,
+					 const struct tsocket_address *local_address,
 					 uint32_t logon_parameters,
 					 const uchar chal[8],
 					 const uchar lm_interactive_pwd[16],
@@ -189,6 +192,7 @@ bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
 			      const char *smb_name,
 			      const char *client_domain,
 			      const struct tsocket_address *remote_address,
+			      const struct tsocket_address *local_address,
 			      const char *service_description,
 			      const uint8_t chal[8],
 			      DATA_BLOB plaintext_password);
@@ -197,10 +201,12 @@ NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
                                       const char *smb_name,
                                       const char *client_domain,
 				      const struct tsocket_address *remote_address,
+				      const struct tsocket_address *local_address,
 				      const char *service_description,
                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp);
 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
 			  const struct tsocket_address *remote_address,
+			  const struct tsocket_address *local_address,
 			  const char *service_description,
 			  struct auth_usersupplied_info **user_info);
 
@@ -270,6 +276,7 @@ NTSTATUS make_user_info(TALLOC_CTX *mem_ctx,
 			const char *domain,
 			const char *workstation_name,
 			const struct tsocket_address *remote_address,
+			const struct tsocket_address *local_address,
 			const char *service_description,
 			const DATA_BLOB *lm_pwd,
 			const DATA_BLOB *nt_pwd,
diff --git a/source3/auth/user_info.c b/source3/auth/user_info.c
index c410d22..6165d59 100644
--- a/source3/auth/user_info.c
+++ b/source3/auth/user_info.c
@@ -49,6 +49,7 @@ NTSTATUS make_user_info(TALLOC_CTX *mem_ctx,
 			const char *domain,
 			const char *workstation_name,
 			const struct tsocket_address *remote_address,
+			const struct tsocket_address *local_address,
 			const char *service_description,
 			const DATA_BLOB *lm_pwd,
 			const DATA_BLOB *nt_pwd,
@@ -106,6 +107,13 @@ NTSTATUS make_user_info(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_NO_MEMORY;
 	}
 
+	user_info->local_host = tsocket_address_copy(local_address,
+						     user_info);
+	if (user_info->local_host == NULL) {
+		TALLOC_FREE(user_info);
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	user_info->service_description = talloc_strdup(user_info, service_description);
 	if (user_info->service_description == NULL) {
 		TALLOC_FREE(user_info);
diff --git a/source3/librpc/rpc/dcerpc_ep.c b/source3/librpc/rpc/dcerpc_ep.c
index 0502557..da26fab 100644
--- a/source3/librpc/rpc/dcerpc_ep.c
+++ b/source3/librpc/rpc/dcerpc_ep.c
@@ -382,6 +382,7 @@ static NTSTATUS ep_register(TALLOC_CTX *mem_ctx,
 		status = rpcint_binding_handle(tmp_ctx,
 					       &ndr_table_epmapper,
 					       local,
+					       NULL,
 					       get_session_info_system(),
 					       msg_ctx,
 					       &h);
diff --git a/source3/printing/nt_printing_migrate_internal.c b/source3/printing/nt_printing_migrate_internal.c
index 34133b2..dd78e69 100644
--- a/source3/printing/nt_printing_migrate_internal.c
+++ b/source3/printing/nt_printing_migrate_internal.c
@@ -227,6 +227,7 @@ bool nt_printing_tdb_migrate(struct messaging_context *msg_ctx)
 					&ndr_table_winreg,
 					session_info,
 					NULL,
+					NULL,
 					msg_ctx,
 					&winreg_pipe);
 	if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/printing/printspoolss.c b/source3/printing/printspoolss.c
index e92f461..6000202 100644
--- a/source3/printing/printspoolss.c
+++ b/source3/printing/printspoolss.c
@@ -154,6 +154,7 @@ NTSTATUS print_spool_open(files_struct *fsp,
 					 &ndr_table_spoolss,
 					 fsp->conn->session_info,
 					 fsp->conn->sconn->remote_address,
+					 fsp->conn->sconn->local_address,
 					 fsp->conn->sconn->msg_ctx,
 					 &fsp->conn->spoolss_pipe);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -343,6 +344,7 @@ void print_spool_terminate(struct connection_struct *conn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &conn->spoolss_pipe);
 	if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/rpc_client/cli_winreg_int.c b/source3/rpc_client/cli_winreg_int.c
index ac04460..3ac8380 100644
--- a/source3/rpc_client/cli_winreg_int.c
+++ b/source3/rpc_client/cli_winreg_int.c
@@ -115,6 +115,7 @@ static NTSTATUS _winreg_int_openkey(TALLOC_CTX *mem_ctx,
 	status = rpcint_binding_handle(mem_ctx,
 				       &ndr_table_winreg,
 				       local,
+				       NULL,
 				       session_info,
 				       msg_ctx,
 				       &binding_handle);
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index ef2c827..424ff71 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -423,6 +423,7 @@ NTSTATUS _netr_NetrEnumerateTrustedDomains(struct pipes_struct *p,
 	status = rpcint_binding_handle(p->mem_ctx,
 				       &ndr_table_lsarpc,
 				       p->remote_address,
+				       p->local_address,
 				       p->session_info,
 				       p->msg_ctx,
 				       &h);
@@ -703,6 +704,7 @@ static NTSTATUS get_md4pw(struct samr_Password *md4pw, const char *mach_acct,
 	status = rpcint_binding_handle(mem_ctx,
 				       &ndr_table_samr,
 				       local,
+				       NULL,
 				       session_info,
 				       msg_ctx,
 				       &h);
@@ -1181,6 +1183,7 @@ static NTSTATUS netr_set_machine_account_password(TALLOC_CTX *mem_ctx,
 	status = rpcint_binding_handle(mem_ctx,
 				       &ndr_table_samr,
 				       local,
+				       NULL,
 				       session_info,
 				       msg_ctx,
 				       &h);
@@ -1605,6 +1608,7 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 						     nt_username, nt_domain,
 						     wksname,
 						     p->remote_address,
+						     p->local_address,
 						     logon->network->identity_info.parameter_control,
 						     logon->network->lm.data,
 						     logon->network->lm.length,
@@ -1664,6 +1668,7 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 							 nt_username, nt_domain,
 							 nt_workstation,
 							 p->remote_address,
+							 p->local_address,
 							 logon->password->identity_info.parameter_control,
 							 chal,
 							 logon->password->lmpassword.hash,
diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c
index cb3b8e6..121e776 100644
--- a/source3/rpc_server/rpc_ncacn_np.c
+++ b/source3/rpc_server/rpc_ncacn_np.c
@@ -183,6 +183,7 @@ out:
 struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
 					      const struct ndr_syntax_id *syntax,
 					      const struct tsocket_address *remote_address,
+					      const struct tsocket_address *local_address,
 					      const struct auth_session_info *session_info,
 					      struct messaging_context *msg_ctx)
 {
@@ -204,7 +205,7 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
 
 	ret = make_base_pipes_struct(mem_ctx, msg_ctx, pipe_name,
 				     NCALRPC, RPC_LITTLE_ENDIAN,
-				     remote_address, NULL, &p);
+				     remote_address, local_address, &p);
 	if (ret) {
 		DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
 		return NULL;
@@ -492,6 +493,7 @@ static NTSTATUS rpcint_binding_handle_ex(TALLOC_CTX *mem_ctx,
 			const struct ndr_syntax_id *abstract_syntax,
 			const struct ndr_interface_table *ndr_table,
 			const struct tsocket_address *remote_address,
+			const struct tsocket_address *local_address,
 			const struct auth_session_info *session_info,
 			struct messaging_context *msg_ctx,
 			struct dcerpc_binding_handle **binding_handle)
@@ -516,6 +518,7 @@ static NTSTATUS rpcint_binding_handle_ex(TALLOC_CTX *mem_ctx,
 	hs->p = make_internal_rpc_pipe_p(hs,
 					 abstract_syntax,
 					 remote_address,
+					 local_address,
 					 session_info,
 					 msg_ctx);
 	if (hs->p == NULL) {
@@ -560,12 +563,14 @@ static NTSTATUS rpcint_binding_handle_ex(TALLOC_CTX *mem_ctx,
 NTSTATUS rpcint_binding_handle(TALLOC_CTX *mem_ctx,
 			       const struct ndr_interface_table *ndr_table,
 			       const struct tsocket_address *remote_address,
+			       const struct tsocket_address *local_address,
 			       const struct auth_session_info *session_info,
 			       struct messaging_context *msg_ctx,
 			       struct dcerpc_binding_handle **binding_handle)
 {
 	return rpcint_binding_handle_ex(mem_ctx, NULL, ndr_table, remote_address,
-					session_info, msg_ctx, binding_handle);
+					local_address, session_info,
+					msg_ctx, binding_handle);
 }
 
 /**
@@ -596,6 +601,7 @@ NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
 				const struct ndr_interface_table *ndr_table,
 				const struct auth_session_info *session_info,
 				const struct tsocket_address *remote_address,
+				const struct tsocket_address *local_address,
 				struct messaging_context *msg_ctx,
 				struct rpc_pipe_client **presult)
 {
@@ -632,6 +638,7 @@ NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
 	status = rpcint_binding_handle(result,
 				       ndr_table,
 				       remote_address,
+				       local_address,
 				       session_info,
 				       msg_ctx,
 				       &result->binding_handle);
@@ -1033,6 +1040,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx,
 				 const struct ndr_interface_table *table,
 				 const struct auth_session_info *session_info,
 				 const struct tsocket_address *remote_address,
+				 const struct tsocket_address *local_address,
 				 struct messaging_context *msg_ctx,
 				 struct rpc_pipe_client **cli_pipe)
 {
@@ -1074,7 +1082,8 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx,
 	case RPC_SERVICE_MODE_EMBEDDED:
 		status = rpc_pipe_open_internal(tmp_ctx,
 						table, session_info,
-						remote_address, msg_ctx,
+						remote_address, local_address,
+						msg_ctx,
 						&cli);
 		if (!NT_STATUS_IS_OK(status)) {
 			goto done;
diff --git a/source3/rpc_server/rpc_ncacn_np.h b/source3/rpc_server/rpc_ncacn_np.h
index 59b9d5a..2ae126d 100644
--- a/source3/rpc_server/rpc_ncacn_np.h
+++ b/source3/rpc_server/rpc_ncacn_np.h
@@ -65,6 +65,7 @@ struct np_proxy_state {
 struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
 					      const struct ndr_syntax_id *syntax,
 					      const struct tsocket_address *remote_address,
+					      const struct tsocket_address *local_address,
 					      const struct auth_session_info *session_info,
 					      struct messaging_context *msg_ctx);
 struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
@@ -75,6 +76,7 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
 NTSTATUS rpcint_binding_handle(TALLOC_CTX *mem_ctx,
 			       const struct ndr_interface_table *ndr_table,
 			       const struct tsocket_address *remote_address,
+			       const struct tsocket_address *local_address,
 			       const struct auth_session_info *session_info,
 			       struct messaging_context *msg_ctx,
 			       struct dcerpc_binding_handle **binding_handle);
@@ -82,6 +84,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx,
 				 const struct ndr_interface_table *table,
 				 const struct auth_session_info *session_info,
 				 const struct tsocket_address *remote_address,
+				 const struct tsocket_address *local_address,
 				 struct messaging_context *msg_ctx,
 				 struct rpc_pipe_client **cli_pipe);
 
@@ -89,6 +92,7 @@ NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
 				const struct ndr_interface_table *ndr_table,
 				const struct auth_session_info *session_info,
 				const struct tsocket_address *remote_address,
+				const struct tsocket_address *local_address,
 				struct messaging_context *msg_ctx,
 				struct rpc_pipe_client **presult);
 
diff --git a/source3/rpc_server/rpc_server.c b/source3/rpc_server/rpc_server.c
index 6c988ce..40f2f06 100644
--- a/source3/rpc_server/rpc_server.c
+++ b/source3/rpc_server/rpc_server.c
@@ -872,14 +872,18 @@ static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
 	struct dcerpc_ncacn_listen_state *state =
 			talloc_get_type_abort(private_data,
 					      struct dcerpc_ncacn_listen_state);
-	struct tsocket_address *cli_addr = NULL;
+	struct tsocket_address *cli_addr = NULL, *srv_addr = NULL;
 	struct sockaddr_un sunaddr;
 	struct sockaddr *addr = (struct sockaddr *)(void *)&sunaddr;
 	socklen_t len = sizeof(sunaddr);
+	struct sockaddr_un sunaddr_server;
+	struct sockaddr *addr_server = (struct sockaddr *)(void *)&sunaddr_server;
+	socklen_t len_server = sizeof(sunaddr_server);
 	int sd = -1;
 	int rc;
 
 	ZERO_STRUCT(sunaddr);
+	ZERO_STRUCT(sunaddr_server);
 
 	sd = accept(state->fd, addr, &len);
 	if (sd == -1) {
@@ -897,13 +901,29 @@ static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
 		return;
 	}
 
-	DEBUG(10, ("Accepted ncalrpc socket %d\n", sd));
+	rc = getsockname(sd, addr_server, &len_server);
+	if (rc < 0) {
+		close(sd);
+		return;
+	}
+
+	rc = tsocket_address_bsd_from_sockaddr(state,
+					       addr_server,
+					       len_server,
+					       &srv_addr);
+	if (rc < 0) {
+		close(sd);
+		return;
+	}
+
+	DEBUG(10, ("Accepted ncalrpc socket %s (fd: %d)\n",
+		   sunaddr.sun_path, sd));
 
 	dcerpc_ncacn_accept(state->ev_ctx,
 			    state->msg_ctx,
 			    NCALRPC,
 			    state->ep.name,
-			    cli_addr, NULL, sd,
+			    cli_addr, srv_addr, sd,
 			    state->disconnect_fn);
 }
 
@@ -977,7 +997,7 @@ void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
 						  ncacn_conn);
 	}
 	if (ncacn_conn->client_name == NULL) {
-		DEBUG(0, ("Out of memory!\n"));
+		DEBUG(0, ("Out of memory obtaining remote socket address as a string!\n"));
 		talloc_free(ncacn_conn);
 		close(s);
 		return;
@@ -985,12 +1005,18 @@ void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
 
 	if (srv_addr != NULL) {
 		ncacn_conn->server = talloc_move(ncacn_conn, &srv_addr);
-
-		ncacn_conn->server_name =
-			tsocket_address_inet_addr_string(ncacn_conn->server,
-							 ncacn_conn);
+		
+		if (tsocket_address_is_inet(ncacn_conn->server, "ip")) {
+			ncacn_conn->server_name =
+				tsocket_address_inet_addr_string(ncacn_conn->server,
+								 ncacn_conn);
+		} else {
+			ncacn_conn->server_name =
+				tsocket_address_unix_path(ncacn_conn->server,
+							  ncacn_conn);
+		}
 		if (ncacn_conn->server_name == NULL) {
-			DEBUG(0, ("Out of memory!\n"));
+			DEBUG(0, ("Out of memory obtaining local socket address as a string!\n"));
 			talloc_free(ncacn_conn);
 			close(s);
 			return;
@@ -1021,7 +1047,7 @@ void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
 									    "/root/ncalrpc_as_system",
 									    &ncacn_conn->client);
 					if (rc < 0) {
-						DEBUG(0, ("Out of memory!\n"));
+						DEBUG(0, ("Out of memory building magic ncalrpc_as_system path!\n"));
 						talloc_free(ncacn_conn);
 						close(s);
 						return;
@@ -1031,7 +1057,7 @@ void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
 					ncacn_conn->client_name = tsocket_address_unix_path(ncacn_conn->client,
 											    ncacn_conn);
 					if (ncacn_conn->client == NULL) {
-						DEBUG(0, ("Out of memory!\n"));
+						DEBUG(0, ("Out of memory getting magic ncalrpc_as_system string!\n"));
 						talloc_free(ncacn_conn);
 						close(s);
 						return;
@@ -1110,7 +1136,7 @@ void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
 	ncacn_conn->send_queue = tevent_queue_create(ncacn_conn,
 							"dcerpc send queue");
 	if (ncacn_conn->send_queue == NULL) {
-		DEBUG(0, ("Out of memory!\n"));
+		DEBUG(0, ("Out of memory building dcerpc send queue!\n"));
 		talloc_free(ncacn_conn);
 		return;
 	}
diff --git a/source3/rpc_server/spoolss/srv_spoolss_util.c b/source3/rpc_server/spoolss/srv_spoolss_util.c
index 32f0e27..17acf51 100644
--- a/source3/rpc_server/spoolss/srv_spoolss_util.c
+++ b/source3/rpc_server/spoolss/srv_spoolss_util.c
@@ -48,6 +48,7 @@ WERROR winreg_printer_binding_handle(TALLOC_CTX *mem_ctx,
 	status = rpcint_binding_handle(mem_ctx,
 				       &ndr_table_winreg,
 				       local,
+				       NULL,
 				       session_info,
 				       msg_ctx,
 				       winreg_binding_handle);
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index 995ed08..c3e540f 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -835,6 +835,7 @@ static bool api_DosPrintQGetInfo(struct smbd_server_connection *sconn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -1032,6 +1033,7 @@ static bool api_DosPrintQEnum(struct smbd_server_connection *sconn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -2266,6 +2268,7 @@ static bool api_RNetShareAdd(struct smbd_server_connection *sconn,
 	status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc,
 					conn->session_info,
 					conn->sconn->remote_address,
+					conn->sconn->local_address,
 					conn->sconn->msg_ctx,
 					&cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -2377,7 +2380,7 @@ static bool api_RNetGroupEnum(struct smbd_server_connection *sconn,
 	status = rpc_pipe_open_interface(
 		talloc_tos(), &ndr_table_samr,
 		conn->session_info, conn->sconn->remote_address,
-		conn->sconn->msg_ctx, &samr_pipe);
+		conn->sconn->local_address, conn->sconn->msg_ctx, &samr_pipe);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
 			  nt_errstr(status)));
@@ -2583,7 +2586,7 @@ static bool api_NetUserGetGroups(struct smbd_server_connection *sconn,
 	status = rpc_pipe_open_interface(
 		talloc_tos(), &ndr_table_samr,
 		conn->session_info, conn->sconn->remote_address,
-		conn->sconn->msg_ctx, &samr_pipe);
+		conn->sconn->local_address, conn->sconn->msg_ctx, &samr_pipe);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
 			  nt_errstr(status)));
@@ -2783,7 +2786,7 @@ static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
 	status = rpc_pipe_open_interface(
 		talloc_tos(), &ndr_table_samr,
 		conn->session_info, conn->sconn->remote_address,
-		conn->sconn->msg_ctx, &samr_pipe);
+		conn->sconn->local_address, conn->sconn->msg_ctx, &samr_pipe);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
 			  nt_errstr(status)));
@@ -3047,6 +3050,7 @@ static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
 	status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr,
 					conn->session_info,
 					conn->sconn->remote_address,
+					conn->sconn->local_address,
 					conn->sconn->msg_ctx,
 					&cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -3144,6 +3148,7 @@ static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -3272,6 +3277,7 @@ static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -3454,6 +3460,7 @@ static bool api_PrintJobInfo(struct smbd_server_connection *sconn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -3631,6 +3638,7 @@ static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
 	status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc,
 					conn->session_info,
 					conn->sconn->remote_address,
+					conn->sconn->local_address,
 					conn->sconn->msg_ctx,
 					&cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -4067,6 +4075,7 @@ static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
 	status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr,
 					conn->session_info,
 					conn->sconn->remote_address,
+					conn->sconn->local_address,
 					conn->sconn->msg_ctx,
 					&cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -4596,6 +4605,7 @@ static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -4738,6 +4748,7 @@ static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -4938,6 +4949,7 @@ static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -5070,6 +5082,7 @@ static bool api_WPrintDestEnum(struct smbd_server_connection *sconn,
 					 &ndr_table_spoolss,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -5381,6 +5394,7 @@ static bool api_RNetSessionEnum(struct smbd_server_connection *sconn,
 					 &ndr_table_srvsvc,
 					 conn->session_info,
 					 conn->sconn->remote_address,
+					 conn->sconn->local_address,
 					 conn->sconn->msg_ctx,
 					 &cli);
 	if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 22941ec..f8cd39d 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -5954,6 +5954,7 @@ void reply_printqueue(struct smb_request *req)
 						 &ndr_table_spoolss,
 						 conn->session_info,
 						 conn->sconn->remote_address,
+						 conn->sconn->local_address,
 						 conn->sconn->msg_ctx,
 						 &cli);
 		if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 26ce9f0..fe82ebb 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -79,6 +79,7 @@ static int push_signature(uint8_t **outbuf)
 ****************************************************************************/
 
 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
+				     const struct tsocket_address *local_address,
 				     TALLOC_CTX *mem_ctx, 
 				     struct auth_session_info **session_info)
 {
@@ -97,8 +98,8 @@ static NTSTATUS check_guest_password(const struct tsocket_address *remote_addres
 	auth_context->get_ntlm_challenge(auth_context,
 					 chal);
 
-	if (!make_user_info_guest(talloc_tos(), remote_address, "smb",
-				  &user_info)) {
+	if (!make_user_info_guest(talloc_tos(), remote_address, local_address,
+				  "smb", &user_info)) {
 		TALLOC_FREE(auth_context);
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -884,7 +885,9 @@ void reply_sesssetup_and_X(struct smb_request *req)
 
 	if (!*user) {
 
-		nt_status = check_guest_password(sconn->remote_address, req, &session_info);
+		nt_status = check_guest_password(sconn->remote_address,
+						 sconn->local_address,
+						 req, &session_info);
 
 	} else if (doencrypt) {
 		struct auth4_context *negprot_auth_context = NULL;
@@ -901,6 +904,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
 							 &user_info, user,
 							 domain,
 							 sconn->remote_address,
+							 sconn->local_address,
 							 "smb",
 							 lm_resp, nt_resp);
 		user_info->auth_description = "bare-NTLM";
@@ -925,6 +929,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
 						      &user_info,
 						      user, domain,
 						      sconn->remote_address,
+						      sconn->local_address,
 						      "smb",
 						      chal,
 						      plaintext_password)) {
diff --git a/source3/torture/pdbtest.c b/source3/torture/pdbtest.c
index d2b30ed..c6b662d 100644
--- a/source3/torture/pdbtest.c
+++ b/source3/torture/pdbtest.c
@@ -261,7 +261,8 @@ static bool test_auth(TALLOC_CTX *mem_ctx, struct samu *pdb_entry)
 	struct auth_context *auth_context;
 	static const uint8_t challenge_8[8] = {1, 2, 3, 4, 5, 6, 7, 8};
 	DATA_BLOB challenge = data_blob_const(challenge_8, sizeof(challenge_8));
-	struct tsocket_address *tsocket_address;
+	struct tsocket_address *remote_address;
+	struct tsocket_address *local_address;
 	unsigned char local_nt_response[24];
 	DATA_BLOB nt_resp = data_blob_const(local_nt_response, sizeof(local_nt_response));
 	unsigned char local_nt_session_key[16];
@@ -273,14 +274,18 @@ static bool test_auth(TALLOC_CTX *mem_ctx, struct samu *pdb_entry)
 		      local_nt_response);
 	SMBsesskeygen_ntv1(pdb_get_nt_passwd(pdb_entry), local_nt_session_key);
 
-	if (tsocket_address_inet_from_strings(NULL, "ip", NULL, 0, &tsocket_address) != 0) {
+	if (tsocket_address_inet_from_strings(NULL, "ip", NULL, 0, &remote_address) != 0) {
 		return False;
 	}
-	
+
+	if (tsocket_address_inet_from_strings(NULL, "ip", NULL, 0, &local_address) != 0) {
+		return False;
+	}
+
 	status = make_user_info(mem_ctx,
 				&user_info, pdb_get_username(pdb_entry), pdb_get_username(pdb_entry),
 				pdb_get_domain(pdb_entry), pdb_get_domain(pdb_entry), lp_netbios_name(), 
-				tsocket_address, "pdbtest",
+				remote_address,local_address, "pdbtest",
 				NULL, &nt_resp, NULL, NULL, NULL, 
 				AUTH_PASSWORD_RESPONSE);
 	if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index c9890ac..39361e2 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -1778,6 +1778,7 @@ NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
 						 table,
 						 session_info,
 						 NULL,
+						 NULL,
 						 winbind_messaging_context(),
 						 &cli);
 	} else {
@@ -1785,6 +1786,7 @@ NTSTATUS wb_open_internal_pipe(TALLOC_CTX *mem_ctx,
 						table,
 						session_info,
 						NULL,
+						NULL,
 						winbind_messaging_context(),
 						&cli);
 	}
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index bc2a9f1..0218fed 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1254,7 +1254,7 @@ static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
 	 * here. 
 	 */
 	status = make_user_info(frame, &user_info, user, user, domain, domain,
-				lp_netbios_name(), local,
+				lp_netbios_name(), local, local,
 				"winbind",
 				lm_resp, nt_resp, NULL, NULL,
 				NULL, AUTH_PASSWORD_RESPONSE);
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 987fcf9..7d01aff 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -148,6 +148,16 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 		}
 	}
 
+	if (call->conn->local_address != NULL) {
+		status = gensec_set_local_address(auth->gensec_security,
+						  call->conn->local_address);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(1, ("Failed to call gensec_set_local_address() %s\n",
+				  nt_errstr(status)));
+			return false;
+		}
+	}
+
 	status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_type,
 					       auth->auth_level);
 	if (!NT_STATUS_IS_OK(status)) {
-- 
2.7.4

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


More information about the samba-technical mailing list