Fix reloading of config when fds are exhausted.

pull/712/head
Roger A. Light 8 years ago
parent 15486f48e7
commit b76982db13

@ -1,3 +1,8 @@
Security:
- Fix CVE-xxxx-xxxx. If a SIGHUP is sent to the broker when there are no more
file descriptors, then opening the configuration file will fail and security
settings will be set back to their default values.
Broker: Broker:
- Use constant time memcmp for password comparisons. - Use constant time memcmp for password comparisons.
- Fix incorrect PSK key being used if it had leading zeroes. - Fix incorrect PSK key being used if it had leading zeroes.

@ -129,7 +129,7 @@ static int _conf_attempt_resolve(const char *host, const char *text, int log, co
return MOSQ_ERR_SUCCESS; return MOSQ_ERR_SUCCESS;
} }
static void _config_init_reload(struct mqtt3_config *config) static void _config_init_reload(struct mosquitto_db *db, struct mqtt3_config *config)
{ {
int i; int i;
/* Set defaults */ /* Set defaults */
@ -165,7 +165,7 @@ static void _config_init_reload(struct mqtt3_config *config)
#else #else
config->log_facility = LOG_DAEMON; config->log_facility = LOG_DAEMON;
config->log_dest = MQTT3_LOG_STDERR; config->log_dest = MQTT3_LOG_STDERR;
if(config->verbose){ if(db->verbose){
config->log_type = INT_MAX; config->log_type = INT_MAX;
}else{ }else{
config->log_type = MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO; config->log_type = MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO;
@ -197,11 +197,10 @@ static void _config_init_reload(struct mqtt3_config *config)
} }
} }
void mqtt3_config_init(struct mqtt3_config *config) void mqtt3_config_init(struct mosquitto_db *db, struct mqtt3_config *config)
{ {
memset(config, 0, sizeof(struct mqtt3_config)); memset(config, 0, sizeof(struct mqtt3_config));
_config_init_reload(config); _config_init_reload(db, config);
config->config_file = NULL;
config->daemon = false; config->daemon = false;
config->default_listener.host = NULL; config->default_listener.host = NULL;
config->default_listener.port = 0; config->default_listener.port = 0;
@ -234,7 +233,6 @@ void mqtt3_config_init(struct mqtt3_config *config)
#endif #endif
config->auth_plugin = NULL; config->auth_plugin = NULL;
config->auth_plugin_deny_special_chars = true; config->auth_plugin_deny_special_chars = true;
config->verbose = false;
config->message_size_limit = 0; config->message_size_limit = 0;
} }
@ -248,7 +246,6 @@ void mqtt3_config_cleanup(struct mqtt3_config *config)
if(config->acl_file) _mosquitto_free(config->acl_file); if(config->acl_file) _mosquitto_free(config->acl_file);
if(config->auto_id_prefix) _mosquitto_free(config->auto_id_prefix); if(config->auto_id_prefix) _mosquitto_free(config->auto_id_prefix);
if(config->clientid_prefixes) _mosquitto_free(config->clientid_prefixes); if(config->clientid_prefixes) _mosquitto_free(config->clientid_prefixes);
if(config->config_file) _mosquitto_free(config->config_file);
if(config->password_file) _mosquitto_free(config->password_file); if(config->password_file) _mosquitto_free(config->password_file);
if(config->persistence_location) _mosquitto_free(config->persistence_location); if(config->persistence_location) _mosquitto_free(config->persistence_location);
if(config->persistence_file) _mosquitto_free(config->persistence_file); if(config->persistence_file) _mosquitto_free(config->persistence_file);
@ -354,7 +351,7 @@ static void print_usage(void)
printf("\nSee http://mosquitto.org/ for more information.\n\n"); printf("\nSee http://mosquitto.org/ for more information.\n\n");
} }
int mqtt3_config_parse_args(struct mqtt3_config *config, int argc, char *argv[]) int mqtt3_config_parse_args(struct mosquitto_db *db, struct mqtt3_config *config, int argc, char *argv[])
{ {
int i; int i;
int port_tmp; int port_tmp;
@ -362,13 +359,9 @@ int mqtt3_config_parse_args(struct mqtt3_config *config, int argc, char *argv[])
for(i=1; i<argc; i++){ for(i=1; i<argc; i++){
if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config-file")){ if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config-file")){
if(i<argc-1){ if(i<argc-1){
config->config_file = _mosquitto_strdup(argv[i+1]); db->config_file = argv[i+1];
if(!config->config_file){
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
if(mqtt3_config_read(config, false)){ if(mqtt3_config_read(db, config, false)){
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open configuration file."); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open configuration file.");
return MOSQ_ERR_INVAL; return MOSQ_ERR_INVAL;
} }
@ -400,7 +393,7 @@ int mqtt3_config_parse_args(struct mqtt3_config *config, int argc, char *argv[])
} }
i++; i++;
}else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")){ }else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")){
config->verbose = true; db->verbose = true;
}else{ }else{
fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]); fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
print_usage(); print_usage();
@ -475,22 +468,87 @@ int mqtt3_config_parse_args(struct mqtt3_config *config, int argc, char *argv[])
if(!config->user){ if(!config->user){
config->user = "mosquitto"; config->user = "mosquitto";
} }
if(config->verbose){ if(db->verbose){
config->log_type = INT_MAX; config->log_type = INT_MAX;
} }
return MOSQ_ERR_SUCCESS; return MOSQ_ERR_SUCCESS;
} }
int mqtt3_config_read(struct mqtt3_config *config, bool reload) /* Copy reloaded config into existing config struct */
void config__copy(struct mqtt3_config *src, struct mqtt3_config *dest)
{
_mosquitto_free(dest->acl_file);
dest->acl_file = src->acl_file;
dest->allow_anonymous = src->allow_anonymous;
dest->allow_duplicate_messages = src->allow_duplicate_messages;
dest->allow_zero_length_clientid = src->allow_zero_length_clientid;
_mosquitto_free(dest->auto_id_prefix);
dest->auto_id_prefix = src->auto_id_prefix;
dest->auto_id_prefix_len = src->auto_id_prefix_len;
dest->autosave_interval = src->autosave_interval;
dest->autosave_on_changes = src->autosave_on_changes;
_mosquitto_free(dest->clientid_prefixes);
dest->clientid_prefixes = src->clientid_prefixes;
dest->connection_messages = src->connection_messages;
dest->log_dest = src->log_dest;
dest->log_facility = src->log_facility;
dest->log_type = src->log_type;
dest->log_timestamp = src->log_timestamp;
_mosquitto_free(dest->log_file);
dest->log_file = src->log_file;
dest->message_size_limit = src->message_size_limit;
_mosquitto_free(dest->password_file);
dest->password_file = src->password_file;
dest->persistence = src->persistence;
_mosquitto_free(dest->persistence_location);
dest->persistence_location = src->persistence_location;
_mosquitto_free(dest->persistence_file);
dest->persistence_file = src->persistence_file;
_mosquitto_free(dest->persistence_filepath);
dest->persistence_filepath = src->persistence_filepath;
dest->persistent_client_expiration = src->persistent_client_expiration;
_mosquitto_free(dest->psk_file);
dest->psk_file = src->psk_file;
dest->queue_qos0_messages = src->queue_qos0_messages;
dest->retry_interval = src->retry_interval;
dest->sys_interval = src->sys_interval;
dest->upgrade_outgoing_qos = src->upgrade_outgoing_qos;
#ifdef WITH_WEBSOCKETS
dest->websockets_log_level = src->websockets_log_level;
#endif
}
int mqtt3_config_read(struct mosquitto_db *db, struct mqtt3_config *config, bool reload)
{ {
int rc = MOSQ_ERR_SUCCESS; int rc = MOSQ_ERR_SUCCESS;
struct config_recurse cr; struct config_recurse cr;
int lineno; int lineno;
int len; int len;
struct mqtt3_config config_reload;
#ifdef WITH_BRIDGE #ifdef WITH_BRIDGE
int i; int i;
#endif #endif
if(reload){
memset(&config_reload, 0, sizeof(struct mqtt3_config));
}
cr.log_dest = MQTT3_LOG_NONE; cr.log_dest = MQTT3_LOG_NONE;
cr.log_dest_set = 0; cr.log_dest_set = 0;
cr.log_type = MOSQ_LOG_NONE; cr.log_type = MOSQ_LOG_NONE;
@ -498,18 +556,24 @@ int mqtt3_config_read(struct mqtt3_config *config, bool reload)
cr.max_inflight_messages = 20; cr.max_inflight_messages = 20;
cr.max_queued_messages = 100; cr.max_queued_messages = 100;
if(!config->config_file) return 0; if(!db->config_file) return 0;
if(reload){ if(reload){
/* Re-initialise appropriate config vars to default for reload. */ /* Re-initialise appropriate config vars to default for reload. */
_config_init_reload(config); _config_init_reload(db, &config_reload);
rc = _config_read_file(&config_reload, reload, db->config_file, &cr, 0, &lineno);
}else{
rc = _config_read_file(config, reload, db->config_file, &cr, 0, &lineno);
} }
rc = _config_read_file(config, reload, config->config_file, &cr, 0, &lineno);
if(rc){ if(rc){
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error found at %s:%d.", config->config_file, lineno); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error found at %s:%d.", db->config_file, lineno);
return rc; return rc;
} }
if(reload){
config__copy(&config_reload, config);
}
#ifdef WITH_PERSISTENCE #ifdef WITH_PERSISTENCE
if(config->persistence){ if(config->persistence){
if(!config->persistence_file){ if(!config->persistence_file){
@ -561,7 +625,7 @@ int mqtt3_config_read(struct mqtt3_config *config, bool reload)
if(cr.log_dest_set){ if(cr.log_dest_set){
config->log_dest = cr.log_dest; config->log_dest = cr.log_dest;
} }
if(config->verbose){ if(db->verbose){
config->log_type = INT_MAX; config->log_type = INT_MAX;
}else if(cr.log_type_set){ }else if(cr.log_type_set){
config->log_type = cr.log_type; config->log_type = cr.log_type;

@ -390,7 +390,7 @@ int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int li
#endif #endif
if(flag_reload){ if(flag_reload){
_mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Reloading config."); _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Reloading config.");
mqtt3_config_read(db->config, true); mqtt3_config_read(db, db->config, true);
mosquitto_security_cleanup(db, true); mosquitto_security_cleanup(db, true);
mosquitto_security_init(db, true); mosquitto_security_init(db, true);
mosquitto_security_apply(db); mosquitto_security_apply(db);

@ -259,8 +259,8 @@ int main(int argc, char *argv[])
_mosquitto_net_init(); _mosquitto_net_init();
mqtt3_config_init(&config); mqtt3_config_init(&int_db, &config);
rc = mqtt3_config_parse_args(&config, argc, argv); rc = mqtt3_config_parse_args(&int_db, &config, argc, argv);
if(rc != MOSQ_ERR_SUCCESS) return rc; if(rc != MOSQ_ERR_SUCCESS) return rc;
int_db.config = &config; int_db.config = &config;
@ -292,8 +292,8 @@ int main(int argc, char *argv[])
return rc; return rc;
} }
_mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s (build date %s) starting", VERSION, TIMESTAMP); _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s (build date %s) starting", VERSION, TIMESTAMP);
if(config.config_file){ if(int_db.config_file){
_mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Config loaded from %s.", config.config_file); _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Config loaded from %s.", int_db.config_file);
}else{ }else{
_mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Using default config."); _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Using default config.");
} }

@ -101,7 +101,6 @@ struct _mqtt3_listener {
}; };
struct mqtt3_config { struct mqtt3_config {
char *config_file;
char *acl_file; char *acl_file;
bool allow_anonymous; bool allow_anonymous;
bool allow_duplicate_messages; bool allow_duplicate_messages;
@ -137,7 +136,6 @@ struct mqtt3_config {
int sys_interval; int sys_interval;
bool upgrade_outgoing_qos; bool upgrade_outgoing_qos;
char *user; char *user;
bool verbose;
#ifdef WITH_WEBSOCKETS #ifdef WITH_WEBSOCKETS
int websockets_log_level; int websockets_log_level;
bool have_websockets_listener; bool have_websockets_listener;
@ -260,9 +258,11 @@ struct mosquitto_db{
int bridge_count; int bridge_count;
#endif #endif
int msg_store_count; int msg_store_count;
char *config_file;
struct mqtt3_config *config; struct mqtt3_config *config;
int persistence_changes; int persistence_changes;
struct _mosquitto_auth_plugin auth_plugin; struct _mosquitto_auth_plugin auth_plugin;
bool verbose;
#ifdef WITH_SYS_TREE #ifdef WITH_SYS_TREE
int subscription_count; int subscription_count;
int retained_count; int retained_count;
@ -365,14 +365,14 @@ struct mosquitto_db *_mosquitto_get_db(void);
* Config functions * Config functions
* ============================================================ */ * ============================================================ */
/* Initialise config struct to default values. */ /* Initialise config struct to default values. */
void mqtt3_config_init(struct mqtt3_config *config); void mqtt3_config_init(struct mosquitto_db *db, struct mqtt3_config *config);
/* Parse command line options into config. */ /* Parse command line options into config. */
int mqtt3_config_parse_args(struct mqtt3_config *config, int argc, char *argv[]); int mqtt3_config_parse_args(struct mosquitto_db *db, struct mqtt3_config *config, int argc, char *argv[]);
/* Read configuration data from config->config_file into config. /* Read configuration data from config->config_file into config.
* If reload is true, don't process config options that shouldn't be reloaded (listeners etc) * If reload is true, don't process config options that shouldn't be reloaded (listeners etc)
* Returns 0 on success, 1 if there is a configuration error or if a file cannot be opened. * Returns 0 on success, 1 if there is a configuration error or if a file cannot be opened.
*/ */
int mqtt3_config_read(struct mqtt3_config *config, bool reload); int mqtt3_config_read(struct mosquitto_db *db, struct mqtt3_config *config, bool reload);
/* Free all config data. */ /* Free all config data. */
void mqtt3_config_cleanup(struct mqtt3_config *config); void mqtt3_config_cleanup(struct mqtt3_config *config);

Loading…
Cancel
Save