Skip to content

Commit

Permalink
Merge branch 'master' of git:https://github.com/LarsVoelker/mosquitto into …
Browse files Browse the repository at this point in the history
…LarsVoelker-master
  • Loading branch information
ralight committed Mar 26, 2019
2 parents 64469ae + 74adb43 commit ea046c2
Show file tree
Hide file tree
Showing 18 changed files with 254 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ set(C_SRC
mosquitto.c mosquitto.h
mosquitto_internal.h
mqtt_protocol.h
net_mosq.c net_mosq.h
net_mosq_ocsp.c net_mosq.c net_mosq.h
options.c
packet_datatypes.c
packet_mosq.c packet_mosq.h
Expand Down
4 changes: 4 additions & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ MOSQ_OBJS=mosquitto.o \
loop.o \
memory_mosq.o \
messages_mosq.o \
net_mosq_ocsp.o \
net_mosq.o \
options.o \
packet_datatypes.o \
Expand Down Expand Up @@ -151,6 +152,9 @@ messages_mosq.o : messages_mosq.c messages_mosq.h
memory_mosq.o : memory_mosq.c memory_mosq.h
${CROSS_COMPILE}$(CC) $(LIB_CFLAGS) -c $< -o $@

net_mosq_ocsp.o : net_mosq_ocsp.c net_mosq.h
${CROSS_COMPILE}$(CC) $(LIB_CFLAGS) -c $< -o $@

net_mosq.o : net_mosq.c net_mosq.h
${CROSS_COMPILE}$(CC) $(LIB_CFLAGS) -c $< -o $@

Expand Down
4 changes: 4 additions & 0 deletions lib/cpp/mosquittopp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,4 +378,8 @@ int mosquittopp::tls_psk_set(const char *psk, const char *identity, const char *
return mosquitto_tls_psk_set(m_mosq, psk, identity, ciphers);
}

int mosquittopp::tls_ocsp_set(int ocsp_reqs)
{
return mosquitto_tls_ocsp_set(m_mosq, ocsp_reqs);
}
}
1 change: 1 addition & 0 deletions lib/cpp/mosquittopp.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class mosqpp_EXPORT mosquittopp {
int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL);
int tls_insecure_set(bool value);
int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL);
int tls_ocsp_set(int ocsp_reqs);
int opts_set(enum mosq_opt_t option, void *value);

int loop(int timeout=-1, int max_packets=1);
Expand Down
1 change: 1 addition & 0 deletions lib/linker.version
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ MOSQ_1.6 {
mosquitto_subscribe_multiple;
mosquitto_subscribe_v5;
mosquitto_subscribe_v5_callback_set;
mosquitto_tls_ocsp_set;
mosquitto_unsubscribe_multiple;
mosquitto_unsubscribe_v5;
mosquitto_unsubscribe_v5_callback_set;
Expand Down
1 change: 1 addition & 0 deletions lib/mosquitto.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_st
mosq->tls_cert_reqs = SSL_VERIFY_PEER;
mosq->tls_insecure = false;
mosq->want_write = false;
mosq->tls_ocsp_required = false;
#endif
#ifdef WITH_THREADING
pthread_mutex_init(&mosq->callback_mutex, NULL);
Expand Down
21 changes: 21 additions & 0 deletions lib/mosquitto.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ enum mosq_err_t {
MOSQ_ERR_TLS_HANDSHAKE = 23,
MOSQ_ERR_QOS_NOT_SUPPORTED = 24,
MOSQ_ERR_OVERSIZE_PACKET = 25,
MOSQ_ERR_OCSP = 26,
};

/* Error values */
Expand Down Expand Up @@ -1724,6 +1725,26 @@ 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);

/*
* Function: mosquitto_tls_ocsp_set
*
* Set advanced SSL/TLS options. Must be called before <mosquitto_connect>.
*
* Parameters:
* mosq - a valid mosquitto instance.
* ocsp_reqs - whether OCSP checking is required:
* 0 - no checking required
* 1 - checking required
*
* 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_ocsp_set(struct mosquitto *mosq, int ocsp_reqs);


/* ======================================================================
*
Expand Down
1 change: 1 addition & 0 deletions lib/mosquitto_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ struct mosquitto {
int tls_cert_reqs;
bool tls_insecure;
bool ssl_ctx_defaults;
bool tls_ocsp_required;
char *tls_engine;
char *tls_engine_kpass_sha1;
enum mosquitto__keyform tls_keyform;
Expand Down
17 changes: 17 additions & 0 deletions lib/net_mosq.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,23 @@ int net__socket_connect_tls(struct mosquitto *mosq)
int ret, err;

ERR_clear_error();
long res;
if (mosq->tls_ocsp_required) {
// Note: OCSP is available in all currently supported OpenSSL versions.
if ((res=SSL_set_tlsext_status_type(mosq->ssl, TLSEXT_STATUSTYPE_ocsp)) != 1) {
log__printf(mosq, MOSQ_LOG_ERR, "Could not activate OCSP (error: %ld)", res);
return MOSQ_ERR_OCSP;
}
if ((res=SSL_CTX_set_tlsext_status_cb(mosq->ssl_ctx, mosquitto__verify_ocsp_status_cb)) != 1) {
log__printf(mosq, MOSQ_LOG_ERR, "Could not activate OCSP (error: %ld)", res);
return MOSQ_ERR_OCSP;
}
if ((res=SSL_CTX_set_tlsext_status_arg(mosq->ssl_ctx, mosq)) != 1) {
log__printf(mosq, MOSQ_LOG_ERR, "Could not activate OCSP (error: %ld)", res);
return MOSQ_ERR_OCSP;
}
}

ret = SSL_connect(mosq->ssl);
if(ret != 1) {
err = SSL_get_error(mosq->ssl, ret);
Expand Down
1 change: 1 addition & 0 deletions lib/net_mosq.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ ssize_t net__write(struct mosquitto *mosq, void *buf, size_t count);
#ifdef WITH_TLS
int net__socket_apply_tls(struct mosquitto *mosq);
int net__socket_connect_tls(struct mosquitto *mosq);
int mosquitto__verify_ocsp_status_cb(SSL * ssl, void *arg);
UI_METHOD *net__get_ui_method(void);
#define ENGINE_FINISH(e) if(e) ENGINE_finish(e)
#define ENGINE_SECRET_MODE "SECRET_MODE"
Expand Down
159 changes: 159 additions & 0 deletions lib/net_mosq_ocsp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
Copyright (c) 2009-2014 Roger Light <[email protected]>
Copyright (c) 2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG), Dr. Lars Voelker <[email protected]>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http:https://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http:https://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Dr. Lars Voelker, BMW AG
*/

/*
COPYRIGHT AND PERMISSION NOTICE of curl on which the ocsp code is based:
Copyright (c) 1996 - 2016, Daniel Stenberg, <[email protected]>, and many
contributors, see the THANKS file.
All rights reserved.
Permission to use, copy, modify, and distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright
notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.
*/

#ifdef WITH_TLS
#include <openssl/safestack.h>
#include <openssl/tls1.h>
#include <openssl/ssl.h>
#include <openssl/ocsp.h>

#include <logging_mosq.h>
#include <mosquitto_internal.h>
#include <net_mosq.h>

int mosquitto__verify_ocsp_status_cb(SSL * ssl, void *arg)
{
struct mosquitto *mosq = (struct mosquitto *)arg;
int ocsp_status, result2, i;
unsigned char *p;
const unsigned char *cp;
OCSP_RESPONSE *rsp = NULL;
OCSP_BASICRESP *br = NULL;
X509_STORE *st = NULL;
STACK_OF(X509) *ch = NULL;

long len = SSL_get_tlsext_status_ocsp_resp(mosq->ssl, &p);
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL_get_tlsext_status_ocsp_resp returned %ld bytes", len);

// the following functions expect a const pointer
cp = (const unsigned char *)p;

if (!cp || len <= 0) {
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: no response");
goto end;
}


rsp = d2i_OCSP_RESPONSE(NULL, &cp, len);
if (rsp==NULL) {
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: invalid response");
goto end;
}

ocsp_status = OCSP_response_status(rsp);
if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: invalid status: %s (%d)",
OCSP_response_status_str(ocsp_status), ocsp_status);
goto end;
}

br = OCSP_response_get1_basic(rsp);
if (!br) {
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: invalid response");
goto end;
}

ch = SSL_get_peer_cert_chain(mosq->ssl);
if (sk_X509_num(ch) <= 0) {
log__printf(mosq, MOSQ_LOG_ERR, "OCSP: we did not receive certificates of the server (num: %d)", sk_X509_num(ch));
goto end;
}

st = SSL_CTX_get_cert_store(mosq->ssl_ctx);

// Note:
// Other checkers often fix problems in OpenSSL before 1.0.2a (e.g. libcurl).
// For all currently supported versions of the OpenSSL project, this is not needed anymore.

if ((result2=OCSP_basic_verify(br, ch, st, 0)) <= 0) {
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: response verification failed (error: %d)", result2);
goto end;
}

for(i = 0; i < OCSP_resp_count(br); i++) {
int cert_status, crl_reason;
OCSP_SINGLERESP *single = NULL;

ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;

single = OCSP_resp_get0(br, i);
if(!single)
continue;

cert_status = OCSP_single_get0_status(single, &crl_reason, &rev, &thisupd, &nextupd);

log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL certificate status: %s (%d)",
OCSP_cert_status_str(cert_status), cert_status);

