Blame SOURCES/openldap-cbinding-Add-channel-binding-support.patch

d0db73
From ca310ebff44f10739fd75aff437c7676e089b134 Mon Sep 17 00:00:00 2001
d0db73
From: Howard Chu <hyc@openldap.org>
d0db73
Date: Mon, 26 Aug 2013 23:31:48 -0700
d0db73
Subject: [PATCH] Add channel binding support
d0db73
d0db73
Currently only implemented for OpenSSL.
d0db73
Needs an option to set the criticality flag.
d0db73
---
d0db73
 include/ldap_pvt.h           |  1 +
d0db73
 libraries/libldap/cyrus.c    | 22 ++++++++++++++++++++++
d0db73
 libraries/libldap/ldap-int.h |  1 +
d0db73
 libraries/libldap/ldap-tls.h |  2 ++
d0db73
 libraries/libldap/tls2.c     |  7 +++++++
d0db73
 libraries/libldap/tls_g.c    |  7 +++++++
d0db73
 libraries/libldap/tls_m.c    |  7 +++++++
d0db73
 libraries/libldap/tls_o.c    | 16 ++++++++++++++++
d0db73
 servers/slapd/connection.c   |  8 ++++++++
d0db73
 servers/slapd/sasl.c         | 18 ++++++++++++++++++
d0db73
 servers/slapd/slap.h         |  1 +
d0db73
 11 files changed, 90 insertions(+)
d0db73
d0db73
diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h
d0db73
index 716c1a90f..61c620785 100644
d0db73
--- a/include/ldap_pvt.h
d0db73
+++ b/include/ldap_pvt.h
d0db73
@@ -420,6 +420,7 @@ LDAP_F (int) ldap_pvt_tls_get_my_dn LDAP_P(( void *ctx, struct berval *dn,
d0db73
 LDAP_F (int) ldap_pvt_tls_get_peer_dn LDAP_P(( void *ctx, struct berval *dn,
d0db73
 	LDAPDN_rewrite_dummy *func, unsigned flags ));
d0db73
 LDAP_F (int) ldap_pvt_tls_get_strength LDAP_P(( void *ctx ));
d0db73
+LDAP_F (int) ldap_pvt_tls_get_unique LDAP_P(( void *ctx, struct berval *buf, int is_server ));
d0db73
 
d0db73
 LDAP_END_DECL
d0db73
 
d0db73
diff --git a/libraries/libldap/cyrus.c b/libraries/libldap/cyrus.c
d0db73
index 4c0089d5d..3171d56a3 100644
d0db73
--- a/libraries/libldap/cyrus.c
d0db73
+++ b/libraries/libldap/cyrus.c
d0db73
@@ -360,6 +360,10 @@ int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc )
d0db73
 		lc->lconn_sasl_sockctx = NULL;
d0db73
 		lc->lconn_sasl_authctx = NULL;
d0db73
 	}
d0db73
+	if( lc->lconn_sasl_cbind ) {
d0db73
+		ldap_memfree( lc->lconn_sasl_cbind );
d0db73
+		lc->lconn_sasl_cbind = NULL;
d0db73
+	}
d0db73
 
d0db73
 	return LDAP_SUCCESS;
d0db73
 }
d0db73
@@ -492,6 +496,24 @@ ldap_int_sasl_bind(
d0db73
 
d0db73
 			(void) ldap_int_sasl_external( ld, ld->ld_defconn, authid.bv_val, fac );
d0db73
 			LDAP_FREE( authid.bv_val );
d0db73
+#ifdef SASL_CHANNEL_BINDING	/* 2.1.25+ */
d0db73
+			{
d0db73
+				char cbinding[64];
d0db73
+				struct berval cbv = { sizeof(cbinding), cbinding };
d0db73
+				if ( ldap_pvt_tls_get_unique( ssl, &cbv, 0 )) {
d0db73
+					sasl_channel_binding_t *cb = ldap_memalloc( sizeof(*cb) +
d0db73
+						cbv.bv_len);
d0db73
+					cb->name = "ldap";
d0db73
+					cb->critical = 0;
d0db73
+					cb->data = (char *)(cb+1);
d0db73
+					cb->len = cbv.bv_len;
d0db73
+					memcpy( cb->data, cbv.bv_val, cbv.bv_len );
d0db73
+					sasl_setprop( ld->ld_defconn->lconn_sasl_authctx,
d0db73
+						SASL_CHANNEL_BINDING, cb );
d0db73
+					ld->ld_defconn->lconn_sasl_cbind = cb;
d0db73
+				}
d0db73
+			}
d0db73
+#endif
d0db73
 		}
