[Patches] The way to remove gensec_update_ev()

Stefan Metzmacher metze at samba.org
Tue Jun 13 22:04:55 UTC 2017


Hi,

here's the next chunk for the LDAP server.

Also available under:
https://git.samba.org/?p=metze/samba/wip.git;a=shortlog;h=refs/heads/master3-gensec-ok

It just passed a private autobuild.

Please review and push:-)

Thanks!
metze

Am 29.05.2017 um 10:40 schrieb Andrew Bartlett:
> On Mon, 2017-05-29 at 09:55 +0200, Stefan Metzmacher wrote:
>> Hi Andrew,
>>
>> it seems I was to optimistic while removing the
>> inhibit_timeout_processing hack. There's a bit more to do
>> before we can remove it.
>>
>> I have also a pending commit to fix a talloc_steal vs. talloc_reparent
>> and the removale of py_com.
>>
>> Please review and push.
>>
>> Thanks!
>> metze
> 
> Thank you so much for getting back to me so promptly with that.  I'll
> test it against the failing configuration in the morning and push it.
> 
> Thanks!
> 
> Andrew Bartlett
> 

-------------- next part --------------
From c24c56d74eb2229cbf8f30fb2d02cc55814db1dd Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 20 Dec 2013 08:52:52 +0100
Subject: [PATCH 01/30] s4:auth/gensec: let GENSEC_FEATURE_SESSION_KEY result
 in GSS_C_INTEG_FLAG

This is important to allow the 'new_spnego' with mech_list protection to work
for a SMB session setup.

This is not strictly needed as we always announce GENSEC_FEATURE_SESSION_KEY
in gensec_gssapi_have_feature(), but it's better to send GSS_C_INTEG_FLAG
over the wire.

This may prevent a ticket from a Samba client to an SMB server
(particularly a DC) being misused to connect to the LDAP server on that
DC, as the LDAP server will require GSSAPI signing of the connection.

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

diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index dd03a96..8bc5452 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -177,6 +177,9 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
 		gensec_gssapi_state->gss_want_flags |= GSS_C_SEQUENCE_FLAG;
 	}
 
+	if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
+		gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
+	}
 	if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
 		gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
 	}
-- 
1.9.1


From 8a5a072c56bc695d661f49d5991882823b48f7fd Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 19:07:04 +0200
Subject: [PATCH 02/30] s4:ldap_server: use talloc_zero() in
 ldapsrv_init_reply()

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

diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c
index 1f0c7af..5e8ce64 100644
--- a/source4/ldap_server/ldap_backend.c
+++ b/source4/ldap_server/ldap_backend.c
@@ -237,11 +237,11 @@ struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, uint8_t type
 {
 	struct ldapsrv_reply *reply;
 
-	reply = talloc(call, struct ldapsrv_reply);
+	reply = talloc_zero(call, struct ldapsrv_reply);
 	if (!reply) {
 		return NULL;
 	}
-	reply->msg = talloc(reply, struct ldap_message);
+	reply->msg = talloc_zero(reply, struct ldap_message);
 	if (reply->msg == NULL) {
 		talloc_free(reply);
 		return NULL;
-- 
1.9.1


From 0cc0b16f2818a7a2948389b791b2ff2c7d6b513b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 16:37:21 +0200
Subject: [PATCH 03/30] s4:ldap_server: introduce a ldapsrv_call_destructor()

This makes sure that a call doesn't become an stale
member of the conn->pending_calls list.

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

diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
index 347a17d..062c3fc 100644
--- a/source4/ldap_server/ldap_server.c
+++ b/source4/ldap_server/ldap_server.c
@@ -254,6 +254,18 @@ failed:
 	return -1;
 }
 
+static int ldapsrv_call_destructor(struct ldapsrv_call *call)
+{
+	if (call->conn == NULL) {
+		return 0;
+	}
+
+	DLIST_REMOVE(call->conn->pending_calls, call);
+
+	call->conn = NULL;
+	return 0;
+}
+
 static struct tevent_req *ldapsrv_process_call_send(TALLOC_CTX *mem_ctx,
 						    struct tevent_context *ev,
 						    struct tevent_queue *call_queue,
@@ -504,6 +516,7 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq)
 		ldapsrv_terminate_connection(conn, "no memory");
 		return;
 	}
+	talloc_set_destructor(call, ldapsrv_call_destructor);
 
 	call->conn = conn;
 
-- 
1.9.1


From 8e4d73d2c963ce8b4664b40173c9bae1c24a634f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 13 May 2017 08:20:00 +0200
Subject: [PATCH 04/30] s4:ldap_server: don't log Unbind and Abandon requests.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_backend.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c
index 5e8ce64..d4e9030 100644
--- a/source4/ldap_server/ldap_backend.c
+++ b/source4/ldap_server/ldap_backend.c
@@ -1257,6 +1257,8 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
 
 		switch(call->request->type) {
 		case LDAP_TAG_BindRequest:
+		case LDAP_TAG_UnbindRequest:
+		case LDAP_TAG_AbandonRequest:
 			log = false;
 			break;
 		case LDAP_TAG_ExtendedResponse: {
-- 
1.9.1


From 6172e59eba6be35a8cdc3dc436ca166f1aeeefaa Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 16:51:15 +0200
Subject: [PATCH 05/30] s4:ldap_server: add call->wait_send/recv infrastructure

If it is set by the dispatch functions, the core server
will use call->wait_send() and wait for it to finally
return frim call->wait_recv() before it asks for the
next incoming pdu.

This can be used to implement bind as async operations.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_server.c | 59 +++++++++++++++++++++++++++++++++++++--
 source4/ldap_server/ldap_server.h |  6 ++++
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
index 062c3fc..6a60532 100644
--- a/source4/ldap_server/ldap_server.c
+++ b/source4/ldap_server/ldap_server.c
@@ -578,7 +578,8 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq)
 	conn->active_call = subreq;
 }
 
-
+static void ldapsrv_call_wait_done(struct tevent_req *subreq);
+static void ldapsrv_call_writev_start(struct ldapsrv_call *call);
 static void ldapsrv_call_writev_done(struct tevent_req *subreq);
 
 static void ldapsrv_call_process_done(struct tevent_req *subreq)
@@ -588,7 +589,6 @@ static void ldapsrv_call_process_done(struct tevent_req *subreq)
 		struct ldapsrv_call);
 	struct ldapsrv_connection *conn = call->conn;
 	NTSTATUS status;
-	DATA_BLOB blob = data_blob_null;
 
 	conn->active_call = NULL;
 
@@ -599,6 +599,61 @@ static void ldapsrv_call_process_done(struct tevent_req *subreq)
 		return;
 	}
 
