Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/MQTTAsync.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,11 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
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;
m->c->sslopts->tlsMin = options->ssl->tlsMin;
m->c->sslopts->tlsMax = options->ssl->tlsMax;
}
if (m->c->sslopts->struct_version >= 2)
{
m->c->sslopts->verify = options->ssl->verify;
Expand Down
19 changes: 17 additions & 2 deletions src/MQTTAsync.h
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,7 @@ typedef struct
#define MQTT_SSL_VERSION_TLS_1_0 1
#define MQTT_SSL_VERSION_TLS_1_1 2
#define MQTT_SSL_VERSION_TLS_1_2 3
#define MQTT_SSL_VERSION_TLS_1_3 4

/**
* MQTTAsync_sslProperties defines the settings to establish an SSL/TLS connection using the
Expand Down Expand Up @@ -1113,11 +1114,25 @@ typedef struct
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).
* MQTT_SSL_VERSION_TLS_1_0 (1), MQTT_SSL_VERSION_TLS_1_1 (2), MQTT_SSL_VERSION_TLS_1_2 (3) or MQTT_SSL_VERSION_TLS_1_3 (4).
* Only used if struct_version is >= 1.
*/
int sslVersion;

/** The TLS maximum version allowed. Specify one of MQTT_SSL_VERSION_TLS_1_0 (1),
* MQTT_SSL_VERSION_TLS_1_1 (2) or MQTT_SSL_VERSION_TLS_1_2 (3) or MQTT_SSL_VERSION_TLS_1_3 (4).
* Ignored if OpenSSL version < 1.1.0 and sslVersion not MQTT_SSL_VERSION_DEFAULT
* Only used if struct_version is >= 1.
*/
int tlsMax;

/** The TLS minimum version allowed. Specify one of MQTT_SSL_VERSION_TLS_1_0 (1),
* MQTT_SSL_VERSION_TLS_1_1 (2), MQTT_SSL_VERSION_TLS_1_2 (3) or MQTT_SSL_VERSION_TLS_1_3 (4).
* Ignored if OpenSSL version < 1.1.0 and sslVersion not MQTT_SSL_VERSION_DEFAULT
* Only used if struct_version is >= 1.
*/
int tlsMin;

/**
* Whether to carry out post-connect checks, including that a certificate
* matches the given host name.
Expand Down Expand Up @@ -1180,7 +1195,7 @@ typedef struct
unsigned int protos_len;
} MQTTAsync_SSLOptions;

#define MQTTAsync_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 5, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0 }
#define MQTTAsync_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 5, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, MQTT_SSL_VERSION_DEFAULT, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0 }

/** Utility structure where name/value pairs are needed */
typedef struct
Expand Down
4 changes: 4 additions & 0 deletions src/MQTTClient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1667,7 +1667,11 @@ static MQTTResponse MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectO
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;
m->c->sslopts->tlsMin = options->ssl->tlsMin;
m->c->sslopts->tlsMax = options->ssl->tlsMax;
}
if (m->c->sslopts->struct_version >= 2)
{
m->c->sslopts->verify = options->ssl->verify;
Expand Down
19 changes: 17 additions & 2 deletions src/MQTTClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ typedef struct
#define MQTT_SSL_VERSION_TLS_1_0 1
#define MQTT_SSL_VERSION_TLS_1_1 2
#define MQTT_SSL_VERSION_TLS_1_2 3
#define MQTT_SSL_VERSION_TLS_1_3 4

/**
* MQTTClient_sslProperties defines the settings to establish an SSL/TLS connection using the
Expand Down Expand Up @@ -718,11 +719,25 @@ typedef struct
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).
* MQTT_SSL_VERSION_TLS_1_0 (1), MQTT_SSL_VERSION_TLS_1_1 (2), MQTT_SSL_VERSION_TLS_1_2 (3) or MQTT_SSL_VERSION_TLS_1_3 (4).
* Only used if struct_version is >= 1.
*/
int sslVersion;

/** The TLS maximum version allowed. Specify one of MQTT_SSL_VERSION_TLS_1_0 (1),
* MQTT_SSL_VERSION_TLS_1_1 (2) or MQTT_SSL_VERSION_TLS_1_2 (3) or MQTT_SSL_VERSION_TLS_1_3 (4).
* Ignored if OpenSSL version < 1.1.0 and sslVersion not MQTT_SSL_VERSION_DEFAULT
* Only used if struct_version is >= 1.
*/
int tlsMax;

/** The TLS minimum version allowed. Specify one of MQTT_SSL_VERSION_TLS_1_0 (1),
* MQTT_SSL_VERSION_TLS_1_1 (2), MQTT_SSL_VERSION_TLS_1_2 (3) or MQTT_SSL_VERSION_TLS_1_3 (4).
* Ignored if OpenSSL version < 1.1.0 and sslVersion not MQTT_SSL_VERSION_DEFAULT
* Only used if struct_version is >= 1.
*/
int tlsMin;

/**
* Whether to carry out post-connect checks, including that a certificate
* matches the given host name.
Expand Down Expand Up @@ -785,7 +800,7 @@ typedef struct
unsigned int protos_len;
} MQTTClient_SSLOptions;

#define MQTTClient_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 5, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0 }
#define MQTTClient_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 5, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, MQTT_SSL_VERSION_DEFAULT, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0 }

/**
* MQTTClient_libraryInfo is used to store details relating to the currently used
Expand Down
67 changes: 66 additions & 1 deletion src/SSLSocket.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ char* SSLSocket_get_version_string(int version)
#endif
#if defined(TLS3_VERSION)
{ TLS3_VERSION, "TLS 1.2" },
#endif
#if defined(TLS4_VERSION)
{TLS4_VERSION, "TLS 1.3"},
#endif
};

Expand Down Expand Up @@ -546,12 +549,13 @@ static unsigned int call_ssl_psk_cb(SSL *ssl, const char *hint, char *identity,
int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
{
int rc = 1;

int tlsBoundsValid = 0;
FUNC_ENTRY;
if (net->ctx == NULL)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
net->ctx = SSL_CTX_new(TLS_client_method());
tlsBoundsValid = 1;
#else
int sslVersion = MQTT_SSL_VERSION_DEFAULT;
if (opts->struct_version >= 1) sslVersion = opts->sslVersion;
Expand All @@ -563,6 +567,7 @@ int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
{
case MQTT_SSL_VERSION_DEFAULT:
net->ctx = SSL_CTX_new(SSLv23_client_method()); /* SSLv23 for compatibility with SSLv2, SSLv3 and TLSv1 */
tlsBoundsValid = 1;
break;
#if defined(SSL_OP_NO_TLSv1) && !defined(OPENSSL_NO_TLS1)
case MQTT_SSL_VERSION_TLS_1_0:
Expand All @@ -578,6 +583,11 @@ int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
case MQTT_SSL_VERSION_TLS_1_2:
net->ctx = SSL_CTX_new(TLSv1_2_client_method());
break;
#endif
#if defined(SSL_OP_NO_TLSv1_3) && !defined(OPENSSL_NO_TLS1)
case MQTT_SSL_VERSION_TLS_1_3:
net->ctx = SSL_CTX_NEW(TLS_client_method());
break;
#endif
default:
break;
Expand Down Expand Up @@ -695,6 +705,61 @@ int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
#endif

SSL_CTX_set_mode(net->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
tlsBoundsValid &= opts->tlsMin <= opts->tlsMax;
if (opts->struct_version >= 1 && tlsBoundsValid)
{
switch (opts->tlsMin)
{
case MQTT_SSL_VERSION_TLS_1_0:
#ifdef TLS1_VERSION
SSL_CTX_set_min_proto_version(net->ctx, TLS1_VERSION);
#endif
break;
case MQTT_SSL_VERSION_TLS_1_1:
#ifdef TLS1_1_VERSION
SSL_CTX_set_min_proto_version(net->ctx, TLS1_1_VERSION);
#endif
break;
case MQTT_SSL_VERSION_TLS_1_2:
#ifdef TLS1_2_VERSION
SSL_CTX_set_min_proto_version(net->ctx, TLS1_2_VERSION);
#endif
break;
case MQTT_SSL_VERSION_TLS_1_3:
#ifdef TLS1_3_VERSION
SSL_CTX_set_min_proto_version(net->ctx, TLS1_3_VERSION);
#endif
break;
default:
break;
}

switch (opts->tlsMax)
{
case MQTT_SSL_VERSION_TLS_1_0:
#ifdef TLS1_VERSION
SSL_CTX_set_max_proto_version(net->ctx, TLS1_VERSION);
#endif
break;
case MQTT_SSL_VERSION_TLS_1_1:
#ifdef TLS1_1_VERSION
SSL_CTX_set_max_proto_version(net->ctx, TLS1_1_VERSION);
#endif
break;
case MQTT_SSL_VERSION_TLS_1_2:
#ifdef TLS1_2_VERSION
SSL_CTX_set_max_proto_version(net->ctx, TLS1_2_VERSION);
#endif
break;
case MQTT_SSL_VERSION_TLS_1_3:
#ifdef TLS1_3_VERSION
SSL_CTX_set_max_proto_version(net->ctx, TLS1_3_VERSION);
#endif
break;
default:
break;
}
}

goto exit;
free_ctx:
Expand Down
109 changes: 108 additions & 1 deletion test/test3.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct Options
char server_auth_connection[100];
char anon_connection[100];
char psk_connection[100];
char tls_connection[100];
char** haconnections; /**< connection to system under test. */
int hacount;
char* client_key_file;
Expand All @@ -94,6 +95,7 @@ struct Options
"mqtts://localhost:18885",
"ssl://localhost:18886",
"mqtts://localhost:18888",
"tls://localhost:18889",
NULL,
0,
"../../../test/ssl/client.pem",
Expand Down Expand Up @@ -173,6 +175,8 @@ void getopts(int argc, char** argv)
printf("Setting anon_connection to %s\n", options.anon_connection);
sprintf(options.psk_connection, "%s://%s:18888", prefix, argv[count]);
printf("Setting psk_connection to %s\n", options.psk_connection);
sprintf(options.tls_connection, "%s://%s:18889", prefix, argv[count]);
printf("Setting tls_connection to %s\n", options.tls_connection);
}
else
usage();
Expand Down Expand Up @@ -1656,6 +1660,109 @@ int test6(struct Options options)
return failures;
}

