From fd7b08c0eb066e929cc8b311ac25312350ae623b Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 15 Mar 2018 21:39:42 +0000 Subject: [PATCH] Per listener psk_file. --- src/conf.c | 13 ++++--- src/mosquitto_broker_internal.h | 4 +- src/security.c | 2 +- src/security_default.c | 66 +++++++++++++++++++++++++-------- 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/src/conf.c b/src/conf.c index f1e77462..606af6c4 100644 --- a/src/conf.c +++ b/src/conf.c @@ -195,8 +195,8 @@ static void config__init_reload(struct mosquitto__config *config) mosquitto__free(config->persistence_file); config->persistence_file = NULL; config->persistent_client_expiration = 0; - mosquitto__free(config->psk_file); - config->psk_file = NULL; + mosquitto__free(config->security_options.psk_file); + config->security_options.psk_file = NULL; config->queue_qos0_messages = false; config->set_tcp_nodelay = false; config->sys_interval = 10; @@ -277,7 +277,7 @@ void config__cleanup(struct mosquitto__config *config) mosquitto__free(config->persistence_location); mosquitto__free(config->persistence_file); mosquitto__free(config->persistence_filepath); - mosquitto__free(config->psk_file); + mosquitto__free(config->security_options.psk_file); mosquitto__free(config->pid_file); if(config->listeners){ for(i=0; ilistener_count; i++){ @@ -1576,11 +1576,12 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, const } }else if(!strcmp(token, "psk_file")){ #ifdef REAL_WITH_TLS_PSK + conf__set_cur_security_options(config, cur_listener, &cur_security_options); if(reload){ - mosquitto__free(config->psk_file); - config->psk_file = NULL; + mosquitto__free(cur_security_options->psk_file); + cur_security_options->psk_file = NULL; } - if(conf__parse_string(&token, "psk_file", &config->psk_file, saveptr)) return MOSQ_ERR_INVAL; + if(conf__parse_string(&token, "psk_file", &cur_security_options->psk_file, saveptr)) return MOSQ_ERR_INVAL; #else log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TLS/TLS-PSK support not available."); #endif diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h index 28768625..5071e0c2 100644 --- a/src/mosquitto_broker_internal.h +++ b/src/mosquitto_broker_internal.h @@ -190,6 +190,7 @@ struct mosquitto__listener { #endif struct mosquitto__security_options security_options; struct mosquitto__unpwd *unpwd; + struct mosquitto__unpwd *psk_id; }; struct mosquitto__config { @@ -220,7 +221,6 @@ struct mosquitto__config { char *persistence_filepath; time_t persistent_client_expiration; char *pid_file; - char *psk_file; bool queue_qos0_messages; bool per_listener_settings; bool set_tcp_nodelay; @@ -615,7 +615,7 @@ 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, 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); +int mosquitto_psk_key_get_default(struct mosquitto_db *db, struct mosquitto *context, const char *hint, const char *identity, char *key, int max_key_len); /* ============================================================ * Window service and signal related functions diff --git a/src/security.c b/src/security.c index 0988e622..931608fc 100644 --- a/src/security.c +++ b/src/security.c @@ -449,7 +449,7 @@ int mosquitto_psk_key_get(struct mosquitto_db *db, struct mosquitto *context, co int rc; int i; - rc = mosquitto_psk_key_get_default(db, hint, identity, key, max_key_len); + rc = mosquitto_psk_key_get_default(db, context, hint, identity, key, max_key_len); if(rc != MOSQ_ERR_PLUGIN_DEFER){ return rc; } diff --git a/src/security_default.c b/src/security_default.c index fcdb9d91..e7474705 100644 --- a/src/security_default.c +++ b/src/security_default.c @@ -27,7 +27,7 @@ static int aclfile__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); +static int psk__file_parse(struct mosquitto_db *db, struct mosquitto__unpwd **psk_id, const char *psk_file); #ifdef WITH_TLS static int pw__digest(const char *password, const unsigned char *salt, unsigned int salt_len, unsigned char *hash, unsigned int *hash_len); static int base64__decode(char *in, unsigned char **decoded, unsigned int *decoded_len); @@ -75,11 +75,25 @@ int mosquitto_security_init_default(struct mosquitto_db *db, bool reload) } /* Load psk data if required. */ - if(db->config->psk_file){ - rc = psk__file_parse(db); - if(rc){ - log__printf(NULL, MOSQ_LOG_ERR, "Error opening psk file \"%s\".", db->config->psk_file); - return rc; + if(db->config->per_listener_settings){ + for(int i=0; iconfig->listener_count; i++){ + char *pskf = db->config->listeners[i].security_options.psk_file; + if(pskf){ + rc = psk__file_parse(db, &db->config->listeners[i].psk_id, pskf); + if(rc){ + log__printf(NULL, MOSQ_LOG_ERR, "Error opening psk file \"%s\".", pskf); + return rc; + } + } + } + }else{ + char *pskf = db->config->security_options.psk_file; + if(pskf){ + rc = psk__file_parse(db, &db->psk_id, pskf); + if(rc){ + log__printf(NULL, MOSQ_LOG_ERR, "Error opening psk file \"%s\".", pskf); + return rc; + } } } @@ -98,10 +112,21 @@ int mosquitto_security_cleanup_default(struct mosquitto_db *db, bool reload) for(int i=0; iconfig->listener_count; i++){ if(db->config->listeners[i].unpwd){ rc = unpwd__cleanup(&db->config->listeners[i].unpwd, reload); + if(rc != MOSQ_ERR_SUCCESS) return rc; } } - return unpwd__cleanup(&db->psk_id, reload); + rc = unpwd__cleanup(&db->psk_id, reload); + if(rc != MOSQ_ERR_SUCCESS) return rc; + + for(int i=0; iconfig->listener_count; i++){ + if(db->config->listeners[i].psk_id){ + rc = unpwd__cleanup(&db->config->listeners[i].psk_id, reload); + if(rc != MOSQ_ERR_SUCCESS) return rc; + } + } + + return MOSQ_ERR_SUCCESS; } @@ -649,20 +674,20 @@ static int unpwd__file_parse(struct mosquitto__unpwd **unpwd, const char *passwo return rc; } -static int psk__file_parse(struct mosquitto_db *db) +static int psk__file_parse(struct mosquitto_db *db, struct mosquitto__unpwd **psk_id, const char *psk_file) { int rc; struct mosquitto__unpwd *u, *tmp; - if(!db || !db->config) return MOSQ_ERR_INVAL; + if(!db || !db->config || !psk_id) return MOSQ_ERR_INVAL; /* We haven't been asked to parse a psk file. */ - if(!db->config->psk_file) return MOSQ_ERR_SUCCESS; + if(!psk_file) return MOSQ_ERR_SUCCESS; - rc = pwfile__parse(db->config->psk_file, &db->psk_id); + rc = pwfile__parse(psk_file, psk_id); if(rc) return rc; - HASH_ITER(hh, db->psk_id, u, tmp){ + HASH_ITER(hh, (*psk_id), u, tmp){ /* Check for hex only digits */ if(!u->password){ log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty psk for identity \"%s\".", u->username); @@ -704,6 +729,7 @@ int mosquitto_unpwd_check_default(struct mosquitto_db *db, struct mosquitto *con #endif if(!db) return MOSQ_ERR_INVAL; + if(db->config->per_listener_settings){ if(!context->listener) return MOSQ_ERR_INVAL; if(!context->listener->unpwd) return MOSQ_ERR_PLUGIN_DEFER; @@ -825,14 +851,24 @@ int mosquitto_security_apply_default(struct mosquitto_db *db) return MOSQ_ERR_SUCCESS; } -int mosquitto_psk_key_get_default(struct mosquitto_db *db, const char *hint, const char *identity, char *key, int max_key_len) +int mosquitto_psk_key_get_default(struct mosquitto_db *db, struct mosquitto *context, const char *hint, const char *identity, char *key, int max_key_len) { struct mosquitto__unpwd *u, *tmp; + struct mosquitto__unpwd *psk_id_ref = NULL; if(!db || !hint || !identity || !key) return MOSQ_ERR_INVAL; - if(!db->psk_id) return MOSQ_ERR_PLUGIN_DEFER; - HASH_ITER(hh, db->psk_id, u, tmp){ + if(db->config->per_listener_settings){ + if(!context->listener) return MOSQ_ERR_INVAL; + if(!context->listener->psk_id) return MOSQ_ERR_PLUGIN_DEFER; + psk_id_ref = context->listener->psk_id; + }else{ + if(!db->psk_id) return MOSQ_ERR_PLUGIN_DEFER; + psk_id_ref = db->psk_id; + } + if(!psk_id_ref) return MOSQ_ERR_PLUGIN_DEFER; + + HASH_ITER(hh, psk_id_ref, u, tmp){ if(!strcmp(u->username, identity)){ strncpy(key, u->password, max_key_len); return MOSQ_ERR_SUCCESS;