d0db73
 #endif
d0db73
 
d0db73
diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h
d0db73
index 98ad4dc05..397894271 100644
d0db73
--- a/libraries/libldap/ldap-int.h
d0db73
+++ b/libraries/libldap/ldap-int.h
d0db73
@@ -308,6 +308,7 @@ typedef struct ldap_conn {
d0db73
 #ifdef HAVE_CYRUS_SASL
d0db73
 	void		*lconn_sasl_authctx;	/* context for bind */
d0db73
 	void		*lconn_sasl_sockctx;	/* for security layer */
d0db73
+	void		*lconn_sasl_cbind;		/* for channel binding */
d0db73
 #endif
d0db73
 #ifdef HAVE_GSSAPI
d0db73
 	void		*lconn_gss_ctx;		/* gss_ctx_id_t */
d0db73
diff --git a/libraries/libldap/ldap-tls.h b/libraries/libldap/ldap-tls.h
d0db73
index c8a27112f..0ecf81ab9 100644
d0db73
--- a/libraries/libldap/ldap-tls.h
d0db73
+++ b/libraries/libldap/ldap-tls.h
d0db73
@@ -41,6 +41,7 @@ typedef char *(TI_session_errmsg)(tls_session *s, int rc, char *buf, size_t len
d0db73
 typedef int (TI_session_dn)(tls_session *sess, struct berval *dn);
d0db73
 typedef int (TI_session_chkhost)(LDAP *ld, tls_session *s, const char *name_in);
d0db73
 typedef int (TI_session_strength)(tls_session *sess);
d0db73
+typedef int (TI_session_unique)(tls_session *sess, struct berval *buf, int is_server);
d0db73
 
d0db73
 typedef void (TI_thr_init)(void);
d0db73
 
d0db73
@@ -64,6 +65,7 @@ typedef struct tls_impl {
d0db73
 	TI_session_dn *ti_session_peer_dn;
d0db73
 	TI_session_chkhost *ti_session_chkhost;
d0db73
 	TI_session_strength *ti_session_strength;
d0db73
+	TI_session_unique *ti_session_unique;
d0db73
 
d0db73
 	Sockbuf_IO *ti_sbio;
d0db73
 
d0db73
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
d0db73
index 82ca5272c..13d734362 100644
d0db73
--- a/libraries/libldap/tls2.c
d0db73
+++ b/libraries/libldap/tls2.c
d0db73
@@ -1013,6 +1013,13 @@ ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func,
d0db73
 		rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags );
d0db73
 	return rc;
d0db73
 }
d0db73
+
d0db73
+int
d0db73
+ldap_pvt_tls_get_unique( void *s, struct berval *buf, int is_server )
d0db73
+{
d0db73
+	tls_session *session = s;
d0db73
+	return tls_imp->ti_session_unique( session, buf, is_server );
d0db73
+}
d0db73
 #endif /* HAVE_TLS */
d0db73
 
d0db73
 int
d0db73
diff --git a/libraries/libldap/tls_g.c b/libraries/libldap/tls_g.c
d0db73
index 3b72cd2a1..b78c12086 100644
d0db73
--- a/libraries/libldap/tls_g.c
d0db73
+++ b/libraries/libldap/tls_g.c
d0db73
@@ -669,6 +669,12 @@ tlsg_session_strength( tls_session *session )
d0db73
 	return gnutls_cipher_get_key_size( c ) * 8;
d0db73
 }
d0db73
 
d0db73
+static int
d0db73
+tlsg_session_unique( tls_session *sess, struct berval *buf, int is_server)
d0db73
+{
d0db73
+	return 0;
d0db73
+}
d0db73
+
d0db73
 /* suites is a string of colon-separated cipher suite names. */
