|
|
e4ff3b |
NOTE: The patch has been adjusted to match the base code before backporting.
|
|
|
e4ff3b |
|
|
|
e4ff3b |
From 3cd50fa8b32a21040a9892e2a8a7a9dfc7541ce6 Mon Sep 17 00:00:00 2001
|
|
|
e4ff3b |
From: Isaac Boukris <iboukris@gmail.com>
|
|
|
e4ff3b |
Date: Tue, 14 Apr 2020 16:10:48 +0300
|
|
|
e4ff3b |
Subject: [PATCH] ITS#9189 rework sasl-cbinding support
|
|
|
e4ff3b |
|
|
|
e4ff3b |
Add LDAP_OPT_X_SASL_CBINDING option to define the binding type to use,
|
|
|
e4ff3b |
defaults to "none".
|
|
|
e4ff3b |
|
|
|
e4ff3b |
Add "tls-endpoint" binding type implementing "tls-server-end-point" from
|
|
|
e4ff3b |
RCF 5929, which is compatible with Windows.
|
|
|
e4ff3b |
|
|
|
e4ff3b |
Fix "tls-unique" to include the prefix in the bindings as per RFC 5056.
|
|
|
e4ff3b |
---
|
|
|
e4ff3b |
doc/man/man3/ldap_get_option.3 | 16 ++++++
|
|
|
e4ff3b |
doc/man/man5/ldap.conf.5 | 3 +
|
|
|
e4ff3b |
doc/man/man5/slapd-config.5 | 4 ++
|
|
|
e4ff3b |
doc/man/man5/slapd.conf.5 | 3 +
|
|
|
e4ff3b |
include/ldap.h | 5 ++
|
|
|
e4ff3b |
include/ldap_pvt.h | 5 ++
|
|
|
e4ff3b |
libraries/libldap/cyrus.c | 101 +++++++++++++++++++++++++++++----
|
|
|
e4ff3b |
libraries/libldap/init.c | 1 +
|
|
|
e4ff3b |
libraries/libldap/ldap-int.h | 1 +
|
|
|
e4ff3b |
libraries/libldap/ldap-tls.h | 2 +
|
|
|
e4ff3b |
libraries/libldap/tls2.c | 7 +++
|
|
|
e4ff3b |
libraries/libldap/tls_g.c | 59 +++++++++++++++++++
|
|
|
e4ff3b |
libraries/libldap/tls_o.c | 45 +++++++++++++++
|
|
|
e4ff3b |
servers/slapd/bconfig.c | 11 +++-
|
|
|
e4ff3b |
servers/slapd/config.c | 1 +
|
|
|
e4ff3b |
servers/slapd/connection.c | 9 +--
|
|
|
e4ff3b |
servers/slapd/proto-slap.h | 4 +-
|
|
|
e4ff3b |
servers/slapd/sasl.c | 27 ++++++---
|
|
|
e4ff3b |
18 files changed, 274 insertions(+), 30 deletions(-)
|
|
|
e4ff3b |
|
|
|
e4ff3b |
diff --git a/doc/man/man3/ldap_get_option.3 b/doc/man/man3/ldap_get_option.3
|
|
|
e4ff3b |
index 7546875f5..e953900ce 100644
|
|
|
e4ff3b |
--- a/doc/man/man3/ldap_get_option.3
|
|
|
e4ff3b |
+++ b/doc/man/man3/ldap_get_option.3
|
|
|
e4ff3b |
@@ -557,6 +557,22 @@ must be a
|
|
|
e4ff3b |
.BR "char **" .
|
|
|
e4ff3b |
Its content needs to be freed by the caller using
|
|
|
e4ff3b |
.BR ldap_memfree (3).
|
|
|
e4ff3b |
+.B LDAP_OPT_X_SASL_CBINDING
|
|
|
e4ff3b |
+Sets/gets the channel-binding type to use in SASL,
|
|
|
e4ff3b |
+one of
|
|
|
e4ff3b |
+.BR LDAP_OPT_X_SASL_CBINDING_NONE
|
|
|
e4ff3b |
+(the default),
|
|
|
e4ff3b |
+.BR LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE
|
|
|
e4ff3b |
+the "tls-unique" type from RCF 5929.
|
|
|
e4ff3b |
+.BR LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT
|
|
|
e4ff3b |
+the "tls-server-end-point" from RCF 5929, compatible with Windows.
|
|
|
e4ff3b |
+.BR invalue
|
|
|
e4ff3b |
+must be
|
|
|
e4ff3b |
+.BR "const int *" ;
|
|
|
e4ff3b |
+.BR outvalue
|
|
|
e4ff3b |
+must be
|
|
|
e4ff3b |
+.BR "int *" .
|
|
|
e4ff3b |
+.TP
|
|
|
e4ff3b |
.SH TCP OPTIONS
|
|
|
e4ff3b |
The TCP options are OpenLDAP specific.
|
|
|
e4ff3b |
Mainly intended for use with Linux, they may not be portable.
|
|
|
e4ff3b |
diff --git a/doc/man/man5/ldap.conf.5 b/doc/man/man5/ldap.conf.5
|
|
|
e4ff3b |
index adf134899..29810fc9f 100644
|
|
|
e4ff3b |
--- a/doc/man/man5/ldap.conf.5
|
|
|
e4ff3b |
+++ b/doc/man/man5/ldap.conf.5
|
|
|
e4ff3b |
@@ -286,6 +286,9 @@ size allowed. 0 disables security layers. The default is 65536.
|
|
|
e4ff3b |
.TP
|
|
|
e4ff3b |
.B SASL_NOCANON <on/true/yes/off/false/no>
|
|
|
e4ff3b |
Do not perform reverse DNS lookups to canonicalize SASL host names. The default is off.
|
|
|
e4ff3b |
+.TP
|
|
|
e4ff3b |
+.B SASL_CBINDING <none/tls-unique/tls-endpoint>
|
|
|
e4ff3b |
+The channel-binding type to use, see also LDAP_OPT_X_SASL_CBINDING. The default is none.
|
|
|
e4ff3b |
.SH GSSAPI OPTIONS
|
|
|
e4ff3b |
If OpenLDAP is built with Generic Security Services Application Programming Interface support,
|
|
|
e4ff3b |
there are more options you can specify.
|
|
|
e4ff3b |
diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5
|
|
|
e4ff3b |
index 0dddfdb6c..8c987d8c1 100644
|
|
|
e4ff3b |
--- a/doc/man/man5/slapd-config.5
|
|
|
e4ff3b |
+++ b/doc/man/man5/slapd-config.5
|
|
|
e4ff3b |
@@ -699,6 +699,10 @@ Used to specify the fully qualified domain name used for SASL processing.
|
|
|
e4ff3b |
.B olcSaslRealm: <realm>
|
|
|
e4ff3b |
Specify SASL realm. Default is empty.
|
|
|
e4ff3b |
.TP
|
|
|
e4ff3b |
+.B olcSaslCbinding: none | tls-unique | tls-endpoint
|
|
|
e4ff3b |
+Specify the channel-binding type, see also LDAP_OPT_X_SASL_CBINDING.
|
|
|
e4ff3b |
+Default is none.
|
|
|
e4ff3b |
+.TP
|
|
|
e4ff3b |
.B olcSaslSecProps: <properties>
|
|
|
e4ff3b |
Used to specify Cyrus SASL security properties.
|
|
|
e4ff3b |
The
|
|
|
e4ff3b |
diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5
|
|
|
e4ff3b |
index 0071072b1..203ab988e 100644
|
|
|
e4ff3b |
--- a/doc/man/man5/slapd.conf.5
|
|
|
e4ff3b |
+++ b/doc/man/man5/slapd.conf.5
|
|
|
e4ff3b |
@@ -893,6 +893,9 @@ The
|
|
|
e4ff3b |
property specifies the maximum security layer receive buffer
|
|
|
e4ff3b |
size allowed. 0 disables security layers. The default is 65536.
|
|
|
e4ff3b |
.TP
|
|
|
e4ff3b |
+.B sasl\-cbinding none | tls-unique | tls-endpoint
|
|
|
e4ff3b |
+Specify the channel-binding type, see also LDAP_OPT_X_SASL_CBINDING.
|
|
|
e4ff3b |
+.TP
|
|
|
e4ff3b |
.B schemadn <dn>
|
|
|
e4ff3b |
Specify the distinguished name for the subschema subentry that
|
|
|
e4ff3b |
controls the entries on this server. The default is "cn=Subschema".
|
|
|
e4ff3b |
diff --git a/include/ldap.h b/include/ldap.h
|
|
|
e4ff3b |
index 88bfcabf8..e8ac968a9 100644
|
|
|
e4ff3b |
--- a/include/ldap.h
|
|
|
e4ff3b |
+++ b/include/ldap.h
|
|
|
e4ff3b |
@@ -180,6 +180,10 @@ LDAP_BEGIN_DECL
|
|
|
e4ff3b |
#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_1 ((3 << 8) + 2)
|
|
|
e4ff3b |
#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_2 ((3 << 8) + 3)
|
|
|
e4ff3b |
|
|
|
e4ff3b |
+#define LDAP_OPT_X_SASL_CBINDING_NONE 0
|
|
|
e4ff3b |
+#define LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE 1
|
|
|
e4ff3b |
+#define LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT 2
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
/* OpenLDAP SASL options */
|
|
|
e4ff3b |
#define LDAP_OPT_X_SASL_MECH 0x6100
|
|
|
e4ff3b |
#define LDAP_OPT_X_SASL_REALM 0x6101
|
|
|
e4ff3b |
@@ -195,6 +199,7 @@ LDAP_BEGIN_DECL
|
|
|
e4ff3b |
#define LDAP_OPT_X_SASL_NOCANON 0x610b
|
|
|
e4ff3b |
#define LDAP_OPT_X_SASL_USERNAME 0x610c /* read-only */
|
|
|
e4ff3b |
#define LDAP_OPT_X_SASL_GSS_CREDS 0x610d
|
|
|
e4ff3b |
+#define LDAP_OPT_X_SASL_CBINDING 0x610e
|
|
|
e4ff3b |
|
|
|
e4ff3b |
/* OpenLDAP GSSAPI options */
|
|
|
e4ff3b |
#define LDAP_OPT_X_GSSAPI_DO_NOT_FREE_CONTEXT 0x6200
|
|
|
e4ff3b |
diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h
|
|
|
e4ff3b |
index c586a95b5..b71552ec5 100644
|
|
|
e4ff3b |
--- a/include/ldap_pvt.h
|
|
|
e4ff3b |
+++ b/include/ldap_pvt.h
|
|
|
e4ff3b |
@@ -262,6 +262,10 @@ LDAP_F (void *) ldap_pvt_sasl_mutex_new LDAP_P((void));
|
|
|
e4ff3b |
LDAP_F (int) ldap_pvt_sasl_mutex_lock LDAP_P((void *mutex));
|
|
|
e4ff3b |
LDAP_F (int) ldap_pvt_sasl_mutex_unlock LDAP_P((void *mutex));
|
|
|
e4ff3b |
LDAP_F (void) ldap_pvt_sasl_mutex_dispose LDAP_P((void *mutex));
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+LDAP_F (int) ldap_pvt_sasl_cbinding_parse LDAP_P(( const char *arg ));
|
|
|
e4ff3b |
+LDAP_F (void *) ldap_pvt_sasl_cbinding LDAP_P(( void *ssl, int type,
|
|
|
e4ff3b |
+ int is_server ));
|
|
|
e4ff3b |
#endif /* HAVE_CYRUS_SASL */
|
|
|
e4ff3b |
|
|
|
e4ff3b |
struct sockbuf; /* avoid pulling in <lber.h> */
|
|
|
e4ff3b |
@@ -426,6 +430,7 @@ LDAP_F (int) ldap_pvt_tls_get_peer_dn LDAP_P(( void *ctx, struct berval *dn,
|
|
|
e4ff3b |
LDAPDN_rewrite_dummy *func, unsigned flags ));
|
|
|
e4ff3b |
LDAP_F (int) ldap_pvt_tls_get_strength LDAP_P(( void *ctx ));
|
|
|
e4ff3b |
LDAP_F (int) ldap_pvt_tls_get_unique LDAP_P(( void *ctx, struct berval *buf, int is_server ));
|
|
|
e4ff3b |
+LDAP_F (int) ldap_pvt_tls_get_endpoint LDAP_P(( void *ctx, struct berval *buf, int is_server ));
|
|
|
e4ff3b |
|
|
|
e4ff3b |
LDAP_END_DECL
|
|
|
e4ff3b |
|
|
|
e4ff3b |
diff --git a/libraries/libldap/cyrus.c b/libraries/libldap/cyrus.c
|
|
|
e4ff3b |
index 3171d56a3..081e3cea5 100644
|
|
|
e4ff3b |
--- a/libraries/libldap/cyrus.c
|
|
|
e4ff3b |
+++ b/libraries/libldap/cyrus.c
|
|
|
e4ff3b |
@@ -368,6 +368,65 @@ int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc )
|
|
|
e4ff3b |
return LDAP_SUCCESS;
|
|
|
e4ff3b |
}
|
|
|
e4ff3b |
|
|
|
e4ff3b |
+int ldap_pvt_sasl_cbinding_parse( const char *arg )
|
|
|
e4ff3b |
+{
|
|
|
e4ff3b |
+ int i = -1;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ if ( strcasecmp(arg, "none") == 0 )
|
|
|
e4ff3b |
+ i = LDAP_OPT_X_SASL_CBINDING_NONE;
|
|
|
e4ff3b |
+ else if ( strcasecmp(arg, "tls-unique") == 0 )
|
|
|
e4ff3b |
+ i = LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE;
|
|
|
e4ff3b |
+ else if ( strcasecmp(arg, "tls-endpoint") == 0 )
|
|
|
e4ff3b |
+ i = LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ return i;
|
|
|
e4ff3b |
+}
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+void *ldap_pvt_sasl_cbinding( void *ssl, int type, int is_server )
|
|
|
e4ff3b |
+{
|
|
|
e4ff3b |
+#if defined(SASL_CHANNEL_BINDING) && defined(HAVE_TLS)
|
|
|
e4ff3b |
+ char unique_prefix[] = "tls-unique:";
|
|
|
e4ff3b |
+ char endpoint_prefix[] = "tls-server-end-point:";
|
|
|
e4ff3b |
+ char cbinding[ 64 ];
|
|
|
e4ff3b |
+ struct berval cbv = { 64, cbinding };
|
|
|
e4ff3b |
+ void *cb_data; /* used since cb->data is const* */
|
|
|
e4ff3b |
+ sasl_channel_binding_t *cb;
|
|
|
e4ff3b |
+ char *prefix;
|
|
|
e4ff3b |
+ int plen;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ switch (type) {
|
|
|
e4ff3b |
+ case LDAP_OPT_X_SASL_CBINDING_NONE:
|
|
|
e4ff3b |
+ return NULL;
|
|
|
e4ff3b |
+ case LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE:
|
|
|
e4ff3b |
+ if ( !ldap_pvt_tls_get_unique( ssl, &cbv, is_server ))
|
|
|
e4ff3b |
+ return NULL;
|
|
|
e4ff3b |
+ prefix = unique_prefix;
|
|
|
e4ff3b |
+ plen = sizeof(unique_prefix) -1;
|
|
|
e4ff3b |
+ break;
|
|
|
e4ff3b |
+ case LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT:
|
|
|
e4ff3b |
+ if ( !ldap_pvt_tls_get_endpoint( ssl, &cbv, is_server ))
|
|
|
e4ff3b |
+ return NULL;
|
|
|
e4ff3b |
+ prefix = endpoint_prefix;
|
|
|
e4ff3b |
+ plen = sizeof(endpoint_prefix) -1;
|
|
|
e4ff3b |
+ break;
|
|
|
e4ff3b |
+ default:
|
|
|
e4ff3b |
+ return NULL;
|
|
|
e4ff3b |
+ }
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ cb = ldap_memalloc( sizeof(*cb) + plen + cbv.bv_len );
|
|
|
e4ff3b |
+ cb->len = plen + cbv.bv_len;
|
|
|
e4ff3b |
+ cb->data = cb_data = cb+1;
|
|
|
e4ff3b |
+ memcpy( cb_data, prefix, plen );
|
|
|
e4ff3b |
+ memcpy( cb_data + plen, cbv.bv_val, cbv.bv_len );
|
|
|
e4ff3b |
+ cb->name = "ldap";
|
|
|
e4ff3b |
+ cb->critical = 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ return cb;
|
|
|
e4ff3b |
+#else
|
|
|
e4ff3b |
+ return NULL;
|
|
|
e4ff3b |
+#endif
|
|
|
e4ff3b |
+}
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
int
|
|
|
e4ff3b |
ldap_int_sasl_bind(
|
|
|
e4ff3b |
LDAP *ld,
|
|
|
e4ff3b |
@@ -497,17 +556,12 @@ ldap_int_sasl_bind(
|
|
|
e4ff3b |
(void) ldap_int_sasl_external( ld, ld->ld_defconn, authid.bv_val, fac );
|
|
|
e4ff3b |
LDAP_FREE( authid.bv_val );
|
|
|
e4ff3b |
#ifdef SASL_CHANNEL_BINDING /* 2.1.25+ */
|
|
|
e4ff3b |
- {
|
|
|
e4ff3b |
- char cbinding[64];
|
|
|
e4ff3b |
- struct berval cbv = { sizeof(cbinding), cbinding };
|
|
|
e4ff3b |
- if ( ldap_pvt_tls_get_unique( ssl, &cbv, 0 )) {
|
|
|
e4ff3b |
- sasl_channel_binding_t *cb = ldap_memalloc( sizeof(*cb) +
|
|
|
e4ff3b |
- cbv.bv_len);
|
|
|
e4ff3b |
- cb->name = "ldap";
|
|
|
e4ff3b |
- cb->critical = 0;
|
|
|
e4ff3b |
- cb->data = (char *)(cb+1);
|
|
|
e4ff3b |
- cb->len = cbv.bv_len;
|
|
|
e4ff3b |
- memcpy( cb->data, cbv.bv_val, cbv.bv_len );
|
|
|
e4ff3b |
+ if ( ld->ld_defconn->lconn_sasl_cbind == NULL ) {
|
|
|
e4ff3b |
+ void *cb;
|
|
|
e4ff3b |
+ cb = ldap_pvt_sasl_cbinding( ssl,
|
|
|
e4ff3b |
+ ld->ld_options.ldo_sasl_cbinding,
|
|
|
e4ff3b |
+ 0 );
|
|
|
e4ff3b |
+ if ( cb != NULL ) {
|
|
|
e4ff3b |
sasl_setprop( ld->ld_defconn->lconn_sasl_authctx,
|
|
|
e4ff3b |
SASL_CHANNEL_BINDING, cb );
|
|
|
e4ff3b |
ld->ld_defconn->lconn_sasl_cbind = cb;
|
|
|
e4ff3b |
@@ -930,12 +984,20 @@ int ldap_pvt_sasl_secprops(
|
|
|
e4ff3b |
int
|
|
|
e4ff3b |
ldap_int_sasl_config( struct ldapoptions *lo, int option, const char *arg )
|
|
|
e4ff3b |
{
|
|
|
e4ff3b |
- int rc;
|
|
|
e4ff3b |
+ int rc, i;
|
|
|
e4ff3b |
|
|
|
e4ff3b |
switch( option ) {
|
|
|
e4ff3b |
case LDAP_OPT_X_SASL_SECPROPS:
|
|
|
e4ff3b |
rc = ldap_pvt_sasl_secprops( arg, &lo->ldo_sasl_secprops );
|
|
|
e4ff3b |
if( rc == LDAP_SUCCESS ) return 0;
|
|
|
e4ff3b |
+ break;
|
|
|
e4ff3b |
+ case LDAP_OPT_X_SASL_CBINDING:
|
|
|
e4ff3b |
+ i = ldap_pvt_sasl_cbinding_parse( arg );
|
|
|
e4ff3b |
+ if ( i >= 0 ) {
|
|
|
e4ff3b |
+ lo->ldo_sasl_cbinding = i;
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+ }
|
|
|
e4ff3b |
+ break;
|
|
|
e4ff3b |
}
|
|
|
e4ff3b |
|
|
|
e4ff3b |
return -1;
|
|
|
e4ff3b |
@@ -1041,6 +1103,10 @@ ldap_int_sasl_get_option( LDAP *ld, int option, void *arg )
|
|
|
e4ff3b |
/* this option is write only */
|
|
|
e4ff3b |
return -1;
|
|
|
e4ff3b |
|
|
|
e4ff3b |
+ case LDAP_OPT_X_SASL_CBINDING:
|
|
|
e4ff3b |
+ *(int *)arg = ld->ld_options.ldo_sasl_cbinding;
|
|
|
e4ff3b |
+ break;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
#ifdef SASL_GSS_CREDS
|
|
|
e4ff3b |
case LDAP_OPT_X_SASL_GSS_CREDS: {
|
|
|
e4ff3b |
sasl_conn_t *ctx;
|
|
|
e4ff3b |
@@ -1142,6 +1208,17 @@ ldap_int_sasl_set_option( LDAP *ld, int option, void *arg )
|
|
|
e4ff3b |
return sc == LDAP_SUCCESS ? 0 : -1;
|
|
|
e4ff3b |
}
|
|
|
e4ff3b |
|
|
|
e4ff3b |
+ case LDAP_OPT_X_SASL_CBINDING:
|
|
|
e4ff3b |
+ if ( !arg ) return -1;
|
|
|
e4ff3b |
+ switch( *(int *) arg ) {
|
|
|
e4ff3b |
+ case LDAP_OPT_X_SASL_CBINDING_NONE:
|
|
|
e4ff3b |
+ case LDAP_OPT_X_SASL_CBINDING_TLS_UNIQUE:
|
|
|
e4ff3b |
+ case LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT:
|
|
|
e4ff3b |
+ ld->ld_options.ldo_sasl_cbinding = *(int *) arg;
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+ }
|
|
|
e4ff3b |
+ return -1;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
#ifdef SASL_GSS_CREDS
|
|
|
e4ff3b |
case LDAP_OPT_X_SASL_GSS_CREDS: {
|
|
|
e4ff3b |
sasl_conn_t *ctx;
|
|
|
e4ff3b |
diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c
|
|
|
e4ff3b |
index 746824fbd..0c4b6237e 100644
|
|
|
e4ff3b |
--- a/libraries/libldap/init.c
|
|
|
e4ff3b |
+++ b/libraries/libldap/init.c
|
|
|
e4ff3b |
@@ -113,6 +113,7 @@ static const struct ol_attribute {
|
|
|
e4ff3b |
offsetof(struct ldapoptions, ldo_def_sasl_authzid)},
|
|
|
e4ff3b |
{0, ATTR_SASL, "SASL_SECPROPS", NULL, LDAP_OPT_X_SASL_SECPROPS},
|
|
|
e4ff3b |
{0, ATTR_BOOL, "SASL_NOCANON", NULL, LDAP_BOOL_SASL_NOCANON},
|
|
|
e4ff3b |
+ {0, ATTR_SASL, "SASL_CBINDING", NULL, LDAP_OPT_X_SASL_CBINDING},
|
|
|
e4ff3b |
#endif
|
|
|
e4ff3b |
|
|
|
e4ff3b |
#ifdef HAVE_GSSAPI
|
|
|
e4ff3b |
diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h
|
|
|
e4ff3b |
index 397894271..08d4b4a92 100644
|
|
|
e4ff3b |
--- a/libraries/libldap/ldap-int.h
|
|
|
e4ff3b |
+++ b/libraries/libldap/ldap-int.h
|
|
|
e4ff3b |
@@ -276,6 +276,7 @@ struct ldapoptions {
|
|
|
e4ff3b |
|
|
|
e4ff3b |
/* SASL Security Properties */
|
|
|
e4ff3b |
struct sasl_security_properties ldo_sasl_secprops;
|
|
|
e4ff3b |
+ int ldo_sasl_cbinding;
|
|
|
e4ff3b |
#define LDAP_LDO_SASL_NULLARG ,0,0,0,0,{0}
|
|
|
e4ff3b |
#else
|
|
|
e4ff3b |
#define LDAP_LDO_SASL_NULLARG
|
|
|
e4ff3b |
diff --git a/libraries/libldap/ldap-tls.h b/libraries/libldap/ldap-tls.h
|
|
|
e4ff3b |
index 103004fa7..77975bb6c 100644
|
|
|
e4ff3b |
--- a/libraries/libldap/ldap-tls.h
|
|
|
e4ff3b |
+++ b/libraries/libldap/ldap-tls.h
|
|
|
e4ff3b |
@@ -42,6 +42,7 @@ typedef int (TI_session_dn)(tls_session *sess, struct berval *dn);
|
|
|
e4ff3b |
typedef int (TI_session_chkhost)(LDAP *ld, tls_session *s, const char *name_in);
|
|
|
e4ff3b |
typedef int (TI_session_strength)(tls_session *sess);
|
|
|
e4ff3b |
typedef int (TI_session_unique)(tls_session *sess, struct berval *buf, int is_server);
|
|
|
e4ff3b |
+typedef int (TI_session_endpoint)(tls_session *sess, struct berval *buf, int is_server);
|
|
|
e4ff3b |
typedef int (TI_session_peercert)(tls_session *s, struct berval *der);
|
|
|
e4ff3b |
|
|
|
e4ff3b |
typedef void (TI_thr_init)(void);
|
|
|
e4ff3b |
@@ -67,6 +68,7 @@ typedef struct tls_impl {
|
|
|
e4ff3b |
TI_session_chkhost *ti_session_chkhost;
|
|
|
e4ff3b |
TI_session_strength *ti_session_strength;
|
|
|
e4ff3b |
TI_session_unique *ti_session_unique;
|
|
|
e4ff3b |
+ TI_session_endpoint *ti_session_endpoint;
|
|
|
e4ff3b |
TI_session_peercert *ti_session_peercert;
|
|
|
e4ff3b |
|
|
|
e4ff3b |
Sockbuf_IO *ti_sbio;
|
|
|
e4ff3b |
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
|
|
|
e4ff3b |
index 8b1fee748..f74af7d1d 100644
|
|
|
e4ff3b |
--- a/libraries/libldap/tls2.c
|
|
|
e4ff3b |
+++ b/libraries/libldap/tls2.c
|
|
|
e4ff3b |
@@ -1041,6 +1041,13 @@ ldap_pvt_tls_get_unique( void *s, struct berval *buf, int is_server )
|
|
|
e4ff3b |
return tls_imp->ti_session_unique( session, buf, is_server );
|
|
|
e4ff3b |
}
|
|
|
e4ff3b |
|
|
|
e4ff3b |
+int
|
|
|
e4ff3b |
+ldap_pvt_tls_get_endpoint( void *s, struct berval *buf, int is_server )
|
|
|
e4ff3b |
+{
|
|
|
e4ff3b |
+ tls_session *session = s;
|
|
|
e4ff3b |
+ return tls_imp->ti_session_endpoint( session, buf, is_server );
|
|
|
e4ff3b |
+}
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
int
|
|
|
e4ff3b |
ldap_pvt_tls_get_peercert( void *s, struct berval *der )
|
|
|
e4ff3b |
{
|
|
|
e4ff3b |
diff --git a/libraries/libldap/tls_g.c b/libraries/libldap/tls_g.c
|
|
|
e4ff3b |
index 26d9f99ce..52dfcd3ab 100644
|
|
|
e4ff3b |
--- a/libraries/libldap/tls_g.c
|
|
|
e4ff3b |
+++ b/libraries/libldap/tls_g.c
|
|
|
e4ff3b |
@@ -675,6 +675,64 @@ tlsg_session_unique( tls_session *sess, struct berval *buf, int is_server)
|
|
|
e4ff3b |
return 0;
|
|
|
e4ff3b |
}
|
|
|
e4ff3b |
|
|
|
e4ff3b |
+static int
|
|
|
e4ff3b |
+tlsg_session_endpoint( tls_session *sess, struct berval *buf, int is_server )
|
|
|
e4ff3b |
+{
|
|
|
e4ff3b |
+ tlsg_session *s = (tlsg_session *)sess;
|
|
|
e4ff3b |
+ const gnutls_datum_t *cert_data;
|
|
|
e4ff3b |
+ gnutls_x509_crt_t server_cert;
|
|
|
e4ff3b |
+ gnutls_digest_algorithm_t md;
|
|
|
e4ff3b |
+ int sign_algo, md_len, rc;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ if ( is_server )
|
|
|
e4ff3b |
+ cert_data = gnutls_certificate_get_ours( s->session );
|
|
|
e4ff3b |
+ else
|
|
|
e4ff3b |
+ cert_data = gnutls_certificate_get_peers( s->session, NULL );
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ if ( cert_data == NULL )
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ rc = gnutls_x509_crt_init( &server_cert );
|
|
|
e4ff3b |
+ if ( rc != GNUTLS_E_SUCCESS )
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ rc = gnutls_x509_crt_import( server_cert, cert_data, GNUTLS_X509_FMT_DER );
|
|
|
e4ff3b |
+ if ( rc != GNUTLS_E_SUCCESS ) {
|
|
|
e4ff3b |
+ gnutls_x509_crt_deinit( server_cert );
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+ }
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ sign_algo = gnutls_x509_crt_get_signature_algorithm( server_cert );
|
|
|
e4ff3b |
+ gnutls_x509_crt_deinit( server_cert );
|
|
|
e4ff3b |
+ if ( sign_algo <= GNUTLS_SIGN_UNKNOWN )
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ md = gnutls_sign_get_hash_algorithm( sign_algo );
|
|
|
e4ff3b |
+ if ( md == GNUTLS_DIG_UNKNOWN )
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ /* See RFC 5929 */
|
|
|
e4ff3b |
+ switch (md) {
|
|
|
e4ff3b |
+ case GNUTLS_DIG_NULL:
|
|
|
e4ff3b |
+ case GNUTLS_DIG_MD2:
|
|
|
e4ff3b |
+ case GNUTLS_DIG_MD5:
|
|
|
e4ff3b |
+ case GNUTLS_DIG_SHA1:
|
|
|
e4ff3b |
+ md = GNUTLS_DIG_SHA256;
|
|
|
e4ff3b |
+ }
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ md_len = gnutls_hash_get_len( md );
|
|
|
e4ff3b |
+ if ( md_len == 0 || md_len > buf->bv_len )
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ rc = gnutls_hash_fast( md, cert_data->data, cert_data->size, buf->bv_val );
|
|
|
e4ff3b |
+ if ( rc != GNUTLS_E_SUCCESS )
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ buf->bv_len = md_len;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ return md_len;
|
|
|
e4ff3b |
+}
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
static int
|
|
|
e4ff3b |
tlsg_session_peercert( tls_session *sess, struct berval *der )
|
|
|
e4ff3b |
{
|
|
|
e4ff3b |
@@ -950,6 +1008,7 @@ tls_impl ldap_int_tls_impl = {
|
|
|
e4ff3b |
tlsg_session_chkhost,
|
|
|
e4ff3b |
tlsg_session_strength,
|
|
|
e4ff3b |
tlsg_session_unique,
|
|
|
e4ff3b |
+ tlsg_session_endpoint,
|
|
|
e4ff3b |
tlsg_session_peercert,
|
|
|
e4ff3b |
|
|
|
e4ff3b |
&tlsg_sbio,
|
|
|
e4ff3b |
diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
|
|
|
e4ff3b |
index 157923289..8ede11572 100644
|
|
|
e4ff3b |
--- a/libraries/libldap/tls_o.c
|
|
|
e4ff3b |
+++ b/libraries/libldap/tls_o.c
|
|
|
e4ff3b |
@@ -861,6 +861,50 @@ tlso_session_unique( tls_session *sess, struct berval *buf, int is_server)
|
|
|
e4ff3b |
return buf->bv_len;
|
|
|
e4ff3b |
}
|
|
|
e4ff3b |
|
|
|
e4ff3b |
+static int
|
|
|
e4ff3b |
+tlso_session_endpoint( tls_session *sess, struct berval *buf, int is_server )
|
|
|
e4ff3b |
+{
|
|
|
e4ff3b |
+ tlso_session *s = (tlso_session *)sess;
|
|
|
e4ff3b |
+ const EVP_MD *md;
|
|
|
e4ff3b |
+ unsigned int md_len;
|
|
|
e4ff3b |
+ X509 *cert;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ if ( buf->bv_len < EVP_MAX_MD_SIZE )
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ if ( is_server )
|
|
|
e4ff3b |
+ cert = SSL_get_certificate( s );
|
|
|
e4ff3b |
+ else
|
|
|
e4ff3b |
+ cert = SSL_get_peer_certificate( s );
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ if ( cert == NULL )
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+#if OPENSSL_VERSION_NUMBER >= 0x10100000
|
|
|
e4ff3b |
+ md = EVP_get_digestbynid( X509_get_signature_nid( cert ));
|
|
|
e4ff3b |
+#else
|
|
|
e4ff3b |
+ md = EVP_get_digestbynid(OBJ_obj2nid( cert->sig_alg->algorithm ));
|
|
|
e4ff3b |
+#endif
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ /* See RFC 5929 */
|
|
|
e4ff3b |
+ if ( md == NULL ||
|
|
|
e4ff3b |
+ md == EVP_md_null() ||
|
|
|
e4ff3b |
+#ifndef OPENSSL_NO_MD2
|
|
|
e4ff3b |
+ md == EVP_md2() ||
|
|
|
e4ff3b |
+#endif
|
|
|
e4ff3b |
+ md == EVP_md4() ||
|
|
|
e4ff3b |
+ md == EVP_md5() ||
|
|
|
e4ff3b |
+ md == EVP_sha1() )
|
|
|
e4ff3b |
+ md = EVP_sha256();
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ if ( !X509_digest( cert, md, buf->bv_val, &md_len ))
|
|
|
e4ff3b |
+ return 0;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ buf->bv_len = md_len;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ return md_len;
|
|
|
e4ff3b |
+}
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
static int
|
|
|
e4ff3b |
tlso_session_peercert( tls_session *sess, struct berval *der )
|
|
|
e4ff3b |
{
|
|
|
e4ff3b |
@@ -1394,6 +1438,7 @@ tls_impl ldap_int_tls_impl = {
|
|
|
e4ff3b |
tlso_session_chkhost,
|
|
|
e4ff3b |
tlso_session_strength,
|
|
|
e4ff3b |
tlso_session_unique,
|
|
|
e4ff3b |
+ tlso_session_endpoint,
|
|
|
e4ff3b |
tlso_session_peercert,
|
|
|
e4ff3b |
|
|
|
e4ff3b |
&tlso_sbio,
|
|
|
e4ff3b |
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
|
|
|
e4ff3b |
index 3188ccfbe..8c4ccb860 100644
|
|
|
e4ff3b |
--- a/servers/slapd/bconfig.c
|
|
|
e4ff3b |
+++ b/servers/slapd/bconfig.c
|
|
|
e4ff3b |
@@ -569,6 +569,15 @@ static ConfigTable config_back_cf_table[] = {
|
|
|
e4ff3b |
#endif
|
|
|
e4ff3b |
"( OLcfgGlAt:89 NAME 'olcSaslAuxprops' "
|
|
|
e4ff3b |
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
|
|
e4ff3b |
+ { "sasl-cbinding", NULL, 2, 2, 0,
|
|
|
e4ff3b |
+#ifdef HAVE_CYRUS_SASL
|
|
|
e4ff3b |
+ ARG_STRING, &sasl_cbinding,
|
|
|
e4ff3b |
+#else
|
|
|
e4ff3b |
+ ARG_IGNORED, NULL,
|
|
|
e4ff3b |
+#endif
|
|
|
e4ff3b |
+ "( OLcfgGlAt:100 NAME 'olcSaslCBinding' "
|
|
|
e4ff3b |
+ "EQUALITY caseIgnoreMatch "
|
|
|
e4ff3b |
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
|
|
e4ff3b |
{ "sasl-host", "host", 2, 2, 0,
|
|
|
e4ff3b |
#ifdef HAVE_CYRUS_SASL
|
|
|
e4ff3b |
ARG_STRING|ARG_UNIQUE, &sasl_host,
|
|
|
e4ff3b |
@@ -820,7 +829,7 @@ static ConfigOCs cf_ocs[] = {
|
|
|
e4ff3b |
"olcPluginLogFile $ olcReadOnly $ olcReferral $ "
|
|
|
e4ff3b |
"olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
|
|
|
e4ff3b |
"olcRootDSE $ "
|
|
|
e4ff3b |
- "olcSaslAuxprops $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
|
|
|
e4ff3b |
+ "olcSaslAuxprops $ olcSaslCBinding $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
|
|
|
e4ff3b |
"olcSecurity $ olcServerID $ olcSizeLimit $ "
|
|
|
e4ff3b |
"olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ "
|
|
|
e4ff3b |
"olcTCPBuffer $ "
|
|
|
e4ff3b |
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
|
|
|
e4ff3b |
index 5108da696..77dd3c1ae 100644
|
|
|
e4ff3b |
--- a/servers/slapd/config.c
|
|
|
e4ff3b |
+++ b/servers/slapd/config.c
|
|
|
e4ff3b |
@@ -73,6 +73,7 @@ char *global_host = NULL;
|
|
|
e4ff3b |
struct berval global_host_bv = BER_BVNULL;
|
|
|
e4ff3b |
char *global_realm = NULL;
|
|
|
e4ff3b |
char *sasl_host = NULL;
|
|
|
e4ff3b |
+char *sasl_cbinding = NULL;
|
|
|
e4ff3b |
char **default_passwd_hash = NULL;
|
|
|
e4ff3b |
struct berval default_search_base = BER_BVNULL;
|
|
|
e4ff3b |
struct berval default_search_nbase = BER_BVNULL;
|
|
|
e4ff3b |
diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c
|
|
|
e4ff3b |
index 0602fdceb..d074009e4 100644
|
|
|
e4ff3b |
--- a/servers/slapd/connection.c
|
|
|
e4ff3b |
+++ b/servers/slapd/connection.c
|
|
|
e4ff3b |
@@ -1430,12 +1430,9 @@ connection_read( ber_socket_t s, conn_readinfo *cri )
|
|
|
e4ff3b |
c->c_connid, (int) s, c->c_tls_ssf, c->c_ssf, 0 );
|
|
|
e4ff3b |
slap_sasl_external( c, c->c_tls_ssf, &authid );
|
|
|
e4ff3b |
if ( authid.bv_val ) free( authid.bv_val );
|
|
|
e4ff3b |
- {
|
|
|
e4ff3b |
- char cbinding[64];
|
|
|
e4ff3b |
- struct berval cbv = { sizeof(cbinding), cbinding };
|
|
|
e4ff3b |
- if ( ldap_pvt_tls_get_unique( ssl, &cbv, 1 ))
|
|
|
e4ff3b |
- slap_sasl_cbinding( c, &cbv );
|
|
|
e4ff3b |
- }
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ slap_sasl_cbinding( c, ssl );
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
} else if ( rc == 1 && ber_sockbuf_ctrl( c->c_sb,
|
|
|
e4ff3b |
LBER_SB_OPT_NEEDS_WRITE, NULL )) { /* need to retry */
|
|
|
e4ff3b |
slapd_set_write( s, 1 );
|
|
|
e4ff3b |
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
|
|
|
e4ff3b |
index de1cabf32..9b52760bd 100644
|
|
|
e4ff3b |
--- a/servers/slapd/proto-slap.h
|
|
|
e4ff3b |
+++ b/servers/slapd/proto-slap.h
|
|
|
e4ff3b |
@@ -1657,8 +1657,7 @@ LDAP_SLAPD_F (int) slap_sasl_external( Connection *c,
|
|
|
e4ff3b |
slap_ssf_t ssf, /* relative strength of external security */
|
|
|
e4ff3b |
struct berval *authid ); /* asserted authenication id */
|
|
|
e4ff3b |
|
|
|
e4ff3b |
-LDAP_SLAPD_F (int) slap_sasl_cbinding( Connection *c,
|
|
|
e4ff3b |
- struct berval *cbv );
|
|
|
e4ff3b |
+LDAP_SLAPD_F (int) slap_sasl_cbinding( Connection *c, void *ssl );
|
|
|
e4ff3b |
|
|
|
e4ff3b |
LDAP_SLAPD_F (int) slap_sasl_reset( Connection *c );
|
|
|
e4ff3b |
LDAP_SLAPD_F (int) slap_sasl_close( Connection *c );
|
|
|
e4ff3b |
@@ -2039,6 +2038,7 @@ LDAP_SLAPD_V (char *) global_host;
|
|
|
e4ff3b |
LDAP_SLAPD_V (struct berval) global_host_bv;
|
|
|
e4ff3b |
LDAP_SLAPD_V (char *) global_realm;
|
|
|
e4ff3b |
LDAP_SLAPD_V (char *) sasl_host;
|
|
|
e4ff3b |
+LDAP_SLAPD_V (char *) sasl_cbinding;
|
|
|
e4ff3b |
LDAP_SLAPD_V (char *) slap_sasl_auxprops;
|
|
|
e4ff3b |
LDAP_SLAPD_V (char **) default_passwd_hash;
|
|
|
e4ff3b |
LDAP_SLAPD_V (int) lber_debug;
|
|
|
e4ff3b |
diff --git a/servers/slapd/sasl.c b/servers/slapd/sasl.c
|
|
|
e4ff3b |
index 258cd5407..c14e8a628 100644
|
|
|
e4ff3b |
--- a/servers/slapd/sasl.c
|
|
|
e4ff3b |
+++ b/servers/slapd/sasl.c
|
|
|
e4ff3b |
@@ -1203,6 +1203,8 @@ int slap_sasl_destroy( void )
|
|
|
e4ff3b |
#endif
|
|
|
e4ff3b |
free( sasl_host );
|
|
|
e4ff3b |
sasl_host = NULL;
|
|
|
e4ff3b |
+ free( sasl_cbinding );
|
|
|
e4ff3b |
+ sasl_cbinding = NULL;
|
|
|
e4ff3b |
|
|
|
e4ff3b |
return 0;
|
|
|
e4ff3b |
}
|
|
|
e4ff3b |
@@ -1389,17 +1391,24 @@ int slap_sasl_external(
|
|
|
e4ff3b |
return LDAP_SUCCESS;
|
|
|
e4ff3b |
}
|
|
|
e4ff3b |
|
|
|
e4ff3b |
-int slap_sasl_cbinding( Connection *conn, struct berval *cbv )
|
|
|
e4ff3b |
+int slap_sasl_cbinding( Connection *conn, void *ssl )
|
|
|
e4ff3b |
{
|
|
|
e4ff3b |
#ifdef SASL_CHANNEL_BINDING
|
|
|
e4ff3b |
- sasl_channel_binding_t *cb = ch_malloc( sizeof(*cb) + cbv->bv_len );;
|
|
|
e4ff3b |
- cb->name = "ldap";
|
|
|
e4ff3b |
- cb->critical = 0;
|
|
|
e4ff3b |
- cb->data = (char *)(cb+1);
|
|
|
e4ff3b |
- cb->len = cbv->bv_len;
|
|
|
e4ff3b |
- memcpy( cb->data, cbv->bv_val, cbv->bv_len );
|
|
|
e4ff3b |
- sasl_setprop( conn->c_sasl_authctx, SASL_CHANNEL_BINDING, cb );
|
|
|
e4ff3b |
- conn->c_sasl_cbind = cb;
|
|
|
e4ff3b |
+ void *cb;
|
|
|
e4ff3b |
+ int i;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ if ( sasl_cbinding == NULL )
|
|
|
e4ff3b |
+ return LDAP_SUCCESS;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ i = ldap_pvt_sasl_cbinding_parse( sasl_cbinding );
|
|
|
e4ff3b |
+ if ( i < 0 )
|
|
|
e4ff3b |
+ return LDAP_SUCCESS;
|
|
|
e4ff3b |
+
|
|
|
e4ff3b |
+ cb = ldap_pvt_sasl_cbinding( ssl, i, 1 );
|
|
|
e4ff3b |
+ if ( cb != NULL ) {
|
|
|
e4ff3b |
+ sasl_setprop( conn->c_sasl_authctx, SASL_CHANNEL_BINDING, cb );
|
|
|
e4ff3b |
+ conn->c_sasl_cbind = cb;
|
|
|
e4ff3b |
+ }
|
|
|
e4ff3b |
#endif
|
|
|
e4ff3b |
return LDAP_SUCCESS;
|
|
|
e4ff3b |
}
|
|
|
e4ff3b |
--
|
|
|
e4ff3b |
2.29.2
|
|
|
e4ff3b |
|