[PATCH] Simplify auth_check_ntlm_password

Jeremy Allison jra at samba.org
Wed Mar 8 01:46:21 UTC 2017


On Wed, Mar 08, 2017 at 01:59:18PM +1300, Andrew Bartlett wrote:
> On Tue, 2017-03-07 at 13:52 -0800, Jeremy Allison wrote:
> > On Wed, Mar 08, 2017 at 10:04:19AM +1300, Andrew Bartlett wrote:
> > > On Tue, 2017-03-07 at 14:28 +0100, Volker Lendecke wrote:
> > > > Hi!
> > > > 
> > > > While working on the auth code I had a hard time following the
> > > > logic
> > > > in auth_check_ntlm_password. The attached patchset is supposed to
> > > > make
> > > > that more traceable. It does not change behaviour, those patches
> > > > will
> > > > come at a later step and will make the routine even simpler. The
> > > > behaviour change will be to always break out of the loop if
> > > > 
> > > > !NT_STATUS_EQUAL(nt_status,NT_STATUS_NOT_IMPLEMENTED);
> > > > 
> > > > Review appreciated!
> > > 
> > > Thanks Volker, these look like a helpful start to making this stuff
> > > simpler.  
> > > 
> > > I looked at this set last night, to see how it works with the
> > > authentication audit code (so I could integrate into that series it
> > > as
> > > promised).  Putting it in before causes rebase pain, so I'll take a
> > > look at adding it after and see if it is any less difficult.
> > > 
> > > Otherwise I'll take the concepts and apply them once we are done.  
> > 
> > Really ? Does this cause much rebase pain ? Yeah, it'll cause
> > some, but this really does clean up these code paths.
> 
> I'm not objecting to the patch, just saying I will try and add it on
> top of the branch rather than underneath it.  I did actually try the
> rebase last night, and perhaps you have better luck, but I've had
> enough of these go bad on me that I would just like to apply it on top,
> if that is OK.
> 
> > Looking at the previously posted logging patch I can only
> > find two places where the logging patch touches source3/auth/auth.c:
> 
> We keep our repo public, but we haven't been spamming the list as we
> go.  The current code is in auth-logging-ntlm in the catalyst git repo.
> 
> git://git.catalyst.net.nz/samba.git auth-logging-ntlm

Here is your patch rebased on top of Volker's work applied to
master.

It only took 10 mins or so (so I exaggerated about 2 mins :-).

I didn't fix the 'static' issue as I only wanted to show your
exact code on top of what I'm proposing to push.

I haven't compiled it yet :-).

Doing the rebase really isn't that hard - it'd be good for
Gary to learn this skill now rather than later !

Cheers,

	Jeremy.
-------------- next part --------------
From a724933277a1e72852c40ce2604bebc92065c599 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/43] 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 8a04c25fa00..009f3629979 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 43c6aa08c76..786c80958ec 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.12.0.246.ga2ecc84866-goog


From ec3083fc260b562f78832ee418fe96d5a4f48067 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/43] 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 b75a9faeb75..02758b90ce1 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.12.0.246.ga2ecc84866-goog


From ba330fa3c127d574260266cb869d05042f92a097 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/43] 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 d1a775d431a..28b9bd77910 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 afa9b1c91e1..60421f5b9fc 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.12.0.246.ga2ecc84866-goog


From 614386f438cafa6515294f233a69630ef8f836db 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/43] 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 | 14 ++++++++++++++
 4 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index d6236137691..e413fbdfd6f 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 e8bd7b1f22a..0c9fa2661a8 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 eba84f0b856..364255d2c5f 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 af0079beabb..769b52bd00a 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -125,6 +125,20 @@ 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,
+						       "DCE/RPC");
+	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.12.0.246.ga2ecc84866-goog


From f9c0198d4975afbf6bdc4300ea8081a89cb66252 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/43] 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 28b9bd77910..1e9ca291ddd 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 ddee8756bfe..6d7cc2bfc74 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.12.0.246.ga2ecc84866-goog


From bd5686211b417710043365a3446c6f53dbbb689e 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/43] 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 f9b918496fd..55555e8501d 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 5fd315846d8..36972114565 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 a338108a41f..7bdfdeeed94 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 f288c94621f..36e1a83e077 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 407d8d70583..4a63dd734aa 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 838ff45aad1..119f2a91258 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 d2c8951b879..f406c43b0af 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 encryption",
 				      &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 8ec60937155..5196e4f6182 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 6a0caac1308..7e3102b0c2b 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.12.0.246.ga2ecc84866-goog


From b6234e414283c11f1c5ec92639178eaa6d05d5c9 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/43] 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 829eb8f96b2..516b485f420 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.12.0.246.ga2ecc84866-goog


From 0b4603cc5bcb31d9a16a29ad96c2a6f4a8e4d5eb 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/43] 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 a0e49027af9..71b8183f410 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 5d9f0e0270f..d015165249e 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 36972114565..69fa20c701c 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 0d5176d2b1f..c410d222af5 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 5196e4f6182..3157dfda036 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 fe51a764798..56bacd5a688 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 5d1da16c93a..fbd61d3a503 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 60421f5b9fc..c10ce09d05f 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 e06853afcd4..94f8bbc1dd7 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.12.0.246.ga2ecc84866-goog


From 7b1489c9ae3c17231219a4705313e6f447041dd9 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/43] 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 aad89315508..83623155a4e 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -180,6 +180,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;
@@ -209,32 +241,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.12.0.246.ga2ecc84866-goog


From a9616f21dc34b2c91d5d364d9d8a609cde032500 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/43] 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 83623155a4e..332bad3224e 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -199,6 +199,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.12.0.246.ga2ecc84866-goog


From 478e5825b3b7ac7a62d35d8dfa08adff31d62dc9 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/43] 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 1cbe46e6756..ebd5597a61b 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -315,6 +315,10 @@ fail:
 
 	/* 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 05d6c3cb75e..310cab41d01 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.12.0.246.ga2ecc84866-goog


From 09487c3fc116a53b6953fd55e52102d4beb7d951 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/43] 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 | 41 ++++++++++++++++++++++++++++-------------
 source4/ldap_server/ldap_bind.c | 22 +++++++++-------------
 3 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/source4/auth/auth.h b/source4/auth/auth.h
index 7c623182ec6..d4be60e2e2a 100644
--- a/source4/auth/auth.h
+++ b/source4/auth/auth.h
@@ -158,15 +158,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 f6dd9d0e6be..ef37e68b8cb 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 332bad3224e..6a91cabcd72 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -68,7 +68,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;
 
@@ -93,18 +92,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.12.0.246.ga2ecc84866-goog


From bcb03c98653a3e6cdec96d5584de64430286e8e3 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/43] 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                 | 1 +
 source3/smbd/sesssetup.c                      | 6 ++++++
 source4/auth/ntlm/auth_simple.c               | 4 +++-
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 3 +++
 5 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/auth/common_auth.h b/auth/common_auth.h
index 1e9ca291ddd..869f1387af4 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 6d7cc2bfc74..322c94c5000 100644
--- a/auth/ntlmssp/ntlmssp_server.c
+++ b/auth/ntlmssp/ntlmssp_server.c
@@ -720,6 +720,7 @@ 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;
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 3157dfda036..e66aae5ab7b 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 ef37e68b8cb..7f077a5d928 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);
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index c10ce09d05f..b459467d9a2 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -910,6 +910,7 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 	case NetlogonServiceInformation:
 	case NetlogonInteractiveTransitiveInformation:
 	case NetlogonServiceTransitiveInformation:
+		user_info->auth_description = "interactive";
 
 		user_info->logon_parameters
 			= r->in.logon->password->identity_info.parameter_control;
@@ -933,6 +934,8 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 		break;
 	case NetlogonNetworkInformation:
 	case NetlogonNetworkTransitiveInformation:
+		user_info->auth_description = "network";
+
 		nt_status = auth_context_set_challenge(
 			auth_context,
 			r->in.logon->network->challenge,
-- 
2.12.0.246.ga2ecc84866-goog


From 9c1c32f5f37691225901707214e66cf789c94ac5 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/43] 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 fbd61d3a503..565fbcb04ea 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1390,7 +1390,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,
@@ -1512,43 +1512,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;
-		}
-		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));
-	}
+		} else {
+			lm_resp = data_blob_null;
+			SMBNTencrypt(pass, chal, local_nt_response);
 
-	if (strequal(name_domain, get_global_sam_name())) {
-		DATA_BLOB chal_blob = data_blob_const(chal, sizeof(chal));
+			nt_resp = data_blob_talloc(mem_ctx, local_nt_response,
+						   sizeof(local_nt_response));
+		}
 
 		result = winbindd_dual_auth_passdb(
 			mem_ctx, 0, name_domain, name_user,
@@ -1557,7 +1557,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;
@@ -1573,9 +1574,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 */
 					     &authoritative,
 					     &flags,
-- 
2.12.0.246.ga2ecc84866-goog


From 83b64fb44b40d4c8b942d6a967030e734b88ceae 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/43] 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 | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index f7ec2106b98..3663a2b4be4 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -939,9 +939,12 @@ 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.
+	 * At this point we still don't know which interface (eg
+	 * netlogon, lsa, drsuapi) the caller requested in this bind!
+	 * 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, but they may not have
+	 * requested one at all!
 	 */
 
 	if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
-- 
2.12.0.246.ga2ecc84866-goog


From 8a690777480f9b83292252e901f4bf682acf1d53 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/43] 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 00000000000..82e2209ef55
--- /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 00000000000..0d8a871b023
--- /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 00000000000..0b4c5964c14
--- /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 ddece0ee7a6..81178b88377 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 6641f211cff..89066c5f52f 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 3a12b6bcd27..c8e8fde63fc 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.12.0.246.ga2ecc84866-goog


From 70cf8ca4d92c7c70897d303afcdc348dc6d6b857 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/43] 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 | 41 ++++++++++++++++++++++++++---------------
 2 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index 69fa20c701c..eb9756c3ac7 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 77b63e4ba63..03c4b646007 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,21 +263,10 @@ 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 */
-- 
2.12.0.246.ga2ecc84866-goog


From 369fa12398d8e0e96906085f53b50f1960e53a7d 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/43] 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 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 source3/auth/auth.c |  17 ++++++++
 2 files changed, 136 insertions(+)
 create mode 100644 auth/auth_log.c

diff --git a/auth/auth_log.c b/auth/auth_log.c
new file mode 100644
index 00000000000..fc3f5506adc
--- /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, domain_name),
+					     log_escape(frame, account_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/source3/auth/auth.c b/source3/auth/auth.c
index ebd5597a61b..c93551d042e 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -171,6 +171,7 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 	const char *unix_username;
 	auth_methods *auth_method;
 	struct auth_serversupplied_info *server_info;
+	struct dom_sid sid = {0};
 
 	if (user_info == NULL || auth_context == NULL || pserver_info == NULL) {
 		return NT_STATUS_LOGON_FAILURE;
@@ -306,6 +307,19 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 	       user_info->mapped.account_name,
 	       unix_username));
 
+	nt_status = get_user_sid_info3_and_extra(server_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,
+			server_info->info3->base.logon_domain.string,
+			server_info->info3->base.account_name.string,
+			unix_username, &sid);
+
 	*pserver_info = talloc_move(mem_ctx, &server_info);
 
 	TALLOC_FREE(frame);
@@ -322,6 +336,9 @@ fail:
 	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);
 
 	TALLOC_FREE(frame);
-- 
2.12.0.246.ga2ecc84866-goog


From b8751085c7e4289fd9c3250c41fd25450af4f8fb 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/43] 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 d35936b243c..406c2c5231e 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.12.0.246.ga2ecc84866-goog


From 626fa2ae463be00a0082950c98c6a1fbcd906838 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/43] 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      | 39 +++++++++++++++++++++++
 12 files changed, 122 insertions(+), 9 deletions(-)

diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c
index 322c94c5000..85d204b38e2 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 55555e8501d..05f3019864c 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 eb9756c3ac7..7f8b28cff08 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 7bdfdeeed94..1092cd3317f 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 36e1a83e077..4e86eabc953 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 4a63dd734aa..446679f39d4 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 119f2a91258..de3d531d033 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 f406c43b0af..8a0dbeb2bf4 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 encryption",
 				      &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 e66aae5ab7b..5afd2a4dce4 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 7e3102b0c2b..52462882771 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 94f8bbc1dd7..3541926193a 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 5e261a20e40..7d92aa28697 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,
@@ -145,6 +146,44 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses
 
 		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.12.0.246.ga2ecc84866-goog


From 0a9bd1aa19fdda8693e7e2d11c9e68ea31fd19fc 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/43] 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                 | 48 +++++++++++++++++++------
 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                       | 15 +++++---
 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 71b8183f410..f004c590c36 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 d015165249e..ffd60e0b467 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 7f8b28cff08..4ac9689932d 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 c410d222af5..6165d592d5a 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 0502557a662..da26fab76ae 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 34133b27a58..dd78e69989e 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 e92f4613ba5..60002020351 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 ac04460ae15..3ac8380bf7c 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 ef2c8278afb..424ff7170c8 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 cb3b8e64340..121e776b90c 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 59b9d5a787e..2ae126dec9e 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 6c988cea7dc..21504c0eeed 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;
@@ -986,11 +1006,17 @@ 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 32f0e274598..17acf515eb9 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 995ed081f62..c3e540ff810 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 22941ec256e..f8cd39d3026 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 5afd2a4dce4..a570849d5c8 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 56bacd5a688..f73c2c5cdc4 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",
+				pdb_get_domain(pdb_entry), pdb_get_domain(pdb_entry), lp_netbios_name(),
+				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 3df4af3ff10..157a19374b3 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 565fbcb04ea..ace1c0305c0 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 769b52bd00a..ece314dcbe6 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -149,6 +149,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.12.0.246.ga2ecc84866-goog


From 2a52429a09fc8b8fb103c77505d5cf3da3c01958 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/43] 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                     | 54 +++++++++++++++++++++++++++++++++++++
 auth/common_auth.h                  | 11 ++++++++
 auth/gensec/gensec.c                | 36 +++++++++++++++++++++++--
 auth/gensec/gensec.h                |  1 +
 auth/wscript_build                  |  6 ++---
 source3/libads/authdata.c           |  2 ++
 source3/rpc_server/wscript_build    |  2 +-
 source4/auth/kerberos/wscript_build |  2 +-
 source4/auth/ntlm/auth.c            | 15 +++++++++--
 source4/kdc/wscript_build           | 10 +++----
 10 files changed, 125 insertions(+), 14 deletions(-)

