diff --git a/ChangeLog.txt b/ChangeLog.txt index d6e6b02f..03855e7d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -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://...` 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, @@ -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 ` and @@ -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://...`, 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 diff --git a/client/client_shared.c b/client/client_shared.c index 6d6f448a..a76000ac 100644 --- a/client/client_shared.c +++ b/client/client_shared.c @@ -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://", 8)) { url += 8; cfg->port = 8883; + cfg->tls_use_os_certs = true; } else { fprintf(stderr, "Error: unsupported URL scheme.\n\n"); return 1; @@ -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"); @@ -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(); diff --git a/client/client_shared.h b/client/client_shared.h index 0496f246..1e80b10c 100644 --- a/client/client_shared.h +++ b/client/client_shared.h @@ -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; diff --git a/client/pub_client.c b/client/pub_client.c index 7acfdbdd..618557ec 100644 --- a/client/pub_client.c +++ b/client/pub_client.c @@ -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 @@ -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"); diff --git a/client/rr_client.c b/client/rr_client.c index c496b2fc..e60f47a9 100644 --- a/client/rr_client.c +++ b/client/rr_client.c @@ -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 @@ -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"); diff --git a/client/sub_client.c b/client/sub_client.c index 797143fa..8412972c 100644 --- a/client/sub_client.c +++ b/client/sub_client.c @@ -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 @@ -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"); diff --git a/include/mosquitto.h b/include/mosquitto.h index 56040b8c..882dba89 100644 --- a/include/mosquitto.h +++ b/include/mosquitto.h @@ -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, }; @@ -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); diff --git a/lib/mosquitto_internal.h b/lib/mosquitto_internal.h index 813582c0..b2d49635 100644 --- a/lib/mosquitto_internal.h +++ b/lib/mosquitto_internal.h @@ -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; diff --git a/lib/net_mosq.c b/lib/net_mosq.c index e79aa4dc..3973f07c 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -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){ @@ -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(); @@ -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) diff --git a/lib/options.c b/lib/options.c index 4ce5c97b..68354cec 100644 --- a/lib/options.c +++ b/lib/options.c @@ -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; diff --git a/man/mosquitto_pub.1.xml b/man/mosquitto_pub.1.xml index 1856305c..adb2e2f0 100644 --- a/man/mosquitto_pub.1.xml +++ b/man/mosquitto_pub.1.xml @@ -75,6 +75,7 @@ engine kpass-sha1 + @@ -545,6 +546,20 @@ See also . + + + + + If used, this will load and trust the OS provided CA + certificates. This can be used in conjunction with + and + and can be used on its own to enable TLS mode. This + will be set by default if + is used, or if port is 8883 and no other certificate + options are used. + + + diff --git a/man/mosquitto_rr.1.xml b/man/mosquitto_rr.1.xml index 2fe4eed7..27309532 100644 --- a/man/mosquitto_rr.1.xml +++ b/man/mosquitto_rr.1.xml @@ -81,6 +81,7 @@ engine kpass-sha1 + @@ -562,6 +563,20 @@ See also . + + + + + If used, this will load and trust the OS provided CA + certificates. This can be used in conjunction with + and + and can be used on its own to enable TLS mode. This + will be set by default if + is used, or if port is 8883 and no other certificate + options are used. + + + diff --git a/man/mosquitto_sub.1.xml b/man/mosquitto_sub.1.xml index 002d96fb..58b9187b 100644 --- a/man/mosquitto_sub.1.xml +++ b/man/mosquitto_sub.1.xml @@ -83,6 +83,7 @@ engine kpass-sha1 + @@ -641,6 +642,20 @@ mosquitto_sub -t 'bbc/#' -T bbc/bbc1 --remove-retained See also . + + + + + If used, this will load and trust the OS provided CA + certificates. This can be used in conjunction with + and + and can be used on its own to enable TLS mode. This + will be set by default if + is used, or if port is 8883 and no other certificate + options are used. + + +