How this update has slipped in my batch was Re: [SCM] Samba Shared Repository - branch master updated

Matthieu Patou mat at samba.org
Mon Oct 4 14:33:13 MDT 2010


  Hi all,


On 05/10/2010 00:24, Matthieu Patou wrote:
> The branch, master has been updated
>         via  d09cfc0 unittests: add a test to avoid regression on previous fix
>         via  19f835d unittests: makes the unit tests for ldb.python back in order
>         via  9dcad79 pyldb: test return code before trying to talloc_steal
>         via  b53fbc7 s4:ldap_server: rewrite to socket layer to use tstream
I'm wondering how this has arrived in the tree given the fact that on my 
private repo git rebase -i master gives me:
   1 pick ed2f6aa pyldb: test return code before trying to talloc_steal
   2 pick dd6c604 unittests: makes the unit tests for ldb.python back in 
order
   3 pick 6f95fec unittests: add a test to avoid regression on previous fix

Should the latest patch be removed ?

>        from  b5f2633 dnsp: Add support for parsing HINFO records
>
> http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
>
>
> - Log -----------------------------------------------------------------
> commit d09cfc04fb29222c39ca4f170982c033fdc8206c
> Author: Matthieu Patou<mat at matws.net>
> Date:   Mon Oct 4 22:56:20 2010 +0400
>
>      unittests: add a test to avoid regression on previous fix
>
>      Autobuild-User: Matthieu Patou<mat at samba.org>
>      Autobuild-Date: Mon Oct  4 20:23:31 UTC 2010 on sn-devel-104
>
> commit 19f835dd69e7ea3ecc10732ebb031f78f79ec9f5
> Author: Matthieu Patou<mat at matws.net>
> Date:   Mon Oct 4 22:54:46 2010 +0400
>
>      unittests: makes the unit tests for ldb.python back in order
>
> commit 9dcad792b6d5ff0481da467b1c6b4524cf462ba8
> Author: Matthieu Patou<mat at matws.net>
> Date:   Mon Oct 4 00:43:33 2010 +0400
>
>      pyldb: test return code before trying to talloc_steal
>
>      Otherwise you can have an error on the talloc_steal as the req can have
>      been not talloced yet
>
> commit b53fbc75acc525f2e2450370e704a62791271788
> Author: Stefan Metzmacher<metze at samba.org>
> Date:   Wed Sep 22 14:24:03 2010 +0200
>
>      s4:ldap_server: rewrite to socket layer to use tstream
>
>      This should make our sasl and tls handling much more robust
>      against partial sent pdus.
>
>      metze
>
> -----------------------------------------------------------------------
>
> Summary of changes:
>   source4/ldap_server/ldap_bind.c     |   99 ++++--
>   source4/ldap_server/ldap_extended.c |  105 ++++-
>   source4/ldap_server/ldap_server.c   |  766 ++++++++++++++++++++++++-----------
>   source4/ldap_server/ldap_server.h   |   35 +-
>   source4/lib/ldb/pyldb.c             |    4 +-
>   source4/lib/ldb/tests/python/api.py |    5 +
>   source4/selftest/tests.py           |    2 +-
>   7 files changed, 705 insertions(+), 311 deletions(-)
>
>
> Changeset truncated at 500 lines:
>
> diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
> index c97211c..5036353 100644
> --- a/source4/ldap_server/ldap_bind.c
> +++ b/source4/ldap_server/ldap_bind.c
> @@ -25,7 +25,9 @@
>   #include "lib/ldb/include/ldb_errors.h"
>   #include "dsdb/samdb/samdb.h"
>   #include "auth/gensec/gensec.h"
> +#include "auth/gensec/gensec_tstream.h"
>   #include "param/param.h"
> +#include "../lib/util/tevent_ntstatus.h"
>
>   static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
>   {
> @@ -94,20 +96,42 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
>   	return NT_STATUS_OK;
>   }
>
> -struct ldapsrv_sasl_context {
> +struct ldapsrv_sasl_postprocess_context {
>   	struct ldapsrv_connection *conn;
> -	struct socket_context *sasl_socket;
> +	struct tstream_context *sasl;
>   };
>
> -static void ldapsrv_set_sasl(void *private_data)
> +struct ldapsrv_sasl_postprocess_state {
> +	uint8_t dummy;
> +};
> +
> +static struct tevent_req *ldapsrv_sasl_postprocess_send(TALLOC_CTX *mem_ctx,
> +						struct tevent_context *ev,
> +						void *private_data)
>   {
> -	struct ldapsrv_sasl_context *ctx = talloc_get_type(private_data, struct ldapsrv_sasl_context);
> -	talloc_steal(ctx->conn->connection, ctx->sasl_socket);
> -	talloc_unlink(ctx->conn->connection, ctx->conn->connection->socket);
> +	struct ldapsrv_sasl_postprocess_context *context =
> +		talloc_get_type_abort(private_data,
> +		struct ldapsrv_sasl_postprocess_context);
> +	struct tevent_req *req;
> +	struct ldapsrv_sasl_postprocess_state *state;
> +
> +	req = tevent_req_create(mem_ctx,&state,
> +				struct ldapsrv_sasl_postprocess_state);
> +	if (req == NULL) {
> +		return NULL;
> +	}
>
> -	ctx->conn->sockets.sasl = ctx->sasl_socket;
> -	ctx->conn->connection->socket = ctx->sasl_socket;
> -	packet_set_socket(ctx->conn->packet, ctx->conn->connection->socket);
> +	TALLOC_FREE(context->conn->sockets.sasl);
> +	context->conn->sockets.sasl = talloc_move(context->conn,&context->sasl);
> +	context->conn->sockets.active = context->conn->sockets.sasl;
> +
> +	tevent_req_done(req);
> +	return tevent_req_post(req, ev);
> +}
> +
> +static NTSTATUS ldapsrv_sasl_postprocess_recv(struct tevent_req *req)
> +{
> +	return tevent_req_simple_recv_ntstatus(req);
>   }
>
>   static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
> @@ -152,7 +176,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
>   			errstr = talloc_asprintf(reply, "SASL: Failed to start authentication system: %s",
>   						 nt_errstr(status));
>   		} else {
> -		
> +
>   			gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
>   			gensec_want_feature(conn->gensec, GENSEC_FEATURE_SEAL);
>   			gensec_want_feature(conn->gensec, GENSEC_FEATURE_ASYNC_REPLIES);
> @@ -193,27 +217,41 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
>   		errstr = NULL;
>   	} else if (NT_STATUS_IS_OK(status)) {
>   		struct auth_session_info *old_session_info=NULL;
> -		struct ldapsrv_sasl_context *ctx;
> +		struct ldapsrv_sasl_postprocess_context *context = NULL;
>
>   		result = LDAP_SUCCESS;
>   		errstr = NULL;
>
> -		ctx = talloc(call, struct ldapsrv_sasl_context);
> +		if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
> +		    gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
>
> -		if (!ctx) {
> -			status = NT_STATUS_NO_MEMORY;
> -		} else {
> -			ctx->conn = conn;
> -			status = gensec_socket_init(conn->gensec,
> -						    conn->connection,
> -						    conn->connection->socket,
> -						    conn->connection->event.ctx,
> -						    stream_io_handler_callback,
> -						    conn->connection,
> -						&ctx->sasl_socket);
> -		}
> -
> -		if (!ctx || !NT_STATUS_IS_OK(status)) {
> +			context = talloc(call, struct ldapsrv_sasl_postprocess_context);
> +
> +			if (!context) {
> +				status = NT_STATUS_NO_MEMORY;
> +			}
> +		}
> +
> +		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);
> +		}
> +
> +		if (context) {
> +			context->conn = conn;
> +			status = gensec_create_tstream(context,
> +						       context->conn->gensec,
> +						       context->conn->sockets.raw,
> +						&context->sasl);
> +		}
> +
> +		if (result != LDAP_SUCCESS) {
> +			conn->session_info = old_session_info;
> +		} else if (!NT_STATUS_IS_OK(status)) {
>   			conn->session_info = old_session_info;
>   			result = LDAP_OPERATIONS_ERROR;
>   			errstr = talloc_asprintf(reply,
> @@ -221,9 +259,6 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
>   						 req->creds.SASL.mechanism, nt_errstr(status));
>   		} else {
>
> -			call->send_callback = ldapsrv_set_sasl;
> -			call->send_private = ctx;
> -		
>   			old_session_info = conn->session_info;
>   			conn->session_info = NULL;
>   			status = gensec_session_info(conn->gensec,&conn->session_info);
> @@ -251,6 +286,12 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
>   				}
>   			}
>   		}
> +
> +		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;
> +		}
>   	} else {
>   		status = auth_nt_status_squash(status);
>   		if (result == 0) {
> diff --git a/source4/ldap_server/ldap_extended.c b/source4/ldap_server/ldap_extended.c
> index 78fd43c..f70b808 100644
> --- a/source4/ldap_server/ldap_extended.c
> +++ b/source4/ldap_server/ldap_extended.c
> @@ -22,28 +22,91 @@
>   #include "../lib/util/dlinklist.h"
>   #include "lib/tls/tls.h"
>   #include "smbd/service_stream.h"
> +#include "../lib/util/tevent_ntstatus.h"
>
> -struct ldapsrv_starttls_context {
> +struct ldapsrv_starttls_postprocess_context {
>   	struct ldapsrv_connection *conn;
> -	struct socket_context *tls_socket;
>   };
>
> -static void ldapsrv_start_tls(void *private_data)
> +struct ldapsrv_starttls_postprocess_state {
> +	struct ldapsrv_connection *conn;
> +};
> +
> +static void ldapsrv_starttls_postprocess_done(struct tevent_req *subreq);
> +
> +static struct tevent_req *ldapsrv_starttls_postprocess_send(TALLOC_CTX *mem_ctx,
> +						struct tevent_context *ev,
> +						void *private_data)
> +{
> +	struct ldapsrv_starttls_postprocess_context *context =
> +		talloc_get_type_abort(private_data,
> +		struct ldapsrv_starttls_postprocess_context);
> +	struct ldapsrv_connection *conn = context->conn;
> +	struct tevent_req *req;
> +	struct ldapsrv_starttls_postprocess_state *state;
> +	struct tevent_req *subreq;
> +
> +	req = tevent_req_create(mem_ctx,&state,
> +				struct ldapsrv_starttls_postprocess_state);
> +	if (req == NULL) {
> +		return NULL;
> +	}
> +
> +	state->conn = conn;
> +
> +	subreq = tstream_tls_accept_send(conn,
> +					 conn->connection->event.ctx,
> +					 conn->sockets.raw,
> +					 conn->service->tls_params);
> +	if (tevent_req_nomem(subreq, req)) {
> +		return tevent_req_post(req, ev);
> +	}
> +	tevent_req_set_callback(subreq, ldapsrv_starttls_postprocess_done, req);
> +
> +	return req;
> +}
> +
> +static void ldapsrv_starttls_postprocess_done(struct tevent_req *subreq)
>   {
> -	struct ldapsrv_starttls_context *ctx = talloc_get_type(private_data, struct ldapsrv_starttls_context);
> -	talloc_steal(ctx->conn->connection, ctx->tls_socket);
> +	struct tevent_req *req =
> +		tevent_req_callback_data(subreq,
> +		struct tevent_req);
> +	struct ldapsrv_starttls_postprocess_state *state =
> +		tevent_req_data(req,
> +		struct ldapsrv_starttls_postprocess_state);
> +	struct ldapsrv_connection *conn = state->conn;
> +	int ret;
> +	int sys_errno;
> +
> +	ret = tstream_tls_accept_recv(subreq,&sys_errno,
> +				      conn,&conn->sockets.tls);
> +	TALLOC_FREE(subreq);
> +	if (ret == -1) {
> +		NTSTATUS status = map_nt_error_from_unix(sys_errno);
> +
> +		DEBUG(1,("ldapsrv_starttls_postprocess_done: accept_tls_loop: "
> +			 "tstream_tls_accept_recv() - %d:%s =>  %s",
> +			 sys_errno, strerror(sys_errno), nt_errstr(status)));
> +
> +		tevent_req_nterror(req, status);
> +		return;
> +	}
> +
> +	conn->sockets.active = conn->sockets.tls;
> +
> +	tevent_req_done(req);
> +}
>
> -	ctx->conn->sockets.tls = ctx->tls_socket;
> -	ctx->conn->connection->socket = ctx->tls_socket;
> -	packet_set_socket(ctx->conn->packet, ctx->conn->connection->socket);
> -	packet_set_unreliable_select(ctx->conn->packet);
> +static NTSTATUS ldapsrv_starttls_postprocess_recv(struct tevent_req *req)
> +{
> +	return tevent_req_simple_recv_ntstatus(req);
>   }
>
>   static NTSTATUS ldapsrv_StartTLS(struct ldapsrv_call *call,
>   				 struct ldapsrv_reply *reply,
>   				 const char **errstr)
>   {
> -	struct ldapsrv_starttls_context *ctx;
> +	struct ldapsrv_starttls_postprocess_context *context;
>
>   	(*errstr) = NULL;
>
> @@ -58,21 +121,19 @@ static NTSTATUS ldapsrv_StartTLS(struct ldapsrv_call *call,
>   		return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
>   	}
>
> -	ctx = talloc(call, struct ldapsrv_starttls_context);
> -	NT_STATUS_HAVE_NO_MEMORY(ctx);
> -
> -	ctx->conn = call->conn;
> -	ctx->tls_socket = tls_init_server(call->conn->service->tls_params,
> -					  call->conn->connection->socket,
> -					  call->conn->connection->event.fde,
> -					  NULL);
> -	if (!ctx->tls_socket) {
> -		(*errstr) = talloc_asprintf(reply, "START-TLS: Failed to setup TLS socket");
> +	if (call->conn->sockets.sasl) {
> +		(*errstr) = talloc_asprintf(reply, "START-TLS: SASL is already enabled on this LDAP session");
>   		return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
>   	}
>
> -	call->send_callback = ldapsrv_start_tls;
> -	call->send_private  = ctx;
> +	context = talloc(call, struct ldapsrv_starttls_postprocess_context);
> +	NT_STATUS_HAVE_NO_MEMORY(context);
> +
> +	context->conn = call->conn;
> +
> +	call->postprocess_send = ldapsrv_starttls_postprocess_send;
> +	call->postprocess_recv = ldapsrv_starttls_postprocess_recv;
> +	call->postprocess_private = context;
>
>   	reply->msg->r.ExtendedResponse.response.resultcode = LDAP_SUCCESS;
>   	reply->msg->r.ExtendedResponse.response.errormessage = NULL;
> diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
> index e975590..56e1bdc 100644
> --- a/source4/ldap_server/ldap_server.c
> +++ b/source4/ldap_server/ldap_server.c
> @@ -22,6 +22,7 @@
>   */
>
>   #include "includes.h"
> +#include "system/network.h"
>   #include "lib/events/events.h"
>   #include "auth/auth.h"
>   #include "auth/credentials/credentials.h"
> @@ -42,173 +43,97 @@
>   #include "lib/socket/netif.h"
>   #include "dsdb/samdb/samdb.h"
>   #include "param/param.h"
> -/*
> -  close the socket and shutdown a server_context
> -*/
> -void ldapsrv_terminate_connection(struct ldapsrv_connection *conn,
> -					 const char *reason)
> -{
> -	packet_recv_disable(conn->packet);
> -	TALLOC_FREE(conn->packet);
> -	TALLOC_FREE(conn->sockets.tls);
> -	stream_terminate_connection(conn->connection, reason);
> -}
> +#include "../lib/tsocket/tsocket.h"
> +#include "../lib/util/tevent_ntstatus.h"
> +#include "../libcli/util/tstream.h"
>
> -/*
> -  handle packet errors
> -*/
> -static void ldapsrv_error_handler(void *private_data, NTSTATUS status)
> -{
> -	struct ldapsrv_connection *conn = talloc_get_type(private_data,
> -							  struct ldapsrv_connection);
> -	ldapsrv_terminate_connection(conn, nt_errstr(status));
> -}
> +static void ldapsrv_terminate_connection_done(struct tevent_req *subreq);
>
>   /*
> -  process a decoded ldap message
> +  close the socket and shutdown a server_context
>   */
> -static void ldapsrv_process_message(struct ldapsrv_connection *conn,
> -				    struct ldap_message *msg)
> +static void ldapsrv_terminate_connection(struct ldapsrv_connection *conn,
> +					 const char *reason)
>   {
> -	struct ldapsrv_call *call;
> -	NTSTATUS status;
> -	DATA_BLOB blob;
> +	struct tevent_req *subreq;
>
> -	call = talloc(conn, struct ldapsrv_call);
> -	if (!call) {
> -		ldapsrv_terminate_connection(conn, "no memory");
> -		return;		
> -	}
> -
> -	call->request = talloc_steal(call, msg);
> -	call->conn = conn;
> -	call->replies = NULL;
> -	call->send_callback = NULL;
> -	call->send_private = NULL;
> -
> -	/* make the call */
> -	status = ldapsrv_do_call(call);
> -	if (!NT_STATUS_IS_OK(status)) {
> -		talloc_free(call);
> -		return;
> -	}
> -
> -	blob = data_blob(NULL, 0);
> -
> -	if (call->replies == NULL) {
> -		talloc_free(call);
> +	if (conn->limits.reason) {
>   		return;
>   	}
>
> -	/* build all the replies into a single blob */
> -	while (call->replies) {
> -		DATA_BLOB b;
> -		bool ret;
> +	conn->limits.endtime = timeval_current_ofs(0, 500);
>
> -		msg = call->replies->msg;
> -		if (!ldap_encode(msg, samba_ldap_control_handlers(),&b, call)) {
> -			DEBUG(0,("Failed to encode ldap reply of type %d\n", msg->type));
> -			talloc_free(call);
> -			return;
> -		}
> +	DEBUG(2,("ldapsrv_terminate_connection: %s - disconnecting\n",
> +		 reason));
>
> -		ret = data_blob_append(call,&blob, b.data, b.length);
> -		data_blob_free(&b);
> -
> -		talloc_set_name_const(blob.data, "Outgoing, encoded LDAP packet");
> -
> -		if (!ret) {
> -			talloc_free(call);
> -			return;
> -		}
> -
> -		DLIST_REMOVE(call->replies, call->replies);
> +	tevent_queue_stop(conn->sockets.send_queue);
> +	if (conn->active_call) {
> +		tevent_req_cancel(conn->active_call);
> +		conn->active_call = NULL;
>   	}
>
> -	packet_send_callback(conn->packet, blob,
> -			     call->send_callback, call->send_private);
> -	talloc_free(call);
> -	return;
> -}
> -
> -/*
> -  disable packets on other sockets while processing this one
> - */
> -static void ldapsrv_disable_recv(struct ldapsrv_connection *conn)
> -{
> -	struct ldapsrv_packet_interfaces *p;
> -	for (p=conn->service->packet_interfaces; p; p=p->next) {
> -		if (p->packet != conn->packet) {
> -			packet_recv_disable(p->packet);
> -		}
> +	conn->limits.reason = talloc_strdup(conn, reason);
> +	if (conn->limits.reason == NULL) {
> +		TALLOC_FREE(conn->sockets.tls);
> +		TALLOC_FREE(conn->sockets.sasl);
> +		TALLOC_FREE(conn->sockets.raw);
> +		stream_terminate_connection(conn->connection, reason);
> +		return;
>   	}
> -}
>
> -/*
> -  disable packets on other sockets while processing this one
> - */
> -static void ldapsrv_enable_recv(struct ldapsrv_connection *conn)
> -{
> -	struct ldapsrv_packet_interfaces *p;
> -	for (p=conn->service->packet_interfaces; p; p=p->next) {
> -		if (p->packet != conn->packet) {
> -			packet_recv_enable(p->packet);
> -		}
> +	subreq = tstream_disconnect_send(conn,
> +					 conn->connection->event.ctx,
> +					 conn->sockets.active);
> +	if (subreq == NULL) {
> +		TALLOC_FREE(conn->sockets.tls);
> +		TALLOC_FREE(conn->sockets.sasl);
> +		TALLOC_FREE(conn->sockets.raw);
> +		stream_terminate_connection(conn->connection, reason);
> +		return;
>   	}
> +	tevent_req_set_endtime(subreq,
> +			       conn->connection->event.ctx,
> +			       conn->limits.endtime);
> +	tevent_req_set_callback(subreq, ldapsrv_terminate_connection_done, conn);
>   }
>
> -/*
> -  decode/process data
> -*/
> -static NTSTATUS ldapsrv_decode(void *private_data, DATA_BLOB blob)
> +static void ldapsrv_terminate_connection_done(struct tevent_req *subreq)
>   {
> -	NTSTATUS status;
> -	struct ldapsrv_connection *conn = talloc_get_type(private_data,
> -							  struct ldapsrv_connection);
> -	struct asn1_data *asn1 = asn1_init(conn);
> -	struct ldap_message *msg = talloc(conn, struct ldap_message);
> +	struct ldapsrv_connection *conn =
> +		tevent_req_callback_data(subreq,
> +		struct ldapsrv_connection);
> +	int ret;
> +	int sys_errno;
>
> -	if (asn1 == NULL || msg == NULL) {
> -		return NT_STATUS_NO_MEMORY;
> -	}
> +	ret = tstream_disconnect_recv(subreq,&sys_errno);
> +	TALLOC_FREE(subreq);
>
> -	if (!asn1_load(asn1, blob)) {
> -		talloc_free(msg);
> -		talloc_free(asn1);
> -		return NT_STATUS_NO_MEMORY;
> +	if (conn->sockets.active == conn->sockets.raw) {
> +		TALLOC_FREE(conn->sockets.tls);
> +		TALLOC_FREE(conn->sockets.sasl);
> +		TALLOC_FREE(conn->sockets.raw);
> +		stream_terminate_connection(conn->connection,
> +					    conn->limits.reason);
> +		return;
>   	}
>
> -	status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
> -	if (!NT_STATUS_IS_OK(status)) {
> -		asn1_free(asn1);
>
>


-- 
Matthieu Patou
Samba Team        http://samba.org



More information about the samba-technical mailing list