diff --git a/auth/auth_log.c b/auth/auth_log.c
index fc3f5506adc..db46f2b5a7d 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -117,3 +117,57 @@ 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 869f1387af4..67fc6bcb746 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -146,4 +146,15 @@ 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);
+
+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 e413fbdfd6f..d97d3b4e4ac 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,18 @@ _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)
+	    && (gensec_security->want_features & GENSEC_FEATURE_NO_AUTHZ_LOG) == 0) {
+		log_successful_gensec_authz_event(gensec_security, *session_info);
+	}
+
+	return status;
 }
 
 _PUBLIC_ void gensec_set_max_update_size(struct gensec_security *gensec_security,
diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h
index 0c9fa2661a8..7bd893266b9 100644
--- a/auth/gensec/gensec.h
+++ b/auth/gensec/gensec.h
@@ -64,6 +64,7 @@ struct gensec_target {
 #define GENSEC_FEATURE_UNIX_TOKEN	0x00000100
 #define GENSEC_FEATURE_NTLM_CCACHE	0x00000200
 #define GENSEC_FEATURE_LDAP_STYLE	0x00000400
+#define GENSEC_FEATURE_NO_AUTHZ_LOG	0x00000800
 
 #define GENSEC_EXPIRE_TIME_INFINITY (NTTIME)0x8000000000000000LL
 
diff --git a/auth/wscript_build b/auth/wscript_build
index 20261537fbd..732536d686e 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/libads/authdata.c b/source3/libads/authdata.c
index f4f4b4f1898..2d7153b3e26 100644
--- a/source3/libads/authdata.c
+++ b/source3/libads/authdata.c
@@ -269,6 +269,8 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx,
 	talloc_unlink(tmp_ctx, gensec_settings);
 	talloc_unlink(tmp_ctx, auth_context);
 
+	gensec_want_feature(gensec_server_context, GENSEC_FEATURE_NO_AUTHZ_LOG);
+
 	status = gensec_start_mech_by_oid(gensec_server_context, GENSEC_OID_KERBEROS5);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(1, (__location__ "Failed to start server-side GENSEC krb5 to validate a Kerberos ticket: %s\n", nt_errstr(status)));
diff --git a/source3/rpc_server/wscript_build b/source3/rpc_server/wscript_build
index 7fe4fda9df5..ae75e567ace 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 0f886fa7c48..30853ec33c5 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 310cab41d01..9a0345c07c0 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 24d89f4c89b..76efb1f02ca 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.12.0.246.ga2ecc84866-goog


From 03b2d8061c4eef9463b74785e134b0c485801d7d 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/43] 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 | 14 ++++++++++++--
 source4/dns_server/dns_server.h |  2 ++
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index c0ae19a4dd4..2373ddee65d 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 *remote_address,
+			    const struct tsocket_address *local_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->remote_address,
+					      state->local_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 830e0703336..86776b06335 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 *remote_address,
+					   const struct tsocket_address *local_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->remote_address,
+				  dns_conn->conn->local_address,
 				  &call->in);
 	if (subreq == NULL) {
 		dns_tcp_terminate_connection(
@@ -534,6 +542,8 @@ 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,
+				  call->src,
+				  sock->dns_socket->local_address,
 				  &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 e623f972316..5395ff95161 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.12.0.246.ga2ecc84866-goog


From fafb6077db49ec29e81f7471061c2d8a1384b78d 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/43] 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 | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/auth/auth_log.c b/auth/auth_log.c
index db46f2b5a7d..3ec8dc89383 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -33,6 +33,42 @@
 #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) {
+		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,6 +89,7 @@ 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;
@@ -62,6 +99,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));
 
@@ -98,7 +136,7 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 
 	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",
@@ -107,6 +145,7 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 		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,
-- 
2.12.0.246.ga2ecc84866-goog


From ed712e5716172a9b36f08ec155a29c061249e1cb 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/43] 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                     |  4 +++-
 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, 84 insertions(+), 4 deletions(-)

diff --git a/auth/auth_log.c b/auth/auth_log.c
index 3ec8dc89383..5a0d8683352 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -171,6 +171,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;
@@ -196,11 +197,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 67fc6bcb746..999d05cf371 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 d97d3b4e4ac..d275976c6da 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 7bd893266b9..e9fab5f30c1 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 55352417e99..26c9817d5df 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 f063f7b358b..017181a3622 100644
--- a/auth/gensec/spnego.c
+++ b/auth/gensec/spnego.c
@@ -1651,6 +1651,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 
@@ -1678,6 +1689,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 85d204b38e2..8d3b5563ee5 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 abf20bc7dfd..907f8a6cfe1 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -1171,6 +1171,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,
@@ -1198,6 +1213,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 2ae2e23f3d2..7feeb0c7491 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 b54a41bfd5d..49469298964 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.12.0.246.ga2ecc84866-goog


From c751f7f0b0db7be724c30bf79b588ffe04f2e905 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/43] 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 05f3019864c..4033996f462 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.12.0.246.ga2ecc84866-goog


From aac3603a3f510b71b3fd01641383c2bd093cf1e3 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/43] 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 | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c
index 3541926193a..ebe310a28c3 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,6 +367,7 @@ 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;
-- 
2.12.0.246.ga2ecc84866-goog


From 46921a5091b3fd50495087fb9cb337686ef16935 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/43] 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 | 37 +++++++++++++++++++++----------------
 source4/ldap_server/ldap_bind.c |  6 ++++++
 2 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c
index 7f077a5d928..a14883da992 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;
@@ -84,7 +85,7 @@ _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";
+	user_info->service_description = "LDAP";
 
 	user_info->auth_description = "simple bind";
 
@@ -106,22 +107,26 @@ _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;
diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 6a91cabcd72..5f34f746546 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -195,6 +195,12 @@ static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn,
 		return status;
 	}
 
+	status = gensec_set_target_service_description(gensec_security,
+						       "LDAP");
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
 	status = gensec_set_remote_address(gensec_security,
 					   conn->connection->remote_address);
 	if (!NT_STATUS_IS_OK(status)) {
-- 
2.12.0.246.ga2ecc84866-goog


From 32a8c37d90ea4297c613996e2770850c5747e407 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 3 Mar 2017 11:49:43 +1300
Subject: [PATCH 29/43] s4-rpc_server: Log authorization to DCE/RPC for
 anonymous and ncacn_np pass-though

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/rpc_server/dcesrv_auth.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index ece314dcbe6..4b0bfdf1e20 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -46,9 +46,24 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 	NTSTATUS status;
 
 	if (pkt->auth_length == 0) {
+		enum dcerpc_transport_t transport =
+			dcerpc_binding_get_transport(call->conn->endpoint->ep_description);
+		const char *auth_type = derpc_transport_string_by_transport(transport);
 		auth->auth_type = DCERPC_AUTH_TYPE_NONE;
 		auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
 		auth->auth_context_id = 0;
+
+		/*
+		 * Log the authorization to this RPC interface.  This
+		 * covered ncacn_np pass-through auth, and anonymous
+		 * DCE/RPC (eg epmapper, netlogon etc)
+		 */
+		log_successful_authz_event(call->conn->remote_address,
+					   call->conn->local_address,
+					   "DCE/RPC",
+					   auth_type,
+					   call->conn->auth_state.session_info);
+
 		return true;
 	}
 
-- 
2.12.0.246.ga2ecc84866-goog


From 8fa281bbcdc4993e636be2656b556b58eab53c03 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 3 Mar 2017 12:03:04 +1300
Subject: [PATCH 30/43] s3-rpc_server: Log authorization to DCE/RPC for
 anonymous and ncacn_np pass-though

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/rpc_server/srv_pipe.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 446679f39d4..bd56be6b79e 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -825,6 +825,17 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 		p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
 		p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
 		p->auth.auth_context_id = 0;
+
+		/*
+		 * Log the authorization to this RPC interface.  This
+		 * covered ncacn_np pass-through auth, and anonymous
+		 * DCE/RPC (eg epmapper, netlogon etc)
+		 */
+		log_successful_authz_event(p->remote_address,
+					   p->local_address,
+					   table->name,
+					   derpc_transport_string_by_transport(p->transport),
+					   p->session_info);
 	}
 
 	ZERO_STRUCT(u.bind_ack);
-- 
2.12.0.246.ga2ecc84866-goog


From 87d665dc261a024eb07183c3081ddac48f4dc943 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 3 Mar 2017 12:40:04 +1300
Subject: [PATCH 31/43] auth_log: Split up auth/authz logging levels and handle
 anonymous better

We typically do not want a lot of logging of anonymous access, as this is often
simple a preperation for authenticated access, so we make that level 5.

Bad passwords remain at level 2, successful password authentication is level 3
and successful authorization (eg kerberos login to SMB) is level 4.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 auth/auth_log.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/auth/auth_log.c b/auth/auth_log.c
index 5a0d8683352..f390cede6db 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -22,15 +22,20 @@
  * 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
+#define AUTH_SUCCESS_LEVEL 3
+#define AUTHZ_SUCCESS_LEVEL 4
+
+/* 5 is used for both authentication and authorization */
+#define AUTH_ANONYMOUS_LEVEL 5
+#define AUTHZ_ANONYMOUS_LEVEL 5
 
 #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"
+#include "libcli/security/security_token.h"
 
 /*
  * Determine the type of the password supplied for the
@@ -92,8 +97,16 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 	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)) {
+	int debug_level = AUTH_FAILURE_LEVEL;
+
+	if (NT_STATUS_IS_OK(status)) {
+		debug_level = AUTH_SUCCESS_LEVEL;
+		if (dom_sid_equal(sid, &global_sid_Anonymous)) {
+			debug_level = AUTH_ANONYMOUS_LEVEL;
+		}
+	}
+
+	if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
 		return;
 	}
 
@@ -134,7 +147,7 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 					     log_escape(frame, ui->mapped.account_name));
 	}
 
-	DEBUGC( DBGC_AUTH_AUDIT, level, (
+	DEBUGC( DBGC_AUTH_AUDIT, debug_level, (
 		"Auth: [%s,%s] user [%s]\\[%s]"
 		" at [%s] with [%s] status [%s]"
 		" workstation [%s] remote host [%s]"
@@ -180,9 +193,14 @@ 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];
+	int debug_level = AUTHZ_SUCCESS_LEVEL;
+
+	if (security_token_is_anonymous(session_info->security_token)) {
+		debug_level = AUTH_ANONYMOUS_LEVEL;
+	}
 
 	/* set the log level */
-	if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL)) {
+	if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
 		return;
 	}
 
-- 
2.12.0.246.ga2ecc84866-goog


From 34472815a66acd82e6c15280a1ca1b0e1cf29480 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 3 Mar 2017 12:53:06 +1300
Subject: [PATCH 32/43] ldap_server: Log access without a bind

This can be over the privileged ldapi socket, or just as the implicit anonymous access

However, do not log for setting up StartTLS, or a rootDSE search.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/ldap_server/ldap_backend.c | 52 ++++++++++++++++++++++++++++++++++++++
 source4/ldap_server/ldap_bind.c    |  6 ++++-
 source4/ldap_server/ldap_server.h  |  1 +
 source4/ldap_server/wscript_build  |  2 +-
 4 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c
index dc6a44c8237..b023eb4dd7c 100644
--- a/source4/ldap_server/ldap_backend.c
+++ b/source4/ldap_server/ldap_backend.c
@@ -24,6 +24,7 @@
 #include "auth/credentials/credentials.h"
 #include "auth/gensec/gensec.h"
 #include "auth/gensec/gensec_internal.h" /* TODO: remove this */
+#include "auth/common_auth.h"
 #include "param/param.h"
 #include "smbd/service_stream.h"
 #include "dsdb/samdb/samdb.h"
@@ -1227,6 +1228,7 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
 	unsigned int i;
 	struct ldap_message *msg = call->request;
 	NTSTATUS status;
+	bool log = true;
 
 	/* Check for undecoded critical extensions */
 	for (i=0; msg->controls && msg->controls[i]; i++) {
@@ -1238,6 +1240,56 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
 		}
 	}
 
