[PATCH] Updated Add detailed authentication logging for NTLM authentication.

Gary Lockyer gary at catalyst.net.nz
Thu Mar 2 03:48:54 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.

Updated to:
	log successful authorizations
	log password type for authentications
        replace talloc_steal with talloc_move in
            source4/smbd/service_named_pipe.c
	separate the auth logging into it's own file


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






-------------- next part --------------
From 81f30b2cf742307b8449711fde1dfffa08dd7c7c 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/28] 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 24842921d728a8b9f25f76e32d85a21b4d90c014 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/28] 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..02758b9 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_move(conn, &server);
+	conn->remote_address = talloc_move(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 aa382864b5ef4ba7a251069a4979b26bd315619a 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/28] 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 d03e653aece697195a5c350648259723ec9b4087 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/28] 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 5f5f903be0b5019ccc7a72b19689edabeb0b680c 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/28] 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 9ff3fcf103d077613d8fe32c33025fd889eb3466 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/28] 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 6a6d63e05d619fe663993a2d06744319418cd4d2 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/28] 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 be9869da6d64ba4910533e317e92fc96a9c220c0 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/28] 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 e2b8c6006b3c79088064775aa211ecc0cc83714d 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/28] 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 0f8fe6f13b06dd8e64a7b3b347bd2808e25b6cbf 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/28] 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 08abfb606522822677a16393a88d36f9726cc908 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/28] 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 a1276df..756f56f 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -431,6 +431,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 a1825225139d9dae10a109e48c10261043f27b9c 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/28] 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 4d1c396119febe303d6e005641929d8cfecbb715 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/28] 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 96fc72f1648fc6de88cdecefaafd8de2c610a4fb 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/28] 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 2a5f2a2b677b2c6b2a3879df9d56ac018d36facc 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/28] 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 76ca5b8a4ef217f0d38322eacc11bccf225ecf8a Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary at catalyst.net.nz>
Date: Wed, 1 Mar 2017 11:10:29 +1300
Subject: [PATCH 16/28] lib/util: Add functions to escape log lines but not
 break all non-ascii

We do not want to turn every non-ascii username into a pile of hex, so we instead focus
on avoding newline insertion attacks and other low control chars

Pair-programmed-by: Andrew Bartlett <abartlet at samba.org>
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 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/torture/local/local.c       |   1 +
 source4/torture/local/wscript_build |   3 +-
 6 files changed, 251 insertions(+), 1 deletion(-)
 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/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..c8e8fde 100644
