]> git.sur5r.net Git - openldap/commitdiff
Add channel binding support
authorHoward Chu <hyc@openldap.org>
Tue, 27 Aug 2013 06:31:48 +0000 (23:31 -0700)
committerHoward Chu <hyc@openldap.org>
Tue, 27 Aug 2013 06:31:48 +0000 (23:31 -0700)
Currently only implemented for OpenSSL.
Needs an option to set the criticality flag.

include/ldap_pvt.h
libraries/libldap/cyrus.c
libraries/libldap/ldap-int.h
libraries/libldap/ldap-tls.h
libraries/libldap/tls2.c
libraries/libldap/tls_g.c
libraries/libldap/tls_m.c
libraries/libldap/tls_o.c
servers/slapd/connection.c
servers/slapd/sasl.c
servers/slapd/slap.h

index 871e7c1800b3c99a34d401aa6d0d2816d9d7010e..fdc9d2de36ab08c0a87db262357cf9bba49b41d7 100644 (file)
@@ -430,6 +430,7 @@ LDAP_F (int) ldap_pvt_tls_get_my_dn LDAP_P(( void *ctx, struct berval *dn,
 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_END_DECL
 
index 28c241b0bf47b508ed34b82a9f958467cb1967d0..a57292800be5a9bbbaff01b57083a7504cb89a74 100644 (file)
@@ -369,6 +369,10 @@ int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc )
                lc->lconn_sasl_sockctx = NULL;
                lc->lconn_sasl_authctx = NULL;
        }
+       if( lc->lconn_sasl_cbind ) {
+               ldap_memfree( lc->lconn_sasl_cbind );
+               lc->lconn_sasl_cbind = NULL;
+       }
 
        return LDAP_SUCCESS;
 }
@@ -482,6 +486,24 @@ 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 ( ldap_pvt_tls_get_unique( ssl, &cbv, 0 )) {
+                                       sasl_channel_binding_t *cb = ldap_memalloc( sizeof(*cb) +
+                                               cbv.bv_len);
+                                       cb->name = "ldap";
+                                       cb->critical = 0;
+                                       cb->data = (char *)(cb+1);
+                                       cb->len = cbv.bv_len;
+                                       memcpy( cb->data, cbv.bv_val, cbv.bv_len );
+                                       sasl_setprop( ld->ld_defconn->lconn_sasl_authctx,
+                                               SASL_CHANNEL_BINDING, cb );
+                                       ld->ld_defconn->lconn_sasl_cbind = cb;
+                               }
+                       }
+#endif
                }
 #endif
 
index 37c342e260f701b53182bbe238bf74b69c1012e6..1915ecab438af30cec78b3b0568933d1f9e15e7c 100644 (file)
@@ -305,6 +305,7 @@ typedef struct ldap_conn {
 #ifdef HAVE_CYRUS_SASL
        void            *lconn_sasl_authctx;    /* context for bind */
        void            *lconn_sasl_sockctx;    /* for security layer */
+       void            *lconn_sasl_cbind;              /* for channel binding */
 #endif
 #ifdef HAVE_GSSAPI
        void            *lconn_gss_ctx;         /* gss_ctx_id_t */
index 75661c0059a497d3dd1d99ed6523239fece5af1d..1eb5ae47e8122535cd0d25a7ec59dd85e6481aad 100644 (file)
@@ -41,6 +41,7 @@ typedef char *(TI_session_errmsg)(tls_session *s, int rc, char *buf, size_t len
 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 void (TI_thr_init)(void);
 
@@ -64,6 +65,7 @@ typedef struct tls_impl {
        TI_session_dn *ti_session_peer_dn;
        TI_session_chkhost *ti_session_chkhost;
        TI_session_strength *ti_session_strength;
+       TI_session_unique *ti_session_unique;
 
        Sockbuf_IO *ti_sbio;
 
index e11d1a8a3932ea7c456b7c685127d58c1a6100ae..957e73c0319974857092b8f5c8b7b124a120eff6 100644 (file)
@@ -981,6 +981,13 @@ ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func,
                rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags );
        return rc;
 }
+
+int
+ldap_pvt_tls_get_unique( void *s, struct berval *buf, int is_server )
+{
+       tls_session *session = s;
+       return tls_imp->ti_session_unique( session, buf, is_server );
+}
 #endif /* HAVE_TLS */
 
 int
index ed1f8f1cb896e1b9f3806bc8a9cd8fd219ccc863..dfdc35da43a3d80a2c322c87af70eefa93f5b1b0 100644 (file)
@@ -780,6 +780,12 @@ tlsg_session_strength( tls_session *session )
        return gnutls_cipher_get_key_size( c ) * 8;
 }
 
+static int
+tlsg_session_unique( tls_session *sess, struct berval *buf, int is_server)
+{
+       return 0;
+}
+
 /* suites is a string of colon-separated cipher suite names. */
 static int
 tlsg_parse_ciphers( tlsg_ctx *ctx, char *suites )
