From f406273544eded85363930b37c51441d43782796 Mon Sep 17 00:00:00 2001 From: rlshumat Date: Mon, 10 Oct 2016 20:35:37 -0400 Subject: [PATCH 1/8] Fixed Memory Leak If the Mongoc returned a cursor error, the cursor was never destroyed causing a memory leak. Also, if only one document was returned with a correct topic match, the cursor would report an error and return 0 although the ACL call succeeded. --- be-mongo.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/be-mongo.c b/be-mongo.c index 22a9a39b..9573c84a 100644 --- a/be-mongo.c +++ b/be-mongo.c @@ -263,23 +263,15 @@ int be_mongo_aclcheck(void *conf, const char *clientid, const char *username, co } } - - - if (mongoc_cursor_error (cursor, &error)) { + + if ( (mongoc_cursor_error (cursor, &error)) && (match != 1) ) { fprintf (stderr, "Cursor Failure: %s\n", error.message); - return 0; } - - + bson_destroy(&query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy(collection); - - - - - - return match; + } #endif /* BE_MONGO */ From c4eebf3dcae5416bdbace30ae391fa8637d5574c Mon Sep 17 00:00:00 2001 From: rlshumat Date: Mon, 10 Oct 2016 21:57:30 -0400 Subject: [PATCH 2/8] Moving mongoParam's configurable from mosquitto.conf Mirgrating mongoParams to mosquitto configuration file. Fixing cursor memory leaks. --- be-mongo.c | 113 +++++++++++++++++++++++++++++---------------------- mongoParam.h | 16 -------- 2 files changed, 65 insertions(+), 64 deletions(-) delete mode 100644 mongoParam.h diff --git a/be-mongo.c b/be-mongo.c index 9573c84a..051b271c 100644 --- a/be-mongo.c +++ b/be-mongo.c @@ -14,61 +14,83 @@ #include #include "hash.h" #include "log.h" -#include "mongoParam.h" struct mongo_backend { mongoc_client_t *client; - char *host; - int port; +// char *host; +// int port; + char *database; + char *users_coll; + char *topics_coll; + char *password_loc; + char *topic_loc; + char *topicId_loc; + char *superuser_loc; }; void *be_mongo_init() { struct mongo_backend *conf; char *host, *p, *user, *password, *authSource; + + conf = (struct mongo_backend *)malloc(sizeof(struct mongo_backend)); if ((host = p_stab("mongo_host")) == NULL) host = "localhost"; if ((p = p_stab("mongo_port")) == NULL) p = "27017"; + if ((p = p_stab("mongo_database")) == NULL) + conf->database = "mqGate"; + if ((p = p_stab("mongo_collection_users")) == NULL) + conf->users_coll = "users"; + if ((p = p_stab("mongo_collection_topics")) == NULL) + conf->topics_coll = "topics"; + if ((p = p_stab("mongo_location_password")) == NULL) + conf->password_loc = "password"; + if ((p = p_stab("mongo_location_topic")) == NULL) + conf->topic_loc = "topics"; + if ((p = p_stab("mongo_location_topicId")) == NULL) + conf->topicId_loc = "_id"; + if ((p = p_stab("mongo_location_topic")) == NULL) + conf->superuser_loc = "superuser"; + user = p_stab("mongo_user"); password = p_stab("mongo_password"); authSource = p_stab("mongo_authSource"); - char uristr[128] = {0}; - strcpy(uristr, "mongodb://"); - if (user != NULL) { - strcat(uristr, user); - if (password != NULL) { - strcat(uristr, ":"); - strcat(uristr, password); - } - strcat(uristr, "@"); - } - strcat(uristr, host); - strcat(uristr, ":"); - strcat(uristr, p); - if (authSource != NULL) { - strcat(uristr, "?authSource="); - strcat(uristr, authSource); - } - printf("mongo: [%s]\n", uristr); - - conf = (struct mongo_backend *)malloc(sizeof(struct mongo_backend)); - mongoc_init (); - - conf->client = mongoc_client_new (uristr); - - if (!conf->client) { - fprintf (stderr, "Failed to parse URI.\n"); - return NULL; - } - return (conf); + char uristr[128] = {0}; + strcpy(uristr, "mongodb://"); + if (user != NULL) { + strcat(uristr, user); + if (password != NULL) { + strcat(uristr, ":"); + strcat(uristr, password); + } + strcat(uristr, "@"); + } + strcat(uristr, host); + strcat(uristr, ":"); + strcat(uristr, p); + if (authSource != NULL) { + strcat(uristr, "?authSource="); + strcat(uristr, authSource); + } + + mongoc_init (); + conf->client = mongoc_client_new (uristr); + + if (!conf->client) { + fprintf (stderr, "Failed to parse URI.\n"); + return NULL; + } + + return (conf); } char *be_mongo_getuser(void *handle, const char *username, const char *password, int *authenticated) { - struct mongo_backend *conf = (struct mongo_backend *)handle; + + struct mongo_backend *conf = (struct mongo_backend *)handle; mongoc_collection_t *collection; mongoc_cursor_t *cursor; bson_error_t error; @@ -81,7 +103,7 @@ char *be_mongo_getuser(void *handle, const char *username, const char *password, bson_append_utf8 (&query, "username", -1, username, -1); - collection = mongoc_client_get_collection (conf->client, dbName, colName); + collection = mongoc_client_get_collection (conf->client, conf->database, conf->users_coll); cursor = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, @@ -97,7 +119,7 @@ char *be_mongo_getuser(void *handle, const char *username, const char *password, if (mongoc_cursor_next (cursor, &doc)) { bson_iter_init(&iter, doc); - bson_iter_find(&iter, passLoc); + bson_iter_find(&iter, conf->password_loc); char *src = (char *)bson_iter_utf8(&iter, NULL); size_t tmp = strlen(src); @@ -109,8 +131,8 @@ char *be_mongo_getuser(void *handle, const char *username, const char *password, if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\n", error.message); - return result; } + bson_destroy (&query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); @@ -142,7 +164,7 @@ int be_mongo_superuser(void *conf, const char *username) bson_init (&query); bson_append_utf8(&query, "username", -1, username, -1); - collection = mongoc_client_get_collection(handle->client, dbName, colName); + collection = mongoc_client_get_collection(handle->client, handle->database, handle->users_coll); cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, @@ -157,26 +179,21 @@ int be_mongo_superuser(void *conf, const char *username) mongoc_cursor_more (cursor)) { if (mongoc_cursor_next (cursor, &doc)) { bson_iter_init(&iter, doc); - bson_iter_find(&iter, superUser); + bson_iter_find(&iter, handle->superuser_loc); result = (int64_t) bson_iter_as_int64(&iter); - //_log(LOG_NOTICE, "SUPERUSER: %d", result); - } } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\n", error.message); - return result; } bson_destroy (&query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); - - return result; } @@ -197,7 +214,7 @@ int be_mongo_aclcheck(void *conf, const char *clientid, const char *username, co bson_init(&query); bson_append_utf8(&query, "username", -1, username, -1); - collection = mongoc_client_get_collection(handle->client, dbName, colName); + collection = mongoc_client_get_collection(handle->client, handle->database, handle->users_coll); cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, @@ -212,7 +229,7 @@ int be_mongo_aclcheck(void *conf, const char *clientid, const char *username, co mongoc_cursor_more (cursor)) { if (foundFlag == 0 && mongoc_cursor_next (cursor, &doc)) { bson_iter_init(&iter, doc); - bson_iter_find(&iter, topicLoc); + bson_iter_find(&iter, handle->topic_loc); int64_t topId = (int64_t) bson_iter_as_int64(&iter);//, NULL); @@ -221,8 +238,8 @@ int be_mongo_aclcheck(void *conf, const char *clientid, const char *username, co mongoc_collection_destroy(collection); bson_init(&query); - bson_append_int64(&query, topicID, -1, topId); - collection = mongoc_client_get_collection(handle->client, dbName, topicLoc); + bson_append_int64(&query, handle->topicId_loc, -1, topId); + collection = mongoc_client_get_collection(handle->client, handle->database, handle->topics_coll); cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, @@ -236,7 +253,7 @@ int be_mongo_aclcheck(void *conf, const char *clientid, const char *username, co if (foundFlag == 1 && mongoc_cursor_next(cursor, &doc)) { bson_iter_init(&iter, doc); - bson_iter_find(&iter, topicLoc); + bson_iter_find(&iter, handle->topic_loc); uint32_t len; const uint8_t *arr; bson_iter_array(&iter, &len, &arr); diff --git a/mongoParam.h b/mongoParam.h deleted file mode 100644 index 75917fc4..00000000 --- a/mongoParam.h +++ /dev/null @@ -1,16 +0,0 @@ -/* -*Mongo database parameters -* -*dbName - Mongo database name -*colName (topics - topicID(int)) - Mongo collection of users (username, password, superuser, topics) -*topicLoc - Mongo collection of topics (_id, topics) -*topicID - mongo fieldname for topicSet ID -*superUser - mongo fieldname for superuser flag (true/false) -*/ - -#define dbName "mqGate" -#define colName "users" -#define passLoc "password" -#define topicLoc "topics" -#define topicID "_id" -#define superUser "superuser" From 3d3e51ecc1fde763455fae733899671752495d6d Mon Sep 17 00:00:00 2001 From: Ryan Shumate Date: Tue, 11 Oct 2016 10:13:04 -0400 Subject: [PATCH 3/8] Adding libmongoc and libbson include paths to makefile Fixes #162 --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index ba2f8f5e..97f4cbed 100644 --- a/Makefile +++ b/Makefile @@ -91,6 +91,8 @@ ifneq ($(BACKEND_MONGO), no) BACKENDSTR += MongoDB BE_CFLAGS += -I/usr/local/include/ + BE_CFLAGS += -I/usr/local/include/libmongoc-1.0/ + BE_CFLAGS += -I/usr/local/include/libbson-1.0/ BE_LDFLAGS += -L/usr/local/lib BE_LDADD += -lmongoc-1.0 -lbson-1.0 OBJS += be-mongo.o From 3a348cddb6b6c2f4cfe04daeb3e5f8f767f4ae13 Mon Sep 17 00:00:00 2001 From: Ryan Shumate Date: Tue, 11 Oct 2016 14:45:36 +0000 Subject: [PATCH 4/8] Fixing Segfault caused by incomplete code --- be-mongo.c | 96 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 32 deletions(-) diff --git a/be-mongo.c b/be-mongo.c index 051b271c..ce2c270c 100644 --- a/be-mongo.c +++ b/be-mongo.c @@ -15,66 +15,98 @@ #include "hash.h" #include "log.h" + +const char* default_db = "mqGate"; + struct mongo_backend { mongoc_client_t *client; -// char *host; -// int port; - char *database; - char *users_coll; - char *topics_coll; - char *password_loc; - char *topic_loc; - char *topicId_loc; - char *superuser_loc; + char *host; + int port; + char *database; + char *users_coll; + char *topics_coll; + char *password_loc; + char *topic_loc; + char *topicId_loc; + char *superuser_loc; }; void *be_mongo_init() { struct mongo_backend *conf; char *host, *p, *user, *password, *authSource; - - conf = (struct mongo_backend *)malloc(sizeof(struct mongo_backend)); + char *database, *users_coll, *topics_coll, *password_loc, *topic_loc; + char *topicId_loc, *superuser_loc; + + conf = (struct mongo_backend *)malloc(sizeof(struct mongo_backend)); if ((host = p_stab("mongo_host")) == NULL) host = "localhost"; if ((p = p_stab("mongo_port")) == NULL) p = "27017"; - if ((p = p_stab("mongo_database")) == NULL) + if ((database = p_stab("mongo_database")) == NULL){ conf->database = "mqGate"; - if ((p = p_stab("mongo_collection_users")) == NULL) + } + else{ + conf->database = database; + } + if ((users_coll = p_stab("mongo_collection_users")) == NULL){ conf->users_coll = "users"; - if ((p = p_stab("mongo_collection_topics")) == NULL) + } + else{ + conf->users_coll = users_coll; + } + if ((topics_coll = p_stab("mongo_collection_topics")) == NULL){ conf->topics_coll = "topics"; - if ((p = p_stab("mongo_location_password")) == NULL) + } + else{ + conf->topics_coll = topics_coll; + } + if ((password_loc = p_stab("mongo_location_password")) == NULL){ conf->password_loc = "password"; - if ((p = p_stab("mongo_location_topic")) == NULL) + } + else{ + conf->password_loc = password_loc; + } + if ((topic_loc = p_stab("mongo_location_topic")) == NULL){ conf->topic_loc = "topics"; - if ((p = p_stab("mongo_location_topicId")) == NULL) + } + else{ + conf->topic_loc = topic_loc; + } + if ((topicId_loc = p_stab("mongo_location_topicId")) == NULL){ conf->topicId_loc = "_id"; - if ((p = p_stab("mongo_location_topic")) == NULL) + } + else{ + conf->topicId_loc = topicId_loc; + } + if ((superuser_loc = p_stab("mongo_location_topic")) == NULL){ conf->superuser_loc = "superuser"; - + } + else{ + conf->superuser_loc = superuser_loc; + } user = p_stab("mongo_user"); password = p_stab("mongo_password"); authSource = p_stab("mongo_authSource"); - char uristr[128] = {0}; - strcpy(uristr, "mongodb://"); - if (user != NULL) { - strcat(uristr, user); - if (password != NULL) { + char uristr[128] = {0}; + strcpy(uristr, "mongodb://"); + if (user != NULL) { + strcat(uristr, user); + if (password != NULL) { strcat(uristr, ":"); strcat(uristr, password); } strcat(uristr, "@"); - } - strcat(uristr, host); - strcat(uristr, ":"); - strcat(uristr, p); - if (authSource != NULL) { - strcat(uristr, "?authSource="); - strcat(uristr, authSource); - } + } + strcat(uristr, host); + strcat(uristr, ":"); + strcat(uristr, p); + if (authSource != NULL) { + strcat(uristr, "?authSource="); + strcat(uristr, authSource); + } mongoc_init (); conf->client = mongoc_client_new (uristr); From 96def50d7f5b2455979d8d430296c617dbeeed7f Mon Sep 17 00:00:00 2001 From: Ryan Shumate Date: Tue, 11 Oct 2016 11:01:03 -0400 Subject: [PATCH 5/8] Formatting Cleanup & Free Config Settings on destroy Freeing the mongo_backend configuration --- be-mongo.c | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/be-mongo.c b/be-mongo.c index ce2c270c..f26aaf13 100644 --- a/be-mongo.c +++ b/be-mongo.c @@ -16,8 +16,6 @@ #include "log.h" -const char* default_db = "mqGate"; - struct mongo_backend { mongoc_client_t *client; char *host; @@ -40,52 +38,56 @@ void *be_mongo_init() conf = (struct mongo_backend *)malloc(sizeof(struct mongo_backend)); - if ((host = p_stab("mongo_host")) == NULL) + if ((host = p_stab("mongo_host")) == NULL){ host = "localhost"; - if ((p = p_stab("mongo_port")) == NULL) + } + + if ((p = p_stab("mongo_port")) == NULL){ p = "27017"; + } + if ((database = p_stab("mongo_database")) == NULL){ conf->database = "mqGate"; - } - else{ + }else{ conf->database = database; } + if ((users_coll = p_stab("mongo_collection_users")) == NULL){ conf->users_coll = "users"; - } - else{ + }else{ conf->users_coll = users_coll; } + if ((topics_coll = p_stab("mongo_collection_topics")) == NULL){ conf->topics_coll = "topics"; - } - else{ + }else{ conf->topics_coll = topics_coll; } + if ((password_loc = p_stab("mongo_location_password")) == NULL){ conf->password_loc = "password"; - } - else{ + }else{ conf->password_loc = password_loc; } + if ((topic_loc = p_stab("mongo_location_topic")) == NULL){ conf->topic_loc = "topics"; - } - else{ + }else{ conf->topic_loc = topic_loc; } + if ((topicId_loc = p_stab("mongo_location_topicId")) == NULL){ conf->topicId_loc = "_id"; - } - else{ + }else{ conf->topicId_loc = topicId_loc; } + if ((superuser_loc = p_stab("mongo_location_topic")) == NULL){ conf->superuser_loc = "superuser"; - } - else{ + }else{ conf->superuser_loc = superuser_loc; - } + } + user = p_stab("mongo_user"); password = p_stab("mongo_password"); authSource = p_stab("mongo_authSource"); @@ -177,6 +179,15 @@ void be_mongo_destroy(void *handle) struct mongo_backend *conf = (struct mongo_backend *)handle; if (conf != NULL) { + /* Free Settings */ + free(conf->database); + free(conf->users_coll); + free(conf->topics_coll); + free(conf->password_loc); + free(conf->topic_loc); + free(conf->topicId_loc); + free(conf->superuser_loc); + mongoc_client_destroy(conf->client); conf->client = NULL; } From e63c7495f99cd55c24e0f85af45e29ed0cdd0ef8 Mon Sep 17 00:00:00 2001 From: Ryan Shumate Date: Tue, 11 Oct 2016 15:16:02 +0000 Subject: [PATCH 6/8] Fixing superuser location --- be-mongo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/be-mongo.c b/be-mongo.c index f26aaf13..a1e38297 100644 --- a/be-mongo.c +++ b/be-mongo.c @@ -82,7 +82,7 @@ void *be_mongo_init() conf->topicId_loc = topicId_loc; } - if ((superuser_loc = p_stab("mongo_location_topic")) == NULL){ + if ((superuser_loc = p_stab("mongo_location_superuser")) == NULL){ conf->superuser_loc = "superuser"; }else{ conf->superuser_loc = superuser_loc; From 226d38f0d1279de8789aa5cfc2b35338ab51f39a Mon Sep 17 00:00:00 2001 From: Ryan Shumate Date: Tue, 11 Oct 2016 12:34:27 -0400 Subject: [PATCH 7/8] Updated Mongo Documentation --- README.md | 53 +++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index e484aa96..24410f37 100644 --- a/README.md +++ b/README.md @@ -518,30 +518,35 @@ the beginning of the line indicating a _superuser_) The `mongo` back-end works with superuser and ACL checks with the following collections format. ``` -users = {username: "user", - password: "PBKDF_string" - topics: int (topicID location) - superuser: int (1 true, 0 false) -} -topics = {_id: int, - topics: ["xx/xx/#", "yy/#", ...] -} -``` -Collection name parameters can be set in mongoParam.h -``` -mongoParam.h - -/* -*Mongo database parameters -* -*dbName - Mongo database name -*colName (topics - topicID(int)) - Mongo collection of users (username, password, superuser, topics) -*topicLoc - Mongo collection of topics (_id, topics) -*topicID - mongo fieldname for topicSet ID -*superUser - mongo fieldname for superuser flag (true/false) -*/ -... -``` +users = { + username: "user", + password: "PBKDF_string" + topics: int (topicID location) + superuser: int (1 true, 0 false) + } + +topics = { + _id: int, + topics: ["xx/xx/#", "yy/#", ...] + } +``` + +The following `auth_opt_mongo_` options are supported by the mysql back-end: + +| Option | default | Meaning | +| ------------------ | ----------------- | --------------------- | +| host | localhost | Hostname/Address +| port | 27017 | TCP port +| user | | Username +| password | | Password +| authSource | | Authentication Database Name +| database | mqGate | Database Name +| collection_users | users | Collection for User Documents +| collection_topics | topics | Collection for Topic Documents +| location_password | password | Password field name in User Document +| location_topic | topics | Topic Document pointer field name in User Document +| lotcation_topicId | _id | Field name that location_topic points to in Topic Document +| location_superuser | superuser | Superuser field name in User Document Mosquitto configuration for the `mongo` back-end: ``` From 196d781570e8e97fd9c3748060d600e53bdfeb18 Mon Sep 17 00:00:00 2001 From: Ryan Shumate Date: Tue, 11 Oct 2016 12:39:31 -0400 Subject: [PATCH 8/8] Formatting Fix --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 97f4cbed..7b293ba7 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,7 @@ ifneq ($(BACKEND_MONGO), no) BE_CFLAGS += -I/usr/local/include/ BE_CFLAGS += -I/usr/local/include/libmongoc-1.0/ - BE_CFLAGS += -I/usr/local/include/libbson-1.0/ + BE_CFLAGS += -I/usr/local/include/libbson-1.0/ BE_LDFLAGS += -L/usr/local/lib BE_LDADD += -lmongoc-1.0 -lbson-1.0 OBJS += be-mongo.o