Added configuration options for TLS cipher suites and TLS versions.

This commit is contained in:
Jan Vidar Krey 2014-07-29 13:31:42 +02:00
parent 0426cb523a
commit b85381c0f5
6 changed files with 127 additions and 21 deletions

View File

@ -428,7 +428,6 @@
<since>0.3.3</since> <since>0.3.3</since>
</option> </option>
<option name="tls_certificate" type="file" default=""> <option name="tls_certificate" type="file" default="">
<short>Certificate file</short> <short>Certificate file</short>
<description><![CDATA[ <description><![CDATA[
@ -445,6 +444,40 @@
<since>0.3.0</since> <since>0.3.0</since>
</option> </option>
<option name="tls_ciphersuite" type="string" default="ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS">
<short>List of TLS ciphers to use</short>
<description><![CDATA[
This is a colon separated list of preferred ciphers in the OpenSSL format.
]]></description>
<since>0.5.0</since>
<example><![CDATA[
<p>
High security with emphasis on forward secrecy:<br />
tls_ciphersuite = "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS"
</p>
<p>
Allow ChaCha20/Poly1305 which are secure, yet generally faster:<br />
tls_ciphersuite = "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
</p>
]]></example>
</option>
<option name="tls_version" type="string" default="1.2">
<short>Specify minimum TLS version supported.</short>
<description><![CDATA[
<p>
This allows you to specify the minimum TLS version the hub requires from connecting clients in order to
connect to the hub.
</p>
<p>
TLS version 1.2 is recommended and enabled by default.
TLS version 1.1 is acceptable without any known flaws, and allows for older clients to connect.
TLS version 1.0 should be avoided, even though it is the most compatible with older ADC clients.
</p>
]]></description>
<since>0.5.0</since>
</option>
<option name="file_acl" type="file" default=""> <option name="file_acl" type="file" default="">
<short>File containing access control lists</short> <short>File containing access control lists</short>
<description><![CDATA[ <description><![CDATA[

View File

@ -3,7 +3,7 @@
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2014, Jan Vidar Krey
* *
* THIS FILE IS AUTOGENERATED - DO NOT MODIFY * THIS FILE IS AUTOGENERATED - DO NOT MODIFY
* Created 2014-05-14 11:38, by config.py * Created 2014-07-29 12:22, by config.py
*/ */
void config_defaults(struct hub_config* config) void config_defaults(struct hub_config* config)
@ -51,6 +51,8 @@ void config_defaults(struct hub_config* config)
config->tls_require_redirect_addr = hub_strdup(""); config->tls_require_redirect_addr = hub_strdup("");
config->tls_certificate = hub_strdup(""); config->tls_certificate = hub_strdup("");
config->tls_private_key = hub_strdup(""); config->tls_private_key = hub_strdup("");
config->tls_ciphersuite = hub_strdup("ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS");
config->tls_version = hub_strdup("1.2");
config->file_acl = hub_strdup(""); config->file_acl = hub_strdup("");
config->file_plugins = hub_strdup(""); config->file_plugins = hub_strdup("");
config->msg_hub_full = hub_strdup("Hub is full"); config->msg_hub_full = hub_strdup("Hub is full");
@ -552,6 +554,26 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
return 0; return 0;
} }
if (!strcmp(key, "tls_ciphersuite"))
{
if (!apply_string(key, data, &config->tls_ciphersuite, (char*) ""))
{
LOG_ERROR("Configuration parse error on line %d", line_count);
return -1;
}
return 0;
}
if (!strcmp(key, "tls_version"))
{
if (!apply_string(key, data, &config->tls_version, (char*) ""))
{
LOG_ERROR("Configuration parse error on line %d", line_count);
return -1;
}
return 0;
}
if (!strcmp(key, "file_acl")) if (!strcmp(key, "file_acl"))
{ {
if (!apply_string(key, data, &config->file_acl, (char*) "")) if (!apply_string(key, data, &config->file_acl, (char*) ""))
@ -955,6 +977,10 @@ void free_config(struct hub_config* config)
hub_free(config->tls_private_key); hub_free(config->tls_private_key);
hub_free(config->tls_ciphersuite);
hub_free(config->tls_version);
hub_free(config->file_acl); hub_free(config->file_acl);
hub_free(config->file_plugins); hub_free(config->file_plugins);
@ -1164,6 +1190,12 @@ void dump_config(struct hub_config* config, int ignore_defaults)
if (!ignore_defaults || strcmp(config->tls_private_key, "") != 0) if (!ignore_defaults || strcmp(config->tls_private_key, "") != 0)
fprintf(stdout, "tls_private_key = \"%s\"\n", config->tls_private_key); fprintf(stdout, "tls_private_key = \"%s\"\n", config->tls_private_key);
if (!ignore_defaults || strcmp(config->tls_ciphersuite, "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS") != 0)
fprintf(stdout, "tls_ciphersuite = \"%s\"\n", config->tls_ciphersuite);
if (!ignore_defaults || strcmp(config->tls_version, "1.2") != 0)
fprintf(stdout, "tls_version = \"%s\"\n", config->tls_version);
if (!ignore_defaults || strcmp(config->file_acl, "") != 0) if (!ignore_defaults || strcmp(config->file_acl, "") != 0)
fprintf(stdout, "file_acl = \"%s\"\n", config->file_acl); fprintf(stdout, "file_acl = \"%s\"\n", config->file_acl);

View File

@ -3,7 +3,7 @@
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2014, Jan Vidar Krey
* *
* THIS FILE IS AUTOGENERATED - DO NOT MODIFY * THIS FILE IS AUTOGENERATED - DO NOT MODIFY
* Created 2014-05-14 11:38, by config.py * Created 2014-07-29 12:22, by config.py
*/ */
struct hub_config struct hub_config
@ -51,6 +51,8 @@ struct hub_config
char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: "") */ char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: "") */
char* tls_certificate; /*<<< Certificate file (default: "") */ char* tls_certificate; /*<<< Certificate file (default: "") */
char* tls_private_key; /*<<< Private key file (default: "") */ char* tls_private_key; /*<<< Private key file (default: "") */
char* tls_ciphersuite; /*<<< List of TLS ciphers to use (default: "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS") */
char* tls_version; /*<<< Specify minimum TLS version supported. (default: "1.2") */
char* file_acl; /*<<< File containing access control lists (default: "") */ char* file_acl; /*<<< File containing access control lists (default: "") */
char* file_plugins; /*<<< Plugin configuration file (default: "") */ char* file_plugins; /*<<< Plugin configuration file (default: "") */
char* msg_hub_full; /*<<< "Hub is full" */ char* msg_hub_full; /*<<< "Hub is full" */

View File

@ -731,7 +731,11 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config
{ {
if (config->tls_enable) if (config->tls_enable)
{ {
hub->ctx = net_ssl_context_create(); hub->ctx = net_ssl_context_create(config->tls_version, config->tls_ciphersuite);
if (!hub->ctx)
return 0;
if (ssl_load_certificate(hub->ctx, config->tls_certificate) && if (ssl_load_certificate(hub->ctx, config->tls_certificate) &&
ssl_load_private_key(hub->ctx, config->tls_private_key) && ssl_load_private_key(hub->ctx, config->tls_private_key) &&
ssl_check_private_key(hub->ctx)) ssl_check_private_key(hub->ctx))

View File

@ -43,8 +43,7 @@ struct net_ssl_openssl
struct net_context_openssl struct net_context_openssl
{ {
SSL_METHOD* ssl_method; SSL_CTX* ssl;
SSL_CTX* ssl_ctx;
}; };
static struct net_ssl_openssl* get_handle(struct net_connection* con) static struct net_ssl_openssl* get_handle(struct net_connection* con)
@ -97,26 +96,61 @@ static void add_io_stats(struct net_ssl_openssl* handle)
} }
} }
static const SSL_METHOD* get_ssl_method(const char* tls_version)
{
if (!tls_version || !*tls_version)
{
LOG_ERROR("tls_version is not set.");
return 0;
}
if (!strcmp(tls_version, "1.0"))
return TLSv1_method();
if (!strcmp(tls_version, "1.1"))
return TLSv1_1_method();
if (!strcmp(tls_version, "1.2"))
return TLSv1_2_method();
LOG_ERROR("Unable to recognize tls_version.");
return 0;
}
/** /**
* Create a new SSL context. * Create a new SSL context.
*/ */
struct ssl_context_handle* net_ssl_context_create() struct ssl_context_handle* net_ssl_context_create(const char* tls_version, const char* tls_ciphersuite)
{ {
struct net_context_openssl* ctx = (struct net_context_openssl*) hub_malloc_zero(sizeof(struct net_context_openssl)); struct net_context_openssl* ctx = (struct net_context_openssl*) hub_malloc_zero(sizeof(struct net_context_openssl));
ctx->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */ const SSL_METHOD* ssl_method = get_ssl_method(tls_version);
ctx->ssl_ctx = SSL_CTX_new(ctx->ssl_method);
if (!ssl_method)
{
hub_free(ctx);
return 0;
}
ctx->ssl = SSL_CTX_new(ssl_method);
/* Disable SSLv2 */ /* Disable SSLv2 */
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_SSLv2);
// FIXME: Why did we need this again?
SSL_CTX_set_quiet_shutdown(ctx->ssl, 1);
#ifdef SSL_OP_NO_COMPRESSION #ifdef SSL_OP_NO_COMPRESSION
/* Disable compression? */ /* Disable compression */
LOG_TRACE("Disabling SSL compression."); /* "CRIME" attack */ LOG_TRACE("Disabling SSL compression."); /* "CRIME" attack */
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_COMPRESSION); SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_COMPRESSION);
#endif #endif
SSL_CTX_set_quiet_shutdown(ctx->ssl_ctx, 1); /* Set preferred cipher suite */
if (SSL_CTX_set_cipher_list(ctx->ssl, tls_ciphersuite) != 1)
{
LOG_ERROR("Unable to set cipher suite.");
SSL_CTX_free(ctx->ssl);
hub_free(ctx);
return 0;
}
return (struct ssl_context_handle*) ctx; return (struct ssl_context_handle*) ctx;
} }
@ -124,16 +158,16 @@ struct ssl_context_handle* net_ssl_context_create()
extern void net_ssl_context_destroy(struct ssl_context_handle* ctx_) extern void net_ssl_context_destroy(struct ssl_context_handle* ctx_)
{ {
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
SSL_CTX_free(ctx->ssl_ctx); SSL_CTX_free(ctx->ssl);
hub_free(ctx); hub_free(ctx);
} }
int ssl_load_certificate(struct ssl_context_handle* ctx_, const char* pem_file) int ssl_load_certificate(struct ssl_context_handle* ctx_, const char* pem_file)
{ {
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem_file) < 0) if (SSL_CTX_use_certificate_chain_file(ctx->ssl, pem_file) < 0)
{ {
LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL)); LOG_ERROR("SSL_CTX_use_certificate_chain_file: %s", ERR_error_string(ERR_get_error(), NULL));
return 0; return 0;
} }
@ -143,7 +177,7 @@ int ssl_load_certificate(struct ssl_context_handle* ctx_, const char* pem_file)
int ssl_load_private_key(struct ssl_context_handle* ctx_, const char* pem_file) int ssl_load_private_key(struct ssl_context_handle* ctx_, const char* pem_file)
{ {
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem_file, SSL_FILETYPE_PEM) < 0) if (SSL_CTX_use_PrivateKey_file(ctx->ssl, pem_file, SSL_FILETYPE_PEM) < 0)
{ {
LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL)); LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL));
return 0; return 0;
@ -154,7 +188,7 @@ int ssl_load_private_key(struct ssl_context_handle* ctx_, const char* pem_file)
int ssl_check_private_key(struct ssl_context_handle* ctx_) int ssl_check_private_key(struct ssl_context_handle* ctx_)
{ {
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
if (SSL_CTX_check_private_key(ctx->ssl_ctx) != 1) if (SSL_CTX_check_private_key(ctx->ssl) != 1)
{ {
LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL)); LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL));
return 0; return 0;
@ -238,7 +272,7 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
if (ssl_mode == net_con_ssl_mode_server) if (ssl_mode == net_con_ssl_mode_server)
{ {
handle->ssl = SSL_new(ctx->ssl_ctx); handle->ssl = SSL_new(ctx->ssl);
if (!handle->ssl) if (!handle->ssl)
{ {
LOG_ERROR("Unable to create new SSL stream\n"); LOG_ERROR("Unable to create new SSL stream\n");

View File

@ -56,8 +56,9 @@ extern int net_ssl_library_shutdown();
/** /**
* Create a new SSL context. * Create a new SSL context.
* Specify a TLS version as a string: "1.2" for TLS 1.2.
*/ */
extern struct ssl_context_handle* net_ssl_context_create(); extern struct ssl_context_handle* net_ssl_context_create(const char* tls_version, const char* tls_ciphersuite);
extern void net_ssl_context_destroy(struct ssl_context_handle* ctx); extern void net_ssl_context_destroy(struct ssl_context_handle* ctx);
/** /**