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