--- a/source4/torture/local/wscript_build
+++ b/source4/torture/local/wscript_build
@@ -20,11 +20,12 @@ 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'''
 
-TORTURE_LOCAL_DEPS = 'RPC_NDR_ECHO TDR LIBCLI_SMB MESSAGING iconv POPT_CREDENTIALS TORTURE_AUTH TORTURE_UTIL TORTURE_NDR TORTURE_LIBCRYPTO share torture_registry PROVISION ldb samdb replace-test RPC_FSS_STATE'
+TORTURE_LOCAL_DEPS = 'RPC_NDR_ECHO TDR LIBCLI_SMB MESSAGING iconv POPT_CREDENTIALS TORTURE_AUTH TORTURE_UTIL TORTURE_NDR TORTURE_LIBCRYPTO share torture_registry PROVISION ldb samdb replace-test RPC_FSS_STATE util_str_escape'
 
 bld.SAMBA_MODULE('TORTURE_LOCAL',
 	source=TORTURE_LOCAL_SOURCE,
-- 
2.7.4


From d00bc8442cb6c0f36ccbff3901868dd5b673843e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 1 Mar 2017 11:22:43 +1300
Subject: [PATCH 17/28] s3-auth: Split out get_user_sid_info3_and_extra() from
 create_local_nt_token_from_info3()

This will allow us to get the SID in another location for logging

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source3/auth/proto.h      |  3 +++
 source3/auth/token_util.c | 43 +++++++++++++++++++++++++++----------------
 2 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index 69fa20c..eb9756c 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -351,6 +351,9 @@ struct security_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
 					    bool is_guest,
 					    int num_groupsids,
 					    const struct dom_sid *groupsids);
+NTSTATUS get_user_sid_info3_and_extra(const struct netr_SamInfo3 *info3,
+				      const struct extra_auth_info *extra,
+				      struct dom_sid *sid);
 NTSTATUS create_local_nt_token_from_info3(TALLOC_CTX *mem_ctx,
 					  bool is_guest,
 					  const struct netr_SamInfo3 *info3,
diff --git a/source3/auth/token_util.c b/source3/auth/token_util.c
index 77b63e4..4a7c1cd 100644
--- a/source3/auth/token_util.c
+++ b/source3/auth/token_util.c
@@ -211,6 +211,28 @@ static NTSTATUS add_builtin_administrators(struct security_token *token,
 static NTSTATUS finalize_local_nt_token(struct security_token *result,
 					bool is_guest);
 
+NTSTATUS get_user_sid_info3_and_extra(const struct netr_SamInfo3 *info3,
+				      const struct extra_auth_info *extra,
+				      struct dom_sid *sid)
+{
+	/* USER SID */
+	if (info3->base.rid == (uint32_t)(-1)) {
+		/* this is a signal the user was fake and generated,
+		 * the actual SID we want to use is stored in the extra
+		 * sids */
+		if (is_null_sid(&extra->user_sid)) {
+			/* we couldn't find the user sid, bail out */
+			DEBUG(3, ("Invalid user SID\n"));
+			return NT_STATUS_UNSUCCESSFUL;
+		}
+		sid_copy(sid, &extra->user_sid);
+	} else {
+		sid_copy(sid, info3->base.domain_sid);
+		sid_append_rid(sid, info3->base.rid);
+	}
+	return NT_STATUS_OK;
+}
+
 NTSTATUS create_local_nt_token_from_info3(TALLOC_CTX *mem_ctx,
 					  bool is_guest,
 					  const struct netr_SamInfo3 *info3,
@@ -241,23 +263,12 @@ NTSTATUS create_local_nt_token_from_info3(TALLOC_CTX *mem_ctx,
 	}
 	usrtok->num_sids = 2;
 
-	/* USER SID */
-	if (info3->base.rid == (uint32_t)(-1)) {
-		/* this is a signal the user was fake and generated,
-		 * the actual SID we want to use is stored in the extra
-		 * sids */
-		if (is_null_sid(&extra->user_sid)) {
-			/* we couldn't find the user sid, bail out */
-			DEBUG(3, ("Invalid user SID\n"));
-			TALLOC_FREE(usrtok);
-			return NT_STATUS_UNSUCCESSFUL;
-		}
-		sid_copy(&usrtok->sids[0], &extra->user_sid);
-	} else {
-		sid_copy(&usrtok->sids[0], info3->base.domain_sid);
-		sid_append_rid(&usrtok->sids[0], info3->base.rid);
+	status = get_user_sid_info3_and_extra(info3, extra, &usrtok->sids[0]);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(usrtok);
+		return status;
 	}
-
+	
 	/* GROUP SID */
 	if (info3->base.primary_gid == (uint32_t)(-1)) {
 		/* this is a signal the user was fake and generated,
-- 
2.7.4


From a02bc0f3cfd8082684bcf5cbe5e5a817926679a5 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 18/28] 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>
---
 auth/auth_log.c                     | 119 ++++++++++++++++++++++++++++++++++++
 auth/common_auth.h                  |   6 ++
 auth/wscript_build                  |   6 +-
 source3/auth/auth.c                 |  17 ++++++
 source3/rpc_server/wscript_build    |   2 +-
 source4/auth/kerberos/wscript_build |   2 +-
 source4/auth/ntlm/auth.c            |  15 ++++-
 source4/kdc/wscript_build           |  10 +--
 8 files changed, 165 insertions(+), 12 deletions(-)
 create mode 100644 auth/auth_log.c

diff --git a/auth/auth_log.c b/auth/auth_log.c
new file mode 100644
index 0000000..e447561
--- /dev/null
+++ b/auth/auth_log.c
@@ -0,0 +1,119 @@
+/*
+
+   Authentication and authorization logging
+
+   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/>.
+*/
+
+/* 
+ * Debug log levels for authentication logging (these both map to
+ * LOG_NOTICE in syslog) 
+ */
+#define AUTH_SUCCESS_LEVEL 4
+#define AUTHZ_SUCCESS_LEVEL 5
+#define AUTH_FAILURE_LEVEL 2
+
+#include "includes.h"
+#include "../lib/tsocket/tsocket.h"
+#include "common_auth.h"
+#include "lib/util/util_str_escape.h"
+#include "libcli/security/dom_sid.h"
+
+/*
+ * Log details of an authentication attempt.
+ * Successful and unsuccessful attempts are logged.
+ *
+ */
+void log_authentication_event(const struct auth_usersupplied_info *ui,
+			      NTSTATUS status,
+			      const char *domain_name,
+			      const char *account_name,
+			      const char *unix_username,
+			      struct dom_sid *sid)
+{
+	TALLOC_CTX *frame = NULL;
+
+	char *ts = NULL;         /* formatted current time      */
+	char *remote = NULL;     /* formatted remote host       */
+	char *local = NULL;      /* formatted local host        */
+	char *nl = NULL;         /* NETLOGON details if present */
+	char *trust_computer_name = NULL;
+	char *trust_account_name = NULL;
+	char *logon_line = NULL;
+	
+	/* set the log level */
+	int  level = NT_STATUS_IS_OK(status) ? AUTH_FAILURE_LEVEL : AUTH_SUCCESS_LEVEL;
+	if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, level)) {
+		return;
+	}
+
+	frame = talloc_stackframe();
+
+	/* Get the current time */
+        ts = http_timestring(frame, time(NULL));
+
+	/* Only log the NETLOGON details if they are present */
+	if (ui->netlogon_trust_account.computer_name ||
+	    ui->netlogon_trust_account.account_name) {
+		trust_computer_name = log_escape(frame,
+			ui->netlogon_trust_account.computer_name);
+		trust_account_name  = log_escape(frame,
+			ui->netlogon_trust_account.account_name);
+		nl = talloc_asprintf(frame,
+			" NETLOGON computer [%s] trust account [%s]",
+			trust_computer_name, trust_account_name);
+	}
+
+	remote = tsocket_address_string(ui->remote_host, frame);
+	local  = tsocket_address_string(ui->local_host, frame);
+
+	if (NT_STATUS_IS_OK(status)) {
+		char sid_buf[DOM_SID_STR_BUFLEN];
+
+		dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
+		logon_line = talloc_asprintf(frame,
+					     " became [%s]\\[%s] %s.",
+					     log_escape(frame, account_name),
+					     log_escape(frame, domain_name),
+					     sid_buf);
+	} else {
+		logon_line = talloc_asprintf(frame,
+					     " mapped to [%s]\\[%s].",
+					     log_escape(frame, ui->mapped.domain_name),
+					     log_escape(frame, ui->mapped.account_name));
+	}
+	
+	DEBUGC( DBGC_AUTH_AUDIT, level, (
+		"Auth: [%s,%s] user [%s]\\[%s]"
+		" at [%s] status [%s]"
+		" workstation [%s] remote host [%s]"
+		"%s local host [%s]"
+		" %s\n",
+		ui->service_description,
+		ui->auth_description,
+		log_escape(frame, ui->client.domain_name),
+		log_escape(frame, ui->client.account_name),
+		ts,
+		nt_errstr( status),
+		log_escape(frame, ui->workstation_name),
+		remote,
+		logon_line,
+		local,
+		nl ? nl : ""
+		));
+
+	talloc_free(frame);
+}
diff --git a/auth/common_auth.h b/auth/common_auth.h
index 869f138..9a83158 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -146,4 +146,10 @@ struct auth4_context {
 					      struct auth_session_info **session_info);
 };
 
+void log_authentication_event(const struct auth_usersupplied_info *ui,
+			      NTSTATUS status,
+			      const char *account_name,
+			      const char *domain_name,
+			      const char *unix_username,
+			      struct dom_sid *sid);
 #endif
diff --git a/auth/wscript_build b/auth/wscript_build
index 2026153..732536d 100644
--- a/auth/wscript_build
+++ b/auth/wscript_build
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 
-bld.SAMBA_LIBRARY('auth_sam_reply',
-                  source='auth_sam_reply.c wbc_auth_util.c',
-                  deps='talloc samba-security samba-util',
+bld.SAMBA_LIBRARY('common_auth',
+                  source='auth_sam_reply.c wbc_auth_util.c auth_log.c',
+                  deps='talloc samba-security samba-util util_str_escape LIBTSOCKET',
                   private_library=True
                   )
 
diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index c1e82a2..7ca1aae 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -264,6 +264,7 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 	/* successful authentication */
 
 	if (NT_STATUS_IS_OK(nt_status)) {
+		struct dom_sid sid = {0};
 		unix_username = (*pserver_info)->unix_name;
 
 		/* We skip doing this step if the caller asked us not to */
@@ -305,6 +306,19 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 			       unix_username));
 		}
 
+		nt_status = get_user_sid_info3_and_extra((*pserver_info)->info3,
+							 &(*pserver_info)->extra,
+							 &sid);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			static const struct dom_sid null_sid = {0};
+			sid = null_sid;
+		}
+		
+		log_authentication_event(user_info, nt_status,
+					 (*pserver_info)->info3->base.logon_domain.string,
+					 (*pserver_info)->info3->base.account_name.string,
+					 unix_username, &sid);
+
 		return nt_status;
 	}
 
@@ -317,6 +331,9 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 	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)));
+	
+	log_authentication_event(user_info, nt_status, NULL, NULL, NULL, NULL);
+	
 	ZERO_STRUCTP(pserver_info);
 
 	return nt_status;
diff --git a/source3/rpc_server/wscript_build b/source3/rpc_server/wscript_build
index 7fe4fda..ae75e56 100644
--- a/source3/rpc_server/wscript_build
+++ b/source3/rpc_server/wscript_build
@@ -11,7 +11,7 @@ bld.SAMBA3_SUBSYSTEM('RPC_CONFIG',
 
 bld.SAMBA3_SUBSYSTEM('RPC_NCACN_NP',
                     source='rpc_ncacn_np.c rpc_handles.c rpc_contexts.c',
-                    deps='RPC_CONFIG auth auth_sam_reply RPC_PIPE_REGISTER npa_tstream')
+                    deps='RPC_CONFIG auth common_auth RPC_PIPE_REGISTER npa_tstream')
 
 bld.SAMBA3_SUBSYSTEM('RPC_SERVER_LOOP',
                     source='rpc_server.c',
diff --git a/source4/auth/kerberos/wscript_build b/source4/auth/kerberos/wscript_build
index 0f886fa..30853ec 100644
--- a/source4/auth/kerberos/wscript_build
+++ b/source4/auth/kerberos/wscript_build
@@ -9,7 +9,7 @@ bld.SAMBA_LIBRARY('authkrb5',
                   source='kerberos_pac.c',
                   autoproto='proto.h',
                   public_deps='ndr-krb5pac krb5samba samba_socket LIBCLI_RESOLVE asn1',
-                  deps='auth_sam_reply tevent LIBPACKET ndr ldb krb5samba KRB_INIT_CTX KRB5_PAC samba-errors',
+                  deps='common_auth tevent LIBPACKET ndr ldb krb5samba KRB_INIT_CTX KRB5_PAC samba-errors',
                   private_library=True
                   )
 
diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index 756f56f..8b181f0 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -428,9 +428,11 @@ _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;
+
+	bool err = tevent_req_is_nterror(req, &status);
 
-	if (tevent_req_is_nterror(req, &status)) {
+	if (err) {
 		/*
 		 * Please try not to change this string, it is probably in use
 		 * in audit logging tools
@@ -442,6 +444,9 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
 			 state->user_info->mapped.domain_name,
 			 state->user_info->mapped.account_name,
 			 nt_errstr(status)));
+
+		log_authentication_event(state->user_info, status,
+					 NULL, NULL, NULL, NULL);
 		tevent_req_received(req);
 		return status;
 	}
@@ -452,6 +457,12 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
 		 state->user_info_dc->info->domain_name,
 		 state->user_info_dc->info->account_name));
 
+	log_authentication_event(state->user_info, status,
+				 state->user_info_dc->info->domain_name,
+				 state->user_info_dc->info->account_name,
+				 NULL,
+				 &state->user_info_dc->sids[0]);
+	
 	*user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
 
 	tevent_req_received(req);
diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build
index 24d89f4..76efb1f 100644
--- a/source4/kdc/wscript_build
+++ b/source4/kdc/wscript_build
@@ -27,7 +27,7 @@ bld.SAMBA_MODULE('service_kdc',
 
 bld.SAMBA_LIBRARY('HDB_SAMBA4',
                   source='hdb-samba4.c hdb-samba4-plugin.c',
-                  deps='ldb auth4_sam auth_sam_reply samba-credentials hdb db-glue samba-hostconfig com_err sdb_hdb',
+                  deps='ldb auth4_sam common_auth samba-credentials hdb db-glue samba-hostconfig com_err sdb_hdb',
                   includes=kdc_include,
                   private_library=True,
                   enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL')
@@ -78,7 +78,7 @@ bld.SAMBA_SUBSYSTEM('KDC-GLUE',
 bld.SAMBA_SUBSYSTEM('WDC_SAMBA4',
 	source='wdc-samba4.c',
         includes=kdc_include,
-	deps='ldb auth4_sam auth_sam_reply samba-credentials hdb PAC_GLUE samba-hostconfig com_err KDC-GLUE',
+	deps='ldb auth4_sam common_auth samba-credentials hdb PAC_GLUE samba-hostconfig com_err KDC-GLUE',
 	enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL')
 	)
 
@@ -107,7 +107,7 @@ bld.SAMBA_SUBSYSTEM('sdb_kdb',
 bld.SAMBA_SUBSYSTEM('PAC_GLUE',
 	source='pac-glue.c',
         includes=kdc_include,
-	deps='ldb auth4_sam auth_sam_reply samba-credentials samba-hostconfig com_err'
+	deps='ldb auth4_sam common_auth samba-credentials samba-hostconfig com_err'
 	)
 
 bld.SAMBA_LIBRARY('pac',
@@ -119,7 +119,7 @@ bld.SAMBA_LIBRARY('pac',
 
 bld.SAMBA_LIBRARY('db-glue',
 	source='db-glue.c',
-	deps='ldb auth4_sam auth_sam_reply samba-credentials sdb samba-hostconfig com_err',
+	deps='ldb auth4_sam common_auth samba-credentials sdb samba-hostconfig com_err',
 	private_library=True,
         includes=kdc_include,
 	)
@@ -134,7 +134,7 @@ bld.SAMBA_SUBSYSTEM('MIT_SAMBA',
                     deps='''
                          ldb
                          auth4_sam
