Skip to content

Commit

Permalink
Add lib and client support for OS CA certs
Browse files Browse the repository at this point in the history
- Add `MOSQ_OPT_TLS_USE_OS_CERTS` option, to instruct the client to load and  trust OS provided CA certificates for use with TLS connections.
- All clients now load OS provided CA certificates if used with `-L
  mqtts:https://...`, or if port is set to 8883 and no other CA certificates are
  used. Closes #1824.
- Add the `--tls-use-os-certs` option to all clients.

Closes #1824. Thanks to Jens Reimann.
  • Loading branch information
ralight committed Dec 1, 2020
1 parent c2f62f0 commit 29c771c
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 23 deletions.
10 changes: 10 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ Breaking changes:
be used, rather than the exact version. Closes #1258.
- The `max_queued_messages` option has been increased from 100 to 1000 by
default, and now also applies to QoS 0 messages, when a client is connected.
- The mosquitto_sub, mosquitto_pub, and mosquitto_rr clients will now load
OS provided CA certificates by default if `-L mqtts:https://...` is used, or if
the port is set to 8883 and no other CA certificates are loaded.


Broker:
- When running as root, if dropping privileges to the "mosquitto" user fails,
Expand Down Expand Up @@ -113,6 +117,8 @@ Client library:
of the `mosquitto_connect*()` call.
- Fix connect properties not being sent when the client automatically
reconnects. Closes #1846.
- Add `MOSQ_OPT_TLS_USE_OS_CERTS` option, to instruct the client to load and
trust OS provided CA certificates for use with TLS connections.

Clients:
- Add timeout return code (27) for `mosquitto_sub -W <secs>` and
Expand Down Expand Up @@ -141,6 +147,10 @@ Clients:
- Fix description of `-e` and `-t` arguments in mosquitto_rr. Closes #1881.
- mosquitto_sub will now quit with an error if the %U option is used on
Windows, rather than just quitting. Closes #1908.
- All clients now load OS provided CA certificates if used with `-L
mqtts:https://...`, or if port is set to 8883 and no other CA certificates are
used. Closes #1824.
- Add the `--tls-use-os-certs` option to all clients.


1.6.12 - 2020-08-19
Expand Down
9 changes: 9 additions & 0 deletions client/client_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
} else if(!strncasecmp(url, "mqtts:https://", 8)) {
url += 8;
cfg->port = 8883;
cfg->tls_use_os_certs = true;
} else {
fprintf(stderr, "Error: unsupported URL scheme.\n\n");
return 1;
Expand Down Expand Up @@ -1049,6 +1050,8 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
cfg->tls_engine_kpass_sha1 = strdup(argv[i+1]);
}
i++;
}else if(!strcmp(argv[i], "--tls-use-os-certs")){
cfg->tls_use_os_certs = true;
}else if(!strcmp(argv[i], "--tls-version")){
if(i==argc-1){
fprintf(stderr, "Error: --tls-version argument given but no version specified.\n\n");
Expand Down Expand Up @@ -1253,7 +1256,13 @@ int client_opts_set(struct mosquitto *mosq, struct mosq_config *cfg)
mosquitto_lib_cleanup();
return 1;
}
}else if(cfg->port == 8883){
mosquitto_int_option(mosq, MOSQ_OPT_TLS_USE_OS_CERTS, 1);
}
if(cfg->tls_use_os_certs){
mosquitto_int_option(mosq, MOSQ_OPT_TLS_USE_OS_CERTS, 1);
}