d0db73
 static int
d0db73
 tlsg_parse_ciphers( tlsg_ctx *ctx, char *suites )
d0db73
@@ -925,6 +931,7 @@ tls_impl ldap_int_tls_impl = {
d0db73
 	tlsg_session_peer_dn,
d0db73
 	tlsg_session_chkhost,
d0db73
 	tlsg_session_strength,
d0db73
+	tlsg_session_unique,
d0db73
 
d0db73
 	&tlsg_sbio,
d0db73
 
d0db73
diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c
d0db73
index 43fbae4bc..c64f4c176 100644
d0db73
--- a/libraries/libldap/tls_m.c
d0db73
+++ b/libraries/libldap/tls_m.c
d0db73
@@ -2874,6 +2874,12 @@ tlsm_session_strength( tls_session *session )
d0db73
 	return rc ? 0 : keySize;
d0db73
 }
d0db73
 
d0db73
+static int
d0db73
+tlsm_session_unique( tls_session *sess, struct berval *buf, int is_server)
d0db73
+{
d0db73
+	return 0;
d0db73
+}
d0db73
+
d0db73
 /*
d0db73
  * TLS support for LBER Sockbufs
d0db73
  */
d0db73
@@ -3302,6 +3308,7 @@ tls_impl ldap_int_tls_impl = {
d0db73
 	tlsm_session_peer_dn,
d0db73
 	tlsm_session_chkhost,
d0db73
 	tlsm_session_strength,
d0db73
+	tlsm_session_unique,
d0db73
 
d0db73
 	&tlsm_sbio,
d0db73
 
d0db73
diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
d0db73
index a13f11fb5..f741a461f 100644
d0db73
--- a/libraries/libldap/tls_o.c
d0db73
+++ b/libraries/libldap/tls_o.c
d0db73
@@ -846,6 +846,21 @@ tlso_session_strength( tls_session *sess )
d0db73
 	return SSL_CIPHER_get_bits(SSL_get_current_cipher(s), NULL);
d0db73
 }
d0db73
 
d0db73
+static int
d0db73
+tlso_session_unique( tls_session *sess, struct berval *buf, int is_server)
d0db73
+{
d0db73
+	tlso_session *s = (tlso_session *)sess;
d0db73
+
d0db73
+	/* Usually the client sends the finished msg. But if the
d0db73
+	 * session was resumed, the server sent the msg.
d0db73
+	 */
d0db73
+	if (SSL_session_reused(s) ^ !is_server)
d0db73
+		buf->bv_len = SSL_get_finished(s, buf->bv_val, buf->bv_len);
d0db73
+	else
d0db73
+		buf->bv_len = SSL_get_peer_finished(s, buf->bv_val, buf->bv_len);
d0db73
+	return buf->bv_len;
d0db73
+}
d0db73
+
d0db73
 /*
d0db73
  * TLS support for LBER Sockbufs
d0db73
  */