int test7(struct Options options)
{
char* testname = "test_tls_minmax";
MQTTClient c;
MQTTClient_connectOptions opts = MQTTClient_connectOptions_initializer;
MQTTClient_SSLOptions sslopts = MQTTClient_SSLOptions_initializer;
int rc = 0;

failures = 0;
MyLog(LOGA_INFO, "Starting test - TLS min/max version check");
fprintf(xml, "<testcase classname=\"%s\" name=\"%s\"", testname, testname);
global_start_time = start_clock();

rc = MQTTClient_create(&c, options.tls_connection, "tls_minmax_client",
MQTTCLIENT_PERSISTENCE_NONE, NULL);
if (!(assert("good rc from create", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc)))
goto exit;

opts.keepAliveInterval = 20;
opts.cleansession = 1;

if (options.haconnections != NULL)
{
opts.serverURIs = options.haconnections;
opts.serverURIcount = options.hacount;
}

opts.ssl = &sslopts;
sslopts.tlsMin = 3;
sslopts.tlsMax = 3;
opts.ssl->enableServerCertAuth = 0;

MyLog(LOGA_DEBUG, "Connecting with TLS min=%d max=%d", sslopts.tlsMin, sslopts.tlsMax);

rc = MQTTClient_connect(c, &opts);
if (!(assert("Good rc from connect", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc)))
goto exit;

MyLog(LOGA_DEBUG, "Disconnecting");

rc = MQTTClient_disconnect(c, 1000);
if (!(assert("Disconnect successful", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc)))
goto exit;

exit:
MQTTClient_destroy(&c);
MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.",
(failures == 0) ? "passed" : "failed", testname, tests, failures);
write_test_result();
return failures;
}

