[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Mon Sep 27 20:30:01 MDT 2010


The branch, master has been updated
       via  ca360fb s4:lib/tls: add gnutls backend for tstream
       via  381f0fc s4:gensec: add gensec_create_tstream()
       via  d6c48b4 s4:wrepl_server: use SOCKET_FLAG_NOCLOSE instead of a dup()
       via  9d8b886 s4:rpc_server: use SOCKET_FLAG_NOCLOSE to avoid calling close() on the socket fd twice.
      from  d7c09f3 Add torture test BAD-NBT-SESSION as regression fix for bug 7698 - Assert causes smbd to panic on invalid NetBIOS session request.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit ca360fba107f7948c52a5f7595ab0f99c8142e07
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 3 14:36:10 2010 +0100

    s4:lib/tls: add gnutls backend for tstream
    
    metze
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Tue Sep 28 02:29:42 UTC 2010 on sn-devel-104

commit 381f0fcd1957b3f485db7773924a81a1282936d5
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Sep 22 12:13:28 2010 +0200

    s4:gensec: add gensec_create_tstream()
    
    Based on the initial patch from Andreas Schneider <asn at redhat.com>.
    
    metze

commit d6c48b4a5fb667b0fba91af5d9113209ae72eede
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Sep 28 02:33:23 2010 +0200

    s4:wrepl_server: use SOCKET_FLAG_NOCLOSE instead of a dup()
    
    The key thing is that we might have to turn the incomming
    connection into a outgoing connection.
    
    This change makes sense anyway, because we donate the fd to
    tstream.
    
    metze

commit 9d8b886b3e631e073b12c559948f53bdbba87339
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Sep 28 02:13:12 2010 +0200

    s4:rpc_server: use SOCKET_FLAG_NOCLOSE to avoid calling close() on the socket fd twice.
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 source4/auth/gensec/gensec_tstream.c       |  723 ++++++++++++++++
 source4/auth/gensec/gensec_tstream.h       |   40 +
 source4/auth/gensec/wscript_build          |    2 +-
 source4/lib/tls/tls.h                      |   48 +-
 source4/lib/tls/tls_tstream.c              | 1249 ++++++++++++++++++++++++++++
 source4/lib/tls/wscript                    |    4 +-
 source4/rpc_server/service_rpc.c           |    1 +
 source4/wrepl_server/wrepl_in_connection.c |   21 +-
 8 files changed, 2066 insertions(+), 22 deletions(-)
 create mode 100644 source4/auth/gensec/gensec_tstream.c
 create mode 100644 source4/auth/gensec/gensec_tstream.h
 create mode 100644 source4/lib/tls/tls_tstream.c


Changeset truncated at 500 lines:

diff --git a/source4/auth/gensec/gensec_tstream.c b/source4/auth/gensec/gensec_tstream.c
new file mode 100644
index 0000000..d2d4d5b
--- /dev/null
+++ b/source4/auth/gensec/gensec_tstream.c
@@ -0,0 +1,723 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   tstream based generic authentication interface
+
+   Copyright (c) 2010 Stefan Metzmacher
+   Copyright (c) 2010 Andreas Schneider <asn at redhat.com>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "system/network.h"
+#include "auth/gensec/gensec.h"
+#include "auth/gensec/gensec_proto.h"
+#include "auth/gensec/gensec_tstream.h"
+#include "lib/tsocket/tsocket.h"
+#include "lib/tsocket/tsocket_internal.h"
+
+
+static const struct tstream_context_ops tstream_gensec_ops;
+
+struct tstream_gensec {
+	struct tstream_context *plain_stream;
+
+	struct gensec_security *gensec_security;
+
+	bool wrap;
+
+	int error;
+
+	struct {
+		size_t max_unwrapped_size;
+		size_t max_wrapped_size;
+	} write;
+
+	struct {
+		off_t ofs;
+		size_t left;
+		DATA_BLOB unwrapped;
+	} read;
+};
+
+_PUBLIC_ NTSTATUS _gensec_create_tstream(TALLOC_CTX *mem_ctx,
+					 struct gensec_security *gensec_security,
+					 struct tstream_context *plain_stream,
+					 struct tstream_context **_gensec_stream,
+					 const char *location)
+{
+	struct tstream_context *gensec_stream;
+	struct tstream_gensec *tgss;
+
+	gensec_stream = tstream_context_create(mem_ctx,
+					       &tstream_gensec_ops,
+					       &tgss,
+					       struct tstream_gensec,
+					       location);
+	if (gensec_stream == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	tgss->plain_stream = plain_stream;
+	tgss->gensec_security = gensec_security;
+	tgss->error = 0;
+
+	if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN) ||
+	    gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
+		tgss->wrap = true;
+	} else {
+		tgss->wrap = false;
+	}
+
+	tgss->write.max_unwrapped_size = gensec_max_input_size(gensec_security);
+	tgss->write.max_wrapped_size = gensec_max_wrapped_size(gensec_security);
+
+	ZERO_STRUCT(tgss->read);
+
+	*_gensec_stream = gensec_stream;
+	return NT_STATUS_OK;
+}
+
+static ssize_t tstream_gensec_pending_bytes(struct tstream_context *stream)
+{
+	struct tstream_gensec *tgss =
+		tstream_context_data(stream,
+		struct tstream_gensec);
+	ssize_t ret;
+
+	if (!tgss->plain_stream) {
+		errno = ENOTCONN;
+		return -1;
+	}
+
+	if (tgss->error != 0) {
+		errno = tgss->error;
+		return -1;
+	}
+
+	if (tgss->wrap) {
+		return tgss->read.left;
+	}
+
+	ret = tstream_pending_bytes(tgss->plain_stream);
+	if (ret == -1) {
+		tgss->error = errno;
+		return -1;
+	}
+
+	return ret;
+}
+
+struct tstream_gensec_readv_state {
+	struct tevent_context *ev;
+	struct tstream_context *stream;
+
+	struct iovec *vector;
+	int count;
+
+	struct {
+		bool asked_for_hdr;
+		uint8_t hdr[4];
+		bool asked_for_blob;
+		DATA_BLOB blob;
+	} wrapped;
+
+	int ret;
+};
+
+static void tstream_gensec_readv_plain_done(struct tevent_req *subreq);
+static void tstream_gensec_readv_wrapped_next(struct tevent_req *req);
+
+static struct tevent_req *tstream_gensec_readv_send(TALLOC_CTX *mem_ctx,
+						    struct tevent_context *ev,
+						    struct tstream_context *stream,
+						    struct iovec *vector,
+						    size_t count)
+{
+	struct tstream_gensec *tgss =
+		tstream_context_data(stream,
+		struct tstream_gensec);
+	struct tevent_req *req;
+	struct tstream_gensec_readv_state *state;
+	struct tevent_req *subreq;
+	ssize_t ret;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct tstream_gensec_readv_state);
+	if (!req) {
+		return NULL;
+	}
+
+	ret = tstream_gensec_pending_bytes(stream);
+	if (ret == -1) {
+		tevent_req_error(req, errno);
+		return tevent_req_post(req, ev);
+	}
+
+	state->ev = ev;
+	state->stream = stream;
+	state->ret = 0;
+
+	if (!tgss->wrap) {
+		subreq = tstream_readv_send(state,
+					    ev,
+					    tgss->plain_stream,
+					    vector,
+					    count);
+		if (tevent_req_nomem(subreq,req)) {
+			return tevent_req_post(req, ev);
+		}
+		tevent_req_set_callback(subreq,
+					tstream_gensec_readv_plain_done,
+					req);
+
+		return req;
+	}
+
+	/*
+	 * we make a copy of the vector so we can change the structure
+	 */
+	state->vector = talloc_array(state, struct iovec, count);
+	if (tevent_req_nomem(state->vector, req)) {
+		return tevent_req_post(req, ev);
+	}
+	memcpy(state->vector, vector, sizeof(struct iovec) * count);
+	state->count = count;
+
+	tstream_gensec_readv_wrapped_next(req);
+	if (!tevent_req_is_in_progress(req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	return req;
+}
+
+static void tstream_gensec_readv_plain_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+		struct tevent_req);
+	struct tstream_gensec_readv_state *state =
+		tevent_req_data(req,
+		struct tstream_gensec_readv_state);
+	struct tstream_gensec *tgss =
+		tstream_context_data(state->stream,
+		struct tstream_gensec);
+	int ret;
+	int sys_errno;
+
+	ret = tstream_readv_recv(subreq, &sys_errno);
+	TALLOC_FREE(subreq);
+	if (ret == -1) {
+		tgss->error = sys_errno;
+		tevent_req_error(req, sys_errno);
+		return;
+	}
+
+	state->ret = ret;
+
+	tevent_req_done(req);
+}
+
+static int tstream_gensec_readv_next_vector(struct tstream_context *unix_stream,
+					    void *private_data,
+					    TALLOC_CTX *mem_ctx,
+					    struct iovec **_vector,
+					    size_t *_count);
+static void tstream_gensec_readv_wrapped_done(struct tevent_req *subreq);
+
+static void tstream_gensec_readv_wrapped_next(struct tevent_req *req)
+{
+	struct tstream_gensec_readv_state *state =
+		tevent_req_data(req,
+		struct tstream_gensec_readv_state);
+	struct tstream_gensec *tgss =
+		tstream_context_data(state->stream,
+		struct tstream_gensec);
+	struct tevent_req *subreq;
+
+	/*
+	 * copy the pending buffer first
+	 */
+	while (tgss->read.left > 0 && state->count > 0) {
+		uint8_t *base = (uint8_t *)state->vector[0].iov_base;
+		size_t len = MIN(tgss->read.left, state->vector[0].iov_len);
+
+		memcpy(base, tgss->read.unwrapped.data + tgss->read.ofs, len);
+
+		base += len;
+		state->vector[0].iov_base = base;
+		state->vector[0].iov_len -= len;
+
+		tgss->read.ofs += len;
+		tgss->read.left -= len;
+
+		if (state->vector[0].iov_len == 0) {
+			state->vector += 1;
+			state->count -= 1;
+		}
+
+		state->ret += len;
+	}
+
+	if (state->count == 0) {
+		tevent_req_done(req);
+		return;
+	}
+
+	data_blob_free(&tgss->read.unwrapped);
+	ZERO_STRUCT(state->wrapped);
+
+	subreq = tstream_readv_pdu_send(state, state->ev,
+					tgss->plain_stream,
+					tstream_gensec_readv_next_vector,
+					state);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, tstream_gensec_readv_wrapped_done, req);
+}
+
+static int tstream_gensec_readv_next_vector(struct tstream_context *unix_stream,
+					    void *private_data,
+					    TALLOC_CTX *mem_ctx,
+					    struct iovec **_vector,
+					    size_t *_count)
+{
+	struct tstream_gensec_readv_state *state =
+		talloc_get_type_abort(private_data,
+		struct tstream_gensec_readv_state);
+	struct iovec *vector;
+	size_t count = 1;
+
+	/* we need to get a message header */
+	vector = talloc_array(mem_ctx, struct iovec, count);
+	if (!vector) {
+		return -1;
+	}
+
+	if (!state->wrapped.asked_for_hdr) {
+		state->wrapped.asked_for_hdr = true;
+		vector[0].iov_base = (char *)state->wrapped.hdr;
+		vector[0].iov_len = sizeof(state->wrapped.hdr);
+	} else if (!state->wrapped.asked_for_blob) {
+		state->wrapped.asked_for_blob = true;
+		uint32_t msg_len;
+
+		msg_len = RIVAL(state->wrapped.hdr, 0);
+
+		if (msg_len > 0x00FFFFFF) {
+			errno = EMSGSIZE;
+			return -1;
+		}
+
+		if (msg_len == 0) {
+			errno = EMSGSIZE;
+			return -1;
+		}
+
+		state->wrapped.blob = data_blob_talloc(state, NULL, msg_len);
+		if (state->wrapped.blob.data == NULL) {
+			return -1;
+		}
+
+		vector[0].iov_base = (char *)state->wrapped.blob.data;
+		vector[0].iov_len = state->wrapped.blob.length;
+	} else {
+		*_vector = NULL;
+		*_count = 0;
+		return 0;
+	}
+
+	*_vector = vector;
+	*_count = count;
+	return 0;
+}
+
+static void tstream_gensec_readv_wrapped_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+		struct tevent_req);
+	struct tstream_gensec_readv_state *state =
+		tevent_req_data(req,
+		struct tstream_gensec_readv_state);
+	struct tstream_gensec *tgss =
+		tstream_context_data(state->stream,
+		struct tstream_gensec);
+	int ret;
+	int sys_errno;
+	NTSTATUS status;
+
+	ret = tstream_readv_pdu_recv(subreq, &sys_errno);
+	TALLOC_FREE(subreq);
+	if (ret == -1) {
+		tgss->error = sys_errno;
+		tevent_req_error(req, sys_errno);
+		return;
+	}
+
+	status = gensec_unwrap(tgss->gensec_security,
+			       state,
+			       &state->wrapped.blob,
+			       &tgss->read.unwrapped);
+	if (!NT_STATUS_IS_OK(status)) {
+		tgss->error = EIO;
+		tevent_req_error(req, tgss->error);
+		return;
+	}
+
+	data_blob_free(&state->wrapped.blob);
+
+	talloc_steal(tgss, tgss->read.unwrapped.data);
+	tgss->read.left = tgss->read.unwrapped.length;
+	tgss->read.ofs = 0;
+
+	tstream_gensec_readv_wrapped_next(req);
+}
+
+static int tstream_gensec_readv_recv(struct tevent_req *req, int *perrno)
+{
+	struct tstream_gensec_readv_state *state =
+		tevent_req_data(req,
+		struct tstream_gensec_readv_state);
+	int ret;
+
+	ret = tsocket_simple_int_recv(req, perrno);
+	if (ret == 0) {
+		ret = state->ret;
+	}
+
+	tevent_req_received(req);
+	return ret;
+}
+
+struct tstream_gensec_writev_state {
+	struct tevent_context *ev;
+	struct tstream_context *stream;
+
+	struct iovec *vector;
+	int count;
+
+	struct {
+		off_t ofs;
+		size_t left;
+		DATA_BLOB blob;
+	} unwrapped;
+
+	struct {
+		uint8_t hdr[4];
+		DATA_BLOB blob;
+		struct iovec iov[2];
+	} wrapped;
+
+	int ret;
+};
+
+static void tstream_gensec_writev_plain_done(struct tevent_req *subreq);
+static void tstream_gensec_writev_wrapped_next(struct tevent_req *req);
+
+static struct tevent_req *tstream_gensec_writev_send(TALLOC_CTX *mem_ctx,
+					struct tevent_context *ev,
+					struct tstream_context *stream,
+					const struct iovec *vector,
+					size_t count)
+{
+	struct tstream_gensec *tgss =
+		tstream_context_data(stream,
+		struct tstream_gensec);
+	struct tevent_req *req;
+	struct tstream_gensec_writev_state *state;
+	struct tevent_req *subreq;
+	ssize_t ret;
+	int i;
+	int total;
+	int chunk;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct tstream_gensec_writev_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	ret = tstream_gensec_pending_bytes(stream);
+	if (ret == -1) {
+		tevent_req_error(req, errno);
+		return tevent_req_post(req, ev);
+	}
+
+	state->ev = ev;
+	state->stream = stream;
+	state->ret = 0;
+
+	if (!tgss->wrap) {
+		subreq = tstream_writev_send(state,
+					     ev,
+					     tgss->plain_stream,
+					     vector,
+					     count);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
+		}
+		tevent_req_set_callback(subreq, tstream_gensec_writev_plain_done, req);
+
+		return req;
+	}
+
+	/*
+	 * we make a copy of the vector so we can change the structure
+	 */
+	state->vector = talloc_array(state, struct iovec, count);
+	if (tevent_req_nomem(state->vector, req)) {
+		return tevent_req_post(req, ev);
+	}
+	memcpy(state->vector, vector, sizeof(struct iovec) * count);
+	state->count = count;
+
+	total = 0;
+	for (i = 0; i < count; i++) {
+		/*
+		 * the generic tstream code makes sure that
+		 * this never wraps.
+		 */


-- 
Samba Shared Repository


More information about the samba-cvs mailing list