+	if (call->wait_send != NULL) {
+		subreq = call->wait_send(call,
+					 conn->connection->event.ctx,
+					 call->wait_private);
+		if (subreq == NULL) {
+			ldapsrv_terminate_connection(conn,
+					"ldapsrv_call_process_done: "
+					"call->wait_send - no memory");
+			return;
+		}
+		tevent_req_set_callback(subreq,
+					ldapsrv_call_wait_done,
+					call);
+		conn->active_call = subreq;
+		return;
+	}
+
+	ldapsrv_call_writev_start(call);
+}
+
+static void ldapsrv_call_wait_done(struct tevent_req *subreq)
+{
+	struct ldapsrv_call *call =
+		tevent_req_callback_data(subreq,
+		struct ldapsrv_call);
+	struct ldapsrv_connection *conn = call->conn;
+	NTSTATUS status;
+
+	conn->active_call = NULL;
+
+	status = call->wait_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		const char *reason;
+
+		reason = talloc_asprintf(call, "ldapsrv_call_wait_done: "
+					 "call->wait_recv() - %s",
+					 nt_errstr(status));
+		if (reason == NULL) {
+			reason = nt_errstr(status);
+		}
+
+		ldapsrv_terminate_connection(conn, reason);
+		return;
+	}
+
+	ldapsrv_call_writev_start(call);
+}
+
+static void ldapsrv_call_writev_start(struct ldapsrv_call *call)
+{
+	struct ldapsrv_connection *conn = call->conn;
+	DATA_BLOB blob = data_blob_null;
+	struct tevent_req *subreq = NULL;
+
 	/* build all the replies into a single blob */
 	while (call->replies) {
 		DATA_BLOB b;
diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h
index 337c974..d3e31fb 100644
--- a/source4/ldap_server/ldap_server.h
+++ b/source4/ldap_server/ldap_server.h
@@ -73,6 +73,12 @@ struct ldapsrv_call {
 	} *replies;
 	struct iovec out_iov;
 
+	struct tevent_req *(*wait_send)(TALLOC_CTX *mem_ctx,
+					struct tevent_context *ev,
+					void *private_data);
+	NTSTATUS (*wait_recv)(struct tevent_req *req);
+	void *wait_private;
+
 	struct tevent_req *(*postprocess_send)(TALLOC_CTX *mem_ctx,
 					       struct tevent_context *ev,
 					       void *private_data);
-- 
1.9.1


From 050fe7297d0325c23ec3aefba893a9ce1e0db749 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 13 Jun 2017 15:02:41 +0200
Subject: [PATCH 06/30] s4:ldap_server: improve ldapsrv_UnbindRequest
 implementation

We should abandon outstanding requests and disconnect the connection.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 68 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 986ecbf..bb6b049 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -23,6 +23,7 @@
 #include "smbd/service.h"
 #include <ldb.h>
 #include <ldb_errors.h>
+#include "../lib/util/dlinklist.h"
 #include "dsdb/samdb/samdb.h"
 #include "auth/gensec/gensec.h"
 #include "auth/gensec/gensec_tstream.h"
@@ -481,8 +482,73 @@ NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
 	return NT_STATUS_OK;
 }
 
+struct ldapsrv_unbind_wait_context {
+	uint8_t dummy;
+};
+
+struct ldapsrv_unbind_wait_state {
+	uint8_t dummy;
+};
+
+static struct tevent_req *ldapsrv_unbind_wait_send(TALLOC_CTX *mem_ctx,
+						 struct tevent_context *ev,
+						 void *private_data)
+{
+	struct ldapsrv_unbind_wait_context *unbind_wait =
+		talloc_get_type_abort(private_data,
+		struct ldapsrv_unbind_wait_context);
+	struct tevent_req *req;
+	struct ldapsrv_unbind_wait_state *state;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct ldapsrv_unbind_wait_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	(void)unbind_wait;
+
+	tevent_req_nterror(req, NT_STATUS_LOCAL_DISCONNECT);
+	return tevent_req_post(req, ev);
+}
+
+static NTSTATUS ldapsrv_unbind_wait_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
+}
+
+static NTSTATUS ldapsrv_unbind_wait_setup(struct ldapsrv_call *call)
+{
+	struct ldapsrv_unbind_wait_context *unbind_wait = NULL;
+
+	if (call->wait_private != NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	unbind_wait = talloc_zero(call, struct ldapsrv_unbind_wait_context);
+	if (unbind_wait == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	call->wait_private = unbind_wait;
+	call->wait_send = ldapsrv_unbind_wait_send;
+	call->wait_recv = ldapsrv_unbind_wait_recv;
+	return NT_STATUS_OK;
+}
+
 NTSTATUS ldapsrv_UnbindRequest(struct ldapsrv_call *call)
 {
+	struct ldapsrv_call *c = NULL;
+	struct ldapsrv_call *n = NULL;
+
 	DEBUG(10, ("UnbindRequest\n"));
-	return NT_STATUS_OK;
+
+	for (c = call->conn->pending_calls; c != NULL; c = n) {
+		n = c->next;
+
+		DLIST_REMOVE(call->conn->pending_calls, c);
+		TALLOC_FREE(c);
+	}
+
+	return ldapsrv_unbind_wait_setup(call);
 }
-- 
1.9.1


From d64e976febb421245e64fa9bafe6f9682dfa65ec Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 17:05:02 +0200
Subject: [PATCH 07/30] s4:auth: add authenticate_ldap_simple_bind_send/recv

TODO: we need to make the backend async.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/auth/auth.h             | 12 +++++++++
 source4/auth/ntlm/auth_simple.c | 60 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/source4/auth/auth.h b/source4/auth/auth.h
index c12e233..2dc0d8c 100644
--- a/source4/auth/auth.h
+++ b/source4/auth/auth.h
@@ -160,6 +160,18 @@ NTSTATUS auth_check_password(struct auth4_context *auth_ctx,
 NTSTATUS auth4_init(void);
 NTSTATUS auth_register(TALLOC_CTX *mem_ctx, const struct auth_operations *ops);
 NTSTATUS server_service_auth_init(TALLOC_CTX *ctx);
+struct tevent_req *authenticate_ldap_simple_bind_send(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,
+					bool using_tls,
+					const char *dn,
+					const char *password);
+NTSTATUS authenticate_ldap_simple_bind_recv(struct tevent_req *req,
+					TALLOC_CTX *mem_ctx,
+					struct auth_session_info **session_info);
 NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 				       struct tevent_context *ev,
 				       struct imessaging_context *msg,
diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c
index cd96113..142bd40 100644
--- a/source4/auth/ntlm/auth_simple.c
+++ b/source4/auth/ntlm/auth_simple.c
@@ -22,9 +22,49 @@
 */
 
 #include "includes.h"
+#include <tevent.h>
+#include "lib/util/tevent_ntstatus.h"
 #include "auth/auth.h"
 #include "dsdb/samdb/samdb.h"
 
+struct authenticate_ldap_simple_bind_state {
+	struct auth_session_info *session_info;
+};
+
+_PUBLIC_ struct tevent_req *authenticate_ldap_simple_bind_send(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,
+					bool using_tls,
+					const char *dn,
+					const char *password)
+{
+	struct tevent_req *req = NULL;
+	struct authenticate_ldap_simple_bind_state *state = NULL;
+	NTSTATUS status;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct authenticate_ldap_simple_bind_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	status = authenticate_ldap_simple_bind(state, ev, msg, lp_ctx,
+					       remote_address,
+					       local_address,
+					       using_tls,
+					       dn, password,
+					       &state->session_info);
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
+	}
+
+	tevent_req_done(req);
+	return tevent_req_post(req, ev);
+}
+
 _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 						struct tevent_context *ev,
 						struct imessaging_context *msg,
@@ -154,3 +194,23 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 	return nt_status;
 }
 
+_PUBLIC_ NTSTATUS authenticate_ldap_simple_bind_recv(struct tevent_req *req,
+					TALLOC_CTX *mem_ctx,
+					struct auth_session_info **session_info)
+{
+	struct authenticate_ldap_simple_bind_state *state =
+		tevent_req_data(req,
+		struct authenticate_ldap_simple_bind_state);
+	NTSTATUS status;
+
+	*session_info = NULL;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		tevent_req_received(req);
+		return status;
+	}
+
+	*session_info = talloc_move(mem_ctx, &state->session_info);
+	tevent_req_received(req);
+	return NT_STATUS_OK;
+}
-- 
1.9.1


From dc6496b72894a385d1ebc5c63998594e3a66cd95 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 18:04:15 +0200
Subject: [PATCH 08/30] s4:ldap_server: implement async BindSimple

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 169 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 149 insertions(+), 20 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index bb6b049..23d34d2 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -60,21 +60,107 @@ static char *ldapsrv_bind_error_msg(TALLOC_CTX *mem_ctx,
 	return msg;
 }
 
+struct ldapsrv_bind_wait_context {
+	struct ldapsrv_reply *reply;
+	struct tevent_req *req;
+	NTSTATUS status;
+	bool done;
+};
 
