[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[mosquitto-dev] RFC: Extend allow_anonymous from localhost only
|
Hey there,
In order to have authenticated access to my MQTT box from outside,
I set allow_anonymous to 1. This does have the side effect that
my local programs also need a 'dummy' username+password to authenticate.
This dummy username+password is then usable from outside also.
I addressed this by adding the patch below. It allows MQTT to be
configured to allow anonymous connections from localhost, and
authenicated connections from outside.
Is this a feasible solution?
Did I get it wrong completely?
Any comments are welcome.
Kurt
--
commit a459fa58b02b95abf4f9da9705666cb5b34fec1b
Author: Kurt Van Dijck <dev.kurt@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue Jun 6 06:19:29 2017
Extend allow_anonymous from localhost only
This commit extends the allow_anonymous config option
with a 3rd possibility 'localhost'.
This allows anonymous connections from localhost, and requires
authenticated connections from elsewhere.
'localhost' is interpreted as '127.0.0.1' or '::1'.
Signed-off-by: Kurt Van Dijck <dev.kurt@xxxxxxxxxxxxxxxxxxxxxx>
diff --git a/src/conf.c b/src/conf.c
index 6edd705..ca21c58 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -60,6 +60,7 @@ extern SERVICE_STATUS_HANDLE service_handle;
#endif
static int _conf_parse_bool(char **token, const char *name, bool *value, char *saveptr);
+static int _conf_parse_bool_net(char **token, const char *name, int *value, char *saveptr);
static int _conf_parse_int(char **token, const char *name, int *value, char *saveptr);
static int _conf_parse_string(char **token, const char *name, char **value, char *saveptr);
static int _config_read_file(struct mqtt3_config *config, bool reload, const char *file, struct config_recurse *config_tmp, int level, int *lineno);
@@ -625,7 +626,7 @@ int _config_read_file_core(struct mqtt3_config *config, bool reload, const char
_mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available.");
#endif
}else if(!strcmp(token, "allow_anonymous")){
- if(_conf_parse_bool(&token, "allow_anonymous", &config->allow_anonymous, saveptr)) return MOSQ_ERR_INVAL;
+ if(_conf_parse_bool_net(&token, "allow_anonymous", &config->allow_anonymous, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "allow_duplicate_messages")){
if(_conf_parse_bool(&token, "allow_duplicate_messages", &config->allow_duplicate_messages, saveptr)) return MOSQ_ERR_INVAL;
}else if(!strcmp(token, "allow_zero_length_clientid")){
@@ -1949,6 +1950,27 @@ static int _conf_parse_bool(char **token, const char *name, bool *value, char *s
return MOSQ_ERR_SUCCESS;
}
+static int _conf_parse_bool_net(char **token, const char *name, int *value, char *saveptr)
+{
+ *token = strtok_r(NULL, " ", &saveptr);
+ if(*token){
+ if(!strcmp(*token, "false") || !strcmp(*token, "0")){
+ *value = 0;
+ }else if(!strcmp(*token, "true") || !strcmp(*token, "1")){
+ *value = 1;
+ }else if(!strcmp(*token, "localhost")){
+ *value = BOOL_HOST;
+ }else{
+ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid %s value (%s).", name, *token);
+ }
+ }else{
+ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty %s value in configuration.", name);
+ return MOSQ_ERR_INVAL;
+ }
+
+ return MOSQ_ERR_SUCCESS;
+}
+
static int _conf_parse_int(char **token, const char *name, int *value, char *saveptr)
{
*token = strtok_r(NULL, " ", &saveptr);
diff --git a/src/mosquitto_broker.h b/src/mosquitto_broker.h
index 8d19790..ad36c55 100644
--- a/src/mosquitto_broker.h
+++ b/src/mosquitto_broker.h
@@ -102,7 +102,7 @@ struct _mqtt3_listener {
struct mqtt3_config {
char *config_file;
char *acl_file;
- bool allow_anonymous;
+ int allow_anonymous;
bool allow_duplicate_messages;
bool allow_zero_length_clientid;
char *auto_id_prefix;
@@ -488,6 +488,9 @@ int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *conte
int mosquitto_unpwd_check_default(struct mosquitto_db *db, 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_allow_anonymous(struct mosquitto_db *db, const char *peername);
+#define BOOL_HOST 2
+
/* ============================================================
* Window service related functions
* ============================================================ */
diff --git a/src/read_handle_server.c b/src/read_handle_server.c
index 2b9c8f5..8ce7cb1 100644
--- a/src/read_handle_server.c
+++ b/src/read_handle_server.c
@@ -399,7 +399,7 @@ int mqtt3_handle_connect(struct mosquitto_db *db, struct mosquitto *context)
password = NULL;
}
- if(!username_flag && db->config->allow_anonymous == false){
+ if(!username_flag && !mosquitto_allow_anonymous(db, context->address)){
_mosquitto_send_connack(context, 0, CONNACK_REFUSED_NOT_AUTHORIZED);
rc = 1;
goto handle_connect_error;
diff --git a/src/security_default.c b/src/security_default.c
index a1d3ec1..31b09c3 100644
--- a/src/security_default.c
+++ b/src/security_default.c
@@ -696,6 +696,20 @@ static int _unpwd_cleanup(struct _mosquitto_unpwd **root, bool reload)
return MOSQ_ERR_SUCCESS;
}
+int mosquitto_allow_anonymous(struct mosquitto_db *db, const char *peername)
+{
+ switch (db->config->allow_anonymous) {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case BOOL_HOST:
+ return !strcmp(peername, "127.0.0.1") || !strcmp(peername, "::1");
+ default:
+ return 0;
+ }
+}
+
/* Apply security settings after a reload.
* Includes:
* - Disconnecting anonymous users if appropriate
@@ -706,15 +720,12 @@ int mosquitto_security_apply_default(struct mosquitto_db *db)
{
struct mosquitto *context, *ctxt_tmp;
struct _mosquitto_acl_user *acl_user_tail;
- bool allow_anonymous;
if(!db) return MOSQ_ERR_INVAL;
- allow_anonymous = db->config->allow_anonymous;
-
HASH_ITER(hh_id, db->contexts_by_id, context, ctxt_tmp){
/* Check for anonymous clients when allow_anonymous is false */
- if(!allow_anonymous && !context->username){
+ if(!context->username && !mosquitto_allow_anonymous(db, context->address)){
context->state = mosq_cs_disconnecting;
do_disconnect(db, context);
continue;