Skip to content

Commit

Permalink
Merge pull request #333 from obiltschnig/feature/allow-tls-version-se…
Browse files Browse the repository at this point in the history
…lection

Add support for selecting/enforcing a TLS version
  • Loading branch information
icraggs committed Sep 18, 2017
2 parents ea49980 + 97ba240 commit f32842c
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 7 deletions.
5 changes: 4 additions & 1 deletion src/MQTTAsync.c
Expand Up @@ -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 (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;
goto exit;
Expand Down Expand Up @@ -2330,6 +2330,7 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
{
m->c->sslopts = malloc(sizeof(MQTTClient_SSLOptions));
memset(m->c->sslopts, '\0', sizeof(MQTTClient_SSLOptions));
m->c->sslopts->struct_version = options->ssl->struct_version;
if (options->ssl->trustStore)
m->c->sslopts->trustStore = MQTTStrdup(options->ssl->trustStore);
if (options->ssl->keyStore)
Expand All @@ -2341,6 +2342,8 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
if (options->ssl->enabledCipherSuites)
m->c->sslopts->enabledCipherSuites = MQTTStrdup(options->ssl->enabledCipherSuites);
m->c->sslopts->enableServerCertAuth = options->ssl->enableServerCertAuth;
if (m->c->sslopts->struct_version >= 1)
m->c->sslopts->sslVersion = options->ssl->sslVersion;
}
#else
if (options->struct_version != 0 && options->ssl)
Expand Down
15 changes: 13 additions & 2 deletions src/MQTTAsync.h
Expand Up @@ -630,6 +630,11 @@ typedef struct

#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
* OpenSSL library. It covers the following scenarios:
Expand All @@ -646,7 +651,7 @@ typedef struct
{
/** The eyecatcher for this structure. Must be MQTS */
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;

/** The file in PEM format containing the public digital certificates trusted by the client. */
Expand Down Expand Up @@ -677,9 +682,15 @@ typedef struct
/** True/False option to enable verification of the server certificate **/
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;

#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
Expand Down
5 changes: 4 additions & 1 deletion src/MQTTClient.c
Expand Up @@ -1104,6 +1104,7 @@ static int MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectOptions* o
{
m->c->sslopts = malloc(sizeof(MQTTClient_SSLOptions));
memset(m->c->sslopts, '\0', sizeof(MQTTClient_SSLOptions));
m->c->sslopts->struct_version = options->ssl->struct_version;
if (options->ssl->trustStore)
m->c->sslopts->trustStore = MQTTStrdup(options->ssl->trustStore);
if (options->ssl->keyStore)
Expand All @@ -1115,6 +1116,8 @@ static int MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectOptions* o
if (options->ssl->enabledCipherSuites)
m->c->sslopts->enabledCipherSuites = MQTTStrdup(options->ssl->enabledCipherSuites);
m->c->sslopts->enableServerCertAuth = options->ssl->enableServerCertAuth;
if (m->c->sslopts->struct_version >= 1)
m->c->sslopts->sslVersion = options->ssl->sslVersion;
}
#endif

Expand Down Expand Up @@ -1180,7 +1183,7 @@ int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options)
#if defined(OPENSSL)
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;
goto exit;
Expand Down
15 changes: 13 additions & 2 deletions src/MQTTClient.h
Expand Up @@ -482,6 +482,11 @@ typedef struct

#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
* OpenSSL library. It covers the following scenarios:
Expand All @@ -498,7 +503,7 @@ typedef struct
{
/** The eyecatcher for this structure. Must be MQTS */
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;

/** The file in PEM format containing the public digital certificates trusted by the client. */
Expand Down Expand Up @@ -529,9 +534,15 @@ typedef struct
/** True/False option to enable verification of the server certificate **/
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;

#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
Expand Down
33 changes: 32 additions & 1 deletion src/SSLSocket.c
Expand Up @@ -514,11 +514,42 @@ int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)

FUNC_ENTRY;
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);
goto exit;
}
}

if (opts->keyStore)
{
Expand Down

0 comments on commit f32842c

Please sign in to comment.