Skip to content

Commit

Permalink
Bridge TLS Application-Layer Protocol Negotiation
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
omenlabs committed Apr 5, 2019
1 parent 925debb commit c011be6
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/mosquitto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions lib/mosquitto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};


Expand Down
1 change: 1 addition & 0 deletions lib/mosquitto_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions lib/net_mosq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 12 additions & 0 deletions lib/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
8 changes: 8 additions & 0 deletions man/mosquitto.conf.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions src/bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 12 additions & 0 deletions src/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/mosquitto_broker_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit c011be6

Please sign in to comment.