Author: mmichelson Date: Tue Mar 24 14:19:23 2015 New Revision: 433336 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433336 Log: Add off-nominal NAPTR flags test.
This test ensures that NAPTR records with invalid flags are not added to the result set. Modified: team/group/dns_naptr/main/dns_naptr.c team/group/dns_naptr/tests/test_dns_naptr.c Modified: team/group/dns_naptr/main/dns_naptr.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/main/dns_naptr.c?view=diff&rev=433336&r1=433335&r2=433336 ============================================================================== --- team/group/dns_naptr/main/dns_naptr.c (original) +++ team/group/dns_naptr/main/dns_naptr.c Tue Mar 24 14:19:23 2015 @@ -39,6 +39,80 @@ #include "asterisk/linkedlists.h" #include "asterisk/dns_internal.h" #include "asterisk/utils.h" + +/*! + * \brief Result of analyzing NAPTR flags on a record + */ +enum flags_result { + /*! Terminal record, meaning the DDDS algorithm can be stopped */ + FLAGS_TERMINAL, + /*! No flags provided, likely meaning another NAPTR lookup */ + FLAGS_EMPTY, + /*! Unrecognized but valid flags. We cannot conclude what they mean */ + FLAGS_UNKNOWN, + /*! Non-alphanumeric or invalid combination of flags */ + FLAGS_INVALID, +}; + +/*! + * \brief Analyze and interpret NAPTR flags as per RFC 3404 + * + * \note The flags string passed into this function is NOT NULL-terminated + * + * \param flags The flags string from a NAPTR record + * \flags_size The size of the flags string in bytes + * \return flag result + */ +static enum flags_result interpret_flags(const char *flags, uint8_t flags_size) +{ + int i; + char known_flag_found = 0; + + if (flags_size == 0) { + return FLAGS_EMPTY; + } + + /* Take care of the most common (and easy) case, one character */ + if (flags_size == 1) { + if (*flags == 's' || *flags == 'S' || + *flags == 'a' || *flags == 'A' || + *flags == 'u' || *flags == 'U') { + return FLAGS_TERMINAL; + } else if (!isalnum(*flags)) { + return FLAGS_INVALID; + } else { + return FLAGS_UNKNOWN; + } + } + + for (i = 0; i < flags_size; ++i) { + if (!isalnum(flags[i])) { + return FLAGS_INVALID; + } else if (flags[i] == 's' || flags[i] == 'S') { + if (known_flag_found && known_flag_found != 's') { + return FLAGS_INVALID; + } + known_flag_found = 's'; + } else if (flags[i] == 'u' || flags[i] == 'U') { + if (known_flag_found && known_flag_found != 'u') { + return FLAGS_INVALID; + } + known_flag_found = 'u'; + } else if (flags[i] == 'a' || flags[i] == 'A') { + if (known_flag_found && known_flag_found != 'a') { + return FLAGS_INVALID; + } + known_flag_found = 'a'; + } else if (flags[i] == 'p' || flags[i] == 'P') { + if (known_flag_found && known_flag_found != 'p') { + return FLAGS_INVALID; + } + known_flag_found = 'p'; + } + } + + return (!known_flag_found || known_flag_found == 'p') ? FLAGS_UNKNOWN : FLAGS_TERMINAL; +} struct ast_dns_record *ast_dns_naptr_alloc(struct ast_dns_query *query, const char *data, const size_t size) { @@ -58,6 +132,7 @@ char *naptr_search_base = (char *)query->result->answer; size_t remaining_size = query->result->answer_size; char *end_of_record; + enum flags_result flags_res; /* * This is bordering on the hackiest thing I've ever written. @@ -162,6 +237,15 @@ return NULL; } + /* We've validated the size of the NAPTR record. Now we can validate + * the individual parts + */ + flags_res = interpret_flags(flags, flags_size); + if (flags_res == FLAGS_INVALID) { + ast_log(LOG_ERROR, "NAPTR Record contained invalid flags %.*s\n", flags_size, flags); + return NULL; + } + naptr = ast_calloc(1, sizeof(*naptr) + size + flags_size + 1 + services_size + 1 + regexp_size + 1 + replacement_size + 1); if (!naptr) { return NULL; Modified: team/group/dns_naptr/tests/test_dns_naptr.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/tests/test_dns_naptr.c?view=diff&rev=433336&r1=433335&r2=433336 ============================================================================== --- team/group/dns_naptr/tests/test_dns_naptr.c (original) +++ team/group/dns_naptr/tests/test_dns_naptr.c Tue Mar 24 14:19:23 2015 @@ -397,10 +397,87 @@ return res; } + +AST_TEST_DEFINE(naptr_resolve_off_nominal_flags) +{ + RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free); + struct naptr_record records[] = { + /* Non-alphanumeric flag */ + { 100, 100, {1, "\x0a"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + /* Mix of valid and non-alphanumeric */ + { 100, 100, {2, "A\x0a"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + /* Invalid combinations of flags */ + { 100, 100, {2, "sa"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "su"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "sp"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "as"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "au"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "ap"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "ua"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "us"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "up"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "pa"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "ps"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + { 100, 100, {2, "pu"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""}, + }; + enum ast_test_result_state res = AST_TEST_PASS; + const struct ast_dns_record *record; + + switch (cmd) { + case TEST_INIT: + info->name = "naptr_resolve_off_nominal_flags"; + info->category = "/main/dns/naptr/"; + info->summary = "Ensure that NAPTR records with invalid flags are not presented in results"; + info->description = "This test defines a set of records where the flags provided are\n" + "invalid in some way. This may be due to providing non-alphanumeric characters or\n" + "by providing clashing flags. The result should be that none of the defined records\n" + "are returned by the resolver\n"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + test_records = records; + num_test_records = ARRAY_LEN(records); + memset(ans_buffer, 0, sizeof(ans_buffer)); + + ast_dns_resolver_register(&naptr_resolver); + + if (ast_dns_resolve("goose.feathers", ns_t_naptr, ns_c_in, &result)) { + ast_test_status_update(test, "Failed to perform DNS resolution, despite using valid inputs\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + if (!result) { + ast_test_status_update(test, "Synchronous DNS resolution failed to set a result\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + record = ast_dns_result_get_records(result); + if (record) { + ast_test_status_update(test, "DNS resolution returned records when it was not expected to\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + +cleanup: + + ast_dns_resolver_unregister(&naptr_resolver); + + test_records = NULL; + num_test_records = 0; + memset(ans_buffer, 0, sizeof(ans_buffer)); + + return res; +} + static int unload_module(void) { AST_TEST_UNREGISTER(naptr_resolve_nominal); AST_TEST_UNREGISTER(naptr_resolve_off_nominal_length); + AST_TEST_UNREGISTER(naptr_resolve_off_nominal_flags); return 0; } @@ -409,6 +486,7 @@ { AST_TEST_REGISTER(naptr_resolve_nominal); AST_TEST_REGISTER(naptr_resolve_off_nominal_length); + AST_TEST_REGISTER(naptr_resolve_off_nominal_flags); return AST_MODULE_LOAD_SUCCESS; } -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits