[PATCH] libads: abstract out SASL wrapping code
Jeremy Allison
jra at samba.org
Wed May 17 18:11:32 UTC 2017
On Mon, May 15, 2017 at 05:28:28PM +0300, Alexander Bokovoy wrote:
> Attached patch passes samba.tests.pam_winbind test.
LGTM. Let's try again :-).
> / Alexander Bokovoy
> From b61efb5c9339f76702fd53effc2134ef3056a62c 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..7f7b790 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, 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