Skip to main content

[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;


Back to the top