Skip to content
This repository has been archived by the owner on Mar 12, 2019. It is now read-only.
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jpmens/mosquitto-auth-plug
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: coldfire84/mosquitto-auth-plug
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 10 commits
  • 7 files changed
  • 5 contributors

Commits on Mar 10, 2019

  1. Created new function for validating subscriptions with ACL. This was …

    …necessary because the previous function does not work with the latest revision of Mosquitto. Added usage of this new function in Mongo backend. Others should get it too.
    
    Squashed commit of the following:
    
    commit cd2e2dccc48b34e94962366dfd7e3126cd145afa
    Author: whendonkiesfly <>
    Date:   Sun Mar 10 17:09:52 2019 -0500
    
        Fixed issues from previous commit
    
    commit 72690e5aadf902a12526fb8bd5ccb4577c9f5da0
    Author: whendonkiesfly <>
    Date:   Sun Mar 10 17:09:41 2019 -0500
    
        minor refactoring
    
    commit 01684a8ecba062dd0c1e4e0adc0b2ede66dd3006
    Author: whendonkiesfly <>
    Date:   Sun Mar 10 17:09:33 2019 -0500
    
        Changed type of 'result' back to bool
    
    commit 6f4631c9926fb77b698606336d9376b9ca72f83d
    Author: whendonkiesfly <>
    Date:   Sun Mar 10 17:39:34 2019 -0500
    
        Minor refactoring and replaced usage of old function with mosquitto_auth_sub_topic_matches_acl
    
    commit a51ad9ed2f086796d9d14ce2d2ddf4535ca3e572
    Author: whendonkiesfly <>
    Date:   Sun Mar 10 17:08:39 2019 -0500
    
        Added new function for validating subscriptions with the ACL
    whendonkiesfly committed Mar 10, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4bdae64 View commit details

Commits on May 2, 2019

  1. Copy the full SHA
    d822c65 View commit details
  2. Copy the full SHA
    d64dbcb View commit details

Commits on May 3, 2019

  1. Support MOSQ_ACL_SUBSCRIBE

    vankxr authored May 3, 2019
    Copy the full SHA
    06d722d View commit details

Commits on Jun 11, 2019

  1. Copy the full SHA
    0455898 View commit details

Commits on Jun 12, 2019

  1. Merge pull request #1 from badman80/master

    + add "whirlpool" hash algorithm support
    vankxr authored Jun 12, 2019
    Copy the full SHA
    0f3a41d View commit details

Commits on Jul 10, 2019

  1. http: nullify freed memory for escaped strings and return BACKEND_DEF…

    …ER in case of error in the http backend (i.e. server down)
    Joan Llopis committed Jul 10, 2019
    Copy the full SHA
    adf3873 View commit details

Commits on Jul 25, 2019

  1. Copy the full SHA
    e0ce9ef View commit details
  2. Copy the full SHA
    8d06038 View commit details
  3. Copy the full SHA
    f1c2adb View commit details
Showing with 149 additions and 20 deletions.
  1. +3 −6 README.md
  2. +7 −7 auth-plug.c
  3. +126 −0 backends.c
  4. +1 −0 backends.h
  5. +5 −3 be-http.c
  6. +5 −4 be-mongo.c
  7. +2 −0 pbkdf2-check.c
9 changes: 3 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# mosquitto-auth-plug

As per 2019-03-11 I am archiving this repository and closing all currently open issues and pull requests without prejudice. The repository will continue to exist and you are welcome to work on your own fork of it, as long as you observe the LICENSEs.

I have not used the `mosquitto-auth-plug` myself for years now, but my users expect, nay, demand, that I support and help them with it. We've received over 580 stars (thank you for that!), and yet some people can't even be bothered to read the documentation and then send me private e-mails or DMs on Twitter, etc. to complain and/or ask for help. I'm tired of having to work on understanding and fixing issues users are experiencing with the software. I'm also a bit tired of the lack of help I've received for this project.
# Fork-specific changes
Merge changes from whendonkiesfly/mosquitto-auth-plug to support ACL checking with MongoDB, plus merge changes from jllopis/mosquitto-auth-plug to support Mosquitto 1.6.x.

The original README begins below this line.
The original README begins below this line (minus the swan song!).

# mosquitto-auth-plug

