Skip to content
Snippets Groups Projects
Commit 4b1bd40d authored by Joshua Colp's avatar Joshua Colp Committed by Gerrit Code Review
Browse files

Merge "res_pjsip: Ensure sanitized XML is NULL terminated." into 13

parents 9182c9e4 8521a863
No related branches found
No related tags found
No related merge requests found
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#include "asterisk/file.h" #include "asterisk/file.h"
#include "asterisk/cli.h" #include "asterisk/cli.h"
#include "asterisk/res_pjsip_cli.h" #include "asterisk/res_pjsip_cli.h"
#include "asterisk/test.h"
#include "asterisk/res_pjsip_presence_xml.h"
/*** MODULEINFO /*** MODULEINFO
<depend>pjproject</depend> <depend>pjproject</depend>
...@@ -3701,6 +3703,57 @@ static void remove_request_headers(pjsip_endpoint *endpt) ...@@ -3701,6 +3703,57 @@ static void remove_request_headers(pjsip_endpoint *endpt)
} }
} }
AST_TEST_DEFINE(xml_sanitization_end_null)
{
char sanitized[8];
switch (cmd) {
case TEST_INIT:
info->name = "xml_sanitization_end_null";
info->category = "/res/res_pjsip/";
info->summary = "Ensure XML sanitization works as expected with a long string";
info->description = "This test sanitizes a string which exceeds the output\n"
"buffer size. Once done the string is confirmed to be NULL terminated.";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
ast_sip_sanitize_xml("aaaaaaaaaaaa", sanitized, sizeof(sanitized));
if (sanitized[7] != '\0') {
ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n");
return AST_TEST_FAIL;
}
return AST_TEST_PASS;
}
AST_TEST_DEFINE(xml_sanitization_exceeds_buffer)
{
char sanitized[8];
switch (cmd) {
case TEST_INIT:
info->name = "xml_sanitization_exceeds_buffer";
info->category = "/res/res_pjsip/";
info->summary = "Ensure XML sanitization does not exceed buffer when output won't fit";
info->description = "This test sanitizes a string which before sanitization would\n"
"fit within the output buffer. After sanitization, however, the string would\n"
"exceed the buffer. Once done the string is confirmed to be NULL terminated.";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
ast_sip_sanitize_xml("<><><>&", sanitized, sizeof(sanitized));
if (sanitized[7] != '\0') {
ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n");
return AST_TEST_FAIL;
}
return AST_TEST_PASS;
}
/*! /*!
* \internal * \internal
* \brief Reload configuration within a PJSIP thread * \brief Reload configuration within a PJSIP thread
...@@ -3870,6 +3923,9 @@ static int load_module(void) ...@@ -3870,6 +3923,9 @@ static int load_module(void)
ast_res_pjsip_init_options_handling(0); ast_res_pjsip_init_options_handling(0);
ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands)); ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
AST_TEST_REGISTER(xml_sanitization_end_null);
AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
return AST_MODULE_LOAD_SUCCESS; return AST_MODULE_LOAD_SUCCESS;
} }
...@@ -3912,6 +3968,9 @@ static int unload_pjsip(void *data) ...@@ -3912,6 +3968,9 @@ static int unload_pjsip(void *data)
static int unload_module(void) static int unload_module(void)
{ {
AST_TEST_UNREGISTER(xml_sanitization_end_null);
AST_TEST_UNREGISTER(xml_sanitization_exceeds_buffer);
/* The thread this is called from cannot call PJSIP/PJLIB functions, /* The thread this is called from cannot call PJSIP/PJLIB functions,
* so we have to push the work to the threadpool to handle * so we have to push the work to the threadpool to handle
*/ */
......
...@@ -30,45 +30,54 @@ void ast_sip_sanitize_xml(const char *input, char *output, size_t len) ...@@ -30,45 +30,54 @@ void ast_sip_sanitize_xml(const char *input, char *output, size_t len)
{ {
char *copy = ast_strdupa(input); char *copy = ast_strdupa(input);
char *break_point; char *break_point;
size_t remaining = len - 1;
output[0] = '\0'; output[0] = '\0';
while ((break_point = strpbrk(copy, "<>\"&'\n\r"))) { while ((break_point = strpbrk(copy, "<>\"&'\n\r")) && remaining) {
char to_escape = *break_point; char to_escape = *break_point;
*break_point = '\0'; *break_point = '\0';
strncat(output, copy, len); strncat(output, copy, remaining);
/* The strncat function will write remaining+1 if the string length is
* equal to or greater than the size provided to it. We take this into
* account by subtracting 1, which ensures that the NULL byte is written
* inside of the provided buffer.
*/
remaining = len - strlen(output) - 1;
switch (to_escape) { switch (to_escape) {
case '<': case '<':
strncat(output, "&lt;", len); strncat(output, "&lt;", remaining);
break; break;
case '>': case '>':
strncat(output, "&gt;", len); strncat(output, "&gt;", remaining);
break; break;
case '"': case '"':
strncat(output, "&quot;", len); strncat(output, "&quot;", remaining);
break; break;
case '&': case '&':
strncat(output, "&amp;", len); strncat(output, "&amp;", remaining);
break; break;
case '\'': case '\'':
strncat(output, "&apos;", len); strncat(output, "&apos;", remaining);
break; break;
case '\r': case '\r':
strncat(output, "&#13;", len); strncat(output, "&#13;", remaining);
break; break;
case '\n': case '\n':
strncat(output, "&#10;", len); strncat(output, "&#10;", remaining);
break; break;
}; };
copy = break_point + 1; copy = break_point + 1;
remaining = len - strlen(output) - 1;
} }
/* Be sure to copy everything after the final bracket */ /* Be sure to copy everything after the final bracket */
if (*copy) { if (*copy && remaining) {
strncat(output, copy, len); strncat(output, copy, remaining);
} }
} }
......
...@@ -40,7 +40,7 @@ static int pidf_supplement_body(void *body, void *data) ...@@ -40,7 +40,7 @@ static int pidf_supplement_body(void *body, void *data)
{ {
struct ast_sip_exten_state_data *state_data = data; struct ast_sip_exten_state_data *state_data = data;
pj_xml_node *node; pj_xml_node *node;
char sanitized[256]; char sanitized[1024];
if (ast_strlen_zero(state_data->user_agent) || if (ast_strlen_zero(state_data->user_agent) ||
!strstr(state_data->user_agent, "digium")) { !strstr(state_data->user_agent, "digium")) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment