Merge branch 'fixes'

pull/267/head v1.4.10
Roger A. Light 9 years ago
commit ee1fd1718b

@ -11,7 +11,7 @@ project(mosquitto)
cmake_minimum_required(VERSION 2.8)
# Only for version 3 and up. cmake_policy(SET CMP0042 NEW)
set (VERSION 1.4.9)
set (VERSION 1.4.10)
if (WIN32)
execute_process(COMMAND cmd /c echo %DATE% %TIME% OUTPUT_VARIABLE TIMESTAMP

@ -1,3 +1,29 @@
1.4.10 - 20160816
=================
Broker:
- Fix TLS operation with websockets listeners and libwebsockts 2.x. Closes
#186.
- Don't disconnect client on HUP before reading the pending data. Closes #7.
- Fix some $SYS messages being incorrectly persisted. Closes #191.
- Support OpenSSL 1.1.0.
- Call fsync after persisting data to ensure it is correctly written. Closes
#189.
- Fix persistence saving of subscription QoS on big-endian machines.
- Fix will retained flag handling on Windows. Closes #222.
- Broker now displays an error if it is unable to open the log file. Closes
#234.
Client library:
- Support OpenSSL 1.1.0.
- Fixed the C++ library not allowing SOCKS support to be used. Closes #198.
- Fix memory leak when verifying a server certificate with a subjectAltName
section. Closes #237.
Build:
- Don't attempt to install docs when WITH_DOCS=no. Closes #184.
1.4.9 - 20160603
================

@ -36,7 +36,9 @@ test : mosquitto
install : mosquitto
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} install; done
ifeq ($(WITH_DOCS),yes)
set -e; for d in ${DOCDIRS}; do $(MAKE) -C $${d} install; done
endif
$(INSTALL) -d ${DESTDIR}/etc/mosquitto
$(INSTALL) -m 644 mosquitto.conf ${DESTDIR}/etc/mosquitto/mosquitto.conf.example
$(INSTALL) -m 644 aclfile.example ${DESTDIR}/etc/mosquitto/aclfile.example

@ -55,6 +55,7 @@ Michael Hekel
Michael Laing
Michael Rushton
Mike Bush
Milan Tucic
Neil Bothwick
Nicholas Humfrey
Nicholas O'Leary

@ -83,7 +83,7 @@ WITH_SOCKS:=yes
# Also bump lib/mosquitto.h, CMakeLists.txt,
# installer/mosquitto.nsi, installer/mosquitto-cygwin.nsi
VERSION=1.4.9
VERSION=1.4.10
TIMESTAMP:=$(shell date "+%F %T%z")
# Client library SO version. Bump if incompatible API/ABI changes are made.

@ -7,7 +7,7 @@
!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
Name "mosquitto"
!define VERSION 1.4.9
!define VERSION 1.4.10
OutFile "mosquitto-${VERSION}-install-cygwin.exe"
InstallDir "$PROGRAMFILES\mosquitto"

@ -9,7 +9,7 @@
!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
Name "mosquitto"
!define VERSION 1.4.9
!define VERSION 1.4.10
OutFile "mosquitto-${VERSION}-install-win32.exe"
InstallDir "$PROGRAMFILES\mosquitto"

@ -281,11 +281,7 @@ void mosquittopp::user_data_set(void *userdata)
int mosquittopp::socks5_set(const char *host, int port, const char *username, const char *password)
{
#ifdef WITH_SOCKS
return mosquitto_socks5_set(m_mosq, host, port, username, password);
#else
return MOSQ_ERR_NOT_SUPPORTED;
#endif
}

@ -45,7 +45,7 @@ extern "C" {
#define LIBMOSQUITTO_MAJOR 1
#define LIBMOSQUITTO_MINOR 4
#define LIBMOSQUITTO_REVISION 9
#define LIBMOSQUITTO_REVISION 10
/* LIBMOSQUITTO_VERSION_NUMBER looks like 1002001 for e.g. version 1.2.1. */
#define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION)

@ -129,6 +129,7 @@ int _mosquitto_verify_certificate_hostname(X509 *cert, const char *hostname)
if(nval->type == GEN_DNS){
data = ASN1_STRING_data(nval->d.dNSName);
if(data && !mosquitto__cmp_hostname_wildcard((char *)data, hostname)){
sk_GENERAL_NAME_pop_free(san, GENERAL_NAME_free);
return 1;
}
have_san_dns = true;
@ -136,20 +137,24 @@ int _mosquitto_verify_certificate_hostname(X509 *cert, const char *hostname)
data = ASN1_STRING_data(nval->d.iPAddress);
if(nval->d.iPAddress->length == 4 && ipv4_ok){
if(!memcmp(ipv4_addr, data, 4)){
sk_GENERAL_NAME_pop_free(san, GENERAL_NAME_free);
return 1;
}
}else if(nval->d.iPAddress->length == 16 && ipv6_ok){
if(!memcmp(ipv6_addr, data, 16)){
sk_GENERAL_NAME_pop_free(san, GENERAL_NAME_free);
return 1;
}
}
}
}
sk_GENERAL_NAME_pop_free(san, GENERAL_NAME_free);
if(have_san_dns){
/* Only check CN if subjectAltName DNS entry does not exist. */
return 0;
}
}
subj = X509_get_subject_name(cert);
if(X509_NAME_get_text_by_NID(subj, NID_commonName, name, sizeof(name)) > 0){
name[sizeof(name) - 1] = '\0';

@ -41,7 +41,7 @@
<refsect1>
<title>Description</title>
<para><command>mosquitto_passwd</command> is a tool for managing
password files the the mosquitto MQTT broker.</para>
password files the mosquitto MQTT broker.</para>
<para>Usernames must not contain ":". Passwords are stored in a similar
format to
<citerefentry><refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>

@ -11,8 +11,9 @@ separately in the case that they are not already available.
Capabilities
------------
The network support in Windows is severely limited. The broker is limited to approximately
1024 MQTT connections.
Some versions of Windows have limitations on the number of concurrent
connections. Non-server versions have been reported to be limited to
approximately 1024 connections.
Websockets
@ -20,7 +21,7 @@ Websockets
The broker executables provided in the installers do not have Websockets support enabled.
If you wish to have a version of the broker with Websockets support, you will need to compile
libwebsockets version v1.3-chrome37-firefox30 yourself and mosquitto version 1.4 yourself.
libwebsockets version v1.7 onwards because no Windows binaries are provided.
Please note that on Windows, libwebsockets limits connections to a maximum of 64 clients.

@ -2,7 +2,11 @@ Eclipse Mosquitto
=================
Mosquitto is an open source implementation of a server for version 3.1 and
3.1.1 of the MQTT protocol.
3.1.1 of the MQTT protocol. It also includes a C and C++ client library, and
the `mosquitto_pub` and `mosquitto_sub` utilities for publishing and
subscribing.
## Links
See the following links for more information on MQTT:
@ -17,6 +21,57 @@ Mosquitto project information is available at the following locations:
There is also a public test server available at <http://test.mosquitto.org/>
## Installing
See <http://mosquitto.org/download/> for details on installing binaries for
various platforms.
## Quick start
If you have installed a binary package the broker should have been started
automatically. If not, it can be started with a basic configuration:
mosquitto
Then use `mosquitto_sub` to subscribe to a topic:
mosquitto_sub -t 'test/topic' -v
And to publish a message:
mosquitto_pub -t 'test/topic' -m 'hello world'
## Documentation
Documentation for the broker, clients and client library API can be found in
the man pages, which are available online at <http://mosquitto.org/man/>. There
are also pages with an introduction to the features of MQTT, the
`mosquitto_passwd` utility for dealing with username/passwords, and a
description of the configuration file options available for the broker.
Detailed client library API documentation can be found at <http://mosquitto.org/api/>
## Building from source
To build from source the recommended route for end users is to download the
archive from <http://mosquitto.org/download/>.
On Windows and Mac, use `cmake` to build. On other platforms, just run `make`
to build. For Windows, see also `readme-windows.md`.
If you are building from the git repository then the documentation will not
already be built. Use `make binary` to skip building the man pages, or install
`docbook-xsl` on Debian/Ubuntu systems.
### Build Dependencies
* c-ares (libc-ares2-dev on Debian based systems) - disable with `make WITH_DNS_SRV=no`
* libuuid (uuid-dev) - disable with `make WITH_UUID=no`
* libwebsockets (libwebsockets-dev) - enable with `make WITH_LIBWEBSOCKETS=yes`
* openssl (libssl-dev on Debian based systems) - disable with `make WITH_TLS=no`
## Credits
Mosquitto was written by Roger Light <roger@atchoo.org>
Master: [![Travis Build Status (master)](https://travis-ci.org/eclipse/mosquitto.svg?branch=master)](https://travis-ci.org/eclipse/mosquitto)

@ -104,8 +104,10 @@ mosquitto_passwd.o : mosquitto_passwd.c
install : all
$(INSTALL) -d ${DESTDIR}$(prefix)/sbin
$(INSTALL) -s --strip-program=${CROSS_COMPILE}${STRIP} mosquitto ${DESTDIR}${prefix}/sbin/mosquitto
$(INSTALL) -d ${DESTDIR}$(prefix)/include
$(INSTALL) mosquitto_plugin.h ${DESTDIR}${prefix}/include/mosquitto_plugin.h
ifeq ($(WITH_TLS),yes)
$(INSTALL) -d ${DESTDIR}$(prefix)/bin
$(INSTALL) -s --strip-program=${CROSS_COMPILE}${STRIP} mosquitto_passwd ${DESTDIR}${prefix}/bin/mosquitto_passwd
endif

@ -71,6 +71,8 @@ int mqtt3_log_init(struct mqtt3_config *config)
}
config->log_fptr = _mosquitto_fopen(config->log_file, "at");
if(!config->log_fptr){
log_destinations = MQTT3_LOG_STDERR;
log_priorities = MOSQ_LOG_ERR;
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open log file %s for writing.", config->log_file);
return MOSQ_ERR_INVAL;
}

@ -449,10 +449,6 @@ static void loop_handle_reads_writes(struct mosquitto_db *db, struct pollfd *pol
}
assert(pollfds[context->pollfd_index].fd == context->sock);
if(pollfds[context->pollfd_index].revents & (POLLERR | POLLNVAL | POLLHUP)){
do_disconnect(db, context);
continue;
}
#ifdef WITH_TLS
if(pollfds[context->pollfd_index].revents & POLLOUT ||
context->want_write ||
@ -496,6 +492,10 @@ static void loop_handle_reads_writes(struct mosquitto_db *db, struct pollfd *pol
}
}while(SSL_DATA_PENDING(context));
}
if(pollfds[context->pollfd_index].revents & (POLLERR | POLLNVAL | POLLHUP)){
do_disconnect(db, context);
continue;
}
}
}