if(cfg->insecure && mosquitto_tls_insecure_set(mosq, true)){
err_printf(cfg, "Error: Problem setting TLS insecure option.\n");
mosquitto_lib_cleanup();
Expand Down
1 change: 1 addition & 0 deletions client/client_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct mosq_config {
char *tls_engine;
char *tls_engine_kpass_sha1;
char *keyform;
bool tls_use_os_certs;
# ifdef FINAL_WITH_TLS_PSK
char *psk;
char *psk_identity;
Expand Down
2 changes: 2 additions & 0 deletions client/pub_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ void print_usage(void)
printf(" [--ciphers ciphers] [--insecure]\n");
printf(" [--tls-alpn protocol]\n");
printf(" [--tls-engine engine] [--keyform keyform] [--tls-engine-kpass-sha1]]\n");
printf(" [--tls-use-os-certs]\n");
#ifdef FINAL_WITH_TLS_PSK
printf(" [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n");
#endif
Expand Down Expand Up @@ -496,6 +497,7 @@ void print_usage(void)
printf(" Do not use this option in a production environment.\n");
printf(" --tls-engine : If set, enables the use of a TLS engine device.\n");
printf(" --tls-engine-kpass-sha1 : SHA1 of the key password to be used with the selected SSL engine.\n");
printf(" --tls-use-os-certs : Load and trust OS provided CA certificates.\n");
# ifdef FINAL_WITH_TLS_PSK
printf(" --psk : pre-shared-key in hexadecimal (no leading 0x) to enable TLS-PSK mode.\n");
printf(" --psk-identity : client identity string for TLS-PSK mode.\n");
Expand Down
4 changes: 3 additions & 1 deletion client/rr_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ void print_usage(void)
printf(" [--ciphers ciphers] [--insecure]\n");
printf(" [--tls-alpn protocol]\n");
printf(" [--tls-engine engine] [--keyform keyform] [--tls-engine-kpass-sha1]]\n");
printf(" [--tls-use-os-certs]\n");
#ifdef FINAL_WITH_TLS_PSK
printf(" [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n");
#endif
Expand Down Expand Up @@ -262,7 +263,8 @@ void print_usage(void)
printf(" --cert : client certificate for authentication, if required by server.\n");
printf(" --key : client private key for authentication, if required by server.\n");
printf(" --ciphers : openssl compatible list of TLS ciphers to support.\n");
printf(" --tls-version : TLS protocol version, can be one of tlsv1.2 tlsv1.1 or tlsv1.\n");
printf(" --tls-use-os-certs : Load and trust OS provided CA certificates.\n");
printf(" --tls-version : TLS protocol version, can be one of tlsv1.3 tlsv1.2 or tlsv1.1.\n");
printf(" Defaults to tlsv1.2 if available.\n");
printf(" --insecure : do not check that the server certificate hostname matches the remote\n");
printf(" hostname. Using this option means that you cannot be sure that the\n");
Expand Down
2 changes: 2 additions & 0 deletions client/sub_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ void print_usage(void)
printf(" [--ciphers ciphers] [--insecure]\n");
printf(" [--tls-alpn protocol]\n");
printf(" [--tls-engine engine] [--keyform keyform] [--tls-engine-kpass-sha1]]\n");
printf(" [--tls-use-os-certs]\n");
#ifdef FINAL_WITH_TLS_PSK
printf(" [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n");
#endif
Expand Down Expand Up @@ -300,6 +301,7 @@ void print_usage(void)
printf(" Do not use this option in a production environment.\n");
printf(" --tls-engine : If set, enables the use of a SSL engine device.\n");
printf(" --tls-engine-kpass-sha1 : SHA1 of the key password to be used with the selected SSL engine.\n");
printf(" --tls-use-os-certs : Load and trust OS provided CA certificates.\n");
#ifdef FINAL_WITH_TLS_PSK
printf(" --psk : pre-shared-key in hexadecimal (no leading 0x) to enable TLS-PSK mode.\n");
printf(" --psk-identity : client identity string for TLS-PSK mode.\n");
Expand Down
5 changes: 5 additions & 0 deletions include/mosquitto.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ enum mosq_opt_t {
MOSQ_OPT_TLS_ALPN = 10,
MOSQ_OPT_TCP_NODELAY = 11,
MOSQ_OPT_BIND_ADDRESS = 12,
MOSQ_OPT_TLS_USE_OS_CERTS = 13,
};


Expand Down Expand Up @@ -1451,6 +1452,10 @@ libmosq_EXPORT int mosquitto_opts_set(struct mosquitto *mosq, enum mosq_opt_t op
* MOSQ_OPT_TLS_OCSP_REQUIRED - Set whether OCSP checking on TLS
* connections is required. Set to 1 to enable checking,
* or 0 (the default) for no checking.
*
* MOSQ_OPT_TLS_USE_OS_CERTS - Set to 1 to instruct the client to load and
* trust OS provided CA certificates for use with TLS connections.
* Set to 0 (the default) to only use manually specified CA certs.
*/
libmosq_EXPORT int mosquitto_int_option(struct mosquitto *mosq, enum mosq_opt_t option, int value);

Expand Down
7 changes: 4 additions & 3 deletions lib/mosquitto_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,15 @@ struct mosquitto {
char *tls_ciphers;
char *tls_psk;
char *tls_psk_identity;
char *tls_engine;
char *tls_engine_kpass_sha1;
char *tls_alpn;
int tls_cert_reqs;
bool tls_insecure;
bool ssl_ctx_defaults;
bool tls_ocsp_required;
char *tls_engine;
char *tls_engine_kpass_sha1;
bool tls_use_os_certs;
enum mosquitto__keyform tls_keyform;
char *tls_alpn;
#endif
bool want_write;
bool want_connect;
Expand Down
43 changes: 24 additions & 19 deletions lib/net_mosq.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,27 +602,32 @@ static int net__tls_load_ca(struct mosquitto *mosq)
{
int ret;

if(mosq->tls_use_os_certs){
SSL_CTX_set_default_verify_paths(mosq->ssl_ctx);
}
#if OPENSSL_VERSION_NUMBER < 0x30000000L
ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath);
if(ret == 0){
if(mosq->tls_cafile || mosq->tls_capath){
ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath);
if(ret == 0){
# ifdef WITH_BROKER
if(mosq->tls_cafile && mosq->tls_capath){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
}else if(mosq->tls_cafile){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile);
}else{
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath);
}
if(mosq->tls_cafile && mosq->tls_capath){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
}else if(mosq->tls_cafile){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile);
}else{
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath);
}
# else
if(mosq->tls_cafile && mosq->tls_capath){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
}else if(mosq->tls_cafile){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile);
}else{
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath);
}
if(mosq->tls_cafile && mosq->tls_capath){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
}else if(mosq->tls_cafile){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile);
}else{
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath);
}
# endif
return MOSQ_ERR_TLS;
return MOSQ_ERR_TLS;
}
}
#else
if(mosq->tls_cafile){
Expand Down Expand Up @@ -674,7 +679,7 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
/* Apply default SSL_CTX settings. This is only used if MOSQ_OPT_SSL_CTX
* has not been set, or if both of MOSQ_OPT_SSL_CTX and
* MOSQ_OPT_SSL_CTX_WITH_DEFAULTS are set. */
if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk || mosq->tls_use_os_certs){
if(!mosq->ssl_ctx){
net__init_tls();

Expand Down Expand Up @@ -750,7 +755,7 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
return MOSQ_ERR_TLS;
}
}
if(mosq->tls_cafile || mosq->tls_capath){
if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_use_os_certs){
ret = net__tls_load_ca(mosq);
if(ret != MOSQ_ERR_SUCCESS){
# if !defined(OPENSSL_NO_ENGINE)
Expand Down
12 changes: 12 additions & 0 deletions lib/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,18 @@ int mosquitto_int_option(struct mosquitto *mosq, enum mosq_opt_t option, int val
return MOSQ_ERR_NOT_SUPPORTED;
#endif

case MOSQ_OPT_TLS_USE_OS_CERTS:
#ifdef WITH_TLS
if(value){
mosq->tls_use_os_certs = true;
}else{
mosq->tls_use_os_certs = false;
}
break;
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif

case MOSQ_OPT_TLS_OCSP_REQUIRED:
#ifdef WITH_TLS
mosq->tls_ocsp_required = (bool)value;
Expand Down
15 changes: 15 additions & 0 deletions man/mosquitto_pub.1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
<arg choice='plain'><replaceable>engine</replaceable></arg>
</group></arg>
<arg><option>--tls-engine-kpass-sha1</option> <replaceable>kpass-sha1</replaceable></arg>
<arg><option>--tls-use-os-certs</option></arg>
<arg><option>--insecure</option></arg>
</arg>
<arg>
Expand Down Expand Up @@ -545,6 +546,20 @@
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-use-os-certs</option></term>
<listitem>
<para>
If used, this will load and trust the OS provided CA
certificates. This can be used in conjunction with
<option>--cafile</option> and <option>--capath</option>
and can be used on its own to enable TLS mode. This
will be set by default if <option>-L mqtts:https://...</option>
is used, or if port is 8883 and no other certificate
options are used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-version</option></term>
<listitem>
Expand Down
15 changes: 15 additions & 0 deletions man/mosquitto_rr.1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
<arg choice='plain'><replaceable>engine</replaceable></arg>
</group></arg>
<arg><option>--tls-engine-kpass-sha1</option> <replaceable>kpass-sha1</replaceable></arg>
<arg><option>--tls-use-os-certs</option></arg>
<arg><option>--insecure</option></arg>
</arg>
<arg>
Expand Down Expand Up @@ -562,6 +563,20 @@
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-use-os-certs</option></term>
<listitem>
<para>
If used, this will load and trust the OS provided CA
certificates. This can be used in conjunction with
<option>--cafile</option> and <option>--capath</option>
and can be used on its own to enable TLS mode. This
will be set by default if <option>-L mqtts:https://...</option>
is used, or if port is 8883 and no other certificate
options are used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-version</option></term>
<listitem>
Expand Down
15 changes: 15 additions & 0 deletions man/mosquitto_sub.1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<arg choice='plain'><replaceable>engine</replaceable></arg>
</group></arg>
<arg><option>--tls-engine-kpass-sha1</option> <replaceable>kpass-sha1</replaceable></arg>
<arg><option>--tls-use-os-certs</option></arg>
<arg><option>--insecure</option></arg>
</arg>
<arg>
Expand Down Expand Up @@ -641,6 +642,20 @@ mosquitto_sub -t 'bbc/#' -T bbc/bbc1 --remove-retained</programlisting>
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-use-os-certs</option></term>
<listitem>
<para>
If used, this will load and trust the OS provided CA
certificates. This can be used in conjunction with
<option>--cafile</option> and <option>--capath</option>
and can be used on its own to enable TLS mode. This
will be set by default if <option>-L mqtts:https://...</option>
is used, or if port is 8883 and no other certificate
options are used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-version</option></term>
<listitem>
Expand Down

0 comments on commit 29c771c

Please sign in to comment.