@@ -1110,6 +1116,7 @@ tls_impl ldap_int_tls_impl = {
        tlsg_session_peer_dn,
        tlsg_session_chkhost,
        tlsg_session_strength,
+       tlsg_session_unique,
 
        &tlsg_sbio,
 
index 072d41d56cc3ffe709353f2bae18345e7c68eb99..240bd9ff6edaf26d08c6329e4ac5eabbe820fab4 100644 (file)
@@ -2838,6 +2838,12 @@ tlsm_session_strength( tls_session *session )
        return rc ? 0 : keySize;
 }
 
+static int
+tlsm_session_unique( tls_session *sess, struct berval *buf, int is_server)
+{
+       return 0;
+}
+
 /*
  * TLS support for LBER Sockbufs
  */
@@ -3266,6 +3272,7 @@ tls_impl ldap_int_tls_impl = {
        tlsm_session_peer_dn,
        tlsm_session_chkhost,
        tlsm_session_strength,
+       tlsm_session_unique,
 
        &tlsm_sbio,
 
index 3c077f895ad2799047792894160fb4fd3f7c8ed0..2ecee465bd35d35d1a6b87c8f59b0d52ef5a91ef 100644 (file)
@@ -676,6 +676,21 @@ tlso_session_strength( tls_session *sess )
        return SSL_CIPHER_get_bits(SSL_get_current_cipher(s), NULL);
 }
 
+static int
+tlso_session_unique( tls_session *sess, struct berval *buf, int is_server)
+{
+       tlso_session *s = (tlso_session *)sess;
+
+       /* Usually the client sends the finished msg. But if the
+        * session was resumed, the server sent the msg.
+        */
+       if (SSL_session_reused(s) ^ !is_server)
+               buf->bv_len = SSL_get_finished(s, buf->bv_val, buf->bv_len);
+       else
+               buf->bv_len = SSL_get_peer_finished(s, buf->bv_val, buf->bv_len);
+       return buf->bv_len;
+}
+
 /*
  * TLS support for LBER Sockbufs
  */
@@ -1283,6 +1298,7 @@ tls_impl ldap_int_tls_impl = {
        tlso_session_peer_dn,
        tlso_session_chkhost,
        tlso_session_strength,
+       tlso_session_unique,
 
        &tlso_sbio,
 
index e34703cb384243b8e4bfc6b04e4069881e6118cf..bc2b8a4d09d2cd7fd3de7e7ec658ddc85b93457e 100644 (file)
@@ -406,6 +406,7 @@ Connection * connection_init(
                c->c_sasl_sockctx = NULL;
                c->c_sasl_extra = NULL;
                c->c_sasl_bindop = NULL;
+               c->c_sasl_cbind = NULL;
 
                c->c_sb = ber_sockbuf_alloc( );
 
@@ -451,6 +452,7 @@ Connection * connection_init(
        assert( c->c_sasl_sockctx == NULL );
        assert( c->c_sasl_extra == NULL );
        assert( c->c_sasl_bindop == NULL );
+       assert( c->c_sasl_cbind == NULL );
        assert( c->c_currentber == NULL );
        assert( c->c_writewaiter == 0);
        assert( c->c_writers == 0);
@@ -1408,6 +1410,12 @@ connection_read( ber_socket_t s, conn_readinfo *cri )
                            c->c_connid, (int) s, c->c_tls_ssf, c->c_ssf, 0 );
                        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 );
+                       }
                } 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 0bd6259bead6d3d9e50d848d9fc860fe7c55d7f7..57907d79b6bfd745fea01b9200effda7bdeecad9 100644 (file)
@@ -1503,6 +1503,21 @@ int slap_sasl_external(
        return LDAP_SUCCESS;
 }
 
+int slap_sasl_cbinding( Connection *conn, struct berval *cbv )
+{
+#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( cb->data, cbv->bv_val, cbv->bv_len );
+       sasl_setprop( conn->c_sasl_authctx, SASL_CHANNEL_BINDING, cb );
+       conn->c_sasl_cbind = cb;
+#endif
+       return LDAP_SUCCESS;
+}
+
 int slap_sasl_reset( Connection *conn )
 {
        return LDAP_SUCCESS;
@@ -1568,6 +1583,9 @@ int slap_sasl_close( Connection *conn )
        free( conn->c_sasl_extra );
        conn->c_sasl_extra = NULL;
 
+       free( conn->c_sasl_cbind );
+       conn->c_sasl_cbind = NULL;
+
 #elif defined(SLAP_BUILTIN_SASL)
        SASL_CTX *ctx = conn->c_sasl_authctx;
        if( ctx ) {
index 09c1854f88ab535d30c35f4942f114d3aed249ec..4b3bbd12e39cb378b9ee615999b9fe217b456610 100644 (file)
@@ -2910,6 +2910,7 @@ struct Connection {
        void    *c_sasl_authctx;        /* SASL authentication context */
        void    *c_sasl_sockctx;        /* SASL security layer context */
        void    *c_sasl_extra;          /* SASL session extra stuff */
+       void    *c_sasl_cbind;          /* SASL channel binding */
        Operation       *c_sasl_bindop; /* set to current op if it's a bind */
 
 #ifdef LDAP_X_TXN