-                         auth_sam_reply
+                         common_auth
                          samba-credentials
                          db-glue
                          PAC_GLUE
-- 
2.7.4


From 8f836a353e98d2de6ea33cf0dd73439a8b8cfa11 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 1 Mar 2017 11:23:28 +1300
Subject: [PATCH 19/28] s3-auth: Clarify the role and purpose of the
 auth_serversupplied_info->security_token

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source3/include/auth.h | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/source3/include/auth.h b/source3/include/auth.h
index d35936b..406c2c5 100644
--- a/source3/include/auth.h
+++ b/source3/include/auth.h
@@ -34,7 +34,14 @@ struct auth_serversupplied_info {
 
 	struct security_unix_token utok;
 
-	/* NT group information taken from the info3 structure */
+	/*
+	 * NT group information taken from the info3 structure
+	 *
+	 * This is not normally filled in, during the typical
+	 * authentication process.  If filled in, it has already been
+	 * finalised by a nasty hack to support a cached guest/system
+	 * session_info
+	 */
 
 	struct security_token *security_token;
 
-- 
2.7.4


From 10314b44f7ee35bd08eb5768512f9de2cb3b4e8a 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 20/28] 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 eb9756c..7f8b28c 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 4ede6c826d4f8a419df882be9cc47f7db4280dce 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 21/28] 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 7f8b28c..4ac9689 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


