From 2a3b64f4e606be0fa1d9adbdb27ebb8e8d2d7b65 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 9 Apr 2021 18:09:15 +0100 Subject: [PATCH] ITS#9518 add LDAP_OPT_X_TLS_PROTOCOL_MAX option OpenSSL only --- doc/man/man3/ldap_get_option.3 | 9 +++++ include/ldap.h | 3 +- libraries/libldap/init.c | 1 + libraries/libldap/ldap-int.h | 5 ++- libraries/libldap/tls2.c | 8 +++++ libraries/libldap/tls_o.c | 64 ++++++++++++++++++++++------------ 6 files changed, 65 insertions(+), 25 deletions(-) diff --git a/doc/man/man3/ldap_get_option.3 b/doc/man/man3/ldap_get_option.3 index 023ef4be49..9675520ab4 100644 --- a/doc/man/man3/ldap_get_option.3 +++ b/doc/man/man3/ldap_get_option.3 @@ -800,6 +800,15 @@ must be and the data it returns needs to be freed by the caller using .BR ldap_memfree (3). .TP +.B LDAP_OPT_X_TLS_PROTOCOL_MAX +Sets/gets the maximum protocol version. +.BR invalue +must be +.BR "const int *" ; +.BR outvalue +must be +.BR "int *" . +.TP .B LDAP_OPT_X_TLS_PROTOCOL_MIN Sets/gets the minimum protocol version. .BR invalue diff --git a/include/ldap.h b/include/ldap.h index aca5790761..fcea81d9f3 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -162,6 +162,7 @@ LDAP_BEGIN_DECL #define LDAP_OPT_X_TLS_KEY 0x6018 #define LDAP_OPT_X_TLS_PEERKEY_HASH 0x6019 #define LDAP_OPT_X_TLS_REQUIRE_SAN 0x601a +#define LDAP_OPT_X_TLS_PROTOCOL_MAX 0x601b #define LDAP_OPT_X_TLS_NEVER 0 #define LDAP_OPT_X_TLS_HARD 1 @@ -173,7 +174,7 @@ LDAP_BEGIN_DECL #define LDAP_OPT_X_TLS_CRL_PEER 1 #define LDAP_OPT_X_TLS_CRL_ALL 2 -/* for LDAP_OPT_X_TLS_PROTOCOL_MIN */ +/* for LDAP_OPT_X_TLS_PROTOCOL_MIN/MAX */ #define LDAP_OPT_X_TLS_PROTOCOL(maj,min) (((maj) << 8) + (min)) #define LDAP_OPT_X_TLS_PROTOCOL_SSL2 (2 << 8) #define LDAP_OPT_X_TLS_PROTOCOL_SSL3 (3 << 8) diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index ff9e5d49c2..b247327d57 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -129,6 +129,7 @@ static const struct ol_attribute { {0, ATTR_TLS, "TLS_RANDFILE", NULL, LDAP_OPT_X_TLS_RANDOM_FILE}, {0, ATTR_TLS, "TLS_CIPHER_SUITE", NULL, LDAP_OPT_X_TLS_CIPHER_SUITE}, {0, ATTR_TLS, "TLS_PROTOCOL_MIN", NULL, LDAP_OPT_X_TLS_PROTOCOL_MIN}, + {0, ATTR_TLS, "TLS_PROTOCOL_MAX", NULL, LDAP_OPT_X_TLS_PROTOCOL_MAX}, {0, ATTR_TLS, "TLS_PEERKEY_HASH", NULL, LDAP_OPT_X_TLS_PEERKEY_HASH}, {0, ATTR_TLS, "TLS_ECNAME", NULL, LDAP_OPT_X_TLS_ECNAME}, diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 06268a96f2..cbcbc1ae3d 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -187,6 +187,7 @@ struct ldaptls { char *lt_randfile; /* OpenSSL only */ char *lt_ecname; /* OpenSSL only */ int lt_protocol_min; + int lt_protocol_max; struct berval lt_cacert; struct berval lt_cert; struct berval lt_key; @@ -301,6 +302,7 @@ struct ldapoptions { #define ldo_tls_cacertdir ldo_tls_info.lt_cacertdir #define ldo_tls_ciphersuite ldo_tls_info.lt_ciphersuite #define ldo_tls_protocol_min ldo_tls_info.lt_protocol_min +#define ldo_tls_protocol_max ldo_tls_info.lt_protocol_max #define ldo_tls_crlfile ldo_tls_info.lt_crlfile #define ldo_tls_randfile ldo_tls_info.lt_randfile #define ldo_tls_cacert ldo_tls_info.lt_cacert @@ -313,7 +315,8 @@ struct ldapoptions { int ldo_tls_require_san; char *ldo_tls_pin_hashalg; struct berval ldo_tls_pin; -#define LDAP_LDO_TLS_NULLARG ,0,0,0,{0,0,0,0,0,0,0,0,0},0,0,0,0,0,0,{0,0} +#define LDAP_LDO_TLS_NULLARG ,0,0,0,{0,0,0,0,0,0,0,0,0,\ + LDAP_OPT_X_TLS_PROTOCOL(0,0), LDAP_OPT_X_TLS_PROTOCOL(255,255)},0,0,0,0,0,0,{0,0} #else #define LDAP_LDO_TLS_NULLARG #endif diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c index 539fbfa8fb..d76ac6adfc 100644 --- a/libraries/libldap/tls2.c +++ b/libraries/libldap/tls2.c @@ -615,6 +615,7 @@ ldap_pvt_tls_config( LDAP *ld, int option, const char *arg ) return ldap_pvt_tls_set_option( ld, option, &i ); } return -1; + case LDAP_OPT_X_TLS_PROTOCOL_MAX: case LDAP_OPT_X_TLS_PROTOCOL_MIN: { char *next; long l; @@ -734,6 +735,9 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) case LDAP_OPT_X_TLS_PROTOCOL_MIN: *(int *)arg = lo->ldo_tls_protocol_min; break; + case LDAP_OPT_X_TLS_PROTOCOL_MAX: + *(int *)arg = lo->ldo_tls_protocol_max; + break; case LDAP_OPT_X_TLS_RANDOM_FILE: *(char **)arg = lo->ldo_tls_randfile ? LDAP_STRDUP( lo->ldo_tls_randfile ) : NULL; @@ -961,6 +965,10 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) if ( !arg ) return -1; lo->ldo_tls_protocol_min = *(int *)arg; return 0; + case LDAP_OPT_X_TLS_PROTOCOL_MAX: + if ( !arg ) return -1; + lo->ldo_tls_protocol_max = *(int *)arg; + return 0; case LDAP_OPT_X_TLS_RANDOM_FILE: if ( ld != NULL ) return -1; diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c index 1d70f79f98..cf32140454 100644 --- a/libraries/libldap/tls_o.c +++ b/libraries/libldap/tls_o.c @@ -334,37 +334,55 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) (const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 ); } + if ( lo->ldo_tls_protocol_min ) { + int opt = 0; + if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) { + opt |= SSL_OP_NO_SSLv2; + SSL_CTX_clear_options( ctx, SSL_OP_NO_SSLv3 ); + } + if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) + opt |= SSL_OP_NO_SSLv3; #ifdef SSL_OP_NO_TLSv1 + if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0 ) + opt |= SSL_OP_NO_TLSv1; +#endif #ifdef SSL_OP_NO_TLSv1_1 + if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1 ) + opt |= SSL_OP_NO_TLSv1_1; +#endif #ifdef SSL_OP_NO_TLSv1_2 + if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2 ) + opt |= SSL_OP_NO_TLSv1_2; +#endif #ifdef SSL_OP_NO_TLSv1_3 - if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_3) - SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | - SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3 ); - else + if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_3 ) + opt |= SSL_OP_NO_TLSv1_3; #endif - if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2) - SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | - SSL_OP_NO_TLSv1_2 ); - else + if ( opt ) + SSL_CTX_set_options( ctx, opt ); + } + { + int opt = 0; +#ifdef SSL_OP_NO_TLSv1_3 + if ( lo->ldo_tls_protocol_max < LDAP_OPT_X_TLS_PROTOCOL_TLS1_3 ) + opt |= SSL_OP_NO_TLSv1_3; #endif - if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1) - SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 ); - else +#ifdef SSL_OP_NO_TLSv1_2 + if ( lo->ldo_tls_protocol_max < LDAP_OPT_X_TLS_PROTOCOL_TLS1_2 ) + opt |= SSL_OP_NO_TLSv1_2; #endif - if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0) - SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_NO_TLSv1); - else +#ifdef SSL_OP_NO_TLSv1_1 + if ( lo->ldo_tls_protocol_max < LDAP_OPT_X_TLS_PROTOCOL_TLS1_1 ) + opt |= SSL_OP_NO_TLSv1_1; #endif - if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) - SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 ); - else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) { - SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 ); - SSL_CTX_clear_options( ctx, SSL_OP_NO_SSLv3 ); +#ifdef SSL_OP_NO_TLSv1 + if ( lo->ldo_tls_protocol_max < LDAP_OPT_X_TLS_PROTOCOL_TLS1_0 ) + opt |= SSL_OP_NO_TLSv1; +#endif + if ( lo->ldo_tls_protocol_max < LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) + opt |= SSL_OP_NO_SSLv3; + if ( opt ) + SSL_CTX_set_options( ctx, opt ); } if ( lo->ldo_tls_ciphersuite ) {