[PATCH] libads: abstract out SASL wrapping code

Alexander Bokovoy ab at samba.org
Fri May 5 17:24:43 UTC 2017


Hi,

this is a preparatory patch to allow libads to user LDAP management via
smbldap instead of doing that directly. The patch has no functional
changes yet but untangles SASL code from direct use of ADS structure
(apart from initialization).

It compiles but I haven't tested yet. Please review.


-- 
/ Alexander Bokovoy
-------------- next part --------------
>From e1ab7f09646a8504f5ad263defc3ab537735b77b Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab at samba.org>
Date: Fri, 5 May 2017 15:37:20 +0300
Subject: [PATCH] libads: abstract out SASL wrapping code

Prepare for rebasing libads on top of libsmbldap.

To make libads using 'struct smbldap_state' instead of direct LDAP
structure, we need to abstract out libads logic from connection
handling. SASL wrapping does not really depend on availability of LDAP
handle and does not need direct access to ADS_STRUCT. As result, we'll
be able to move SASL wrapping code under smbldap once the latter is able
to pass settings that libads passes to the SASL wrapping.

Signed-off-by: Alexander Bokovoy <ab at samba.org>
---
 source3/include/ads.h          |  68 ++++++-------
 source3/libads/ads_proto.h     |   8 +-
 source3/libads/ldap.c          |  17 ++--
 source3/libads/ndr.c           |  26 +----
 source3/libads/sasl.c          | 126 +++++++++++++------------
 source3/libads/sasl_wrapping.c | 210 ++++++++++++++++++++++++-----------------
 6 files changed, 243 insertions(+), 212 deletions(-)

diff --git a/source3/include/ads.h b/source3/include/ads.h
index cacb25c..2b25c1c 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -9,13 +9,13 @@
 #include "libads/ads_status.h"
 #include "smb_ldap.h"
 