+	if (call->conn->authz_logged == false) {
+
+		/*
+		 * We do not want to log anonymous access if the query
+		 * is just for the rootDSE, or it is a startTLS or a
+		 * Bind.
+		 *
+		 * A rootDSE search could also be done over
+		 * CLDAP anonymously for example, so these don't
+		 * really count.
+		 * Essentially we want to know about
+		 * access beyond that normally done prior to a
+		 * bind.
+		 */
+
+		switch(call->request->type) {
+		case LDAP_TAG_BindRequest:
+			log = false;
+			break;
+		case LDAP_TAG_ExtendedResponse: {
+			struct ldap_ExtendedRequest *req = &call->request->r.ExtendedRequest;
+			if (strcmp(req->oid, LDB_EXTENDED_START_TLS_OID) == 0) {
+				log = false;
+			}
+			break;
+		}
+		case LDAP_TAG_SearchRequest: {
+			struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
+			if (req->scope == LDAP_SEARCH_SCOPE_BASE) {
+				if (req->basedn[0] == '\0') {
+					log = false;
+				}
+			}
+			break;
+		}
+		default:
+			break;
+		}
+
+		if (log) {
+			log_successful_authz_event(call->conn->connection->remote_address,
+						   call->conn->connection->local_address,
+						   "LDAP",
+						   "no bind",
+						   call->conn->session_info);
+
+			call->conn->authz_logged = true;
+		}
+	}
+
 	switch(call->request->type) {
 	case LDAP_TAG_BindRequest:
 		return ldapsrv_BindRequest(call);
diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 5f34f746546..47cc64f9dda 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -109,6 +109,8 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 		talloc_unlink(call->conn, call->conn->session_info);
 		call->conn->session_info = talloc_steal(call->conn, session_info);
 
+		call->conn->authz_logged = true;
+
 		/* don't leak the old LDB */
 		talloc_unlink(call->conn, call->conn->ldb);
 
@@ -381,7 +383,9 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 				
 				/* don't leak the old LDB */
 				talloc_unlink(conn, conn->ldb);
-				
+
+				call->conn->authz_logged = true;
+
 				status = ldapsrv_backend_Init(conn);		
 				
 				if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h
index 86e5d34f21e..337c974aaae 100644
--- a/source4/ldap_server/ldap_server.h
+++ b/source4/ldap_server/ldap_server.h
@@ -46,6 +46,7 @@ struct ldapsrv_connection {
 	bool global_catalog;
 	bool is_privileged;
 	enum ldap_server_require_strong_auth require_strong_auth;
+	bool authz_logged;
 
 	struct {
 		int initial_timeout;
diff --git a/source4/ldap_server/wscript_build b/source4/ldap_server/wscript_build
index 32a77c79c91..881cc893c72 100644
--- a/source4/ldap_server/wscript_build
+++ b/source4/ldap_server/wscript_build
@@ -6,7 +6,7 @@ bld.SAMBA_MODULE('service_ldap',
 	autoproto='proto.h',
 	subsystem='service',
 	init_function='server_service_ldap_init',
-	deps='samba-credentials cli-ldap samdb process_model gensec samba-hostconfig samba_server_gensec',
+	deps='samba-credentials cli-ldap samdb process_model gensec samba-hostconfig samba_server_gensec common_auth',
 	internal_module=False,
 	enabled=bld.AD_DC_BUILD_IS_ENABLED()
 	)
-- 
2.12.0.246.ga2ecc84866-goog


From bb32cf05cb3e14d16c7a4ce0ae4cb968196db7c1 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 6 Mar 2017 11:54:56 +1300
Subject: [PATCH 33/43] gensec: Return upper-case NTLMSSP for NTLMSSP auth

By making this a #define, we can rely on it in other places.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 auth/gensec/gensec.h          | 1 +
 auth/ntlmssp/ntlmssp.c        | 6 ++++++
 auth/ntlmssp/ntlmssp_server.c | 4 ++--
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h
index e9fab5f30c1..bc96e697de4 100644
--- a/auth/gensec/gensec.h
+++ b/auth/gensec/gensec.h
@@ -35,6 +35,7 @@
 #define GENSEC_OID_KERBEROS5_USER2USER "1.2.840.113554.1.2.2.3"
 
 #define GENSEC_FINAL_AUTH_TYPE_KRB5 "krb5"
+#define GENSEC_FINAL_AUTH_TYPE_NTLMSSP "NTLMSSP"
 
 enum gensec_priority {
 	GENSEC_SPNEGO = 90,
diff --git a/auth/ntlmssp/ntlmssp.c b/auth/ntlmssp/ntlmssp.c
index 3283c964470..6f7c089467f 100644
--- a/auth/ntlmssp/ntlmssp.c
+++ b/auth/ntlmssp/ntlmssp.c
@@ -207,6 +207,11 @@ static NTSTATUS gensec_ntlmssp_may_reset_crypto(struct gensec_security *gensec_s
 	return NT_STATUS_OK;
 }
 
+static const char *gensec_ntlmssp_final_auth_type(struct gensec_security *gensec_security)
+{
+	return GENSEC_FINAL_AUTH_TYPE_NTLMSSP;
+}
+
 static const char *gensec_ntlmssp_oids[] = {
 	GENSEC_OID_NTLMSSP,
 	NULL
@@ -232,6 +237,7 @@ static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
 	.session_key	= gensec_ntlmssp_session_key,
 	.session_info   = gensec_ntlmssp_session_info,
 	.have_feature   = gensec_ntlmssp_have_feature,
+	.final_auth_type = gensec_ntlmssp_final_auth_type,
 	.enabled        = true,
 	.priority       = GENSEC_NTLMSSP
 };
diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c
index 8d3b5563ee5..38c38d4c1d9 100644
--- a/auth/ntlmssp/ntlmssp_server.c
+++ b/auth/ntlmssp/ntlmssp_server.c
@@ -723,8 +723,8 @@ static NTSTATUS ntlmssp_server_check_password(struct gensec_security *gensec_sec
 		= gensec_get_target_service_description(gensec_security);
 
 	/*
-	 * This will just be the string "ntlmssp" from
-	 * gensec_ntlmssp_security_ops, but ensures it stays in sync
+	 * This will just be the string "NTLMSSP" from
+	 * gensec_ntlmssp_final_auth_type, but ensures it stays in sync
 	 * with the same use in the authorization logging triggered by
 	 * gensec_session_info() later
 	 */
-- 
2.12.0.246.ga2ecc84866-goog


From 018fca6a005442688c8e4afedc0e34cdd7bb4909 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 6 Mar 2017 12:13:47 +1300
Subject: [PATCH 34/43] auth: Log SMB and SMB2 in upper-case, these are
 acronyms and should be logged this way

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/smbd/sesssetup.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index a570849d5c8..0cc49d916f8 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -99,7 +99,7 @@ static NTSTATUS check_guest_password(const struct tsocket_address *remote_addres
 					 chal);
 
 	if (!make_user_info_guest(talloc_tos(), remote_address, local_address,
-				  "smb", &user_info)) {
+				  "SMB", &user_info)) {
 		TALLOC_FREE(auth_context);
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -905,7 +905,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
 							 domain,
 							 sconn->remote_address,
 							 sconn->local_address,
-							 "smb",
+							 "SMB",
 							 lm_resp, nt_resp);
 		user_info->auth_description = "bare-NTLM";
 
@@ -930,7 +930,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
 						      user, domain,
 						      sconn->remote_address,
 						      sconn->local_address,
-						      "smb",
+						      "SMB",
 						      chal,
 						      plaintext_password)) {
 				nt_status = NT_STATUS_NO_MEMORY;
-- 
2.12.0.246.ga2ecc84866-goog


From 04cfa248a7346ce0eb7e512f7f9a8266579ad417 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 6 Mar 2017 14:10:17 +1300
Subject: [PATCH 35/43] auth: Log the transport connection for the
 authorization

We also log if a simple bind was over TLS, as this particular case matters to a lot of folks

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 auth/auth_log.c                     |  1 +
 auth/common_auth.h                  |  7 +++++++
 auth/gensec/gensec.c                | 13 +++++++++++++
 auth/gensec/gensec.h                |  2 ++
 source3/auth/auth_generic.c         |  1 +
 source3/rpc_server/srv_pipe.c       |  6 ++++++
 source3/smbd/sesssetup.c            |  1 +
 source3/smbd/smb2_sesssetup.c       |  1 +
 source4/auth/auth.h                 |  1 +
 source4/auth/ntlm/auth_simple.c     | 12 +++++++++++-
 source4/ldap_server/ldap_backend.c  |  6 ++++++
 source4/ldap_server/ldap_bind.c     |  9 ++++++++-
 source4/rpc_server/dcesrv_auth.c    |  5 +++++
 source4/smb_server/smb/sesssetup.c  |  2 ++
 source4/smb_server/smb2/sesssetup.c |  1 +
 15 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/auth/auth_log.c b/auth/auth_log.c
index f390cede6db..e2512f7d135 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -185,6 +185,7 @@ void log_successful_authz_event(const struct tsocket_address *remote,
 				const struct tsocket_address *local,
 				const char *service_description,
 				const char *auth_type,
+				const char *transport_protection,
 				struct auth_session_info *session_info)
 {
 	TALLOC_CTX *frame = NULL;
diff --git a/auth/common_auth.h b/auth/common_auth.h
index 999d05cf371..2568237d1f9 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -146,6 +146,12 @@ struct auth4_context {
 					      struct auth_session_info **session_info);
 };
 
+#define AUTHZ_TRANSPORT_PROTECTION_NONE "NONE"
+#define AUTHZ_TRANSPORT_PROTECTION_SMB "SMB"
+#define AUTHZ_TRANSPORT_PROTECTION_TLS "TLS"
+#define AUTHZ_TRANSPORT_PROTECTION_SEAL "SEAL"
+#define AUTHZ_TRANSPORT_PROTECTION_SIGN "SIGN"
+
 void log_authentication_event(const struct auth_usersupplied_info *ui,
 			      NTSTATUS status,
 			      const char *account_name,
@@ -157,5 +163,6 @@ void log_successful_authz_event(const struct tsocket_address *remote,
 				const struct tsocket_address *local,
 				const char *service_description,
 				const char *auth_type,
+				const char *transport_protection,
 				struct auth_session_info *session_info);
 #endif
diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index d275976c6da..14fd9f46ef7 100644
--- a/auth/gensec/gensec.c
+++ b/auth/gensec/gensec.c
@@ -221,9 +221,22 @@ static void log_successful_gensec_authz_event(struct gensec_security *gensec_sec
 		= gensec_get_target_service_description(gensec_security);
 	const char *final_auth_type
 		= gensec_final_auth_type(gensec_security);
+	const char *transport_protection = NULL;
+	if (gensec_security->want_features & GENSEC_FEATURE_SMB_TRANSPORT) {
+		transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
+	} else if (gensec_security->want_features & GENSEC_FEATURE_LDAPS_TRANSPORT) {
+		transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
+	} else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
+		transport_protection = AUTHZ_TRANSPORT_PROTECTION_SEAL;
+	} else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
+		transport_protection = AUTHZ_TRANSPORT_PROTECTION_SIGN;
+	} else {
+		transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
+	}
 	log_successful_authz_event(remote, local,
 				   service_description,
 				   final_auth_type,
+				   transport_protection,
 				   session_info);
 }
 
diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h
index bc96e697de4..6764ee5e461 100644
--- a/auth/gensec/gensec.h
+++ b/auth/gensec/gensec.h
@@ -68,6 +68,8 @@ struct gensec_target {
 #define GENSEC_FEATURE_NTLM_CCACHE	0x00000200
 #define GENSEC_FEATURE_LDAP_STYLE	0x00000400
 #define GENSEC_FEATURE_NO_AUTHZ_LOG	0x00000800
+#define GENSEC_FEATURE_SMB_TRANSPORT	0x00001000
+#define GENSEC_FEATURE_LDAPS_TRANSPORT	0x00002000
 
 #define GENSEC_EXPIRE_TIME_INFINITY (NTTIME)0x8000000000000000LL
 
diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 4033996f462..2e429e800d4 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -437,6 +437,7 @@ NTSTATUS auth_check_password_session_info(struct auth4_context *auth_context,
 				   user_info->local_host,
 				   user_info->service_description,
 				   user_info->auth_description,
+				   AUTHZ_TRANSPORT_PROTECTION_SMB,
 				   *session_info);
 
 	return nt_status;
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index bd56be6b79e..c8b0fdccf42 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -822,6 +822,11 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 			goto err_exit;
 		}
 	} else {
+		const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
+		if (p->transport == NCACN_NP) {
+			transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
+		}
+
 		p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
 		p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
 		p->auth.auth_context_id = 0;
@@ -835,6 +840,7 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 					   p->local_address,
 					   table->name,
 					   derpc_transport_string_by_transport(p->transport),
+					   transport_protection,
 					   p->session_info);
 	}
 
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 0cc49d916f8..2ed5a4c7ed7 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -263,6 +263,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 
 		gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
 		gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
+		gensec_want_feature(auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
 
 		status = gensec_start_mech_by_oid(auth->gensec,
 						  GENSEC_OID_SPNEGO);
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index 52462882771..53cd7ded2b0 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -864,6 +864,7 @@ auth:
 
 		gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SESSION_KEY);
 		gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
+		gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
 
 		status = gensec_start_mech_by_oid(state->auth->gensec,
 						  GENSEC_OID_SPNEGO);
diff --git a/source4/auth/auth.h b/source4/auth/auth.h
index d4be60e2e2a..88f88a40aaa 100644
--- a/source4/auth/auth.h
+++ b/source4/auth/auth.h
@@ -164,6 +164,7 @@ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 				       struct loadparm_context *lp_ctx,
 				       struct tsocket_address *remote_address,
 				       struct tsocket_address *local_address,
+				       bool using_tls,
 				       const char *dn,
 				       const char *password,
 				       struct auth_session_info **session_info);
diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c
index a14883da992..4e5780f7a10 100644
--- a/source4/auth/ntlm/auth_simple.c
+++ b/source4/auth/ntlm/auth_simple.c
@@ -35,6 +35,7 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 						struct loadparm_context *lp_ctx,
 						struct tsocket_address *remote_address,
 						struct tsocket_address *local_address,
+						bool using_tls,
 						const char *dn,
 						const char *password,
 						struct auth_session_info **session_info)
@@ -47,6 +48,10 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 	const char *nt4_domain;
 	const char *nt4_username;
 	uint32_t flags = 0;
+	const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
+	if (using_tls) {
+		transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
+	}
 
 	if (!tmp_ctx) {
 		return NT_STATUS_NO_MEMORY;
@@ -87,7 +92,11 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 
 	user_info->service_description = "LDAP";
 
-	user_info->auth_description = "simple bind";
+	if (using_tls) {
+		user_info->auth_description = "simple bind";
+	} else {
+		user_info->auth_description = "simple bind/TLS";
+	}
 
 	user_info->password_state = AUTH_PASSWORD_PLAIN;
 	user_info->password.plaintext = talloc_strdup(user_info, password);
@@ -126,6 +135,7 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 				   local_address,
 				   "LDAP",
 				   "simple bind",
+				   transport_protection,
 				   *session_info);
 
 	talloc_free(tmp_ctx);
diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c
index b023eb4dd7c..7aa51f293ed 100644
--- a/source4/ldap_server/ldap_backend.c
+++ b/source4/ldap_server/ldap_backend.c
@@ -1280,10 +1280,16 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
 		}
 
 		if (log) {
+			const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
+			if (call->conn->sockets.active == call->conn->sockets.tls) {
+				transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
+			}
+
 			log_successful_authz_event(call->conn->connection->remote_address,
 						   call->conn->connection->local_address,
 						   "LDAP",
 						   "no bind",
+						   transport_protection,
 						   call->conn->session_info);
 
 			call->conn->authz_logged = true;
diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 47cc64f9dda..181c2c507b6 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -73,6 +73,8 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 
 	NTSTATUS status;
 
+	bool using_tls = call->conn->sockets.active == call->conn->sockets.tls;
+
 	DEBUG(10, ("BindSimple dn: %s\n",req->dn));
 
 	reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
@@ -83,7 +85,7 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 	if (req->dn != NULL &&
 	    strlen(req->dn) != 0 &&
 	    call->conn->require_strong_auth > LDAP_SERVER_REQUIRE_STRONG_AUTH_NO &&
-	    call->conn->sockets.active != call->conn->sockets.tls)
+	    !using_tls)
 	{
 		status = NT_STATUS_NETWORK_ACCESS_DENIED;
 		result = LDAP_STRONG_AUTH_REQUIRED;
@@ -98,6 +100,7 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 					       call->conn->lp_ctx,
 					       call->conn->connection->remote_address,
 					       call->conn->connection->local_address,
+					       using_tls,
 					       req->dn,
 					       req->creds.password,
 					       &session_info);
@@ -218,6 +221,10 @@ static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn,
 	gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
 	gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAP_STYLE);
 
+	if (conn->sockets.active == conn->sockets.tls) {
+		gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAPS_TRANSPORT);
+	}
+
 	status = gensec_start_mech_by_sasl_name(gensec_security, sasl_mech);
 
 	if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 4b0bfdf1e20..1ebb5143b93 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -49,6 +49,10 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 		enum dcerpc_transport_t transport =
 			dcerpc_binding_get_transport(call->conn->endpoint->ep_description);
 		const char *auth_type = derpc_transport_string_by_transport(transport);
+		const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
+		if (transport == NCACN_NP) {
+			transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
+		}
 		auth->auth_type = DCERPC_AUTH_TYPE_NONE;
 		auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
 		auth->auth_context_id = 0;
@@ -62,6 +66,7 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 					   call->conn->local_address,
 					   "DCE/RPC",
 					   auth_type,
+					   transport_protection,
 					   call->conn->auth_state.session_info);
 
 		return true;
diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c
index ebe310a28c3..ce73a02c2d5 100644
--- a/source4/smb_server/smb/sesssetup.c
+++ b/source4/smb_server/smb/sesssetup.c
@@ -58,6 +58,7 @@ void smbsrv_not_spengo_sesssetup_authz_log(struct smbsrv_request *req,
 				   local_address,
 				   "SMB",
 				   "bare-NTLM",
+				   AUTHZ_TRANSPORT_PROTECTION_SMB,
 				   session_info);
 
 	talloc_free(frame);