int test8(struct Options options)
{
char* testname = "test_tls_minmax_no_overlap";
MQTTClient c;
MQTTClient_connectOptions opts = MQTTClient_connectOptions_initializer;
MQTTClient_SSLOptions sslopts = MQTTClient_SSLOptions_initializer;
int rc = 0;

failures = 0;
MyLog(LOGA_INFO, "Starting test - TLS min/max no overlap (expect failure)");
fprintf(xml, "<testcase classname=\"%s\" name=\"%s\"", testname, testname);
global_start_time = start_clock();

rc = MQTTClient_create(&c, options.tls_connection, "tls_no_overlap_client",
MQTTCLIENT_PERSISTENCE_NONE, NULL);
if (!(assert("good rc from create", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc)))
goto exit;

opts.keepAliveInterval = 20;
opts.cleansession = 1;

if (options.haconnections != NULL)
{
opts.serverURIs = options.haconnections;
opts.serverURIcount = options.hacount;
}

opts.ssl = &sslopts;
opts.ssl->enableServerCertAuth = 0;

sslopts.tlsMin = 1;
sslopts.tlsMax = 1;

MyLog(LOGA_DEBUG, "Connecting with TLS min=%d max=%d (expect failure)",
sslopts.tlsMin, sslopts.tlsMax);

rc = MQTTClient_connect(c, &opts);

if (!(assert("connect should fail due to no TLS overlap",
rc != MQTTCLIENT_SUCCESS,
"connect unexpectedly succeeded (rc=%d)\n", rc)))
goto exit;

exit:
MQTTClient_destroy(&c);
MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.",
(failures == 0) ? "passed" : "failed", testname, tests, failures);
write_test_result();
return failures;
}


typedef struct
{
Expand Down Expand Up @@ -1705,7 +1812,7 @@ int main(int argc, char** argv)
int* numtests = &tests;
int rc = 0;
int (*tests[])(struct Options) = {NULL, test1, test2a_s, test2a_m, test2b, test2c, test3a_s, test3a_m, test3b, test4_s, test4_m, test6,
test2e_s /*test5a, test5b,test5c */};
test2e_s, test7, test8 /*test5a, test5b,test5c */};
//MQTTClient_nameValue* info;

xml = fopen("TEST-test3.xml", "w");
Expand Down
9 changes: 9 additions & 0 deletions test/tls-testing/mosquitto.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ log_type notice
log_type information
#log_type debug


#log_dest file /var/log/mosquitto/tls-testing.log

allow_anonymous true
Expand Down Expand Up @@ -56,3 +57,11 @@ listener 18888
ciphers PSK-AES128-CBC-SHA
psk_hint Test
psk_file test/tls-testing/mosquitto.psk

# TLS min/max verification
listener 18889
cafile test/tls-testing/keys/all-ca.crt
certfile test/ssl/server.crt
keyfile test/ssl/server.key
require_certificate false
tls_version tlsv1.2