Rework TLS engine support.

This commit is contained in:
Roger A. Light 2019-02-26 17:11:29 +00:00
parent 20894fcbce
commit e862a047a8
20 changed files with 230 additions and 254 deletions

View File

@ -152,7 +152,7 @@ void client_config_cleanup(struct mosq_config *cfg)
free(cfg->ciphers); free(cfg->ciphers);
free(cfg->tls_version); free(cfg->tls_version);
free(cfg->tls_engine); free(cfg->tls_engine);
free(cfg->tls_engine_kpass_sha); free(cfg->tls_engine_kpass_sha1);
free(cfg->keyform); free(cfg->keyform);
# ifdef WITH_TLS_PSK # ifdef WITH_TLS_PSK
free(cfg->psk); free(cfg->psk);
@ -308,15 +308,15 @@ int client_config_load(struct mosq_config *cfg, int pub_or_sub, int argc, char *
} }
#ifdef WITH_TLS #ifdef WITH_TLS
if((cfg->certfile && !cfg->keyfile) || (cfg->keyfile && !cfg->certfile)){ if((cfg->certfile && !cfg->keyfile) || (cfg->keyfile && !cfg->certfile)){
fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is.\n"); fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is set.\n");
return 1; return 1;
} }
if((cfg->keyform && !cfg->keyfile)){ if((cfg->keyform && !cfg->keyfile)){
fprintf(stderr, "Error: keyfile must be specified if keyform is.\n"); fprintf(stderr, "Error: If keyform is set, keyfile must be also specified.\n");
return 1; return 1;
} }
if((cfg->tls_engine_kpass_sha && (!cfg->keyform || !cfg->tls_engine))){ if((cfg->tls_engine_kpass_sha1 && (!cfg->keyform || !cfg->tls_engine))){
fprintf(stderr, "Error: when using tls-engine-kpass-sha, both tls-engine and keyform must also be provided.\n"); fprintf(stderr, "Error: when using tls-engine-kpass-sha1, both tls-engine and keyform must also be provided.\n");
return 1; return 1;
} }
#endif #endif
@ -444,12 +444,12 @@ int client_config_line_proc(struct mosq_config *cfg, int pub_or_sub, int argc, c
cfg->tls_engine = strdup(argv[i+1]); cfg->tls_engine = strdup(argv[i+1]);
} }
i++; i++;
}else if(!strcmp(argv[i], "--tls-engine-kpass-sha")){ }else if(!strcmp(argv[i], "--tls-engine-kpass-sha1")){
if(i==argc-1){ if(i==argc-1){
fprintf(stderr, "Error: --tls-engine-kpass-sha argument given but no kpass sha specified.\n\n"); fprintf(stderr, "Error: --tls-engine-kpass-sha1 argument given but no kpass sha1 specified.\n\n");
return 1; return 1;
}else{ }else{
cfg->tls_engine_kpass_sha = strdup(argv[i+1]); cfg->tls_engine_kpass_sha1 = strdup(argv[i+1]);
} }
i++; i++;
#endif #endif
@ -952,17 +952,17 @@ int client_opts_set(struct mosquitto *mosq, struct mosq_config *cfg)
mosquitto_lib_cleanup(); mosquitto_lib_cleanup();
return 1; return 1;
} }
if(cfg->tls_engine && mosquitto_tls_engine_set(mosq, cfg->tls_engine)){ if(cfg->tls_engine && mosquitto_string_option(mosq, MOSQ_OPT_TLS_ENGINE, cfg->tls_engine)){
if(!cfg->quiet) fprintf(stderr, "Error: Problem setting TLS engine.\n"); if(!cfg->quiet) fprintf(stderr, "Error: Problem setting TLS engine.\n");
mosquitto_lib_cleanup(); mosquitto_lib_cleanup();
return 1; return 1;
} }
if(cfg->keyform && mosquitto_tls_keyform_set(mosq, cfg->keyform)){ if(cfg->keyform && mosquitto_string_option(mosq, MOSQ_OPT_TLS_KEYFORM, cfg->keyform)){
if(!cfg->quiet) fprintf(stderr, "Error: Problem setting keyform.\n"); if(!cfg->quiet) fprintf(stderr, "Error: Problem setting keyform.\n");
mosquitto_lib_cleanup(); mosquitto_lib_cleanup();
return 1; return 1;
} }
if(cfg->tls_engine_kpass_sha && mosquitto_tls_engine_kpass_sha_set(mosq, cfg->tls_engine_kpass_sha)){ if(cfg->tls_engine_kpass_sha1 && mosquitto_string_option(mosq, MOSQ_OPT_TLS_ENGINE_KPASS_SHA1, cfg->tls_engine_kpass_sha1)){
if(!cfg->quiet) fprintf(stderr, "Error: Problem setting TLS engine key pass sha.\n"); if(!cfg->quiet) fprintf(stderr, "Error: Problem setting TLS engine key pass sha.\n");
mosquitto_lib_cleanup(); mosquitto_lib_cleanup();
return 1; return 1;

View File

@ -67,7 +67,7 @@ struct mosq_config {
bool insecure; bool insecure;
char *tls_version; char *tls_version;
char *tls_engine; char *tls_engine;
char *tls_engine_kpass_sha; char *tls_engine_kpass_sha1;
char *keyform; char *keyform;
# ifdef WITH_TLS_PSK # ifdef WITH_TLS_PSK
char *psk; char *psk;

View File

@ -222,8 +222,8 @@ void print_usage(void)
printf(" [--will-topic [--will-payload payload] [--will-qos qos] [--will-retain]]\n"); printf(" [--will-topic [--will-payload payload] [--will-qos qos] [--will-retain]]\n");
#ifdef WITH_TLS #ifdef WITH_TLS
printf(" [{--cafile file | --capath dir} [--cert file] [--key file]\n"); printf(" [{--cafile file | --capath dir} [--cert file] [--key file]\n");
printf(" [--ciphers ciphers] [--insecure] [--tls-engine engine]\n"); printf(" [--ciphers ciphers] [--insecure]\n");
printf(" [--keyform keyform] [--tls-engine-kpass-sha]]\n"); printf(" [--tls-engine engine] [--keyform keyform] [--tls-engine-kpass-sha1]]\n");
#ifdef WITH_TLS_PSK #ifdef WITH_TLS_PSK
printf(" [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n"); printf(" [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n");
#endif #endif
@ -274,7 +274,7 @@ void print_usage(void)
printf(" communication.\n"); printf(" communication.\n");
printf(" --cert : client certificate for authentication, if required by server.\n"); printf(" --cert : client certificate for authentication, if required by server.\n");
printf(" --key : client private key for authentication, if required by server.\n"); printf(" --key : client private key for authentication, if required by server.\n");
printf(" --keyform : keyfile type, can be one of pem or engine.\n"); printf(" --keyform : keyfile type, can be either \"pem\" or \"engine\".\n");
printf(" --ciphers : openssl compatible list of TLS ciphers to support.\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-version : TLS protocol version, can be one of tlsv1.2 tlsv1.1 or tlsv1.\n");
printf(" Defaults to tlsv1.2 if available.\n"); printf(" Defaults to tlsv1.2 if available.\n");
@ -282,8 +282,8 @@ void print_usage(void)
printf(" hostname. Using this option means that you cannot be sure that the\n"); printf(" hostname. Using this option means that you cannot be sure that the\n");
printf(" remote host is the server you wish to connect to and so is insecure.\n"); printf(" remote host is the server you wish to connect to and so is insecure.\n");
printf(" Do not use this option in a production environment.\n"); printf(" Do not use this option in a production environment.\n");
printf(" --tls-engine : toggles the usage of a SSL engine device.\n"); printf(" --tls-engine : If set, enables the use of a SSL engine device.\n");
printf(" --tls-engine-kpass-sha : SHA1 of the key password to be used with the selected SSL engine.\n"); printf(" --tls-engine-kpass-sha1 : SHA1 of the key password to be used with the selected SSL engine.\n");
# ifdef WITH_TLS_PSK # ifdef WITH_TLS_PSK
printf(" --psk : pre-shared-key in hexadecimal (no leading 0x) to enable TLS-PSK mode.\n"); 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"); printf(" --psk-identity : client identity string for TLS-PSK mode.\n");

View File

@ -158,7 +158,7 @@ void print_usage(void)
#ifdef WITH_TLS #ifdef WITH_TLS
printf(" [{--cafile file | --capath dir} [--cert file] [--key file]\n"); printf(" [{--cafile file | --capath dir} [--cert file] [--key file]\n");
printf(" [--ciphers ciphers] [--insecure] [--tls-engine engine]\n"); printf(" [--ciphers ciphers] [--insecure] [--tls-engine engine]\n");
printf(" [--keyform keyform] [--tls-engine-kpass-sha]]\n"); printf(" [--keyform keyform] [--tls-engine-kpass-sha1]]\n");
#ifdef WITH_TLS_PSK #ifdef WITH_TLS_PSK
printf(" [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n"); printf(" [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n");
#endif #endif
@ -216,7 +216,7 @@ void print_usage(void)
printf(" communication.\n"); printf(" communication.\n");
printf(" --cert : client certificate for authentication, if required by server.\n"); printf(" --cert : client certificate for authentication, if required by server.\n");
printf(" --key : client private key for authentication, if required by server.\n"); printf(" --key : client private key for authentication, if required by server.\n");
printf(" --keyform : keyfile type, can be one of pem or engine.\n"); printf(" --keyform : keyfile type, can be either \"pem\" or \"engine\".\n");
printf(" --ciphers : openssl compatible list of TLS ciphers to support.\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-version : TLS protocol version, can be one of tlsv1.2 tlsv1.1 or tlsv1.\n");
printf(" Defaults to tlsv1.2 if available.\n"); printf(" Defaults to tlsv1.2 if available.\n");
@ -224,8 +224,8 @@ void print_usage(void)
printf(" hostname. Using this option means that you cannot be sure that the\n"); printf(" hostname. Using this option means that you cannot be sure that the\n");
printf(" remote host is the server you wish to connect to and so is insecure.\n"); printf(" remote host is the server you wish to connect to and so is insecure.\n");
printf(" Do not use this option in a production environment.\n"); printf(" Do not use this option in a production environment.\n");
printf(" --tls-engine : toggles the usage of a SSL engine device.\n"); printf(" --tls-engine : If set, enables the use of a SSL engine device.\n");
printf(" --tls-engine-kpass-sha : SHA1 of the key password to be used with the selected SSL engine.\n"); printf(" --tls-engine-kpass-sha1 : SHA1 of the key password to be used with the selected SSL engine.\n");
#ifdef WITH_TLS_PSK #ifdef WITH_TLS_PSK
printf(" --psk : pre-shared-key in hexadecimal (no leading 0x) to enable TLS-PSK mode.\n"); 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"); printf(" --psk-identity : client identity string for TLS-PSK mode.\n");

View File

@ -17,6 +17,8 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#define OPENSSL_LOAD_CONF
/* ============================================================ /* ============================================================
* Compatibility defines * Compatibility defines
* ============================================================ */ * ============================================================ */

View File

@ -366,19 +366,4 @@ int mosquittopp::tls_psk_set(const char *psk, const char *identity, const char *
return mosquitto_tls_psk_set(m_mosq, psk, identity, ciphers); return mosquitto_tls_psk_set(m_mosq, psk, identity, ciphers);
} }
int mosquittopp::tls_engine_set(const char *engine_id)
{
return mosquitto_tls_engine_set(m_mosq, engine_id);
}
int mosquittopp::tls_keyform_set(const char *keyform)
{
return mosquitto_tls_keyform_set(m_mosq, keyform);
}
int mosquittopp::tls_engine_kpass_sha_set(const char *kpass_sha)
{
return mosquitto_tls_engine_kpass_sha_set(m_mosq, kpass_sha);
}
} }

