Add mosquitto_sub_matches_acl_with_pattern.

pull/2263/head
Roger A. Light 4 years ago
parent 09fe737038
commit a02aad0a9c

@ -52,6 +52,9 @@ Client library:
substitution.
- Add `mosquitto_sub_matches_acl()`, which can match one topic filter (a
subscription) against another topic filter (an ACL).
- Add `mosquitto_sub_matches_acl_with_pattern()`, which can match one topic
filter (a subscription) against another topic filter (an ACL), with `%c` and
`%u` patterns for client id / username substitution.
- Performance: reduce memory allocations when sending packets.
Clients:

@ -2463,7 +2463,7 @@ libmosq_EXPORT int mosquitto_topic_matches_sub2(const char *sub, size_t sublen,
* Check whether a topic matches a subscription, with client id/username
* pattern substitution.
*
* Any instances of a topic hierarchy that are exactly %c or %u will be
* Any instances of a subscriptions hierarchy that are exactly %c or %u will be
* replaced with the client id or username respectively.
*
* For example:
@ -2515,7 +2515,46 @@ libmosq_EXPORT int mosquitto_topic_matches_sub_with_pattern(const char *sub, con
* MOSQ_ERR_SUCCESS - on success
* MOSQ_ERR_INVAL - if the input parameters were invalid.
*/
libmosq_EXPORT int mosquitto_sub_matches_acl(const char *sub, const char *topic, bool *result);
libmosq_EXPORT int mosquitto_sub_matches_acl(const char *acl, const char *sub, bool *result);
/*
* Function: mosquitto_sub_matches_acl_with_pattern
*
* Check whether a subscription (a topic filter with wildcards) matches an ACL
* (a topic filter with wildcards) , with client id/username pattern
* substitution.
*
* Any instances of an ACL hierarchy that are exactly %c or %u will be
* replaced with the client id or username respectively.
*
* For example:
*
* mosquitto_sub_matches_acl_with_pattern("sensors/%c/+", "sensors/kitchen/temperature", "kitchen", NULL, &result)
* -> this will match
*
* mosquitto_sub_matches_acl_with_pattern("sensors/%c/+", "sensors/bathroom/temperature", "kitchen", NULL, &result)
* -> this will not match
*
* mosquitto_sub_matches_acl_with_pattern("sensors/%count/+", "sensors/kitchen/temperature", "kitchen", NULL, &result)
* -> this will not match - the `%count` is not treated as a pattern
*
* mosquitto_sub_matches_acl_with_pattern("%c/%c/%u/+", "kitchen/kitchen/bathroom/bathroom", "kitchen", "bathroom", &result)
* -> this will match
*
* Parameters:
* acl - ACL topic filter string to check sub against.
* sub - subscription to check.
* clientid - client id to substitute in patterns. If NULL, then any %c patterns will not match.
* username - username to substitute in patterns. If NULL, then any %u patterns will not match.
* result - bool pointer to hold result. Will be set to true if the subscription
* matches the ACL.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success
* MOSQ_ERR_INVAL - if the input parameters were invalid.
*/
libmosq_EXPORT int mosquitto_sub_matches_acl_with_pattern(const char *acl, const char *sub, const char *clientid, const char *username, bool *result);
/*

@ -147,4 +147,5 @@ MOSQ_2.1 {
mosquitto_pre_connect_callback_set;
mosquitto_topic_matches_sub_with_pattern;
mosquitto_sub_matches_acl;
mosquitto_sub_matches_acl_with_pattern;
} MOSQ_1.7;

@ -354,9 +354,11 @@ static int topic_matches_sub(const char *sub, const char *topic, const char *cli
return MOSQ_ERR_SUCCESS;
}
static int sub_matches_acl(const char *acl, const char *sub, bool *result)
static int sub_matches_acl(const char *acl, const char *sub, const char *clientid, const char *username, bool match_patterns, bool *result)
{
size_t apos;
const char *pattern_check;
const char *lastchar = NULL;
*result = false;
@ -373,6 +375,51 @@ static int sub_matches_acl(const char *acl, const char *sub, bool *result)
apos = 0;
while(acl[0] != 0){
if(match_patterns &&
(lastchar == NULL || lastchar[0] == '/') &&
acl[0] == '%' &&
(acl[1] == 'c' || acl[1] == 'u') &&
(acl[2] == '/' || acl[2] == '\0')
){
if(acl[1] == 'c'){
pattern_check = clientid;
}else{
pattern_check = username;
}
if(pattern_check == NULL || pattern_check[0] == '\0'){
/* no match */
return MOSQ_ERR_SUCCESS;
}
if(pattern_check[1] == '\0' && (
pattern_check[0] == '+' ||
pattern_check[0] == '#' ||
pattern_check[0] == '/')
){
/* username/client id of just + / # not allowed */
return MOSQ_ERR_SUCCESS;
}
apos +=2;
acl += 2;
while(pattern_check[0] != 0 && sub[0] != 0 && sub[0] != '/'){
if(pattern_check[0] != sub[0]){
/* Valid input, but no match */
return MOSQ_ERR_SUCCESS;
}
pattern_check++;
sub++;
}
if(sub[0] == '\0' && (acl[0] == '\0' ||
(acl[0] == '/' && acl[1] == '#' && acl[2] == '\0'))
){
*result = true;
return MOSQ_ERR_SUCCESS;
}
}
if(acl[0] != sub[0] || sub[0] == 0){ /* Check for wildcard matches */
if(acl[0] == '+'){
if(sub[0] == '#'){
@ -460,6 +507,7 @@ static int sub_matches_acl(const char *acl, const char *sub, bool *result)
return MOSQ_ERR_SUCCESS;
}
}
lastchar = acl-1;
}
if((sub[0] != 0 || acl[0] != 0)){
return MOSQ_ERR_SUCCESS;
@ -477,7 +525,12 @@ static int sub_matches_acl(const char *acl, const char *sub, bool *result)
int mosquitto_sub_matches_acl(const char *acl, const char *sub, bool *result)
{
return sub_matches_acl(acl, sub, result);
return sub_matches_acl(acl, sub, NULL, NULL, false, result);
}
int mosquitto_sub_matches_acl_with_pattern(const char *acl, const char *sub, const char *clientid, const char *username, bool *result)
{
return sub_matches_acl(acl, sub, clientid, username, true, result);
}
int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)

