mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
Merge "res_pjsip: Ensure sanitized XML is NULL terminated."
This commit is contained in:
@@ -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>
|
||||||
@@ -3755,6 +3757,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
|
||||||
@@ -3909,6 +3962,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3950,6 +4006,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)
|
|||||||
{
|
{
|
||||||
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, "<", len);
|
strncat(output, "<", remaining);
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
strncat(output, ">", len);
|
strncat(output, ">", remaining);
|
||||||
break;
|
break;
|
||||||
case '"':
|
case '"':
|
||||||
strncat(output, """, len);
|
strncat(output, """, remaining);
|
||||||
break;
|
break;
|
||||||
case '&':
|
case '&':
|
||||||
strncat(output, "&", len);
|
strncat(output, "&", remaining);
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
strncat(output, "'", len);
|
strncat(output, "'", remaining);
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
strncat(output, " ", len);
|
strncat(output, " ", remaining);
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
strncat(output, " ", len);
|
strncat(output, " ", 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)
|
|||||||
{
|
{
|
||||||
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")) {
|
||||||
|
Reference in New Issue
Block a user