View File

@ -110,9 +110,6 @@ class mosqpp_EXPORT mosquittopp {
int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL); int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL);
int tls_insecure_set(bool value); int tls_insecure_set(bool value);
int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL); int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL);
int tls_engine_set(const char *engine_id);
int tls_keyform_set(const char *keyform);
int tls_engine_kpass_sha_set(const char *kpass_sha);
int opts_set(enum mosq_opt_t option, void *value); int opts_set(enum mosq_opt_t option, void *value);
int loop(int timeout=-1, int max_packets=1); int loop(int timeout=-1, int max_packets=1);

View File

@ -90,12 +90,10 @@ MOSQ_1.5 {
mosquitto_sub_topic_check2; mosquitto_sub_topic_check2;
mosquitto_topic_matches_sub2; mosquitto_topic_matches_sub2;
mosquitto_connect_with_flags_callback_set; mosquitto_connect_with_flags_callback_set;
mosquitto_tls_engine_set;
mosquitto_tls_keyform_set;
mosquitto_tls_engine_kpass_sha_set;
} MOSQ_1.4; } MOSQ_1.4;
MOSQ_1.6 { MOSQ_1.6 {
global: global:
mosquitto_string_option;
mosquitto_subscribe_multiple; mosquitto_subscribe_multiple;
} MOSQ_1.5; } MOSQ_1.5;