-static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
+struct ldapsrv_bind_wait_state {
+	uint8_t dummy;
+};
+
+static struct tevent_req *ldapsrv_bind_wait_send(TALLOC_CTX *mem_ctx,
+						 struct tevent_context *ev,
+						 void *private_data)
 {
-	struct ldap_BindRequest *req = &call->request->r.BindRequest;
-	struct ldapsrv_reply *reply;
-	struct ldap_BindResponse *resp;
+	struct ldapsrv_bind_wait_context *bind_wait =
+		talloc_get_type_abort(private_data,
+		struct ldapsrv_bind_wait_context);
+	struct tevent_req *req;
+	struct ldapsrv_bind_wait_state *state;
 
-	int result;
-	const char *errstr;
+	req = tevent_req_create(mem_ctx, &state,
+				struct ldapsrv_bind_wait_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	bind_wait->req = req;
 
-	struct auth_session_info *session_info;
+	tevent_req_defer_callback(req, ev);
 
-	NTSTATUS status;
+	if (!bind_wait->done) {
+		return req;
+	}
+
+	if (tevent_req_nterror(req, bind_wait->status)) {
+		return tevent_req_post(req, ev);
+	}
+
+	tevent_req_done(req);
+	return tevent_req_post(req, ev);
+}
+
+static NTSTATUS ldapsrv_bind_wait_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
+}
+
+static NTSTATUS ldapsrv_bind_wait_setup(struct ldapsrv_call *call,
+					struct ldapsrv_reply *reply)
+{
+	struct ldapsrv_bind_wait_context *bind_wait = NULL;
+
+	if (call->wait_private != NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	bind_wait = talloc_zero(call, struct ldapsrv_bind_wait_context);
+	if (bind_wait == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	bind_wait->reply = reply;
+
+	call->wait_private = bind_wait;
+	call->wait_send = ldapsrv_bind_wait_send;
+	call->wait_recv = ldapsrv_bind_wait_recv;
+	return NT_STATUS_OK;
+}
 
+static void ldapsrv_bind_wait_finished(struct ldapsrv_call *call,
+				       NTSTATUS status)
+{
+	struct ldapsrv_bind_wait_context *bind_wait =
+		talloc_get_type_abort(call->wait_private,
+		struct ldapsrv_bind_wait_context);
+
+	bind_wait->done = true;
+	bind_wait->status = status;
+
+	if (bind_wait->req == NULL) {
+		return;
+	}
+
+	if (tevent_req_nterror(bind_wait->req, status)) {
+		return;
+	}
+
+	tevent_req_done(bind_wait->req);
+}
+
+static void ldapsrv_BindSimple_done(struct tevent_req *subreq);
+
+static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
+{
+	struct ldap_BindRequest *req = &call->request->r.BindRequest;
+	struct ldapsrv_reply *reply = NULL;
+	struct ldap_BindResponse *resp = NULL;
+	int result;
+	const char *errstr = NULL;
+	NTSTATUS status;
 	bool using_tls = call->conn->sockets.active == call->conn->sockets.tls;
+	struct tevent_req *subreq = NULL;
 
 	DEBUG(10, ("BindSimple dn: %s\n",req->dn));
 
@@ -95,17 +181,61 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 		goto do_reply;
 	}
 
-	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,
-					       using_tls,
-					       req->dn,
-					       req->creds.password,
-					       &session_info);
+	subreq = authenticate_ldap_simple_bind_send(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,
+					using_tls,
+					req->dn,
+					req->creds.password);
+	if (subreq == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	tevent_req_set_callback(subreq, ldapsrv_BindSimple_done, call);
 
+	status = ldapsrv_bind_wait_setup(call, reply);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(subreq);
+		return status;
+	}
+
+	/*
+	 * The rest will be async.
+	 */
+	return NT_STATUS_OK;
+
+do_reply:
+	resp = &reply->msg->r.BindResponse;
+	resp->response.resultcode = result;
+	resp->response.errormessage = errstr;
+	resp->response.dn = NULL;
+	resp->response.referral = NULL;
+	resp->SASL.secblob = NULL;
+
+	ldapsrv_queue_reply(call, reply);
+	return NT_STATUS_OK;
+}
+
+static void ldapsrv_BindSimple_done(struct tevent_req *subreq)
+{
+	struct ldapsrv_call *call =
+		tevent_req_callback_data(subreq,
+		struct ldapsrv_call);
+	struct ldapsrv_bind_wait_context *bind_wait =
+		talloc_get_type_abort(call->wait_private,
+		struct ldapsrv_bind_wait_context);
+	struct ldapsrv_reply *reply = bind_wait->reply;
+	struct auth_session_info *session_info = NULL;
+	NTSTATUS status;
+	struct ldap_BindResponse *resp = NULL;
+	int result;
+	const char *errstr = NULL;
+
+	status = authenticate_ldap_simple_bind_recv(subreq,
+						    call,
+						    &session_info);
 	if (NT_STATUS_IS_OK(status)) {
 		result = LDAP_SUCCESS;
 		errstr = NULL;
@@ -132,7 +262,6 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 						0x0C0903A9, status);
 	}
 
-do_reply:
 	resp = &reply->msg->r.BindResponse;
 	resp->response.resultcode = result;
 	resp->response.errormessage = errstr;
@@ -141,7 +270,7 @@ do_reply:
 	resp->SASL.secblob = NULL;
 
 	ldapsrv_queue_reply(call, reply);
-	return NT_STATUS_OK;
+	ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
 }
 
 struct ldapsrv_sasl_postprocess_context {
-- 
1.9.1


From 054a1822d5958475aa7d24e9b8de3fe37aae67db Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 18:53:06 +0200
Subject: [PATCH 09/30] s4:auth: make authenticate_ldap_simple_bind*() use
 auth_check_password_send/recv

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

diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c
index 142bd40..c3bc25a 100644
--- a/source4/auth/ntlm/auth_simple.c
+++ b/source4/auth/ntlm/auth_simple.c
@@ -28,9 +28,14 @@
 #include "dsdb/samdb/samdb.h"
 
 struct authenticate_ldap_simple_bind_state {
+	bool using_tls;
+	struct auth4_context *auth_context;
+	struct auth_usersupplied_info *user_info;
 	struct auth_session_info *session_info;
 };
 
+static void authenticate_ldap_simple_bind_done(struct tevent_req *subreq);
+
 _PUBLIC_ struct tevent_req *authenticate_ldap_simple_bind_send(TALLOC_CTX *mem_ctx,
 					struct tevent_context *ev,
 					struct imessaging_context *msg,
@@ -43,6 +48,10 @@ _PUBLIC_ struct tevent_req *authenticate_ldap_simple_bind_send(TALLOC_CTX *mem_c
 {
 	struct tevent_req *req = NULL;
 	struct authenticate_ldap_simple_bind_state *state = NULL;
+	struct auth_usersupplied_info *user_info = NULL;
+	const char *nt4_domain = NULL;
+	const char *nt4_username = NULL;
+	struct tevent_req *subreq = NULL;
 	NTSTATUS status;
 
 	req = tevent_req_create(mem_ctx, &state,
@@ -50,76 +59,23 @@ _PUBLIC_ struct tevent_req *authenticate_ldap_simple_bind_send(TALLOC_CTX *mem_c
 	if (req == NULL) {
 		return NULL;
 	}
+	state->using_tls = using_tls;
 
-	status = authenticate_ldap_simple_bind(state, ev, msg, lp_ctx,
-					       remote_address,
-					       local_address,
-					       using_tls,
-					       dn, password,
-					       &state->session_info);
+	status = auth_context_create(state, ev, msg, lp_ctx,
+				     &state->auth_context);
 	if (tevent_req_nterror(req, status)) {
 		return tevent_req_post(req, ev);
 	}
 
-	tevent_req_done(req);
-	return tevent_req_post(req, ev);
-}
-
-_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,
-						bool using_tls,
-						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;
-	uint8_t authoritative = 0;
-	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-	const char *nt4_domain = NULL;
-	const char *nt4_username = NULL;
-	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;
-	}
-
-	nt_status = auth_context_create(tmp_ctx,
-					ev, msg,
-					lp_ctx,
-					&auth_context);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		talloc_free(tmp_ctx);
-		return nt_status;
-	}
-
-	/*
-	 * We check the error after building the user_info so we can
-	 * log a failure to find the user correctly
-	 */
-	nt_status = crack_auto_name_to_nt4_name(tmp_ctx, ev, lp_ctx, dn,
-						&nt4_domain, &nt4_username);
-
-	user_info = talloc_zero(tmp_ctx, struct auth_usersupplied_info);
-	if (!user_info) {
-		talloc_free(tmp_ctx);
-		return NT_STATUS_NO_MEMORY;
+	user_info = talloc_zero(state, struct auth_usersupplied_info);
+	if (tevent_req_nomem(user_info, req)) {
+		return tevent_req_post(req, ev);
 	}
+	state->user_info = user_info;
 
 	user_info->client.account_name = dn;
 	/* No client.domain_name, use account_name instead */
-	user_info->mapped.account_name = nt4_username;
-	user_info->mapped.domain_name = nt4_domain;
+	/* user_info->mapped.* will be filled below */
 
 	user_info->workstation_name = NULL;
 
@@ -136,6 +92,9 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 
 	user_info->password_state = AUTH_PASSWORD_PLAIN;
 	user_info->password.plaintext = talloc_strdup(user_info, password);
+	if (tevent_req_nomem(user_info->password.plaintext, req)) {
+		return tevent_req_post(req, ev);
+	}
 
 	user_info->flags = USER_INFO_CASE_INSENSITIVE_USERNAME |
 		USER_INFO_DONT_CHECK_UNIX_ACCOUNT;
@@ -146,39 +105,76 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 		MSV1_0_CLEARTEXT_PASSWORD_ALLOWED |
 		MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED;
 
-	/* This is a check for the crack names call above */
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		log_authentication_event(auth_context->msg_ctx,
-					 auth_context->lp_ctx,
-					 user_info, nt_status,
+	status = crack_auto_name_to_nt4_name(state, ev, lp_ctx, dn,
+					     &nt4_domain, &nt4_username);
+	if (!NT_STATUS_IS_OK(status)) {
+		log_authentication_event(msg, lp_ctx,
+					 user_info, status,
 					 NULL, NULL, NULL, NULL);
-		talloc_free(tmp_ctx);
-		return nt_status;
+	}
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
 	}
 
-	/* Now that we have checked if the crack names worked, set mapped_state */
+	user_info->mapped.account_name = nt4_username;
+	user_info->mapped.domain_name = nt4_domain;
 	user_info->mapped_state = true;
 
-	nt_status = auth_check_password(auth_context, tmp_ctx, user_info,
-					&user_info_dc, &authoritative);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		talloc_free(tmp_ctx);
-		return nt_status;
+	subreq = auth_check_password_send(state, ev,
+					  state->auth_context,
+					  state->user_info);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, authenticate_ldap_simple_bind_done, req);
+
+	return req;
+}
+
+static void authenticate_ldap_simple_bind_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+		struct tevent_req);
+	struct authenticate_ldap_simple_bind_state *state =
+		tevent_req_data(req,
+		struct authenticate_ldap_simple_bind_state);
+	struct auth4_context *auth_context = state->auth_context;
+	struct auth_usersupplied_info *user_info = state->user_info;
+	const char *nt4_username = user_info->mapped.account_name;
+	const struct tsocket_address *remote_address = user_info->remote_host;
+	const struct tsocket_address *local_address = user_info->local_host;
+	const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
+	struct auth_user_info_dc *user_info_dc = NULL;
+	uint8_t authoritative = 0;
+	uint32_t flags = 0;
+	NTSTATUS nt_status;
+
+	if (state->using_tls) {
+		transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
+	}
+
+	nt_status = auth_check_password_recv(subreq, state,
+					     &user_info_dc,
+					     &authoritative);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, nt_status)) {
+		return;
 	}
 
 	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,
+							state,
 							user_info_dc,
 							nt4_username,
 							flags,
-							session_info);
-
-	if (NT_STATUS_IS_OK(nt_status)) {
-		talloc_steal(mem_ctx, *session_info);
+							&state->session_info);
+	if (tevent_req_nterror(req, nt_status)) {
+		return;
 	}
 
 	log_successful_authz_event(auth_context->msg_ctx,
@@ -188,10 +184,9 @@ _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind(TALLOC_CTX *mem_ctx,
 				   "LDAP",
 				   "simple bind",
 				   transport_protection,
-				   *session_info);
+				   state->session_info);
 
-	talloc_free(tmp_ctx);
-	return nt_status;
+	tevent_req_done(req);
 }
 
 _PUBLIC_ NTSTATUS authenticate_ldap_simple_bind_recv(struct tevent_req *req,
-- 
1.9.1


From e176b5885aafc51d54c091b7ee694d93c828445a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 19:04:27 +0200
Subject: [PATCH 10/30] s4:ldap_server: add use goto do_reply; to make the
 logic in ldapsrv_BindSASL() more sane

The following patches will simplify the logic by avoiding else branches
by using early returns.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 23d34d2..3f2cd2b 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -401,6 +401,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 			result = LDAP_OPERATIONS_ERROR;
 			errstr = talloc_asprintf(reply, "SASL: Failed to start authentication system: %s", 
 						 nt_errstr(status));
+			goto do_reply;
 		}
 	}
 
@@ -426,6 +427,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
 		result = LDAP_SASL_BIND_IN_PROGRESS;
 		errstr = NULL;
+		goto do_reply;
 	} else if (NT_STATUS_IS_OK(status)) {
 		struct ldapsrv_sasl_postprocess_context *context = NULL;
 
@@ -449,6 +451,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 			errstr = talloc_asprintf(reply,
 						 "SASL:[%s]: Sign or Seal are not allowed if TLS is used",
 						 req->creds.SASL.mechanism);
+			goto do_reply;
 		}
 
 		if (context && conn->sockets.sasl) {
@@ -458,6 +461,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 			errstr = talloc_asprintf(reply,
 						 "SASL:[%s]: Sign or Seal are not allowed if SASL encryption has already been set up",
 						 req->creds.SASL.mechanism);
+			goto do_reply;
 		}
 
 		if (context) {
@@ -484,14 +488,15 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 				errstr = talloc_asprintf(reply,
 						"SASL:[%s]: not allowed if TLS is used.",
 						 req->creds.SASL.mechanism);
-				break;
+				goto do_reply;
+
 			case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES:
 				status = NT_STATUS_NETWORK_ACCESS_DENIED;
 				result = LDAP_STRONG_AUTH_REQUIRED;
 				errstr = talloc_asprintf(reply,
 						 "SASL:[%s]: Sign or Seal are required.",
 						 req->creds.SASL.mechanism);
-				break;
+				goto do_reply;
 			}
 		}
 
@@ -501,6 +506,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 			errstr = talloc_asprintf(reply, 
 						 "SASL:[%s]: Failed to setup SASL socket: %s", 
 						 req->creds.SASL.mechanism, nt_errstr(status));
+			goto do_reply;
 		} else {
 			struct auth_session_info *old_session_info=NULL;
 
@@ -513,6 +519,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 				errstr = talloc_asprintf(reply, 
 							 "SASL:[%s]: Failed to get session info: %s", 
 							 req->creds.SASL.mechanism, nt_errstr(status));
+				goto do_reply;
 			} else {
 				talloc_unlink(conn, old_session_info);
 				
@@ -529,6 +536,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 								 "SASL:[%s]: Failed to advise samdb of new credentials: %s", 
 								 req->creds.SASL.mechanism, 
 								 nt_errstr(status));
+					goto do_reply;
 				}
 			}
 		}
@@ -549,8 +557,10 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		}
 		talloc_unlink(conn, conn->gensec);
 		conn->gensec = NULL;
+		goto do_reply;
 	}
 
+do_reply:
 	resp->response.resultcode = result;
 	resp->response.dn = NULL;
 	resp->response.errormessage = errstr;
-- 
1.9.1


From f251e71ab1b9b1b8a94e8ff707f428317bf4825a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 19:11:43 +0200
Subject: [PATCH 11/30] s4:ldap_server: always allocate resp->SASL.secblob

The code path with resp->SASL.secblob = NULL was completely untested
(and wrong) as ldapsrv_setup_gensec() is very unlikely to ever fail.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 3f2cd2b..4913629 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -382,7 +382,12 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		return NT_STATUS_NO_MEMORY;
 	}
 	resp = &reply->msg->r.BindResponse;
-	
+	/* Windows 2000 mmc doesn't like secblob == NULL and reports a decoding error */
+	resp->SASL.secblob = talloc_zero(reply, DATA_BLOB);
+	if (resp->SASL.secblob == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	conn = call->conn;
 
 	/* 
@@ -416,12 +421,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		status = gensec_update_ev(conn->gensec, reply, conn->connection->event.ctx,
 					  input, &output);
 
-		/* Windows 2000 mmc doesn't like secblob == NULL and reports a decoding error */
-		resp->SASL.secblob = talloc(reply, DATA_BLOB);
-		NT_STATUS_HAVE_NO_MEMORY(resp->SASL.secblob);
 		*resp->SASL.secblob = output;
-	} else {
-		resp->SASL.secblob = NULL;
 	}
 
 	if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
-- 
1.9.1


From 9ca6a69d1bb44d4c630cb8334f0924879e083ca4 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 19:13:49 +0200
Subject: [PATCH 12/30] s4:ldap_server: remove an useless indentation level
 from gensec_update_ev()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 4913629..fb4593d 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -374,6 +374,8 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	int result = 0;
 	const char *errstr=NULL;
 	NTSTATUS status = NT_STATUS_OK;
+	DATA_BLOB input = data_blob_null;
+	DATA_BLOB output = data_blob_null;
 
 	DEBUG(10, ("BindSASL dn: %s\n",req->dn));
 
@@ -410,20 +412,14 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		}
 	}
 
-	if (NT_STATUS_IS_OK(status)) {
-		DATA_BLOB input = data_blob(NULL, 0);
-		DATA_BLOB output = data_blob(NULL, 0);
-
-		if (req->creds.SASL.secblob) {
-			input = *req->creds.SASL.secblob;
-		}
-
-		status = gensec_update_ev(conn->gensec, reply, conn->connection->event.ctx,
-					  input, &output);
-
-		*resp->SASL.secblob = output;
+	if (req->creds.SASL.secblob) {
+		input = *req->creds.SASL.secblob;
 	}
 
+	status = gensec_update_ev(conn->gensec, reply, conn->connection->event.ctx,
+				  input, &output);
+	*resp->SASL.secblob = output;
+
 	if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
 		result = LDAP_SASL_BIND_IN_PROGRESS;
 		errstr = NULL;
-- 
1.9.1


From c2e14005e1e1312d5807bbf8edbdd264bb874a20 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 21:09:08 +0200
Subject: [PATCH 13/30] s4:ldap_server: move invalid credential handling before
 the success handling.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index fb4593d..e36cb1c 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -424,7 +424,21 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		result = LDAP_SASL_BIND_IN_PROGRESS;
 		errstr = NULL;
 		goto do_reply;
-	} else if (NT_STATUS_IS_OK(status)) {
+	}
+
+	if (!NT_STATUS_IS_OK(status)) {
+		status = nt_status_squash(status);
+		if (result == 0) {
+			result = LDAP_INVALID_CREDENTIALS;
+			errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
+							0x0C0904DC, status);
+		}
+		talloc_unlink(conn, conn->gensec);
+		conn->gensec = NULL;
+		goto do_reply;
+	}
+
+	{
 		struct ldapsrv_sasl_postprocess_context *context = NULL;
 
 		result = LDAP_SUCCESS;
@@ -544,16 +558,6 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		}
 		talloc_unlink(conn, conn->gensec);
 		conn->gensec = NULL;
-	} else {
-		status = nt_status_squash(status);
-		if (result == 0) {
-			result = LDAP_INVALID_CREDENTIALS;
-			errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
-							0x0C0904DC, status);
-		}
-		talloc_unlink(conn, conn->gensec);
-		conn->gensec = NULL;
-		goto do_reply;
 	}
 
 do_reply:
-- 
1.9.1


From 7cac23931a37313a258bd750517dd75ab49a534d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 16:04:02 +0200
Subject: [PATCH 14/30] s4:ldap_server: avoid pointless check arround
 LDAP_INVALID_CREDENTIALS

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

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index e36cb1c..06b52fe 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -428,11 +428,9 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 
 	if (!NT_STATUS_IS_OK(status)) {
 		status = nt_status_squash(status);
-		if (result == 0) {
-			result = LDAP_INVALID_CREDENTIALS;
-			errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
-							0x0C0904DC, status);
-		}
+		result = LDAP_INVALID_CREDENTIALS;
+		errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
+						0x0C0904DC, status);
 		talloc_unlink(conn, conn->gensec);
 		conn->gensec = NULL;
 		goto do_reply;
-- 
1.9.1


From 061888b46db040d8db2609dd5b9c5ca972b13c5d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:44:05 +0200
Subject: [PATCH 15/30] s4:ldap_server: make sure we destroy the gensec context
 on error

If the client tries a new bind we need to start with a fresh context.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 06b52fe..5c390b6 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -431,8 +431,6 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		result = LDAP_INVALID_CREDENTIALS;
 		errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
 						0x0C0904DC, status);
-		talloc_unlink(conn, conn->gensec);
-		conn->gensec = NULL;
 		goto do_reply;
 	}
 
@@ -559,6 +557,18 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	}
 
 do_reply:
+	if (result != LDAP_SASL_BIND_IN_PROGRESS) {
+		/*
+		 * We should destroy the gensec context
+		 * when we hit a fatal error.
+		 *
+		 * Note: conn->gensec is already cleared
+		 * for the LDAP_SUCCESS case.
+		 */
+		talloc_unlink(conn, conn->gensec);
+		conn->gensec = NULL;
+	}
+
 	resp->response.resultcode = result;
 	resp->response.dn = NULL;
 	resp->response.errormessage = errstr;
-- 
1.9.1


From 216c9e59f830119b966a0216bdb3039a1b85d959 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 21:11:00 +0200
Subject: [PATCH 16/30] s4:ldap_server: remove indentation level for the valid
 credential case

Check with git show -w.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 181 ++++++++++++++++++++--------------------
 1 file changed, 89 insertions(+), 92 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 5c390b6..337ce12 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -371,6 +371,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	struct ldapsrv_reply *reply;
 	struct ldap_BindResponse *resp;
 	struct ldapsrv_connection *conn;
+	struct ldapsrv_sasl_postprocess_context *context = NULL;
 	int result = 0;
 	const char *errstr=NULL;
 	NTSTATUS status = NT_STATUS_OK;
@@ -434,127 +435,123 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		goto do_reply;
 	}
 
-	{
-		struct ldapsrv_sasl_postprocess_context *context = NULL;
+	result = LDAP_SUCCESS;
+	errstr = NULL;
 
-		result = LDAP_SUCCESS;
-		errstr = NULL;
+	if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
+	    gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
 
-		if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
-		    gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
+		context = talloc(call, struct ldapsrv_sasl_postprocess_context);
+
+		if (!context) {
+			status = NT_STATUS_NO_MEMORY;
+		}
+	}
 
-			context = talloc(call, struct ldapsrv_sasl_postprocess_context);
+	if (context && conn->sockets.tls) {
+		TALLOC_FREE(context);
+		status = NT_STATUS_NOT_SUPPORTED;
+		result = LDAP_UNWILLING_TO_PERFORM;
+		errstr = talloc_asprintf(reply,
+					 "SASL:[%s]: Sign or Seal are not allowed if TLS is used",
+					 req->creds.SASL.mechanism);
+		goto do_reply;
+	}
 
-			if (!context) {
+	if (context && conn->sockets.sasl) {
+		TALLOC_FREE(context);
+		status = NT_STATUS_NOT_SUPPORTED;
+		result = LDAP_UNWILLING_TO_PERFORM;
+		errstr = talloc_asprintf(reply,
+					 "SASL:[%s]: Sign or Seal are not allowed if SASL encryption has already been set up",
+					 req->creds.SASL.mechanism);
+		goto do_reply;
+	}
+
+	if (context) {
+		context->conn = conn;
+		status = gensec_create_tstream(context,
+					       context->conn->gensec,
+					       context->conn->sockets.raw,
+					       &context->sasl);
+		if (NT_STATUS_IS_OK(status)) {
+			if (!talloc_reference(context->sasl, conn->gensec)) {
 				status = NT_STATUS_NO_MEMORY;
 			}
 		}
-
-		if (context && conn->sockets.tls) {
-			TALLOC_FREE(context);
-			status = NT_STATUS_NOT_SUPPORTED;
-			result = LDAP_UNWILLING_TO_PERFORM;
+	} else {
+		switch (call->conn->require_strong_auth) {
+		case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
+			break;
+		case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
+			if (call->conn->sockets.active == call->conn->sockets.tls) {
+				break;
+			}
+			status = NT_STATUS_NETWORK_ACCESS_DENIED;
+			result = LDAP_STRONG_AUTH_REQUIRED;
 			errstr = talloc_asprintf(reply,
-						 "SASL:[%s]: Sign or Seal are not allowed if TLS is used",
-						 req->creds.SASL.mechanism);
+					"SASL:[%s]: not allowed if TLS is used.",
+					 req->creds.SASL.mechanism);
 			goto do_reply;
-		}
 
-		if (context && conn->sockets.sasl) {
-			TALLOC_FREE(context);
-			status = NT_STATUS_NOT_SUPPORTED;
-			result = LDAP_UNWILLING_TO_PERFORM;
+		case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES:
+			status = NT_STATUS_NETWORK_ACCESS_DENIED;
+			result = LDAP_STRONG_AUTH_REQUIRED;
 			errstr = talloc_asprintf(reply,
-						 "SASL:[%s]: Sign or Seal are not allowed if SASL encryption has already been set up",
-						 req->creds.SASL.mechanism);
+					 "SASL:[%s]: Sign or Seal are required.",
+					 req->creds.SASL.mechanism);
 			goto do_reply;
 		}
+	}
 
