svn commit: samba r18068 - in branches/SAMBA_4_0/source/auth/gensec: .

abartlet at samba.org abartlet at samba.org
Tue Sep 5 09:42:55 GMT 2006


Author: abartlet
Date: 2006-09-05 09:42:54 +0000 (Tue, 05 Sep 2006)
New Revision: 18068

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

Log:
This splits the handling of multiple SASL packets between the GENSEC
backend (if it chooses to implement it), or the GENSEC socket code.

This is to allow us to handle DIGEST-MD5 across to cyrus-sasl.

Andrew Bartlett

Modified:
   branches/SAMBA_4_0/source/auth/gensec/gensec.c
   branches/SAMBA_4_0/source/auth/gensec/gensec.h
   branches/SAMBA_4_0/source/auth/gensec/socket.c
   branches/SAMBA_4_0/source/auth/gensec/socket.h
   branches/SAMBA_4_0/source/auth/gensec/spnego.c


Changeset:
Modified: branches/SAMBA_4_0/source/auth/gensec/gensec.c
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/gensec.c	2006-09-05 07:58:26 UTC (rev 18067)
+++ branches/SAMBA_4_0/source/auth/gensec/gensec.c	2006-09-05 09:42:54 UTC (rev 18068)
@@ -4,7 +4,7 @@
    Generic Authentication Interface
 
    Copyright (C) Andrew Tridgell 2003
-   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2004-2005
+   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2004-2006
    
    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
@@ -51,7 +51,9 @@
 	int i, j, num_mechs_in;
 
 	if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
-		talloc_reference(mem_ctx, old_gensec_list);
+		if (!talloc_reference(mem_ctx, old_gensec_list)) {
+			return NULL;
+		}
 		return old_gensec_list;
 	}
 
@@ -103,13 +105,17 @@
 	struct gensec_security_ops **backends;
 	backends = gensec_security_all();
 	if (!gensec_security) {
-		talloc_reference(mem_ctx, backends);
+		if (!talloc_reference(mem_ctx, backends)) {
+			return NULL;
+		}
 		return backends;
 	} else {
 		enum credentials_use_kerberos use_kerberos;
 		struct cli_credentials *creds = gensec_get_credentials(gensec_security);
 		if (!creds) {
-			talloc_reference(mem_ctx, backends);
+			if (!talloc_reference(mem_ctx, backends)) {
+				return NULL;
+			}
 			return backends;
 		}
 		use_kerberos = cli_credentials_get_kerberos_state(creds);
@@ -840,25 +846,25 @@
 	return gensec_security->ops->sig_size(gensec_security, data_size);
 }
 
-size_t gensec_max_input_size(struct gensec_security *gensec_security) 
+size_t gensec_max_wrapped_size(struct gensec_security *gensec_security) 
 {
-	if (!gensec_security->ops->max_input_size) {
-		return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
+	if (!gensec_security->ops->max_wrapped_size) {
+		return (1 << 17);
 	}
 	
-	return gensec_security->ops->max_input_size(gensec_security);
+	return gensec_security->ops->max_wrapped_size(gensec_security);
 }
 
-size_t gensec_max_wrapped_size(struct gensec_security *gensec_security) 
+size_t gensec_max_input_size(struct gensec_security *gensec_security) 
 {
-	if (!gensec_security->ops->max_wrapped_size) {
-		return (1 << 17);
+	if (!gensec_security->ops->max_input_size) {
+		return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
 	}
 	
-	return gensec_security->ops->max_wrapped_size(gensec_security);
+	return gensec_security->ops->max_input_size(gensec_security);
 }
 
-_PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security, 
+NTSTATUS gensec_wrap(struct gensec_security *gensec_security, 
 		     TALLOC_CTX *mem_ctx, 
 		     const DATA_BLOB *in, 
 		     DATA_BLOB *out) 
@@ -869,7 +875,7 @@
 	return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
 }
 
-_PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security, 
+NTSTATUS gensec_unwrap(struct gensec_security *gensec_security, 
 		       TALLOC_CTX *mem_ctx, 
 		       const DATA_BLOB *in, 
 		       DATA_BLOB *out) 

Modified: branches/SAMBA_4_0/source/auth/gensec/gensec.h
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/gensec.h	2006-09-05 07:58:26 UTC (rev 18067)
+++ branches/SAMBA_4_0/source/auth/gensec/gensec.h	2006-09-05 09:42:54 UTC (rev 18068)
@@ -105,9 +105,21 @@
 				  const DATA_BLOB *in, 
 				  DATA_BLOB *out); 
 	NTSTATUS (*unwrap)(struct gensec_security *gensec_security, 
-				  TALLOC_CTX *mem_ctx, 
-				  const DATA_BLOB *in, 
-				  DATA_BLOB *out); 
+			   TALLOC_CTX *mem_ctx, 
+			   const DATA_BLOB *in, 
+			   DATA_BLOB *out); 
+	NTSTATUS (*wrap_packets)(struct gensec_security *gensec_security, 
+				 TALLOC_CTX *mem_ctx, 
+				 const DATA_BLOB *in, 
+				 DATA_BLOB *out,
+				 size_t *len_processed); 
+	NTSTATUS (*unwrap_packets)(struct gensec_security *gensec_security, 
+				   TALLOC_CTX *mem_ctx, 
+				   const DATA_BLOB *in, 
+				   DATA_BLOB *out,
+				   size_t *len_processed); 
+	NTSTATUS (*packet_full_request)(struct gensec_security *gensec_security,
+					DATA_BLOB blob, size_t *size);
 	NTSTATUS (*session_key)(struct gensec_security *gensec_security, DATA_BLOB *session_key);
 	NTSTATUS (*session_info)(struct gensec_security *gensec_security, 
 				 struct auth_session_info **session_info); 