@ -287,7 +287,10 @@ int main(int argc, char *argv[])
/* Initialise logging only after initialising the database in case we're
* logging to topics */
mqtt3_log_init(&config);
if(mqtt3_log_init(&config)){
rc = 1;
return rc;
}
_mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s (build date %s) starting", VERSION, TIMESTAMP);
if(config.config_file){
_mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Config loaded from %s.", config.config_file);

@ -31,6 +31,7 @@ Contributors:
# define libwebsocket_write(A, B, C, D) lws_write((A), (B), (C), (D))
# define libwebsocket_get_socket_fd(A) lws_get_socket_fd((A))
# define libwebsockets_return_http_status(A, B, C, D) lws_return_http_status((B), (C), (D))
# define libwebsocket_get_protocol(A) lws_get_protocol((A))
# define libwebsocket_context lws_context
# define libwebsocket_protocols lws_protocols

@ -90,7 +90,11 @@ int output_new_password(FILE *fptr, const char *username, const char *password)
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int hash_len;
const EVP_MD *digest;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_MD_CTX context;
#else
EVP_MD_CTX *context;
#endif
rc = RAND_bytes(salt, SALT_LEN);
if(!rc){
@ -113,12 +117,21 @@ int output_new_password(FILE *fptr, const char *username, const char *password)
return 1;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_MD_CTX_init(&context);
EVP_DigestInit_ex(&context, digest, NULL);
EVP_DigestUpdate(&context, password, strlen(password));
EVP_DigestUpdate(&context, salt, SALT_LEN);
EVP_DigestFinal_ex(&context, hash, &hash_len);
EVP_MD_CTX_cleanup(&context);
#else
context = EVP_MD_CTX_new();
EVP_DigestInit_ex(context, digest, NULL);
EVP_DigestUpdate(context, password, strlen(password));
EVP_DigestUpdate(context, salt, SALT_LEN);
EVP_DigestFinal_ex(context, hash, &hash_len);
EVP_MD_CTX_free(context);
#endif
rc = base64_encode(hash, hash_len, &hash64);
if(rc){

@ -34,6 +34,11 @@ struct mosquitto_auth_opt {
* shared library. Using gcc this can be achieved as follows:
*
* gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -o plugin.so
*
* On Mac OS X:
*
* gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -undefined dynamic_lookup -o plugin.so
*
*/
/* =========================================================================

@ -302,7 +302,7 @@ static int _mosquitto_tls_server_ctx(struct _mqtt3_listener *listener)
#endif
#ifdef WITH_EC
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_CTX_set_ecdh_auto(listener->ssl_ctx, 1);
#elif OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10002000L
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);

@ -140,7 +140,7 @@ static int mqtt3_db_message_store_write(struct mosquitto_db *db, FILE *db_fptr)
stored = db->msg_store;
while(stored){
if(stored->topic && !strncmp(stored->topic, "$SYS", 4)){
if(stored->ref_count == 1 && stored->dest_id_count == 0){
if(stored->ref_count <= 1 && stored->dest_id_count == 0){
/* $SYS messages that are only retained shouldn't be persisted. */
stored = stored->next;
continue;
@ -261,6 +261,7 @@ static int _db_subs_retain_write(struct mosquitto_db *db, FILE *db_fptr, struct
char *thistopic;
uint32_t length;
uint16_t i16temp;
uint8_t i8temp;
dbid_t i64temp;
size_t slen;
@ -292,7 +293,8 @@ static int _db_subs_retain_write(struct mosquitto_db *db, FILE *db_fptr, struct
write_e(db_fptr, &i16temp, sizeof(uint16_t));
write_e(db_fptr, thistopic, slen);
write_e(db_fptr, &sub->qos, sizeof(uint8_t));
i8temp = (uint8_t )sub->qos;
write_e(db_fptr, &i8temp, sizeof(uint8_t));
}
sub = sub->next;
}
@ -362,6 +364,36 @@ int mqtt3_db_backup(struct mosquitto_db *db, bool shutdown)
}
snprintf(outfile, len, "%s.new", db->config->persistence_filepath);
outfile[len] = '\0';
#ifndef WIN32
/**
*
* If a system lost power during the rename operation at the
* end of this file the filesystem could potentially be left
* with a directory that looks like this after powerup:
*
* 24094 -rw-r--r-- 2 root root 4099 May 30 16:27 mosquitto.db
* 24094 -rw-r--r-- 2 root root 4099 May 30 16:27 mosquitto.db.new
*
* The 24094 shows that mosquitto.db.new is hard-linked to the
* same file as mosquitto.db. If fopen(outfile, "wb") is naively
* called then mosquitto.db will be truncated and the database
* potentially corrupted.
*
* Any existing mosquitto.db.new file must be removed prior to
* opening to guarantee that it is not hard-linked to
* mosquitto.db.
*
*/
rc = unlink(outfile);
if (rc != 0) {
if (errno != ENOENT) {
_mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Error saving in-memory database, unable to remove %s.", outfile);
goto error;
}
}
#endif
db_fptr = _mosquitto_fopen(outfile, "wb");
if(db_fptr == NULL){
_mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Error saving in-memory database, unable to open %s for writing.", outfile);
@ -395,6 +427,32 @@ int mqtt3_db_backup(struct mosquitto_db *db, bool shutdown)
mqtt3_db_client_write(db, db_fptr);
mqtt3_db_subs_retain_write(db, db_fptr);
#ifndef WIN32
/**
*
* Closing a file does not guarantee that the contents are
* written to disk. Need to flush to send data from app to OS
* buffers, then fsync to deliver data from OS buffers to disk
* (as well as disk hardware permits).
*
* man close (http://linux.die.net/man/2/close, 2016-06-20):
*
* "successful close does not guarantee that the data has
* been successfully saved to disk, as the kernel defers
* writes. It is not common for a filesystem to flush
* the buffers when the stream is closed. If you need
* to be sure that the data is physically stored, use
* fsync(2). (It will depend on the disk hardware at this
* point."
*
* This guarantees that the new state file will not overwrite
* the old state file before its contents are valid.
*
*/
fflush(db_fptr);
fsync(fileno(db_fptr));
#endif
fclose(db_fptr);
#ifdef WIN32

@ -180,7 +180,7 @@ int mqtt3_handle_connect(struct mosquitto_db *db, struct mosquitto *context)
rc = MOSQ_ERR_PROTOCOL;
goto handle_connect_error;
}
will_retain = connect_flags & 0x20;
will_retain = ((connect_flags & 0x20) == 0x20); // Temporary hack because MSVC<1800 doesn't have stdbool.h.
password_flag = connect_flags & 0x40;
username_flag = connect_flags & 0x80;
@ -364,7 +364,7 @@ int mqtt3_handle_connect(struct mosquitto_db *db, struct mosquitto *context)
goto handle_connect_error;
}
name_entry = X509_NAME_get_entry(name, i);
context->username = _mosquitto_strdup((char *)ASN1_STRING_data(name_entry->value));
context->username = _mosquitto_strdup((char *)ASN1_STRING_data(X509_NAME_ENTRY_get_data(name_entry)));
if(!context->username){
rc = 1;
goto handle_connect_error;

@ -770,6 +770,7 @@ int mosquitto_psk_key_get_default(struct mosquitto_db *db, const char *hint, con
int _pw_digest(const char *password, const unsigned char *salt, unsigned int salt_len, unsigned char *hash, unsigned int *hash_len)
{
const EVP_MD *digest;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_MD_CTX context;
digest = EVP_get_digestbyname("sha512");
@ -785,6 +786,23 @@ int _pw_digest(const char *password, const unsigned char *salt, unsigned int sal
/* hash is assumed to be EVP_MAX_MD_SIZE bytes long. */
EVP_DigestFinal_ex(&context, hash, hash_len);
EVP_MD_CTX_cleanup(&context);
#else
EVP_MD_CTX *context;
digest = EVP_get_digestbyname("sha512");
if(!digest){
// FIXME fprintf(stderr, "Error: Unable to create openssl digest.\n");
return 1;
}
context = EVP_MD_CTX_new();
EVP_DigestInit_ex(context, digest, NULL);
EVP_DigestUpdate(context, password, strlen(password));
EVP_DigestUpdate(context, salt, salt_len);
/* hash is assumed to be EVP_MAX_MD_SIZE bytes long. */
EVP_DigestFinal_ex(context, hash, hash_len);
EVP_MD_CTX_free(context);
#endif
return MOSQ_ERR_SUCCESS;
}

@ -168,7 +168,8 @@ static int callback_mqtt(struct libwebsocket_context *context,
struct mosquitto_db *db;
struct mosquitto *mosq = NULL;
struct _mosquitto_packet *packet;
int count;
int count, i, j;
const struct libwebsocket_protocols *p;
struct libws_mqtt_data *u = (struct libws_mqtt_data *)user;
size_t pos;
uint8_t *buf;
@ -181,6 +182,18 @@ static int callback_mqtt(struct libwebsocket_context *context,
case LWS_CALLBACK_ESTABLISHED:
mosq = mqtt3_context_init(db, WEBSOCKET_CLIENT);
if(mosq){
p = libwebsocket_get_protocol(wsi);
for (i=0; i<db->config->listener_count; i++){
if (db->config->listeners[i].protocol == mp_websockets) {
for (j=0; db->config->listeners[i].ws_protocol[j].name; j++){
if (p == &db->config->listeners[i].ws_protocol[j]){
mosq->listener = &db->config->listeners[i];
mosq->listener->client_count++;
}
}
}
}
#if !defined(LWS_LIBRARY_VERSION_NUMBER)
mosq->ws_context = context;
#endif
@ -603,6 +616,9 @@ struct libwebsocket_context *mosq_websockets_init(struct _mqtt3_listener *listen
#ifndef LWS_IS_OLD
info.options |= LWS_SERVER_OPTION_DISABLE_IPV6;
#endif
#if LWS_LIBRARY_VERSION_MAJOR>1
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
#endif
user = _mosquitto_calloc(1, sizeof(struct libws_mqtt_hack));
if(!user){

Loading…
Cancel
Save