Add/rename parameters that control TLS

This commit is contained in:
Denis Glazachev 2020-06-12 21:59:47 +04:00
parent 04f222f85b
commit 276fcd8903
4 changed files with 134 additions and 40 deletions

View File

@ -209,20 +209,29 @@
Specify 'no' for plain text (ldap://) protocol (not recommended). Specify 'no' for plain text (ldap://) protocol (not recommended).
Specify 'yes' for LDAP over SSL/TLS (ldaps://) protocol (recommended, the default). Specify 'yes' for LDAP over SSL/TLS (ldaps://) protocol (recommended, the default).
Specify 'starttls' for legacy StartTLS protocol (plain text (ldap://) protocol, upgraded to TLS). Specify 'starttls' for legacy StartTLS protocol (plain text (ldap://) protocol, upgraded to TLS).
tls_cert_verify - TLS peer certificate verification behavior. tls_minimum_protocol_version - the minimum protocol version of SSL/TLS.
Accepted values are: never, allow, try, demand. Accepted values are: 'ssl2', 'ssl3', 'tls1.0', 'tls1.1', 'tls1.2' (the default).
ca_cert_dir - path to CA certificates directory. tls_require_cert - SSL/TLS peer certificate verification behavior.
ca_cert_file - path to CA certificate file. Accepted values are: 'never', 'allow', 'try', 'demand' (the default).
Example: tls_cert_file - path to certificate file.
tls_key_file - path to certificate key file.
tls_ca_cert_file - path to CA certificate file.
tls_ca_cert_dir - path to the directory containing CA certificates.
tls_cipher_suite - allowed cipher suite.
Example:
<my_ldap_server> <my_ldap_server>
<host>localhost</host> <host>localhost</host>
<port>636</port> <port>636</port>
<auth_dn_prefix>cn=</auth_dn_prefix> <auth_dn_prefix>cn=</auth_dn_prefix>
<auth_dn_suffix>, ou=users, dc=example, dc=com</auth_dn_suffix> <auth_dn_suffix>, ou=users, dc=example, dc=com</auth_dn_suffix>
<enable_tls>yes</enable_tls> <enable_tls>yes</enable_tls>
<tls_cert_verify>demand</tls_cert_verify> <tls_minimum_protocol_version>tls1.2</tls_minimum_protocol_version>
<ca_cert_dir>/path/to/ca_cert_dir</ca_cert_dir> <tls_require_cert>demand</tls_require_cert>
<ca_cert_file>/path/to/ca_cert_file</ca_cert_file> <tls_cert_file>/path/to/tls_cert_file</tls_cert_file>
<tls_key_file>/path/to/tls_key_file</tls_key_file>
<tls_ca_cert_file>/path/to/tls_ca_cert_file</tls_ca_cert_file>
<tls_ca_cert_dir>/path/to/tls_ca_cert_dir</tls_ca_cert_dir>
<tls_cipher_suite>SECURE256:+SECURE128:-VERS-TLS-ALL:+VERS-TLS1.2:-RSA:-DHE-DSS:-CAMELLIA-128-CBC:-CAMELLIA-256-CBC</tls_cipher_suite>
</my_ldap_server> </my_ldap_server>
--> -->
</ldap_servers> </ldap_servers>

View File

@ -30,9 +30,13 @@ auto parseLDAPServer(const Poco::Util::AbstractConfiguration & config, const Str
const bool has_auth_dn_prefix = config.has(ldap_server_config + ".auth_dn_prefix"); const bool has_auth_dn_prefix = config.has(ldap_server_config + ".auth_dn_prefix");
const bool has_auth_dn_suffix = config.has(ldap_server_config + ".auth_dn_suffix"); const bool has_auth_dn_suffix = config.has(ldap_server_config + ".auth_dn_suffix");
const bool has_enable_tls = config.has(ldap_server_config + ".enable_tls"); const bool has_enable_tls = config.has(ldap_server_config + ".enable_tls");
const bool has_tls_cert_verify = config.has(ldap_server_config + ".tls_cert_verify"); const bool has_tls_minimum_protocol_version = config.has(ldap_server_config + ".tls_minimum_protocol_version");
const bool has_ca_cert_dir = config.has(ldap_server_config + ".ca_cert_dir"); const bool has_tls_require_cert = config.has(ldap_server_config + ".tls_require_cert");
const bool has_ca_cert_file = config.has(ldap_server_config + ".ca_cert_file"); const bool has_tls_cert_file = config.has(ldap_server_config + ".tls_cert_file");
const bool has_tls_key_file = config.has(ldap_server_config + ".tls_key_file");
const bool has_tls_ca_cert_file = config.has(ldap_server_config + ".tls_ca_cert_file");
const bool has_tls_ca_cert_dir = config.has(ldap_server_config + ".tls_ca_cert_dir");
const bool has_tls_cipher_suite = config.has(ldap_server_config + ".tls_cipher_suite");
if (!has_host) if (!has_host)
throw Exception("Missing 'host' entry", ErrorCodes::BAD_ARGUMENTS); throw Exception("Missing 'host' entry", ErrorCodes::BAD_ARGUMENTS);
@ -61,28 +65,56 @@ auto parseLDAPServer(const Poco::Util::AbstractConfiguration & config, const Str
params.enable_tls = LDAPServerParams::TLSEnable::NO; params.enable_tls = LDAPServerParams::TLSEnable::NO;
} }
if (has_tls_cert_verify) if (has_tls_minimum_protocol_version)
{ {
String tls_cert_verify_lc_str = config.getString(ldap_server_config + ".tls_cert_verify"); String tls_minimum_protocol_version_lc_str = config.getString(ldap_server_config + ".tls_minimum_protocol_version");
boost::to_lower(tls_cert_verify_lc_str); boost::to_lower(tls_minimum_protocol_version_lc_str);
if (tls_cert_verify_lc_str == "never") if (tls_minimum_protocol_version_lc_str == "ssl2")
params.tls_cert_verify = LDAPServerParams::TLSCertVerify::NEVER; params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::SSL2;
else if (tls_cert_verify_lc_str == "allow") else if (tls_minimum_protocol_version_lc_str == "ssl3")
params.tls_cert_verify = LDAPServerParams::TLSCertVerify::ALLOW; params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::SSL3;
else if (tls_cert_verify_lc_str == "try") else if (tls_minimum_protocol_version_lc_str == "tls1.0")
params.tls_cert_verify = LDAPServerParams::TLSCertVerify::TRY; params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::TLS1_0;
else if (tls_cert_verify_lc_str == "demand") else if (tls_minimum_protocol_version_lc_str == "tls1.1")
params.tls_cert_verify = LDAPServerParams::TLSCertVerify::DEMAND; params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::TLS1_1;
else if (tls_minimum_protocol_version_lc_str == "tls1.2")
params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::TLS1_2;
else else
throw Exception("Bad value for 'tls_cert_verify' entry, allowed values are: 'never', 'allow', 'try', 'demand'", ErrorCodes::BAD_ARGUMENTS); throw Exception("Bad value for 'tls_minimum_protocol_version' entry, allowed values are: 'ssl2', 'ssl3', 'tls1.0', 'tls1.1', 'tls1.2'", ErrorCodes::BAD_ARGUMENTS);
} }
if (has_ca_cert_dir) if (has_tls_require_cert)
params.ca_cert_dir = config.getString(ldap_server_config + ".ca_cert_dir"); {
String tls_require_cert_lc_str = config.getString(ldap_server_config + ".tls_require_cert");
boost::to_lower(tls_require_cert_lc_str);
if (has_ca_cert_file) if (tls_require_cert_lc_str == "never")
params.ca_cert_file = config.getString(ldap_server_config + ".ca_cert_file"); params.tls_require_cert = LDAPServerParams::TLSRequireCert::NEVER;
else if (tls_require_cert_lc_str == "allow")
params.tls_require_cert = LDAPServerParams::TLSRequireCert::ALLOW;
else if (tls_require_cert_lc_str == "try")
params.tls_require_cert = LDAPServerParams::TLSRequireCert::TRY;
else if (tls_require_cert_lc_str == "demand")
params.tls_require_cert = LDAPServerParams::TLSRequireCert::DEMAND;
else
throw Exception("Bad value for 'tls_require_cert' entry, allowed values are: 'never', 'allow', 'try', 'demand'", ErrorCodes::BAD_ARGUMENTS);
}
if (has_tls_cert_file)
params.tls_cert_file = config.getString(ldap_server_config + ".tls_cert_file");
if (has_tls_key_file)
params.tls_key_file = config.getString(ldap_server_config + ".tls_key_file");
if (has_tls_ca_cert_file)
params.tls_ca_cert_file = config.getString(ldap_server_config + ".tls_ca_cert_file");
if (has_tls_ca_cert_dir)
params.tls_ca_cert_dir = config.getString(ldap_server_config + ".tls_ca_cert_dir");
if (has_tls_cipher_suite)
params.tls_cipher_suite = config.getString(ldap_server_config + ".tls_cipher_suite");
if (has_port) if (has_port)
{ {

View File

@ -140,19 +140,23 @@ int LDAPClient::openConnection(const bool graceful_bind_failure)
diag(ldap_set_option(handle, LDAP_OPT_KEEPCONN, LDAP_OPT_ON)); diag(ldap_set_option(handle, LDAP_OPT_KEEPCONN, LDAP_OPT_ON));
#endif #endif
#ifdef LDAP_OPT_TIMEOUT
{ {
::timeval operation_timeout; ::timeval operation_timeout;
operation_timeout.tv_sec = params.operation_timeout.count(); operation_timeout.tv_sec = params.operation_timeout.count();
operation_timeout.tv_usec = 0; operation_timeout.tv_usec = 0;
diag(ldap_set_option(handle, LDAP_OPT_TIMEOUT, &operation_timeout)); diag(ldap_set_option(handle, LDAP_OPT_TIMEOUT, &operation_timeout));
} }
#endif
#ifdef LDAP_OPT_NETWORK_TIMEOUT
{ {
::timeval network_timeout; ::timeval network_timeout;
network_timeout.tv_sec = params.network_timeout.count(); network_timeout.tv_sec = params.network_timeout.count();
network_timeout.tv_usec = 0; network_timeout.tv_usec = 0;
diag(ldap_set_option(handle, LDAP_OPT_NETWORK_TIMEOUT, &network_timeout)); diag(ldap_set_option(handle, LDAP_OPT_NETWORK_TIMEOUT, &network_timeout));
} }
#endif
{ {
const int search_timeout = params.search_timeout.count(); const int search_timeout = params.search_timeout.count();
@ -164,23 +168,59 @@ int LDAPClient::openConnection(const bool graceful_bind_failure)
diag(ldap_set_option(handle, LDAP_OPT_SIZELIMIT, &size_limit)); diag(ldap_set_option(handle, LDAP_OPT_SIZELIMIT, &size_limit));
} }
#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
{ {
int value = 0; int value = 0;
switch (params.tls_cert_verify) switch (params.tls_minimum_protocol_version)
{ {
case LDAPServerParams::TLSCertVerify::NEVER: value = LDAP_OPT_X_TLS_NEVER; break; case LDAPServerParams::TLSProtocolVersion::SSL2: value = LDAP_OPT_X_TLS_PROTOCOL_SSL2; break;
case LDAPServerParams::TLSCertVerify::ALLOW: value = LDAP_OPT_X_TLS_ALLOW; break; case LDAPServerParams::TLSProtocolVersion::SSL3: value = LDAP_OPT_X_TLS_PROTOCOL_SSL3; break;
case LDAPServerParams::TLSCertVerify::TRY: value = LDAP_OPT_X_TLS_TRY; break; case LDAPServerParams::TLSProtocolVersion::TLS1_0: value = LDAP_OPT_X_TLS_PROTOCOL_TLS1_0; break;
case LDAPServerParams::TLSCertVerify::DEMAND: value = LDAP_OPT_X_TLS_DEMAND; break; case LDAPServerParams::TLSProtocolVersion::TLS1_1: value = LDAP_OPT_X_TLS_PROTOCOL_TLS1_1; break;
case LDAPServerParams::TLSProtocolVersion::TLS1_2: value = LDAP_OPT_X_TLS_PROTOCOL_TLS1_2; break;
}
diag(ldap_set_option(handle, LDAP_OPT_X_TLS_PROTOCOL_MIN, &value));
}
#endif
#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
{
int value = 0;
switch (params.tls_require_cert)
{
case LDAPServerParams::TLSRequireCert::NEVER: value = LDAP_OPT_X_TLS_NEVER; break;
case LDAPServerParams::TLSRequireCert::ALLOW: value = LDAP_OPT_X_TLS_ALLOW; break;
case LDAPServerParams::TLSRequireCert::TRY: value = LDAP_OPT_X_TLS_TRY; break;
case LDAPServerParams::TLSRequireCert::DEMAND: value = LDAP_OPT_X_TLS_DEMAND; break;
} }
diag(ldap_set_option(handle, LDAP_OPT_X_TLS_REQUIRE_CERT, &value)); diag(ldap_set_option(handle, LDAP_OPT_X_TLS_REQUIRE_CERT, &value));
} }
#endif
if (!params.ca_cert_dir.empty()) #ifdef LDAP_OPT_X_TLS_CERTFILE
diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTDIR, params.ca_cert_dir.c_str())); if (!params.tls_cert_file.empty())
diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CERTFILE, params.tls_cert_file.c_str()));
#endif
if (!params.ca_cert_file.empty()) #ifdef LDAP_OPT_X_TLS_KEYFILE
diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTFILE, params.ca_cert_file.c_str())); if (!params.tls_key_file.empty())
diag(ldap_set_option(handle, LDAP_OPT_X_TLS_KEYFILE, params.tls_key_file.c_str()));
#endif
#ifdef LDAP_OPT_X_TLS_CACERTFILE
if (!params.tls_ca_cert_file.empty())
diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTFILE, params.tls_ca_cert_file.c_str()));
#endif
#ifdef LDAP_OPT_X_TLS_CACERTDIR
if (!params.tls_ca_cert_dir.empty())
diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTDIR, params.tls_ca_cert_dir.c_str()));
#endif
#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
if (!params.tls_cipher_suite.empty())
diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CIPHER_SUITE, params.tls_cipher_suite.c_str()));
#endif
#ifdef LDAP_OPT_X_TLS_NEWCTX #ifdef LDAP_OPT_X_TLS_NEWCTX
{ {

View File

@ -23,7 +23,16 @@ struct LDAPServerParams
YES YES
}; };
enum class TLSCertVerify enum class TLSProtocolVersion
{
SSL2,
SSL3,
TLS1_0,
TLS1_1,
TLS1_2
};
enum class TLSRequireCert
{ {
NEVER, NEVER,
ALLOW, ALLOW,
@ -42,9 +51,13 @@ struct LDAPServerParams
std::uint16_t port = 636; std::uint16_t port = 636;
TLSEnable enable_tls = TLSEnable::YES; TLSEnable enable_tls = TLSEnable::YES;
TLSCertVerify tls_cert_verify = TLSCertVerify::DEMAND; TLSProtocolVersion tls_minimum_protocol_version = TLSProtocolVersion::TLS1_2;
String ca_cert_dir; TLSRequireCert tls_require_cert = TLSRequireCert::DEMAND;
String ca_cert_file; String tls_cert_file;
String tls_key_file;
String tls_ca_cert_file;
String tls_ca_cert_dir;
String tls_cipher_suite;
SASLMechanism sasl_mechanism = SASLMechanism::SIMPLE; SASLMechanism sasl_mechanism = SASLMechanism::SIMPLE;