Merge branch 'master' of git://github.com/LarsVoelker/mosquitto into LarsVoelker-master

pull/1224/head
Roger A. Light 7 years ago
commit ea046c2405

@ -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

@ -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 \
@ -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 $@

@ -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);
}
}

@ -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);

@ -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;

@ -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);

@ -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 */
@ -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);
/* ======================================================================
*

@ -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;

@ -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);

@ -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"

@ -0,0 +1,159 @@
/*
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
Copyright (c) 2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG), Dr. Lars Voelker <lars.voelker@bmw.de>
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://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://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, <daniel@haxx.se>, 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

@ -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

@ -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>

@ -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

@ -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 \
@ -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 $@

@ -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

@ -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)

@ -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;

Loading…
Cancel
Save