svn commit: samba r17222 - in branches/SAMBA_4_0/source: auth/gensec ldap_server lib/stream lib/tls libcli/ldap

abartlet at samba.org abartlet at samba.org
Tue Jul 25 00:57:28 GMT 2006


Author: abartlet
Date: 2006-07-25 00:57:27 +0000 (Tue, 25 Jul 2006)
New Revision: 17222

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17222

Log:
Change the function prototypes for the GENSEc and TLS socket creation
routines to return an NTSTATUS.  This should help track down errors.

Use a bit of talloc_steal and talloc_unlink to get the real socket to
be a child of the GENSEC or TLS socket.

Always return a new socket, even for the 'pass-though' case.

Andrew Bartlett

Modified:
   branches/SAMBA_4_0/source/auth/gensec/socket.c
   branches/SAMBA_4_0/source/auth/gensec/socket.h
   branches/SAMBA_4_0/source/ldap_server/ldap_bind.c
   branches/SAMBA_4_0/source/ldap_server/ldap_server.c
   branches/SAMBA_4_0/source/lib/stream/packet.c
   branches/SAMBA_4_0/source/lib/tls/tls.c
   branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c
   branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c


Changeset:
Modified: branches/SAMBA_4_0/source/auth/gensec/socket.c
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/socket.c	2006-07-25 00:53:03 UTC (rev 17221)
+++ branches/SAMBA_4_0/source/auth/gensec/socket.c	2006-07-25 00:57:27 UTC (rev 17222)
@@ -41,6 +41,7 @@
 	void (*recv_handler)(void *, uint16_t);
 	void *recv_private;
 	int in_extra_read;
+	BOOL wrap; /* Should we be wrapping on this socket at all? */
 };
 
 static NTSTATUS gensec_socket_init_fn(struct socket_context *sock)
