libads: abstract out SASL wrapping code
authorAlexander Bokovoy <ab@samba.org>
Fri, 5 May 2017 12:37:20 +0000 (15:37 +0300)
committerJeremy Allison <jra@samba.org>
Wed, 17 May 2017 21:02:09 +0000 (23:02 +0200)
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@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/include/ads.h
source3/libads/ads_proto.h
source3/libads/ldap.c
source3/libads/ndr.c
source3/libads/sasl.c
source3/libads/sasl_wrapping.c

index cacb25ca325dae4fba92d54f84dd9a7de19bd84b..2b25c1c6c291554b6fa3965d478301f241ef0b46 100644 (file)
@@ -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;
index 425c352476c7e8d99d7287da3fef89b7208f978a..b6d9d9b31fc1e78c7be66954f48f576017ac03d2 100644 (file)
@@ -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  */
 
index c70cdeb5163a129b5cddb9f756472b2514fca1e6..fdb729e90daf7ec740b3a9ae52588966f49b2aba 100644 (file)
@@ -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);
 }
 
 /*
index 6cecbb08ccd6799845b28fe0982baa44278fd0ac..1b586c342821e20c65f6d23bfe9f41e84113eae6 100644 (file)
@@ -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 */
index ab79f70f77316f396cad9f93b796fba29ed9318a..7f7b790810ce4dc76ab8bf5d8dcc48e53fdfcc7d 100644 (file)
 
 #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);
index c7a58ab6147a3323541d8840101a2671ab20459a..1dbd357a8de5a05e36d92fa595ff5d740c5a655f 100644 (file)
 #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)
 {