@@ -507,6 +508,7 @@ static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *se
 		}
 
 		gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
+		gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SMB_TRANSPORT);
 
 		remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
 							req);
diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c
index 7d92aa28697..d87651d7ce5 100644
--- a/source4/smb_server/smb2/sesssetup.c
+++ b/source4/smb_server/smb2/sesssetup.c
@@ -145,6 +145,7 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses
 		}
 
 		gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
+		gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SMB_TRANSPORT);
 
 		remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
 							req);
-- 
2.12.0.246.ga2ecc84866-goog


From a1856d286d30a0eb2d4f7c598d0b4d592cbc6858 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 6 Mar 2017 12:11:18 +1300
Subject: [PATCH 36/43] auth: Add SID_NT_NTLM_AUTHENTICATION / S-1-5-64-10 to
 the token during NTLM auth

So far this is only on the AD DC

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 auth/common_auth.h                       |  1 +
 auth/ntlmssp/gensec_ntlmssp_server.c     |  1 +
 source3/auth/auth_generic.c              |  3 ++-
 source4/auth/pyauth.c                    |  1 +
 source4/auth/session.c                   |  9 +++++++++
 source4/dsdb/tests/python/token_group.py | 16 +++++++++++++++-
 source4/selftest/tests.py                |  3 ++-
 7 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/auth/common_auth.h b/auth/common_auth.h
index 2568237d1f9..331f112858f 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -39,6 +39,7 @@ enum auth_password_state {
 #define AUTH_SESSION_INFO_AUTHENTICATED      0x02 /* Add the user to the 'authenticated users' group */
 #define AUTH_SESSION_INFO_SIMPLE_PRIVILEGES  0x04 /* Use a trivial map between users and privilages, rather than a DB */
 #define AUTH_SESSION_INFO_UNIX_TOKEN         0x08 /* The returned token must have the unix_token and unix_info elements provided */
+#define AUTH_SESSION_INFO_NTLM               0x10 /* The returned token must have authenticated-with-NTLM flag set */
 
 struct auth_usersupplied_info
 {
diff --git a/auth/ntlmssp/gensec_ntlmssp_server.c b/auth/ntlmssp/gensec_ntlmssp_server.c
index da0cd50bac2..561c7cff5bd 100644
--- a/auth/ntlmssp/gensec_ntlmssp_server.c
+++ b/auth/ntlmssp/gensec_ntlmssp_server.c
@@ -62,6 +62,7 @@ NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
 	}
 
 	session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
+	session_info_flags |= AUTH_SESSION_INFO_NTLM;
 
 	if (gensec_security->auth_context && gensec_security->auth_context->generate_session_info) {
 		nt_status = gensec_security->auth_context->generate_session_info(gensec_security->auth_context, mem_ctx, 
diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 2e429e800d4..5631c856bff 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -423,7 +423,8 @@ NTSTATUS auth_check_password_session_info(struct auth4_context *auth_context,
 								server_info,
 								user_info->client.account_name,
 								AUTH_SESSION_INFO_UNIX_TOKEN |
-								AUTH_SESSION_INFO_DEFAULT_GROUPS,
+								AUTH_SESSION_INFO_DEFAULT_GROUPS |
+								AUTH_SESSION_INFO_NTLM,
 								session_info);
 		TALLOC_FREE(server_info);
 	}
diff --git a/source4/auth/pyauth.c b/source4/auth/pyauth.c
index 61db907b902..7255b13e8ae 100644
--- a/source4/auth/pyauth.c
+++ b/source4/auth/pyauth.c
@@ -322,5 +322,6 @@ void initauth(void)
 	ADD_FLAG(AUTH_SESSION_INFO_DEFAULT_GROUPS);
 	ADD_FLAG(AUTH_SESSION_INFO_AUTHENTICATED);
 	ADD_FLAG(AUTH_SESSION_INFO_SIMPLE_PRIVILEGES);
+	ADD_FLAG(AUTH_SESSION_INFO_NTLM);
 
 }
diff --git a/source4/auth/session.c b/source4/auth/session.c
index 3d8714c3e1f..982d51d65e9 100644
--- a/source4/auth/session.c
+++ b/source4/auth/session.c
@@ -154,6 +154,15 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
 		num_sids++;
 	}
 