@ -31,6 +31,7 @@ _mosquitto_realloc
_mosquitto_set_username
_mosquitto_strdup
_mosquitto_sub_matches_acl
_mosquitto_sub_matches_acl_with_pattern
_mosquitto_sub_topic_check
_mosquitto_topic_matches_sub
_mosquitto_topic_matches_sub_with_pattern

@ -32,6 +32,7 @@
mosquitto_set_username;
mosquitto_strdup;
mosquitto_sub_matches_acl;
mosquitto_sub_matches_acl_with_pattern;
mosquitto_sub_topic_check;
mosquitto_topic_matches_sub;
mosquitto_topic_matches_sub_with_pattern;

@ -84,7 +84,7 @@ static void TEST_empty_input(void)
CU_ASSERT_EQUAL(match, false);
}
static void TEST_pattern_empty_input(void)
static void TEST_topic_pattern_empty_input(void)
{
int rc;
bool match;
@ -150,6 +150,72 @@ static void TEST_pattern_empty_input(void)
CU_ASSERT_EQUAL(match, false);
}
static void TEST_acl_pattern_empty_input(void)
{
int rc;
bool match;
rc = mosquitto_sub_matches_acl_with_pattern(NULL, NULL, NULL, NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("acl", NULL, NULL, NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern(NULL, "sub", NULL, NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern(NULL, NULL, "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern(NULL, NULL, NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("acl", "", "", "", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("", "sub", "", "", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("", "", "clientid", "", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("", "", "", "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%c", "sub", NULL, NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%u", "sub", NULL, NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%c", "", "", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%u", "", NULL, "", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("test/%c/test", "test//test", "", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("test/%u/test", "test//test", NULL, "", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
}
static void TEST_sub_match_empty_input(void)
{
int rc;
@ -278,10 +344,10 @@ static void TEST_invalid(void)
}
/* ========================================================================
* PATTERNS
* TOPIC MATCHES SUB PATTERNS
* ======================================================================== */
static void TEST_pattern_clientid(void)
static void TEST_topic_pattern_clientid(void)
{
int rc;
bool match;
@ -337,7 +403,7 @@ static void TEST_pattern_clientid(void)
CU_ASSERT_EQUAL(match, false);
}
static void TEST_pattern_username(void)
static void TEST_topic_pattern_username(void)
{
int rc;
bool match;
@ -393,7 +459,7 @@ static void TEST_pattern_username(void)
CU_ASSERT_EQUAL(match, false);
}
static void TEST_pattern_both(void)
static void TEST_topic_pattern_both(void)
{
int rc;
bool match;
@ -448,7 +514,7 @@ static void TEST_pattern_both(void)
CU_ASSERT_EQUAL(match, false);
}
static void TEST_pattern_wildcard(void)
static void TEST_topic_pattern_wildcard(void)
{
int rc;
bool match;
@ -530,6 +596,430 @@ static void TEST_pattern_wildcard(void)
CU_ASSERT_EQUAL(match, false);
}
/* ========================================================================
* SUB MATCHES ACL PATTERNS
* ======================================================================== */
static void TEST_acl_pattern_clientid(void)
{
int rc;
bool match;
/* Sole pattern */
rc = mosquitto_sub_matches_acl_with_pattern("%c", "clientid", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("%c", "clientid", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern at beginning */
rc = mosquitto_sub_matches_acl_with_pattern("%c/test", "clientid/test", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("%c/test", "clientid/test", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern at end */
rc = mosquitto_sub_matches_acl_with_pattern("test/%c", "test/clientid", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("test/%c", "test/clientid", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern in middle */
rc = mosquitto_sub_matches_acl_with_pattern("test/%c/test", "test/clientid/test", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("test/%c/test", "test/clientid/test", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Repeated pattern */
rc = mosquitto_sub_matches_acl_with_pattern("test/%c/%c/test", "test/clientid/clientid/test", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("test/%c/%c/test", "test/clientid/clientid/test", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Not a pattern */
rc = mosquitto_sub_matches_acl_with_pattern("test/%count", "test/clientid", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Now repeated, with wildcards: */
/* Pattern at beginning */
rc = mosquitto_sub_matches_acl_with_pattern("%c/test/+", "clientid/test/+", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("%c/test/+", "clientid/test/+", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%c/test/#", "clientid/test/+", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("%c/test/#", "clientid/test/+", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern at end */
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%c", "+/test/clientid", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%c", "+/test/clientid", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern in middle */
rc = mosquitto_sub_matches_acl_with_pattern("test/%c/+/test", "test/clientid/+/test", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("test/%c/+/test", "test/clientid/+/test", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Repeated pattern */
rc = mosquitto_sub_matches_acl_with_pattern("test/%c/%c/test/+", "test/clientid/clientid/test/test", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("test/%c/%c/test/+", "test/clientid/clientid/test/test", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Not a pattern */
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%count", "+/test/clientid", "clientid", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
}
static void TEST_acl_pattern_username(void)
{
int rc;
bool match;
/* Sole pattern */
rc = mosquitto_sub_matches_acl_with_pattern("%u", "username", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("%u", "username", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern at beginning */
rc = mosquitto_sub_matches_acl_with_pattern("%u/test", "username/test", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("%u/test", "username/test", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern at end */
rc = mosquitto_sub_matches_acl_with_pattern("test/%u", "test/username", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("test/%u", "test/username", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern in middle */
rc = mosquitto_sub_matches_acl_with_pattern("test/%u/test", "test/username/test", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("test/%u/test", "test/username/test", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Repeated pattern */
rc = mosquitto_sub_matches_acl_with_pattern("test/%u/%u/test", "test/username/username/test", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("test/%u/%u/test", "test/username/username/test", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Not a pattern */
rc = mosquitto_sub_matches_acl_with_pattern("test/%username", "test/username", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Now repeat with wildcards: */
/* Pattern at beginning */
rc = mosquitto_sub_matches_acl_with_pattern("%u/test/+", "username/test/+", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("%u/test/+", "username/test/+", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%u/#", "username/test/+", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("%u/#", "username/test/+", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern at end */
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%u", "+/test/username", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%u", "+/test/username", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern in middle */
rc = mosquitto_sub_matches_acl_with_pattern("+/%u/test", "test/username/test", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("+/%u/test", "test/username/test", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Repeated pattern */
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%u/%u/test", "+/test/username/username/test", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%u/%u/test", "+/test/username/username/test", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Not a pattern */
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%username/+", "+/test/username/+", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
}
static void TEST_acl_pattern_both(void)
{
int rc;
bool match;
/* Sole pattern */
rc = mosquitto_sub_matches_acl_with_pattern("%u/%c", "username/clientid", "clientid", "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("%u/%c", "username/clientid", "clientid", "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%u/%c", "username/clientid", "nomatch", "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%u/%c", "username/clientid", "nomatch", "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Pattern in middle */
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%c/%u/#", "+/test/clientid/username/test", "clientid", "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%c/%u/#", "+/test/clientid/username/test", "clientid", "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%c/%u/test", "a/test/clientid/username/test", "nomatch", "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("+/test/%c/%u/test", "a/test/clientid/username/test", "nomatch", "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Repeated pattern */
rc = mosquitto_sub_matches_acl_with_pattern("test/%u/%c/%c/%u/#", "test/username/clientid/clientid/username/#", "clientid", "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
/* Not a pattern */
rc = mosquitto_sub_matches_acl_with_pattern("test/%username/+/%client", "test/username/a/clientid", "clientid", "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Not a pattern */
rc = mosquitto_sub_matches_acl_with_pattern("test/a%u/+/a%c", "test/ausername/a/aclientid", "clientid", "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
}
static void TEST_acl_pattern_wildcard(void)
{
int rc;
bool match;
/* Malicious */
/* ========= */
/* / in client id */
rc = mosquitto_sub_matches_acl_with_pattern("%c", "clientid/test", "clientid/test", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%c", "/", "/", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* / in username */
rc = mosquitto_sub_matches_acl_with_pattern("%u", "username/test", NULL, "username/test", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%u", "/", NULL, "/", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* + in client id */
rc = mosquitto_sub_matches_acl_with_pattern("%c", "clientid", "+", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("%c", "+", "+", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* + in username */
rc = mosquitto_sub_matches_acl_with_pattern("username/%u/+", "username/test/+", NULL, "+", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("username/%u/+", "username/+/+", NULL, "+", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("username/%u/+", "username/+", NULL, "+/a", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* # in client id */
rc = mosquitto_sub_matches_acl_with_pattern("%c", "#", "#", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* # in username */
rc = mosquitto_sub_matches_acl_with_pattern("%u", "#", NULL, "#", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Valid */
/* ========= */
/* Ends in + */
rc = mosquitto_sub_matches_acl_with_pattern("clientid/%c/+", "clientid/test/topic", "test", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("clientid/%c/+", "clientid/test/topic", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("username/%u/+", "username/test/topic", NULL, "test", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("username/%u/+", "username/test/topic", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
/* Ends in # */
rc = mosquitto_sub_matches_acl_with_pattern("+/clientid/%c/#", "+/clientid/test/topic", "test", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("+/clientid/%c/#", "+/clientid/test/topic", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("+/username/%u/#", "+/username/test/topic", NULL, "test", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("+/username/%u/#", "+/username/test/topic", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("+/clientid/%c/#", "+/clientid/test", "test", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("+/clientid/%c/#", "+/clientid/test", "nomatch", NULL, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl_with_pattern("+/pattern/%u/#", "+/pattern/username", NULL, "username", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl_with_pattern("+/username/%u/#", "+/username/test", NULL, "nomatch", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
}
static void TEST_acl_pattern_wildcard_wildcard(void)
{
int rc;
bool match;
rc = mosquitto_sub_matches_acl("$SYS/#", "$SYS/broker/#", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl("$SYS/#", "$SYS/+/#", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl("$SYS/#", "$SYS", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
rc = mosquitto_sub_matches_acl("$SYS/+", "$SYS/#", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl("$SYS/+/a", "$SYS/a/+", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl("$SYS/+", "$SYS/+/a", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl("$SYS/broker/uptime", "$SYS/broker/#", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
rc = mosquitto_sub_matches_acl("#", "$SYS/broker/#", &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, false);
}
/* ========================================================================
* PUB TOPIC CHECK
* ======================================================================== */
@ -680,11 +1170,17 @@ int init_util_topic_tests(void)
|| !CU_add_test(test_suite, "Pub topic: Invalid", TEST_pub_topic_invalid)
|| !CU_add_test(test_suite, "Sub topic: Valid", TEST_sub_topic_valid)
|| !CU_add_test(test_suite, "Sub topic: Invalid", TEST_sub_topic_invalid)
|| !CU_add_test(test_suite, "Pattern topic: Empty input", TEST_pattern_empty_input)
|| !CU_add_test(test_suite, "Pattern topic: clientid", TEST_pattern_clientid)
|| !CU_add_test(test_suite, "Pattern topic: username", TEST_pattern_username)
|| !CU_add_test(test_suite, "Pattern topic: both", TEST_pattern_both)
|| !CU_add_test(test_suite, "Pattern topic: wildcard", TEST_pattern_wildcard)
|| !CU_add_test(test_suite, "Pattern topic: Empty input", TEST_topic_pattern_empty_input)
|| !CU_add_test(test_suite, "Pattern topic: clientid", TEST_topic_pattern_clientid)
|| !CU_add_test(test_suite, "Pattern topic: username", TEST_topic_pattern_username)
|| !CU_add_test(test_suite, "Pattern topic: both", TEST_topic_pattern_both)
|| !CU_add_test(test_suite, "Pattern topic: wildcard", TEST_topic_pattern_wildcard)
|| !CU_add_test(test_suite, "Pattern acl: Empty input", TEST_acl_pattern_empty_input)
|| !CU_add_test(test_suite, "Pattern acl: clientid", TEST_acl_pattern_clientid)
|| !CU_add_test(test_suite, "Pattern acl: username", TEST_acl_pattern_username)
|| !CU_add_test(test_suite, "Pattern acl: both", TEST_acl_pattern_both)
|| !CU_add_test(test_suite, "Pattern acl: wildcard", TEST_acl_pattern_wildcard)
|| !CU_add_test(test_suite, "Pattern acl: wildcard vs wildcard", TEST_acl_pattern_wildcard_wildcard)
|| !CU_add_test(test_suite, "Sub matching: Empty input", TEST_sub_match_empty_input)
|| !CU_add_test(test_suite, "Sub matching: normal", TEST_sub_match_acl)
){
@ -695,5 +1191,3 @@ int init_util_topic_tests(void)
return 0;
}
#if 0
#endif

Loading…
Cancel
Save