d0db73
@@ -1363,6 +1378,7 @@ tls_impl ldap_int_tls_impl = {
d0db73
 	tlso_session_peer_dn,
d0db73
 	tlso_session_chkhost,
d0db73
 	tlso_session_strength,
d0db73
+	tlso_session_unique,
d0db73
 
d0db73
 	&tlso_sbio,
d0db73
 
d0db73
diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c
d0db73
index 44c3fc63d..0602fdceb 100644
d0db73
--- a/servers/slapd/connection.c
d0db73
+++ b/servers/slapd/connection.c
d0db73
@@ -406,6 +406,7 @@ Connection * connection_init(
d0db73
 		c->c_sasl_sockctx = NULL;
d0db73
 		c->c_sasl_extra = NULL;
d0db73
 		c->c_sasl_bindop = NULL;
d0db73
+		c->c_sasl_cbind = NULL;
d0db73
 
d0db73
 		c->c_sb = ber_sockbuf_alloc( );
d0db73
 
d0db73
@@ -451,6 +452,7 @@ Connection * connection_init(
d0db73
 	assert( c->c_sasl_sockctx == NULL );
d0db73
 	assert( c->c_sasl_extra == NULL );
d0db73
 	assert( c->c_sasl_bindop == NULL );
d0db73
+	assert( c->c_sasl_cbind == NULL );
d0db73
 	assert( c->c_currentber == NULL );
d0db73
 	assert( c->c_writewaiter == 0);
d0db73
 	assert( c->c_writers == 0);
d0db73
@@ -1428,6 +1430,12 @@ connection_read( ber_socket_t s, conn_readinfo *cri )
d0db73
 			    c->c_connid, (int) s, c->c_tls_ssf, c->c_ssf, 0 );
d0db73
 			slap_sasl_external( c, c->c_tls_ssf, &authid );
d0db73
 			if ( authid.bv_val ) free( authid.bv_val );
d0db73
+			{
d0db73
+				char cbinding[64];
d0db73
+				struct berval cbv = { sizeof(cbinding), cbinding };
d0db73
+				if ( ldap_pvt_tls_get_unique( ssl, &cbv, 1 ))
d0db73
+					slap_sasl_cbinding( c, &cbv );
d0db73
+			}
d0db73
 		} else if ( rc == 1 && ber_sockbuf_ctrl( c->c_sb,
d0db73
 			LBER_SB_OPT_NEEDS_WRITE, NULL )) {	/* need to retry */
d0db73
 			slapd_set_write( s, 1 );
d0db73
diff --git a/servers/slapd/sasl.c b/servers/slapd/sasl.c
d0db73
index 5144170d1..258cd5407 100644
d0db73
--- a/servers/slapd/sasl.c
d0db73
+++ b/servers/slapd/sasl.c
d0db73
@@ -1389,6 +1389,21 @@ int slap_sasl_external(
d0db73
 	return LDAP_SUCCESS;
d0db73
 }
d0db73
 
d0db73
+int slap_sasl_cbinding( Connection *conn, struct berval *cbv )
d0db73
+{
d0db73
+#ifdef SASL_CHANNEL_BINDING
d0db73
+	sasl_channel_binding_t *cb = ch_malloc( sizeof(*cb) + cbv->bv_len );;
d0db73
+	cb->name = "ldap";
d0db73
+	cb->critical = 0;
d0db73
+	cb->data = (char *)(cb+1);
d0db73
+	cb->len = cbv->bv_len;
d0db73
+	memcpy( cb->data, cbv->bv_val, cbv->bv_len );
d0db73
+	sasl_setprop( conn->c_sasl_authctx, SASL_CHANNEL_BINDING, cb );
d0db73
+	conn->c_sasl_cbind = cb;
d0db73
+#endif
d0db73
+	return LDAP_SUCCESS;
d0db73
+}
d0db73
+
d0db73
 int slap_sasl_reset( Connection *conn )
d0db73
 {
d0db73
 	return LDAP_SUCCESS;
d0db73
@@ -1454,6 +1469,9 @@ int slap_sasl_close( Connection *conn )
d0db73
 	free( conn->c_sasl_extra );
d0db73
 	conn->c_sasl_extra = NULL;
d0db73
 
d0db73
+	free( conn->c_sasl_cbind );
d0db73
+	conn->c_sasl_cbind = NULL;
d0db73
+
d0db73
 #elif defined(SLAP_BUILTIN_SASL)
d0db73
 	SASL_CTX *ctx = conn->c_sasl_authctx;
d0db73
 	if( ctx ) {
d0db73
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
d0db73
index 7581967be..ad797d752 100644
d0db73
--- a/servers/slapd/slap.h
d0db73
+++ b/servers/slapd/slap.h
d0db73
@@ -2910,6 +2910,7 @@ struct Connection {
d0db73
 	void	*c_sasl_authctx;	/* SASL authentication context */
d0db73
 	void	*c_sasl_sockctx;	/* SASL security layer context */
d0db73
 	void	*c_sasl_extra;		/* SASL session extra stuff */
d0db73
+	void	*c_sasl_cbind;		/* SASL channel binding */
d0db73
 	Operation	*c_sasl_bindop;	/* set to current op if it's a bind */
d0db73
 
d0db73
 #ifdef LDAP_X_TXN
d0db73
-- 
d0db73
2.29.2
d0db73