+	if (session_info_flags & AUTH_SESSION_INFO_NTLM) {
+		sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 1);
+		NT_STATUS_HAVE_NO_MEMORY(sids);
+
+		if (!dom_sid_parse(SID_NT_NTLM_AUTHENTICATION, &sids[num_sids])) {
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+		num_sids++;
+	}
 
 
 	if (num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(anonymous_sid, &sids[PRIMARY_USER_SID_INDEX])) {
diff --git a/source4/dsdb/tests/python/token_group.py b/source4/dsdb/tests/python/token_group.py
index e3a75863163..6a9c8677541 100755
--- a/source4/dsdb/tests/python/token_group.py
+++ b/source4/dsdb/tests/python/token_group.py
@@ -24,7 +24,7 @@ from samba.dsdb import GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GRO
 import samba.tests
 from samba.tests import delete_force
 from samba.dcerpc import samr, security
-from samba.auth import AUTH_SESSION_INFO_DEFAULT_GROUPS, AUTH_SESSION_INFO_AUTHENTICATED, AUTH_SESSION_INFO_SIMPLE_PRIVILEGES
+from samba.auth import AUTH_SESSION_INFO_DEFAULT_GROUPS, AUTH_SESSION_INFO_AUTHENTICATED, AUTH_SESSION_INFO_SIMPLE_PRIVILEGES, AUTH_SESSION_INFO_NTLM
 
 
 parser = optparse.OptionParser("token_group.py [options] <host>")
@@ -71,6 +71,9 @@ class StaticTokenTest(samba.tests.TestCase):
         session_info_flags = ( AUTH_SESSION_INFO_DEFAULT_GROUPS |
                                AUTH_SESSION_INFO_AUTHENTICATED |
                                AUTH_SESSION_INFO_SIMPLE_PRIVILEGES)
+        if creds.get_kerberos_state() == DONT_USE_KERBEROS:
+            session_info_flags |= AUTH_SESSION_INFO_NTLM
+
         session = samba.auth.user_session(self.ldb, lp_ctx=lp, dn=self.user_sid_dn,
                                           session_info_flags=session_info_flags)
 
@@ -118,6 +121,9 @@ class StaticTokenTest(samba.tests.TestCase):
             self.fail(msg="calculated groups don't match against user DN tokenGroups")
 
     def test_pac_groups(self):
+        if creds.get_kerberos_state() == DONT_USE_KERBEROS:
+            self.skipTest("Kerberos disabled, skipping PAC test")
+
         settings = {}
         settings["lp_ctx"] = lp
         settings["target_hostname"] = lp.get("netbios name")
@@ -276,6 +282,10 @@ class DynamicTokenTest(samba.tests.TestCase):
         session_info_flags = ( AUTH_SESSION_INFO_DEFAULT_GROUPS |
                                AUTH_SESSION_INFO_AUTHENTICATED |
                                AUTH_SESSION_INFO_SIMPLE_PRIVILEGES)
+
+        if creds.get_kerberos_state() == DONT_USE_KERBEROS:
+            session_info_flags |= AUTH_SESSION_INFO_NTLM
+
         session = samba.auth.user_session(self.ldb, lp_ctx=lp, dn=self.user_sid_dn,
                                           session_info_flags=session_info_flags)
 
@@ -336,6 +346,10 @@ class DynamicTokenTest(samba.tests.TestCase):
 
         sidset1 = set(dn_tokengroups)
         sidset2 = set(self.user_sids)
+
+        # The SIDs on the DN do not include the NTLM authentication SID
+        sidset2.discard(samba.dcerpc.security.SID_NT_NTLM_AUTHENTICATION)
+
         if len(sidset1.difference(sidset2)):
             print("token sids don't match")
             print("difference : %s" % sidset1.difference(sidset2))
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index ac601f5f217..0afa5895f10 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -585,7 +585,8 @@ planoldpythontestsuite("ad_dc_ntvfs", "samba.tests.dcerpc.dnsserver", extra_args
 planoldpythontestsuite("ad_dc", "samba.tests.dcerpc.dnsserver", extra_args=['-U"$USERNAME%$PASSWORD"'])
 planoldpythontestsuite("ad_dc", "samba.tests.dcerpc.raw_protocol", extra_args=['-U"$USERNAME%$PASSWORD"'])
 plantestsuite_loadlist("samba4.ldap.python(ad_dc_ntvfs)", "ad_dc_ntvfs", [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
-plantestsuite_loadlist("samba4.tokengroups.python(ad_dc_ntvfs)", "ad_dc_ntvfs:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/token_group.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
+plantestsuite_loadlist("samba4.tokengroups.krb5.python(ad_dc_ntvfs)", "ad_dc_ntvfs:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/token_group.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '-k', 'yes', '$LOADLIST', '$LISTOPT'])
+plantestsuite_loadlist("samba4.tokengroups.ntlm.python(ad_dc_ntvfs)", "ad_dc_ntvfs:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/token_group.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '-k', 'no', '$LOADLIST', '$LISTOPT'])
 plantestsuite("samba4.sam.python(fl2008r2dc)", "fl2008r2dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/sam.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN'])
 plantestsuite("samba4.sam.python(ad_dc_ntvfs)", "ad_dc_ntvfs", [python, os.path.join(samba4srcdir, "dsdb/tests/python/sam.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN'])
 plantestsuite("samba4.user_account_control.python(ad_dc_ntvfs)", "ad_dc_ntvfs", [python, os.path.join(samba4srcdir, "dsdb/tests/python/user_account_control.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN'])
-- 
2.12.0.246.ga2ecc84866-goog


From 8cb249c31eaa9affc6ccdfaac088c4b298de4f3e Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary at catalyst.net.nz>
Date: Mon, 6 Mar 2017 16:16:51 +1300
Subject: [PATCH 37/43] auth_log: Add JSON logging of Authorisation and
 Authentications

---
 auth/auth_log.c        | 650 +++++++++++++++++++++++++++++++++++++++++++++----
 auth/wscript_build     |   2 +-
 auth/wscript_configure |  11 +
 lib/util/debug.c       |   1 +
 lib/util/debug.h       |   2 +-
 wscript                |   1 +
 6 files changed, 612 insertions(+), 55 deletions(-)
 create mode 100644 auth/wscript_configure

diff --git a/auth/auth_log.c b/auth/auth_log.c
index e2512f7d135..d69c393e59f 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -30,6 +30,21 @@
 #define AUTH_ANONYMOUS_LEVEL 5
 #define AUTHZ_ANONYMOUS_LEVEL 5
 
+#define AUTHZ_JSON_TYPE "Authorization"
+#define AUTH_JSON_TYPE  "Authentication"
+
+/*
+ * JSON message version numbers
+ *
+ * If adding a field increment the minor version
+ * If removing or changing the format/meaning of a field
+ * increment the major version.
+ */
+#define AUTH_MAJOR 1
+#define AUTH_MINOR 0
+#define AUTHZ_MAJOR 1
+#define AUTHZ_MINOR 0
+
 #include "includes.h"
 #include "../lib/tsocket/tsocket.h"
 #include "common_auth.h"
@@ -42,6 +57,471 @@
  * authorisation attempt.
  *
  */
+static const char* get_password_type(const struct auth_usersupplied_info *ui);
+
+#ifdef HAVE_JSON_GLIB_1_0
+
+#include "system/time.h"
+#include <glib-object.h>
+#include <json-glib/json-glib.h>
+
+/*
+ * Context required by the JSON generation
+ *  routines
+ *
+ */
+struct json_context {
+	JsonBuilder *builder;
+	bool error;
+};
+/*
+ * Create a new json logging context.
+ *
+ * Free with a call to free_json_context
+ *
+ */
+static struct json_context get_json_context( void) {
+
+	struct json_context context;
+	context.error = false;
+
+	context.builder = json_builder_new();
+	if (context.builder == NULL) {
+		context.error = true;
+		DBG_ERR("Unable to create json_builder\n");
+		return context;
+	}
+
+	return context;
+}
+
+/*
+ * free a previously created json_context
+ *
+ */
+static void free_json_context(struct json_context *context)
+{
+	if (context->builder) {
+		g_object_unref(context->builder);
+		context->builder = NULL;
+	}
+}
+
+/*
+ * Start a json object, with the supplied name
+ *
+ */
+static void start_object(struct json_context *context,
+			 const char* name)
+{
+	JsonBuilder *r = NULL;
+
+	if (context->error) {
+		return;
+	}
+
+	if (name) {
+		r = json_builder_set_member_name( context->builder, name);
+		if (r == NULL) {
+			DBG_ERR("Unable to set member name\n");
+			context->error = true;
+			return;
+		}
+	}
+
+	r = json_builder_begin_object( context->builder);
+	if (r == NULL) {
+		DBG_ERR("Unable to begin object\n");
+		context->error = true;
+		return;
+	}
+}
+
+/*
+ * Close the currently active JSON object
+ *
+ */
+static void end_object(struct json_context *context)
+{
+	JsonBuilder *r = NULL;
+
+	if (context->error) {
+		return;
+	}
+
+	r = json_builder_end_object( context->builder);
+	if (r == NULL) {
+		DBG_ERR("Unable to end object\n");
+		context->error = true;
+	}
+}
+
+/*
+ * Output a JSON pair with name name and integer value value
+ *
+ */
+static void add_int(struct json_context *context,
+		    const char* name,
+		    const int value)
+{
+	JsonBuilder *r = NULL;
+
+	if (context->error) {
+		return;
+	}
+
+	r = json_builder_set_member_name( context->builder, name);
+	if (r == NULL) {
+		DBG_ERR("Unable to set name [%s] value [%d]\n", name, value);
+		context->error = true;
+		return;
+	}
+	r = json_builder_add_int_value( context->builder, value);
+	if (r == NULL) {
+		DBG_ERR("Unable set value for [%s] value [%d]", name,  value);
+		context->error = true;
+		return;
+	}
+}
+
+/*
+ * Output a JSON pair with name name and string value value
+ *
+ */
+static void add_string(struct json_context *context,
+		       const char* name,
+		       const char* value)
+{
+	JsonBuilder *r = NULL;
+
+	if (context->error) {
+		return;
+	}
+
+	r = json_builder_set_member_name( context->builder, name);
+	if (r == NULL) {
+		DBG_ERR("Unable to set name [%s] value [%s]", name, value);
+		context->error = true;
+		return;
+	}
+	if (value) {
+		r = json_builder_add_string_value( context->builder, value);
+		if (r == NULL) {
+			DBG_ERR("Unable to set value for [%s] value [%s]",
+				name, value);
+			context->error = true;
+			return;
+		}
+	} else {
+		json_builder_add_null_value( context->builder);
+		if (r == NULL) {
+			DBG_ERR("Unable to set null value for [%s]", name);
+			context->error = true;
+			return;
+		}
+	}
+}
+
+/*
+ * Output a version object
+ *
+ * "version":{"major":1,"minor":0}
+ *
+ */
+static void add_version( struct json_context *context, int major, int minor)
+{
+	start_object(context, "version");
+	add_int(context, "major", major);
+	add_int(context, "minor", minor);
+	end_object(context);
+}
+
+/*
+ * Output the current date and time as a timestamp in ISO 8601 format
+ *
+ * "timestamp":"2017-03-06T17:18:04.455081+1300"
+ *
+ */
+static void add_timestamp( struct json_context *context)
+{
+	char buffer[40];
+	char timestamp[50];
+	char tz[10];
+	struct tm* tm_info;
+	struct timeval tv;
+	int r;
+
+	if (context->error) {
+		return;
+	}
+
+	r = gettimeofday(&tv, NULL);
+	if (r) {
+		DBG_ERR("Unable to get time of day: (%d) %s\n",
+			errno,
+			strerror( errno));
+		context->error = true;
+		return;
+	}
+
+	tm_info = localtime(&tv.tv_sec);
+	if (tm_info == NULL) {
+		DBG_ERR("Unable to determine local time\n");
+		context->error = true;
+		return;
+	}
+
+	strftime(buffer, sizeof(buffer), "%Y-%m-%dT%T", tm_info);
+	strftime(tz, sizeof(tz), "%z", tm_info);
+	snprintf(timestamp, sizeof(timestamp),"%s.%06ld%s",
+		 buffer, tv.tv_usec, tz);
+	add_string(context,"timestamp", timestamp);
+}
+
+
+/*
+ * Output an address pair, with name name.
+ *
+ * "localAddress":"ipv6::::0"
+ *
+ */
+static void add_address(struct json_context *context,
+			const char *name,
+			const struct tsocket_address *address)
+{
+	char *s = NULL;
+	TALLOC_CTX *frame = NULL;
+
+	if (context->error) {
+		return;
+	}
+
+	s = tsocket_address_string(address, frame);
+	add_string(context, name, s);
+	talloc_free(frame);
+
+}
+
+/*
+ * Output a SID with name name
+ *
+ * "sid":"S-1-5-18"
+ *
+ */
+static void add_sid(struct json_context *context,
+		    const char *name,
+		    const struct dom_sid *sid)
+{
+	char sid_buf[DOM_SID_STR_BUFLEN];
+
+	if (context->error) {
+		return;
+	}
+
+	dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
+	add_string(context, name, sid_buf);
+}
+
+/*
+ * Write the json object to the debug lines.
+ *
+ */
+static void log_json(struct json_context *context,
+		     const char *type, int debug_class, int debug_level)
+{
+	JsonGenerator *gen = NULL;
+	JsonNode *root = NULL;
+	gchar *json = NULL;
+
+	if( context->error) {
+		return;
+	}
+
+	gen = json_generator_new();
+	if (gen == NULL) {
+		DBG_ERR( "Unable to create a JSON gemerator");
+		context->error = true;
+		goto exit;
+	}
+
+	root = json_builder_get_root( context->builder);
+	if (root == NULL) {
+		DBG_ERR( "Unable to get root object");
+		context->error = true;
+		goto exit;
+	}
+
+
+	// set root copies the root, so it can be deleted
+	json_generator_set_root( gen, root);
+	json_node_free( root);
+
+	json = json_generator_to_data( gen, NULL);
+
+	DEBUGC( debug_class, debug_level, ( "JSON %s: %s\n", type, json));
+
+exit:
+	if (json)
+		g_free( json);
+	if( gen)
+		g_object_unref( gen);
+}
+
+/*
+ * Write a machine parsable json formatted authentication log entry.
+ *
+ * IF removing or changing the format/meaning of a field please update the
+ *    major version number AUTH_MAJOR
+ *
+ * IF adding a new field please update the minor version number AUTH_MINOR
+ *
+ *  To process the resulting log lines from the commend line use jq to
+ *  parse the json.
+ *
+ *  grep "JSON Authentication" log file |
+ *  sed 's;^[^{]*;;' |
+ * jq -rc  '"\(.timestamp)\t\(.Authentication.status)\t
+ *           \(.Authentication.clientDomain)\t
+ *           \(.Authentication.clientAccount)
+ *           \t\(.Authentication.workstation)
+ *           \t\(.Authentication.remoteAddress)
+ *           \t\(.Authentication.localAddress)"'
+ */
+static void log_authentication_event_json(
+			const struct auth_usersupplied_info *ui,
+			NTSTATUS status,
+			const char *domain_name,
+			const char *account_name,
+			const char *unix_username,
+			struct dom_sid *sid,
+			int debug_level)
+{
+	struct json_context context = get_json_context();
+
+	start_object(&context, NULL);
+	add_timestamp(&context);
+	add_string(&context, "type", AUTH_JSON_TYPE);
+	start_object(&context, AUTH_JSON_TYPE);
+	add_version(&context, AUTH_MAJOR, AUTH_MINOR);
+	add_string(&context, "status", nt_errstr( status));
+	add_address(&context, "localAddress", ui->local_host);
+	add_address(&context, "remoteAddress", ui->remote_host);
+	add_string(&context, "serviceDescription", ui->service_description);
+	add_string(&context, "authDescription", ui->auth_description);
+	add_string(&context, "clientDomain", ui->client.domain_name);
+	add_string(&context, "clientAccount", ui->client.account_name);
+	add_string(&context, "workstation", ui->workstation_name);
+	add_string(&context, "becameAccount", account_name);
+	add_string(&context, "becameDomain", domain_name);
+	add_string(&context, "mappedAccount", ui->mapped.account_name);
+	add_string(&context, "mappedDomain", ui->mapped.domain_name);
+	add_string(&context,
+		   "netlogonComputer",
+		   ui->netlogon_trust_account.computer_name);
+	add_string(&context,
+		   "trustAccount",
+		   ui->netlogon_trust_account.account_name);
+	add_string(&context, "passwordType", get_password_type( ui));
+
+	end_object(&context);
+	end_object(&context);
+
+	log_json(&context, AUTH_JSON_TYPE, DBGC_AUTH_AUDIT, debug_level);
+	free_json_context(&context);
+}
+
+/*
+ * Log details of a successful authorization to a service,
+ * in a machine parsable json format
+ *
+ * IF removing or changing the format/meaning of a field please update the
+ *    major version number AUTHZ_MAJOR
+ *
+ * IF adding a new field please update the minor version number AUTHZ_MINOR
+ *
+ *  To process the resulting log lines from the commend line use jq to
+ *  parse the json.
+ *
+ *  grep "JSON Authentication" log_file |\
+ *  sed "s;^[^{]*;;" |\
+ *  jq -rc '"\(.timestamp)\t
+ *           \(.Authorization.domain)\t
+ *           \(.Authorization.account)\t
+ *           \(.Authorization.remoteAddress)"'
+ *
+ */
+static void log_successful_authz_event_json(
+				const struct tsocket_address *remote,
+				const struct tsocket_address *local,
+				const char *service_description,
+				const char *auth_type,
+				const char *transport_protection,
+				struct auth_session_info *session_info,
+				int debug_level)
+{
+	struct json_context context = get_json_context();
+	char account_flags[11];
+
+	start_object(&context, NULL);
+	add_timestamp(&context);
+	add_string(&context, "type", AUTHZ_JSON_TYPE);
+	start_object(&context, AUTHZ_JSON_TYPE);
+	add_version(&context, AUTHZ_MAJOR, AUTHZ_MINOR);
+	add_address(&context, "localAddress", local);
+	add_address(&context, "remoteAddress", remote);
+	add_string(&context, "serviceDescription", service_description);
+	add_string(&context, "authType", auth_type);
+	add_string(&context, "domain", session_info->info->domain_name);
+	add_string(&context, "account", session_info->info->account_name);
+	add_sid(&context, "sid", &session_info->security_token->sids[0]);
+	add_string(&context, "logonServer", session_info->info->logon_server);
+	add_string(&context, "transportProtection", transport_protection);
+
+	snprintf(account_flags,
+		 sizeof( account_flags),
+		 "0x%08X",
+		 session_info->info->acct_flags);
+	add_string(&context, "accountFlags", account_flags);
+	end_object(&context);
+	end_object(&context);
+
+	log_json(&context, AUTHZ_JSON_TYPE, DBGC_AUTH_AUDIT, debug_level);
+	free_json_context(&context);
+}
+
+#else
+
+static void log_authentication_event_json(
+			const struct auth_usersupplied_info *ui,
+			NTSTATUS status,
+			const char *domain_name,
+			const char *account_name,
+			const char *unix_username,
+			struct dom_sid *sid,
+			int debug_level)
+{
+	return;
+}
+
+static void log_successful_authz_event_json(
+				const struct tsocket_address *remote,
+				const struct tsocket_address *local,
+				const char *service_description,
+				const char *auth_type,
+				const char *transport_protection,
+				struct auth_session_info *session_info,
+				int debug_level)
+{
+	return;
+}
+
+#endif
+
+/*
+ * Determine the type of the password supplied for the
+ * authorisation attempt.
+ *
+ */
 static const char* get_password_type(const struct auth_usersupplied_info *ui)
 {
 
@@ -74,19 +554,19 @@ static const char* get_password_type(const struct auth_usersupplied_info *ui)
 }
 
 /*
- * Log details of an authentication attempt.
- * Successful and unsuccessful attempts are logged.
+ * Write a human readable authentication log entry.
  *
  */
-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)
+static void log_authentication_event_human_readable(
+			const struct auth_usersupplied_info *ui,
+			NTSTATUS status,
+			const char *domain_name,
+			const char *account_name,
+			const char *unix_username,
+			struct dom_sid *sid,
+			int debug_level)
 {
 	TALLOC_CTX *frame = NULL;
-
 	char *ts = NULL;         /* formatted current time      */
 	char *remote = NULL;     /* formatted remote host       */
 	char *local = NULL;      /* formatted local host        */
@@ -96,20 +576,6 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 	char *logon_line = NULL;
 	const char *password_type = NULL;
 
-	/* set the log level */
-	int debug_level = AUTH_FAILURE_LEVEL;
-
-	if (NT_STATUS_IS_OK(status)) {
-		debug_level = AUTH_SUCCESS_LEVEL;
-		if (dom_sid_equal(sid, &global_sid_Anonymous)) {
-			debug_level = AUTH_ANONYMOUS_LEVEL;
-		}
-	}
-
-	if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
-		return;
-	}
-
 	frame = talloc_stackframe();
 
 	password_type = get_password_type( ui);
@@ -135,16 +601,18 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 		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, domain_name),
-					     log_escape(frame, account_name),
-					     sid_buf);
+		logon_line = talloc_asprintf(
+				frame,
+				" became [%s]\\[%s] %s.",
+				log_escape(frame, domain_name),
+				log_escape(frame, account_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));
+		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, debug_level, (
@@ -170,23 +638,63 @@ 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
+ * Log details of an authentication attempt.
+ * Successful and unsuccessful attempts are logged.
  *
- * The service may later refuse authorization due to an ACL.
+ */
+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)
+{
+	/* set the log level */
+	int debug_level = AUTH_FAILURE_LEVEL;
+
+	if (NT_STATUS_IS_OK(status)) {
+		debug_level = AUTH_SUCCESS_LEVEL;
+		if (dom_sid_equal(sid, &global_sid_Anonymous)) {
+			debug_level = AUTH_ANONYMOUS_LEVEL;
+		}
+	}
+
+	if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
+		log_authentication_event_human_readable(ui,
+							status,
+							domain_name,
+							account_name,
+							unix_username,
+							sid,
+							debug_level);
+	}
+	if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT_JSON, debug_level)) {
+		log_authentication_event_json(ui,
+					      status,
+					      domain_name,
+					      account_name,
+					      unix_username,
+					      sid,
+					      debug_level);
+	}
+}
+
+
+
+/*
+ * Log details of a successful authorization to a service,
+ * in a human readable format.
  *
  */
-void log_successful_authz_event(const struct tsocket_address *remote,
+static void log_successful_authz_event_human_readable(
+				const struct tsocket_address *remote,
 				const struct tsocket_address *local,
 				const char *service_description,
 				const char *auth_type,
 				const char *transport_protection,
-				struct auth_session_info *session_info)
+				struct auth_session_info *session_info,
+				int debug_level)
 {
 	TALLOC_CTX *frame = NULL;
 
@@ -194,16 +702,6 @@ 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];
-	int debug_level = AUTHZ_SUCCESS_LEVEL;
-
-	if (security_token_is_anonymous(session_info->security_token)) {
-		debug_level = AUTH_ANONYMOUS_LEVEL;
-	}
-
-	/* set the log level */
-	if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
-		return;
-	}
 
 	frame = talloc_stackframe();
 
@@ -213,9 +711,11 @@ void log_successful_authz_event(const struct tsocket_address *remote,
 	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));
+	dom_sid_string_buf(&session_info->security_token->sids[0],
+			   sid_buf,
+			   sizeof(sid_buf));
 
-	DEBUGC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL, (
+	DEBUGC( DBGC_AUTH_AUDIT, debug_level, (
 		"Successful AuthZ: [%s,%s] user [%s]\\[%s] [%s]"
 		" at [%s]"
 		" Remote host [%s]"
@@ -231,3 +731,47 @@ void log_successful_authz_event(const struct tsocket_address *remote,
 
 	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 log_authentication_event
+ * - 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,
+				const char *auth_type,
+				const char *transport_protection,
+				struct auth_session_info *session_info)
+{
+	int debug_level = AUTHZ_SUCCESS_LEVEL;
+
+	/* set the log level */
+	if (security_token_is_anonymous(session_info->security_token)) {
+		debug_level = AUTH_ANONYMOUS_LEVEL;
+	}
+
+	if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
+		log_successful_authz_event_human_readable(remote,
+							  local,
+							  service_description,
+							  auth_type,
+							  transport_protection,
+							  session_info,
+							  debug_level);
+	}
+	if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT_JSON, debug_level)) {
+		log_successful_authz_event_json(remote,
+						local,
+						service_description,
+						auth_type,
+						transport_protection,
+						session_info,
+						debug_level);
+	}
+}
diff --git a/auth/wscript_build b/auth/wscript_build
index 732536d686e..9ef03501194 100644
--- a/auth/wscript_build
+++ b/auth/wscript_build
@@ -2,7 +2,7 @@
 
 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',
+                  deps='talloc samba-security samba-util util_str_escape LIBTSOCKET json-glib-1.0 glib-2.0 gobject-2.0',
                   private_library=True
                   )
 
diff --git a/auth/wscript_configure b/auth/wscript_configure
new file mode 100644
index 00000000000..712248e4274
--- /dev/null
+++ b/auth/wscript_configure
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+
+conf.SET_TARGET_TYPE('json-glib-1.0', 'EMPTY')
+conf.SET_TARGET_TYPE('glib-2.0', 'EMPTY')
+conf.SET_TARGET_TYPE('gobject-2.0', 'EMPTY')
+
+if conf.CHECK_CFG(package='json-glib-1.0', args='--cflags --libs',
+		  msg='Checking for json-glib-1.0'):
+    conf.CHECK_FUNCS_IN('json_builder_new', 'json-glib-1.0')
+    conf.CHECK_FUNCS_IN('g_free', 'glib-2.0')
+    conf.CHECK_FUNCS_IN('g_object_unref', 'gobject-2.0')
diff --git a/lib/util/debug.c b/lib/util/debug.c
index 009f3629979..f48daf69553 100644
--- a/lib/util/debug.c
+++ b/lib/util/debug.c
@@ -538,6 +538,7 @@ static const char *default_classname_table[] = {
 	[DBGC_LDB] =		"ldb",
 	[DBGC_TEVENT] =		"tevent",
 	[DBGC_AUTH_AUDIT] =	"auth_audit",
+	[DBGC_AUTH_AUDIT_JSON] = "auth_json_audit",
 };
 
 /*
diff --git a/lib/util/debug.h b/lib/util/debug.h
index 786c80958ec..9d5f438255d 100644
--- a/lib/util/debug.h
+++ b/lib/util/debug.h
@@ -90,7 +90,7 @@ bool dbghdr( int level, const char *location, const char *func);
 #define DBGC_LDB		22
 #define DBGC_TEVENT		23
 #define DBGC_AUTH_AUDIT		24
-
+#define DBGC_AUTH_AUDIT_JSON	25
 /* So you can define DBGC_CLASS before including debug.h */
 #ifndef DBGC_CLASS
 #define DBGC_CLASS            0     /* override as shown above */
diff --git a/wscript b/wscript
index 407bcdc132e..eefe24615f1 100644
--- a/wscript
+++ b/wscript
@@ -199,6 +199,7 @@ def configure(conf):
         conf.RECURSE('ctdb')
     conf.RECURSE('lib/socket')
     conf.RECURSE('testsuite/unittests')
+    conf.RECURSE('auth')
 
     conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS()
 
-- 
2.12.0.246.ga2ecc84866-goog


From a0a0b875127ab17f70a134f304d7130b49b8d7ee Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 7 Mar 2017 15:09:38 +1300
Subject: [PATCH 38/43] messaging.idl: Register a message type for
 authentication log messages

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 librpc/idl/messaging.idl | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl
index 032f95eeab9..2a94eeee93b 100644
--- a/librpc/idl/messaging.idl
+++ b/librpc/idl/messaging.idl
@@ -139,6 +139,9 @@ interface messaging
 		MSG_NTVFS_OPLOCK_BREAK          = 0x0703,
 		MSG_DREPL_ALLOCATE_RID          = 0x0704,
 
+		/* Called during authentication and authorization to allow out-of- */
+		MSG_AUTH_LOG                    = 0x0800,
+
 		/* dbwrap messages 4001-4999 (0x0FA0 - 0x1387) */
 		/* MSG_DBWRAP_TDB2_CHANGES		= 4001, */
 		/* MSG_DBWRAP_G_LOCK_RETRY		= 4002, */
-- 
2.12.0.246.ga2ecc84866-goog


From fc7c15739b77010ec9c486c54910074b1fda3311 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 7 Mar 2017 16:50:38 +1300
Subject: [PATCH 39/43] auth_log: Allow logging JSON events to a server over
 the message bus

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 auth/auth_log.c                                    | 230 ++++++++++++++++-----
 auth/common_auth.h                                 |  28 ++-
 auth/gensec/gensec.c                               |   4 +-
 auth/wscript_build                                 |   2 +-
 .../smbdotconf/logon/autheventnotification.xml     |  15 ++
 source3/auth/auth.c                                |   4 +-
 source3/auth/auth_generic.c                        |   4 +-
 source3/rpc_server/srv_pipe.c                      |   3 +-
 source4/auth/ntlm/auth.c                           |   8 +-
 source4/auth/ntlm/auth_simple.c                    |   4 +-
 source4/ldap_server/ldap_backend.c                 |   4 +-
 source4/lib/messaging/messaging.c                  |  79 +------
 source4/lib/messaging/messaging_internal.h         |  36 ++++
 source4/lib/messaging/messaging_send.c             | 115 +++++++++++
 source4/lib/messaging/wscript_build                |   6 +
 source4/rpc_server/dcesrv_auth.c                   |   4 +-
 source4/smb_server/smb/sesssetup.c                 |   4 +-
 17 files changed, 404 insertions(+), 146 deletions(-)
 create mode 100644 docs-xml/smbdotconf/logon/autheventnotification.xml
 create mode 100644 source4/lib/messaging/messaging_internal.h
 create mode 100644 source4/lib/messaging/messaging_send.c

diff --git a/auth/auth_log.c b/auth/auth_log.c
index d69c393e59f..f1f11735173 100644
--- a/auth/auth_log.c
+++ b/auth/auth_log.c
@@ -51,7 +51,11 @@
 #include "lib/util/util_str_escape.h"
 #include "libcli/security/dom_sid.h"
 #include "libcli/security/security_token.h"
-
+#include "librpc/gen_ndr/server_id.h"
+#include "source4/lib/messaging/messaging.h"
+#include "source4/lib/messaging/irpc.h"
+#include "lib/util/server_id_db.h"
+#include "lib/param/param.h"
 /*
  * Determine the type of the password supplied for the
  * authorisation attempt.
@@ -74,6 +78,129 @@ struct json_context {
 	JsonBuilder *builder;
 	bool error;
 };
+
+static NTSTATUS get_auth_event_server(struct imessaging_context *msg_ctx,
+				      struct server_id *auth_event_server)
+{
+	NTSTATUS status;
+	TALLOC_CTX *frame = talloc_stackframe();
+	unsigned num_servers, i;
+	struct server_id *servers;
+
+	status = irpc_servers_byname(msg_ctx, frame,
+				     "auth_event",
+				     &num_servers, &servers);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_NOTICE("Failed to find 'auth_event' registered on the "
+			   "message bus to send JSON authentication events to: %s\n",
+			   nt_errstr(status));
+		TALLOC_FREE(frame);
+		return status;
+	}
+
+	/*
+	 * Select the first server that is listening, because
+	 * we get connection refused as
+	 * NT_STATUS_OBJECT_NAME_NOT_FOUND without waiting
+	 */
+	for (i = 0; i < num_servers; i++) {
+		status = imessaging_send(msg_ctx, servers[i], MSG_PING,
+					 &data_blob_null);
+		if (NT_STATUS_IS_OK(status)) {
+			TALLOC_FREE(frame);
+			*auth_event_server = servers[i];
+		}
+	}
+	if (i == num_servers) {
+		DBG_NOTICE("Failed to find a running 'auth_event' server "
+			   "registered on the message bus to send JSON "
+			   "authentication events to\n");
+	}
+	TALLOC_FREE(frame);
+	return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+}
+
+static void auth_message_send(struct imessaging_context *msg_ctx,
+			      const char *json)
+{
+	static struct server_id	auth_event_server;
+	NTSTATUS status;
+	DATA_BLOB json_blob = data_blob_string_const(json);
+	if (msg_ctx == NULL) {
+		return;
+	}
+
+	if (auth_event_server.pid == 0) {
+		status = get_auth_event_server(msg_ctx, &auth_event_server);
+		if (!NT_STATUS_IS_OK(status)) {
+			return;
+		}
+	}
+
+	status = imessaging_send(msg_ctx, auth_event_server, MSG_AUTH_LOG,
+				 &json_blob);
+
+	/* If the server crashed, try to find it again */
+	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+		status = get_auth_event_server(msg_ctx, &auth_event_server);
+		if (!NT_STATUS_IS_OK(status)) {
+			return;
+		}
+		imessaging_send(msg_ctx, auth_event_server, MSG_AUTH_LOG,
+				&json_blob);
+
+	}
+}
+
+/*
+ * Write the json object to the debug lines.
+ *
+ */
+static void log_json(struct imessaging_context *msg_ctx,
+		     struct json_context *context,
+		     const char *type, int debug_class, int debug_level)
+{
+	JsonGenerator *gen = NULL;
+	JsonNode *root = NULL;
+	gchar *json = NULL;
+
+	if( context->error) {
+		return;
+	}
+
+	gen = json_generator_new();
+	if (gen == NULL) {
+		DBG_ERR( "Unable to create a JSON gemerator");
+		context->error = true;
+		goto exit;
+	}
+
+	root = json_builder_get_root( context->builder);
+	if (root == NULL) {
+		DBG_ERR( "Unable to get root object");
+		context->error = true;
+		goto exit;
+	}
+
+
+	// set root copies the root, so it can be deleted
+	json_generator_set_root( gen, root);
+	json_node_free( root);
+
+	json = json_generator_to_data( gen, NULL);
+
+	DEBUGC( debug_class, debug_level, ( "JSON %s: %s\n", type, json));
+
+	auth_message_send(msg_ctx, json);
+
+exit:
+	if (json)
+		g_free( json);
+	if( gen)
+		g_object_unref( gen);
+}
+
 /*
  * Create a new json logging context.
  *
@@ -323,51 +450,6 @@ static void add_sid(struct json_context *context,
 }
 
 /*
- * Write the json object to the debug lines.
- *
- */
-static void log_json(struct json_context *context,
-		     const char *type, int debug_class, int debug_level)
-{
-	JsonGenerator *gen = NULL;
-	JsonNode *root = NULL;
-	gchar *json = NULL;
-
-	if( context->error) {
-		return;
-	}
-
-	gen = json_generator_new();
-	if (gen == NULL) {
-		DBG_ERR( "Unable to create a JSON gemerator");
-		context->error = true;
-		goto exit;
-	}
-
-	root = json_builder_get_root( context->builder);
-	if (root == NULL) {
-		DBG_ERR( "Unable to get root object");
-		context->error = true;
-		goto exit;
-	}
-
-
-	// set root copies the root, so it can be deleted
-	json_generator_set_root( gen, root);
-	json_node_free( root);
-
-	json = json_generator_to_data( gen, NULL);
-
-	DEBUGC( debug_class, debug_level, ( "JSON %s: %s\n", type, json));
-
-exit:
-	if (json)
-		g_free( json);
-	if( gen)
-		g_object_unref( gen);
-}
-
-/*
  * Write a machine parsable json formatted authentication log entry.
  *
  * IF removing or changing the format/meaning of a field please update the
@@ -388,6 +470,7 @@ exit:
  *           \t\(.Authentication.localAddress)"'
  */
 static void log_authentication_event_json(
+	                struct imessaging_context *msg_ctx,
 			const struct auth_usersupplied_info *ui,
 			NTSTATUS status,
 			const char *domain_name,
@@ -426,7 +509,7 @@ static void log_authentication_event_json(
 	end_object(&context);
 	end_object(&context);
 
-	log_json(&context, AUTH_JSON_TYPE, DBGC_AUTH_AUDIT, debug_level);
+	log_json(msg_ctx, &context, AUTH_JSON_TYPE, DBGC_AUTH_AUDIT, debug_level);
 	free_json_context(&context);
 }
 
@@ -451,6 +534,7 @@ static void log_authentication_event_json(
  *
  */
 static void log_successful_authz_event_json(
+				struct imessaging_context *msg_ctx,
 				const struct tsocket_address *remote,
 				const struct tsocket_address *local,
 				const char *service_description,
@@ -485,13 +569,35 @@ static void log_successful_authz_event_json(
 	end_object(&context);
 	end_object(&context);
 
-	log_json(&context, AUTHZ_JSON_TYPE, DBGC_AUTH_AUDIT, debug_level);
+	log_json(msg_ctx, &context, AUTHZ_JSON_TYPE, DBGC_AUTH_AUDIT, debug_level);
 	free_json_context(&context);
 }
 
 #else
 
+static void log_no_json(struct imessaging_context *msg_ctx,
+                        struct loadparm_context *lp_ctx)
+{
+	if (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx)) {
+		static auth_event_logged = false;
+		if (auth_event_logged == false) {
+			auth_event_logged = true;
+			DBG_ERR("auth event notification = true but Samba was not compiled with glib-json-1.0\n");
+		}
+	} else {
+		static json_logged = false;
+		if (json_logged == false) {
+			json_logged = true;
+			DBG_NOTICE("JSON auth logs not available unless compiled with glib-json-1.0\n");
+		}
+	}
+
+	return;
+}
+
 static void log_authentication_event_json(
+	                struct imessaging_context *msg_ctx,
+                        struct loadparm_context *lp_ctx,
 			const struct auth_usersupplied_info *ui,
 			NTSTATUS status,
 			const char *domain_name,
@@ -500,10 +606,13 @@ static void log_authentication_event_json(
 			struct dom_sid *sid,
 			int debug_level)
 {
+	log_no_json(msg_ctx, lp_ctx);
 	return;
 }
 
 static void log_successful_authz_event_json(
+	                        struct imessaging_context *msg_ctx,
+                                struct loadparm_context *lp_ctx,
 				const struct tsocket_address *remote,
 				const struct tsocket_address *local,
 				const char *service_description,
@@ -512,6 +621,7 @@ static void log_successful_authz_event_json(
 				struct auth_session_info *session_info,
 				int debug_level)
 {
+	log_no_json(msg_ctx, lp_ctx);
 	return;
 }
 
@@ -642,8 +752,12 @@ static void log_authentication_event_human_readable(
  * Log details of an authentication attempt.
  * Successful and unsuccessful attempts are logged.
  *
+ * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
+ * authentication events over the message bus.
  */
-void log_authentication_event(const struct auth_usersupplied_info *ui,
+void log_authentication_event(struct imessaging_context *msg_ctx,
+			      struct loadparm_context *lp_ctx,
+			      const struct auth_usersupplied_info *ui,
 			      NTSTATUS status,
 			      const char *domain_name,
 			      const char *account_name,
@@ -669,8 +783,10 @@ void log_authentication_event(const struct auth_usersupplied_info *ui,
 							sid,
 							debug_level);
 	}
-	if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT_JSON, debug_level)) {
-		log_authentication_event_json(ui,
+	if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT_JSON, debug_level) ||
+	    (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx))) {
+		log_authentication_event_json(msg_ctx,
+					      ui,
 					      status,
 					      domain_name,
 					      account_name,
@@ -741,8 +857,12 @@ static void log_successful_authz_event_human_readable(
  *
  * The service may later refuse authorization due to an ACL.
  *
+ * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
+ * authentication events over the message bus.
  */
-void log_successful_authz_event(const struct tsocket_address *remote,
+void log_successful_authz_event(struct imessaging_context *msg_ctx,
+				struct loadparm_context *lp_ctx,
+				const struct tsocket_address *remote,
 				const struct tsocket_address *local,
 				const char *service_description,
 				const char *auth_type,
@@ -765,8 +885,10 @@ void log_successful_authz_event(const struct tsocket_address *remote,
 							  session_info,
 							  debug_level);
 	}
-	if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT_JSON, debug_level)) {
-		log_successful_authz_event_json(remote,
+	if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT_JSON, debug_level) ||
+	    (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx))) {
+		log_successful_authz_event_json(msg_ctx,
+						remote,
 						local,
 						service_description,
 						auth_type,
diff --git a/auth/common_auth.h b/auth/common_auth.h
index 331f112858f..2fc687e009c 100644
--- a/auth/common_auth.h
+++ b/auth/common_auth.h
@@ -153,14 +153,38 @@ struct auth4_context {
 #define AUTHZ_TRANSPORT_PROTECTION_SEAL "SEAL"
 #define AUTHZ_TRANSPORT_PROTECTION_SIGN "SIGN"
 
-void log_authentication_event(const struct auth_usersupplied_info *ui,
+/*
+ * Log details of an authentication attempt.
+ * Successful and unsuccessful attempts are logged.
+ *
+ * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
+ * authentication events over the message bus.
+ */
+void log_authentication_event(struct imessaging_context *msg_ctx,
+			      struct loadparm_context *lp_ctx,
+			      const struct auth_usersupplied_info *ui,
 			      NTSTATUS status,
 			      const char *account_name,
 			      const char *domain_name,
 			      const char *unix_username,
 			      struct dom_sid *sid);
 
-void log_successful_authz_event(const struct tsocket_address *remote,
+/*
+ * Log details of a successful authorization to a service.
+ *
+ * Only successful authorizations are logged.  For clarity:
+ * - NTLM bad passwords will be recorded by log_authentication_event
+ * - Kerberos decrypt failures need to be logged in gensec_gssapi et al
+ *
+ * The service may later refuse authorization due to an ACL.
+ *
+ *
+ * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
+ * authorization events over the message bus.
+ */
+void log_successful_authz_event(struct imessaging_context *msg_ctx,
+				struct loadparm_context *lp_ctx,
+				const struct tsocket_address *remote,
 				const struct tsocket_address *local,
 				const char *service_description,
 				const char *auth_type,
diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index 14fd9f46ef7..48ccea160f2 100644
--- a/auth/gensec/gensec.c
+++ b/auth/gensec/gensec.c
@@ -233,7 +233,9 @@ static void log_successful_gensec_authz_event(struct gensec_security *gensec_sec
 	} else {
 		transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
 	}
-	log_successful_authz_event(remote, local,
+	log_successful_authz_event(gensec_security->auth_context->msg_ctx,
+				   gensec_security->auth_context->lp_ctx,
+				   remote, local,
 				   service_description,
 				   final_auth_type,
 				   transport_protection,
diff --git a/auth/wscript_build b/auth/wscript_build
index 9ef03501194..7a2e3835b86 100644
--- a/auth/wscript_build
+++ b/auth/wscript_build
@@ -2,7 +2,7 @@
 
 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 json-glib-1.0 glib-2.0 gobject-2.0',
+                  deps='talloc samba-security samba-util util_str_escape LIBTSOCKET json-glib-1.0 glib-2.0 gobject-2.0 MESSAGING_SEND server_id_db ',
                   private_library=True
                   )
 
diff --git a/docs-xml/smbdotconf/logon/autheventnotification.xml b/docs-xml/smbdotconf/logon/autheventnotification.xml
new file mode 100644
index 00000000000..cf7ac53c693
--- /dev/null
+++ b/docs-xml/smbdotconf/logon/autheventnotification.xml
@@ -0,0 +1,15 @@
+<samba:parameter name="auth event notification"
+                 context="G"
+                 type="boolean"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+	<para>When enabled, this option causes Samba (acting as an
+	Active Directory Domain Controller) to stream authentication
+	events across the internal message bus.  Scripts built using
+	Samba's python bindings can listen to these events by
+	registering as the service
+	<filename moreinfo="none">auth_event</filename>.</para>
+</description>
+
+<value type="default">no</value>
+</samba:parameter>
diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index c93551d042e..bde8cb78c1b 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -315,7 +315,7 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 		sid = null_sid;
 	}
 
-	log_authentication_event(user_info, nt_status,
+	log_authentication_event(NULL, NULL,
 			server_info->info3->base.logon_domain.string,
 			server_info->info3->base.account_name.string,
 			unix_username, &sid);
@@ -337,7 +337,7 @@ fail:
 		  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);
+	log_authentication_event(NULL, NULL, user_info, nt_status, NULL, NULL, NULL, NULL);
 
 	ZERO_STRUCTP(pserver_info);
 
diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 5631c856bff..477c2a892db 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -434,7 +434,9 @@ NTSTATUS auth_check_password_session_info(struct auth4_context *auth_context,
 	 * authorizations consistently (be they NLTM, NTLMSSP or
 	 * krb5) we log this info again.
 	 */
-	log_successful_authz_event(user_info->remote_host,
+	log_successful_authz_event(auth_context->msg_ctx,
+				   auth_context->lp_ctx,
+				   user_info->remote_host,
 				   user_info->local_host,
 				   user_info->service_description,
 				   user_info->auth_description,
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index c8b0fdccf42..95e2cebee8b 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -836,7 +836,8 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 		 * covered ncacn_np pass-through auth, and anonymous
 		 * DCE/RPC (eg epmapper, netlogon etc)
 		 */
-		log_successful_authz_event(p->remote_address,
+		log_successful_authz_event(NULL, NULL,
+					   p->remote_address,
 					   p->local_address,
 					   table->name,
 					   derpc_transport_string_by_transport(p->transport),
diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index 9a0345c07c0..fddb5123062 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -445,7 +445,9 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
 			 state->user_info->mapped.account_name,
 			 nt_errstr(status)));
 
-		log_authentication_event(state->user_info, status,
+		log_authentication_event(state->auth_ctx->msg_ctx,
+					 state->auth_ctx->lp_ctx,
+					 state->user_info, status,
 					 NULL, NULL, NULL, NULL);
 		tevent_req_received(req);
 		return status;
@@ -457,7 +459,9 @@ _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,
+	log_authentication_event(state->auth_ctx->msg_ctx,
+				 state->auth_ctx->lp_ctx,
+				 state->user_info, status,
 				 state->user_info_dc->info->domain_name,
 				 state->user_info_dc->info->account_name,
 				 NULL,
diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c
index 4e5780f7a10..3d2dbb92948 100644
--- a/source4/auth/ntlm/auth_simple.c
+++ b/source4/auth/ntlm/auth_simple.c
@@ -131,7 +131,9 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 		talloc_steal(mem_ctx, *session_info);
 	}
 
-	log_successful_authz_event(remote_address,
+	log_successful_authz_event(auth_context->msg_ctx,
+				   auth_context->lp_ctx,
+				   remote_address,
 				   local_address,
 				   "LDAP",
 				   "simple bind",
diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c
index 7aa51f293ed..d20d586d237 100644
--- a/source4/ldap_server/ldap_backend.c
+++ b/source4/ldap_server/ldap_backend.c
@@ -1285,7 +1285,9 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
 				transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
 			}
 
-			log_successful_authz_event(call->conn->connection->remote_address,
+			log_successful_authz_event(call->conn->connection->msg_ctx,
+						   call->conn->connection->lp_ctx,
+						   call->conn->connection->remote_address,
 						   call->conn->connection->local_address,
 						   "LDAP",
 						   "no bind",
diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c
index 84df9345d80..761fd0dec7c 100644
--- a/source4/lib/messaging/messaging.c
+++ b/source4/lib/messaging/messaging.c
@@ -24,6 +24,7 @@
 #include "lib/util/server_id.h"
 #include "system/filesys.h"
 #include "messaging/messaging.h"
+#include "messaging/messaging_internal.h"
 #include "../lib/util/dlinklist.h"
 #include "lib/socket/socket.h"
 #include "librpc/gen_ndr/ndr_irpc.h"
@@ -55,22 +56,6 @@ struct irpc_request {
 	} incoming;
 };
 
-struct imessaging_context {
-	struct imessaging_context *prev, *next;
-	struct tevent_context *ev;
-	struct server_id server_id;
-	const char *sock_dir;
-	const char *lock_dir;
-	struct dispatch_fn **dispatch;
-	uint32_t num_types;
-	struct idr_context *dispatch_tree;
-	struct irpc_list *irpc;
-	struct idr_context *idr;
-	struct server_id_db *names;
-	struct timeval start_time;
-	void *msg_dgm_ref;
-};
-
 /* we have a linked list of dispatch handlers for each msg_type that
    this messaging server can deal with */
 struct dispatch_fn {
@@ -246,68 +231,6 @@ void imessaging_deregister(struct imessaging_context *msg, uint32_t msg_type, vo
 }
 
 /*
-  Send a message to a particular server
-*/
-NTSTATUS imessaging_send(struct imessaging_context *msg, struct server_id server,
-			uint32_t msg_type, const DATA_BLOB *data)
-{
-	uint8_t hdr[MESSAGE_HDR_LENGTH];
-	struct iovec iov[2];
-	int num_iov, ret;
-	pid_t pid;
-	void *priv;
-
-	if (!cluster_node_equal(&msg->server_id, &server)) {
-		/* No cluster in source4... */
-		return NT_STATUS_OK;
-	}
-
-	message_hdr_put(hdr, msg_type, msg->server_id, server);
-
-	iov[0] = (struct iovec) { .iov_base = &hdr, .iov_len = sizeof(hdr) };
-	num_iov = 1;
-
-	if (data != NULL) {
-		iov[1] = (struct iovec) { .iov_base = data->data,
-					  .iov_len = data->length };
-		num_iov += 1;
-	}
-
-	pid = server.pid;
-	if (pid == 0) {
-		pid = getpid();
-	}
-
-	ret = messaging_dgm_send(pid, iov, num_iov, NULL, 0);
-
-	if (ret == EACCES) {
-		priv = root_privileges();
-		ret = messaging_dgm_send(pid, iov, num_iov, NULL, 0);
-		TALLOC_FREE(priv);
-	}
-
-	if (ret != 0) {
-		return map_nt_error_from_unix_common(ret);
-	}
-	return NT_STATUS_OK;
-}
-
-/*
-  Send a message to a particular server, with the message containing a single pointer
-*/
-NTSTATUS imessaging_send_ptr(struct imessaging_context *msg, struct server_id server,
-			    uint32_t msg_type, void *ptr)
-{
-	DATA_BLOB blob;
-
-	blob.data = (uint8_t *)&ptr;
-	blob.length = sizeof(void *);
-
-	return imessaging_send(msg, server, msg_type, &blob);
-}
-
-
-/*
 */
 int imessaging_cleanup(struct imessaging_context *msg)
 {
diff --git a/source4/lib/messaging/messaging_internal.h b/source4/lib/messaging/messaging_internal.h
new file mode 100644
index 00000000000..93c5c4bdd7b
--- /dev/null
+++ b/source4/lib/messaging/messaging_internal.h
@@ -0,0 +1,36 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Samba internal messaging functions
+
+   Copyright (C) Andrew Tridgell 2004
+
+   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/>.
+*/
+
+struct imessaging_context {
+	struct imessaging_context *prev, *next;
+	struct tevent_context *ev;
+	struct server_id server_id;
+	const char *sock_dir;
+	const char *lock_dir;
+	struct dispatch_fn **dispatch;
+	uint32_t num_types;
+	struct idr_context *dispatch_tree;
+	struct irpc_list *irpc;
+	struct idr_context *idr;
+	struct server_id_db *names;
+	struct timeval start_time;
+	void *msg_dgm_ref;
+};
diff --git a/source4/lib/messaging/messaging_send.c b/source4/lib/messaging/messaging_send.c
new file mode 100644
index 00000000000..a4f828186c9
--- /dev/null
+++ b/source4/lib/messaging/messaging_send.c
@@ -0,0 +1,115 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Samba internal messaging functions (send).
+
+   Copyright (C) Andrew Tridgell 2004
+
+   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 "messaging/messaging.h"
+#include "messaging/irpc.h"
+#include "../source3/lib/messages_dgm.h"
+#include "../source3/lib/messages_dgm_ref.h"
+#include "../source3/lib/messages_util.h"
+#include "messaging/messaging_internal.h"
+#include "lib/util/server_id_db.h"
+#include "cluster/cluster.h"
+#include "../lib/util/unix_privs.h"
+
+/*
+ * This file is for functions that can be called from auth_log without
+ * depending on all of dcerpc and so cause dep loops.
+ */
+
+/*
+  return a list of server ids for a server name
+*/
+NTSTATUS irpc_servers_byname(struct imessaging_context *msg_ctx,
+			     TALLOC_CTX *mem_ctx, const char *name,
+			     unsigned *num_servers,
+			     struct server_id **servers)
+{
+	int ret;
+
+	ret = server_id_db_lookup(msg_ctx->names, name, mem_ctx,
+				  num_servers, servers);
+	if (ret != 0) {
+		return map_nt_error_from_unix_common(ret);
+	}
+	return NT_STATUS_OK;
+}
+
+/*
+  Send a message to a particular server
+*/
+NTSTATUS imessaging_send(struct imessaging_context *msg, struct server_id server,
+			uint32_t msg_type, const DATA_BLOB *data)
+{
+	uint8_t hdr[MESSAGE_HDR_LENGTH];
+	struct iovec iov[2];
+	int num_iov, ret;
+	pid_t pid;
+	void *priv;
+
+	if (!cluster_node_equal(&msg->server_id, &server)) {
+		/* No cluster in source4... */
+		return NT_STATUS_OK;
+	}
+
+	message_hdr_put(hdr, msg_type, msg->server_id, server);
+
+	iov[0] = (struct iovec) { .iov_base = &hdr, .iov_len = sizeof(hdr) };
+	num_iov = 1;
+
+	if (data != NULL) {
+		iov[1] = (struct iovec) { .iov_base = data->data,
+					  .iov_len = data->length };
+		num_iov += 1;
+	}
+
+	pid = server.pid;
+	if (pid == 0) {
+		pid = getpid();
+	}
+
+	ret = messaging_dgm_send(pid, iov, num_iov, NULL, 0);
+
+	if (ret == EACCES) {
+		priv = root_privileges();
+		ret = messaging_dgm_send(pid, iov, num_iov, NULL, 0);
+		TALLOC_FREE(priv);
+	}
+
+	if (ret != 0) {
+		return map_nt_error_from_unix_common(ret);
+	}
+	return NT_STATUS_OK;
+}
+
+/*
+  Send a message to a particular server, with the message containing a single pointer
+*/
+NTSTATUS imessaging_send_ptr(struct imessaging_context *msg, struct server_id server,
+			    uint32_t msg_type, void *ptr)
+{
+	DATA_BLOB blob;
+
+	blob.data = (uint8_t *)&ptr;
+	blob.length = sizeof(void *);
+
+	return imessaging_send(msg, server, msg_type, &blob);
+}
diff --git a/source4/lib/messaging/wscript_build b/source4/lib/messaging/wscript_build
index 86877af8441..2b6cf81885c 100644
--- a/source4/lib/messaging/wscript_build
+++ b/source4/lib/messaging/wscript_build
@@ -1,6 +1,12 @@
 #!/usr/bin/env python
 
 
+bld.SAMBA_LIBRARY('MESSAGING_SEND',
+	source='messaging_send.c',
+	public_deps='messages_util messages_dgm UNIX_PRIVS cluster server_id_db',
+	private_library=True
+	)
+
 bld.SAMBA_LIBRARY('MESSAGING',
 	source='messaging.c',
 	public_deps='samba-util NDR_IRPC UNIX_PRIVS cluster ndr dcerpc messages_util server_id_db talloc_report',
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 1ebb5143b93..efcb586bfcf 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -62,7 +62,9 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 		 * covered ncacn_np pass-through auth, and anonymous
 		 * DCE/RPC (eg epmapper, netlogon etc)
 		 */
-		log_successful_authz_event(call->conn->remote_address,
+		log_successful_authz_event(call->conn->msg_ctx,
+					   call->conn->dce_ctx->lp_ctx,
+					   call->conn->remote_address,
 					   call->conn->local_address,
 					   "DCE/RPC",
 					   auth_type,
diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c
index ce73a02c2d5..4d223f00fec 100644
--- a/source4/smb_server/smb/sesssetup.c
+++ b/source4/smb_server/smb/sesssetup.c
@@ -54,7 +54,9 @@ void smbsrv_not_spengo_sesssetup_authz_log(struct smbsrv_request *req,
 	local_address = socket_get_local_addr(req->smb_conn->connection->socket,
 					      frame);
 
-	log_successful_authz_event(remote_address,
+	log_successful_authz_event(req->smb_conn->connection->msg_ctx,
+				   req->smb_conn->lp_ctx,
+				   remote_address,
 				   local_address,
 				   "SMB",
 				   "bare-NTLM",
-- 
2.12.0.246.ga2ecc84866-goog


From 19cf96c40edd7111ce739cba97d9d5af1f97ee32 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 8 Mar 2017 11:03:44 +1300
Subject: [PATCH 40/43] pytevent: Allow other parts of Samba to consume tevent
 python bindings

This will make it possible for pymessaging to consume a pytevent created context, and so
make pymessaging practical

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 .../smbdotconf/logon/autheventnotification.xml     |  2 ++
 lib/tevent/pytevent.c                              |  9 +-----
 lib/tevent/pytevent.h                              | 34 ++++++++++++++++++++++
 source4/lib/messaging/pymessaging.c                | 27 ++++++++++++++---
 4 files changed, 60 insertions(+), 12 deletions(-)
 create mode 100644 lib/tevent/pytevent.h

diff --git a/docs-xml/smbdotconf/logon/autheventnotification.xml b/docs-xml/smbdotconf/logon/autheventnotification.xml
index cf7ac53c693..a42d98c8e86 100644
--- a/docs-xml/smbdotconf/logon/autheventnotification.xml
+++ b/docs-xml/smbdotconf/logon/autheventnotification.xml
@@ -9,6 +9,8 @@
 	Samba's python bindings can listen to these events by
 	registering as the service
 	<filename moreinfo="none">auth_event</filename>.</para>
+
+	<para>Samba must be compiled with glib-json support for this option to be effective</para>
 </description>
 
 <value type="default">no</value>
diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c
index 10d8a22a8cf..eb76c2b8abc 100644
--- a/lib/tevent/pytevent.c
+++ b/lib/tevent/pytevent.c
@@ -22,9 +22,7 @@
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 
-#include <Python.h>
-#include "replace.h"
-#include <tevent.h>
+#include "pytevent.h"
 
 #if PY_MAJOR_VERSION >= 3
 #define PyStr_Check PyUnicode_Check
@@ -41,11 +39,6 @@ void init_tevent(void);
 
 typedef struct {
 	PyObject_HEAD
-	struct tevent_context *ev;
-} TeventContext_Object;
-
-typedef struct {
-	PyObject_HEAD
 	struct tevent_queue *queue;
 } TeventQueue_Object;
 
diff --git a/lib/tevent/pytevent.h b/lib/tevent/pytevent.h
new file mode 100644
index 00000000000..625ea024134
--- /dev/null
+++ b/lib/tevent/pytevent.h
@@ -0,0 +1,34 @@
+/*
+   Unix SMB/CIFS implementation.
+   Python bindings for tevent
+
+   Copyright (C) Jelmer Vernooij 2010
+
+     ** NOTE! The following LGPL license applies to the tevent
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include "replace.h"
+#include <tevent.h>
+
+typedef struct {
+	PyObject_HEAD
+	struct tevent_context *ev;
+} TeventContext_Object;
+
+#define pytevent_Context_AsTeventContext(pyobj) ((TeventContext_Object *)pyobj)->ev
diff --git a/source4/lib/messaging/pymessaging.c b/source4/lib/messaging/pymessaging.c
index f62354b8a02..9f463c0dc39 100644
--- a/source4/lib/messaging/pymessaging.c
+++ b/source4/lib/messaging/pymessaging.c
@@ -34,6 +34,7 @@
 #include "librpc/rpc/dcerpc.h"
 #include "librpc/gen_ndr/server_id.h"
 #include <pytalloc.h>
+#include <pytevent.h>
 
 void initmessaging(void);
 
@@ -75,19 +76,21 @@ typedef struct {
 	PyObject_HEAD
 	TALLOC_CTX *mem_ctx;
 	struct imessaging_context *msg_ctx;
+	PyObject *py_ev;
 } imessaging_Object;
 
 static PyObject *py_imessaging_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)
 {
 	struct tevent_context *ev;
-	const char *kwnames[] = { "own_id", "lp_ctx", NULL };
+	const char *kwnames[] = { "own_id", "lp_ctx", "ev", NULL };
 	PyObject *own_id = Py_None;
 	PyObject *py_lp_ctx = Py_None;
+	PyObject *py_ev = Py_None;
 	imessaging_Object *ret;
 	struct loadparm_context *lp_ctx;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:connect", 
-		discard_const_p(char *, kwnames), &own_id, &py_lp_ctx)) {
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:connect",
+					 discard_const_p(char *, kwnames), &own_id, &py_lp_ctx, &py_ev)) {
 		return NULL;
 	}
 
@@ -104,7 +107,22 @@ static PyObject *py_imessaging_connect(PyTypeObject *self, PyObject *args, PyObj
 		return NULL;
 	}
 
-	ev = s4_event_context_init(ret->mem_ctx);
+	if (py_ev == Py_None) {
+		ev = s4_event_context_init(ret->mem_ctx);
+		ret->py_ev = Py_None;
+	} else {
+		if (!py_check_dcerpc_type(py_ev, "tevent", "Context")) {
+			PyErr_SetString(PyExc_TypeError, "tevent Context object required");
+			return NULL;
+		}
+		ret->py_ev = py_ev;
+		ev = pytevent_Context_AsTeventContext(py_ev);
+		if (ev == NULL) {
+			PyErr_NoMemory();
+			return NULL;
+		}
+	}
+	Py_INCREF(ret->py_ev);
 
 	if (own_id != Py_None) {
 		struct server_id server_id;
@@ -135,6 +153,7 @@ static void py_imessaging_dealloc(PyObject *self)
 {
 	imessaging_Object *iface = (imessaging_Object *)self;
 	talloc_free(iface->msg_ctx);
+	Py_DECREF(iface->py_ev);
 	self->ob_type->tp_free(self);
 }
 
-- 
2.12.0.246.ga2ecc84866-goog


From 9ddb41cebfb28ad2468cdb0af36f2b4e000c88b3 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 8 Mar 2017 11:04:50 +1300
Subject: [PATCH 41/43] pytevent: Allow other parts of Samba to consume tevent
 python bindings

This will make it possible for pymessaging to consume a pytevent created context, and so
make pymessaging practical

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 .../smbdotconf/logon/autheventnotification.xml     |  2 --
 source4/lib/messaging/pymessaging.c                | 27 ++++------------------
 2 files changed, 4 insertions(+), 25 deletions(-)

diff --git a/docs-xml/smbdotconf/logon/autheventnotification.xml b/docs-xml/smbdotconf/logon/autheventnotification.xml
index a42d98c8e86..cf7ac53c693 100644
--- a/docs-xml/smbdotconf/logon/autheventnotification.xml
+++ b/docs-xml/smbdotconf/logon/autheventnotification.xml
@@ -9,8 +9,6 @@
 	Samba's python bindings can listen to these events by
 	registering as the service
 	<filename moreinfo="none">auth_event</filename>.</para>
-
-	<para>Samba must be compiled with glib-json support for this option to be effective</para>
 </description>
 
 <value type="default">no</value>
diff --git a/source4/lib/messaging/pymessaging.c b/source4/lib/messaging/pymessaging.c
index 9f463c0dc39..5022e41911f 100644
--- a/source4/lib/messaging/pymessaging.c
+++ b/source4/lib/messaging/pymessaging.c
@@ -34,7 +34,6 @@
 #include "librpc/rpc/dcerpc.h"
 #include "librpc/gen_ndr/server_id.h"
 #include <pytalloc.h>
-#include <pytevent.h>
 
 void initmessaging(void);
 
@@ -76,21 +75,19 @@ typedef struct {
 	PyObject_HEAD
 	TALLOC_CTX *mem_ctx;
 	struct imessaging_context *msg_ctx;
-	PyObject *py_ev;
 } imessaging_Object;
 
 static PyObject *py_imessaging_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)
 {
 	struct tevent_context *ev;
-	const char *kwnames[] = { "own_id", "lp_ctx", "ev", NULL };
+	const char *kwnames[] = { "own_id", "lp_ctx", NULL };
 	PyObject *own_id = Py_None;
 	PyObject *py_lp_ctx = Py_None;
-	PyObject *py_ev = Py_None;
 	imessaging_Object *ret;
 	struct loadparm_context *lp_ctx;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:connect",
-					 discard_const_p(char *, kwnames), &own_id, &py_lp_ctx, &py_ev)) {
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:connect",
+		discard_const_p(char *, kwnames), &own_id, &py_lp_ctx)) {
 		return NULL;
 	}
 
@@ -107,22 +104,7 @@ static PyObject *py_imessaging_connect(PyTypeObject *self, PyObject *args, PyObj
 		return NULL;
 	}
 
-	if (py_ev == Py_None) {
-		ev = s4_event_context_init(ret->mem_ctx);
-		ret->py_ev = Py_None;
-	} else {
-		if (!py_check_dcerpc_type(py_ev, "tevent", "Context")) {
-			PyErr_SetString(PyExc_TypeError, "tevent Context object required");
-			return NULL;
-		}
-		ret->py_ev = py_ev;
-		ev = pytevent_Context_AsTeventContext(py_ev);
-		if (ev == NULL) {
-			PyErr_NoMemory();
-			return NULL;
-		}
-	}
-	Py_INCREF(ret->py_ev);
+	ev = s4_event_context_init(ret->mem_ctx);
 
 	if (own_id != Py_None) {
 		struct server_id server_id;
@@ -153,7 +135,6 @@ static void py_imessaging_dealloc(PyObject *self)
 {
 	imessaging_Object *iface = (imessaging_Object *)self;
 	talloc_free(iface->msg_ctx);
-	Py_DECREF(iface->py_ev);
 	self->ob_type->tp_free(self);
 }
 
-- 
2.12.0.246.ga2ecc84866-goog


From 61820f984bfcfce19336ee8cf8845a36695461d0 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 8 Mar 2017 11:05:11 +1300
Subject: [PATCH 42/43] fix auth_log json message

---
 docs-xml/smbdotconf/logon/autheventnotification.xml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/docs-xml/smbdotconf/logon/autheventnotification.xml b/docs-xml/smbdotconf/logon/autheventnotification.xml
index cf7ac53c693..a42d98c8e86 100644
--- a/docs-xml/smbdotconf/logon/autheventnotification.xml
+++ b/docs-xml/smbdotconf/logon/autheventnotification.xml
@@ -9,6 +9,8 @@
 	Samba's python bindings can listen to these events by
 	registering as the service
 	<filename moreinfo="none">auth_event</filename>.</para>
+
+	<para>Samba must be compiled with glib-json support for this option to be effective</para>
 </description>
 
 <value type="default">no</value>
-- 
2.12.0.246.ga2ecc84866-goog


From 67cef355749ec73ec3a9edbf08d0182c46cad404 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 8 Mar 2017 11:05:48 +1300
Subject: [PATCH 43/43] pymessaging: Allow an event context to be passed in to
 py_imessaging_connect()

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/lib/messaging/pymessaging.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/source4/lib/messaging/pymessaging.c b/source4/lib/messaging/pymessaging.c
index 5022e41911f..9f463c0dc39 100644
--- a/source4/lib/messaging/pymessaging.c
+++ b/source4/lib/messaging/pymessaging.c
@@ -34,6 +34,7 @@
 #include "librpc/rpc/dcerpc.h"
 #include "librpc/gen_ndr/server_id.h"
 #include <pytalloc.h>
+#include <pytevent.h>
 
 void initmessaging(void);
 
@@ -75,19 +76,21 @@ typedef struct {
 	PyObject_HEAD
 	TALLOC_CTX *mem_ctx;
 	struct imessaging_context *msg_ctx;
+	PyObject *py_ev;
 } imessaging_Object;
 
 static PyObject *py_imessaging_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)
 {
 	struct tevent_context *ev;
-	const char *kwnames[] = { "own_id", "lp_ctx", NULL };
+	const char *kwnames[] = { "own_id", "lp_ctx", "ev", NULL };
 	PyObject *own_id = Py_None;
 	PyObject *py_lp_ctx = Py_None;
+	PyObject *py_ev = Py_None;
 	imessaging_Object *ret;
 	struct loadparm_context *lp_ctx;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:connect",
-		discard_const_p(char *, kwnames), &own_id, &py_lp_ctx)) {
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:connect",
+					 discard_const_p(char *, kwnames), &own_id, &py_lp_ctx, &py_ev)) {
 		return NULL;
 	}
 
@@ -104,7 +107,22 @@ static PyObject *py_imessaging_connect(PyTypeObject *self, PyObject *args, PyObj
 		return NULL;
 	}
 
-	ev = s4_event_context_init(ret->mem_ctx);
+	if (py_ev == Py_None) {
+		ev = s4_event_context_init(ret->mem_ctx);
+		ret->py_ev = Py_None;
+	} else {
+		if (!py_check_dcerpc_type(py_ev, "tevent", "Context")) {
+			PyErr_SetString(PyExc_TypeError, "tevent Context object required");
+			return NULL;
+		}
+		ret->py_ev = py_ev;
+		ev = pytevent_Context_AsTeventContext(py_ev);
+		if (ev == NULL) {
+			PyErr_NoMemory();
+			return NULL;
+		}
+	}
+	Py_INCREF(ret->py_ev);
 
 	if (own_id != Py_None) {
 		struct server_id server_id;
@@ -135,6 +153,7 @@ static void py_imessaging_dealloc(PyObject *self)
 {
 	imessaging_Object *iface = (imessaging_Object *)self;
 	talloc_free(iface->msg_ctx);
+	Py_DECREF(iface->py_ev);
 	self->ob_type->tp_free(self);
 }
 
-- 
2.12.0.246.ga2ecc84866-goog



More information about the samba-technical mailing list