14 changes: 7 additions & 7 deletions auth-plug.c
Original file line number Diff line number Diff line change
@@ -499,7 +499,7 @@ int mosquitto_auth_security_cleanup(void *userdata, struct mosquitto_auth_opt *a


#if MOSQ_AUTH_PLUGIN_VERSION >=3
int mosquitto_auth_unpwd_check(void *userdata, const struct mosquitto *client, const char *username, const char *password)
int mosquitto_auth_unpwd_check(void *userdata, struct mosquitto *client, const char *username, const char *password)
#else
int mosquitto_auth_unpwd_check(void *userdata, const char *username, const char *password)
#endif
@@ -521,12 +521,12 @@ int mosquitto_auth_unpwd_check(void *userdata, const char *username, const char
free(e->username);
free(e->clientid);
e->username = strdup(username);
e->clientid = strdup("client id not available");
e->clientid = strdup(mosquitto_client_id(client));
} else {
e = (struct cliententry *)malloc(sizeof(struct cliententry));
e->key = (void *)client;
e->username = strdup(username);
e->clientid = strdup("client id not available");
e->clientid = strdup(mosquitto_client_id(client));
HASH_ADD(hh, ud->clients, key, sizeof(void *), e);
}
#endif
@@ -598,7 +598,7 @@ int mosquitto_auth_unpwd_check(void *userdata, const char *username, const char
}

#if MOSQ_AUTH_PLUGIN_VERSION >= 3
int mosquitto_auth_acl_check(void *userdata, int access, const struct mosquitto *client, const struct mosquitto_acl_msg *msg)
int mosquitto_auth_acl_check(void *userdata, int access, struct mosquitto *client, const struct mosquitto_acl_msg *msg)
#else
int mosquitto_auth_acl_check(void *userdata, const char *clientid, const char *username, const char *topic, int access)
#endif
@@ -652,11 +652,11 @@ int mosquitto_auth_acl_check(void *userdata, const char *clientid, const char *u
return MOSQ_DENY_ACL;
}

_log(LOG_DEBUG, "mosquitto_auth_acl_check(..., %s, %s, %s, %s)",
_log(LOG_DEBUG, "mosquitto_auth_acl_check(..., %s, %s, %s, %d)",
clientid ? clientid : "NULL",
username ? username : "NULL",
topic ? topic : "NULL",
access == MOSQ_ACL_READ ? "MOSQ_ACL_READ" : "MOSQ_ACL_WRITE" );
access );


granted = acl_cache_q(clientid, username, topic, access, userdata);
@@ -749,7 +749,7 @@ int mosquitto_auth_acl_check(void *userdata, const char *clientid, const char *u


#if MOSQ_AUTH_PLUGIN_VERSION >= 3
int mosquitto_auth_psk_key_get(void *userdata, const struct mosquitto *client, const char *hint, const char *identity, char *key, int max_key_len)
int mosquitto_auth_psk_key_get(void *userdata, struct mosquitto *client, const char *hint, const char *identity, char *key, int max_key_len)
#else
int mosquitto_auth_psk_key_get(void *userdata, const char *hint, const char *identity, char *key, int max_key_len)
#endif
126 changes: 126 additions & 0 deletions backends.c
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@
#include <string.h>
#include <stdlib.h>
#include "backends.h"
#include "mosquitto.h"

/*
* Search through `in' for tokens %c (clientid) and %u (username); build a
@@ -81,3 +82,128 @@ void t_expand(const char *clientid, const char *username, const char *in, char *

*res = work;
}



/*
* Compares an ACL topic filter with a requested subscribe filter to see if the subscription is allowed.
* Sets *result to 1 if a match is found and false otherwise.
*/

int mosquitto_auth_sub_topic_matches_acl(const char *acl_topic, const char *req_topic, int *result)
{
if(!result) {
*result = FALSE;
return MOSQ_ERR_INVAL;
}

if(!req_topic || !acl_topic) {
*result = FALSE;
return MOSQ_ERR_INVAL;
}

if(mosquitto_sub_topic_check(req_topic) != MOSQ_ERR_SUCCESS) {
*result = FALSE;
return MOSQ_ERR_INVAL;
}

if(mosquitto_sub_topic_check(acl_topic) != MOSQ_ERR_SUCCESS) {
*result = FALSE;
return MOSQ_ERR_INVAL;
}

if((*req_topic == '$' && *acl_topic != '$') || (*acl_topic == '$' && *req_topic != '$')) {
*result = FALSE;
return MOSQ_ERR_SUCCESS;
}

while(*req_topic && *acl_topic) {
int check_equiv;

//Process the # if it exists here.
if(*acl_topic == '#') {
//No need to check any further. The ACL has a #.
*result = TRUE;
return MOSQ_ERR_SUCCESS;
} else if(*req_topic == '#') {
//The user subscribed with a #, but the ACL does not allow that.
*result = FALSE;
return MOSQ_ERR_SUCCESS;
}

//Process the + if it exists here.
if(*req_topic == '+') {
//The subscription includes a single-level wild card. Check to see if that is allowed.
if(*acl_topic == '+') {
//The ACL allows for a + here. We need to move on to the next level without checking for equivalence.
check_equiv = FALSE;
} else {
//The ACL doesn't allow for a + in this position.
*result = FALSE;
return MOSQ_ERR_SUCCESS;
}
} else {
//We are just looking at normal subscription level.
//If the ACL has a single level wildcard, no need to check anything else at this level.
if(*acl_topic == '+') {
//The ACL allows for a + here. We need to move on to the next level without checking for equivalence.
check_equiv = FALSE;
} else {
//No wildcards. We need to compare to make sure the topic level for both topic filters are identical.
check_equiv = TRUE;
}
}

//Get the length of the current sub topic level.
int sub_level_length = 0;
while(req_topic[sub_level_length] && (req_topic[sub_level_length] != '/')) {
sub_level_length++;
}

//Get the length of the current acl topic level.
int acl_level_length = 0;
while(acl_topic[acl_level_length] && (acl_topic[acl_level_length] != '/')) {
acl_level_length++;
}

//If we need to check for equivalency, do so.
if(check_equiv) {
//First check to see if the lengths of the levels are identical. If not, we know we don't have a match.
if(sub_level_length != acl_level_length) {
*result = FALSE;
return MOSQ_ERR_SUCCESS;
}

//Lengths are the same, so we need to check the contents.
if(memcmp(req_topic, acl_topic, sub_level_length)) {
*result = FALSE;
return MOSQ_ERR_SUCCESS;
}
} else {
}

//Increment pointers
req_topic += sub_level_length;
acl_topic += acl_level_length;

//If we haven't incremented to the null terminator, go one more to get past the '/'.
// Only do this if both topics have not reached the end to avoid covering up situation
// where one topic is longer than the other.
if(*req_topic && *acl_topic) {
req_topic++;
acl_topic++;
}
}


//If we hit the null terminator on one and not the other, we don't have a match.
if((*req_topic != 0) ^ (*acl_topic != 0))
{
*result = FALSE;
return MOSQ_ERR_SUCCESS;
}

//Topics match.
*result = TRUE;
return MOSQ_ERR_SUCCESS;
}
1 change: 1 addition & 0 deletions backends.h
Original file line number Diff line number Diff line change
@@ -55,5 +55,6 @@ typedef int (f_superuser)(void *conf, const char *username);
typedef int (f_aclcheck)(void *conf, const char *clientid, const char *username, const char *topic, int acc);

void t_expand(const char *clientid, const char *username, const char *in, char **res);
int mosquitto_auth_sub_topic_matches_acl(const char *acl_topic, const char *req_topic, int *result);

#endif
8 changes: 5 additions & 3 deletions be-http.c
Original file line number Diff line number Diff line change
@@ -87,14 +87,16 @@ static int get_string_envs(CURL *curl, const char *required_env, char *querystri
curl_free(escaped_val);
}

if (escaped_key) free(escaped_key);
if (escaped_val) free(escaped_val);
// They are already freed by curl_free above
if (escaped_key) escaped_key = NULL;
if (escaped_val) escaped_val = NULL;
free(env_string);
return (num);
}

static int http_post(void *handle, char *uri, const char *clientid, const char *username, const char *password, const char *topic, int acc, int method)
{

struct http_backend *conf = (struct http_backend *)handle;
CURL *curl;
struct curl_slist *headerlist=NULL;
@@ -208,7 +210,7 @@ static int http_post(void *handle, char *uri, const char *clientid, const char *
}
} else {
_log(LOG_DEBUG, "http req fail url=%s re=%s", url, curl_easy_strerror(re));
ok = BACKEND_ERROR;
ok = BACKEND_DEFER;
}

curl_easy_cleanup(curl);
9 changes: 5 additions & 4 deletions be-mongo.c
Original file line number Diff line number Diff line change
@@ -321,13 +321,13 @@ bool be_mongo_check_acl_topics_array(const bson_iter_t *topics, const char *req_

while (bson_iter_next(&iter)) {
const char *permitted_topic = bson_iter_utf8(&iter, NULL);
bool topic_matches = false;
int topic_matches = FALSE;

char *expanded;

t_expand(clientid, username, permitted_topic, &expanded);
if (expanded && *expanded) {
mosquitto_topic_matches_sub(expanded, req_topic, &topic_matches);
mosquitto_auth_sub_topic_matches_acl(expanded, req_topic, &topic_matches);
free(expanded);

if (topic_matches) {
@@ -345,16 +345,17 @@ bool be_mongo_check_acl_topics_map(const bson_iter_t *topics, const char *req_to
bson_iter_recurse(topics, &iter);
bool granted = false;


// Loop through mapped topics, allowing for the fact that a two different ACLs may have complementary permissions.
while (bson_iter_next(&iter) && !granted) {
const char *permitted_topic = bson_iter_key(&iter);
bool topic_matches = false;
int topic_matches = FALSE;

char *expanded;

t_expand(clientid, username, permitted_topic, &expanded);
if (expanded && *expanded) {
mosquitto_topic_matches_sub(expanded, req_topic, &topic_matches);
mosquitto_auth_sub_topic_matches_acl(expanded, req_topic, &topic_matches);
free(expanded);

if (topic_matches) {
2 changes: 2 additions & 0 deletions pbkdf2-check.c
Original file line number Diff line number Diff line change
@@ -154,6 +154,8 @@ int pbkdf2_check(char *password, char *hash)
evpmd = EVP_sha1();
} else if (strcmp(sha, "sha512") == 0) {
evpmd = EVP_sha512();
} else if (strcmp(sha, "whirlpool") == 0) {
evpmd = EVP_whirlpool();
}

rc = PKCS5_PBKDF2_HMAC(password, strlen(password),