diff --git a/ChangeLog.txt b/ChangeLog.txt index 92b2c79d9..913193562 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -8,6 +8,7 @@ Broker: - Satisfy valgrind when exiting on error due to not being able to open a listening socket, by calling freeaddrinfo. Closes #1565. - Fix config->user not being freed on exit. Closes #1564. +- Fix trailing whitespace not being trimmed on acl users. Closes #1539. Library: - Set minimum keepalive argument to `mosquitto_connect*()` to be 5 seconds. diff --git a/lib/util_mosq.c b/lib/util_mosq.c index 58fb5dfc5..ef37b7916 100644 --- a/lib/util_mosq.c +++ b/lib/util_mosq.c @@ -17,6 +17,7 @@ Contributors: #include "config.h" #include +#include #include #ifdef WIN32 @@ -382,3 +383,21 @@ enum mosquitto_client_state mosquitto__get_state(struct mosquitto *mosq) return state; } + + +char *util__trimblanks(char *str) +{ + char *endptr; + + if(str == NULL) return NULL; + + while(isblank(str[0])){ + str++; + } + endptr = &str[strlen(str)-1]; + while(endptr > str && isblank(endptr[0])){ + endptr[0] = '\0'; + endptr--; + } + return str; +} diff --git a/lib/util_mosq.h b/lib/util_mosq.h index a527fd62b..db621d0b1 100644 --- a/lib/util_mosq.h +++ b/lib/util_mosq.h @@ -47,4 +47,7 @@ void util__increment_receive_quota(struct mosquitto *mosq); void util__increment_send_quota(struct mosquitto *mosq); void util__decrement_receive_quota(struct mosquitto *mosq); void util__decrement_send_quota(struct mosquitto *mosq); + + +char *util__trimblanks(char *str); #endif diff --git a/src/conf.c b/src/conf.c index b5ec93841..49eca766b 100644 --- a/src/conf.c +++ b/src/conf.c @@ -2379,16 +2379,11 @@ static int conf__parse_string(char **token, const char *name, char **value, char return MOSQ_ERR_INVAL; } /* Deal with multiple spaces at the beginning of the string. */ - while((*token)[0] == ' ' || (*token)[0] == '\t'){ - (*token)++; - } + *token = util__trimblanks(*token); if(strlen(*token) == 0){ log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty %s value in configuration.", name); return MOSQ_ERR_INVAL; } - while((*token)[strlen(*token)-1] == ' ' || (*token)[strlen(*token)-1] == '\t'){ - (*token)[strlen(*token)-1] = '\0'; - } if(mosquitto_validate_utf8(*token, strlen(*token))){ log__printf(NULL, MOSQ_LOG_ERR, "Error: Malformed UTF-8 in configuration."); diff --git a/src/security_default.c b/src/security_default.c index 8ad61db9a..58b2158e6 100644 --- a/src/security_default.c +++ b/src/security_default.c @@ -531,9 +531,12 @@ static int aclfile__parse(struct mosquitto_db *db, struct mosquitto__security_op }else if(!strcmp(token, "user")){ token = strtok_r(NULL, "", &saveptr); if(token){ - /* Ignore duplicate spaces */ - while(token[0] == ' '){ - token++; + token = util__trimblanks(token); + if(slen == 0){ + log__printf(NULL, MOSQ_LOG_ERR, "Error: Missing username in acl_file \"%s\".", security_opts->acl_file); + mosquitto__free(user); + fclose(aclfptr); + return 1; } mosquitto__free(user); user = mosquitto__strdup(token); diff --git a/test/unit/Makefile b/test/unit/Makefile index 9d422428d..6d8c934d9 100644 --- a/test/unit/Makefile +++ b/test/unit/Makefile @@ -16,11 +16,13 @@ TEST_OBJS = test.o \ property_write.o \ stubs.o \ util_topic_test.o \ + util_trim_test.o \ utf8.o LIB_OBJS = memory_mosq.o \ packet_datatypes.o \ property_mosq.o \ + util_mosq.o \ util_topic.o \ utf8_mosq.o diff --git a/test/unit/stubs.c b/test/unit/stubs.c index f4b7c97a0..094a9ec3a 100644 --- a/test/unit/stubs.c +++ b/test/unit/stubs.c @@ -1,6 +1,27 @@ +#include #include +struct mosquitto_db{ + +}; + int log__printf(struct mosquitto *mosq, int priority, const char *fmt, ...) { return 0; } + +time_t mosquitto_time(void) +{ + return 123; +} + +int net__socket_close(struct mosquitto_db *db, struct mosquitto *mosq) +{ + return MOSQ_ERR_SUCCESS; +} + +int send__pingreq(struct mosquitto *mosq) +{ + return MOSQ_ERR_SUCCESS; +} + diff --git a/test/unit/test.c b/test/unit/test.c index b6f836f65..1b083963a 100644 --- a/test/unit/test.c +++ b/test/unit/test.c @@ -12,6 +12,7 @@ int init_property_user_read_tests(void); int init_property_write_tests(void); int init_utf8_tests(void); int init_util_topic_tests(void); +int init_util_trim_tests(void); int main(int argc, char *argv[]) { @@ -31,6 +32,7 @@ int main(int argc, char *argv[]) || init_property_user_read_tests() || init_property_write_tests() || init_util_topic_tests() + || init_util_trim_tests() ){ CU_cleanup_registry(); diff --git a/test/unit/util_trim_test.c b/test/unit/util_trim_test.c new file mode 100644 index 000000000..aaa0d6462 --- /dev/null +++ b/test/unit/util_trim_test.c @@ -0,0 +1,183 @@ +#include +#include + +#include + + +static void rtrim_helper(const char *expected, char *buf) +{ + char *res; + + res = util__trimblanks(buf); + CU_ASSERT_PTR_NOT_NULL(res); + if(res){ + CU_ASSERT_EQUAL(strlen(buf), strlen(res)); + CU_ASSERT_STRING_EQUAL(res, expected); + CU_ASSERT_PTR_EQUAL(res, buf); + } +} + + +static void ltrim_helper(const char *expected, char *buf) +{ + char *res; + + res = util__trimblanks(buf); + CU_ASSERT_PTR_NOT_NULL(res); + if(res){ + CU_ASSERT_EQUAL(strlen(expected), strlen(res)); + CU_ASSERT_STRING_EQUAL(res, expected); + } +} + + +static void TEST_null_input(void) +{ + char *res; + + res = util__trimblanks(NULL); + CU_ASSERT_PTR_NULL(res); +} + + +static void TEST_empty_input(void) +{ + char buf[10]; + char *res; + + memset(buf, 0, sizeof(buf)); + res = util__trimblanks(buf); + CU_ASSERT_PTR_NOT_NULL(res); + if(res){ + CU_ASSERT_STRING_EQUAL(res, ""); + } +} + + +static void TEST_no_blanks(void) +{ + char buf[10] = "noblanks"; + + rtrim_helper("noblanks", buf); +} + + +static void TEST_rtrim(void) +{ + char buf1[20] = "spaces "; + char buf2[20] = "spaces "; + char buf3[20] = "spaces "; + char buf4[20] = "spaces "; + char buf5[20] = "tabs\t"; + char buf6[20] = "tabs\t\t"; + char buf7[20] = "tabs\t\t\t"; + char buf8[20] = "tabs\t\t\t\t"; + char buf9[20] = "mixed \t"; + char buf10[20] = "mixed\t "; + char buf11[20] = "mixed\t\t "; + char buf12[20] = "mixed \t \t "; + + rtrim_helper("spaces", buf1); + rtrim_helper("spaces", buf2); + rtrim_helper("spaces", buf3); + rtrim_helper("spaces", buf4); + rtrim_helper("tabs", buf5); + rtrim_helper("tabs", buf6); + rtrim_helper("tabs", buf7); + rtrim_helper("tabs", buf8); + rtrim_helper("mixed", buf9); + rtrim_helper("mixed", buf10); + rtrim_helper("mixed", buf11); + rtrim_helper("mixed", buf12); +} + + +static void TEST_ltrim(void) +{ + char buf1[20] = " spaces"; + char buf2[20] = " spaces"; + char buf3[20] = " spaces"; + char buf4[20] = " spaces"; + char buf5[20] = "\ttabs"; + char buf6[20] = "\t\ttabs"; + char buf7[20] = "\t\t\ttabs"; + char buf8[20] = "\t\t\t\ttabs"; + char buf9[20] = "\t mixed"; + char buf10[20] = " \tmixed"; + char buf11[20] = " \t\tmixed"; + char buf12[20] = "\t \t mixed"; + + ltrim_helper("spaces", buf1); + ltrim_helper("spaces", buf2); + ltrim_helper("spaces", buf3); + ltrim_helper("spaces", buf4); + ltrim_helper("tabs", buf5); + ltrim_helper("tabs", buf6); + ltrim_helper("tabs", buf7); + ltrim_helper("tabs", buf8); + ltrim_helper("mixed", buf9); + ltrim_helper("mixed", buf10); + ltrim_helper("mixed", buf11); + ltrim_helper("mixed", buf12); +} + + +static void TEST_btrim(void) +{ + char buf1[20] = " spaces "; + char buf2[20] = " spaces "; + char buf3[20] = " spaces "; + char buf4[20] = " spaces "; + char buf5[20] = "\ttabs\t"; + char buf6[20] = "\t\ttabs\t\t"; + char buf7[20] = "\t\t\ttabs\t\t\t"; + char buf8[20] = "\t\t\t\ttabs\t\t\t\t"; + char buf9[20] = "\t mixed \t"; + char buf10[20] = " \tmixed\t "; + char buf11[20] = " \t\tmixed\t\t "; + char buf12[20] = "\t \t mixed \t \t "; + + ltrim_helper("spaces", buf1); + ltrim_helper("spaces", buf2); + ltrim_helper("spaces", buf3); + ltrim_helper("spaces", buf4); + ltrim_helper("tabs", buf5); + ltrim_helper("tabs", buf6); + ltrim_helper("tabs", buf7); + ltrim_helper("tabs", buf8); + ltrim_helper("mixed", buf9); + ltrim_helper("mixed", buf10); + ltrim_helper("mixed", buf11); + ltrim_helper("mixed", buf12); +} + + +/* ======================================================================== + * TEST SUITE SETUP + * ======================================================================== */ + +int init_util_trim_tests(void) +{ + CU_pSuite test_suite = NULL; + + test_suite = CU_add_suite("Util string trim", NULL, NULL); + if(!test_suite){ + printf("Error adding CUnit util string trim test suite.\n"); + return 1; + } + + if(0 + || !CU_add_test(test_suite, "Null input", TEST_null_input) + || !CU_add_test(test_suite, "Empty input", TEST_empty_input) + || !CU_add_test(test_suite, "No blanks", TEST_no_blanks) + || !CU_add_test(test_suite, "Right trim", TEST_rtrim) + || !CU_add_test(test_suite, "Left trim", TEST_ltrim) + || !CU_add_test(test_suite, "Both trim", TEST_btrim) + ){ + + printf("Error adding util topic CUnit tests.\n"); + return 1; + } + + return 0; +}