Add TLS engine and keyform support to mosquitto

Add same OpenSSL engine support to mosquitto (server side) previously added to
client side only.

Signed-off-by: Nicolás Pernas Maradei <nicopernas@gmail.com>
pull/1203/head
Nicolás Pernas Maradei 7 years ago committed by Roger A. Light
parent f88cc06435
commit d5f039ec7c

@ -894,6 +894,22 @@
the "openssl ciphers" command.</para>
</listitem>
</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>crlfile</option> <replaceable>file path</replaceable></term>
<listitem>

@ -298,6 +298,7 @@ void config__cleanup(struct mosquitto__config *config)
mosquitto__free(config->listeners[i].psk_hint);
mosquitto__free(config->listeners[i].crlfile);
mosquitto__free(config->listeners[i].tls_version);
mosquitto__free(config->listeners[i].tls_engine);
#ifdef WITH_WEBSOCKETS
if(!config->listeners[i].ws_context) /* libwebsockets frees its own SSL_CTX */
#endif
@ -433,6 +434,8 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
|| config->default_listener.capath
|| config->default_listener.certfile
|| config->default_listener.keyfile
|| config->default_listener.tls_engine
|| config->default_listener.tls_keyform != mosq_k_pem
|| config->default_listener.ciphers
|| config->default_listener.psk_hint
|| config->default_listener.require_certificate
@ -483,6 +486,8 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
config->listeners[config->listener_count-1].use_username_as_clientid = config->default_listener.use_username_as_clientid;
#ifdef WITH_TLS
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_keyform = config->default_listener.tls_keyform;
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].certfile = config->default_listener.certfile;
@ -1085,6 +1090,24 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_string(&token, "certfile", &cur_listener->certfile, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "tls_engine")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
if(conf__parse_string(&token, "tls_engine", &cur_listener->tls_engine, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "tls_keyform")){
#ifdef WITH_TLS
if(reload) continue; // Listeners not valid for reloading.
char *keyform = NULL;
if(conf__parse_string(&token, "tls_keyform", &keyform, saveptr)) return MOSQ_ERR_INVAL;
cur_listener->tls_keyform = mosq_k_pem;
if(!strcmp(keyform, "engine")) cur_listener->tls_keyform = mosq_k_engine;
mosquitto__free(keyform);
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "ciphers")){
#ifdef WITH_TLS

@ -224,6 +224,8 @@ struct mosquitto__listener {
char *capath;
char *certfile;
char *keyfile;
char *tls_engine;
enum _mosquitto_keyform tls_keyform;
char *ciphers;
char *psk_hint;
SSL_CTX *ssl_ctx;

@ -385,6 +385,7 @@ int net__socket_listen(struct mosquitto__listener *listener)
int rc;
X509_STORE *store;
X509_LOOKUP *lookup;
ENGINE *engine = NULL;
#endif
if(!listener) return MOSQ_ERR_INVAL;
@ -469,6 +470,22 @@ int net__socket_listen(struct mosquitto__listener *listener)
COMPAT_CLOSE(sock);
return 1;
}
if(listener->tls_engine){
engine = ENGINE_by_id(listener->tls_engine);
if(!engine){
log__printf(NULL, MOSQ_LOG_ERR, "Error loading %s engine\n", listener->tls_engine);
COMPAT_CLOSE(sock);
return 1;
}
if(!ENGINE_init(engine)){
log__printf(NULL, MOSQ_LOG_ERR, "Failed engine initialisation\n");
ENGINE_free(engine);
COMPAT_CLOSE(sock);
return 1;
}
ENGINE_set_default(engine, ENGINE_METHOD_ALL);
ENGINE_free(engine); /* release the structural reference from ENGINE_by_id() */
}
/* FIXME user data? */
if(listener->require_certificate){
SSL_CTX_set_verify(listener->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, client_certificate_verify);
@ -480,20 +497,39 @@ int net__socket_listen(struct mosquitto__listener *listener)
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load server certificate \"%s\". Check certfile.", listener->certfile);
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);
ENGINE_FINISH(engine);
return 1;
}
rc = SSL_CTX_use_PrivateKey_file(listener->ssl_ctx, listener->keyfile, SSL_FILETYPE_PEM);
if(rc != 1){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load server key file \"%s\". Check keyfile.", listener->keyfile);
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);
return 1;
if(listener->tls_keyform == mosq_k_engine){
EVP_PKEY *pkey = ENGINE_load_private_key(engine, listener->keyfile, net__get_ui_method(), NULL);
if(!pkey){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load engine private key file \"%s\".", listener->keyfile);
COMPAT_CLOSE(sock);
ENGINE_FINISH(engine);
return 1;
}
if(SSL_CTX_use_PrivateKey(listener->ssl_ctx, pkey) <= 0){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to use engine private key file \"%s\".", listener->keyfile);
COMPAT_CLOSE(sock);
ENGINE_FINISH(engine);
return 1;
}
}else{
rc = SSL_CTX_use_PrivateKey_file(listener->ssl_ctx, listener->keyfile, SSL_FILETYPE_PEM);
if(rc != 1){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load server key file \"%s\". Check keyfile.", listener->keyfile);
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);
ENGINE_FINISH(engine);
return 1;
}
}
rc = SSL_CTX_check_private_key(listener->ssl_ctx);
if(rc != 1){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Server certificate/key are inconsistent.");
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);
ENGINE_FINISH(engine);
return 1;
}
/* Load CRLs if they exist. */
@ -503,6 +539,7 @@ int net__socket_listen(struct mosquitto__listener *listener)
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to obtain TLS store.");
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);
ENGINE_FINISH(engine);
return 1;
}
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
@ -511,6 +548,7 @@ int net__socket_listen(struct mosquitto__listener *listener)
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load certificate revocation file \"%s\". Check crlfile.", listener->crlfile);
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);
ENGINE_FINISH(engine);
return 1;
}
X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
@ -527,6 +565,7 @@ int net__socket_listen(struct mosquitto__listener *listener)
if(mosquitto__tls_server_ctx(listener)){
COMPAT_CLOSE(sock);
ENGINE_FINISH(engine);
return 1;
}
SSL_CTX_set_psk_server_callback(listener->ssl_ctx, psk_server_callback);
@ -536,6 +575,7 @@ int net__socket_listen(struct mosquitto__listener *listener)
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set TLS PSK hint.");
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);
ENGINE_FINISH(engine);
return 1;
}
}

Loading…
Cancel
Save