View File

@ -94,8 +94,13 @@ enum mosq_opt_t {
MOSQ_OPT_PROTOCOL_VERSION = 1, MOSQ_OPT_PROTOCOL_VERSION = 1,
MOSQ_OPT_SSL_CTX = 2, MOSQ_OPT_SSL_CTX = 2,
MOSQ_OPT_SSL_CTX_WITH_DEFAULTS = 3, MOSQ_OPT_SSL_CTX_WITH_DEFAULTS = 3,
MOSQ_OPT_TLS_KEYFORM = 6,
MOSQ_OPT_TLS_ENGINE = 7,
MOSQ_OPT_TLS_ENGINE_KPASS_SHA1 = 8,
}; };
/* MQTT specification restricts client ids to a maximum of 23 characters */ /* MQTT specification restricts client ids to a maximum of 23 characters */
#define MOSQ_MQTT_ID_MAX_LENGTH 23 #define MOSQ_MQTT_ID_MAX_LENGTH 23
@ -1160,65 +1165,6 @@ libmosq_EXPORT int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs,
*/ */
libmosq_EXPORT int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers); libmosq_EXPORT int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers);
/*
* Function: mosquitto_tls_engine_set
*
* Configure the client for TLS engine support. Must be called
* before <mosquitto_connect>.
*
* Parameters:
* mosq - a valid mosquitto instance.
* engine_id - the engine ID that wants to be used.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
*
* See Also:
* <mosquitto_tls_set>
*/
libmosq_EXPORT int mosquitto_tls_engine_set(struct mosquitto *mosq, const char *engine_id);
/*
* Function: mosquitto_tls_keyform_set
*
* Configure the client to treat the keyfile differently depending on its type.
* Must be called before <mosquitto_connect>.
*
* Parameters:
* mosq - a valid mosquitto instance.
* keyform - the key type. Currently only "pem" or "engine" are supported.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
*
* See Also:
* <mosquitto_tls_set>
*/
libmosq_EXPORT int mosquitto_tls_keyform_set(struct mosquitto *mosq, const char *keyform);
/*
* Function: mosquitto_tls_engine_kpass_sha_set
*
* Some SSL engines may require the usage of a password in order to being
* accessed, like the TPM engine. This function allows a SHA1 hash of the
* password to be passed on to the engine directly.
* Must be called before <mosquitto_connect>.
*
* Parameters:
* mosq - a valid mosquitto instance.
* kpass_sha - SHA1 of the private key password.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success.
* MOSQ_ERR_INVAL - if the input parameters were invalid.
*
* See Also:
* <mosquitto_tls_set>
*/
libmosq_EXPORT int mosquitto_tls_engine_kpass_sha_set(struct mosquitto *mosq, const char *kpass_sha);
/* /*
* Function: mosquitto_connect_callback_set * Function: mosquitto_connect_callback_set
* *
@ -1391,6 +1337,37 @@ libmosq_EXPORT void mosquitto_unsubscribe_callback_set(struct mosquitto *mosq, v
*/ */
libmosq_EXPORT void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mosquitto *, void *, int, const char *)); libmosq_EXPORT void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mosquitto *, void *, int, const char *));
/*
* Function: mosquitto_string_option
*
* Used to set const char* options for the client.
*
* Parameters:
* mosq - a valid mosquitto instance.
* option - the option to set.
* value - the option specific value.
*
* Options:
* MOSQ_OPT_TLS_ENGINE
* Configure the client for TLS Engine support. Pass a TLS Engine ID
* to be used when creating TLS connections.
* Must be set before <mosquitto_connect>.
* MOSQ_OPT_TLS_KEYFORM
* Configure the client to treat the keyfile differently depending
* on its type. Must be set before <mosquitto_connect>.
* Set as either "pem" or "engine", to determine from where the
* private key for a TLS connection will be obtained. Defaults to
* "pem", a normal private key file.
* MOSQ_OPT_TLS_KPASS_SHA1
* Where the TLS Engine requires the use of a password to be
* accessed, this option allows a hex encoded SHA1 hash of the
* private key password to be passed to the engine directly.
* Must be set before <mosquitto_connect>.
*/
libmosq_EXPORT int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, const char *value);
/* /*
* Function: mosquitto_reconnect_delay_set * Function: mosquitto_reconnect_delay_set
* *

View File

@ -154,7 +154,7 @@ struct mosquitto_message_all{
}; };
#ifdef WITH_TLS #ifdef WITH_TLS
enum _mosquitto_keyform { enum mosquitto__keyform {
mosq_k_pem = 0, mosq_k_pem = 0,
mosq_k_engine = 1, mosq_k_engine = 1,
}; };
@ -199,8 +199,8 @@ struct mosquitto {
bool tls_insecure; bool tls_insecure;
bool ssl_ctx_defaults; bool ssl_ctx_defaults;
char *tls_engine; char *tls_engine;
char *tls_engine_kpass_sha; char *tls_engine_kpass_sha1;
enum _mosquitto_keyform tls_keyform; enum mosquitto__keyform tls_keyform;
#endif #endif
bool want_write; bool want_write;
bool want_connect; bool want_connect;

View File

@ -126,7 +126,6 @@ int net__init(void)
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
ENGINE_load_builtin_engines(); ENGINE_load_builtin_engines();
setup_ui_method(); setup_ui_method();
if(tls_ex_index_mosq == -1){ if(tls_ex_index_mosq == -1){
@ -616,15 +615,15 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
if(mosq->tls_keyfile){ if(mosq->tls_keyfile){
if(mosq->tls_keyform == mosq_k_engine){ if(mosq->tls_keyform == mosq_k_engine){
UI_METHOD *ui_method = net__get_ui_method(); UI_METHOD *ui_method = net__get_ui_method();
if(mosq->tls_engine_kpass_sha){ if(mosq->tls_engine_kpass_sha1){
if(!ENGINE_ctrl_cmd(engine, ENGINE_SECRET_MODE, ENGINE_SECRET_MODE_SHA, NULL, NULL, 0)){ if(!ENGINE_ctrl_cmd(engine, ENGINE_SECRET_MODE, ENGINE_SECRET_MODE_SHA, NULL, NULL, 0)){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set engine secret mode sha"); log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set engine secret mode sha1");
ENGINE_FINISH(engine); ENGINE_FINISH(engine);
COMPAT_CLOSE(mosq->sock); COMPAT_CLOSE(mosq->sock);
net__print_ssl_error(mosq); net__print_ssl_error(mosq);
return MOSQ_ERR_TLS; return MOSQ_ERR_TLS;
} }
if(!ENGINE_ctrl_cmd(engine, ENGINE_PIN, 0, mosq->tls_engine_kpass_sha, NULL, 0)){ if(!ENGINE_ctrl_cmd(engine, ENGINE_PIN, 0, mosq->tls_engine_kpass_sha1, NULL, 0)){
log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set engine pin"); log__printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set engine pin");
ENGINE_FINISH(engine); ENGINE_FINISH(engine);
COMPAT_CLOSE(mosq->sock); COMPAT_CLOSE(mosq->sock);

View File

@ -22,6 +22,10 @@ Contributors:
#include <string.h> #include <string.h>
#ifdef WITH_TLS
# include <openssl/engine.h>
#endif
#include "mosquitto.h" #include "mosquitto.h"
#include "mosquitto_internal.h" #include "mosquitto_internal.h"
#include "memory_mosq.h" #include "memory_mosq.h"
@ -219,55 +223,66 @@ int mosquitto_tls_insecure_set(struct mosquitto *mosq, bool value)
} }
int mosquitto_tls_engine_set(struct mosquitto *mosq, const char *engine_id) int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, const char *value)
{ {
#ifdef WITH_TLS #ifdef WITH_TLS
if(!mosq) return MOSQ_ERR_INVAL; ENGINE *eng;
ENGINE *e = ENGINE_by_id(engine_id); char *str;
if (!e)
return MOSQ_ERR_INVAL;
ENGINE_free(e); /* release the structural reference from ENGINE_by_id() */
mosq->tls_engine = mosquitto__strdup(engine_id);
return MOSQ_ERR_SUCCESS;
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif #endif
}
int mosquitto_tls_keyform_set(struct mosquitto *mosq, const char *keyform)
{
#ifdef WITH_TLS
if(!mosq) return MOSQ_ERR_INVAL; if(!mosq) return MOSQ_ERR_INVAL;
if (keyform){ switch(option){
if(!strcasecmp(keyform, "pem")) case MOSQ_OPT_TLS_ENGINE:
mosq->tls_keyform = mosq_k_pem; #ifdef WITH_TLS
else if (!strcasecmp(keyform, "engine")) eng = ENGINE_by_id(value);
mosq->tls_keyform = mosq_k_engine; if(!eng){
else return MOSQ_ERR_INVAL;
}
ENGINE_free(eng); /* release the structural reference from ENGINE_by_id() */
mosq->tls_engine = mosquitto__strdup(value);
if(!mosq->tls_engine){
return MOSQ_ERR_NOMEM;
}
return MOSQ_ERR_SUCCESS;
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif
break;
case MOSQ_OPT_TLS_KEYFORM:
#ifdef WITH_TLS
if(!value) return MOSQ_ERR_INVAL;
if(!strcasecmp(value, "pem")){
mosq->tls_keyform = mosq_k_pem;
}else if (!strcasecmp(value, "engine")){
mosq->tls_keyform = mosq_k_engine;
}else{
return MOSQ_ERR_INVAL;
}
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif
break;
case MOSQ_OPT_TLS_ENGINE_KPASS_SHA1:
#ifdef WITH_TLS
if(mosquitto__hex2bin_sha1(value, (unsigned char**)&str) != MOSQ_ERR_SUCCESS){
return MOSQ_ERR_INVAL;
}
mosq->tls_engine_kpass_sha1 = str;
return MOSQ_ERR_SUCCESS;
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif
break;
default:
return MOSQ_ERR_INVAL; return MOSQ_ERR_INVAL;
}else{
mosq->tls_keyform = mosq_k_pem;
} }
return MOSQ_ERR_SUCCESS;
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif
}
return MOSQ_ERR_INVAL;
int mosquitto_tls_engine_kpass_sha_set(struct mosquitto *mosq, const char *kpass_sha)
{
#ifdef WITH_TLS
if(!mosq) return MOSQ_ERR_INVAL;
char *kpass_sha_bin = NULL;
if(mosquitto__hex2bin_sha1(kpass_sha, (unsigned char**)&kpass_sha_bin) != MOSQ_ERR_SUCCESS) return MOSQ_ERR_INVAL;
mosq->tls_engine_kpass_sha = kpass_sha_bin;
return MOSQ_ERR_SUCCESS;
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif
} }

