From cf1558659be55a87acdd50bfb01366b4fba0fc2a Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sat, 24 Jan 2009 03:34:49 +0000 Subject: [PATCH] ITS#5655 TLS_PROTOCOL_MIN from Philip Guenther --- include/ldap.h | 10 +++++++++- libraries/libldap/init.c | 1 + libraries/libldap/ldap-int.h | 2 ++ libraries/libldap/tls.c | 31 ++++++++++++++++++++++++++++++- servers/slapd/bconfig.c | 10 ++++++++++ servers/slapd/config.c | 25 +++++++++++++++++++++++++ servers/slapd/slap.h | 1 + 7 files changed, 78 insertions(+), 2 deletions(-) diff --git a/include/ldap.h b/include/ldap.h index 3dff72ad68..19e25fb7a7 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -144,7 +144,7 @@ LDAP_BEGIN_DECL #define LDAP_OPT_X_TLS_CERTFILE 0x6004 #define LDAP_OPT_X_TLS_KEYFILE 0x6005 #define LDAP_OPT_X_TLS_REQUIRE_CERT 0x6006 -/* #define LDAP_OPT_X_TLS_PROTOCOL 0x6007 */ +#define LDAP_OPT_X_TLS_PROTOCOL_MIN 0x6007 #define LDAP_OPT_X_TLS_CIPHER_SUITE 0x6008 #define LDAP_OPT_X_TLS_RANDOM_FILE 0x6009 #define LDAP_OPT_X_TLS_SSL_CTX 0x600a /* OpenSSL SSL* */ @@ -165,6 +165,14 @@ 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 */ +#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) +#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_0 ((3 << 8) + 1) +#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_1 ((3 << 8) + 2) +#define LDAP_OPT_X_TLS_PROTOCOL_TLS1_2 ((3 << 8) + 3) + /* OpenLDAP SASL options */ #define LDAP_OPT_X_SASL_MECH 0x6100 #define LDAP_OPT_X_SASL_REALM 0x6101 diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index eb5ff66f59..8cf2530b39 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -123,6 +123,7 @@ static const struct ol_attribute { {0, ATTR_TLS, "TLS_REQCERT", NULL, LDAP_OPT_X_TLS_REQUIRE_CERT}, {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}, #ifdef HAVE_OPENSSL_CRL {0, ATTR_TLS, "TLS_CRLCHECK", NULL, LDAP_OPT_X_TLS_CRLCHECK}, diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index f3d64a9239..6b6cf08af4 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -157,6 +157,7 @@ struct ldaptls { char *lt_ciphersuite; char *lt_crlfile; char *lt_randfile; /* OpenSSL only */ + int lt_protocol_min; }; #endif @@ -204,6 +205,7 @@ struct ldapoptions { #define ldo_tls_cacertfile ldo_tls_info.lt_cacertfile #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_crlfile ldo_tls_info.lt_crlfile #define ldo_tls_randfile ldo_tls_info.lt_randfile int ldo_tls_mode; diff --git a/libraries/libldap/tls.c b/libraries/libldap/tls.c index 3579351bd1..31504ec282 100644 --- a/libraries/libldap/tls.c +++ b/libraries/libldap/tls.c @@ -772,6 +772,12 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server ) (const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 ); } + if (lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3) + SSL_CTX_set_options( lo->ldo_tls_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( lo->ldo_tls_ctx, SSL_OP_NO_SSLv2 ); + if ( lo->ldo_tls_ciphersuite && !SSL_CTX_set_cipher_list( lo->ldo_tls_ctx, ciphersuite ) ) { @@ -2146,6 +2152,23 @@ ldap_int_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_MIN: { + char *next; + long l; + l = strtol( arg, &next, 10 ); + if ( l < 0 || l > 0xff || next == arg || + ( *next != '\0' && *next != '.' ) ) + return -1; + i = l << 8; + if (*next == '.') { + arg = next + 1; + l = strtol( arg, &next, 10 ); + if ( l < 0 || l > 0xff || next == arg || *next != '\0' ) + return -1; + i += l; + } + return ldap_pvt_tls_set_option( ld, option, &i ); + } #ifdef HAVE_OPENSSL_CRL case LDAP_OPT_X_TLS_CRLCHECK: i = -1; @@ -2235,6 +2258,9 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) *(char **)arg = lo->ldo_tls_ciphersuite ? LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL; break; + case LDAP_OPT_X_TLS_PROTOCOL_MIN: + *(int *)arg = lo->ldo_tls_protocol_min; + break; case LDAP_OPT_X_TLS_RANDOM_FILE: #ifdef HAVE_OPENSSL *(char **)arg = tls_opt_randfile ? @@ -2373,7 +2399,10 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) if ( lo->ldo_tls_ciphersuite ) LDAP_FREE( lo->ldo_tls_ciphersuite ); lo->ldo_tls_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; - + case LDAP_OPT_X_TLS_PROTOCOL_MIN: + if ( !arg ) return -1; + lo->ldo_tls_protocol_min = * (int *) arg; + return 0; case LDAP_OPT_X_TLS_RANDOM_FILE: if ( ld != NULL ) return -1; diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index b7237c7c0f..2d23b9e2a3 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -145,6 +145,7 @@ enum { CFG_DATABASE, CFG_TLS_RAND, CFG_TLS_CIPHER, + CFG_TLS_PROTOCOL_MIN, CFG_TLS_CERT_FILE, CFG_TLS_CERT_KEY, CFG_TLS_CA_PATH, @@ -685,6 +686,14 @@ static ConfigTable config_back_cf_table[] = { #endif "( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' " "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, + { "TLSProtocolMin", NULL, 0, 0, 0, +#ifdef HAVE_TLS + CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC, &config_tls_config, +#else + ARG_IGNORED, NULL, +#endif + "( OLcfgGlAt:85 NAME 'olcTLSProtocolMin' " + "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, { "tool-threads", "count", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_TTHREADS, &config_generic, "( OLcfgGlAt:80 NAME 'olcToolThreads' " "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, @@ -3207,6 +3216,7 @@ config_tls_config(ConfigArgs *c) { switch(c->type) { case CFG_TLS_CRLCHECK: flag = LDAP_OPT_X_TLS_CRLCHECK; break; case CFG_TLS_VERIFY: flag = LDAP_OPT_X_TLS_REQUIRE_CERT; break; + case CFG_TLS_PROTOCOL_MIN: flag = LDAP_OPT_X_TLS_PROTOCOL_MIN; break; default: Debug(LDAP_DEBUG_ANY, "%s: " "unknown tls_option <0x%x>\n", diff --git a/servers/slapd/config.c b/servers/slapd/config.c index de0e5badc2..16e335e404 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -1200,6 +1200,7 @@ static slap_cf_aux_table bindkey[] = { { BER_BVC("tls_cacertdir="), offsetof(slap_bindconf, sb_tls_cacertdir), 's', 1, NULL }, { BER_BVC("tls_reqcert="), offsetof(slap_bindconf, sb_tls_reqcert), 's', 1, NULL }, { BER_BVC("tls_cipher_suite="), offsetof(slap_bindconf, sb_tls_cipher_suite), 's', 1, NULL }, + { BER_BVC("tls_protocol_min="), offsetof(slap_bindconf, sb_tls_protocol_min), 's', 1, NULL }, #ifdef HAVE_OPENSSL_CRL { BER_BVC("tls_crlcheck="), offsetof(slap_bindconf, sb_tls_crlcheck), 's', 1, NULL }, #endif @@ -1408,6 +1409,14 @@ slap_tls_get_config( LDAP *ld, int opt, char **val ) case LDAP_OPT_X_TLS_REQUIRE_CERT: keys = vfykeys; break; + case LDAP_OPT_X_TLS_PROTOCOL_MIN: { + char buf[8]; + ldap_pvt_tls_get_option( ld, opt, &ival ); + snprintf( buf, sizeof( buf ), "%d.%d", + ( ival >> 8 ) & 0xff, ival & 0xff ); + *val = ch_strdup( buf ); + return 0; + } default: return -1; } @@ -1519,6 +1528,10 @@ void bindconf_free( slap_bindconf *bc ) { ch_free( bc->sb_tls_cipher_suite ); bc->sb_tls_cipher_suite = NULL; } + if ( bc->sb_tls_protocol_min ) { + ch_free( bc->sb_tls_protocol_min ); + bc->sb_tls_protocol_min = NULL; + } #ifdef HAVE_OPENSSL_CRL if ( bc->sb_tls_crlcheck ) { ch_free( bc->sb_tls_crlcheck ); @@ -1570,6 +1583,7 @@ static struct { { "tls_cacert", offsetof(slap_bindconf, sb_tls_cacert), LDAP_OPT_X_TLS_CACERTFILE }, { "tls_cacertdir", offsetof(slap_bindconf, sb_tls_cacertdir), LDAP_OPT_X_TLS_CACERTDIR }, { "tls_cipher_suite", offsetof(slap_bindconf, sb_tls_cipher_suite), LDAP_OPT_X_TLS_CIPHER_SUITE }, + { "tls_protocol_min", offsetof(slap_bindconf, sb_tls_protocol_min), LDAP_OPT_X_TLS_PROTOCOL_MIN }, {0, 0} }; @@ -1604,6 +1618,17 @@ int bindconf_tls_set( slap_bindconf *bc, LDAP *ld ) } else newctx = 1; } + if ( bc->sb_tls_protocol_min ) { + rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_PROTOCOL_MIN, + bc->sb_tls_protocol_min ); + if ( rc ) { + Debug( LDAP_DEBUG_ANY, + "bindconf_tls_set: failed to set tls_protocol_min to %s\n", + bc->sb_tls_protocol_min, 0, 0 ); + res = -1; + } else + newctx = 1; + } #ifdef HAVE_OPENSSL_CRL if ( bc->sb_tls_crlcheck ) { rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_CRLCHECK, diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 6bd3af7c48..2439156a48 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1607,6 +1607,7 @@ typedef struct slap_bindconf { char *sb_tls_cacertdir; char *sb_tls_reqcert; char *sb_tls_cipher_suite; + char *sb_tls_protocol_min; #ifdef HAVE_OPENSSL_CRL char *sb_tls_crlcheck; #endif -- 2.39.5