0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 04:02:15 +02:00

Implement tls-cipher and tls-ciphersuite

Signed-off-by: Arne Schwabe <arne@openvpn.net>
This commit is contained in:
Arne Schwabe 2020-02-19 16:42:53 +01:00 committed by David Sommerseth
parent fa5f0f0b02
commit 6e463ca1f4
No known key found for this signature in database
GPG Key ID: 86CF944C9671FDF2
5 changed files with 128 additions and 19 deletions

View File

@ -442,6 +442,8 @@ namespace openvpn {
int default_key_direction = -1;
std::string tls_version_min_override;
std::string tls_cert_profile_override;
std::string tls_cipher_list;
std::string tls_ciphersuite_list;
std::string gui_version;
std::string sso_methods;
bool allow_local_lan_access;
@ -697,6 +699,8 @@ namespace openvpn {
state->default_key_direction = config.defaultKeyDirection;
state->tls_version_min_override = config.tlsVersionMinOverride;
state->tls_cert_profile_override = config.tlsCertProfileOverride;
state->tls_cipher_list = config.tlsCipherList;
state->tls_ciphersuite_list = config.tlsCiphersuitesList;
state->allow_local_lan_access = config.allowLocalLanAccess;
state->gui_version = config.guiVersion;
state->sso_methods = config.ssoMethods;
@ -978,6 +982,8 @@ namespace openvpn {
cc.default_key_direction = state->default_key_direction;
cc.tls_version_min_override = state->tls_version_min_override;
cc.tls_cert_profile_override = state->tls_cert_profile_override;
cc.tls_cipher_list = state->tls_cipher_list;
cc.tls_ciphersuite_list = state->tls_ciphersuite_list;
cc.gui_version = state->gui_version;
cc.sso_methods = state->sso_methods;
cc.hw_addr_override = state->hw_addr_override;

View File

@ -277,6 +277,13 @@ namespace openvpn {
// doesn't specify tls-cert-profile
std::string tlsCertProfileOverride;
// Overrides the list of tls ciphers like the tls-cipher option
std::string tlsCipherList;
// Overrides the list of TLS 1.3 ciphersuites like the tls-ciphersuites
// option
std::string tlsCiphersuitesList;
// Pass custom key/value pairs to OpenVPN server.
std::vector<KeyValue> peerInfo;

View File

@ -149,6 +149,8 @@ namespace openvpn {
bool allow_local_lan_access = false;
std::string tls_version_min_override;
std::string tls_cert_profile_override;
std::string tls_cipher_list;
std::string tls_ciphersuite_list;
PeerInfo::Set::Ptr extra_peer_info;
#ifdef OPENVPN_GREMLIN
Gremlin::Config::Ptr gremlin_config;
@ -729,6 +731,8 @@ namespace openvpn {
cc->load(opt, lflags);
cc->set_tls_version_min_override(config.tls_version_min_override);
cc->set_tls_cert_profile_override(config.tls_cert_profile_override);
cc->set_tls_cipher_list(config.tls_cipher_list);
cc->set_tls_ciphersuite_list(config.tls_ciphersuite_list);
if (!cc->get_mode().is_client())
throw option_error("only client configuration supported");

View File

@ -404,6 +404,17 @@ namespace openvpn {
tls_cert_profile = type;
}
virtual void set_tls_cipher_list(const std::string& override)
{
if(!override.empty())
tls_cipher_list = override;
}
virtual void set_tls_ciphersuite_list(const std::string& override)
{
// mbed TLS does not have TLS 1.3 support
}
virtual void set_tls_cert_profile_override(const std::string& override)
{
TLSCertProfile::apply_override(tls_cert_profile, override);
@ -549,6 +560,10 @@ namespace openvpn {
// parse tls-cert-profile
tls_cert_profile = TLSCertProfile::parse_tls_cert_profile(opt, relay_prefix);
// Overrides for tls cipher suites
if (opt.exists("tls-cipher"))
tls_cipher_list = opt.get_optional("tls-cipher", 1, 256);
// unsupported cert verification options
{
}
@ -613,6 +628,7 @@ namespace openvpn {
VerifyX509Name verify_x509_name; // --verify-x509-name feature
TLSVersion::Type tls_version_min; // minimum TLS version that we will negotiate
TLSCertProfile::Type tls_cert_profile;
std::string tls_cipher_list;
X509Track::ConfigSet x509_track_config;
bool local_cert_enabled;
bool allow_name_constraints;
@ -835,7 +851,14 @@ namespace openvpn {
// in mbed TLS config.h.
mbedtls_ssl_conf_renegotiation(sslconf, MBEDTLS_SSL_RENEGOTIATION_DISABLED);
mbedtls_ssl_conf_ciphersuites(sslconf, mbedtls_ctx_private::ciphersuites);
if (!c.tls_cipher_list.empty())
{
set_mbedtls_cipherlist(c.tls_cipher_list);
}
else
{
mbedtls_ssl_conf_ciphersuites(sslconf, mbedtls_ctx_private::ciphersuites);
}
// set CA chain
if (c.ca_chain)
@ -935,9 +958,44 @@ namespace openvpn {
}
mbedtls_ssl_config *sslconf; // SSL configuration parameters for SSL connection object
std::unique_ptr<int[]> allowed_ciphers; //! Hold the array that is used for setting the allowed ciphers
// must have the same lifetime as sslconf
MbedTLSContext *parent;
private:
void set_mbedtls_cipherlist(const std::string& cipher_list)
{
auto num_ciphers = std::count(cipher_list.begin(), cipher_list.end(), ':') + 1;
allowed_ciphers.reset(new int[num_ciphers+1]);
std::stringstream cipher_list_ss(cipher_list);
std::string ciphersuite;
int i=0;
while(std::getline(cipher_list_ss, ciphersuite, ':'))
{
auto cipher_id = mbedtls_ssl_get_ciphersuite_id(ciphersuite.c_str());
if (cipher_id != 0)
{
allowed_ciphers[i] = cipher_id;
i++;
}
else
{
/* OpenVPN 2.x ignores silently ignores unknown cipher suites with
* mbed TLS. We warn about them in OpenVPN 3.x */
OPENVPN_LOG_SSL("mbed TLS -- warning ignoring unknown cipher suite '"
<< ciphersuite << "' in tls-cipher");
}
}
// Last element needs to be null
allowed_ciphers[i] = 0;
mbedtls_ssl_conf_ciphersuites(sslconf, allowed_ciphers.get());
}
// cleartext read callback
static int ct_read_func(void *arg, unsigned char *data, size_t length)
{
@ -986,6 +1044,7 @@ namespace openvpn {
ssl = nullptr;
sslconf = nullptr;
overflow = false;
allowed_ciphers = nullptr;
}
void erase()

View File

@ -282,6 +282,18 @@ namespace openvpn {
TLSCertProfile::apply_override(tls_cert_profile, override);
}
virtual void set_tls_cipher_list(const std::string& override)
{
if(!override.empty())
tls_cipher_list = override;
}
virtual void set_tls_ciphersuite_list(const std::string& override)
{
if(!override.empty())
tls_ciphersuite_list = override;
}
void set_local_cert_enabled(const bool v) override
{
local_cert_enabled = v;
@ -412,6 +424,13 @@ namespace openvpn {
// parse tls-cert-profile
tls_cert_profile = TLSCertProfile::parse_tls_cert_profile(opt, relay_prefix);
// Overrides for tls cipher suites
if (opt.exists("tls-cipher"))
tls_cipher_list = opt.get_optional("tls-cipher", 1, 256);
if (opt.exists("tls-ciphersuites"))
tls_ciphersuite_list = opt.get_optional("tls-ciphersuites", 1, 256);
// unsupported cert checkers
{
}
@ -554,6 +573,8 @@ namespace openvpn {
VerifyX509Name verify_x509_name; // --verify-x509-name feature
TLSVersion::Type tls_version_min{TLSVersion::UNDEF}; // minimum TLS version that we will negotiate
TLSCertProfile::Type tls_cert_profile{TLSCertProfile::UNDEF};
std::string tls_cipher_list;
std::string tls_ciphersuite_list
X509Track::ConfigSet x509_track_config;
bool local_cert_enabled = true;
bool client_session_tickets = false;
@ -1079,25 +1100,37 @@ namespace openvpn {
#endif
SSL_CTX_set_options(ctx, sslopt);
#if defined(TLS1_3_VERSION)
if (!config->tls_ciphersuite_list.empty())
{
if(!SSL_CTX_set_ciphersuites(ctx, config->tls_ciphersuite_list.c_str()))
OPENVPN_THROW(ssl_context_error, "OpenSSLContext: SSL_CTX_set_ciphersuites_list failed");
}
#endif
const char* tls_cipher_list =
/* default list as a basis */
"DEFAULT"
/* Disable export ciphers, low and medium */
":!EXP:!LOW:!MEDIUM"
/* Disable static (EC)DH keys (no forward secrecy) */
":!kDH:!kECDH"
/* Disable DSA private keys */
":!DSS"
/* Disable RC4 cipher */
":!RC4"
/* Disable MD5 */
":!MD5"
/* Disable unsupported TLS modes */
":!PSK:!SRP:!kRSA"
/* Disable SSLv2 cipher suites*/
":!SSLv2";
if (!SSL_CTX_set_cipher_list(ctx,
/* default list as a basis */
"DEFAULT"
/* Disable export ciphers, low and medium */
":!EXP:!LOW:!MEDIUM"
/* Disable static (EC)DH keys (no forward secrecy) */
":!kDH:!kECDH"
/* Disable DSA private keys */
":!DSS"
/* Disable RC4 cipher */
":!RC4"
/* Disable MD5 */
":!MD5"
/* Disable unsupported TLS modes */
":!PSK:!SRP:!kRSA"
/* Disable SSLv2 cipher suites*/
":!SSLv2"
))
if (!config->tls_cipher_list.empty())
{
tls_cipher_list = config->tls_cipher_list.c_str();
}
if (!SSL_CTX_set_cipher_list(ctx, tls_cipher_list))
OPENVPN_THROW(ssl_context_error, "OpenSSLContext: SSL_CTX_set_cipher_list failed");
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_CTX_set_ecdh_auto(ctx, 1); // this method becomes a no-op in OpenSSL 1.1