diff --git a/CMakeLists.txt b/CMakeLists.txt index 086d9179..d4d148ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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.7) +set (VERSION 1.4.8) if (WIN32) execute_process(COMMAND cmd /c echo %DATE% %TIME% OUTPUT_VARIABLE TIMESTAMP diff --git a/ChangeLog.txt b/ChangeLog.txt index 2612b520..3f13ce9f 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,21 @@ +1.4.8 - 20150214 +================ + +Broker: +- Wills published by clients connected to a listener with mount_point defined + now correctly obey the mount point. This was a potential security risk + because it allowed clients to publish messages outside of their restricted + mount point. This is only affects brokers where the mount_point option is in + use. Closes #487178. +- Fix detection of broken connections on Windows. Closes #485143. +- Close stdin etc. when daemonised. Closes #485589. +- Fix incorrect detection of FreeBSD and OpenBSD. Closes #485131. + +Client library: +- mosq->want_write should be cleared immediately before a call to SSL_write, + to allow clients using mosquitto_want_write() to get accurate results. + + 1.4.7 - 20151221 ================ diff --git a/appveyor.yml b/appveyor.yml index 8aaeb39c..590ad265 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,9 @@ +os: Visual Studio 2013 + environment: CMAKE_ARGS: -DCMAKE_BUILD_TYPE=Release NSIS_ROOT: C:\nsis - SSL_VER: 1_0_2d + SSL_VER: 1_0_2e configuration: - Release diff --git a/config.mk b/config.mk index 01532c3c..c0082fb9 100644 --- a/config.mk +++ b/config.mk @@ -83,7 +83,7 @@ WITH_SOCKS:=yes # Also bump lib/mosquitto.h, CMakeLists.txt, # installer/mosquitto.nsi, installer/mosquitto-cygwin.nsi -VERSION=1.4.7 +VERSION=1.4.8 TIMESTAMP:=$(shell date "+%F %T%z") # Client library SO version. Bump if incompatible API/ABI changes are made. @@ -115,7 +115,7 @@ LIB_LDFLAGS:=${LDFLAGS} BROKER_CFLAGS:=${LIB_CFLAGS} ${CPPFLAGS} -DVERSION="\"${VERSION}\"" -DTIMESTAMP="\"${TIMESTAMP}\"" -DWITH_BROKER CLIENT_CFLAGS:=${CFLAGS} ${CPPFLAGS} -I../lib -DVERSION="\"${VERSION}\"" -ifneq ($(or $(find $(UNAME),FreeBSD), $(find $(UNAME),OpenBSD)),) +ifneq ($(or $(findstring $(UNAME),FreeBSD), $(findstring $(UNAME),OpenBSD)),) BROKER_LIBS:=-lm else BROKER_LIBS:=-ldl -lm diff --git a/installer/mosquitto-cygwin.nsi b/installer/mosquitto-cygwin.nsi index f87fca57..bd350d2f 100644 --- a/installer/mosquitto-cygwin.nsi +++ b/installer/mosquitto-cygwin.nsi @@ -7,7 +7,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "mosquitto" -!define VERSION 1.4.7 +!define VERSION 1.4.8 OutFile "mosquitto-${VERSION}-install-cygwin.exe" InstallDir "$PROGRAMFILES\mosquitto" diff --git a/installer/mosquitto.nsi b/installer/mosquitto.nsi index 9e01367e..4eb0d605 100644 --- a/installer/mosquitto.nsi +++ b/installer/mosquitto.nsi @@ -9,7 +9,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "mosquitto" -!define VERSION 1.4.7 +!define VERSION 1.4.8 OutFile "mosquitto-${VERSION}-install-win32.exe" InstallDir "$PROGRAMFILES\mosquitto" diff --git a/lib/messages_mosq.c b/lib/messages_mosq.c index 478412b8..2adaa867 100644 --- a/lib/messages_mosq.c +++ b/lib/messages_mosq.c @@ -192,10 +192,10 @@ void _mosquitto_messages_reconnect_reset(struct mosquitto *mosq) mosq->out_queue_len++; message->timestamp = 0; - if(message->msg.qos > 0){ - mosq->inflight_messages++; - } if(mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages){ + if(message->msg.qos > 0){ + mosq->inflight_messages++; + } if(message->msg.qos == 1){ message->state = mosq_ms_wait_for_puback; }else if(message->msg.qos == 2){ diff --git a/lib/mosquitto.c b/lib/mosquitto.c index 195a25aa..cd40f775 100644 --- a/lib/mosquitto.c +++ b/lib/mosquitto.c @@ -863,7 +863,6 @@ int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets) if(mosq->ssl){ if(mosq->want_write){ FD_SET(mosq->sock, &writefds); - mosq->want_write = false; }else if(mosq->want_connect){ /* Remove possible FD_SET from above, we don't want to check * for writing if we are still connecting, unless want_write is diff --git a/lib/mosquitto.h b/lib/mosquitto.h index d279f063..a43924f9 100644 --- a/lib/mosquitto.h +++ b/lib/mosquitto.h @@ -45,7 +45,7 @@ extern "C" { #define LIBMOSQUITTO_MAJOR 1 #define LIBMOSQUITTO_MINOR 4 -#define LIBMOSQUITTO_REVISION 7 +#define LIBMOSQUITTO_REVISION 8 /* 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) diff --git a/lib/net_mosq.c b/lib/net_mosq.c index 4c258a47..ccb717a3 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -712,6 +712,7 @@ ssize_t _mosquitto_net_write(struct mosquitto *mosq, void *buf, size_t count) errno = 0; #ifdef WITH_TLS if(mosq->ssl){ + mosq->want_write = false; ret = SSL_write(mosq->ssl, buf, count); if(ret < 0){ err = SSL_get_error(mosq->ssl, ret); diff --git a/set-version.sh b/set-version.sh new file mode 100755 index 00000000..eb17c0e2 --- /dev/null +++ b/set-version.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +MAJOR=1 +MINOR=4 +REVISION=8 + +sed -i "s/^VERSION=.*/VERSION=${MAJOR}.${MINOR}.${REVISION}/" config.mk + +sed -i "s/^#define LIBMOSQUITTO_MAJOR .*/#define LIBMOSQUITTO_MAJOR ${MAJOR}/" lib/mosquitto.h +sed -i "s/^#define LIBMOSQUITTO_MINOR .*/#define LIBMOSQUITTO_MINOR ${MINOR}/" lib/mosquitto.h +sed -i "s/^#define LIBMOSQUITTO_REVISION .*/#define LIBMOSQUITTO_REVISION ${REVISION}/" lib/mosquitto.h + +sed -i "s/^set (VERSION .*)/set (VERSION ${MAJOR}.${MINOR}.${REVISION})/" CMakeLists.txt + +sed -i "s/^!define VERSION .*/!define VERSION ${MAJOR}.${MINOR}.${REVISION}/" installer/*.nsi + diff --git a/src/loop.c b/src/loop.c index a5f624b3..2a99ae7d 100644 --- a/src/loop.c +++ b/src/loop.c @@ -56,7 +56,6 @@ extern int run; extern int g_clients_expired; #endif -static void loop_handle_errors(struct mosquitto_db *db, struct pollfd *pollfds); static void loop_handle_reads_writes(struct mosquitto_db *db, struct pollfd *pollfds); #ifdef WITH_WEBSOCKETS @@ -322,7 +321,7 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li fdcount = WSAPoll(pollfds, pollfd_index, 100); #endif if(fdcount == -1){ - loop_handle_errors(db, pollfds); + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error in poll: %s.", strerror(errno)); }else{ loop_handle_reads_writes(db, pollfds); @@ -437,23 +436,6 @@ void do_disconnect(struct mosquitto_db *db, struct mosquitto *context) } } -/* Error ocurred, probably an fd has been closed. - * Loop through and check them all. - */ -static void loop_handle_errors(struct mosquitto_db *db, struct pollfd *pollfds) -{ - struct mosquitto *context, *ctxt_tmp; - - HASH_ITER(hh_sock, db->contexts_by_sock, context, ctxt_tmp){ - if(context->pollfd_index < 0){ - continue; - } - - if(pollfds[context->pollfd_index].revents & (POLLERR | POLLNVAL)){ - do_disconnect(db, context); - } - } -} static void loop_handle_reads_writes(struct mosquitto_db *db, struct pollfd *pollfds) { @@ -467,6 +449,10 @@ 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 || diff --git a/src/mosquitto.c b/src/mosquitto.c index eaf43953..55ff678c 100644 --- a/src/mosquitto.c +++ b/src/mosquitto.c @@ -21,6 +21,7 @@ Contributors: # define _BSD_SOURCE # include # include +# include #endif #ifndef WIN32 @@ -175,6 +176,35 @@ void handle_sigusr1(int signal) #endif } +void mosquitto__daemonise(void) +{ +#ifndef WIN32 + char err[256]; + pid_t pid; + + pid = fork(); + if(pid < 0){ + strerror_r(errno, err, 256); + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error in fork: %s", err); + exit(1); + } + if(pid > 0){ + exit(0); + } + if(setsid() < 0){ + strerror_r(errno, err, 256); + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error in setsid: %s", err); + exit(1); + } + + assert(freopen("/dev/null", "r", stdin)); + assert(freopen("/dev/null", "w", stdout)); + assert(freopen("/dev/null", "w", stderr)); +#else + _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Can't start in daemon mode in Windows."); +#endif +} + /* Signal handler for SIGUSR2 - vacuum the db. */ void handle_sigusr2(int signal) { @@ -197,7 +227,6 @@ int main(int argc, char *argv[]) #ifdef WIN32 SYSTEMTIME st; #else - char err[256]; struct timeval tv; #endif struct mosquitto *ctxt, *ctxt_tmp; @@ -236,20 +265,7 @@ int main(int argc, char *argv[]) int_db.config = &config; if(config.daemon){ -#ifndef WIN32 - switch(fork()){ - case 0: - break; - case -1: - strerror_r(errno, err, 256); - _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error in fork: %s", err); - return 1; - default: - return MOSQ_ERR_SUCCESS; - } -#else - _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Can't start in daemon mode in Windows."); -#endif + mosquitto__daemonise(); } if(config.daemon && config.pid_file){ diff --git a/src/read_handle_server.c b/src/read_handle_server.c index 2e35aaa3..2b9c8f5f 100644 --- a/src/read_handle_server.c +++ b/src/read_handle_server.c @@ -82,6 +82,7 @@ int mqtt3_handle_connect(struct mosquitto_db *db, struct mosquitto *context) uint8_t connect_ack = 0; char *client_id = NULL; char *will_payload = NULL, *will_topic = NULL; + char *will_topic_mount; uint16_t will_payloadlen; struct mosquitto_message *will_struct = NULL; uint8_t will, will_retain, will_qos, clean_session; @@ -240,6 +241,21 @@ int mqtt3_handle_connect(struct mosquitto_db *db, struct mosquitto *context) rc = 1; goto handle_connect_error; } + + if(context->listener && context->listener->mount_point){ + slen = strlen(context->listener->mount_point) + strlen(will_topic); + will_topic_mount = _mosquitto_malloc(slen+1); + if(!will_topic_mount){ + rc = MOSQ_ERR_NOMEM; + goto handle_connect_error; + } + snprintf(will_topic_mount, slen, "%s%s", context->listener->mount_point, will_topic); + will_topic_mount[slen] = '\0'; + + _mosquitto_free(will_topic); + will_topic = will_topic_mount; + } + if(mosquitto_pub_topic_check(will_topic)){ rc = 1; goto handle_connect_error; diff --git a/src/websockets.c b/src/websockets.c index 6e641af2..d79fabf7 100644 --- a/src/websockets.c +++ b/src/websockets.c @@ -604,6 +604,7 @@ struct libwebsocket_context *mosq_websockets_init(struct _mqtt3_listener *listen user = _mosquitto_calloc(1, sizeof(struct libws_mqtt_hack)); if(!user){ _mosquitto_free(p); + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Out of memory."); return NULL; } @@ -616,6 +617,7 @@ struct libwebsocket_context *mosq_websockets_init(struct _mqtt3_listener *listen if(!user->http_dir){ _mosquitto_free(user); _mosquitto_free(p); + _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open http dir \"%s\".", user->http_dir); return NULL; } }