]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9189 rework sasl-cbinding support
authorIsaac Boukris <iboukris@gmail.com>
Tue, 14 Apr 2020 13:10:48 +0000 (16:10 +0300)
committerIsaac Boukris <iboukris@gmail.com>
Thu, 23 Apr 2020 19:00:39 +0000 (21:00 +0200)
Add LDAP_OPT_X_SASL_CBINDING option to define the binding type to use,
defaults to "none".

Add "tls-endpoint" binding type implementing "tls-server-end-point" from
RCF 5929, which is compatible with Windows.

Fix "tls-unique" to include the prefix in the bindings as per RFC 5056.

18 files changed:
doc/man/man3/ldap_get_option.3
doc/man/man5/ldap.conf.5
doc/man/man5/slapd-config.5
doc/man/man5/slapd.conf.5
include/ldap.h
include/ldap_pvt.h
libraries/libldap/cyrus.c
libraries/libldap/init.c
libraries/libldap/ldap-int.h
libraries/libldap/ldap-tls.h
libraries/libldap/tls2.c
libraries/libldap/tls_g.c
libraries/libldap/tls_o.c
servers/slapd/bconfig.c
servers/slapd/config.c
servers/slapd/connection.c
servers/slapd/proto-slap.h
servers/slapd/sasl.c

index 4f03a01a30d8e9fd28c06fbec40051af6a2e70ba..fd1b3c91c2b9d7a18bc0cb6a74af7866c64cda86 100644 (file)
@@ -563,6 +563,22 @@ must be a
 .BR "char **" .
 Its content needs to be freed by the caller using
 .BR ldap_memfree (3).
+.B LDAP_OPT_X_SASL_CBINDING
+Sets/gets the channel-binding type to use in SASL,
+one of
+.BR LDAP_OPT_X_SASL_CBINDING_NONE
+(the default),
+.BR LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE
+the "tls-unique" type from RCF 5929.
+.BR LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT
+the "tls-server-end-point" from RCF 5929, compatible with Windows.
+.BR invalue
+must be
+.BR "const int *" ;
+.BR outvalue
+must be
+.BR "int *" .
+.TP
 .SH TCP OPTIONS
 The TCP options are OpenLDAP specific.
 Mainly intended for use with Linux, they may not be portable.
index 65ad40c1be6becbe01c441a74b3dae3c8ae96fdc..4974f83400479fc46634863771fa3a14d666b3f3 100644 (file)
@@ -286,6 +286,9 @@ size allowed.  0 disables security layers.  The default is 65536.
 .TP
 .B SASL_NOCANON <on/true/yes/off/false/no>
 Do not perform reverse DNS lookups to canonicalize SASL host names. The default is off.
+.TP
+.B SASL_CBINDING <none/tls-unique/tls-endpoint>
+The channel-binding type to use, see also LDAP_OPT_X_SASL_CBINDING. The default is none.
 .SH GSSAPI OPTIONS
 If OpenLDAP is built with Generic Security Services Application Programming Interface support,
 there are more options you can specify.
index 18518a1863dc8a8b4e060e1b0a3377b99fdc6e0b..dc0ab769f3217c818f03b5368894f20902932318 100644 (file)
@@ -720,6 +720,10 @@ Used to specify the fully qualified domain name used for SASL processing.
 .B olcSaslRealm: <realm>
 Specify SASL realm.  Default is empty.
 .TP
+.B olcSaslCbinding: none | tls-unique | tls-endpoint
+Specify the channel-binding type, see also LDAP_OPT_X_SASL_CBINDING.
+Default is none.
+.TP
 .B olcSaslSecProps: <properties>
 Used to specify Cyrus SASL security properties.
 The
index f2094b7fddea5d1fe39297708404b544e415e091..73a151a70180d0fd8f43f0614a5a57ada126f3c5 100644 (file)
@@ -914,6 +914,9 @@ The
 property specifies the maximum security layer receive buffer
 size allowed.  0 disables security layers.  The default is 65536.
 .TP
+.B sasl\-cbinding none | tls-unique | tls-endpoint
+Specify the channel-binding type, see also LDAP_OPT_X_SASL_CBINDING.
+.TP
 .B schemadn <dn>
 Specify the distinguished name for the subschema subentry that
 controls the entries on this server.  The default is "cn=Subschema".
index 7b4fc9d64860a096fd034f2fb37ea3889ba5373d..9d5679ae84074ecb119040de229b408ebd00a3b8 100644 (file)
@@ -186,6 +186,10 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_1         ((3 << 8) + 2)
 #define LDAP_OPT_X_TLS_PROTOCOL_TLS1_2         ((3 << 8) + 3)
 
+#define LDAP_OPT_X_SASL_CBINDING_NONE          0
+#define LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE    1
+#define LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT  2
+
 /* OpenLDAP SASL options */
 #define LDAP_OPT_X_SASL_MECH                   0x6100
 #define LDAP_OPT_X_SASL_REALM                  0x6101
@@ -201,6 +205,7 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_X_SASL_NOCANON                        0x610b
 #define LDAP_OPT_X_SASL_USERNAME               0x610c /* read-only */
 #define LDAP_OPT_X_SASL_GSS_CREDS              0x610d
+#define LDAP_OPT_X_SASL_CBINDING               0x610e
 
 /*
  * OpenLDAP per connection tcp-keepalive settings
index 783d280a5e5cfe18b3340e37b4de2c7e29226857..01220d00afce1d5ed0250559568c526cb8e5b368 100644 (file)
@@ -262,6 +262,10 @@ LDAP_F (void *) ldap_pvt_sasl_mutex_new LDAP_P((void));
 LDAP_F (int) ldap_pvt_sasl_mutex_lock LDAP_P((void *mutex));
 LDAP_F (int) ldap_pvt_sasl_mutex_unlock LDAP_P((void *mutex));
 LDAP_F (void) ldap_pvt_sasl_mutex_dispose LDAP_P((void *mutex));
+
+LDAP_F (int) ldap_pvt_sasl_cbinding_parse LDAP_P(( const char *arg ));
+LDAP_F (void *) ldap_pvt_sasl_cbinding LDAP_P(( void *ssl, int type,
+                                               int is_server ));
 #endif /* HAVE_CYRUS_SASL */
 
 struct sockbuf; /* avoid pulling in <lber.h> */
@@ -438,6 +442,7 @@ LDAP_F (int) ldap_pvt_tls_get_peer_dn LDAP_P(( void *ctx, struct berval *dn,
        LDAPDN_rewrite_dummy *func, unsigned flags ));
 LDAP_F (int) ldap_pvt_tls_get_strength LDAP_P(( void *ctx ));
 LDAP_F (int) ldap_pvt_tls_get_unique LDAP_P(( void *ctx, struct berval *buf, int is_server ));
+LDAP_F (int) ldap_pvt_tls_get_endpoint LDAP_P(( void *ctx, struct berval *buf, int is_server ));
 LDAP_F (const char *) ldap_pvt_tls_get_version LDAP_P(( void *ctx ));
 LDAP_F (const char *) ldap_pvt_tls_get_cipher LDAP_P(( void *ctx ));
 
index beb1cf4a040852d0039e33f52cc73994e921bd8e..4d4d5b3e3e2393795edfe5aaf1b4d41275d13348 100644 (file)
@@ -368,6 +368,65 @@ int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc )
        return LDAP_SUCCESS;
 }
 
