From f7e6c71e13cc276896d108a1af978c6a6f02981a Mon Sep 17 00:00:00 2001 From: johan pascal Date: Thu, 2 Mar 2023 10:51:19 +0100 Subject: [PATCH] ITS#10014: Add TLS handle using MbedTLS --- .gitlab-ci.yml | 26 + configure.ac | 33 +- doc/man/man3/ldap_get_option.3 | 2 + doc/man/man5/lloadd.conf.5 | 2 + doc/man/man5/slapd-config.5 | 2 + doc/man/man5/slapd.conf.5 | 2 + libraries/libldap/Makefile.in | 4 +- libraries/libldap/tls_mt.c | 1014 +++++++++++++++++++++++++++++ servers/slapd/overlays/otp.c | 37 +- tests/scripts/test067-tls | 2 +- tests/scripts/test077-sasl-gssapi | 5 + 11 files changed, 1123 insertions(+), 6 deletions(-) create mode 100644 libraries/libldap/tls_mt.c diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 773d82df2e..1ff44c76b9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -73,3 +73,29 @@ build-gnutls-mit-standalone-lloadd: - obj/tests/testrun/ - obj/servers/ - obj/libraries/ + +build-mbedtls-mit-standalone-lloadd: + image: "debian:testing" + stage: build + script: + - export STARTTIME=$(date +%s) + - apt update + - DEBIAN_FRONTEND=noninteractive apt install -y build-essential python3 gdb procps pkg-config automake libsasl2-dev libltdl-dev groff-base unixodbc-dev libwiredtiger-dev libperl-dev krb5-user krb5-kdc krb5-admin-server libsasl2-modules-gssapi-mit sasl2-bin libmbedtls-dev libevent-dev libargon2-dev libsystemd-dev + - autoreconf + - mkdir obj + - cd obj + - echo "$(date -u -d "now - $STARTTIME sec" +%T) Configuring" + - ../configure --with-tls=mbedtls --enable-backends=mod --enable-overlays=mod --disable-autoca --enable-modules --enable-dynamic --enable-balancer=mod --enable-argon2 --with-systemd + - make depend + - echo "$(date -u -d "now - $STARTTIME sec" +%T) Building" + - make + - ulimit -n 4096 # back-monitor takes a while scanning a long connections array + - SLAPD_COMMON_WRAPPER=gdb make test + artifacts: + name: testdir + when: on_failure + expire_in: '1 week' + paths: + - obj/tests/testrun/ + - obj/servers/ + - obj/libraries/ diff --git a/configure.ac b/configure.ac index 7d291e863f..95cdbea451 100644 --- a/configure.ac +++ b/configure.ac @@ -247,8 +247,8 @@ OL_ARG_WITH(threads, [AS_HELP_STRING([--with-threads], [with threads library auto|nt|posix|pth|lwp|manual])], auto, [auto nt posix pth lwp yes no manual] ) OL_ARG_WITH(tls, - [AS_HELP_STRING([--with-tls], [with TLS/SSL support auto|openssl|gnutls])], - auto, [auto openssl gnutls yes no] ) + [AS_HELP_STRING([--with-tls], [with TLS/SSL support auto|openssl|gnutls|mbedtls])], + auto, [auto openssl gnutls mbedtls yes no] ) OL_ARG_WITH(yielding_select, [AS_HELP_STRING([--with-yielding-select], [with implicitly yielding select])], auto, [auto yes no manual] ) @@ -1290,6 +1290,35 @@ if test $ol_link_tls = no ; then fi fi +if test $ol_link_tls = no ; then + if test $ol_with_tls = mbedtls || test $ol_with_tls = auto ; then + AC_CHECK_HEADERS(mbedtls/ssl.h) + + if test $ac_cv_header_mbedtls_ssl_h = yes ; then + AC_PREPROC_IFELSE([AC_LANG_SOURCE( + [[#include ] +[#if MBEDTLS_VERSION_NUMBER < 0x02120000] +[#error "mbedtls is too old"] +[#endif]])], + , [AC_MSG_FAILURE([mbedtls 2.18.0 or newer required])]) + + AC_CHECK_LIB(mbedtls, mbedtls_ssl_init, + [have_mbedtls=yes], [have_mbedtls=no], -lmbedx509 -lmbedcrypto) + + if test $have_mbedtls = yes ; then + ol_with_tls=mbedtls + ol_link_tls=yes + WITH_TLS_TYPE=mbedtls + + TLS_LIBS="-lmbedtls -lmbedx509 -lmbedcrypto" + + AC_DEFINE(HAVE_MBEDTLS, 1, + [define if you have mbedtls]) + fi + fi + fi +fi + WITH_TLS=no if test $ol_link_tls = yes ; then AC_DEFINE(HAVE_TLS, 1, [define if you have TLS]) diff --git a/doc/man/man3/ldap_get_option.3 b/doc/man/man3/ldap_get_option.3 index b7ed9762e3..7a8008e051 100644 --- a/doc/man/man3/ldap_get_option.3 +++ b/doc/man/man3/ldap_get_option.3 @@ -692,6 +692,7 @@ and its contents need to be freed by the caller using .TP .B LDAP_OPT_X_TLS_CIPHER_SUITE Sets/gets the allowed cipher suite. +This directive is not supported when using MbedTLS. .BR invalue must be .BR "const char *" ; @@ -762,6 +763,7 @@ manipulate this structure. .B LDAP_OPT_X_TLS_DHFILE Gets/sets the full-path of the file containing the parameters for Diffie-Hellman ephemeral key exchange. +This directive is not supported when using MbedTLS. .BR invalue must be .BR "const char *" ; diff --git a/doc/man/man5/lloadd.conf.5 b/doc/man/man5/lloadd.conf.5 index 3d137d0e1c..6010cc32d1 100644 --- a/doc/man/man5/lloadd.conf.5 +++ b/doc/man/man5/lloadd.conf.5 @@ -462,6 +462,7 @@ option. Permits configuring what ciphers will be accepted and the preference order. should be a cipher specification for the TLS library in use (OpenSSL, GnuTLS, or Mozilla NSS). +This directive is not supported when using MbedTLS. Example: .RS .RS @@ -577,6 +578,7 @@ You should append "!ADH" to your cipher suites to ensure that these suites are not used. When using Mozilla NSS these parameters are always generated randomly so this directive is ignored. +This directive is not supported when using MbedTLS. .TP .B TLSECName Specify the name of a curve to use for Elliptic curve Diffie-Hellman diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5 index a61ed67d57..a16a223edc 100644 --- a/doc/man/man5/slapd-config.5 +++ b/doc/man/man5/slapd-config.5 @@ -903,6 +903,7 @@ you can specify. Permits configuring what ciphers will be accepted and the preference order. should be a cipher specification for the TLS library in use (OpenSSL or GnuTLS). +This directive is not supported when using MbedTLS. Example: .RS .RS @@ -982,6 +983,7 @@ actual client or server authentication and provide no protection against man-in-the-middle attacks. You should append "!ADH" to your cipher suites to ensure that these suites are not used. +This directive is not supported when using MbedTLS. .TP .B olcTLSECName: Specify the name of the curve(s) to use for Elliptic curve Diffie-Hellman diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 index fdebcbdd55..3325b92d03 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -1133,6 +1133,7 @@ you can specify. Permits configuring what ciphers will be accepted and the preference order. should be a cipher specification for the TLS library in use (OpenSSL or GnuTLS). +This directive is not supported when using MbedTLS. Example: .RS .RS @@ -1209,6 +1210,7 @@ actual client or server authentication and provide no protection against man-in-the-middle attacks. You should append "!ADH" to your cipher suites to ensure that these suites are not used. +This directive is not supported when using MbedTLS. .TP .B TLSECName Specify the name of the curve(s) to use for Elliptic curve Diffie-Hellman diff --git a/libraries/libldap/Makefile.in b/libraries/libldap/Makefile.in index 5d5c4c6514..4d314ae8e4 100644 --- a/libraries/libldap/Makefile.in +++ b/libraries/libldap/Makefile.in @@ -26,7 +26,7 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \ request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ - tls2.c tls_o.c tls_g.c \ + tls2.c tls_o.c tls_g.c tls_mt.c\ turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \ assertion.c deref.c ldifutil.c ldif.c fetch.c lbase64.c \ msctrl.c psearchctrl.c threads.c rdwr.c tpool.c rq.c \ @@ -42,7 +42,7 @@ OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ - tls2.lo tls_o.lo tls_g.lo \ + tls2.lo tls_o.lo tls_g.lo tls_mt.lo\ turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \ assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo lbase64.lo \ msctrl.lo psearchctrl.lo threads.lo rdwr.lo tpool.lo rq.lo \ diff --git a/libraries/libldap/tls_mt.c b/libraries/libldap/tls_mt.c new file mode 100644 index 0000000000..5ca0926d78 --- /dev/null +++ b/libraries/libldap/tls_mt.c @@ -0,0 +1,1014 @@ +/* tls_mt.c - Handle tls/ssl using MbedTLS */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2010-2023 Belledonne Communications SARL. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* ACKNOWLEDGEMENTS: + */ + +#include "portable.h" + +#ifdef HAVE_MBEDTLS + +#include "ldap_config.h" + +#include + +#include +#include +#include +#include +#include + +#include "ldap-int.h" +#include "ldap-tls.h" + +#include +#include +#include +#include +#include +#include +#include + +typedef struct tlsmt_ctx { + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_config ssl_config; + mbedtls_x509_crt own_cert; + mbedtls_pk_context own_cert_key; + mbedtls_x509_crt ca_chain; + unsigned long verify_depth; + int refcount; +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_t ref_mutex; +#endif +} tlsmt_ctx; + +typedef struct tlsmt_session { + mbedtls_ssl_context ssl_ctx; + tlsmt_ctx *config; +} tlsmt_session; + +#ifdef LDAP_R_COMPILE +static void tlsmt_thr_init( void ) +{ +} +#endif /* LDAP_R_COMPILE */ + +/* + * Initialize TLS subsystem. Should be called only once. + */ +static int +tlsmt_init( void ) +{ + return 0; +} + +/* + * Tear down the TLS subsystem. Should only be called once. + */ +static void +tlsmt_destroy( void ) +{ + +} + +static tls_ctx * +tlsmt_ctx_new( struct ldapoptions *lo ) +{ + tlsmt_ctx *ctx; + + ctx = ber_memcalloc ( 1, sizeof (*ctx) ); + if ( ctx ) { + int ret = 0; + ctx->refcount = 1; + mbedtls_entropy_init( &ctx->entropy ); + mbedtls_ctr_drbg_init( &ctx->ctr_drbg ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctx->ctr_drbg, mbedtls_entropy_func, &ctx->entropy, NULL, 0 ) ) != 0 ) + { + mbedtls_ctr_drbg_free( &ctx->ctr_drbg ); + mbedtls_entropy_free( &ctx->entropy ); + ber_memfree ( ctx ); + Debug1(LDAP_DEBUG_ANY, "Mbedtls can't init ctr_drbg: [-0x%x]. Unable to create tls context", -ret); + return NULL; + } + mbedtls_ssl_config_init( &ctx->ssl_config ); + mbedtls_ssl_conf_rng( &ctx->ssl_config, mbedtls_ctr_drbg_random, &ctx->ctr_drbg); + mbedtls_x509_crt_init( &ctx->own_cert ); + mbedtls_pk_init( &ctx->own_cert_key ); + mbedtls_x509_crt_init( &ctx->ca_chain ); + +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_init( &ctx->ref_mutex ); +#endif + } + + return (tls_ctx *)ctx; +} + +static void +tlsmt_ctx_ref( tls_ctx *ctx ) +{ + + tlsmt_ctx *c = (tlsmt_ctx *)ctx; + LDAP_MUTEX_LOCK( &c->ref_mutex ); + c->refcount++; + LDAP_MUTEX_UNLOCK( &c->ref_mutex ); +} + +static void +tlsmt_ctx_free ( tls_ctx *ctx ) +{ + + tlsmt_ctx *c = (tlsmt_ctx *)ctx; + int refcount; + + if ( !c ) return; + + LDAP_MUTEX_LOCK( &c->ref_mutex ); + refcount = --c->refcount; + LDAP_MUTEX_UNLOCK( &c->ref_mutex ); + if ( refcount ) + return; + + mbedtls_ssl_config_free( &c->ssl_config ); + mbedtls_ctr_drbg_free( &c->ctr_drbg ); + mbedtls_entropy_free( &c->entropy ); + mbedtls_x509_crt_free( &c->own_cert ); + mbedtls_pk_free( &c->own_cert_key ); + mbedtls_x509_crt_free( &c->ca_chain ); + ber_memfree ( c ); +} + +/* + * initialize a new TLS context + */ +static int +tlsmt_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server, char *errmsg ) +{ + tlsmt_ctx *ctx = (tlsmt_ctx *)lo->ldo_tls_ctx; + mbedtls_ssl_config *ssl_config = &ctx->ssl_config; + + // Set all options for the connection + int ret = mbedtls_ssl_config_defaults(ssl_config, is_server?MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); + +// MBedtls v3 deprecated SSLv3, TLS1.0, TLS1.1 +#if MBEDTLS_VERSION_NUMBER < 0x03000000 + if ( lo->ldo_tls_protocol_min ) { + int minor = MBEDTLS_SSL_MINOR_VERSION_0; // SSLv3.0 shall be avoided + switch (lo->ldo_tls_protocol_min) { + case LDAP_OPT_X_TLS_PROTOCOL_SSL2: // SSL2 not supported, set min to SSLv3 + case LDAP_OPT_X_TLS_PROTOCOL_SSL3: + minor = MBEDTLS_SSL_MINOR_VERSION_0; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_0: + minor = MBEDTLS_SSL_MINOR_VERSION_1; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_1: + minor = MBEDTLS_SSL_MINOR_VERSION_2; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_2: + default: + minor = MBEDTLS_SSL_MINOR_VERSION_3; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_3: + Debug0 ( LDAP_DEBUG_ANY, "MbedTLSv2 backend does not support TLSv1.3, keep minimum version to 1.2" ); + minor = MBEDTLS_SSL_MINOR_VERSION_3; + break; + } + mbedtls_ssl_conf_min_version ( ssl_config, MBEDTLS_SSL_MAJOR_VERSION_3, minor ); + } + + if ( lo->ldo_tls_protocol_max ) { + int minor = MBEDTLS_SSL_MINOR_VERSION_3; + switch (lo->ldo_tls_protocol_max) { + case LDAP_OPT_X_TLS_PROTOCOL_SSL2: // SSL2 not supported, set min to SSLv3 + case LDAP_OPT_X_TLS_PROTOCOL_SSL3: + minor = MBEDTLS_SSL_MINOR_VERSION_0; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_0: + minor = MBEDTLS_SSL_MINOR_VERSION_1; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_1: + minor = MBEDTLS_SSL_MINOR_VERSION_2; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_2: + default: + minor = MBEDTLS_SSL_MINOR_VERSION_3; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_3: + Debug0 ( LDAP_DEBUG_ANY, "MbedTLSv2 backend does not support TLSv1.3, keep maximum version to 1.2" ); + minor = MBEDTLS_SSL_MINOR_VERSION_3; + break; + } + mbedtls_ssl_conf_max_version ( ssl_config, MBEDTLS_SSL_MAJOR_VERSION_3, minor ); + } +#else /* MBEDTLS_VERSION_NUMBER < 0x03000000 : MBEDTLS version 3 and above: No SSLv3, TLSv1.0, TLSv1.1 */ + if ( lo->ldo_tls_protocol_min ) { + mbedtls_ssl_protocol_version version = MBEDTLS_SSL_VERSION_TLS1_2; // TLSv1.2 is the lowest version available + switch (lo->ldo_tls_protocol_max) { + case LDAP_OPT_X_TLS_PROTOCOL_SSL2: + case LDAP_OPT_X_TLS_PROTOCOL_SSL3: + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_0: + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_1: + /* for all non supported version request, force TLSv1.2 */ + Debug0 ( LDAP_DEBUG_ANY, "MbedTLSv3 backend does not support TLS version under 1.2, switch the minimum version requested to it" ); + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_2: + default: + version = MBEDTLS_SSL_VERSION_TLS1_2; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_3: + version = MBEDTLS_SSL_VERSION_TLS1_3; + break; + } + mbedtls_ssl_conf_min_tls_version ( ssl_config, version ); + } + + if ( lo->ldo_tls_protocol_max ) { + mbedtls_ssl_protocol_version version = MBEDTLS_SSL_VERSION_TLS1_3; + switch (lo->ldo_tls_protocol_min) { + case LDAP_OPT_X_TLS_PROTOCOL_SSL2: + case LDAP_OPT_X_TLS_PROTOCOL_SSL3: + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_0: + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_1: + /* for all non supported version request, force TLSv1.2 */ + Debug0 ( LDAP_DEBUG_ANY, "MbedTLSv3 backend does not support TLS version under 1.2, switch the maximum version requested to it" ); + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_2: + default: + version = MBEDTLS_SSL_VERSION_TLS1_2; + break; + case LDAP_OPT_X_TLS_PROTOCOL_TLS1_3: + version = MBEDTLS_SSL_VERSION_TLS1_3; + break; + } + mbedtls_ssl_conf_max_tls_version ( ssl_config, version ); + } + +#endif /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ + + if ( lo->ldo_tls_ciphersuite ) { + Debug1 (LDAP_DEBUG_ANY, "tlsmt_ctx_init Cipher suite selection is not supported by MbedTLS backend, ignore setting %s\n", lt->lt_ciphersuite); + } + + if (lo->ldo_tls_cacertdir != NULL) { + char **dirs = ldap_str2charray( lt->lt_cacertdir, CERTPATHSEP ); + int i; + for ( i=0; dirs[i]; i++ ) { + int ret = mbedtls_x509_crt_parse_path( &ctx->ca_chain, dirs[i] ); + if ( ret < 0 ) { + Debug1( LDAP_DEBUG_ANY, + "TLS: warning: no certificate found in CA certificate directory `%s'.\n", + dirs[i] ); + /* only warn, no return */ + mbedtls_strerror( ret, errmsg, ERRBUFSIZE ); + } + } + ldap_charray_free( dirs ); + } + + if (lo->ldo_tls_cacertfile != NULL) { + int ret = mbedtls_x509_crt_parse_file( &ctx->ca_chain, lt->lt_cacertfile ); + if ( ret < 0 ) { + char errParseFile[ERRBUFSIZE]; + mbedtls_strerror( ret, errParseFile, ERRBUFSIZE ); + Debug3( LDAP_DEBUG_ANY, + "TLS: could not use CA certificate file `%s': %s (%d)\n", + lo->ldo_tls_cacertfile, + errParseFile, + ret ); + return -1; + } + } + mbedtls_ssl_conf_ca_chain(ssl_config, &ctx->ca_chain, NULL); // CRL not supported + + if (( lo->ldo_tls_certfile && lo->ldo_tls_keyfile ) || + ( lo->ldo_tls_cert.bv_val && lo->ldo_tls_key.bv_val )) { + +#if MBEDTLS_VERSION_NUMBER < 0x03000000 + if ( lo->ldo_tls_key.bv_val ) { + ret = mbedtls_pk_parse_key(&ctx->own_cert_key, (unsigned char *)lo->ldo_tls_key.bv_val, lo->ldo_tls_key.bv_len, NULL, 0); + } else { + ret = mbedtls_pk_parse_keyfile(&ctx->own_cert_key, lt->lt_keyfile, NULL); + } +#else /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ + if ( lo->ldo_tls_key.bv_val ) { + ret = mbedtls_pk_parse_key(&ctx->own_cert_key, (unsigned char *)lo->ldo_tls_key.bv_val, lo->ldo_tls_key.bv_len, NULL, 0, mbedtls_ctr_drbg_random, &ctx->ctr_drbg); + } else { + ret = mbedtls_pk_parse_keyfile(&ctx->own_cert_key, lt->lt_keyfile, NULL, mbedtls_ctr_drbg_random, &ctx->ctr_drbg); + } +#endif /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ + + if (ret != 0) { + return -1; + } + + if ( lo->ldo_tls_cert.bv_val ) { + ret = mbedtls_x509_crt_parse( &ctx->own_cert, (unsigned char *)lo->ldo_tls_cert.bv_val, lo->ldo_tls_cert.bv_len); + } else { + ret = mbedtls_x509_crt_parse_file( &ctx->own_cert, lt->lt_certfile); + } + + if (ret != 0) { + return -1; + } + + if ( (ret = mbedtls_ssl_conf_own_cert(ssl_config, &ctx->own_cert, &ctx->own_cert_key ) ) != 0) { + return -1; + } + } + + switch ( lo->ldo_tls_require_cert ) { + case LDAP_OPT_X_TLS_NEVER : + mbedtls_ssl_conf_authmode( ssl_config, MBEDTLS_SSL_VERIFY_NONE ); + break; + case LDAP_OPT_X_TLS_HARD: + case LDAP_OPT_X_TLS_DEMAND: + default: + mbedtls_ssl_conf_authmode( ssl_config, MBEDTLS_SSL_VERIFY_REQUIRED ); + break; + case LDAP_OPT_X_TLS_ALLOW: + case LDAP_OPT_X_TLS_TRY: + mbedtls_ssl_conf_authmode( ssl_config, MBEDTLS_SSL_VERIFY_OPTIONAL ); + break; + } + + if ( is_server && lo->ldo_tls_dhfile ) { + Debug1 (LDAP_DEBUG_ANY, "tlsmt_ctx_init DH params from file is not supported by MbedTLS backend, ignore setting %s\n", lo->ldo_tls_dhfile); + } + + return 0; +} + +static tls_session * +tlsmt_session_new( tls_ctx *ctx, int is_server ) +{ + tlsmt_ctx *c = (tlsmt_ctx *)ctx; + tlsmt_session *session; + + session = ber_memcalloc ( 1, sizeof (*session) ); + if ( !session ) + return NULL; + + session->config = c; + + mbedtls_ssl_init(&(session->ssl_ctx)); + mbedtls_ssl_setup(&(session->ssl_ctx), &session->config->ssl_config); + + return (tls_session *)session; +} + +static int +tlsmt_session_accept( tls_session *sess ) +{ + tlsmt_session *s = (tlsmt_session *)sess; + + int ret; + do { + ret = mbedtls_ssl_handshake( &(s->ssl_ctx) ); + } while (ret!=0 && (ret== MBEDTLS_ERR_SSL_WANT_READ || ret==MBEDTLS_ERR_SSL_WANT_WRITE)); + + return ret; +} + +static int +tlsmt_session_connect( LDAP *ld, tls_session *sess, const char *name_in ) +{ + tlsmt_session *s = (tlsmt_session *)sess; + if (name_in) { + int ret = mbedtls_ssl_set_hostname( &(s->ssl_ctx), name_in ); + if ( ret != 0 ) { + return ret; + } + } + + return tlsmt_session_accept(sess); +} + +static int +tlsmt_session_upflags( Sockbuf *sb, tls_session *sess, int rc ) +{ + if (rc == MBEDTLS_ERR_SSL_WANT_READ) { + sb->sb_trans_needs_read = 1; + return 1; + + } else if (rc == MBEDTLS_ERR_SSL_WANT_WRITE) { + sb->sb_trans_needs_write = 1; + return 1; + } + return 0; +} + +static char * +tlsmt_session_errmsg( tls_session *sess, int rc, char *buf, size_t len ) +{ + if ( rc ) { + mbedtls_strerror(rc, buf, len); + return buf; + } + return NULL; +} + +static int +tlsmt_session_my_dn( tls_session *sess, struct berval *der_dn ) +{ + // Session cannot give us our own certificate but it is stored in the config context + tlsmt_session *s = (tlsmt_session *)sess; + + der_dn->bv_len = s->config->own_cert.subject_raw.len; + der_dn->bv_val = s->config->own_cert.subject_raw.p; + + return 0; +} + +static int +tlsmt_session_peer_dn( tls_session *sess, struct berval *der_dn ) +{ + tlsmt_session *s = (tlsmt_session *)sess; + const mbedtls_x509_crt* peer_cert = mbedtls_ssl_get_peer_cert( &s->ssl_ctx ); + + if ( peer_cert == NULL ) { + + return LDAP_INVALID_CREDENTIALS; + } + + der_dn->bv_len = peer_cert->subject_raw.len; + der_dn->bv_val = peer_cert->subject_raw.p; + + return 0; +} + +/* what kind of hostname were we given? */ +#define IS_DNS 0 +#define IS_IP4 1 +#define IS_IP6 2 + +static int +tlsmt_session_chkhost( LDAP *ld, tls_session *sess, const char *name_in ) +{ + tlsmt_session *s = (tlsmt_session *)sess; + int i, ret = LDAP_LOCAL_ERROR; + int chkSAN = ld->ld_options.ldo_tls_require_san, gotSAN = 0; + const char *name; + char *ptr; + char *domain = NULL; + int len1 = 0, len2 = 0; + int ntype = IS_DNS, nlen; +#ifdef LDAP_PF_INET6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif + + if( ldap_int_hostname && + ( !name_in || !strcasecmp( name_in, "localhost" ) ) ) + { + name = ldap_int_hostname; + } else { + name = name_in; + } + nlen = strlen(name); + + const mbedtls_x509_crt* x = mbedtls_ssl_get_peer_cert( &s->ssl_ctx ); + if (!x) { + Debug0( LDAP_DEBUG_ANY, + "TLS: unable to get peer certificate.\n" ); + /* If this was a fatal condition, things would have + * aborted long before now. + */ + return LDAP_SUCCESS; + } + +#ifdef LDAP_PF_INET6 + if (inet_pton(AF_INET6, name, &addr)) { + ntype = IS_IP6; + } else +#endif + if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) { + if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4; + } + + if (ntype == IS_DNS) { + len1 = strlen(name); + domain = strchr(name, '.'); + if (domain) { + len2 = len1 - (domain-name); + } + } + +#if MBEDTLS_VERSION_NUMBER < 0x03000000 + if ( chkSAN && ( ret != LDAP_SUCCESS ) && ( x->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) ) { +#else + if ( chkSAN && ( ret != LDAP_SUCCESS ) && ( mbedtls_x509_crt_has_ext_type(x, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) != 0 ) ) { +#endif + mbedtls_x509_sequence *SANs = (mbedtls_x509_sequence *)&x->subject_alt_names; + while ( SANs != NULL && ret != LDAP_SUCCESS ) { + gotSAN = 1; + const mbedtls_x509_buf *san_buf = &SANs->buf; + /* mbedtls does not support SAN ip address type, so parse it here instead of using x509_crt_check_san */ + switch ( san_buf->tag & ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK )) { + /* DNS type */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ) : + { + /* Is this an exact match? */ + if ((len1 == san_buf->len) && !strncasecmp(name, san_buf->p, len1)) { + ret = LDAP_SUCCESS; + } + + /* Is this a wildcard match? */ + if (domain && (san_buf->p[0] == '*') && (san_buf->p[1] == '.') && + (len2 == san_buf->len-1) && !strncasecmp(domain, (san_buf->p)+1, len2)) + { + ret = LDAP_SUCCESS; + } + } + break; + /* IPADDRESS type */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS ) : + { + + if ( + (ntype == IS_IP4 && san_buf->len == sizeof(struct in_addr)) +#ifdef LDAP_PF_INET6 + || (ntype == IS_IP6 && san_buf->len == sizeof(struct in6_addr)) +#endif + ) { + if (!memcmp(san_buf->p, &addr, san_buf->len)) { + ret = LDAP_SUCCESS; + } + } + } + break; + default: + Debug0(LDAP_DEBUG_ANY, "Unsupported SAN type. Only DNS and IP ADDRESS are supported"); + } + + SANs = SANs->next; + } + } + + if (ret != LDAP_SUCCESS && chkSAN) { + switch(chkSAN) { + case LDAP_OPT_X_TLS_DEMAND: + case LDAP_OPT_X_TLS_HARD: + if (!gotSAN) { + Debug0( LDAP_DEBUG_ANY, + "TLS: unable to get subjectAltName from peer certificate.\n" ); + ret = LDAP_CONNECT_ERROR; + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + } + ld->ld_error = LDAP_STRDUP( + _("TLS: unable to get subjectAltName from peer certificate")); + goto done; + } + /* FALLTHRU */ + case LDAP_OPT_X_TLS_TRY: + if (gotSAN) { + Debug1( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match " + "subjectAltName in certificate.\n", + name ); + ret = LDAP_CONNECT_ERROR; + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + } + ld->ld_error = LDAP_STRDUP( + _("TLS: hostname does not match subjectAltName in peer certificate")); + goto done; + } + break; + case LDAP_OPT_X_TLS_ALLOW: + break; + } + } + + if (ret != LDAP_SUCCESS) { + /* find the last CN */ + const mbedtls_x509_name *subject; + for( subject = &x->subject; subject != NULL && ret != LDAP_SUCCESS; subject = subject->next ) { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &subject->oid ) == 0 ) { + const mbedtls_x509_buf *cn=&subject->val; + /* Is this an exact match? */ + if ((len1 == cn->len) && !strncasecmp(name, cn->p, len1)) { + ret = LDAP_SUCCESS; + } + + /* Is this a wildcard match? */ + if (domain && (cn->p[0] == '*') && (cn->p[1] == '.') && + (len2 == cn->len-1) && !strncasecmp(domain, (cn->p)+1, len2)) + { + ret = LDAP_SUCCESS; + } + } + } + } +done: + return ret; +} + +static int +tlsmt_session_strength( tls_session *sess ) +{ + tlsmt_session *s = (tlsmt_session *)sess; +#if MBEDTLS_VERSION_NUMBER < 0x03000000 + const mbedtls_ssl_ciphersuite_t *currentCipherSuite = mbedtls_ssl_ciphersuite_from_string( mbedtls_ssl_get_ciphersuite( &s->ssl_ctx ) ); + if (currentCipherSuite == NULL) return 0; + + return ( ( mbedtls_cipher_info_from_type( currentCipherSuite->cipher )->key_bitlen ) ); +#else /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ + const mbedtls_ssl_ciphersuite_t *currentCipherSuite = mbedtls_ssl_ciphersuite_from_id( mbedtls_ssl_get_ciphersuite_id_from_ssl( &s->ssl_ctx ) ); + if (currentCipherSuite == NULL) return 0; + + return ( ( mbedtls_ssl_ciphersuite_get_cipher_key_bitlen( currentCipherSuite ) ) ); +#endif /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ +} + +static int +tlsmt_session_unique( tls_session *sess, struct berval *buf, int is_server) +{ + Debug0(LDAP_DEBUG_ANY, "tlsmt_session_unique channel binding using unique is not available with MbedTLS backend\n"); + + return 0; +} + +static int +tlsmt_session_endpoint( tls_session *sess, struct berval *buf, int is_server ) +{ + tlsmt_session *s = (tlsmt_session *)sess; + + const mbedtls_x509_crt* cert = NULL; + + /* get server certificate */ + if ( is_server ) { + cert = &s->config->own_cert; + } else { + cert = mbedtls_ssl_get_peer_cert( &s->ssl_ctx ); + } +#if MBEDTLS_VERSION_NUMBER < 0x03000000 + mbedtls_md_type_t mdt = cert->sig_md; +#else + mbedtls_md_type_t mdt; + mbedtls_pk_type_t pk; + mbedtls_oid_get_sig_alg(&(cert->sig_oid), &mdt, &pk); +#endif + + /* RFC 5929 */ + switch (mdt) { + case MBEDTLS_MD_NONE: +#if MBEDTLS_VERSION_NUMBER < 0x03000000 + case MBEDTLS_MD_MD2: + case MBEDTLS_MD_MD4: +#endif + case MBEDTLS_MD_MD5: + case MBEDTLS_MD_SHA1: + mdt = MBEDTLS_MD_SHA256; + } + + const mbedtls_md_info_t *md = mbedtls_md_info_from_type(mdt); + + int md_len = mbedtls_md_get_size(md); + if ( md_len > buf->bv_len) { + return 0; + } + + if ( mbedtls_md( md, cert->raw.p, cert->raw.len, buf->bv_val ) != 0 ) { + return 0; + } + buf->bv_len = md_len; + + return md_len; +} + +static const char * +tlsmt_session_version( tls_session *sess ) +{ + tlsmt_session *s = (tlsmt_session *)sess; + return mbedtls_ssl_get_version( &s->ssl_ctx ); +} + +static const char * +tlsmt_session_cipher( tls_session *sess ) +{ + tlsmt_session *s = (tlsmt_session *)sess; + return mbedtls_ssl_get_ciphersuite( &s->ssl_ctx ); +} + +static int +tlsmt_session_peercert( tls_session *sess, struct berval *der ) +{ + tlsmt_session *s = (tlsmt_session *)sess; + const mbedtls_x509_crt* peer_cert = mbedtls_ssl_get_peer_cert( &s->ssl_ctx ); + + if ( peer_cert == NULL ) { + return -1; + } + + der->bv_len = peer_cert->raw.len; + der->bv_val = LDAP_MALLOC( der->bv_len ); + if (!der->bv_val) + return -1; + memcpy(der->bv_val, peer_cert->raw.p, der->bv_len); + return 0; +} + +static int +tlsmt_session_pinning( LDAP *ld, tls_session *sess, char *hashalg, struct berval *hash ) +{ + int ret; + tlsmt_session *s = (tlsmt_session *)sess; + const mbedtls_x509_crt* peer_cert = mbedtls_ssl_get_peer_cert(&s->ssl_ctx); + + if (peer_cert == NULL) { + return -1; + } + const mbedtls_md_info_t *mbedtls_hash; + if ( hashalg ) { + // mbedtls hash algo parser requires all uppercase characters in algo name + size_t hashalg_len = strlen(hashalg); + char *hashalgUpper = ber_memcalloc ( 1, hashalg_len + 1 ); + for (int i=0; ipk; + size_t pk_size = mbedtls_pk_get_len( pk ); + + unsigned char *der_pk = ber_memcalloc ( 1, 2*pk_size ); +#if MBEDTLS_VERSION_NUMBER < 0x03000000 + int der_pk_len = mbedtls_pk_write_pubkey_der( (mbedtls_pk_context *)pk, der_pk, pk_size*2 ); +#else + int der_pk_len = mbedtls_pk_write_pubkey_der( pk, der_pk, pk_size*2 ); +#endif + + unsigned char *digest[MBEDTLS_MD_MAX_SIZE]; + struct berval keyhash; + + if ( hashalg ) { + keyhash.bv_len = mbedtls_md_get_size(mbedtls_hash); + keyhash.bv_val = (char *)digest; + mbedtls_md(mbedtls_hash, der_pk+2*pk_size-der_pk_len, der_pk_len, keyhash.bv_val ); + } else { + keyhash.bv_len = der_pk_len; + keyhash.bv_val = der_pk+2*pk_size-der_pk_len; + } + ber_memfree(der_pk); + + if ( ber_bvcmp( hash, &keyhash ) ) { + ret = LDAP_CONNECT_ERROR; + Debug0( LDAP_DEBUG_ANY, "tlsmt_session_pinning: " + "public key hash does not match provided pin.\n" ); + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + } + ld->ld_error = LDAP_STRDUP( + _("TLS: public key hash does not match provided pin")); + } else { + ret = LDAP_SUCCESS; + } + + return ret; +} + +/* + * TLS support for LBER Sockbufs + */ + +struct tls_data { + tlsmt_session *session; + Sockbuf_IO_Desc *sbiod; +}; + +static int +tlsmt_read ( void *ptr, unsigned char *buf, size_t len ) +{ + struct tls_data *p; + + if ( buf == NULL || len <= 0 ) return 0; + + p = (struct tls_data *)ptr; + + if ( p == NULL || p->sbiod == NULL ) { + return 0; + } + + int ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len ); + + if ( ret < 0 ) { + int err = sock_errno(); + if ( err == EAGAIN || err == EWOULDBLOCK ) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + } + + return ret; +} + +static int +tlsmt_write( void *ptr, const unsigned char *buf, size_t len ) +{ + struct tls_data *p; + + if ( buf == NULL || len <= 0 ) return 0; + + p = (struct tls_data *)ptr; + + if ( p == NULL || p->sbiod == NULL ) { + return 0; + } + + int ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len ); + + if ( ret < 0 ) { + int err = sock_errno(); + if ( err == EAGAIN || err == EWOULDBLOCK ) { + + return MBEDTLS_ERR_SSL_WANT_WRITE; + } + } + + return ret; +} + +static int +tlsmt_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + struct tls_data *p; + tlsmt_session *session = (tlsmt_session *) arg; + + assert( sbiod != NULL ); + + p = LBER_MALLOC( sizeof( *p ) ); + if ( p == NULL ) { + return -1; + } + mbedtls_ssl_set_bio(&(session->ssl_ctx), p, tlsmt_write, tlsmt_read, NULL); + + p->session = session; + p->sbiod = sbiod; + sbiod->sbiod_pvt = p; + + return 0; +} + +static int +tlsmt_sb_remove( Sockbuf_IO_Desc *sbiod ) +{ + struct tls_data *p; + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + p = (struct tls_data *)sbiod->sbiod_pvt; + + mbedtls_ssl_free( &p->session->ssl_ctx ); + LBER_FREE( p->session ); + LBER_FREE( sbiod->sbiod_pvt ); + sbiod->sbiod_pvt = NULL; + return 0; +} + +static int +tlsmt_sb_close( Sockbuf_IO_Desc *sbiod ) +{ + struct tls_data *p; + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + p = (struct tls_data *)sbiod->sbiod_pvt; + + int ret = MBEDTLS_ERR_SSL_WANT_WRITE; + do { ret = mbedtls_ssl_close_notify( &(p->session->ssl_ctx) ); } + while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + return 0; +} + +static int +tlsmt_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + struct tls_data *p; + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + p = (struct tls_data *)sbiod->sbiod_pvt; + + if ( opt == LBER_SB_OPT_GET_SSL ) { + *((tlsmt_session **)arg) = p->session; + return 1; + + } else if ( opt == LBER_SB_OPT_DATA_READY ) { + return mbedtls_ssl_check_pending( &(p->session->ssl_ctx) ); + } + + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +static ber_slen_t +tlsmt_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct tls_data *p; + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + p = (struct tls_data *)sbiod->sbiod_pvt; + + int ret = mbedtls_ssl_read( &(p->session->ssl_ctx), buf, len); + + if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) { + sbiod->sbiod_sb->sb_trans_needs_read = 1; + sock_errset(EWOULDBLOCK); + return 0; + } + else { + sbiod->sbiod_sb->sb_trans_needs_read = 0; + } + + return ret; +} + +static ber_slen_t +tlsmt_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct tls_data *p; + assert( sbiod != NULL ); + assert( sbiod->sbiod_pvt != NULL ); + p = (struct tls_data *)sbiod->sbiod_pvt; + + int ret = mbedtls_ssl_write( &(p->session->ssl_ctx), buf, len); + + if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) { + sbiod->sbiod_sb->sb_trans_needs_write = 1; + sock_errset(EWOULDBLOCK); + return 0; + } + else { + sbiod->sbiod_sb->sb_trans_needs_write = 0; + } + return ret; +} + +static Sockbuf_IO tlsmt_sbio = +{ + tlsmt_sb_setup, /* sbi_setup */ + tlsmt_sb_remove, /* sbi_remove */ + tlsmt_sb_ctrl, /* sbi_ctrl */ + tlsmt_sb_read, /* sbi_read */ + tlsmt_sb_write, /* sbi_write */ + tlsmt_sb_close /* sbi_close */ +}; + +tls_impl ldap_int_tls_impl = { + "MbedTLS", + + tlsmt_init, + tlsmt_destroy, + + tlsmt_ctx_new, + tlsmt_ctx_ref, + tlsmt_ctx_free, + tlsmt_ctx_init, + + tlsmt_session_new, + tlsmt_session_connect, + tlsmt_session_accept, + tlsmt_session_upflags, + tlsmt_session_errmsg, + tlsmt_session_my_dn, + tlsmt_session_peer_dn, + tlsmt_session_chkhost, + tlsmt_session_strength, + tlsmt_session_unique, + tlsmt_session_endpoint, + tlsmt_session_version, + tlsmt_session_cipher, + tlsmt_session_peercert, + tlsmt_session_pinning, + + &tlsmt_sbio, + +#ifdef LDAP_R_COMPILE + tlsmt_thr_init, +#else + NULL, +#endif + + 0 +}; + +#endif /* HAVE_MBEDTLS */ diff --git a/servers/slapd/overlays/otp.c b/servers/slapd/overlays/otp.c index 590ee5022d..b9d6e37a97 100644 --- a/servers/slapd/overlays/otp.c +++ b/servers/slapd/overlays/otp.c @@ -37,6 +37,7 @@ /* include socket.h to get sys/types.h and/or winsock2.h */ #include +#include "slap.h" #if HAVE_OPENSSL #include #include @@ -124,11 +125,45 @@ static EVP_MAC *evp_mac; hmac_digest( &ctx.outer, &ctx.inner, &ctx.state, h, h->digest_size, dig ); \ dlen = h->digest_size +#elif HAVE_MBEDTLS + +#include "mbedtls/md.h" + +#define TOTP_SHA512_DIGEST_LENGTH MBEDTLS_MD_MAX_SIZE +#define TOTP_SHA1 mbedtls_md_info_from_type(MBEDTLS_MD_SHA1) +#define TOTP_SHA224 mbedtls_md_info_from_type(MBEDTLS_MD_SHA224) +#define TOTP_SHA256 mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) +#define TOTP_SHA384 mbedtls_md_info_from_type(MBEDTLS_MD_SHA384) +#define TOTP_SHA512 mbedtls_md_info_from_type(MBEDTLS_MD_SHA512) + +static mbedtls_md_context_t * +HMAC_CTX_new( void ) +{ + mbedtls_md_context_t *ctx = ch_malloc( sizeof(mbedtls_md_context_t) ); + if ( ctx != NULL ) { + mbedtls_md_init( ctx ); + } + return ctx; +} + +#define TOTP_HMAC_CTX mbedtls_md_context_t* +#define HMAC_setup( ctx, key, len, hash ) \ + ctx = HMAC_CTX_new(); \ + mbedtls_md_setup(ctx, (const mbedtls_md_info_t *)hash, 1); \ + mbedtls_md_hmac_starts(ctx, key, len) + +#define HMAC_crunch( ctx, buf, len ) mbedtls_md_hmac_update( ctx, buf, len ) + +#define HMAC_finish( ctx, dig, dlen ) \ + mbedtls_md_hmac_finish(ctx, dig); \ + dlen = mbedtls_md_get_size((const mbedtls_md_info_t *)hash); \ + mbedtls_md_free(ctx); \ + ch_free(ctx) + #else #error Unsupported crypto backend. #endif -#include "slap.h" #include "slap-config.h" /* Schema from OATH-LDAP project by Michael Ströder */ diff --git a/tests/scripts/test067-tls b/tests/scripts/test067-tls index cd99fcfa06..7d1e4c1fe2 100755 --- a/tests/scripts/test067-tls +++ b/tests/scripts/test067-tls @@ -110,7 +110,7 @@ else echo "success" fi -if test $WITH_TLS_TYPE = openssl ; then +if [ $WITH_TLS_TYPE = openssl ] || [ $WITH_TLS_TYPE = mbedtls ]; then echo -n "Using ldapsearch with startTLS and specific protocol version...." $LDAPSEARCH -o tls_cacert=$TESTDIR/tls/ca/certs/testsuiteCA.crt -o tls_reqcert=hard -o tls_protocol_min=3.3 -ZZ -b "" -s base -H $URIP1 \ '@extensibleObject' > $SEARCHOUT 2>&1 diff --git a/tests/scripts/test077-sasl-gssapi b/tests/scripts/test077-sasl-gssapi index 4d4e260c8f..c7698c09e7 100755 --- a/tests/scripts/test077-sasl-gssapi +++ b/tests/scripts/test077-sasl-gssapi @@ -194,10 +194,15 @@ EOF for icb in "none" "tls-unique" "tls-endpoint" ; do # The gnutls implementation of "tls-unique" seems broken + # mbedtls does not support "tls-unique" if test $icb = "tls-unique" -o $acb = "tls-unique" ; then if test $WITH_TLS_TYPE = gnutls ; then continue fi + if test $WITH_TLS_TYPE = mbedtls ; then + echo "mbedtls backend does not support TLS-unique binding, skip" + continue + fi fi fail="no" -- 2.47.3