Bridge TLS Application-Layer Protocol Negotiation

In order to connect to brokers that support both websockets and
mqtt on the same port (such as Amazon IoT), we need to set an
application for the SSL context.  This change allows the specification
of an application by using the `bridge_alpn` configuration token.

Signed-off-by: John Hickey <jjh-github@daedalian.us>
pull/1224/head
John Hickey 7 years ago
parent 925debb8a5
commit c011be62a4

@ -247,6 +247,7 @@ void mosquitto__destroy(struct mosquitto *mosq)
mosquitto__free(mosq->tls_ciphers);
mosquitto__free(mosq->tls_psk);
mosquitto__free(mosq->tls_psk_identity);
mosquitto__free(mosq->tls_alpn);
#endif
mosquitto__free(mosq->address);

@ -110,6 +110,7 @@ enum mosq_opt_t {
MOSQ_OPT_TLS_ENGINE = 7,
MOSQ_OPT_TLS_ENGINE_KPASS_SHA1 = 8,
MOSQ_OPT_TLS_OCSP_REQUIRED = 9,
MOSQ_OPT_TLS_ALPN = 10,
};

@ -224,6 +224,7 @@ struct mosquitto {
char *tls_engine;
char *tls_engine_kpass_sha1;
enum mosquitto__keyform tls_keyform;
char *tls_alpn;
#endif
bool want_write;
bool want_connect;

@ -527,6 +527,10 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
{
int ret;
ENGINE *engine = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x10002000L /* ALPN was added into OpenSSL 1.0.2 */
uint8_t tls_alpn_wire[256];
uint8_t tls_alpn_len;
#endif
if(mosq->ssl_ctx){
if(!mosq->ssl_ctx_defaults){
@ -582,6 +586,18 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
/* Disable compression */
SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_COMPRESSION);
/* Set ALPN */
if(mosq->tls_alpn) {
#if OPENSSL_VERSION_NUMBER >= 0x10002000L /* ALPN was added into OpenSSL 1.0.2 */
tls_alpn_len = (uint8_t) strnlen(mosq->tls_alpn, 254);
tls_alpn_wire[0] = tls_alpn_len; // first byte is length of string
memcpy(tls_alpn_wire + 1, mosq->tls_alpn, tls_alpn_len);
SSL_CTX_set_alpn_protos(mosq->ssl_ctx, tls_alpn_wire, tls_alpn_len + 1);
#else
log__printf(mosq, MOSQ_LOG_ERR, "Error: TLS ALPN not supported by version of OpenSSL.");
#endif
}
#ifdef SSL_MODE_RELEASE_BUFFERS
/* Use even less memory per SSL connection. */
SSL_CTX_set_mode(mosq->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);

@ -298,6 +298,18 @@ int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, cons
#endif
break;
case MOSQ_OPT_TLS_ALPN:
#ifdef WITH_TLS
mosq->tls_alpn = mosquitto__strdup(value);
if(!mosq->tls_alpn){
return MOSQ_ERR_NOMEM;
}
return MOSQ_ERR_SUCCESS;
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif
break;
default:
return MOSQ_ERR_INVAL;
}

@ -1809,6 +1809,14 @@ topic clients/total in 0 test/mosquitto/org $SYS/broker/
connection to succeed.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>bridge_alpn</option> <replaceable>alpn</replaceable></term>
<listitem>
<para>Configure the application layer protocol negotiation
option for the TLS session. Useful for brokers that support
both websockets and MQTT on the same port.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>

@ -87,6 +87,7 @@ int bridge__new(struct mosquitto_db *db, struct mosquitto__bridge *bridge)
new_context->tls_ocsp_required = new_context->bridge->tls_ocsp_required;
new_context->tls_version = new_context->bridge->tls_version;
new_context->tls_insecure = new_context->bridge->tls_insecure;
new_context->tls_alpn = new_context->bridge->tls_alpn;
#ifdef FINAL_WITH_TLS_PSK
new_context->tls_psk_identity = new_context->bridge->tls_psk_identity;
new_context->tls_psk = new_context->bridge->tls_psk;

@ -356,6 +356,7 @@ void config__cleanup(struct mosquitto__config *config)
#ifdef WITH_TLS
mosquitto__free(config->bridges[i].tls_version);
mosquitto__free(config->bridges[i].tls_cafile);
mosquitto__free(config->bridges[i].tls_alpn);
#ifdef FINAL_WITH_TLS_PSK
mosquitto__free(config->bridges[i].tls_psk_identity);
mosquitto__free(config->bridges[i].tls_psk);
@ -962,6 +963,17 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
if(conf__parse_string(&token, "bridge_cafile", &cur_bridge->tls_cafile, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge and/or TLS support not available.");
#endif
}else if(!strcmp(token, "bridge_alpn")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // FIXME
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
}
if(conf__parse_string(&token, "bridge_alpn", &cur_bridge->tls_alpn, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge and/or TLS support not available.");
#endif
}else if(!strcmp(token, "bridge_capath")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)

@ -493,6 +493,7 @@ struct mosquitto__bridge{
char *tls_certfile;
char *tls_keyfile;
char *tls_version;
char *tls_alpn;
# ifdef FINAL_WITH_TLS_PSK
char *tls_psk_identity;
char *tls_psk;

Loading…
Cancel
Save