From aae2e55d35f60aa174a54b8add2b6218c28bc5b6 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 1 Mar 2017 12:18:49 +1300
Subject: [PATCH 22/28] auth: Add logging of service authorization

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 auth/auth_log.c      | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 auth/common_auth.h   |  5 +++++
 auth/gensec/gensec.c | 35 ++++++++++++++++++++++++++++++--
 3 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/auth/auth_log.c b/auth/auth_log.c
index e447561..7ceae61 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -117,3 +117,59 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 
 	talloc_free(frame);
 }
+
+
+/*
+ * Log details of a successful authorization to a service.
+ *
+ * Only successful authorizations are logged.  For clarity:
+ * - NTLM bad passwords will be recorded by the above
+ * - Kerberos decrypt failures need to be logged in gensec_gssapi et al
+ *
+ * The service may later refuse authorization due to an ACL.
+ *
+ */
+void log_successful_authz_event(const struct tsocket_address *remote,
+				const struct tsocket_address *local,
+				const char *service_description,
+				struct auth_session_info *session_info)
+{
+	TALLOC_CTX *frame = NULL;
+
+	char *ts = NULL;             /* formatted current time      */
+	char *remote_str = NULL;     /* formatted remote host       */
+	char *local_str = NULL;      /* formatted local host        */
+	char sid_buf[DOM_SID_STR_BUFLEN];
+	
+	/* set the log level */
+	if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL)) {
+		return;
+	}
+
+	frame = talloc_stackframe();
+
+	/* Get the current time */
+        ts = http_timestring(frame, time(NULL));
+
+	remote_str = tsocket_address_string(remote, frame);
+	local_str  = tsocket_address_string(local, frame);
+
+	dom_sid_string_buf(&session_info->security_token->sids[0], sid_buf, sizeof(sid_buf));
+	
+	DEBUGC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL, (
+		"Successful AuthZ: [%s] user [%s]\\[%s] [%s]"
+		" at [%s]"
+		" Remote host [%s]"
+		" local host [%s]\n",
+		service_description,
+		log_escape(frame, session_info->info->domain_name),
+		log_escape(frame, session_info->info->account_name),
+		sid_buf,
+		ts,
+		remote_str,
+		local_str));
+
+	talloc_free(frame);
+}
+
+
diff --git a/auth/common_auth.h b/auth/common_auth.h
index 9a83158..67fc6bc 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -152,4 +152,9 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 			      const char *domain_name,
 			      const char *unix_username,
 			      struct dom_sid *sid);
+
+void log_successful_authz_event(const struct tsocket_address *remote,
+				const struct tsocket_address *local,
+				const char *service_description,
+				struct auth_session_info *session_info);
 #endif
diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index 4615bd8..812d48d 100644
--- a/auth/gensec/gensec.c
+++ b/auth/gensec/gensec.c
@@ -29,6 +29,7 @@
 #include "auth/gensec/gensec.h"
 #include "auth/gensec/gensec_internal.h"
 #include "librpc/gen_ndr/dcerpc.h"
+#include "auth/common_auth.h"
 
 _PRIVATE_ NTSTATUS gensec_may_reset_crypto(struct gensec_security *gensec_security,
 					   bool full_reset)
@@ -192,13 +193,36 @@ _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
 	return gensec_security->ops->session_key(gensec_security, mem_ctx, session_key);
 }
 
+/*
+ * Log details of a successful GENSEC authorization to a service.
+ *
+ * Only successful authorizations are logged, as only these call gensec_session_info()
+ *
+ * The service may later refuse authorization due to an ACL.
+ *
+ */
+static void log_successful_gensec_authz_event(struct gensec_security *gensec_security,
+					      struct auth_session_info *session_info)
+{
+	const struct tsocket_address *remote
+		= gensec_get_remote_address(gensec_security);
+	const struct tsocket_address *local
+		= gensec_get_local_address(gensec_security);
+	const char *service_description
+		= gensec_get_target_service_description(gensec_security);
+	log_successful_authz_event(remote, local, service_description, session_info);
+}
+
+
 /**
  * Return the credentials of a logged on user, including session keys
  * etc.
  *
  * Only valid after a successful authentication
  *
- * May only be called once per authentication.
+ * May only be called once per authentication.  This will also make an
+ * authorization log entry, as it is already called by all the
+ * callers.
  *
  */
 