switch(cert_status) {
case V_OCSP_CERTSTATUS_GOOD:
// Note: A OCSP stapling result will be accepted up to 5 minutes after it expired!
if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: OCSP response has expired");
goto end;
}
break;

case V_OCSP_CERTSTATUS_REVOKED:
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL certificate revocation reason: %s (%d)",
OCSP_crl_reason_str(crl_reason), crl_reason);
goto end;

case V_OCSP_CERTSTATUS_UNKNOWN:
goto end;

default:
log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL certificate revocation status unknown");
goto end;
}
}

if (br!=NULL) OCSP_BASICRESP_free(br);
if (rsp!=NULL) OCSP_RESPONSE_free(rsp);
return 1; // OK

end:
if (br!=NULL) OCSP_BASICRESP_free(br);
if (rsp!=NULL) OCSP_RESPONSE_free(rsp);
return 0; // Not OK
}
#endif
18 changes: 18 additions & 0 deletions lib/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,24 @@ int mosquitto_tls_set(struct mosquitto *mosq, const char *cafile, const char *ca
}


int mosquitto_tls_ocsp_set(struct mosquitto *mosq, int ocsp_reqs)
{
#ifdef WITH_TLS
if (ocsp_reqs==0) {
mosq->tls_ocsp_required = false;
return MOSQ_ERR_SUCCESS;
}

if (ocsp_reqs==1) {
mosq->tls_ocsp_required = true;
return MOSQ_ERR_SUCCESS;
}
#endif

return MOSQ_ERR_INVAL;
}


int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers)
{
#ifdef WITH_TLS
Expand Down
7 changes: 7 additions & 0 deletions man/mosquitto.conf.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1792,6 +1792,13 @@ topic clients/total in 0 test/mosquitto/org $SYS/broker/
connection to succeed.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>bridge_require_ocsp</option> [ true | false ]</term>
<listitem>
<para>When set to true, the bridge requires OCSP on the TLS
connection it opens as client.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>
Expand Down
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ set (MOSQ_SRCS
mosquitto.c
mosquitto_broker.h mosquitto_broker_internal.h
net.c
../lib/net_mosq.c ../lib/net_mosq.h
../lib/net_mosq_ocsp.c ../lib/net_mosq.c ../lib/net_mosq.h
../lib/packet_datatypes.c
../lib/packet_mosq.c ../lib/packet_mosq.h
persist_read_v234.c persist_read_v5.c persist_read.c
Expand Down
4 changes: 4 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ OBJS= mosquitto.o \
memory_mosq.o \
net.o \
net_mosq.o \
net_mosq_ocsp.o \
packet_datatypes.o \
packet_mosq.o \
property_broker.o \
Expand Down Expand Up @@ -140,6 +141,9 @@ memory_mosq.o : ../lib/memory_mosq.c ../lib/memory_mosq.h
net.o : net.c mosquitto_broker_internal.h
${CROSS_COMPILE}${CC} $(BROKER_CFLAGS) -c $< -o $@

net_mosq_ocsp.o : ../lib/net_mosq_ocsp.c ../lib/net_mosq.h
${CROSS_COMPILE}${CC} $(BROKER_CFLAGS) -c $< -o $@

net_mosq.o : ../lib/net_mosq.c ../lib/net_mosq.h
${CROSS_COMPILE}${CC} $(BROKER_CFLAGS) -c $< -o $@

Expand Down
1 change: 1 addition & 0 deletions src/bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ int bridge__new(struct mosquitto_db *db, struct mosquitto__bridge *bridge)
new_context->tls_certfile = new_context->bridge->tls_certfile;
new_context->tls_keyfile = new_context->bridge->tls_keyfile;
new_context->tls_cert_reqs = SSL_VERIFY_PEER;
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;
#ifdef FINAL_WITH_TLS_PSK
Expand Down
11 changes: 11 additions & 0 deletions src/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1023,6 +1023,17 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
}
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge and/or TLS-PSK support not available.");
#endif
}else if(!strcmp(token, "bridge_require_ocsp")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS)
if(reload) continue; // Listeners not valid for reloading.
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
}
if(conf__parse_bool(&token, "bridge_require_ocsp", &cur_bridge->tls_ocsp_required, saveptr)) return MOSQ_ERR_INVAL;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS support not available.");
#endif
}else if(!strcmp(token, "bridge_keyfile")){
#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 @@ -486,6 +486,7 @@ struct mosquitto__bridge{
bool initial_notification_done;
#ifdef WITH_TLS
bool tls_insecure;
bool tls_ocsp_required;
char *tls_cafile;
char *tls_capath;
char *tls_certfile;
Expand Down

0 comments on commit ea046c2

Please sign in to comment.