Modified: branches/SAMBA_4_0/source/auth/gensec/socket.c
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/socket.c	2006-09-05 07:58:26 UTC (rev 18067)
+++ branches/SAMBA_4_0/source/auth/gensec/socket.c	2006-09-05 09:42:54 UTC (rev 18068)
@@ -58,6 +58,115 @@
 	return NT_STATUS_OK;
 }
 
+/* These functions are for use here only (public because SPNEGO must
+ * use them for recursion) */
+NTSTATUS gensec_wrap_packets(struct gensec_security *gensec_security, 
+			     TALLOC_CTX *mem_ctx, 
+			     const DATA_BLOB *in, 
+			     DATA_BLOB *out,
+			     size_t *len_processed) 
+{
+	if (!gensec_security->ops->wrap_packets) {
+		NTSTATUS nt_status;
+		size_t max_input_size;
+		DATA_BLOB unwrapped, wrapped;
+		max_input_size = gensec_max_input_size(gensec_security);
+		unwrapped = data_blob_const(in->data, MIN(max_input_size, (size_t)in->length));
+		
+		nt_status = gensec_wrap(gensec_security, 
+					mem_ctx,
+					&unwrapped, &wrapped);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			talloc_free(mem_ctx);
+			return nt_status;
+		}
+		
+		*out = data_blob_talloc(mem_ctx, NULL, 4);
+		if (!out->data) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		RSIVAL(out->data, 0, wrapped.length);
+		
+		nt_status = data_blob_append(mem_ctx, out, wrapped.data, wrapped.length);
+		
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			return nt_status;
+		}
+		*len_processed = unwrapped.length;
+		return nt_status;
+	}
+	return gensec_security->ops->wrap_packets(gensec_security, mem_ctx, in, out,
+						  len_processed);
+}
+
+/* These functions are for use here only (public because SPNEGO must
+ * use them for recursion) */
+NTSTATUS gensec_unwrap_packets(struct gensec_security *gensec_security, 
+					TALLOC_CTX *mem_ctx, 
+					const DATA_BLOB *in, 
+					DATA_BLOB *out,
+					size_t *len_processed) 
+{
+	if (!gensec_security->ops->unwrap_packets) {
+		DATA_BLOB wrapped;
+		NTSTATUS nt_status;
+		size_t packet_size;
+		if (in->length < 4) {
+			/* Missing the header we already had! */
+			DEBUG(0, ("Asked to unwrap packet of bogus length!  How did we get the short packet?!\n"));
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+		
+		packet_size = RIVAL(in->data, 0);
+		
+		wrapped = data_blob_const(in->data + 4, packet_size);
+		
+		if (wrapped.length > (in->length - 4)) {
+			DEBUG(0, ("Asked to unwrap packed of bogus length %d > %d!  How did we get this?!\n",
+				  wrapped.length, in->length - 4));
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+		
+		nt_status = gensec_unwrap(gensec_security, 
+					  mem_ctx,
+					  &wrapped, out);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			return nt_status;
+		}
+		
+		*len_processed = packet_size + 4;
+		return nt_status;
+	}
+	return gensec_security->ops->unwrap_packets(gensec_security, mem_ctx, in, out,
+						    len_processed);
+}
+
+/* These functions are for use here only (public because SPNEGO must
+ * use them for recursion) */
+NTSTATUS gensec_packet_full_request(struct gensec_security *gensec_security,
+				    DATA_BLOB blob, size_t *size) 
+{
+	if (gensec_security->ops->packet_full_request) {
+		return gensec_security->ops->packet_full_request(gensec_security,
+								 blob, size);
+	}
+	if (gensec_security->ops->unwrap_packets) {
+		if (blob.length) {
+			*size = blob.length;
+			return NT_STATUS_OK;
+		}
+		return STATUS_MORE_ENTRIES;
+	}
+	return packet_full_request_u32(NULL, blob, size);
+}
+
+static NTSTATUS gensec_socket_full_request(void *private, DATA_BLOB blob, size_t *size) 
+{
+	struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
+	struct gensec_security *gensec_security = gensec_socket->gensec_security;
+	return gensec_packet_full_request(gensec_security, blob, size);
+}
+
 /* Try to figure out how much data is waiting to be read */
 static NTSTATUS gensec_socket_pending(struct socket_context *sock, size_t *npending) 
 {
@@ -183,37 +292,29 @@
 static NTSTATUS gensec_socket_unwrap(void *private, DATA_BLOB blob)
 {
 	struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
-	DATA_BLOB wrapped;
 	DATA_BLOB unwrapped;
 	NTSTATUS nt_status;
 	TALLOC_CTX *mem_ctx;
 	uint32_t packet_size;
 
-	if (blob.length < 4) {
-		/* Missing the header we already had! */
-		DEBUG(0, ("Asked to unwrap packed of bogus length!  How did we get the short packet?!\n"));
-		return NT_STATUS_INVALID_PARAMETER;
-	}
-
-	wrapped = data_blob_const(blob.data + 4, blob.length - 4);
-
-	packet_size = RIVAL(blob.data, 0);
-	if (packet_size != wrapped.length) {
-		DEBUG(0, ("Asked to unwrap packed of bogus length!  How did we get this?!\n"));
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
 	mem_ctx = talloc_new(gensec_socket);
 	if (!mem_ctx) {
 		return NT_STATUS_NO_MEMORY;
 	}
-	nt_status = gensec_unwrap(gensec_socket->gensec_security, 
-				  mem_ctx,
-				  &wrapped, &unwrapped);
+	nt_status = gensec_unwrap_packets(gensec_socket->gensec_security, 
+					  mem_ctx,
+					  &blob, &unwrapped, 
+					  &packet_size);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		talloc_free(mem_ctx);
 		return nt_status;
 	}
+
+	if (packet_size != blob.length) {
+		DEBUG(0, ("gensec_socket_unwrap: Did not consume entire packet!\n"));
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
 	/* We could change this into a linked list, and have
 	 * gensec_socket_recv() and gensec_socket_pending() walk the
 	 * linked list */
@@ -242,9 +343,8 @@
 {
 	NTSTATUS nt_status;
 	struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
-	DATA_BLOB unwrapped, wrapped, out;
+	DATA_BLOB wrapped;
 	TALLOC_CTX *mem_ctx;
-	size_t max_input_size;
 
 	if (!gensec_socket->wrap) {
 		return socket_send(gensec_socket->socket, blob, sendlen);
@@ -273,38 +373,20 @@
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	max_input_size = gensec_max_input_size(gensec_socket->gensec_security);
-	unwrapped = data_blob_const(blob->data, MIN(max_input_size, (size_t)blob->length));
-	
-	nt_status = gensec_wrap(gensec_socket->gensec_security, 
-				mem_ctx,
-				&unwrapped, &wrapped);
+	nt_status = gensec_wrap_packets(gensec_socket->gensec_security, 
+					mem_ctx,
+					blob, &wrapped, 
+					&gensec_socket->orig_send_len);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		talloc_free(mem_ctx);
 		return nt_status;
 	}
 	
-	out = data_blob_talloc(mem_ctx, NULL, 4);
-	if (!out.data) {
-		talloc_free(mem_ctx);
-		return NT_STATUS_NO_MEMORY;
-	}
-	RSIVAL(out.data, 0, wrapped.length);
-
-	nt_status = data_blob_append(gensec_socket, &out, wrapped.data, wrapped.length);
-
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		talloc_free(mem_ctx);
-		return nt_status;
-	}
-	
 	gensec_socket->interrupted = True;
 	gensec_socket->error = NT_STATUS_OK;
-	gensec_socket->orig_send_len
-		= unwrapped.length;
 
 	nt_status = packet_send_callback(gensec_socket->packet, 
-					 out,
+					 wrapped,
 					 send_callback, gensec_socket);
 
 	talloc_free(mem_ctx);
@@ -390,7 +472,7 @@
 	packet_set_private(gensec_socket->packet, gensec_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_full_request(gensec_socket->packet, gensec_socket_full_request);
 	packet_set_error_handler(gensec_socket->packet, gensec_socket_error_handler);
 	packet_set_serialise(gensec_socket->packet);
 

Modified: branches/SAMBA_4_0/source/auth/gensec/socket.h
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/socket.h	2006-09-05 07:58:26 UTC (rev 18067)
+++ branches/SAMBA_4_0/source/auth/gensec/socket.h	2006-09-05 09:42:54 UTC (rev 18068)
@@ -26,3 +26,23 @@
 			    void (*recv_handler)(void *, uint16_t),
 			    void *recv_private,
 			    struct socket_context **new_socket);
+/* These functions are for use here only (public because SPNEGO must
+ * use them for recursion) */
+NTSTATUS gensec_wrap_packets(struct gensec_security *gensec_security, 
+			     TALLOC_CTX *mem_ctx, 
+			     const DATA_BLOB *in, 
+			     DATA_BLOB *out,
+			     size_t *len_processed);
+/* These functions are for use here only (public because SPNEGO must
+ * use them for recursion) */
+NTSTATUS gensec_unwrap_packets(struct gensec_security *gensec_security, 
+			       TALLOC_CTX *mem_ctx, 
+			       const DATA_BLOB *in, 
+			       DATA_BLOB *out,
+			       size_t *len_processed);
+
+/* These functions are for use here only (public because SPNEGO must
+ * use them for recursion) */
+NTSTATUS gensec_packet_full_request(struct gensec_security *gensec_security,
+				    DATA_BLOB blob, size_t *size);
+

Modified: branches/SAMBA_4_0/source/auth/gensec/spnego.c
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/spnego.c	2006-09-05 07:58:26 UTC (rev 18067)
+++ branches/SAMBA_4_0/source/auth/gensec/spnego.c	2006-09-05 09:42:54 UTC (rev 18068)
@@ -26,6 +26,8 @@
 #include "auth/auth.h"
 #include "auth/gensec/spnego_proto.h"
 #include "librpc/gen_ndr/ndr_dcerpc.h"
+#include "lib/socket/socket.h"
+#include "auth/gensec/socket.h"
 
 enum spnego_state_position {
 	SPNEGO_SERVER_START,
@@ -199,6 +201,59 @@
 			     mem_ctx, in, out);
 }
 
+static NTSTATUS gensec_spnego_wrap_packets(struct gensec_security *gensec_security, 
+					   TALLOC_CTX *mem_ctx, 
+					   const DATA_BLOB *in, 
+					   DATA_BLOB *out,
+					   size_t *len_processed) 
+{
+	struct spnego_state *spnego_state = gensec_security->private_data;
+
+	if (spnego_state->state_position != SPNEGO_DONE 
+	    && spnego_state->state_position != SPNEGO_FALLBACK) {
+		DEBUG(1, ("gensec_spnego_wrap: wrong state for wrap\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	
+	return gensec_wrap_packets(spnego_state->sub_sec_security, 
+				   mem_ctx, in, out,
+				   len_processed);
+}
+
+static NTSTATUS gensec_spnego_packet_full_request(struct gensec_security *gensec_security, 
+					     	DATA_BLOB blob, size_t *size)
+{
+	struct spnego_state *spnego_state = gensec_security->private_data;
+
+	if (spnego_state->state_position != SPNEGO_DONE 
+	    && spnego_state->state_position != SPNEGO_FALLBACK) {
+		DEBUG(1, ("gensec_spnego_unwrap: wrong state for unwrap\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	
+	return gensec_packet_full_request(spnego_state->sub_sec_security, 
+					  blob, size);
+}
+
+static NTSTATUS gensec_spnego_unwrap_packets(struct gensec_security *gensec_security, 
+					     TALLOC_CTX *mem_ctx, 
+					     const DATA_BLOB *in, 
+					     DATA_BLOB *out,
+					     size_t *len_processed) 
+{
+	struct spnego_state *spnego_state = gensec_security->private_data;
+
+	if (spnego_state->state_position != SPNEGO_DONE 
+	    && spnego_state->state_position != SPNEGO_FALLBACK) {
+		DEBUG(1, ("gensec_spnego_unwrap: wrong state for unwrap\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	
+	return gensec_unwrap_packets(spnego_state->sub_sec_security, 
+				     mem_ctx, in, out,
+				     len_processed);
+}
+
 static size_t gensec_spnego_sig_size(struct gensec_security *gensec_security, size_t data_size) 
 {
 	struct spnego_state *spnego_state = gensec_security->private_data;
@@ -976,8 +1031,11 @@
 	.max_input_size	  = gensec_spnego_max_input_size,
 	.check_packet	  = gensec_spnego_check_packet,
 	.unseal_packet	  = gensec_spnego_unseal_packet,
+	.packet_full_request = gensec_spnego_packet_full_request,
 	.wrap             = gensec_spnego_wrap,
 	.unwrap           = gensec_spnego_unwrap,
+	.wrap_packets     = gensec_spnego_wrap_packets,
+	.unwrap_packets   = gensec_spnego_unwrap_packets,
 	.session_key	  = gensec_spnego_session_key,
 	.session_info     = gensec_spnego_session_info,
 	.have_feature     = gensec_spnego_have_feature,



More information about the samba-cvs mailing list