]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap/tls_g.c
Merge remote-tracking branch 'origin/mdb.master'
[openldap] / libraries / libldap / tls_g.c
index ed1f8f1cb896e1b9f3806bc8a9cd8fd219ccc863..7396804392fd0e1f3a2015dffd639655dd89ad44 100644 (file)
@@ -45,8 +45,6 @@
 #include <gnutls/x509.h>
 #include <gcrypt.h>
 
-#define DH_BITS        (1024)
-
 #if LIBGNUTLS_VERSION_NUMBER >= 0x020200
 #define        HAVE_CIPHERSUITES       1
 /* This is a kludge. gcrypt 1.4.x has support. Recent GnuTLS requires gcrypt 1.4.x
@@ -277,6 +275,8 @@ tlsg_ctx_free ( tls_ctx *ctx )
        LDAP_FREE( c->kx_list );
 #endif
        gnutls_certificate_free_credentials( c->cred );
+       if ( c->dh_params )
+               gnutls_dh_params_deinit( c->dh_params );
        ber_memfree ( c );
 }
 
@@ -368,6 +368,17 @@ tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
                 * then we have to build the cert chain.
                 */
                if ( max == 1 && !gnutls_x509_crt_check_issuer( certs[0], certs[0] )) {
+#if GNUTLS_VERSION_NUMBER >= 0x020c00
+                       unsigned int i;
+                       for ( i = 1; i<VERIFY_DEPTH; i++ ) {
+                               if ( gnutls_certificate_get_issuer( ctx->cred, certs[i-1], &certs[i], 0 ))
+                                       break;
+                               max++;
+                               /* If this CA is self-signed, we're done */
+                               if ( gnutls_x509_crt_check_issuer( certs[i], certs[i] ))
+                                       break;
+                       }
+#else
                        gnutls_x509_crt_t *cas;
                        unsigned int i, j, ncas;
 
@@ -387,6 +398,7 @@ tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
                                if ( j == ncas )
                                        break;
                        }
+#endif
                }
                rc = gnutls_certificate_set_x509_key( ctx->cred, certs, max, key );
                if ( rc ) return -1;
@@ -397,12 +409,6 @@ tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
                return -1;
        }
 
-       if ( lo->ldo_tls_dhfile ) {
-               Debug( LDAP_DEBUG_ANY, 
-                      "TLS: warning: ignoring dhfile\n", 
-                      NULL, NULL, NULL );
-       }
-
        if ( lo->ldo_tls_crlfile ) {
                rc = gnutls_certificate_set_x509_crl_file( 
                        ctx->cred,
@@ -412,15 +418,23 @@ tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
                rc = 0;
        }
 
-       /* FIXME: ITS#5992 - this should go be configurable,
+       /* FIXME: ITS#5992 - this should be configurable,
         * and V1 CA certs should be phased out ASAP.
         */
        gnutls_certificate_set_verify_flags( ctx->cred,
                GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT );
 
-       if ( is_server ) {
-               gnutls_dh_params_init(&ctx->dh_params);
-               gnutls_dh_params_generate2(ctx->dh_params, DH_BITS);
+       if ( is_server && lo->ldo_tls_dhfile ) {
+               gnutls_datum_t buf;
+               rc = tlsg_getfile( lo->ldo_tls_dhfile, &buf );
+               if ( rc ) return -1;
+               rc = gnutls_dh_params_init( &ctx->dh_params );
+               if ( rc == 0 )
+                       rc = gnutls_dh_params_import_pkcs3( ctx->dh_params, &buf,
+                               GNUTLS_X509_FMT_PEM );
+               LDAP_FREE( buf.data );
+               if ( rc ) return -1;
+               gnutls_certificate_set_dh_params( ctx->cred, ctx->dh_params );
        }
        return 0;
 }
@@ -780,13 +794,70 @@ 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)
+{
+/* channel bindings added in 2.12.0 */
+#if GNUTLS_VERSION_NUMBER >= 0x020c00
+       tlsg_session *s = (tlsg_session *)sess;
+       gnutls_datum_t cb;
+       int rc;
+
+       rc = gnutls_session_channel_binding( s->session, GNUTLS_CB_TLS_UNIQUE, &cb );
+       if ( rc == 0 ) {
+               int len = cb.size;
+               if ( len > buf->bv_len )
+                       len = buf->bv_len;
+               buf->bv_len = len;
+               memcpy( buf->bv_val, cb.data, len );
+               return len;
+       }
+#endif
+       return 0;
+}
+
+static const char *
+tlsg_session_version( tls_session *sess )
+{
+       tlsg_session *s = (tlsg_session *)sess;
+       return gnutls_protocol_get_name(gnutls_protocol_get_version( s->session ));
+}
+
+static const char *
+tlsg_session_cipher( tls_session *sess )
+{
+       tlsg_session *s = (tlsg_session *)sess;
+       return gnutls_cipher_get_name(gnutls_cipher_get( s->session ));
+}
+
+static int
+tlsg_session_peercert( tls_session *sess, struct berval *der )
+{
+       tlsg_session *s = (tlsg_session *)sess;
+       const gnutls_datum_t *peer_cert_list;
+       unsigned int list_size;
+
+       peer_cert_list = gnutls_certificate_get_peers( s->session, &list_size );
+       if (!peer_cert_list)
+               return -1;
+       der->bv_len = peer_cert_list[0].size;
+       der->bv_val = LDAP_MALLOC( der->bv_len );
+       if (!der->bv_val)
+               return -1;
+       memcpy(der->bv_val, peer_cert_list[0].data, der->bv_len);
+       return 0;
+}
+
 /* suites is a string of colon-separated cipher suite names. */
 static int
 tlsg_parse_ciphers( tlsg_ctx *ctx, char *suites )
 {
 #ifdef HAVE_CIPHERSUITES
        const char *err;
-       return gnutls_priority_init( &ctx->prios, suites, &err );
+       int rc = gnutls_priority_init( &ctx->prios, suites, &err );
+       if ( rc )
+               ctx->prios = NULL;
+       return rc;
 #else
        char *ptr, *end;
        int i, j, len, num;
@@ -1110,6 +1181,10 @@ tls_impl ldap_int_tls_impl = {
        tlsg_session_peer_dn,
        tlsg_session_chkhost,
        tlsg_session_strength,
+       tlsg_session_unique,
+       tlsg_session_version,
+       tlsg_session_cipher,
+       tlsg_session_peercert,
 
        &tlsg_sbio,