From 57e852db05fcec28cb7114933e8ad7b393e388d2 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Tue, 13 Mar 2018 17:44:33 +0000 Subject: [PATCH] Per listener password file. --- src/conf.c | 25 +++++++++++++----- src/mosquitto_broker_internal.h | 29 +++++++++++++------- src/security.c | 2 +- src/security_default.c | 47 ++++++++++++++++++++++++--------- 4 files changed, 73 insertions(+), 30 deletions(-) diff --git a/src/conf.c b/src/conf.c index 53ea4046..a5adf80d 100644 --- a/src/conf.c +++ b/src/conf.c @@ -96,6 +96,13 @@ static char *fgets_extending(char **buf, int *buflen, FILE *stream) } +static void conf__set_cur_security_options(struct mosquitto__config *config, struct mosquitto__security_options **security_options) +{ + if(!(*security_options)){ + (*security_options) = &config->security_options; + } +} + static int conf__attempt_resolve(const char *host, const char *text, int log, const char *msg) { struct addrinfo gai_hints; @@ -178,8 +185,8 @@ static void config__init_reload(struct mosquitto__config *config) } #endif config->log_timestamp = true; - mosquitto__free(config->password_file); - config->password_file = NULL; + mosquitto__free(config->security_options.password_file); + config->security_options.password_file = NULL; config->persistence = false; mosquitto__free(config->persistence_location); config->persistence_location = NULL; @@ -264,7 +271,7 @@ void config__cleanup(struct mosquitto__config *config) mosquitto__free(config->auto_id_prefix); mosquitto__free(config->clientid_prefixes); mosquitto__free(config->config_file); - mosquitto__free(config->password_file); + mosquitto__free(config->security_options.password_file); mosquitto__free(config->persistence_location); mosquitto__free(config->persistence_file); mosquitto__free(config->persistence_filepath); @@ -627,6 +634,7 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, const int i; #endif int lineno_ext; + struct mosquitto__security_options *cur_security_options = NULL; *lineno = 0; @@ -1442,13 +1450,18 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, const log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "password_file")){ + conf__set_cur_security_options(config, &cur_security_options); if(reload){ - mosquitto__free(config->password_file); - config->password_file = NULL; + mosquitto__free(cur_security_options->password_file); + cur_security_options->password_file = NULL; } - if(conf__parse_string(&token, "password_file", &config->password_file, saveptr)) return MOSQ_ERR_INVAL; + if(conf__parse_string(&token, "password_file", &cur_security_options->password_file, saveptr)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "per_listener_settings")){ if(conf__parse_bool(&token, "per_listener_settings", &config->per_listener_settings, saveptr)) return MOSQ_ERR_INVAL; + if(cur_security_options && config->per_listener_settings){ + log__printf(NULL, MOSQ_LOG_ERR, "Error: per_listener_settings must be set before any other security settings."); + return MOSQ_ERR_INVAL; + } }else if(!strcmp(token, "persistence") || !strcmp(token, "retained_persistence")){ if(conf__parse_bool(&token, token, &config->persistence, saveptr)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "persistence_file")){ diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h index 19e0c340..baca78c1 100644 --- a/src/mosquitto_broker_internal.h +++ b/src/mosquitto_broker_internal.h @@ -138,6 +138,21 @@ typedef union { typedef uint64_t dbid_t; +struct mosquitto__auth_plugin_config +{ + char *path; + struct mosquitto_opt *options; + int option_count; + bool deny_special_chars; +}; + +struct mosquitto__security_options { + char *password_file; + char *psk_file; + struct mosquitto__auth_plugin_config *auth_plugins; + int auth_plugin_count; +}; + struct mosquitto__listener { int fd; uint16_t port; @@ -168,14 +183,8 @@ struct mosquitto__listener { char *http_dir; struct libwebsocket_protocols *ws_protocol; #endif -}; - -struct mosquitto__auth_plugin_config -{ - char *path; - struct mosquitto_opt *options; - int option_count; - bool deny_special_chars; + struct mosquitto__security_options security_options; + struct mosquitto__unpwd *unpwd; }; struct mosquitto__config { @@ -201,7 +210,6 @@ struct mosquitto__config { char *log_file; FILE *log_fptr; uint32_t message_size_limit; - char *password_file; bool persistence; char *persistence_location; char *persistence_file; @@ -226,6 +234,7 @@ struct mosquitto__config { #endif struct mosquitto__auth_plugin_config *auth_plugins; int auth_plugin_count; + struct mosquitto__security_options security_options; }; struct mosquitto__subleaf { @@ -601,7 +610,7 @@ int mosquitto_security_init_default(struct mosquitto_db *db, bool reload); int mosquitto_security_apply_default(struct mosquitto_db *db); int mosquitto_security_cleanup_default(struct mosquitto_db *db, bool reload); int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *context, const char *topic, int access); -int mosquitto_unpwd_check_default(struct mosquitto_db *db, const char *username, const char *password); +int mosquitto_unpwd_check_default(struct mosquitto_db *db, struct mosquitto *context, const char *username, const char *password); int mosquitto_psk_key_get_default(struct mosquitto_db *db, const char *hint, const char *identity, char *key, int max_key_len); /* ============================================================ diff --git a/src/security.c b/src/security.c index 1f4ab01d..0988e622 100644 --- a/src/security.c +++ b/src/security.c @@ -416,7 +416,7 @@ int mosquitto_unpwd_check(struct mosquitto_db *db, struct mosquitto *context, co int rc; int i; - rc = mosquitto_unpwd_check_default(db, username, password); + rc = mosquitto_unpwd_check_default(db, context, username, password); if(rc != MOSQ_ERR_PLUGIN_DEFER){ return rc; } diff --git a/src/security_default.c b/src/security_default.c index 7f6b1ffc..0b00ee53 100644 --- a/src/security_default.c +++ b/src/security_default.c @@ -24,7 +24,7 @@ Contributors: #include "util_mosq.h" static int aclfile__parse(struct mosquitto_db *db); -static int unpwd__file_parse(struct mosquitto_db *db); +static int unpwd__file_parse(struct mosquitto__unpwd **unpwd, const char *password_file); static int acl__cleanup(struct mosquitto_db *db, bool reload); static int unpwd__cleanup(struct mosquitto__unpwd **unpwd, bool reload); static int psk__file_parse(struct mosquitto_db *db); @@ -41,11 +41,27 @@ int mosquitto_security_init_default(struct mosquitto_db *db, bool reload) int rc; /* Load username/password data if required. */ - if(db->config->password_file){ - rc = unpwd__file_parse(db); - if(rc){ - log__printf(NULL, MOSQ_LOG_ERR, "Error opening password file \"%s\".", db->config->password_file); - return rc; + if(db->config->per_listener_settings){ + for(int i=0; iconfig->listener_count; i++){ + char *pwf = db->config->listeners[i].security_options.password_file; + if(pwf){ + rc = unpwd__file_parse(&db->config->listeners[i].unpwd, pwf); + if(rc){ + log__printf(NULL, MOSQ_LOG_ERR, "Error opening password file \"%s\".", pwf); + return rc; + } + } + } + }else{ + if(db->config->security_options.password_file){ + char *pwf = db->config->security_options.password_file; + if(pwf){ + rc = unpwd__file_parse(&db->unpwd, pwf); + if(rc){ + log__printf(NULL, MOSQ_LOG_ERR, "Error opening password file \"%s\".", pwf); + return rc; + } + } } } @@ -563,7 +579,7 @@ static int pwfile__parse(const char *file, struct mosquitto__unpwd **root) return MOSQ_ERR_SUCCESS; } -static int unpwd__file_parse(struct mosquitto_db *db) +static int unpwd__file_parse(struct mosquitto__unpwd **unpwd, const char *password_file) { int rc; #ifdef WITH_TLS @@ -575,15 +591,15 @@ static int unpwd__file_parse(struct mosquitto_db *db) unsigned int password_len; #endif - if(!db || !db->config) return MOSQ_ERR_INVAL; + if(!unpwd) return MOSQ_ERR_INVAL; - if(!db->config->password_file) return MOSQ_ERR_SUCCESS; + if(!password_file) return MOSQ_ERR_SUCCESS; - rc = pwfile__parse(db->config->password_file, &db->unpwd); + rc = pwfile__parse(password_file, unpwd); #ifdef WITH_TLS if(rc) return rc; - HASH_ITER(hh, db->unpwd, u, tmp){ + HASH_ITER(hh, *unpwd, u, tmp){ /* Need to decode password into hashed data + salt. */ if(u->password){ token = strtok(u->password, "$"); @@ -669,7 +685,7 @@ static int mosquitto__memcmp_const(const void *a, const void *b, size_t len) } -int mosquitto_unpwd_check_default(struct mosquitto_db *db, const char *username, const char *password) +int mosquitto_unpwd_check_default(struct mosquitto_db *db, struct mosquitto *context, const char *username, const char *password) { struct mosquitto__unpwd *u, *tmp; #ifdef WITH_TLS @@ -679,7 +695,12 @@ int mosquitto_unpwd_check_default(struct mosquitto_db *db, const char *username, #endif if(!db) return MOSQ_ERR_INVAL; - if(!db->unpwd) return MOSQ_ERR_PLUGIN_DEFER; + if(db->config->per_listener_settings){ + if(!context->listener) return MOSQ_ERR_INVAL; + if(!context->listener->unpwd) return MOSQ_ERR_PLUGIN_DEFER; + }else{ + if(!db->unpwd) return MOSQ_ERR_PLUGIN_DEFER; + } if(!username) return MOSQ_ERR_INVAL; /* Check must be made only after checking db->unpwd. */ HASH_ITER(hh, db->unpwd, u, tmp){