View File

@ -351,17 +351,16 @@ int mosquitto__hex2bin_sha1(const char *hex, unsigned char **bin)
{ {
unsigned char *sha, tmp[SHA_DIGEST_LENGTH]; unsigned char *sha, tmp[SHA_DIGEST_LENGTH];
if(mosquitto__hex2bin(hex, tmp, SHA_DIGEST_LENGTH) != SHA_DIGEST_LENGTH) if(mosquitto__hex2bin(hex, tmp, SHA_DIGEST_LENGTH) != SHA_DIGEST_LENGTH){
return MOSQ_ERR_INVAL; return MOSQ_ERR_INVAL;
}
sha = mosquitto__malloc(SHA_DIGEST_LENGTH); sha = mosquitto__malloc(SHA_DIGEST_LENGTH);
memcpy(sha, tmp, SHA_DIGEST_LENGTH); memcpy(sha, tmp, SHA_DIGEST_LENGTH);
*bin = sha; *bin = sha;
return MOSQ_ERR_SUCCESS; return MOSQ_ERR_SUCCESS;
} }
#endif
#if defined(WITH_TLS_PSK) || defined(WITH_TLS)
int mosquitto__hex2bin(const char *hex, unsigned char *bin, int bin_max_len) int mosquitto__hex2bin(const char *hex, unsigned char *bin, int bin_max_len)
{ {
BIGNUM *bn = NULL; BIGNUM *bn = NULL;

View File

@ -35,9 +35,6 @@ FILE *mosquitto__fopen(const char *path, const char *mode, bool restrict_read);
#ifdef WITH_TLS #ifdef WITH_TLS
int mosquitto__hex2bin_sha1(const char *hex, unsigned char **bin); int mosquitto__hex2bin_sha1(const char *hex, unsigned char **bin);
#endif
#if defined(WITH_TLS_PSK) || defined(WITH_TLS)
int mosquitto__hex2bin(const char *hex, unsigned char *bin, int bin_max_len); int mosquitto__hex2bin(const char *hex, unsigned char *bin, int bin_max_len);
#endif #endif

View File

@ -894,33 +894,6 @@
the "openssl ciphers" command.</para> the "openssl ciphers" command.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>tls_engine</option> <replaceable>engine</replaceable></term>
<listitem>
<para>A valid openssl engine id. These can be listed with
openssl engine command.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>tls_keyform</option> [ pem | engine ]</term>
<listitem>
<para>Specifies the type of key in use. This could be pem or
engine. This parameter is useful for example when a TPM
module is being used and the key has been created with
it. If not specified, pem keys are assumed</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>tls_engine_kpass_sha</option> <replaceable>engine_kpass_sha</replaceable></term>
<listitem>
<para>SHA1 of private key password when using an SSL engine.
Some SSL engines may require the usage of a password
in order to being accessed, like the TPM engine. Instead
of being prompted for the password, this option allows
a SHA1 hash of the password to be passed on to the
engine directly, without user interaction.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>crlfile</option> <replaceable>file path</replaceable></term> <term><option>crlfile</option> <replaceable>file path</replaceable></term>
<listitem> <listitem>
@ -955,6 +928,36 @@
mechanisms provided by MQTT.</para> mechanisms provided by MQTT.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>tls_engine</option> <replaceable>engine</replaceable></term>
<listitem>
<para>A valid openssl engine id. These can be listed with
openssl engine command.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>tls_engine_kpass_sha1</option> <replaceable>engine_kpass_sha1</replaceable></term>
<listitem>
<para>SHA1 of the private key password when using an
TLS engine. Some TLS engines such as the TPM
engine may require the use of a password in order
to be accessed. This option allows a hex encoded
SHA1 hash of the password to the engine directly,
instead of the user being prompted for the
password.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>tls_keyform</option> [ pem | engine ]</term>
<listitem>
<para>Specifies the type of private key in use when
making TLS connections.. This can be "pem" or
"engine". This parameter is useful when a TPM
module is being used and the private key has been
created with it. Defaults to "pem", which means
normal private key files are used.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>tls_version</option> <replaceable>version</replaceable></term> <term><option>tls_version</option> <replaceable>version</replaceable></term>
<listitem> <listitem>

View File

@ -68,7 +68,7 @@
<arg choice='plain'><replaceable>pem</replaceable></arg> <arg choice='plain'><replaceable>pem</replaceable></arg>
<arg choice='plain'><replaceable>engine</replaceable></arg> <arg choice='plain'><replaceable>engine</replaceable></arg>
</group></arg> </group></arg>
<arg><option>--tls-engine-kpass-sha</option> <replaceable>kpass-sha</replaceable></arg> <arg><option>--tls-engine-kpass-sha1</option> <replaceable>kpass-sha1</replaceable></arg>
<arg><option>--insecure</option></arg> <arg><option>--insecure</option></arg>
</arg> </arg>
<arg> <arg>
@ -187,36 +187,6 @@
for more information.</para> for more information.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--tls-engine</option></term>
<listitem>
<para>A valid openssl engine id. These can be listed with
openssl engine command.</para>
<para>See also <option>--keyform</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--keyform</option></term>
<listitem>
<para>Specifies the type of key in use. This could be pem or
engine. This parameter is useful for example when a TPM
module is being used and the key has been created with
it. If not specified, pem keys are assumed</para>
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-engine-kpass-sha</option></term>
<listitem>
<para>SHA1 of private key password when using an SSL engine.
Some SSL engines may require the usage of a password
in order to being accessed, like the TPM engine. Instead
of being prompted for the password, this option allows
a SHA1 hash of the password to be passed on to the
engine directly, without user interaction.</para>
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-d</option></term> <term><option>-d</option></term>
<term><option>--debug</option></term> <term><option>--debug</option></term>
@ -298,6 +268,18 @@
<para>See also <option>--cert</option>.</para> <para>See also <option>--cert</option>.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--keyform</option></term>
<listitem>
<para>Specifies the type of private key in use when making
TLS connections.. This can be "pem" or "engine". This
parameter is useful when a TPM module is being used and
the private key has been created with it. Defaults to
"pem", which means normal private key files are
used.</para>
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-L</option></term> <term><option>-L</option></term>
<term><option>--url</option></term> <term><option>--url</option></term>
@ -438,6 +420,26 @@
<para>The MQTT topic on which to publish the message. See <citerefentry><refentrytitle>mqtt</refentrytitle><manvolnum>7</manvolnum></citerefentry> for more information on MQTT topics.</para> <para>The MQTT topic on which to publish the message. See <citerefentry><refentrytitle>mqtt</refentrytitle><manvolnum>7</manvolnum></citerefentry> for more information on MQTT topics.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--tls-engine</option></term>
<listitem>
<para>A valid openssl engine id. These can be listed with
openssl engine command.</para>
<para>See also <option>--keyform</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-engine-kpass-sha1</option></term>
<listitem>
<para>SHA1 of the private key password when using an TLS
engine. Some TLS engines such as the TPM engine may
require the use of a password in order to be accessed.
This option allows a hex encoded SHA1 hash of the
password to the engine directly, instead of the user
being prompted for the password.</para>
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--tls-version</option></term> <term><option>--tls-version</option></term>
<listitem> <listitem>

View File

@ -75,7 +75,7 @@
<arg choice='plain'><replaceable>pem</replaceable></arg> <arg choice='plain'><replaceable>pem</replaceable></arg>
<arg choice='plain'><replaceable>engine</replaceable></arg> <arg choice='plain'><replaceable>engine</replaceable></arg>
</group></arg> </group></arg>
<arg><option>--tls-engine-kpass-sha</option> <replaceable>kpass-sha</replaceable></arg> <arg><option>--tls-engine-kpass-sha1</option> <replaceable>kpass-sha1</replaceable></arg>
<arg><option>--insecure</option></arg> <arg><option>--insecure</option></arg>
</arg> </arg>
<arg> <arg>
@ -197,36 +197,6 @@
for more information.</para> for more information.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--tls-engine</option></term>
<listitem>
<para>A valid openssl engine id. These can be listed with
openssl engine command.</para>
<para>See also <option>--keyform</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--keyform</option></term>
<listitem>
<para>Specifies the type of key in use. This could be pem or
engine. This parameter is useful for example when a TPM
module is being used and the key has been created with
it. If not specified, pem keys are assumed</para>
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-engine-kpass-sha</option></term>
<listitem>
<para>SHA1 of private key password when using an SSL engine.
Some SSL engines may require the usage of a password
in order to being accessed, like the TPM engine. Instead
of being prompted for the password, this option allows
a SHA1 hash of the password to be passed on to the
engine directly, without user interaction.</para>
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-C</option></term> <term><option>-C</option></term>
<listitem> <listitem>
@ -339,6 +309,18 @@
<para>See also <option>--cert</option>.</para> <para>See also <option>--cert</option>.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--keyform</option></term>
<listitem>
<para>Specifies the type of private key in use when making
TLS connections.. This can be "pem" or "engine". This
parameter is useful when a TPM module is being used and
the private key has been created with it. Defaults to
"pem", which means normal private key files are
used.</para>
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-L</option></term> <term><option>-L</option></term>
<term><option>--url</option></term> <term><option>--url</option></term>
@ -503,6 +485,26 @@
topics or topic trees.</para> topics or topic trees.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--tls-engine</option></term>
<listitem>
<para>A valid openssl engine id. These can be listed with
openssl engine command.</para>
<para>See also <option>--keyform</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--tls-engine-kpass-sha1</option></term>
<listitem>
<para>SHA1 of the private key password when using an TLS
engine. Some TLS engines such as the TPM engine may
require the use of a password in order to be accessed.
This option allows a hex encoded SHA1 hash of the
password to the engine directly, instead of the user
being prompted for the password.</para>
<para>See also <option>--tls-engine</option>.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--tls-version</option></term> <term><option>--tls-version</option></term>
<listitem> <listitem>

View File

@ -299,7 +299,7 @@ void config__cleanup(struct mosquitto__config *config)
mosquitto__free(config->listeners[i].crlfile); mosquitto__free(config->listeners[i].crlfile);
mosquitto__free(config->listeners[i].tls_version); mosquitto__free(config->listeners[i].tls_version);
mosquitto__free(config->listeners[i].tls_engine); mosquitto__free(config->listeners[i].tls_engine);
mosquitto__free(config->listeners[i].tls_engine_kpass_sha); mosquitto__free(config->listeners[i].tls_engine_kpass_sha1);
#ifdef WITH_WEBSOCKETS #ifdef WITH_WEBSOCKETS
if(!config->listeners[i].ws_context) /* libwebsockets frees its own SSL_CTX */ if(!config->listeners[i].ws_context) /* libwebsockets frees its own SSL_CTX */
#endif #endif
@ -437,7 +437,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
|| config->default_listener.keyfile || config->default_listener.keyfile
|| config->default_listener.tls_engine || config->default_listener.tls_engine
|| config->default_listener.tls_keyform != mosq_k_pem || config->default_listener.tls_keyform != mosq_k_pem
|| config->default_listener.tls_engine_kpass_sha || config->default_listener.tls_engine_kpass_sha1
|| config->default_listener.ciphers || config->default_listener.ciphers
|| config->default_listener.psk_hint || config->default_listener.psk_hint
|| config->default_listener.require_certificate || config->default_listener.require_certificate
@ -490,7 +490,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
config->listeners[config->listener_count-1].tls_version = config->default_listener.tls_version; config->listeners[config->listener_count-1].tls_version = config->default_listener.tls_version;
config->listeners[config->listener_count-1].tls_engine = config->default_listener.tls_engine; config->listeners[config->listener_count-1].tls_engine = config->default_listener.tls_engine;
config->listeners[config->listener_count-1].tls_keyform = config->default_listener.tls_keyform; config->listeners[config->listener_count-1].tls_keyform = config->default_listener.tls_keyform;
config->listeners[config->listener_count-1].tls_engine_kpass_sha = config->default_listener.tls_engine_kpass_sha; config->listeners[config->listener_count-1].tls_engine_kpass_sha1 = config->default_listener.tls_engine_kpass_sha1;
config->listeners[config->listener_count-1].cafile = config->default_listener.cafile; config->listeners[config->listener_count-1].cafile = config->default_listener.cafile;
config->listeners[config->listener_count-1].capath = config->default_listener.capath; config->listeners[config->listener_count-1].capath = config->default_listener.capath;
config->listeners[config->listener_count-1].certfile = config->default_listener.certfile; config->listeners[config->listener_count-1].certfile = config->default_listener.certfile;
@ -1112,16 +1112,16 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
#else #else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available."); log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif #endif
}else if(!strcmp(token, "tls_engine_kpass_sha")){ }else if(!strcmp(token, "tls_engine_kpass_sha1")){
#ifdef WITH_TLS #ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading. if(reload) continue; // Listeners not valid for reloading.
char *kpass_sha = NULL, *kpass_sha_bin = NULL; char *kpass_sha = NULL, *kpass_sha_bin = NULL;
if(conf__parse_string(&token, "tls_engine_kpass_sha", &kpass_sha, saveptr)) return MOSQ_ERR_INVAL; if(conf__parse_string(&token, "tls_engine_kpass_sha1", &kpass_sha, saveptr)) return MOSQ_ERR_INVAL;
if(mosquitto__hex2bin_sha1(kpass_sha, (unsigned char**)&kpass_sha_bin) != MOSQ_ERR_SUCCESS){ if(mosquitto__hex2bin_sha1(kpass_sha, (unsigned char**)&kpass_sha_bin) != MOSQ_ERR_SUCCESS){
mosquitto__free(kpass_sha); mosquitto__free(kpass_sha);
return MOSQ_ERR_INVAL; return MOSQ_ERR_INVAL;
} }
cur_listener->tls_engine_kpass_sha = kpass_sha_bin; cur_listener->tls_engine_kpass_sha1 = kpass_sha_bin;
mosquitto__free(kpass_sha); mosquitto__free(kpass_sha);
#else #else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available."); log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");

View File

@ -225,16 +225,16 @@ struct mosquitto__listener {
char *certfile; char *certfile;
char *keyfile; char *keyfile;
char *tls_engine; char *tls_engine;
enum _mosquitto_keyform tls_keyform; char *tls_engine_kpass_sha1;
char *tls_engine_kpass_sha;
char *ciphers; char *ciphers;
char *psk_hint; char *psk_hint;
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
char *crlfile; char *crlfile;
char *tls_version;
bool use_identity_as_username; bool use_identity_as_username;
bool use_subject_as_username; bool use_subject_as_username;
bool require_certificate; bool require_certificate;
char *tls_version; enum mosquitto__keyform tls_keyform;
#endif #endif
#ifdef WITH_WEBSOCKETS #ifdef WITH_WEBSOCKETS
struct libwebsocket_context *ws_context; struct libwebsocket_context *ws_context;

View File

@ -502,14 +502,14 @@ int net__socket_listen(struct mosquitto__listener *listener)
} }
if(listener->tls_keyform == mosq_k_engine){ if(listener->tls_keyform == mosq_k_engine){
UI_METHOD *ui_method = net__get_ui_method(); UI_METHOD *ui_method = net__get_ui_method();
if(listener->tls_engine_kpass_sha){ if(listener->tls_engine_kpass_sha1){
if(!ENGINE_ctrl_cmd(engine, ENGINE_SECRET_MODE, ENGINE_SECRET_MODE_SHA, NULL, NULL, 0)){ if(!ENGINE_ctrl_cmd(engine, ENGINE_SECRET_MODE, ENGINE_SECRET_MODE_SHA, NULL, NULL, 0)){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set engine secret mode sha"); log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set engine secret mode sha");
COMPAT_CLOSE(sock); COMPAT_CLOSE(sock);
ENGINE_FINISH(engine); ENGINE_FINISH(engine);
return 1; return 1;
} }
if(!ENGINE_ctrl_cmd(engine, ENGINE_PIN, 0, listener->tls_engine_kpass_sha, NULL, 0)){ if(!ENGINE_ctrl_cmd(engine, ENGINE_PIN, 0, listener->tls_engine_kpass_sha1, NULL, 0)){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set engine pin"); log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set engine pin");
COMPAT_CLOSE(sock); COMPAT_CLOSE(sock);
ENGINE_FINISH(engine); ENGINE_FINISH(engine);