-struct ads_struct;
+struct ads_saslwrap;
 
 struct ads_saslwrap_ops {
 	const char *name;
-	ADS_STATUS (*wrap)(struct ads_struct *, uint8_t *buf, uint32_t len);
-	ADS_STATUS (*unwrap)(struct ads_struct *);
-	void (*disconnect)(struct ads_struct *);
+	ADS_STATUS (*wrap)(struct ads_saslwrap *, uint8_t *buf, uint32_t len);
+	ADS_STATUS (*unwrap)(struct ads_saslwrap *);
+	void (*disconnect)(struct ads_saslwrap *);
 };
 
 enum ads_saslwrap_type {
@@ -24,6 +24,37 @@ enum ads_saslwrap_type {
 	ADS_SASLWRAP_TYPE_SEAL = 4
 };
 
+struct ads_saslwrap {
+	/* expected SASL wrapping type */
+	enum ads_saslwrap_type wrap_type;
+	/* SASL wrapping operations */
+	const struct ads_saslwrap_ops *wrap_ops;
+#ifdef HAVE_LDAP_SASL_WRAPPING
+	Sockbuf_IO_Desc *sbiod; /* lowlevel state for LDAP wrapping */
+#endif /* HAVE_LDAP_SASL_WRAPPING */
+	TALLOC_CTX *mem_ctx;
+	void *wrap_private_data;
+	struct {
+		uint32_t ofs;
+		uint32_t needed;
+		uint32_t left;
+#define        ADS_SASL_WRAPPING_IN_MAX_WRAPPED        0x0FFFFFFF
+		uint32_t max_wrapped;
+		uint32_t min_wrapped;
+		uint32_t size;
+		uint8_t *buf;
+	} in;
+	struct {
+		uint32_t ofs;
+		uint32_t left;
+#define        ADS_SASL_WRAPPING_OUT_MAX_WRAPPED       0x00A00000
+		uint32_t max_unwrapped;
+		uint32_t sig_size;
+		uint32_t size;
+		uint8_t *buf;
+	} out;
+};
+
 typedef struct ads_struct {
 	int is_mine;	/* do I own this structure's memory? */
 
@@ -65,39 +96,12 @@ typedef struct ads_struct {
 
 	/* info about the current LDAP connection */
 #ifdef HAVE_LDAP
+	struct ads_saslwrap ldap_wrap_data;
 	struct {
 		LDAP *ld;
 		struct sockaddr_storage ss; /* the ip of the active connection, if any */
 		time_t last_attempt; /* last attempt to reconnect, monotonic clock */
 		int port;
-
-		enum ads_saslwrap_type wrap_type;
-
-#ifdef HAVE_LDAP_SASL_WRAPPING
-		Sockbuf_IO_Desc *sbiod; /* lowlevel state for LDAP wrapping */
-#endif /* HAVE_LDAP_SASL_WRAPPING */
-		TALLOC_CTX *mem_ctx;
-		const struct ads_saslwrap_ops *wrap_ops;
-		void *wrap_private_data;
-		struct {
-			uint32_t ofs;
-			uint32_t needed;
-			uint32_t left;
-#define        ADS_SASL_WRAPPING_IN_MAX_WRAPPED        0x0FFFFFFF
-			uint32_t max_wrapped;
-			uint32_t min_wrapped;
-			uint32_t size;
-			uint8_t *buf;
-		} in;
-		struct {
-			uint32_t ofs;
-			uint32_t left;
-#define        ADS_SASL_WRAPPING_OUT_MAX_WRAPPED       0x00A00000
-			uint32_t max_unwrapped;
-			uint32_t sig_size;
-			uint32_t size;
-			uint8_t *buf;
-		} out;
 	} ldap;
 #endif /* HAVE_LDAP */
 } ADS_STRUCT;
diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h
index 425c352..b6d9d9b 100644
--- a/source3/libads/ads_proto.h
+++ b/source3/libads/ads_proto.h
@@ -182,12 +182,12 @@ ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads);
 
 /* The following definitions come from libads/sasl_wrapping.c  */
 
-ADS_STATUS ads_setup_sasl_wrapping(ADS_STRUCT *ads,
-				   const struct ads_saslwrap_ops *ops,
-				   void *private_data);
-ADS_STATUS ads_setup_sasl_wrapping(ADS_STRUCT *ads,
+ADS_STATUS ads_setup_sasl_wrapping(struct ads_saslwrap *wrap, LDAP *ld,
 				   const struct ads_saslwrap_ops *ops,
 				   void *private_data);
+void ndr_print_ads_saslwrap_struct(struct ndr_print *ndr,
+				   const char *name,
+				   const struct ads_saslwrap *r);
 
 /* The following definitions come from libads/util.c  */
 
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index c70cdeb..fdb729e 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -566,8 +566,9 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
 	char addr[INET6_ADDRSTRLEN];
 
 	ZERO_STRUCT(ads->ldap);
+	ZERO_STRUCT(ads->ldap_wrap_data);
 	ads->ldap.last_attempt	= time_mono(NULL);
-	ads->ldap.wrap_type	= ADS_SASLWRAP_TYPE_PLAIN;
+	ads->ldap_wrap_data.wrap_type	= ADS_SASLWRAP_TYPE_PLAIN;
 
 	/* try with a user specified server */
 
@@ -643,8 +644,8 @@ got_connection:
 		goto out;
 	}
 
-	ads->ldap.mem_ctx = talloc_init("ads LDAP connection memory");
-	if (!ads->ldap.mem_ctx) {
+	ads->ldap_wrap_data.mem_ctx = talloc_init("ads LDAP connection memory");
+	if (!ads->ldap_wrap_data.mem_ctx) {
 		status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
 		goto out;
 	}
@@ -730,13 +731,15 @@ void ads_disconnect(ADS_STRUCT *ads)
 		ldap_unbind(ads->ldap.ld);
 		ads->ldap.ld = NULL;
 	}
-	if (ads->ldap.wrap_ops && ads->ldap.wrap_ops->disconnect) {
-		ads->ldap.wrap_ops->disconnect(ads);
+	if (ads->ldap_wrap_data.wrap_ops &&
+		ads->ldap_wrap_data.wrap_ops->disconnect) {
+		ads->ldap_wrap_data.wrap_ops->disconnect(&ads->ldap_wrap_data);
 	}
-	if (ads->ldap.mem_ctx) {
-		talloc_free(ads->ldap.mem_ctx);
+	if (ads->ldap_wrap_data.mem_ctx) {
+		talloc_free(ads->ldap_wrap_data.mem_ctx);
 	}
 	ZERO_STRUCT(ads->ldap);
+	ZERO_STRUCT(ads->ldap_wrap_data);
 }
 
 /*
diff --git a/source3/libads/ndr.c b/source3/libads/ndr.c
index 6cecbb0..1b586c3 100644
--- a/source3/libads/ndr.c
+++ b/source3/libads/ndr.c
@@ -87,31 +87,7 @@ void ndr_print_ads_struct(struct ndr_print *ndr, const char *name, const struct
 	ndr_print_sockaddr_storage(ndr, "ss", &r->ldap.ss);
 	ndr_print_time_t(ndr, "last_attempt", r->ldap.last_attempt);
 	ndr_print_uint32(ndr, "port", r->ldap.port);
-	ndr_print_uint16(ndr, "wrap_type", r->ldap.wrap_type);
-#ifdef HAVE_LDAP_SASL_WRAPPING
-	ndr_print_ptr(ndr, "sbiod", r->ldap.sbiod);
-#endif /* HAVE_LDAP_SASL_WRAPPING */
-	ndr_print_ptr(ndr, "mem_ctx", r->ldap.mem_ctx);
-	ndr_print_ptr(ndr, "wrap_ops", r->ldap.wrap_ops);
-	ndr_print_ptr(ndr, "wrap_private_data", r->ldap.wrap_private_data);
-	ndr_print_struct(ndr, name, "in");
-	ndr->depth++;
-	ndr_print_uint32(ndr, "ofs", r->ldap.in.ofs);
-	ndr_print_uint32(ndr, "needed", r->ldap.in.needed);
-	ndr_print_uint32(ndr, "left", r->ldap.in.left);
-	ndr_print_uint32(ndr, "max_wrapped", r->ldap.in.max_wrapped);
-	ndr_print_uint32(ndr, "min_wrapped", r->ldap.in.min_wrapped);
-	ndr_print_uint32(ndr, "size", r->ldap.in.size);
-	ndr_print_array_uint8(ndr, "buf", r->ldap.in.buf, r->ldap.in.size);
-	ndr->depth--;
-	ndr_print_struct(ndr, name, "out");
-	ndr->depth++;
-	ndr_print_uint32(ndr, "ofs", r->ldap.out.ofs);
-	ndr_print_uint32(ndr, "left", r->ldap.out.left);
-	ndr_print_uint32(ndr, "max_unwrapped", r->ldap.out.max_unwrapped);
-	ndr_print_uint32(ndr, "sig_size", r->ldap.out.sig_size);
-	ndr_print_uint32(ndr, "size", r->ldap.out.size);
-	ndr_print_array_uint8(ndr, "buf", r->ldap.out.buf, r->ldap.out.size);
+	ndr_print_ads_saslwrap_struct(ndr, "saslwrap", &(r->ldap_wrap_data));
 	ndr->depth--;
 	ndr->depth--;
 #endif /* HAVE_LDAP */
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index ab79f70..580a6d7 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -30,10 +30,11 @@
 
 #ifdef HAVE_LDAP
 
-static ADS_STATUS ads_sasl_gensec_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len)
+static ADS_STATUS ads_sasl_gensec_wrap(struct ads_saslwrap *wrap,
+				       uint8_t *buf, uint32_t len)
 {
 	struct gensec_security *gensec_security =
-		talloc_get_type_abort(ads->ldap.wrap_private_data,
+		talloc_get_type_abort(wrap->wrap_private_data,
 		struct gensec_security);
 	NTSTATUS nt_status;
 	DATA_BLOB unwrapped, wrapped;
@@ -47,32 +48,32 @@ static ADS_STATUS ads_sasl_gensec_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t l
 		return ADS_ERROR_NT(nt_status);
 	}
 
-	if ((ads->ldap.out.size - 4) < wrapped.length) {
+	if ((wrap->out.size - 4) < wrapped.length) {
 		TALLOC_FREE(frame);
 		return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
 	}
 
 	/* copy the wrapped blob to the right location */
-	memcpy(ads->ldap.out.buf + 4, wrapped.data, wrapped.length);
+	memcpy(wrap->out.buf + 4, wrapped.data, wrapped.length);
 
 	/* set how many bytes must be written to the underlying socket */
-	ads->ldap.out.left = 4 + wrapped.length;
+	wrap->out.left = 4 + wrapped.length;
 
 	TALLOC_FREE(frame);
 
 	return ADS_SUCCESS;
 }
 
-static ADS_STATUS ads_sasl_gensec_unwrap(ADS_STRUCT *ads)
+static ADS_STATUS ads_sasl_gensec_unwrap(struct ads_saslwrap *wrap)
 {
 	struct gensec_security *gensec_security =
-		talloc_get_type_abort(ads->ldap.wrap_private_data,
+		talloc_get_type_abort(wrap->wrap_private_data,
 		struct gensec_security);
 	NTSTATUS nt_status;
 	DATA_BLOB unwrapped, wrapped;
 	TALLOC_CTX *frame = talloc_stackframe();
 
-	wrapped = data_blob_const(ads->ldap.in.buf + 4, ads->ldap.in.ofs - 4);
+	wrapped = data_blob_const(wrap->in.buf + 4, wrap->in.ofs - 4);
 
 	nt_status = gensec_unwrap(gensec_security, frame, &wrapped, &unwrapped);
 	if (!NT_STATUS_IS_OK(nt_status)) {
@@ -86,27 +87,27 @@ static ADS_STATUS ads_sasl_gensec_unwrap(ADS_STRUCT *ads)
 	}
 
 	/* copy the wrapped blob to the right location */
-	memcpy(ads->ldap.in.buf + 4, unwrapped.data, unwrapped.length);
+	memcpy(wrap->in.buf + 4, unwrapped.data, unwrapped.length);
 
 	/* set how many bytes must be written to the underlying socket */
-	ads->ldap.in.left	= unwrapped.length;
-	ads->ldap.in.ofs	= 4;
+	wrap->in.left	= unwrapped.length;
+	wrap->in.ofs	= 4;
 
 	TALLOC_FREE(frame);
 
 	return ADS_SUCCESS;
 }
 
-static void ads_sasl_gensec_disconnect(ADS_STRUCT *ads)
+static void ads_sasl_gensec_disconnect(struct ads_saslwrap *wrap)
 {
 	struct gensec_security *gensec_security =
-		talloc_get_type_abort(ads->ldap.wrap_private_data,
+		talloc_get_type_abort(wrap->wrap_private_data,
 		struct gensec_security);
 
 	TALLOC_FREE(gensec_security);
 
-	ads->ldap.wrap_ops = NULL;
-	ads->ldap.wrap_private_data = NULL;
+	wrap->wrap_ops = NULL;
+	wrap->wrap_private_data = NULL;
 }
 
 static const struct ads_saslwrap_ops ads_sasl_gensec_ops = {
@@ -136,6 +137,7 @@ static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
 	bool use_spnego_principal = lp_client_use_spnego_principal();
 	const char *sasl_list[] = { sasl, NULL };
 	NTTIME end_nt_time;
+	struct ads_saslwrap *wrap = &ads->ldap_wrap_data;
 
 	nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
 	if (!NT_STATUS_IS_OK(nt_status)) {
@@ -185,7 +187,7 @@ static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
 		use_spnego_principal = false;
 	}
 
-	switch (ads->ldap.wrap_type) {
+	switch (wrap->wrap_type) {
 	case ADS_SASLWRAP_TYPE_SEAL:
 		gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
 		gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
@@ -278,7 +280,7 @@ static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
 	data_blob_free(&blob_in);
 	data_blob_free(&blob_out);
 
-	if (ads->ldap.wrap_type >= ADS_SASLWRAP_TYPE_SEAL) {
+	if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SEAL) {
 		bool ok;
 
 		ok = gensec_have_feature(auth_generic_state->gensec_security,
@@ -297,7 +299,7 @@ static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
 			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
 		}
 
-	} else if (ads->ldap.wrap_type >= ADS_SASLWRAP_TYPE_SIGN) {
+	} else if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SIGN) {
 		bool ok;
 
 		ok = gensec_have_feature(auth_generic_state->gensec_security,
@@ -317,20 +319,24 @@ static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
 		ads->auth.tgs_expire = tv.tv_sec;
 	}
 
-	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
-		size_t max_wrapped = gensec_max_wrapped_size(auth_generic_state->gensec_security);
-		ads->ldap.out.max_unwrapped = gensec_max_input_size(auth_generic_state->gensec_security);
+	if (wrap->wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
+		size_t max_wrapped =
+			gensec_max_wrapped_size(auth_generic_state->gensec_security);
+		wrap->out.max_unwrapped =
+			gensec_max_input_size(auth_generic_state->gensec_security);
 
-		ads->ldap.out.sig_size = max_wrapped - ads->ldap.out.max_unwrapped;
+		wrap->out.sig_size = max_wrapped - wrap->out.max_unwrapped;
 		/*
 		 * Note that we have to truncate this to 0x2C
 		 * (taken from a capture with LDAP unbind), as the
 		 * signature size is not constant for Kerberos with
 		 * arcfour-hmac-md5.
 		 */
-		ads->ldap.in.min_wrapped = MIN(ads->ldap.out.sig_size, 0x2C);
-		ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
-		status = ads_setup_sasl_wrapping(ads, &ads_sasl_gensec_ops, auth_generic_state->gensec_security);
+		wrap->in.min_wrapped = MIN(wrap->out.sig_size, 0x2C);
+		wrap->in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
+		status = ads_setup_sasl_wrapping(wrap->wrap_private_data, ads->ldap.ld,
+						 &ads_sasl_gensec_ops,
+						 auth_generic_state->gensec_security);
 		if (!ADS_ERR_OK(status)) {
 			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
 				ads_errstr(status)));
@@ -387,9 +393,9 @@ done:
 	return status;
 }
 
-static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len)
+static ADS_STATUS ads_sasl_gssapi_wrap(struct ads_saslwrap *wrap, uint8_t *buf, uint32_t len)
 {
-	gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
+	gss_ctx_id_t context_handle = (gss_ctx_id_t)wrap->wrap_private_data;
 	ADS_STATUS status;
 	int gss_rc;
 	uint32_t minor_status;
@@ -400,7 +406,7 @@ static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t l
 	unwrapped.length	= len;
 
 	/* for now request sign and seal */
-	conf_req_flag	= (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL);
+	conf_req_flag	= (wrap->wrap_type == ADS_SASLWRAP_TYPE_SEAL);
 
 	gss_rc = gss_wrap(&minor_status, context_handle,
 			  conf_req_flag, GSS_C_QOP_DEFAULT,
@@ -413,32 +419,32 @@ static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t l
 		return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
 	}
 
-	if ((ads->ldap.out.size - 4) < wrapped.length) {
+	if ((wrap->out.size - 4) < wrapped.length) {
 		return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
 	}
 
 	/* copy the wrapped blob to the right location */
-	memcpy(ads->ldap.out.buf + 4, wrapped.value, wrapped.length);
+	memcpy(wrap->out.buf + 4, wrapped.value, wrapped.length);
 
 	/* set how many bytes must be written to the underlying socket */
-	ads->ldap.out.left = 4 + wrapped.length;
+	wrap->out.left = 4 + wrapped.length;
 
 	gss_release_buffer(&minor_status, &wrapped);
 
 	return ADS_SUCCESS;
 }
 
-static ADS_STATUS ads_sasl_gssapi_unwrap(ADS_STRUCT *ads)
+static ADS_STATUS ads_sasl_gssapi_unwrap(struct ads_saslwrap *wrap)
 {
-	gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
+	gss_ctx_id_t context_handle = (gss_ctx_id_t)wrap->wrap_private_data;
 	ADS_STATUS status;
 	int gss_rc;
 	uint32_t minor_status;
 	gss_buffer_desc unwrapped, wrapped;
 	int conf_state;
 
-	wrapped.value	= ads->ldap.in.buf + 4;
-	wrapped.length	= ads->ldap.in.ofs - 4;
+	wrapped.value	= wrap->in.buf + 4;
+	wrapped.length	= wrap->in.ofs - 4;
 
 	gss_rc = gss_unwrap(&minor_status, context_handle,
 			    &wrapped, &unwrapped,
@@ -446,7 +452,7 @@ static ADS_STATUS ads_sasl_gssapi_unwrap(ADS_STRUCT *ads)
 	status = ADS_ERROR_GSS(gss_rc, minor_status);
 	if (!ADS_ERR_OK(status)) return status;
 
-	if (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL && conf_state == 0) {
+	if (wrap->wrap_type == ADS_SASLWRAP_TYPE_SEAL && conf_state == 0) {
 		return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
 	}
 
@@ -455,26 +461,26 @@ static ADS_STATUS ads_sasl_gssapi_unwrap(ADS_STRUCT *ads)
 	}
 
 	/* copy the wrapped blob to the right location */
-	memcpy(ads->ldap.in.buf + 4, unwrapped.value, unwrapped.length);
+	memcpy(wrap->in.buf + 4, unwrapped.value, unwrapped.length);
 
 	/* set how many bytes must be written to the underlying socket */
-	ads->ldap.in.left	= unwrapped.length;
-	ads->ldap.in.ofs	= 4;
+	wrap->in.left	= unwrapped.length;
+	wrap->in.ofs	= 4;
 
 	gss_release_buffer(&minor_status, &unwrapped);
 
 	return ADS_SUCCESS;
 }
 
-static void ads_sasl_gssapi_disconnect(ADS_STRUCT *ads)
+static void ads_sasl_gssapi_disconnect(struct ads_saslwrap *wrap)
 {
-	gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
+	gss_ctx_id_t context_handle = (gss_ctx_id_t)wrap->wrap_private_data;
 	uint32_t minor_status;
 
 	gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
 
-	ads->ldap.wrap_ops = NULL;
-	ads->ldap.wrap_private_data = NULL;
+	wrap->wrap_ops = NULL;
+	wrap->wrap_private_data = NULL;
 }
 
 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops = {
@@ -827,6 +833,7 @@ static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv
 	uint32_t max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
 	uint8_t wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
 	ADS_STATUS status;
+	struct ads_saslwrap *wrap = &ads->ldap_wrap_data;
 
 	input_token.value = NULL;
 	input_token.length = 0;
@@ -916,13 +923,13 @@ static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv
 
 	gss_release_buffer(&minor_status, &output_token);
 
-	if (!(wrap_type & ads->ldap.wrap_type)) {
+	if (!(wrap_type & wrap->wrap_type)) {
 		/*
 		 * the server doesn't supports the wrap
 		 * type we want :-(
 		 */
 		DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
-			ads->ldap.wrap_type, wrap_type));
+			wrap->wrap_type, wrap_type));
 		DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
 		status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
 		goto failed;
@@ -943,7 +950,7 @@ static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv
 	p = (uint8_t *)output_token.value;
 
 	RSIVAL(p,0,max_msg_size);
-	SCVAL(p,0,ads->ldap.wrap_type);
+	SCVAL(p,0,wrap->wrap_type);
 
 	/*
 	 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
@@ -980,20 +987,22 @@ static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv
 		goto failed;
 	}
 
-	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
+	if (wrap->wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
 		gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
-					     (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
+					     (wrap->wrap_type == ADS_SASLWRAP_TYPE_SEAL),
 					     GSS_C_QOP_DEFAULT,
-					     max_msg_size, &ads->ldap.out.max_unwrapped);
+					     max_msg_size, &wrap->out.max_unwrapped);
 		if (gss_rc) {
 			status = ADS_ERROR_GSS(gss_rc, minor_status);
 			goto failed;
 		}
 
-		ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
-		ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
-		ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
-		status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
+		wrap->out.sig_size = max_msg_size - wrap->out.max_unwrapped;
+		wrap->in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
+		wrap->in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
+		status = ads_setup_sasl_wrapping(wrap->wrap_private_data, ads->ldap.ld,
+						 &ads_sasl_gssapi_ops,
+						 context_handle);
 		if (!ADS_ERR_OK(status)) {
 			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
 				ads_errstr(status)));
@@ -1068,6 +1077,7 @@ ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
 	ADS_STATUS status;
 	int i, j;
 	LDAPMessage *res;
+	struct ads_saslwrap *wrap = &ads->ldap_wrap_data;
 
 	/* get a list of supported SASL mechanisms */
 	status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
@@ -1076,11 +1086,11 @@ ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
 	values = ldap_get_values(ads->ldap.ld, res, "supportedSASLMechanisms");
 
 	if (ads->auth.flags & ADS_AUTH_SASL_SEAL) {
-		ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
+		wrap->wrap_type = ADS_SASLWRAP_TYPE_SEAL;
 	} else if (ads->auth.flags & ADS_AUTH_SASL_SIGN) {
-		ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
+		wrap->wrap_type = ADS_SASLWRAP_TYPE_SIGN;
 	} else {
-		ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
+		wrap->wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
 	}
 
 	/* try our supported mechanisms in order */
@@ -1093,11 +1103,11 @@ retry:
 				status = sasl_mechanisms[i].fn(ads);
 				if (status.error_type == ENUM_ADS_ERROR_LDAP &&
 				    status.err.rc == LDAP_STRONG_AUTH_REQUIRED &&
-				    ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_PLAIN)
+				    wrap->wrap_type == ADS_SASLWRAP_TYPE_PLAIN)
 				{
 					DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
 						 "retrying with signing enabled\n"));
-					ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
+					wrap->wrap_type = ADS_SASLWRAP_TYPE_SIGN;
 					goto retry;
 				}
 				ldap_value_free(values);
diff --git a/source3/libads/sasl_wrapping.c b/source3/libads/sasl_wrapping.c
index c7a58ab..1dbd357 100644
--- a/source3/libads/sasl_wrapping.c
+++ b/source3/libads/sasl_wrapping.c
@@ -20,15 +20,47 @@
 #include "includes.h"
 #include "ads.h"
 
+void ndr_print_ads_saslwrap_struct(struct ndr_print *ndr, const char *name, const struct ads_saslwrap *r)
+{
+	ndr_print_struct(ndr, name, "saslwrap");
+	ndr->depth++;
+	ndr_print_uint16(ndr, "wrap_type", r->wrap_type);
+#ifdef HAVE_LDAP_SASL_WRAPPING
+	ndr_print_ptr(ndr, "sbiod", r->sbiod);
+#endif /* HAVE_LDAP_SASL_WRAPPING */
+	ndr_print_ptr(ndr, "mem_ctx", r->mem_ctx);
+	ndr_print_ptr(ndr, "wrap_ops", r->wrap_ops);
+	ndr_print_ptr(ndr, "wrap_private_data", r->wrap_private_data);
+	ndr_print_struct(ndr, name, "in");
+	ndr->depth++;
+	ndr_print_uint32(ndr, "ofs", r->in.ofs);
+	ndr_print_uint32(ndr, "needed", r->in.needed);
+	ndr_print_uint32(ndr, "left", r->in.left);
+	ndr_print_uint32(ndr, "max_wrapped", r->in.max_wrapped);
+	ndr_print_uint32(ndr, "min_wrapped", r->in.min_wrapped);
+	ndr_print_uint32(ndr, "size", r->in.size);
+	ndr_print_array_uint8(ndr, "buf", r->in.buf, r->in.size);
+	ndr->depth--;
+	ndr_print_struct(ndr, name, "out");
+	ndr->depth++;
+	ndr_print_uint32(ndr, "ofs", r->out.ofs);
+	ndr_print_uint32(ndr, "left", r->out.left);
+	ndr_print_uint32(ndr, "max_unwrapped", r->out.max_unwrapped);
+	ndr_print_uint32(ndr, "sig_size", r->out.sig_size);
+	ndr_print_uint32(ndr, "size", r->out.size);
+	ndr_print_array_uint8(ndr, "buf", r->out.buf, r->out.size);
+	ndr->depth--;
+}
+
 #ifdef HAVE_LDAP_SASL_WRAPPING
 
 static int ads_saslwrap_setup(Sockbuf_IO_Desc *sbiod, void *arg)
 {
-	ADS_STRUCT *ads = (ADS_STRUCT *)arg;
+	struct ads_saslwrap *wrap = (struct ads_saslwrap *)arg;
 
-	ads->ldap.sbiod	= sbiod;
+	wrap->sbiod	= sbiod;
 
-	sbiod->sbiod_pvt = ads;
+	sbiod->sbiod_pvt = wrap;
 
 	return 0;
 }
@@ -38,78 +70,80 @@ static int ads_saslwrap_remove(Sockbuf_IO_Desc *sbiod)
 	return 0;
 }
 
-static ber_slen_t ads_saslwrap_prepare_inbuf(ADS_STRUCT *ads)
+static ber_slen_t ads_saslwrap_prepare_inbuf(struct ads_saslwrap *wrap)
 {
-	ads->ldap.in.ofs	= 0;
-	ads->ldap.in.needed	= 0;
-	ads->ldap.in.left	= 0;
-	ads->ldap.in.size	= 4 + ads->ldap.in.min_wrapped;
-	ads->ldap.in.buf	= talloc_array(ads->ldap.mem_ctx,
-					       uint8_t, ads->ldap.in.size);
-	if (!ads->ldap.in.buf) {
+	wrap->in.ofs	= 0;
+	wrap->in.needed	= 0;
+	wrap->in.left	= 0;
+	wrap->in.size	= 4 + wrap->in.min_wrapped;
+	wrap->in.buf	= talloc_array(wrap->mem_ctx,
+				       uint8_t, wrap->in.size);
+	if (!wrap->in.buf) {
 		return -1;
 	}
 
 	return 0;
 }
 
-static ber_slen_t ads_saslwrap_grow_inbuf(ADS_STRUCT *ads)
+static ber_slen_t ads_saslwrap_grow_inbuf(struct ads_saslwrap *wrap)
 {
-	if (ads->ldap.in.size == (4 + ads->ldap.in.needed)) {
+	if (wrap->in.size == (4 + wrap->in.needed)) {
 		return 0;
 	}
 
-	ads->ldap.in.size	= 4 + ads->ldap.in.needed;
-	ads->ldap.in.buf	= talloc_realloc(ads->ldap.mem_ctx,
-						 ads->ldap.in.buf,
-						 uint8_t, ads->ldap.in.size);
-	if (!ads->ldap.in.buf) {
+	wrap->in.size	= 4 + wrap->in.needed;
+	wrap->in.buf	= talloc_realloc(wrap->mem_ctx,
+					 wrap->in.buf,
+					 uint8_t, wrap->in.size);
+	if (!wrap->in.buf) {
 		return -1;
 	}
 
 	return 0;
 }
 
-static void ads_saslwrap_shrink_inbuf(ADS_STRUCT *ads)
+static void ads_saslwrap_shrink_inbuf(struct ads_saslwrap *wrap)
 {
-	talloc_free(ads->ldap.in.buf);
+	talloc_free(wrap->in.buf);
 
-	ads->ldap.in.buf	= NULL;
-	ads->ldap.in.size	= 0;
-	ads->ldap.in.ofs	= 0;
-	ads->ldap.in.needed	= 0;
-	ads->ldap.in.left	= 0;
+	wrap->in.buf	= NULL;
+	wrap->in.size	= 0;
+	wrap->in.ofs	= 0;
+	wrap->in.needed	= 0;
+	wrap->in.left	= 0;
 }
 
-static ber_slen_t ads_saslwrap_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+static ber_slen_t ads_saslwrap_read(Sockbuf_IO_Desc *sbiod,
+				    void *buf, ber_len_t len)
 {
-	ADS_STRUCT *ads = (ADS_STRUCT *)sbiod->sbiod_pvt;
+	struct ads_saslwrap *wrap =
+			(struct ads_saslwrap *)sbiod->sbiod_pvt;
 	ber_slen_t ret;
 
 	/* If ofs < 4 it means we don't have read the length header yet */
-	if (ads->ldap.in.ofs < 4) {
-		ret = ads_saslwrap_prepare_inbuf(ads);
+	if (wrap->in.ofs < 4) {
+		ret = ads_saslwrap_prepare_inbuf(wrap);
 		if (ret < 0) return ret;
 
 		ret = LBER_SBIOD_READ_NEXT(sbiod,
-					   ads->ldap.in.buf + ads->ldap.in.ofs,
-					   4 - ads->ldap.in.ofs);
+					   wrap->in.buf + wrap->in.ofs,
+					   4 - wrap->in.ofs);
 		if (ret <= 0) return ret;
-		ads->ldap.in.ofs += ret;
+		wrap->in.ofs += ret;
 
-		if (ads->ldap.in.ofs < 4) goto eagain;
+		if (wrap->in.ofs < 4) goto eagain;
 
-		ads->ldap.in.needed = RIVAL(ads->ldap.in.buf, 0);
-		if (ads->ldap.in.needed > ads->ldap.in.max_wrapped) {
+		wrap->in.needed = RIVAL(wrap->in.buf, 0);
+		if (wrap->in.needed > wrap->in.max_wrapped) {
 			errno = EINVAL;
 			return -1;
 		}
-		if (ads->ldap.in.needed < ads->ldap.in.min_wrapped) {
+		if (wrap->in.needed < wrap->in.min_wrapped) {
 			errno = EINVAL;
 			return -1;
 		}
 
-		ret = ads_saslwrap_grow_inbuf(ads);
+		ret = ads_saslwrap_grow_inbuf(wrap);
 		if (ret < 0) return ret;
 	}
 
@@ -117,24 +151,24 @@ static ber_slen_t ads_saslwrap_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t
 	 * if there's more data needed from the remote end,
 	 * we need to read more
 	 */
-	if (ads->ldap.in.needed > 0) {
+	if (wrap->in.needed > 0) {
 		ret = LBER_SBIOD_READ_NEXT(sbiod,
-					   ads->ldap.in.buf + ads->ldap.in.ofs,
-					   ads->ldap.in.needed);
+					   wrap->in.buf + wrap->in.ofs,
+					   wrap->in.needed);
 		if (ret <= 0) return ret;
-		ads->ldap.in.ofs += ret;
-		ads->ldap.in.needed -= ret;
+		wrap->in.ofs += ret;
+		wrap->in.needed -= ret;
 
-		if (ads->ldap.in.needed > 0) goto eagain;
+		if (wrap->in.needed > 0) goto eagain;
 	}
 
 	/*
 	 * if we have a complete packet and have not yet unwrapped it
 	 * we need to call the mech specific unwrap() hook
 	 */
-	if (ads->ldap.in.needed == 0 && ads->ldap.in.left == 0) {
+	if (wrap->in.needed == 0 && wrap->in.left == 0) {
 		ADS_STATUS status;
-		status = ads->ldap.wrap_ops->unwrap(ads);
+		status = wrap->wrap_ops->unwrap(wrap);
 		if (!ADS_ERR_OK(status)) {
 			errno = EACCES;
 			return -1;
@@ -144,19 +178,19 @@ static ber_slen_t ads_saslwrap_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t
 	/*
 	 * if we have unwrapped data give it to the caller
 	 */
-	if (ads->ldap.in.left > 0) {
-		ret = MIN(ads->ldap.in.left, len);
-		memcpy(buf, ads->ldap.in.buf + ads->ldap.in.ofs, ret);
-		ads->ldap.in.ofs += ret;
-		ads->ldap.in.left -= ret;
+	if (wrap->in.left > 0) {
+		ret = MIN(wrap->in.left, len);
+		memcpy(buf, wrap->in.buf + wrap->in.ofs, ret);
+		wrap->in.ofs += ret;
+		wrap->in.left -= ret;
 
 		/*
 		 * if no more is left shrink the inbuf,
 		 * this will trigger reading a new SASL packet
 		 * from the remote stream in the next call
 		 */
-		if (ads->ldap.in.left == 0) {
-			ads_saslwrap_shrink_inbuf(ads);
+		if (wrap->in.left == 0) {
+			ads_saslwrap_shrink_inbuf(wrap);
 		}
 
 		return ret;
@@ -171,37 +205,40 @@ eagain:
 	return -1;
 }
 
-static ber_slen_t ads_saslwrap_prepare_outbuf(ADS_STRUCT *ads, uint32_t len)
+static ber_slen_t ads_saslwrap_prepare_outbuf(struct ads_saslwrap *wrap,
+					      uint32_t len)
 {
-	ads->ldap.out.ofs	= 0;
-	ads->ldap.out.left	= 0;
-	ads->ldap.out.size	= 4 + ads->ldap.out.sig_size + len;
-	ads->ldap.out.buf	= talloc_array(ads->ldap.mem_ctx,
-					       uint8_t, ads->ldap.out.size);
-	if (!ads->ldap.out.buf) {
+	wrap->out.ofs	= 0;
+	wrap->out.left	= 0;
+	wrap->out.size	= 4 + wrap->out.sig_size + len;
+	wrap->out.buf	= talloc_array(wrap->mem_ctx,
+					       uint8_t, wrap->out.size);
+	if (!wrap->out.buf) {
 		return -1;
 	}
 
 	return 0;
 }
 
-static void ads_saslwrap_shrink_outbuf(ADS_STRUCT *ads)
+static void ads_saslwrap_shrink_outbuf(struct ads_saslwrap *wrap)
 {
-	talloc_free(ads->ldap.out.buf);
+	talloc_free(wrap->out.buf);
 
-	ads->ldap.out.buf	= NULL;
-	ads->ldap.out.size	= 0;
-	ads->ldap.out.ofs	= 0;
-	ads->ldap.out.left	= 0;
+	wrap->out.buf	= NULL;
+	wrap->out.size	= 0;
+	wrap->out.ofs	= 0;
+	wrap->out.left	= 0;
 }
 
-static ber_slen_t ads_saslwrap_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+static ber_slen_t ads_saslwrap_write(Sockbuf_IO_Desc *sbiod,
+				     void *buf, ber_len_t len)
 {
-	ADS_STRUCT *ads = (ADS_STRUCT *)sbiod->sbiod_pvt;
+	struct ads_saslwrap *wrap =
+			(struct ads_saslwrap *)sbiod->sbiod_pvt;
 	ber_slen_t ret, rlen;
 
 	/* if the buffer is empty, we need to wrap in incoming buffer */
-	if (ads->ldap.out.left == 0) {
+	if (wrap->out.left == 0) {
 		ADS_STATUS status;
 
 		if (len == 0) {
@@ -209,31 +246,31 @@ static ber_slen_t ads_saslwrap_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_
 			return -1;
 		}
 
-		rlen = MIN(len, ads->ldap.out.max_unwrapped);
+		rlen = MIN(len, wrap->out.max_unwrapped);
 
-		ret = ads_saslwrap_prepare_outbuf(ads, rlen);
+		ret = ads_saslwrap_prepare_outbuf(wrap, rlen);
 		if (ret < 0) return ret;
 		
-		status = ads->ldap.wrap_ops->wrap(ads, (uint8_t *)buf, rlen);
+		status = wrap->wrap_ops->wrap(wrap, (uint8_t *)buf, rlen);
 		if (!ADS_ERR_OK(status)) {
 			errno = EACCES;
 			return -1;
 		}
 
-		RSIVAL(ads->ldap.out.buf, 0, ads->ldap.out.left - 4);
+		RSIVAL(wrap->out.buf, 0, wrap->out.left - 4);
 	} else {
 		rlen = -1;
 	}
 
 	ret = LBER_SBIOD_WRITE_NEXT(sbiod,
-				    ads->ldap.out.buf + ads->ldap.out.ofs,
-				    ads->ldap.out.left);
+				    wrap->out.buf + wrap->out.ofs,
+				    wrap->out.left);
 	if (ret <= 0) return ret;
-	ads->ldap.out.ofs += ret;
-	ads->ldap.out.left -= ret;
+	wrap->out.ofs += ret;
+	wrap->out.left -= ret;
 
-	if (ads->ldap.out.left == 0) {
-		ads_saslwrap_shrink_outbuf(ads);
+	if (wrap->out.left == 0) {
+		ads_saslwrap_shrink_outbuf(wrap);
 	}
 
 	if (rlen > 0) return rlen;
@@ -244,12 +281,13 @@ static ber_slen_t ads_saslwrap_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_
 
 static int ads_saslwrap_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
 {
-	ADS_STRUCT *ads = (ADS_STRUCT *)sbiod->sbiod_pvt;
+	struct ads_saslwrap *wrap =
+			(struct ads_saslwrap *)sbiod->sbiod_pvt;
 	int ret;
 
 	switch (opt) {
 	case LBER_SB_OPT_DATA_READY:
-		if (ads->ldap.in.left > 0) {
+		if (wrap->in.left > 0) {
 			return 1;
 		}
 		ret = LBER_SBIOD_CTRL_NEXT(sbiod, opt, arg);
@@ -276,7 +314,7 @@ static const Sockbuf_IO ads_saslwrap_sockbuf_io = {
 	ads_saslwrap_close	/* sbi_close */
 };
 
-ADS_STATUS ads_setup_sasl_wrapping(ADS_STRUCT *ads,
+ADS_STATUS ads_setup_sasl_wrapping(struct ads_saslwrap *wrap, LDAP *ld,
 				   const struct ads_saslwrap_ops *ops,
 				   void *private_data)
 {
@@ -285,26 +323,26 @@ ADS_STATUS ads_setup_sasl_wrapping(ADS_STRUCT *ads,
 	Sockbuf_IO *io = discard_const_p(Sockbuf_IO, &ads_saslwrap_sockbuf_io);
 	int rc;
 
-	rc = ldap_get_option(ads->ldap.ld, LDAP_OPT_SOCKBUF, &sb);
+	rc = ldap_get_option(ld, LDAP_OPT_SOCKBUF, &sb);
 	status = ADS_ERROR_LDAP(rc);
 	if (!ADS_ERR_OK(status)) {
 		return status;
 	}
 
 	/* setup the real wrapping callbacks */
-	rc = ber_sockbuf_add_io(sb, io, LBER_SBIOD_LEVEL_TRANSPORT, ads);
+	rc = ber_sockbuf_add_io(sb, io, LBER_SBIOD_LEVEL_TRANSPORT, wrap);
 	status = ADS_ERROR_LDAP(rc);
 	if (!ADS_ERR_OK(status)) {
 		return status;
 	}
 
-	ads->ldap.wrap_ops		= ops;
-	ads->ldap.wrap_private_data	= private_data;
+	wrap->wrap_ops		= ops;
+	wrap->wrap_private_data	= private_data;
 
 	return ADS_SUCCESS;
 }
 #else
-ADS_STATUS ads_setup_sasl_wrapping(ADS_STRUCT *ads,
+ADS_STATUS ads_setup_sasl_wrapping(struct ads_saslwrap *wrap, LDAP *ld,
 				   const struct ads_saslwrap_ops *ops,
 				   void *private_data)
 {
-- 
2.9.3



More information about the samba-technical mailing list