Commit f32842c5 authored by Ian Craggs's avatar Ian Craggs Committed by GitHub

Merge pull request #333 from obiltschnig/feature/allow-tls-version-selection

Add support for selecting/enforcing a TLS version
parents ea499805 97ba2404
...@@ -2222,7 +2222,7 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options) ...@@ -2222,7 +2222,7 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
} }
if (options->struct_version != 0 && options->ssl) /* check validity of SSL options structure */ if (options->struct_version != 0 && options->ssl) /* check validity of SSL options structure */
{ {
if (strncmp(options->ssl->struct_id, "MQTS", 4) != 0 || options->ssl->struct_version != 0) if (strncmp(options->ssl->struct_id, "MQTS", 4) != 0 || options->ssl->struct_version < 0 || options->ssl->struct_version > 1)
{ {
rc = MQTTASYNC_BAD_STRUCTURE; rc = MQTTASYNC_BAD_STRUCTURE;
goto exit; goto exit;
...@@ -2330,6 +2330,7 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options) ...@@ -2330,6 +2330,7 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
{ {
m->c->sslopts = malloc(sizeof(MQTTClient_SSLOptions)); m->c->sslopts = malloc(sizeof(MQTTClient_SSLOptions));
memset(m->c->sslopts, '\0', sizeof(MQTTClient_SSLOptions)); memset(m->c->sslopts, '\0', sizeof(MQTTClient_SSLOptions));
m->c->sslopts->struct_version = options->ssl->struct_version;
if (options->ssl->trustStore) if (options->ssl->trustStore)
m->c->sslopts->trustStore = MQTTStrdup(options->ssl->trustStore); m->c->sslopts->trustStore = MQTTStrdup(options->ssl->trustStore);
if (options->ssl->keyStore) if (options->ssl->keyStore)
...@@ -2341,6 +2342,8 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options) ...@@ -2341,6 +2342,8 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
if (options->ssl->enabledCipherSuites) if (options->ssl->enabledCipherSuites)
m->c->sslopts->enabledCipherSuites = MQTTStrdup(options->ssl->enabledCipherSuites); m->c->sslopts->enabledCipherSuites = MQTTStrdup(options->ssl->enabledCipherSuites);
m->c->sslopts->enableServerCertAuth = options->ssl->enableServerCertAuth; m->c->sslopts->enableServerCertAuth = options->ssl->enableServerCertAuth;
if (m->c->sslopts->struct_version >= 1)
m->c->sslopts->sslVersion = options->ssl->sslVersion;
} }
#else #else
if (options->struct_version != 0 && options->ssl) if (options->struct_version != 0 && options->ssl)
......
...@@ -630,6 +630,11 @@ typedef struct ...@@ -630,6 +630,11 @@ typedef struct
#define MQTTAsync_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0, { 0, NULL } } #define MQTTAsync_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0, { 0, NULL } }
#define MQTT_SSL_VERSION_DEFAULT 0
#define MQTT_SSL_VERSION_TLS_1_0 1
#define MQTT_SSL_VERSION_TLS_1_1 2
#define MQTT_SSL_VERSION_TLS_1_2 3
/** /**
* MQTTAsync_sslProperties defines the settings to establish an SSL/TLS connection using the * MQTTAsync_sslProperties defines the settings to establish an SSL/TLS connection using the
* OpenSSL library. It covers the following scenarios: * OpenSSL library. It covers the following scenarios:
...@@ -646,7 +651,7 @@ typedef struct ...@@ -646,7 +651,7 @@ typedef struct
{ {
/** The eyecatcher for this structure. Must be MQTS */ /** The eyecatcher for this structure. Must be MQTS */
char struct_id[4]; char struct_id[4];
/** The version number of this structure. Must be 0 */ /** The version number of this structure. Must be 0, or 1 to enable TLS version selection. */
int struct_version; int struct_version;
/** The file in PEM format containing the public digital certificates trusted by the client. */ /** The file in PEM format containing the public digital certificates trusted by the client. */
...@@ -677,9 +682,15 @@ typedef struct ...@@ -677,9 +682,15 @@ typedef struct
/** True/False option to enable verification of the server certificate **/ /** True/False option to enable verification of the server certificate **/
int enableServerCertAuth; int enableServerCertAuth;
/** The SSL/TLS version to use. Specify one of MQTT_SSL_VERSION_DEFAULT (0),
* MQTT_SSL_VERSION_TLS_1_0 (1), MQTT_SSL_VERSION_TLS_1_1 (2) or MQTT_SSL_VERSION_TLS_1_2 (3).
* Only used if struct_version is >= 1.
*/
int sslVersion;
} MQTTAsync_SSLOptions; } MQTTAsync_SSLOptions;
#define MQTTAsync_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 0, NULL, NULL, NULL, NULL, NULL, 1 } #define MQTTAsync_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 1, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT }
/** /**
* MQTTAsync_connectOptions defines several settings that control the way the * MQTTAsync_connectOptions defines several settings that control the way the
......
...@@ -1104,6 +1104,7 @@ static int MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectOptions* o ...@@ -1104,6 +1104,7 @@ static int MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectOptions* o
{ {
m->c->sslopts = malloc(sizeof(MQTTClient_SSLOptions)); m->c->sslopts = malloc(sizeof(MQTTClient_SSLOptions));
memset(m->c->sslopts, '\0', sizeof(MQTTClient_SSLOptions)); memset(m->c->sslopts, '\0', sizeof(MQTTClient_SSLOptions));
m->c->sslopts->struct_version = options->ssl->struct_version;
if (options->ssl->trustStore) if (options->ssl->trustStore)
m->c->sslopts->trustStore = MQTTStrdup(options->ssl->trustStore); m->c->sslopts->trustStore = MQTTStrdup(options->ssl->trustStore);
if (options->ssl->keyStore) if (options->ssl->keyStore)
...@@ -1115,6 +1116,8 @@ static int MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectOptions* o ...@@ -1115,6 +1116,8 @@ static int MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectOptions* o
if (options->ssl->enabledCipherSuites) if (options->ssl->enabledCipherSuites)
m->c->sslopts->enabledCipherSuites = MQTTStrdup(options->ssl->enabledCipherSuites); m->c->sslopts->enabledCipherSuites = MQTTStrdup(options->ssl->enabledCipherSuites);
m->c->sslopts->enableServerCertAuth = options->ssl->enableServerCertAuth; m->c->sslopts->enableServerCertAuth = options->ssl->enableServerCertAuth;
if (m->c->sslopts->struct_version >= 1)
m->c->sslopts->sslVersion = options->ssl->sslVersion;
} }
#endif #endif
...@@ -1180,7 +1183,7 @@ int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options) ...@@ -1180,7 +1183,7 @@ int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options)
#if defined(OPENSSL) #if defined(OPENSSL)
if (options->struct_version != 0 && options->ssl) /* check validity of SSL options structure */ if (options->struct_version != 0 && options->ssl) /* check validity of SSL options structure */
{ {
if (strncmp(options->ssl->struct_id, "MQTS", 4) != 0 || options->ssl->struct_version != 0) if (strncmp(options->ssl->struct_id, "MQTS", 4) != 0 || options->ssl->struct_version < 0 || options->ssl->struct_version > 1)
{ {
rc = MQTTCLIENT_BAD_STRUCTURE; rc = MQTTCLIENT_BAD_STRUCTURE;
goto exit; goto exit;
......
...@@ -482,6 +482,11 @@ typedef struct ...@@ -482,6 +482,11 @@ typedef struct
#define MQTTClient_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0, {0, NULL} } #define MQTTClient_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0, {0, NULL} }
#define MQTT_SSL_VERSION_DEFAULT 0
#define MQTT_SSL_VERSION_TLS_1_0 1
#define MQTT_SSL_VERSION_TLS_1_1 2
#define MQTT_SSL_VERSION_TLS_1_2 3
/** /**
* MQTTClient_sslProperties defines the settings to establish an SSL/TLS connection using the * MQTTClient_sslProperties defines the settings to establish an SSL/TLS connection using the
* OpenSSL library. It covers the following scenarios: * OpenSSL library. It covers the following scenarios:
...@@ -498,7 +503,7 @@ typedef struct ...@@ -498,7 +503,7 @@ typedef struct
{ {
/** The eyecatcher for this structure. Must be MQTS */ /** The eyecatcher for this structure. Must be MQTS */
char struct_id[4]; char struct_id[4];
/** The version number of this structure. Must be 0 */ /** The version number of this structure. Must be 0, or 1 to enable TLS version selection. */
int struct_version; int struct_version;
/** The file in PEM format containing the public digital certificates trusted by the client. */ /** The file in PEM format containing the public digital certificates trusted by the client. */
...@@ -529,9 +534,15 @@ typedef struct ...@@ -529,9 +534,15 @@ typedef struct
/** True/False option to enable verification of the server certificate **/ /** True/False option to enable verification of the server certificate **/
int enableServerCertAuth; int enableServerCertAuth;
/** The SSL/TLS version to use. Specify one of MQTT_SSL_VERSION_DEFAULT (0),
* MQTT_SSL_VERSION_TLS_1_0 (1), MQTT_SSL_VERSION_TLS_1_1 (2) or MQTT_SSL_VERSION_TLS_1_2 (3).
* Only used if struct_version is >= 1.
*/
int sslVersion;
} MQTTClient_SSLOptions; } MQTTClient_SSLOptions;
#define MQTTClient_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 0, NULL, NULL, NULL, NULL, NULL, 1 } #define MQTTClient_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 1, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT }
/** /**
* MQTTClient_connectOptions defines several settings that control the way the * MQTTClient_connectOptions defines several settings that control the way the
......
...@@ -514,11 +514,42 @@ int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts) ...@@ -514,11 +514,42 @@ int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
FUNC_ENTRY; FUNC_ENTRY;
if (net->ctx == NULL) if (net->ctx == NULL)
if ((net->ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) /* SSLv23 for compatibility with SSLv2, SSLv3 and TLSv1 */ {
int sslVersion = MQTT_SSL_VERSION_DEFAULT;
if (opts->struct_version >= 1) sslVersion = opts->sslVersion;
/* SSL_OP_NO_TLSv1_1 is defined in ssl.h if the library version supports TLSv1.1.
* OPENSSL_NO_TLS1 is defined in opensslconf.h or on the compiler command line
* if TLS1.x was removed at OpenSSL library build time via Configure options.
*/
switch (sslVersion)
{
case MQTT_SSL_VERSION_DEFAULT:
net->ctx = SSL_CTX_new(SSLv23_client_method()); /* SSLv23 for compatibility with SSLv2, SSLv3 and TLSv1 */
break;
#if defined(SSL_OP_NO_TLSv1) && !defined(OPENSSL_NO_TLS1)
case MQTT_SSL_VERSION_TLS_1_0:
net->ctx = SSL_CTX_new(TLSv1_client_method());
break;
#endif
#if defined(SSL_OP_NO_TLSv1_1) && !defined(OPENSSL_NO_TLS1)
case MQTT_SSL_VERSION_TLS_1_1:
net->ctx = SSL_CTX_new(TLSv1_1_client_method());
break;
#endif
#if defined(SSL_OP_NO_TLSv1_2) && !defined(OPENSSL_NO_TLS1)
case MQTT_SSL_VERSION_TLS_1_2:
net->ctx = SSL_CTX_new(TLSv1_2_client_method());
break;
#endif
default:
break;
}
if (net->ctx == NULL)
{ {
SSLSocket_error("SSL_CTX_new", NULL, net->socket, rc); SSLSocket_error("SSL_CTX_new", NULL, net->socket, rc);
goto exit; goto exit;
} }
}
if (opts->keyStore) if (opts->keyStore)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment