MQTT: Validate broker IP and escape quotes when displaying

This commit implements address validation for the broker address in the
MQTT configuration page. Additionally, the Type ID, Org ID, Auth Token,
Command Type and Event Type ID fields have quotes escaped (" -> ")
to prevent XSS issues when displaying user-sourced input.
This commit is contained in:
alexstanoev 2017-04-23 17:06:32 +01:00
parent ed47d47155
commit 6b78ee9a4e
2 changed files with 47 additions and 5 deletions

View file

@ -137,6 +137,10 @@ PROCESS(httpd_simple_process, "CC26XX Web Server");
#define REQUEST_TYPE_GET 1 #define REQUEST_TYPE_GET 1
#define REQUEST_TYPE_POST 2 #define REQUEST_TYPE_POST 2
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Temporary buffer for holding escaped HTML used by html_escape_quotes */
#define HTML_ESCAPED_BUFFER_SIZE 128
static char html_escaped_buf[HTML_ESCAPED_BUFFER_SIZE];
/*---------------------------------------------------------------------------*/
static const char *NOT_FOUND = "<html><body bgcolor=\"white\">" static const char *NOT_FOUND = "<html><body bgcolor=\"white\">"
"<center>" "<center>"
"<h1>404 - file not found</h1>" "<h1>404 - file not found</h1>"
@ -305,6 +309,30 @@ url_unescape(const char *src, size_t srclen, char *dst, size_t dstlen)
return i == srclen; return i == srclen;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static char*
html_escape_quotes(const char *src)
{
memset(html_escaped_buf, 0, HTML_ESCAPED_BUFFER_SIZE);
size_t dstpos = 0;
for(size_t i = 0; i < HTML_ESCAPED_BUFFER_SIZE; i++) {
if(src[i] == '\0') {
break;
} else if(src[i] == '"') {
if(dstpos + 6 > HTML_ESCAPED_BUFFER_SIZE) {
break;
}
strcpy(&html_escaped_buf[dstpos], "&quot;");
dstpos += 6;
} else {
html_escaped_buf[dstpos++] = src[i];
}
}
html_escaped_buf[HTML_ESCAPED_BUFFER_SIZE - 1] = '\0';
return html_escaped_buf;
}
/*---------------------------------------------------------------------------*/
void void
httpd_simple_register_post_handler(httpd_simple_post_handler_t *h) httpd_simple_register_post_handler(httpd_simple_post_handler_t *h)
{ {
@ -675,7 +703,8 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s))
config_div_right)); config_div_right));
PT_WAIT_THREAD(&s->generate_pt, PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "value=\"%s\" ", enqueue_chunk(s, 0, "value=\"%s\" ",
cc26xx_web_demo_config.mqtt_config.type_id)); html_escape_quotes(
cc26xx_web_demo_config.mqtt_config.type_id)));
PT_WAIT_THREAD(&s->generate_pt, PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "name=\"type_id\">%s", config_div_close)); enqueue_chunk(s, 0, "name=\"type_id\">%s", config_div_close));
@ -687,7 +716,8 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s))
config_div_right)); config_div_right));
PT_WAIT_THREAD(&s->generate_pt, PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "value=\"%s\" ", enqueue_chunk(s, 0, "value=\"%s\" ",
cc26xx_web_demo_config.mqtt_config.org_id)); html_escape_quotes(
cc26xx_web_demo_config.mqtt_config.org_id)));
PT_WAIT_THREAD(&s->generate_pt, PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "name=\"org_id\">%s", config_div_close)); enqueue_chunk(s, 0, "name=\"org_id\">%s", config_div_close));
@ -711,7 +741,8 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s))
config_div_right)); config_div_right));
PT_WAIT_THREAD(&s->generate_pt, PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "value=\"%s\" ", enqueue_chunk(s, 0, "value=\"%s\" ",
cc26xx_web_demo_config.mqtt_config.cmd_type)); html_escape_quotes(
cc26xx_web_demo_config.mqtt_config.cmd_type)));
PT_WAIT_THREAD(&s->generate_pt, PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "name=\"cmd_type\">%s", enqueue_chunk(s, 0, "name=\"cmd_type\">%s",
config_div_close)); config_div_close));
@ -724,7 +755,8 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s))
config_div_right)); config_div_right));
PT_WAIT_THREAD(&s->generate_pt, PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "value=\"%s\" ", enqueue_chunk(s, 0, "value=\"%s\" ",
cc26xx_web_demo_config.mqtt_config.event_type_id)); html_escape_quotes(
cc26xx_web_demo_config.mqtt_config.event_type_id)));
PT_WAIT_THREAD(&s->generate_pt, PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "name=\"event_type_id\">%s", enqueue_chunk(s, 0, "name=\"event_type_id\">%s",
config_div_close)); config_div_close));

View file

@ -64,6 +64,9 @@
*/ */
static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd"; static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd";
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define ADDRESS_CONVERSION_OK 1
#define ADDRESS_CONVERSION_ERROR 0
/*---------------------------------------------------------------------------*/
/* /*
* A timeout used when waiting for something to happen (e.g. to connect or to * A timeout used when waiting for something to happen (e.g. to connect or to
* disconnect) * disconnect)
@ -356,7 +359,14 @@ ip_addr_post_handler(char *key, int key_len, char *val, int val_len)
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
} }
if(val_len > MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN) { /*
* uiplib_ip6addrconv will immediately start writing into the supplied buffer
* even if it subsequently fails. Thus, pass an intermediate buffer
*/
uip_ip6addr_t tmp_addr;
if(val_len > MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN
|| uiplib_ip6addrconv(val, &tmp_addr) != ADDRESS_CONVERSION_OK) {
/* Ours but bad value */ /* Ours but bad value */
rv = HTTPD_SIMPLE_POST_HANDLER_ERROR; rv = HTTPD_SIMPLE_POST_HANDLER_ERROR;
} else { } else {