@@ -206,10 +230,17 @@ _PUBLIC_ NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
 				      TALLOC_CTX *mem_ctx,
 				      struct auth_session_info **session_info)
 {
+	NTSTATUS status;
 	if (!gensec_security->ops->session_info) {
 		return NT_STATUS_NOT_IMPLEMENTED;
 	}
-	return gensec_security->ops->session_info(gensec_security, mem_ctx, session_info);
+	status = gensec_security->ops->session_info(gensec_security, mem_ctx, session_info);
+
+	if (NT_STATUS_IS_OK(status)) {
+		log_successful_gensec_authz_event(gensec_security, *session_info);
+	}
+	
+	return status;
 }
 
 _PUBLIC_ void gensec_set_max_update_size(struct gensec_security *gensec_security,
-- 
2.7.4


From d764cdf54fb1f49df83cab2af1db53ce456456f3 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 1 Mar 2017 14:19:50 +1300
Subject: [PATCH 23/28] dns: Provide local and remote socket address to GENSEC

This can be used for logging and for Kerberos channel bindings

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source4/dns_server/dns_query.c  | 21 +++++++++++++++++++++
 source4/dns_server/dns_server.c | 13 +++++++++++--
 source4/dns_server/dns_server.h |  2 ++
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index c0ae19a..b066365 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -702,6 +702,8 @@ static WERROR handle_authoritative_recv(struct tevent_req *req)
 static NTSTATUS create_tkey(struct dns_server *dns,
 			    const char* name,
 			    const char* algorithm,
+			    const struct tsocket_address *local_address,
+			    const struct tsocket_address *remote_address,
 			    struct dns_server_tkey **tkey)
 {
 	NTSTATUS status;
@@ -738,6 +740,23 @@ static NTSTATUS create_tkey(struct dns_server *dns,
 
 	gensec_want_feature(k->gensec, GENSEC_FEATURE_SIGN);
 
+	status = gensec_set_remote_address(k->gensec,
+					   remote_address);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Failed to set remote address into GENSEC: %s\n",
+			  nt_errstr(status)));
+		*tkey = NULL;
+	}
+
+	status = gensec_set_local_address(k->gensec,
+					  local_address);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Failed to set local address into GENSEC: %s\n",
+			  nt_errstr(status)));
+		*tkey = NULL;
+		return status;
+	}
+
 	status = gensec_start_mech_by_oid(k->gensec, GENSEC_OID_SPNEGO);
 
 	if (!NT_STATUS_IS_OK(status)) {
@@ -861,6 +880,8 @@ static WERROR handle_tkey(struct dns_server *dns,
 		if (tkey == NULL) {
 			status  = create_tkey(dns, in->questions[0].name,
 					      in_tkey->rdata.tkey_record.algorithm,
+					      state->local_address,
+					      state->remote_address,
 					      &tkey);
 			if (!NT_STATUS_IS_OK(status)) {
 				ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c
index 830e070..0816b65 100644
--- a/source4/dns_server/dns_server.c
+++ b/source4/dns_server/dns_server.c
@@ -117,6 +117,8 @@ static void dns_process_done(struct tevent_req *subreq);
 static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx,
 					   struct tevent_context *ev,
 					   struct dns_server *dns,
+					   const struct tsocket_address *local_address,
+					   const struct tsocket_address *remote_address,
 					   DATA_BLOB *in)
 {
 	struct tevent_req *req, *subreq;
@@ -161,6 +163,8 @@ static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx,
 	state->state.flags = state->in_packet.operation;
 	state->state.flags |= DNS_FLAG_REPLY;
 
+	state->state.local_address = local_address;
+	state->state.remote_address = remote_address;
 
 	if (forwarder && *forwarder && **forwarder) {
 		state->state.flags |= DNS_FLAG_RECURSION_AVAIL;
@@ -168,7 +172,8 @@ static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx,
 
 	state->out_packet = state->in_packet;
 
-	ret = dns_verify_tsig(dns, state, &state->state, &state->out_packet, in);
+	ret = dns_verify_tsig(dns, state, &state->state,
+			      &state->out_packet, in);
 	if (!W_ERROR_IS_OK(ret)) {
 		state->dns_err = werr_to_dns_err(ret);
 		tevent_req_done(req);
@@ -178,7 +183,8 @@ static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx,
 	switch (state->in_packet.operation & DNS_OPCODE) {
 	case DNS_OPCODE_QUERY:
 		subreq = dns_server_process_query_send(
-			state, ev, dns, &state->state, &state->in_packet);
+			state, ev, dns,
+			&state->state, &state->in_packet);
 		if (tevent_req_nomem(subreq, req)) {
 			return tevent_req_post(req, ev);
 		}
@@ -333,6 +339,8 @@ static void dns_tcp_call_loop(struct tevent_req *subreq)
 	call->in.length -= 2;
 
 	subreq = dns_process_send(call, dns->task->event_ctx, dns,
+				  dns_conn->conn->local_address, 
+				  dns_conn->conn->remote_address, 
 				  &call->in);
 	if (subreq == NULL) {
 		dns_tcp_terminate_connection(
@@ -534,6 +542,7 @@ static void dns_udp_call_loop(struct tevent_req *subreq)
 		 tsocket_address_string(call->src, call)));
 
 	subreq = dns_process_send(call, dns->task->event_ctx, dns,
+				  sock->dns_socket->local_address, call->src,
 				  &call->in);
 	if (subreq == NULL) {
 		TALLOC_FREE(call);
diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h
index e623f97..5395ff9 100644
--- a/source4/dns_server/dns_server.h
+++ b/source4/dns_server/dns_server.h
@@ -61,6 +61,8 @@ struct dns_request_state {
 	char *key_name;
 	struct dns_res_rec *tsig;
 	uint16_t tsig_error;
+	const struct tsocket_address *local_address;
+	const struct tsocket_address *remote_address;
 };
 
 struct tevent_req *dns_server_process_query_send(
-- 
2.7.4


From 75a9ab38672801520a431bf9d512d976b1089150 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 1 Mar 2017 15:06:25 +1300
Subject: [PATCH 24/28] auth_log: Expand to include the type of password used
 (eg ntlmv2)

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 auth/auth_log.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 49 insertions(+), 7 deletions(-)

diff --git a/auth/auth_log.c b/auth/auth_log.c
index 7ceae61..f5c0e19 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -18,9 +18,9 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-/* 
+/*
  * Debug log levels for authentication logging (these both map to
- * LOG_NOTICE in syslog) 
+ * LOG_NOTICE in syslog)
  */
 #define AUTH_SUCCESS_LEVEL 4
 #define AUTHZ_SUCCESS_LEVEL 5
@@ -33,6 +33,45 @@
 #include "libcli/security/dom_sid.h"
 
 /*
+ * Determine the type of the password supplied for the
+ * authorisation attempt.
+ *
+ */
+static const char* get_password_type(const struct auth_usersupplied_info *ui)
+{
+
+	const char *password_type = NULL;
+
+	if (ui->password_state == AUTH_PASSWORD_RESPONSE &&
+		   (ui->logon_parameters & MSV1_0_ALLOW_MSVCHAPV2) &&
+	    ui->password.response.nt.length == 24) {
+		password_type = "mschapv2";
+	} else if ((ui->logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED)
+		   || (ui->password_state == AUTH_PASSWORD_PLAIN)) {
+		password_type = "plaintext";
+	} else if ((ui->password_state == AUTH_PASSWORD_HASH)
+		   && (ui->flags & USER_INFO_INTERACTIVE_LOGON)) {
+		password_type = "interactive";
+	} else if (ui->password_state == AUTH_PASSWORD_HASH) {
+		password_type = "supplied-hash";
+	} else if (ui->password_state == AUTH_PASSWORD_RESPONSE
+		   && ui->password.response.nt.length > 24) {
+		password_type = "ntlmv2";
+	} else if (ui->password_state == AUTH_PASSWORD_RESPONSE
+		   && ui->password.response.nt.length == 24) {
+		password_type = "ntlmv1";
+	} else if (ui->password_state == AUTH_PASSWORD_RESPONSE
+		   && ui->password.response.lanman.length == 24) {
+		password_type = "lanman";
+	} else if (ui->password_state == AUTH_PASSWORD_RESPONSE
+		   && ui->password.response.nt.length == 0
+		   && ui->password.response.lanman.length == 0) {
+		password_type = "no-password";
+	}
+	return password_type;
+}
+
+/*
  * Log details of an authentication attempt.
  * Successful and unsuccessful attempts are logged.
  *
@@ -53,7 +92,8 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 	char *trust_computer_name = NULL;
 	char *trust_account_name = NULL;
 	char *logon_line = NULL;
-	
+	const char *password_type = NULL;
+
 	/* set the log level */
 	int  level = NT_STATUS_IS_OK(status) ? AUTH_FAILURE_LEVEL : AUTH_SUCCESS_LEVEL;
 	if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, level)) {
@@ -62,6 +102,7 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 
 	frame = talloc_stackframe();
 
+	password_type = get_password_type( ui);
 	/* Get the current time */
         ts = http_timestring(frame, time(NULL));
 
@@ -95,15 +136,16 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 					     log_escape(frame, ui->mapped.domain_name),
 					     log_escape(frame, ui->mapped.account_name));
 	}
-	
+
 	DEBUGC( DBGC_AUTH_AUDIT, level, (
 		"Auth: [%s,%s] user [%s]\\[%s]"
-		" at [%s] status [%s]"
+		" at [%s] with [%s] status [%s]"
 		" workstation [%s] remote host [%s]"
 		"%s local host [%s]"
 		" %s\n",
 		ui->service_description,
 		ui->auth_description,
+		password_type,
 		log_escape(frame, ui->client.domain_name),
 		log_escape(frame, ui->client.account_name),
 		ts,
@@ -140,7 +182,7 @@ void log_successful_authz_event(const struct tsocket_address *remote,
 	char *remote_str = NULL;     /* formatted remote host       */
 	char *local_str = NULL;      /* formatted local host        */
 	char sid_buf[DOM_SID_STR_BUFLEN];
-	
+
 	/* set the log level */
 	if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL)) {
 		return;
@@ -155,7 +197,7 @@ void log_successful_authz_event(const struct tsocket_address *remote,
 	local_str  = tsocket_address_string(local, frame);
 
 	dom_sid_string_buf(&session_info->security_token->sids[0], sid_buf, sizeof(sid_buf));
-	
+
 	DEBUGC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL, (
 		"Successful AuthZ: [%s] user [%s]\\[%s] [%s]"
 		" at [%s]"
-- 
2.7.4


From a75208dce4b3d25d9b770eb7b10ebfbecbb42b4e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 1 Mar 2017 16:00:03 +1300
Subject: [PATCH 25/28] auth_log: Also log the final type of authentication
 (ntlmssp,krb5)

Administrators really care about how their users were authenticated, so make
this clear.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 auth/auth_log.c                     |  8 +++++---
 auth/common_auth.h                  |  1 +
 auth/gensec/gensec.c                | 16 +++++++++++++++-
 auth/gensec/gensec.h                |  2 ++
 auth/gensec/gensec_internal.h       |  3 +++
 auth/gensec/spnego.c                | 12 ++++++++++++
 auth/ntlmssp/ntlmssp_server.c       |  9 ++++++++-
 source3/librpc/crypto/gse.c         | 16 ++++++++++++++++
 source4/auth/gensec/gensec_gssapi.c | 16 ++++++++++++++++
 source4/auth/gensec/gensec_krb5.c   |  9 ++++++++-
 10 files changed, 86 insertions(+), 6 deletions(-)

diff --git a/auth/auth_log.c b/auth/auth_log.c
index f5c0e19..92b502a 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -127,8 +127,8 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 		dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
 		logon_line = talloc_asprintf(frame,
 					     " became [%s]\\[%s] %s.",
-					     log_escape(frame, account_name),
 					     log_escape(frame, domain_name),
+					     log_escape(frame, account_name),
 					     sid_buf);
 	} else {
 		logon_line = talloc_asprintf(frame,
@@ -145,10 +145,10 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 		" %s\n",
 		ui->service_description,
 		ui->auth_description,
-		password_type,
 		log_escape(frame, ui->client.domain_name),
 		log_escape(frame, ui->client.account_name),
 		ts,
+		password_type,
 		nt_errstr( status),
 		log_escape(frame, ui->workstation_name),
 		remote,
@@ -174,6 +174,7 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 void log_successful_authz_event(const struct tsocket_address *remote,
 				const struct tsocket_address *local,
 				const char *service_description,
+				const char *auth_type,
 				struct auth_session_info *session_info)
 {
 	TALLOC_CTX *frame = NULL;
@@ -199,11 +200,12 @@ void log_successful_authz_event(const struct tsocket_address *remote,
 	dom_sid_string_buf(&session_info->security_token->sids[0], sid_buf, sizeof(sid_buf));
 
 	DEBUGC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL, (
-		"Successful AuthZ: [%s] user [%s]\\[%s] [%s]"
+		"Successful AuthZ: [%s,%s] user [%s]\\[%s] [%s]"
 		" at [%s]"
 		" Remote host [%s]"
 		" local host [%s]\n",
 		service_description,
+		auth_type,
 		log_escape(frame, session_info->info->domain_name),
 		log_escape(frame, session_info->info->account_name),
 		sid_buf,
diff --git a/auth/common_auth.h b/auth/common_auth.h
index 67fc6bc..999d05c 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -156,5 +156,6 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 void log_successful_authz_event(const struct tsocket_address *remote,
 				const struct tsocket_address *local,
 				const char *service_description,
+				const char *auth_type,
 				struct auth_session_info *session_info);
 #endif
diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index 812d48d..2bdf709 100644
--- a/auth/gensec/gensec.c
+++ b/auth/gensec/gensec.c
@@ -193,6 +193,15 @@ _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
 	return gensec_security->ops->session_key(gensec_security, mem_ctx, session_key);
 }
 
+const char *gensec_final_auth_type(struct gensec_security *gensec_security)
+{
+	if (!gensec_security->ops->final_auth_type) {
+		return gensec_security->ops->name;
+	}
+	
+	return gensec_security->ops->final_auth_type(gensec_security);
+}
+
 /*
  * Log details of a successful GENSEC authorization to a service.
  *
@@ -210,7 +219,12 @@ static void log_successful_gensec_authz_event(struct gensec_security *gensec_sec
 		= gensec_get_local_address(gensec_security);
 	const char *service_description
 		= gensec_get_target_service_description(gensec_security);
-	log_successful_authz_event(remote, local, service_description, session_info);
+	const char *final_auth_type
+		= gensec_final_auth_type(gensec_security);
+	log_successful_authz_event(remote, local,
+				   service_description,
+				   final_auth_type,
+				   session_info);
 }
 
 
diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h
index 7b5242c..eef575d 100644
--- a/auth/gensec/gensec.h
+++ b/auth/gensec/gensec.h
@@ -34,6 +34,8 @@
 #define GENSEC_OID_KERBEROS5_OLD "1.2.840.48018.1.2.2"
 #define GENSEC_OID_KERBEROS5_USER2USER "1.2.840.113554.1.2.2.3"
 
+#define GENSEC_FINAL_AUTH_TYPE_KRB5 "krb5"
+
 enum gensec_priority {
 	GENSEC_SPNEGO = 90,
 	GENSEC_GSSAPI = 80,
diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h
index 5535241..26c9817 100644
--- a/auth/gensec/gensec_internal.h
+++ b/auth/gensec/gensec_internal.h
@@ -85,6 +85,7 @@ struct gensec_security_ops {
 	bool (*have_feature)(struct gensec_security *gensec_security,
 				    uint32_t feature);
 	NTTIME (*expire_time)(struct gensec_security *gensec_security);
+	const char *(*final_auth_type)(struct gensec_security *gensec_security);
 	bool enabled;
 	bool kerberos;
 	enum gensec_priority priority;
@@ -126,4 +127,6 @@ struct gensec_critical_sizes {
 NTSTATUS gensec_may_reset_crypto(struct gensec_security *gensec_security,
 				 bool full_reset);
 
+const char *gensec_final_auth_type(struct gensec_security *gensec_security);
+
 #endif /* __GENSEC_H__ */
diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c
index 4787892..8efa6ef 100644
--- a/auth/gensec/spnego.c
+++ b/auth/gensec/spnego.c
@@ -1603,6 +1603,17 @@ static NTTIME gensec_spnego_expire_time(struct gensec_security *gensec_security)
 	return gensec_expire_time(spnego_state->sub_sec_security);
 }
 
+static const char *gensec_spnego_final_auth_type(struct gensec_security *gensec_security)
+{
+	struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data;
+
+	if (!spnego_state->sub_sec_security) {
+		return "NONE";
+	} else {
+		return gensec_final_auth_type(spnego_state->sub_sec_security);
+	}
+}
+
 static const char *gensec_spnego_oids[] = { 
 	GENSEC_OID_SPNEGO,
 	NULL 
@@ -1630,6 +1641,7 @@ static const struct gensec_security_ops gensec_spnego_security_ops = {
 	.want_feature     = gensec_spnego_want_feature,
 	.have_feature     = gensec_spnego_have_feature,
 	.expire_time      = gensec_spnego_expire_time,
+	.final_auth_type  = gensec_spnego_final_auth_type,
 	.enabled          = true,
 	.priority         = GENSEC_SPNEGO
 };
diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c
index 1a4e02b..2c92037 100644
--- a/auth/ntlmssp/ntlmssp_server.c
+++ b/auth/ntlmssp/ntlmssp_server.c
@@ -721,7 +721,14 @@ static NTSTATUS ntlmssp_server_check_password(struct gensec_security *gensec_sec
 	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";
+
+	/*
+	 * This will just be the string "ntlmssp" from
+	 * gensec_ntlmssp_security_ops, but ensures it stays in sync
+	 * with the same use in the authorization logging triggered by
+	 * gensec_session_info() later 
+	 */
+	user_info->auth_description = gensec_final_auth_type(gensec_security);
 	
 	user_info->password_state = AUTH_PASSWORD_RESPONSE;
 	user_info->password.response.lanman = ntlmssp_state->lm_resp;
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c
index 99971d3..18af6fc 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -1137,6 +1137,21 @@ static size_t gensec_gse_sig_size(struct gensec_security *gensec_security,
 	return gse_ctx->sig_size;
 }
 
+static const char *gensec_gse_final_auth_type(struct gensec_security *gensec_security)
+{
+	struct gse_context *gse_ctx =
+		talloc_get_type_abort(gensec_security->private_data,
+		struct gse_context);
+
+	/* Only return the string for GSSAPI/Krb5 */
+	if (smb_gss_oid_equal(&gse_ctx->gss_mech,
+			      gss_mech_krb5)) {
+		return GENSEC_FINAL_AUTH_TYPE_KRB5;
+	} else {
+		return "gensec_gse: UNKNOWN MECH";
+	}
+}
+
 static const char *gensec_gse_krb5_oids[] = {
 	GENSEC_OID_KERBEROS5_OLD,
 	GENSEC_OID_KERBEROS5,
@@ -1164,6 +1179,7 @@ const struct gensec_security_ops gensec_gse_krb5_security_ops = {
 	.unwrap         = gensec_gse_unwrap,
 	.have_feature   = gensec_gse_have_feature,
 	.expire_time    = gensec_gse_expire_time,
+	.final_auth_type  = gensec_gse_final_auth_type,
 	.enabled        = true,
 	.kerberos       = true,
 	.priority       = GENSEC_GSSAPI
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index 2ae2e23..7feeb0c74 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -1389,6 +1389,19 @@ static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, si
 	return gensec_gssapi_state->sig_size;
 }
 
+static const char *gensec_gssapi_final_auth_type(struct gensec_security *gensec_security)
+{
+	struct gensec_gssapi_state *gensec_gssapi_state
+		= talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
+	/* Only return the string for GSSAPI/Krb5 */
+	if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
+			      gss_mech_krb5)) {
+		return GENSEC_FINAL_AUTH_TYPE_KRB5;
+	} else {
+		return "gensec_gssapi: UNKNOWN MECH";
+	}
+}
+
 static const char *gensec_gssapi_krb5_oids[] = { 
 	GENSEC_OID_KERBEROS5_OLD,
 	GENSEC_OID_KERBEROS5,
@@ -1422,6 +1435,7 @@ static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
 	.unwrap         = gensec_gssapi_unwrap,
 	.have_feature   = gensec_gssapi_have_feature,
 	.expire_time    = gensec_gssapi_expire_time,
+	.final_auth_type = gensec_gssapi_final_auth_type,
 	.enabled        = false,
 	.kerberos       = true,
 	.priority       = GENSEC_GSSAPI
@@ -1449,6 +1463,7 @@ static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
 	.unwrap         = gensec_gssapi_unwrap,
 	.have_feature   = gensec_gssapi_have_feature,
 	.expire_time    = gensec_gssapi_expire_time,
+	.final_auth_type = gensec_gssapi_final_auth_type,
 	.enabled        = true,
 	.kerberos       = true,
 	.priority       = GENSEC_GSSAPI
@@ -1469,6 +1484,7 @@ static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {
 	.unwrap           = gensec_gssapi_unwrap,
 	.have_feature     = gensec_gssapi_have_feature,
 	.expire_time      = gensec_gssapi_expire_time,
+	.final_auth_type = gensec_gssapi_final_auth_type,
 	.enabled          = true,
 	.kerberos         = true,
 	.priority         = GENSEC_GSSAPI
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index b54a41b..4946929 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -1038,6 +1038,11 @@ static bool gensec_krb5_have_feature(struct gensec_security *gensec_security,
 	return false;
 }
 
+static const char *gensec_krb5_final_auth_type(struct gensec_security *gensec_security)
+{
+	return GENSEC_FINAL_AUTH_TYPE_KRB5;
+}
+
 static const char *gensec_krb5_oids[] = { 
 	GENSEC_OID_KERBEROS5,
 	GENSEC_OID_KERBEROS5_OLD,
@@ -1055,9 +1060,10 @@ static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {
 	.session_key	= gensec_krb5_session_key,
 	.session_info	= gensec_krb5_session_info,
 	.have_feature   = gensec_krb5_have_feature,
+	.final_auth_type = gensec_krb5_final_auth_type,
 	.enabled        = false,
 	.kerberos       = true,
-	.priority       = GENSEC_KRB5
+	.priority       = GENSEC_KRB5,
 };
 
 static const struct gensec_security_ops gensec_krb5_security_ops = {
@@ -1070,6 +1076,7 @@ static const struct gensec_security_ops gensec_krb5_security_ops = {
 	.have_feature   = gensec_krb5_have_feature,
 	.wrap           = gensec_krb5_wrap,
 	.unwrap         = gensec_krb5_unwrap,
+	.final_auth_type = gensec_krb5_final_auth_type,
 	.enabled        = true,
 	.kerberos       = true,
 	.priority       = GENSEC_KRB5
-- 
2.7.4


From e23c2c19587de577603c9b1b1774cf7bcb97dcd2 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 1 Mar 2017 16:27:51 +1300
Subject: [PATCH 26/28] s3-auth: Log SMB authorization for bare NTLM
 (NTLMSSP/krb5 already done)

gensec_session_info() is not called for bare NTLM, so we have to log manually

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

diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 52fbef6..1b8808d 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -399,6 +399,11 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
 	return NT_STATUS_OK;
 }
 
+/* 
+ * Check a username and password, and return the final session_info.
+ * We also log the authorization of the session here, just as
+ * gensec_session_info() does. 
+ */
 NTSTATUS auth_check_password_session_info(struct auth4_context *auth_context,
 					  TALLOC_CTX *mem_ctx,
 					  struct auth_usersupplied_info *user_info,
@@ -422,5 +427,17 @@ NTSTATUS auth_check_password_session_info(struct auth4_context *auth_context,
 								session_info);
 		TALLOC_FREE(server_info);
 	}
+
+	/*
+	 * This is rather redundant, but because we want to log all
+	 * authorizations consistently (be they NLTM, NTLMSSP or
+	 * krb5) we log this info again.
+	 */
+	log_successful_authz_event(user_info->remote_host,
+				   user_info->local_host,
+				   user_info->service_description,
+				   user_info->auth_description,
+				   *session_info);
+	
 	return nt_status;
 }
-- 
2.7.4


From 48a9b56cc608b5cc576ac8a53c39182dbc0bffd5 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 1 Mar 2017 16:28:06 +1300
Subject: [PATCH 27/28] s4-auth: Log SMB authorization for bare NTLM
 (NTLMSSP/krb5 already done)

gensec_session_info() is not called for bare NTLM, so we have to log manually

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source4/smb_server/smb/sesssetup.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c
index 3528548..412ce27 100644
--- a/source4/smb_server/smb/sesssetup.c
+++ b/source4/smb_server/smb/sesssetup.c
@@ -39,6 +39,33 @@ struct sesssetup_context {
 };
 
 /*
+ * Log the SMB authentication, as by not calling GENSEC we won't log
+ * it during the gensec_session_info().
+ */
+void smbsrv_not_spengo_sesssetup_authz_log(struct smbsrv_request *req,
+					       struct auth_session_info *session_info)
+{
+	struct tsocket_address *local_address;
+	struct tsocket_address *remote_address;
+	TALLOC_CTX *frame = talloc_stackframe();
+	
+	remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
+						frame);
+	local_address = socket_get_local_addr(req->smb_conn->connection->socket,
+					      frame);
+
+	log_successful_authz_event(remote_address,
+				   local_address,
+				   "smb",
+				   "bare-NTLM",
+				   session_info);
+	
+	talloc_free(frame);
+	return;
+}
+
+
+/*
   setup the OS, Lanman and domain portions of a session setup reply
 */
 static void sesssetup_common_strings(struct smbsrv_request *req,
@@ -96,6 +123,8 @@ static void sesssetup_old_send(struct tevent_req *subreq)
 		goto failed;
 	}
 
+	smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
+
 	/* Ensure this is marked as a 'real' vuid, not one
 	 * simply valid for the session setup leg */
 	status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
@@ -237,6 +266,8 @@ static void sesssetup_nt1_send(struct tevent_req *subreq)
 		goto failed;
 	}
 
+	smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
+	
 	/* Ensure this is marked as a 'real' vuid, not one
 	 * simply valid for the session setup leg */
 	status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
@@ -336,7 +367,8 @@ static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
 	if (!user_info) goto nomem;
 
 	user_info->service_description = "smb";
-	
+	user_info->auth_description = "bare-NTLM";
+
 	user_info->mapped_state = false;
 	user_info->logon_parameters = 0;
 	user_info->flags = 0;
-- 
2.7.4


From 41d45bbd64315615d1a9e51289b8092451e36a76 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 1 Mar 2017 16:49:01 +1300
Subject: [PATCH 28/28] ldap_server: Log authorization for simple binds

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Pair-Programmed: Gary Lockyer <gary at catalyst.net.nz>
---
 source4/auth/ntlm/auth_simple.c | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c
index 6831f91..cee6e8b 100644
--- a/source4/auth/ntlm/auth_simple.c
+++ b/source4/auth/ntlm/auth_simple.c
@@ -46,6 +46,7 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 	const char *nt4_domain;
 	const char *nt4_username;
+	uint32_t flags = 0;
 	
 	if (!tmp_ctx) {
 		return NT_STATUS_NO_MEMORY;
@@ -106,23 +107,27 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 		return nt_status;
 	}
 
-	if (session_info) {
-		uint32_t flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
-		if (user_info_dc->info->authenticated) {
-			flags |= AUTH_SESSION_INFO_AUTHENTICATED;
-		}
-		nt_status = auth_context->generate_session_info(auth_context,
-								tmp_ctx, 
-								user_info_dc,
-								nt4_username,
-								flags,
-								session_info);
-
-		if (NT_STATUS_IS_OK(nt_status)) {
-			talloc_steal(mem_ctx, *session_info);
-		}
+	flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
+	if (user_info_dc->info->authenticated) {
+		flags |= AUTH_SESSION_INFO_AUTHENTICATED;
+	}
+	nt_status = auth_context->generate_session_info(auth_context,
+							tmp_ctx, 
+							user_info_dc,
+							nt4_username,
+							flags,
+							session_info);
+	
+	if (NT_STATUS_IS_OK(nt_status)) {
+		talloc_steal(mem_ctx, *session_info);
 	}
 
+	log_successful_authz_event(remote_address,
+				   local_address,
+				   "ldap",
+				   "simple bind",
+				   *session_info);
+	
 	talloc_free(tmp_ctx);
 	return nt_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/20170302/6089a4cf/signature-0001.sig>


More information about the samba-technical mailing list