-		if (context) {
-			context->conn = conn;
-			status = gensec_create_tstream(context,
-						       context->conn->gensec,
-						       context->conn->sockets.raw,
-						       &context->sasl);
-			if (NT_STATUS_IS_OK(status)) {
-				if (!talloc_reference(context->sasl, conn->gensec)) {
-					status = NT_STATUS_NO_MEMORY;
-				}
-			}
-		} else {
-			switch (call->conn->require_strong_auth) {
-			case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
-				break;
-			case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
-				if (call->conn->sockets.active == call->conn->sockets.tls) {
-					break;
-				}
-				status = NT_STATUS_NETWORK_ACCESS_DENIED;
-				result = LDAP_STRONG_AUTH_REQUIRED;
-				errstr = talloc_asprintf(reply,
-						"SASL:[%s]: not allowed if TLS is used.",
-						 req->creds.SASL.mechanism);
-				goto do_reply;
-
-			case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES:
-				status = NT_STATUS_NETWORK_ACCESS_DENIED;
-				result = LDAP_STRONG_AUTH_REQUIRED;
-				errstr = talloc_asprintf(reply,
-						 "SASL:[%s]: Sign or Seal are required.",
-						 req->creds.SASL.mechanism);
-				goto do_reply;
-			}
-		}
+	if (result != LDAP_SUCCESS) {
+	} else if (!NT_STATUS_IS_OK(status)) {
+		result = LDAP_OPERATIONS_ERROR;
+		errstr = talloc_asprintf(reply,
+					 "SASL:[%s]: Failed to setup SASL socket: %s",
+					 req->creds.SASL.mechanism, nt_errstr(status));
+		goto do_reply;
+	} else {
+		struct auth_session_info *old_session_info=NULL;
 
-		if (result != LDAP_SUCCESS) {
-		} else if (!NT_STATUS_IS_OK(status)) {
+		old_session_info = conn->session_info;
+		conn->session_info = NULL;
+		status = gensec_session_info(conn->gensec, conn, &conn->session_info);
+		if (!NT_STATUS_IS_OK(status)) {
+			conn->session_info = old_session_info;
 			result = LDAP_OPERATIONS_ERROR;
 			errstr = talloc_asprintf(reply, 
-						 "SASL:[%s]: Failed to setup SASL socket: %s", 
+						 "SASL:[%s]: Failed to get session info: %s",
 						 req->creds.SASL.mechanism, nt_errstr(status));
 			goto do_reply;
 		} else {
-			struct auth_session_info *old_session_info=NULL;
+			talloc_unlink(conn, old_session_info);
+
+			/* don't leak the old LDB */
+			talloc_unlink(conn, conn->ldb);
+
+			call->conn->authz_logged = true;
+
+			status = ldapsrv_backend_Init(conn);
 
-			old_session_info = conn->session_info;
-			conn->session_info = NULL;
-			status = gensec_session_info(conn->gensec, conn, &conn->session_info);
 			if (!NT_STATUS_IS_OK(status)) {
-				conn->session_info = old_session_info;
 				result = LDAP_OPERATIONS_ERROR;
 				errstr = talloc_asprintf(reply, 
-							 "SASL:[%s]: Failed to get session info: %s", 
-							 req->creds.SASL.mechanism, nt_errstr(status));
+							 "SASL:[%s]: Failed to advise samdb of new credentials: %s",
+							 req->creds.SASL.mechanism,
+							 nt_errstr(status));
 				goto do_reply;
-			} else {
-				talloc_unlink(conn, old_session_info);
-				
-				/* 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)) {
-					result = LDAP_OPERATIONS_ERROR;
-					errstr = talloc_asprintf(reply, 
-								 "SASL:[%s]: Failed to advise samdb of new credentials: %s", 
-								 req->creds.SASL.mechanism, 
-								 nt_errstr(status));
-					goto do_reply;
-				}
 			}
 		}
+	}
 
-		if (NT_STATUS_IS_OK(status) && context) {
-			call->postprocess_send = ldapsrv_sasl_postprocess_send;
-			call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
-			call->postprocess_private = context;
-		}
-		talloc_unlink(conn, conn->gensec);
-		conn->gensec = NULL;
+	if (NT_STATUS_IS_OK(status) && context) {
+		call->postprocess_send = ldapsrv_sasl_postprocess_send;
+		call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
+		call->postprocess_private = context;
 	}
+	talloc_unlink(conn, conn->gensec);
+	conn->gensec = NULL;
 
 do_reply:
 	if (result != LDAP_SASL_BIND_IN_PROGRESS) {
-- 
1.9.1


From e0706b4f0085c34691286f09116fdfa60af15989 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 21:14:00 +0200
Subject: [PATCH 17/30] s4:ldap_server: only set *resp->SASL.secblob = output
 for OK or MORE_PROCESSING_REQUIRED

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 337ce12..451f9d5 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -419,9 +419,9 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 
 	status = gensec_update_ev(conn->gensec, reply, conn->connection->event.ctx,
 				  input, &output);
-	*resp->SASL.secblob = output;
 
 	if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
+		*resp->SASL.secblob = output;
 		result = LDAP_SASL_BIND_IN_PROGRESS;
 		errstr = NULL;
 		goto do_reply;
@@ -553,6 +553,8 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	talloc_unlink(conn, conn->gensec);
 	conn->gensec = NULL;
 
+	*resp->SASL.secblob = output;
+
 do_reply:
 	if (result != LDAP_SASL_BIND_IN_PROGRESS) {
 		/*
-- 
1.9.1


From c833b071fd05cf2a61ec28841e1ef3658caac4c3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 21:17:40 +0200
Subject: [PATCH 18/30] s4:ldap_server: drop the connection if we fail to
 allocate ldapsrv_sasl_postprocess_context

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 451f9d5..64ee1b3 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -442,9 +442,8 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	    gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
 
 		context = talloc(call, struct ldapsrv_sasl_postprocess_context);
-
-		if (!context) {
-			status = NT_STATUS_NO_MEMORY;
+		if (context == NULL) {
+			return NT_STATUS_NO_MEMORY;
 		}
 	}
 
-- 
1.9.1


From 9f0e76089bcce23d734087b5dc138e81eb948c80 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 11 May 2017 21:18:07 +0200
Subject: [PATCH 19/30] s4:ldap_server: use talloc_zero for
 ldapsrv_sasl_postprocess_context

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

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 64ee1b3..e259727 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -441,7 +441,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
 	    gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
 
-		context = talloc(call, struct ldapsrv_sasl_postprocess_context);
+		context = talloc_zero(call, struct ldapsrv_sasl_postprocess_context);
 		if (context == NULL) {
 			return NT_STATUS_NO_MEMORY;
 		}
-- 
1.9.1


From d9431efc628b6fcb51c3953dede8911c942f9b0a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:04:59 +0200
Subject: [PATCH 20/30] s4:ldap_server: do the transport validation before
 calling gensec_create_tstream()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index e259727..6a88891 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -467,18 +467,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		goto do_reply;
 	}
 
-	if (context) {
-		context->conn = conn;
-		status = gensec_create_tstream(context,
-					       context->conn->gensec,
-					       context->conn->sockets.raw,
-					       &context->sasl);
-		if (NT_STATUS_IS_OK(status)) {
-			if (!talloc_reference(context->sasl, conn->gensec)) {
-				status = NT_STATUS_NO_MEMORY;
-			}
-		}
-	} else {
+	if (context == NULL) {
 		switch (call->conn->require_strong_auth) {
 		case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
 			break;
@@ -503,6 +492,19 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		}
 	}
 
+	if (context != NULL) {
+		context->conn = conn;
+		status = gensec_create_tstream(context,
+					       context->conn->gensec,
+					       context->conn->sockets.raw,
+					       &context->sasl);
+		if (NT_STATUS_IS_OK(status)) {
+			if (!talloc_reference(context->sasl, conn->gensec)) {
+				status = NT_STATUS_NO_MEMORY;
+			}
+		}
+	}
+
 	if (result != LDAP_SUCCESS) {
 	} else if (!NT_STATUS_IS_OK(status)) {
 		result = LDAP_OPERATIONS_ERROR;
-- 
1.9.1


From bee3340a40c47745fe35ed3bb7a5237ea57c9ed6 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:07:31 +0200
Subject: [PATCH 21/30] s4:ldap_server: remove pointless (result !=
 LDAP_SUCCESS) check

We set result = LDAP_SUCCESS above and have goto do_reply;
in all cases where we overwrite 'result'.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 6a88891..7f14384 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -505,8 +505,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		}
 	}
 
-	if (result != LDAP_SUCCESS) {
-	} else if (!NT_STATUS_IS_OK(status)) {
+	if (!NT_STATUS_IS_OK(status)) {
 		result = LDAP_OPERATIONS_ERROR;
 		errstr = talloc_asprintf(reply,
 					 "SASL:[%s]: Failed to setup SASL socket: %s",
-- 
1.9.1


From 795dfd345bce05d852ffe9ca114603cbf0cba627 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:09:38 +0200
Subject: [PATCH 22/30] s4:ldap_server: terminate the connection if
 talloc_reference fails

talloc_reference will be removed completely in the next commits...

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

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 7f14384..25fe528 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -500,7 +500,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 					       &context->sasl);
 		if (NT_STATUS_IS_OK(status)) {
 			if (!talloc_reference(context->sasl, conn->gensec)) {
-				status = NT_STATUS_NO_MEMORY;
+				return NT_STATUS_NO_MEMORY;
 			}
 		}
 	}
-- 
1.9.1


From 19ac233dfee85381b8f4f40101165ff697328180 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 13 Jun 2017 15:28:53 +0200
Subject: [PATCH 23/30] s4:ldap_server: only touch conn->session_info on
 success in ldapsrv_BindSASL()

The old conn->session_info (as well as conn->ldb) should only be changed
after a successful Bind().

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 25fe528..352e67d 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -377,6 +377,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	NTSTATUS status = NT_STATUS_OK;
 	DATA_BLOB input = data_blob_null;
 	DATA_BLOB output = data_blob_null;
+	struct auth_session_info *session_info = NULL;
 
 	DEBUG(10, ("BindSASL dn: %s\n",req->dn));
 
@@ -512,20 +513,17 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 					 req->creds.SASL.mechanism, nt_errstr(status));
 		goto do_reply;
 	} else {
-		struct auth_session_info *old_session_info=NULL;
 
-		old_session_info = conn->session_info;
-		conn->session_info = NULL;
-		status = gensec_session_info(conn->gensec, conn, &conn->session_info);
+		status = gensec_session_info(conn->gensec, call, &session_info);
 		if (!NT_STATUS_IS_OK(status)) {
-			conn->session_info = old_session_info;
 			result = LDAP_OPERATIONS_ERROR;
 			errstr = talloc_asprintf(reply, 
 						 "SASL:[%s]: Failed to get session info: %s",
 						 req->creds.SASL.mechanism, nt_errstr(status));
 			goto do_reply;
 		} else {
-			talloc_unlink(conn, old_session_info);
+			talloc_unlink(conn, conn->session_info);
+			conn->session_info = talloc_steal(conn, session_info);
 
 			/* don't leak the old LDB */
 			talloc_unlink(conn, conn->ldb);
-- 
1.9.1


From 1ec9a7c22bb77675a4d7290b8b31ac5d71f80471 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:26:12 +0200
Subject: [PATCH 24/30] s4:ldap_server: make the gensec_create_tstream() error
 checking more clear

Check with 'git show -w'.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 352e67d..cd6b7e4 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -499,21 +499,20 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 					       context->conn->gensec,
 					       context->conn->sockets.raw,
 					       &context->sasl);
-		if (NT_STATUS_IS_OK(status)) {
-			if (!talloc_reference(context->sasl, conn->gensec)) {
-				return NT_STATUS_NO_MEMORY;
-			}
-		}
-	}
-
-	if (!NT_STATUS_IS_OK(status)) {
-		result = LDAP_OPERATIONS_ERROR;
-		errstr = talloc_asprintf(reply,
+		if (!NT_STATUS_IS_OK(status)) {
+			result = LDAP_OPERATIONS_ERROR;
+			errstr = talloc_asprintf(reply,
 					 "SASL:[%s]: Failed to setup SASL socket: %s",
 					 req->creds.SASL.mechanism, nt_errstr(status));
-		goto do_reply;
-	} else {
+			goto do_reply;
+		}
 
+		if (!talloc_reference(context->sasl, conn->gensec)) {
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
+
+	{
 		status = gensec_session_info(conn->gensec, call, &session_info);
 		if (!NT_STATUS_IS_OK(status)) {
 			result = LDAP_OPERATIONS_ERROR;
-- 
1.9.1


From 026a7dd94b60ef5dd437f2937c3293da02f725ab Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:27:26 +0200
Subject: [PATCH 25/30] s4:ldap_server: remove useless indentation level
 arround gensec_session_info()

Check with git show -w

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 44 ++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 23 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index cd6b7e4..c33eaac 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -512,33 +512,31 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		}
 	}
 
-	{
-		status = gensec_session_info(conn->gensec, call, &session_info);
-		if (!NT_STATUS_IS_OK(status)) {
-			result = LDAP_OPERATIONS_ERROR;
-			errstr = talloc_asprintf(reply, 
-						 "SASL:[%s]: Failed to get session info: %s",
-						 req->creds.SASL.mechanism, nt_errstr(status));
-			goto do_reply;
-		} else {
-			talloc_unlink(conn, conn->session_info);
-			conn->session_info = talloc_steal(conn, session_info);
+	status = gensec_session_info(conn->gensec, call, &session_info);
+	if (!NT_STATUS_IS_OK(status)) {
+		result = LDAP_OPERATIONS_ERROR;
+		errstr = talloc_asprintf(reply,
+					 "SASL:[%s]: Failed to get session info: %s",
+					 req->creds.SASL.mechanism, nt_errstr(status));
+		goto do_reply;
+	} else {
+		talloc_unlink(conn, conn->session_info);
+		conn->session_info = talloc_steal(conn, session_info);
 
-			/* don't leak the old LDB */
-			talloc_unlink(conn, conn->ldb);
+		/* don't leak the old LDB */
+		talloc_unlink(conn, conn->ldb);
 
-			call->conn->authz_logged = true;
+		call->conn->authz_logged = true;
 
-			status = ldapsrv_backend_Init(conn);
+		status = ldapsrv_backend_Init(conn);
 
-			if (!NT_STATUS_IS_OK(status)) {
-				result = LDAP_OPERATIONS_ERROR;
-				errstr = talloc_asprintf(reply, 
-							 "SASL:[%s]: Failed to advise samdb of new credentials: %s",
-							 req->creds.SASL.mechanism,
-							 nt_errstr(status));
-				goto do_reply;
-			}
+		if (!NT_STATUS_IS_OK(status)) {
+			result = LDAP_OPERATIONS_ERROR;
+			errstr = talloc_asprintf(reply,
+						 "SASL:[%s]: Failed to advise samdb of new credentials: %s",
+						 req->creds.SASL.mechanism,
+						 nt_errstr(status));
+			goto do_reply;
 		}
 	}
 
-- 
1.9.1


From 38cc0616f19d8d668a4471fa2a86ea6b7bde17e8 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:27:26 +0200
Subject: [PATCH 26/30] s4:ldap_server: remove useless indentation level
 arround ldapsrv_backend_Init()

Check with git show -w

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index c33eaac..51440cb 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -519,25 +519,25 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 					 "SASL:[%s]: Failed to get session info: %s",
 					 req->creds.SASL.mechanism, nt_errstr(status));
 		goto do_reply;
-	} else {
-		talloc_unlink(conn, conn->session_info);
-		conn->session_info = talloc_steal(conn, session_info);
+	}
 
-		/* don't leak the old LDB */
-		talloc_unlink(conn, conn->ldb);
+	talloc_unlink(conn, conn->session_info);
+	conn->session_info = talloc_steal(conn, session_info);
 
-		call->conn->authz_logged = true;
+	/* don't leak the old LDB */
+	talloc_unlink(conn, conn->ldb);
 
-		status = ldapsrv_backend_Init(conn);
+	call->conn->authz_logged = true;
 
-		if (!NT_STATUS_IS_OK(status)) {
-			result = LDAP_OPERATIONS_ERROR;
-			errstr = talloc_asprintf(reply,
-						 "SASL:[%s]: Failed to advise samdb of new credentials: %s",
-						 req->creds.SASL.mechanism,
-						 nt_errstr(status));
-			goto do_reply;
-		}
+	status = ldapsrv_backend_Init(conn);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		result = LDAP_OPERATIONS_ERROR;
+		errstr = talloc_asprintf(reply,
+					 "SASL:[%s]: Failed to advise samdb of new credentials: %s",
+					 req->creds.SASL.mechanism,
+					 nt_errstr(status));
+		goto do_reply;
 	}
 
 	if (NT_STATUS_IS_OK(status) && context) {
-- 
1.9.1


From 2b8d14cf8cb753f37c30cf83b8ce9712aa967df5 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:31:25 +0200
Subject: [PATCH 27/30] s4:ldap_server: remove useless NT_STATUS_IS_OK(status)
 check

We checked a few lines above already, check with:
git show -U10

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

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 51440cb..3ba7ea3 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -540,7 +540,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		goto do_reply;
 	}
 
-	if (NT_STATUS_IS_OK(status) && context) {
+	if (context != NULL) {
 		call->postprocess_send = ldapsrv_sasl_postprocess_send;
 		call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
 		call->postprocess_private = context;
-- 
1.9.1


From a41a835e411f56f1173ddb040048227fbba1db2e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:38:59 +0200
Subject: [PATCH 28/30] s4:ldap_server: avoid using talloc_reference()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 3ba7ea3..7137642 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -506,10 +506,6 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 					 req->creds.SASL.mechanism, nt_errstr(status));
 			goto do_reply;
 		}
-
-		if (!talloc_reference(context->sasl, conn->gensec)) {
-			return NT_STATUS_NO_MEMORY;
-		}
 	}
 
 	status = gensec_session_info(conn->gensec, call, &session_info);
@@ -541,11 +537,19 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	}
 
 	if (context != NULL) {
+		const void *ptr = NULL;
+
+		ptr = talloc_reparent(conn, context->sasl, conn->gensec);
+		if (ptr == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
 		call->postprocess_send = ldapsrv_sasl_postprocess_send;
 		call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
 		call->postprocess_private = context;
+	} else {
+		talloc_unlink(conn, conn->gensec);
 	}
-	talloc_unlink(conn, conn->gensec);
 	conn->gensec = NULL;
 
 	*resp->SASL.secblob = output;
-- 
1.9.1


From b84ffe319f1f553f0b40ca24ec659d38fa1d0572 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 12:41:13 +0200
Subject: [PATCH 29/30] s4:ldap_server: set result = LDAP_SUCCESS at the end,
 when we're really done

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 7137642..9336d16 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -436,9 +436,6 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		goto do_reply;
 	}
 
-	result = LDAP_SUCCESS;
-	errstr = NULL;
-
 	if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
 	    gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
 
@@ -553,6 +550,8 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 	conn->gensec = NULL;
 
 	*resp->SASL.secblob = output;
+	result = LDAP_SUCCESS;
+	errstr = NULL;
 
 do_reply:
 	if (result != LDAP_SASL_BIND_IN_PROGRESS) {
-- 
1.9.1


From 57a8578cc41cce595192c96a046c0dffb9157897 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 12 May 2017 13:15:27 +0200
Subject: [PATCH 30/30] s4:ldap_server: implement async BindSASL

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/ldap_server/ldap_bind.c | 77 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 69 insertions(+), 8 deletions(-)

diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 9336d16..21cbb7b 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -365,19 +365,19 @@ static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn,
 	return status;
 }
 
+static void ldapsrv_BindSASL_done(struct tevent_req *subreq);
+
 static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 {
 	struct ldap_BindRequest *req = &call->request->r.BindRequest;
 	struct ldapsrv_reply *reply;
 	struct ldap_BindResponse *resp;
 	struct ldapsrv_connection *conn;
-	struct ldapsrv_sasl_postprocess_context *context = NULL;
 	int result = 0;
 	const char *errstr=NULL;
 	NTSTATUS status = NT_STATUS_OK;
 	DATA_BLOB input = data_blob_null;
-	DATA_BLOB output = data_blob_null;
-	struct auth_session_info *session_info = NULL;
+	struct tevent_req *subreq = NULL;
 
 	DEBUG(10, ("BindSASL dn: %s\n",req->dn));
 
@@ -418,8 +418,67 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		input = *req->creds.SASL.secblob;
 	}
 
-	status = gensec_update_ev(conn->gensec, reply, conn->connection->event.ctx,
-				  input, &output);
+	subreq = gensec_update_send(call, conn->connection->event.ctx,
+				    conn->gensec, input);
+	if (subreq == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	tevent_req_set_callback(subreq, ldapsrv_BindSASL_done, call);
+
+	status = ldapsrv_bind_wait_setup(call, reply);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(subreq);
+		return status;
+	}
+
+	/*
+	 * The rest will be async.
+	 */
+	return NT_STATUS_OK;
+
+do_reply:
+	if (result != LDAP_SASL_BIND_IN_PROGRESS) {
+		/*
+		 * We should destroy the gensec context
+		 * when we hit a fatal error.
+		 *
+		 * Note: conn->gensec is already cleared
+		 * for the LDAP_SUCCESS case.
+		 */
+		talloc_unlink(conn, conn->gensec);
+		conn->gensec = NULL;
+	}
+
+	resp->response.resultcode = result;
+	resp->response.dn = NULL;
+	resp->response.errormessage = errstr;
+	resp->response.referral = NULL;
+
+	ldapsrv_queue_reply(call, reply);
+	return NT_STATUS_OK;
+}
+
+static void ldapsrv_BindSASL_done(struct tevent_req *subreq)
+{
+	struct ldapsrv_call *call =
+		tevent_req_callback_data(subreq,
+		struct ldapsrv_call);
+	struct ldapsrv_bind_wait_context *bind_wait =
+		talloc_get_type_abort(call->wait_private,
+		struct ldapsrv_bind_wait_context);
+	struct ldap_BindRequest *req = &call->request->r.BindRequest;
+	struct ldapsrv_reply *reply = bind_wait->reply;
+	struct ldap_BindResponse *resp = &reply->msg->r.BindResponse;
+	struct ldapsrv_connection *conn = call->conn;
+	struct auth_session_info *session_info = NULL;
+	struct ldapsrv_sasl_postprocess_context *context = NULL;
+	NTSTATUS status;
+	int result;
+	const char *errstr = NULL;
+	DATA_BLOB output = data_blob_null;
+
+	status = gensec_update_recv(subreq, call, &output);
+	TALLOC_FREE(subreq);
 
 	if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
 		*resp->SASL.secblob = output;
@@ -441,7 +500,8 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 
 		context = talloc_zero(call, struct ldapsrv_sasl_postprocess_context);
 		if (context == NULL) {
-			return NT_STATUS_NO_MEMORY;
+			ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
+			return;
 		}
 	}
 
@@ -538,7 +598,8 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 
 		ptr = talloc_reparent(conn, context->sasl, conn->gensec);
 		if (ptr == NULL) {
-			return NT_STATUS_NO_MEMORY;
+			ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
+			return;
 		}
 
 		call->postprocess_send = ldapsrv_sasl_postprocess_send;
@@ -572,7 +633,7 @@ do_reply:
 	resp->response.referral = NULL;
 
 	ldapsrv_queue_reply(call, reply);
-	return NT_STATUS_OK;
+	ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
 }
 
 NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
-- 
1.9.1

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


More information about the samba-technical mailing list