@@ -61,6 +62,10 @@
 static NTSTATUS gensec_socket_pending(struct socket_context *sock, size_t *npending) 
 {
 	struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
+	if (!gensec_socket->wrap) {
+		return socket_pending(gensec_socket->socket, npending);
+	}
+
 	if (gensec_socket->read_buffer.length > 0) {
 		*npending = gensec_socket->read_buffer.length;
 		return NT_STATUS_OK;
@@ -112,6 +117,10 @@
 {
 	struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
 
+	if (!gensec_socket->wrap) {
+		return socket_recv(gensec_socket->socket, buf, wantlen, nread);
+	}
+
 	gensec_socket->error = NT_STATUS_OK;
 
 	if (gensec_socket->read_buffer.length == 0) {
@@ -237,6 +246,10 @@
 	TALLOC_CTX *mem_ctx;
 	size_t max_input_size;
 
+	if (!gensec_socket->wrap) {
+		return socket_send(gensec_socket->socket, blob, sendlen);
+	}
+
 	*sendlen = 0;
 
 	/* We have have been interupted, so the caller should be
@@ -309,58 +322,73 @@
 	}
 }
 
-struct socket_context *gensec_socket_init(struct gensec_security *gensec_security,
-					  struct socket_context *socket,
-					  struct event_context *ev,
-					  void (*recv_handler)(void *, uint16_t),
-					  void *recv_private)
+/* Turn a normal socket into a potentially GENSEC wrapped socket */
+
+NTSTATUS gensec_socket_init(struct gensec_security *gensec_security,
+			    struct socket_context *current_socket,
+			    struct event_context *ev,
+			    void (*recv_handler)(void *, uint16_t),
+			    void *recv_private,
+			    struct socket_context **new_socket)
 {
 	struct gensec_socket *gensec_socket;
 	struct socket_context *new_sock;
 	NTSTATUS nt_status;
 
-	/* Nothing to do here, if we are not actually wrapping on this socket */
-	if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL) &&
-	    !gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
-		return socket;
-	}
-
-	nt_status = socket_create_with_ops(socket, &gensec_socket_ops, &new_sock, 
-					   SOCKET_TYPE_STREAM, socket->flags | SOCKET_FLAG_ENCRYPT);
+	nt_status = socket_create_with_ops(current_socket, &gensec_socket_ops, &new_sock, 
+					   SOCKET_TYPE_STREAM, current_socket->flags | SOCKET_FLAG_ENCRYPT);
 	if (!NT_STATUS_IS_OK(nt_status)) {
-		return NULL;
+		*new_socket = NULL;
+		return nt_status;
 	}
 
+	new_sock->state = current_socket->state;
+
 	gensec_socket = talloc(new_sock, struct gensec_socket);
 	if (gensec_socket == NULL) {
-		return NULL;
+		*new_socket = NULL;
+		return NT_STATUS_NO_MEMORY;
 	}
 
-	gensec_socket->eof = False;
-	gensec_socket->error = NT_STATUS_OK;
-	gensec_socket->interrupted = False;
-	gensec_socket->in_extra_read = 0;
+	new_sock->private_data       = gensec_socket;
+	gensec_socket->socket        = current_socket;
 
-	gensec_socket->read_buffer = data_blob(NULL, 0);
+	if (talloc_reference(gensec_socket, current_socket) == NULL) {
+		*new_socket = NULL;
+		return NT_STATUS_NO_MEMORY;
+	}
 
-	gensec_socket->gensec_security = gensec_security;
-	gensec_socket->socket          = socket;
-	if (talloc_reference(gensec_socket, socket) == NULL) {
-		return NULL;
+	/* Nothing to do here, if we are not actually wrapping on this socket */
+	if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL) &&
+	    !gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
+		
+		gensec_socket->wrap = False;
+		*new_socket = new_sock;
+		return NT_STATUS_OK;
 	}
-	gensec_socket->recv_handler    = recv_handler;
-	gensec_socket->recv_private    = recv_private;
-	gensec_socket->ev              = ev;
 
-	new_sock->private_data    = gensec_socket;
+	gensec_socket->gensec_security = gensec_security;
 
+	gensec_socket->wrap          = True;
+	gensec_socket->eof           = False;
+	gensec_socket->error         = NT_STATUS_OK;
+	gensec_socket->interrupted   = False;
+	gensec_socket->in_extra_read = 0;
+
+	gensec_socket->read_buffer   = data_blob(NULL, 0);
+
+	gensec_socket->recv_handler  = recv_handler;
+	gensec_socket->recv_private  = recv_private;
+	gensec_socket->ev            = ev;
+
 	gensec_socket->packet = packet_init(gensec_socket);
 	if (gensec_socket->packet == NULL) {
-		return NULL;
+		*new_socket = NULL;
+		return NT_STATUS_NO_MEMORY;
 	}
 
 	packet_set_private(gensec_socket->packet, gensec_socket);
-	packet_set_socket(gensec_socket->packet, socket);
+	packet_set_socket(gensec_socket->packet, gensec_socket->socket);
 	packet_set_callback(gensec_socket->packet, gensec_socket_unwrap);
 	packet_set_full_request(gensec_socket->packet, packet_full_request_u32);
 	packet_set_error_handler(gensec_socket->packet, gensec_socket_error_handler);
@@ -368,9 +396,8 @@
 
 	/* TODO: full-request that knows about maximum packet size */
 
-	new_sock->state = socket->state;
-
-	return new_sock;
+	*new_socket = new_sock;
+	return NT_STATUS_OK;
 }
 
 

Modified: branches/SAMBA_4_0/source/auth/gensec/socket.h
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/socket.h	2006-07-25 00:53:03 UTC (rev 17221)
+++ branches/SAMBA_4_0/source/auth/gensec/socket.h	2006-07-25 00:57:27 UTC (rev 17222)
@@ -20,8 +20,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-struct socket_context *gensec_socket_init(struct gensec_security *gensec_security,
-					  struct socket_context *socket,
-					  struct event_context *ev,
-					  void (*recv_handler)(void *, uint16_t),
-					  void *recv_private);
+NTSTATUS gensec_socket_init(struct gensec_security *gensec_security,
+			    struct socket_context *current_socket,
+			    struct event_context *ev,
+			    void (*recv_handler)(void *, uint16_t),
+			    void *recv_private,
+			    struct socket_context **new_socket);

Modified: branches/SAMBA_4_0/source/ldap_server/ldap_bind.c
===================================================================
--- branches/SAMBA_4_0/source/ldap_server/ldap_bind.c	2006-07-25 00:53:03 UTC (rev 17221)
+++ branches/SAMBA_4_0/source/ldap_server/ldap_bind.c	2006-07-25 00:57:27 UTC (rev 17222)
@@ -98,9 +98,11 @@
 static void ldapsrv_set_sasl(void *private) 
 {
 	struct ldapsrv_sasl_context *ctx = talloc_get_type(private, struct ldapsrv_sasl_context);
+	talloc_steal(ctx->conn->connection, ctx->sasl_socket);
+	talloc_unlink(ctx->conn->connection, ctx->conn->connection->socket);
+
 	ctx->conn->connection->socket = ctx->sasl_socket;
-	talloc_steal(ctx->conn->connection->socket, ctx->sasl_socket);
-	packet_set_socket(ctx->conn->packet, ctx->sasl_socket);
+	packet_set_socket(ctx->conn->packet, ctx->conn->connection->socket);
 }
 
 static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
@@ -193,21 +195,24 @@
 
 		ctx = talloc(call, struct ldapsrv_sasl_context); 
 
-		if (ctx) {
+		if (!ctx) {
+			status = NT_STATUS_NO_MEMORY;
+		} else {
 			ctx->conn = conn;
-			ctx->sasl_socket = gensec_socket_init(conn->gensec, 
-							      conn->connection->socket,
-							      conn->connection->event.ctx, 
-							      stream_io_handler_callback,
-							      conn->connection);
-		}
+			status = gensec_socket_init(conn->gensec, 
+						    conn->connection->socket,
+						    conn->connection->event.ctx, 
+						    stream_io_handler_callback,
+						    conn->connection,
+						    &ctx->sasl_socket);
+		} 
 
-		if (!ctx || !ctx->sasl_socket) {
+		if (!ctx || !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 (out of memory)", 
-						 req->creds.SASL.mechanism);
+						 "SASL:[%s]: Failed to setup SASL socket: %s", 
+						 req->creds.SASL.mechanism, nt_errstr(status));
 		} else {
 
 			call->send_callback = ldapsrv_set_sasl;

Modified: branches/SAMBA_4_0/source/ldap_server/ldap_server.c
===================================================================
--- branches/SAMBA_4_0/source/ldap_server/ldap_server.c	2006-07-25 00:53:03 UTC (rev 17221)
+++ branches/SAMBA_4_0/source/ldap_server/ldap_server.c	2006-07-25 00:57:27 UTC (rev 17222)
@@ -342,12 +342,16 @@
 	talloc_free(socket_address);
 
 	if (port == 636) {
-		c->socket = tls_init_server(ldapsrv_service->tls_params, c->socket, 
-					    c->event.fde, NULL);
-		if (!c->socket) {
+		struct socket_context *tls_socket = tls_init_server(ldapsrv_service->tls_params, c->socket, 
+								    c->event.fde, NULL);
+		if (!tls_socket) {
 			ldapsrv_terminate_connection(conn, "ldapsrv_accept: tls_init_server() failed");
 			return;
 		}
+		talloc_unlink(c, c->socket);
+		talloc_steal(c, tls_socket);
+		c->socket = tls_socket;
+
 	} else if (port == 3268) /* Global catalog */ {
 		conn->global_catalog = True;
 	}

Modified: branches/SAMBA_4_0/source/lib/stream/packet.c
===================================================================
--- branches/SAMBA_4_0/source/lib/stream/packet.c	2006-07-25 00:53:03 UTC (rev 17221)
+++ branches/SAMBA_4_0/source/lib/stream/packet.c	2006-07-25 00:57:27 UTC (rev 17222)
@@ -270,6 +270,16 @@
 		return;
 	}
 
+	if (npending + pc->num_read < npending) {
+		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
+		return;
+	}
+
+	if (npending + pc->num_read < pc->num_read) {
+		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
+		return;
+	}
+
 	/* possibly expand the partial packet buffer */
 	if (npending + pc->num_read > pc->partial.length) {
 		status = data_blob_realloc(pc, &pc->partial, npending+pc->num_read);
@@ -279,6 +289,20 @@
 		}
 	}
 