+int ldap_pvt_sasl_cbinding_parse( const char *arg )
+{
+       int i = -1;
+
+       if ( strcasecmp(arg, "none") == 0 )
+               i = LDAP_OPT_X_SASL_CBINDING_NONE;
+       else if ( strcasecmp(arg, "tls-unique") == 0 )
+               i = LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE;
+       else if ( strcasecmp(arg, "tls-endpoint") == 0 )
+               i = LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT;
+
+       return i;
+}
+
+void *ldap_pvt_sasl_cbinding( void *ssl, int type, int is_server )
+{
+#if defined(SASL_CHANNEL_BINDING) && defined(HAVE_TLS)
+       char unique_prefix[] = "tls-unique:";
+       char endpoint_prefix[] = "tls-server-end-point:";
+       char cbinding[ 64 ];
+       struct berval cbv = { 64, cbinding };
+       void *cb_data; /* used since cb->data is const* */
+       sasl_channel_binding_t *cb;
+       char *prefix;
+       int plen;
+
+       switch (type) {
+       case LDAP_OPT_X_SASL_CBINDING_NONE:
+               return NULL;
+       case LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE:
+               if ( !ldap_pvt_tls_get_unique( ssl, &cbv, is_server ))
+                       return NULL;
+               prefix = unique_prefix;
+               plen = sizeof(unique_prefix) -1;
+               break;
+       case LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT:
+               if ( !ldap_pvt_tls_get_endpoint( ssl, &cbv, is_server ))
+                       return NULL;
+               prefix = endpoint_prefix;
+               plen = sizeof(endpoint_prefix) -1;
+               break;
+       default:
+               return NULL;
+       }
+
+       cb = ldap_memalloc( sizeof(*cb) + plen + cbv.bv_len );
+       cb->len = plen + cbv.bv_len;
+       cb->data = cb_data = cb+1;
+       memcpy( cb_data, prefix, plen );
+       memcpy( cb_data + plen, cbv.bv_val, cbv.bv_len );
+       cb->name = "ldap";
+       cb->critical = 0;
+
+       return cb;
+#else
+       return NULL;
+#endif
+}
+
 int
 ldap_int_sasl_bind(
        LDAP                    *ld,
@@ -497,19 +556,12 @@ ldap_int_sasl_bind(
                        (void) ldap_int_sasl_external( ld, ld->ld_defconn, authid.bv_val, fac );
                        LDAP_FREE( authid.bv_val );
 #ifdef SASL_CHANNEL_BINDING    /* 2.1.25+ */
-                       {
-                               char cbinding[64];
-                               struct berval cbv = { sizeof(cbinding), cbinding };
-                               if ( ld->ld_defconn->lconn_sasl_cbind == NULL &&
-                                       ldap_pvt_tls_get_unique( ssl, &cbv, 0 )) {
-                                       sasl_channel_binding_t *cb = ldap_memalloc( sizeof(*cb) +
-                                               cbv.bv_len);
-                                       void *cb_data; /* used since cb->data is const* */
-                                       cb->name = "ldap";
-                                       cb->critical = 0;
-                                       cb->len = cbv.bv_len;
-                                       cb->data = cb_data = cb+1;
-                                       memcpy( cb_data, cbv.bv_val, cbv.bv_len );
+                       if ( ld->ld_defconn->lconn_sasl_cbind == NULL ) {
+                               void *cb;
+                               cb = ldap_pvt_sasl_cbinding( ssl,
+                                                            ld->ld_options.ldo_sasl_cbinding,
+                                                            0 );
+                               if ( cb != NULL ) {
                                        sasl_setprop( ld->ld_defconn->lconn_sasl_authctx,
                                                SASL_CHANNEL_BINDING, cb );
                                        ld->ld_defconn->lconn_sasl_cbind = cb;
@@ -931,12 +983,20 @@ int ldap_pvt_sasl_secprops(
 int
 ldap_int_sasl_config( struct ldapoptions *lo, int option, const char *arg )
 {
-       int rc;
+       int rc, i;
 
        switch( option ) {
        case LDAP_OPT_X_SASL_SECPROPS:
                rc = ldap_pvt_sasl_secprops( arg, &lo->ldo_sasl_secprops );
                if( rc == LDAP_SUCCESS ) return 0;
+               break;
+       case LDAP_OPT_X_SASL_CBINDING:
+               i = ldap_pvt_sasl_cbinding_parse( arg );
+               if ( i >= 0 ) {
+                       lo->ldo_sasl_cbinding = i;
+                       return 0;
+               }
+               break;
        }
 
        return -1;
@@ -1042,6 +1102,10 @@ ldap_int_sasl_get_option( LDAP *ld, int option, void *arg )
                        /* this option is write only */
                        return -1;
 
+               case LDAP_OPT_X_SASL_CBINDING:
+                       *(int *)arg = ld->ld_options.ldo_sasl_cbinding;
+                       break;
+
 #ifdef SASL_GSS_CREDS
                case LDAP_OPT_X_SASL_GSS_CREDS: {
                        sasl_conn_t *ctx;
@@ -1143,6 +1207,17 @@ ldap_int_sasl_set_option( LDAP *ld, int option, void *arg )
                return sc == LDAP_SUCCESS ? 0 : -1;
                }
 
+       case LDAP_OPT_X_SASL_CBINDING:
+               if ( !arg ) return -1;
+               switch( *(int *) arg ) {
+               case LDAP_OPT_X_SASL_CBINDING_NONE:
+               case LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE:
+               case LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT:
+                       ld->ld_options.ldo_sasl_cbinding = *(int *) arg;
+                       return 0;
+               }
+               return -1;
+
 #ifdef SASL_GSS_CREDS
        case LDAP_OPT_X_SASL_GSS_CREDS: {
                sasl_conn_t *ctx;
index 3468ee249cdf38c6e52fa15fccd4e6f0ecdbe594..dfe1ea9da4906f00fda9c54a812144213a846e32 100644 (file)
@@ -110,6 +110,7 @@ static const struct ol_attribute {
                offsetof(struct ldapoptions, ldo_def_sasl_authzid)},
        {0, ATTR_SASL,          "SASL_SECPROPS",        NULL,   LDAP_OPT_X_SASL_SECPROPS},
        {0, ATTR_BOOL,          "SASL_NOCANON", NULL,   LDAP_BOOL_SASL_NOCANON},
+       {0, ATTR_SASL,          "SASL_CBINDING",        NULL,   LDAP_OPT_X_SASL_CBINDING},
 #endif
 
 #ifdef HAVE_TLS
index 67e8bd6da3e1de6f3c6be72ba6e6a2b575228cf3..c6c6891a9e307ca2a64e52352776757221eb7cfe 100644 (file)
@@ -300,6 +300,7 @@ struct ldapoptions {
 
        /* SASL Security Properties */
        struct sasl_security_properties ldo_sasl_secprops;
+       int ldo_sasl_cbinding;
 #define LDAP_LDO_SASL_NULLARG ,0,0,0,0,{0}
 #else
 #define LDAP_LDO_SASL_NULLARG
index efd51aaa2bd8c4cff15921c05067af864be30808..9f01ddda12d3d8181e3ad73b6510c82582ffc4c0 100644 (file)
@@ -42,6 +42,7 @@ typedef int (TI_session_dn)(tls_session *sess, struct berval *dn);
 typedef int (TI_session_chkhost)(LDAP *ld, tls_session *s, const char *name_in);
 typedef int (TI_session_strength)(tls_session *sess);
 typedef int (TI_session_unique)(tls_session *sess, struct berval *buf, int is_server);
+typedef int (TI_session_endpoint)(tls_session *sess, struct berval *buf, int is_server);
 typedef const char *(TI_session_name)(tls_session *s);
 typedef int (TI_session_peercert)(tls_session *s, struct berval *der);
 typedef int (TI_session_pinning)(LDAP *ld, tls_session *s, char *hashalg, struct berval *hash);
@@ -69,6 +70,7 @@ typedef struct tls_impl {
        TI_session_chkhost *ti_session_chkhost;
        TI_session_strength *ti_session_strength;
        TI_session_unique *ti_session_unique;
+       TI_session_endpoint *ti_session_endpoint;
        TI_session_name *ti_session_version;
        TI_session_name *ti_session_cipher;
        TI_session_peercert *ti_session_peercert;
index 79a651a38074cfaafbda5a06887b3fbfcae0ca59..72827a1a3bd62385eeb9a5c82d410b0a95f78428 100644 (file)
@@ -1200,6 +1200,13 @@ ldap_pvt_tls_get_unique( void *s, struct berval *buf, int is_server )
        return tls_imp->ti_session_unique( session, buf, is_server );
 }
 
+int
+ldap_pvt_tls_get_endpoint( void *s, struct berval *buf, int is_server )
+{
+       tls_session *session = s;
+       return tls_imp->ti_session_endpoint( session, buf, is_server );
+}
+
 const char *
 ldap_pvt_tls_get_version( void *s )
 {
index 956a9ec908d01eec35bd5a4f1edfa172d287b65c..ef0f44e208c279b08422352051faa322923b6432 100644 (file)
@@ -729,6 +729,64 @@ tlsg_session_unique( tls_session *sess, struct berval *buf, int is_server)
        return 0;
 }
 
+static int
+tlsg_session_endpoint( tls_session *sess, struct berval *buf, int is_server )
+{
+       tlsg_session *s = (tlsg_session *)sess;
+       const gnutls_datum_t *cert_data;
+       gnutls_x509_crt_t server_cert;
+       gnutls_digest_algorithm_t md;
+       int sign_algo, md_len, rc;
+
+       if ( is_server )
+               cert_data = gnutls_certificate_get_ours( s->session );
+       else
+               cert_data = gnutls_certificate_get_peers( s->session, NULL );
+
+       if ( cert_data == NULL )
+               return 0;
+
+       rc = gnutls_x509_crt_init( &server_cert );
+       if ( rc != GNUTLS_E_SUCCESS )
+               return 0;
+
+       rc = gnutls_x509_crt_import( server_cert, cert_data, GNUTLS_X509_FMT_DER );
+       if ( rc != GNUTLS_E_SUCCESS ) {
+               gnutls_x509_crt_deinit( server_cert );
+               return 0;
+       }
+
+       sign_algo = gnutls_x509_crt_get_signature_algorithm( server_cert );
+       gnutls_x509_crt_deinit( server_cert );
+       if ( sign_algo <= GNUTLS_SIGN_UNKNOWN )
+               return 0;
+
+       md = gnutls_sign_get_hash_algorithm( sign_algo );
+       if ( md == GNUTLS_DIG_UNKNOWN )
+               return 0;
+
+       /* See RFC 5929 */
+       switch (md) {
+       case GNUTLS_DIG_NULL:
+       case GNUTLS_DIG_MD2:
+       case GNUTLS_DIG_MD5:
+       case GNUTLS_DIG_SHA1:
+               md = GNUTLS_DIG_SHA256;
+       }
+
+       md_len = gnutls_hash_get_len( md );
+       if ( md_len == 0 || md_len > buf->bv_len )
+               return 0;
+
+       rc = gnutls_hash_fast( md, cert_data->data, cert_data->size, buf->bv_val );
+       if ( rc != GNUTLS_E_SUCCESS )
+               return 0;
+
+       buf->bv_len = md_len;
+
+       return md_len;
+}
+
 static const char *
 tlsg_session_version( tls_session *sess )
 {
@@ -1117,6 +1175,7 @@ tls_impl ldap_int_tls_impl = {
        tlsg_session_chkhost,
        tlsg_session_strength,
        tlsg_session_unique,
+       tlsg_session_endpoint,
        tlsg_session_version,
        tlsg_session_cipher,
        tlsg_session_peercert,
index cf97d763254484490bfa398805d65acc15124a67..aa855d77a1c57c5795825b5b1be19666088b491b 100644 (file)
@@ -858,6 +858,50 @@ tlso_session_unique( tls_session *sess, struct berval *buf, int is_server)
        return buf->bv_len;
 }
 
+static int
+tlso_session_endpoint( tls_session *sess, struct berval *buf, int is_server )
+{
+       tlso_session *s = (tlso_session *)sess;
+       const EVP_MD *md;
+       unsigned int md_len;
+       X509 *cert;
+
+       if ( buf->bv_len < EVP_MAX_MD_SIZE )
+               return 0;
+
+       if ( is_server )
+               cert = SSL_get_certificate( s );
+       else
+               cert = SSL_get_peer_certificate( s );
+
+       if ( cert == NULL )
+               return 0;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000
+       md = EVP_get_digestbynid( X509_get_signature_nid( cert ));
+#else
+       md = EVP_get_digestbynid(OBJ_obj2nid( cert->sig_alg->algorithm ));
+#endif
+
+       /* See RFC 5929 */
+       if ( md == NULL ||
+            md == EVP_md_null() ||
+#ifndef OPENSSL_NO_MD2
+            md == EVP_md2() ||
+#endif
+            md == EVP_md4() ||
+            md == EVP_md5() ||
+            md == EVP_sha1() )
+               md = EVP_sha256();
+
+       if ( !X509_digest( cert, md, buf->bv_val, &md_len ))
+               return 0;
+
+       buf->bv_len = md_len;
+
+       return md_len;
+}
+
 static const char *
 tlso_session_version( tls_session *sess )
 {
@@ -1474,6 +1518,7 @@ tls_impl ldap_int_tls_impl = {
        tlso_session_chkhost,
        tlso_session_strength,
        tlso_session_unique,
+       tlso_session_endpoint,
        tlso_session_version,
        tlso_session_cipher,
        tlso_session_peercert,
index 6069ee20340ac4f8153a516086a5aa0d5dc17614..4c90715be58c88b414387b1bfd163cad6485915a 100644 (file)
@@ -630,6 +630,15 @@ static ConfigTable config_back_cf_table[] = {
                "( OLcfgGlAt:92 NAME 'olcSaslAuxpropsDontUseCopyIgnore' "
                        "EQUALITY booleanMatch "
                        "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+       { "sasl-cbinding", NULL, 2, 2, 0,
+#ifdef HAVE_CYRUS_SASL
+               ARG_STRING, &sasl_cbinding,
+#else
+               ARG_IGNORED, NULL,
+#endif
+               "( OLcfgGlAt:100 NAME 'olcSaslCBinding' "
+                       "EQUALITY caseIgnoreMatch "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "sasl-host", "host", 2, 2, 0,
 #ifdef HAVE_CYRUS_SASL
                ARG_STRING|ARG_UNIQUE, &sasl_host,
@@ -948,7 +957,7 @@ static ConfigOCs cf_ocs[] = {
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
                 "olcRootDSE $ "
                 "olcSaslAuxprops $ olcSaslAuxpropsDontUseCopy $ olcSaslAuxpropsDontUseCopyIgnore $ "
-                "olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
+                "olcSaslCBinding $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
                 "olcSecurity $ olcServerID $ olcSizeLimit $ "
                 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ "
                 "olcTCPBuffer $ "
index 060d3410f1335e824243ffdc60f23dde88e287b7..3d713d4fb39f788d73450776269939df94800040 100644 (file)
@@ -73,6 +73,7 @@ char  *global_host = NULL;
 struct berval global_host_bv = BER_BVNULL;
 char   *global_realm = NULL;
 char   *sasl_host = NULL;
+char   *sasl_cbinding = NULL;
 char           **default_passwd_hash = NULL;
 struct berval default_search_base = BER_BVNULL;
 struct berval default_search_nbase = BER_BVNULL;
index 5f11a0cf1a67d4f5f47440453efb1f8ba62b98d5..6d9bb8e8538bd87353c3b63fff8c65bf5298f500 100644 (file)
@@ -1440,12 +1440,9 @@ connection_read( ber_socket_t s, conn_readinfo *cri )
                                msgbuf, ldap_pvt_tls_get_version( ssl ), ldap_pvt_tls_get_cipher( ssl ));
                        slap_sasl_external( c, c->c_tls_ssf, &authid );
                        if ( authid.bv_val ) free( authid.bv_val );
-                       {
-                               char cbinding[64];
-                               struct berval cbv = { sizeof(cbinding), cbinding };
-                               if ( ldap_pvt_tls_get_unique( ssl, &cbv, 1 ))
-                                       slap_sasl_cbinding( c, &cbv );
-                       }
+
+                       slap_sasl_cbinding( c, ssl );
+
                } else if ( rc == 1 && ber_sockbuf_ctrl( c->c_sb,
                        LBER_SB_OPT_NEEDS_WRITE, NULL )) {      /* need to retry */
                        slapd_set_write( s, 1 );
index b89fa836a12b2ec03d002aeed5944cd8446e7e0a..0790a8004083ee28618fc5b1deb7f2c8d9d33e5e 100644 (file)
@@ -1681,8 +1681,7 @@ LDAP_SLAPD_F (int) slap_sasl_external( Connection *c,
        slap_ssf_t ssf, /* relative strength of external security */
        struct berval *authid );        /* asserted authentication id */
 
-LDAP_SLAPD_F (int) slap_sasl_cbinding( Connection *c,
-       struct berval *cbv );
+LDAP_SLAPD_F (int) slap_sasl_cbinding( Connection *c, void *ssl );
 
 LDAP_SLAPD_F (int) slap_sasl_reset( Connection *c );
 LDAP_SLAPD_F (int) slap_sasl_close( Connection *c );
@@ -2072,6 +2071,7 @@ LDAP_SLAPD_V (char *)     global_host;
 LDAP_SLAPD_V (struct berval)   global_host_bv;
 LDAP_SLAPD_V (char *)  global_realm;
 LDAP_SLAPD_V (char *)  sasl_host;
+LDAP_SLAPD_V (char *)  sasl_cbinding;
 LDAP_SLAPD_V (char *)  slap_sasl_auxprops;
 #ifdef SLAP_AUXPROP_DONTUSECOPY
 LDAP_SLAPD_V (int)             slap_dontUseCopy_ignore;
index fc023904a0797b2f8ce5a2b7da957d7f67ef46f0..5cced358c0fc21c79ef86b27743970cee476f2a1 100644 (file)
@@ -1320,6 +1320,8 @@ int slap_sasl_destroy( void )
 #endif
        free( sasl_host );
        sasl_host = NULL;
+       free( sasl_cbinding );
+       sasl_cbinding = NULL;
 
        return 0;
 }
@@ -1506,17 +1508,24 @@ int slap_sasl_external(
        return LDAP_SUCCESS;
 }
 
-int slap_sasl_cbinding( Connection *conn, struct berval *cbv )
+int slap_sasl_cbinding( Connection *conn, void *ssl )
 {
 #ifdef SASL_CHANNEL_BINDING
-       sasl_channel_binding_t *cb = ch_malloc( sizeof(*cb) + cbv->bv_len );;
-       cb->name = "ldap";
-       cb->critical = 0;
-       cb->data = (char *)(cb+1);
-       cb->len = cbv->bv_len;
-       memcpy( (void *)cb->data, cbv->bv_val, cbv->bv_len );
-       sasl_setprop( conn->c_sasl_authctx, SASL_CHANNEL_BINDING, cb );
-       conn->c_sasl_cbind = cb;
+       void *cb;
+       int i;
+
+       if ( sasl_cbinding == NULL )
+               return LDAP_SUCCESS;
+
+       i = ldap_pvt_sasl_cbinding_parse( sasl_cbinding );
+       if ( i < 0 )
+               return LDAP_SUCCESS;
+
+       cb = ldap_pvt_sasl_cbinding( ssl, i, 1 );
+       if ( cb != NULL ) {
+               sasl_setprop( conn->c_sasl_authctx, SASL_CHANNEL_BINDING, cb );
+               conn->c_sasl_cbind = cb;
+       }
 #endif
        return LDAP_SUCCESS;
 }