+	if (pc->partial.length < pc->num_read + npending) {
+		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
+		return;
+	}
+
+	if ((uint8_t *)pc->partial.data + pc->num_read < (uint8_t *)pc->partial.data) {
+		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
+		return;
+	}
+	if ((uint8_t *)pc->partial.data + pc->num_read + npending < (uint8_t *)pc->partial.data) {
+		packet_error(pc, NT_STATUS_INVALID_PARAMETER);
+		return;
+	}
+
 	status = socket_recv(pc->sock, pc->partial.data + pc->num_read, 
 			     npending, &nread);
 
@@ -337,6 +361,7 @@
 			packet_error(pc, NT_STATUS_NO_MEMORY);
 			return;
 		}
+		/* Trunate the blob sent to the caller to only the packet length */
 		status = data_blob_realloc(pc, &blob, pc->packet_size);
 		if (!NT_STATUS_IS_OK(status)) {
 			packet_error(pc, status);

Modified: branches/SAMBA_4_0/source/lib/tls/tls.c
===================================================================
--- branches/SAMBA_4_0/source/lib/tls/tls.c	2006-07-25 00:53:03 UTC (rev 17221)
+++ branches/SAMBA_4_0/source/lib/tls/tls.c	2006-07-25 00:57:27 UTC (rev 17222)
@@ -433,9 +433,9 @@
   setup for a new connection
 */
 struct socket_context *tls_init_server(struct tls_params *params, 
-				    struct socket_context *socket,
-				    struct fd_event *fde, 
-				    const char *plain_chars)
+				       struct socket_context *socket,
+				       struct fd_event *fde, 
+				       const char *plain_chars)
 {
 	struct tls_context *tls;
 	int ret;
@@ -457,17 +457,19 @@
 	tls->socket          = socket;
 	tls->fde             = fde;
 	if (talloc_reference(tls, fde) == NULL) {
+		talloc_free(new_sock);
 		return NULL;
 	}
 	if (talloc_reference(tls, socket) == NULL) {
+		talloc_free(new_sock);
 		return NULL;
 	}
 
 	new_sock->private_data    = tls;
 
 	if (!params->tls_enabled) {
-		tls->tls_enabled = False;
-		return new_sock;
+		talloc_free(new_sock);
+		return NULL;
 	}
 
 	TLSCHECK(gnutls_init(&tls->session, GNUTLS_SERVER));
@@ -503,9 +505,8 @@
 
 failed:
 	DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret)));
-	tls->tls_enabled = False;
-	params->tls_enabled = False;
-	return new_sock;
+	talloc_free(new_sock);
+	return NULL;
 }
 
 
@@ -649,7 +650,10 @@
 				    struct fd_event *fde, 
 				    const char *plain_chars)
 {
-	return socket;
+	if (plain_chars) {
+		return socket;
+	}
+	return NULL;
 }
 
 
@@ -659,7 +663,7 @@
 struct socket_context *tls_init_client(struct socket_context *socket,
 				       struct fd_event *fde)
 {
-	return socket;
+	return NULL;
 }
 
 BOOL tls_support(struct tls_params *params)

Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c	2006-07-25 00:53:03 UTC (rev 17221)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c	2006-07-25 00:57:27 UTC (rev 17222)
@@ -370,15 +370,18 @@
 	talloc_free(tmp_ctx);
 
 	if (NT_STATUS_IS_OK(status)) {
-		struct socket_context *socket = gensec_socket_init(conn->gensec, 
-								   conn->sock,
-								   conn->event.event_ctx, 
-								   ldap_read_io_handler,
-								   conn);
-		if (socket) {
-			conn->sock = socket;
-			talloc_steal(conn->sock, socket);
-			packet_set_socket(conn->packet, socket);
+		struct socket_context *sasl_socket;
+		status = gensec_socket_init(conn->gensec, 
+					    conn->sock,
+					    conn->event.event_ctx, 
+					    ldap_read_io_handler,
+					    conn,
+					    &sasl_socket);
+		if (NT_STATUS_IS_OK(status)) {
+			talloc_steal(conn->sock, sasl_socket);
+			talloc_unlink(conn, conn->sock);
+			conn->sock = sasl_socket;
+			packet_set_socket(conn->packet, conn->sock);
 		} else {
 			status = NT_STATUS_NO_MEMORY;
 			goto failed;

Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c	2006-07-25 00:53:03 UTC (rev 17221)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c	2006-07-25 00:57:27 UTC (rev 17222)
@@ -320,7 +320,6 @@
 
 static void ldap_connect_recv_conn(struct composite_context *ctx)
 {
-	struct socket_context *initial_socket;
 	struct ldap_connect_state *state =
 		talloc_get_type(ctx->async.private_data,
 				struct ldap_connect_state);
@@ -341,13 +340,15 @@
 	}
 
 	talloc_steal(conn, conn->sock);
-	initial_socket = conn->sock;
 	if (conn->ldaps) {
-		conn->sock = tls_init_client(conn->sock, conn->event.fde);
-		if (conn->sock == NULL) {
-			talloc_free(initial_socket);
+		struct socket_context *tls_socket = tls_init_client(conn->sock, conn->event.fde);
+		if (tls_socket == NULL) {
+			talloc_free(conn->sock);
 			return;
 		}
+		talloc_unlink(conn, conn->sock);
+		conn->sock = tls_socket;
+		talloc_steal(conn, conn->sock);
 	}
 
 	conn->packet = packet_init(conn);



More information about the samba-cvs mailing list