aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-02-04 11:44:04 +0000
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-02-04 11:44:04 +0000
commit101e71a8cf90c3b12c66f5a40436509ea1bc4184 (patch)
treeb57513b85bf0437c9b5e07683b2644b234a47f14
parentb2a05d373cfec12f26bd71de7a1d63741b8b5e15 (diff)
downloadlibmicrohttpd-101e71a8cf90c3b12c66f5a40436509ea1bc4184.tar.gz
libmicrohttpd-101e71a8cf90c3b12c66f5a40436509ea1bc4184.zip
Added some buffer overrun protection, fixed handling of misformed URI with spaces.
-rw-r--r--ChangeLog4
-rw-r--r--src/microhttpd/connection.c68
2 files changed, 53 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index d0daf4b1..57f84066 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
1Thu Feb 4 11:38:11 CET 2016
2 Added some buffer overrun protection.
3 Fixed handling of misformed URI with spaces. -EG
4
1Wed Feb 3 15:41:57 CET 2016 5Wed Feb 3 15:41:57 CET 2016
2 Make signal-pipe non-blocking and drain it. -CG 6 Make signal-pipe non-blocking and drain it. -CG
3 7
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index e3f92567..0a9f9885 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1328,10 +1328,13 @@ MHD_connection_update_event_loop_info (struct MHD_Connection *connection)
1328 * return NULL. Otherwise return a pointer to the line. 1328 * return NULL. Otherwise return a pointer to the line.
1329 * 1329 *
1330 * @param connection connection we're processing 1330 * @param connection connection we're processing
1331 * @param[out] line_len pointer to variable that receive
1332 * length of line or NULL
1331 * @return NULL if no full line is available 1333 * @return NULL if no full line is available
1332 */ 1334 */
1333static char * 1335static char *
1334get_next_header_line (struct MHD_Connection *connection) 1336get_next_header_line (struct MHD_Connection *connection,
1337 size_t *line_len)
1335{ 1338{
1336 char *rbuf; 1339 char *rbuf;
1337 size_t pos; 1340 size_t pos;
@@ -1357,8 +1360,13 @@ get_next_header_line (struct MHD_Connection *connection)
1357 : MHD_HTTP_REQUEST_URI_TOO_LONG, 1360 : MHD_HTTP_REQUEST_URI_TOO_LONG,
1358 REQUEST_TOO_BIG); 1361 REQUEST_TOO_BIG);
1359 } 1362 }
1363 if (line_len)
1364 *line_len = 0;
1360 return NULL; 1365 return NULL;
1361 } 1366 }
1367
1368 if (line_len)
1369 *line_len = pos;
1362 /* found, check if we have proper LFCR */ 1370 /* found, check if we have proper LFCR */
1363 if (('\r' == rbuf[pos]) && ('\n' == rbuf[pos + 1])) 1371 if (('\r' == rbuf[pos]) && ('\n' == rbuf[pos + 1]))
1364 rbuf[pos++] = '\0'; /* skip both r and n */ 1372 rbuf[pos++] = '\0'; /* skip both r and n */
@@ -1512,11 +1520,13 @@ parse_cookie_header (struct MHD_Connection *connection)
1512 * 1520 *
1513 * @param connection the connection (updated) 1521 * @param connection the connection (updated)
1514 * @param line the first line 1522 * @param line the first line
1523 * @param line_len length of the first line
1515 * @return #MHD_YES if the line is ok, #MHD_NO if it is malformed 1524 * @return #MHD_YES if the line is ok, #MHD_NO if it is malformed
1516 */ 1525 */
1517static int 1526static int
1518parse_initial_message_line (struct MHD_Connection *connection, 1527parse_initial_message_line (struct MHD_Connection *connection,
1519 char *line) 1528 char *line,
1529 size_t line_len)
1520{ 1530{
1521 struct MHD_Daemon *daemon = connection->daemon; 1531 struct MHD_Daemon *daemon = connection->daemon;
1522 char *uri; 1532 char *uri;
@@ -1524,25 +1534,48 @@ parse_initial_message_line (struct MHD_Connection *connection,
1524 char *args; 1534 char *args;
1525 unsigned int unused_num_headers; 1535 unsigned int unused_num_headers;
1526 1536
1527 if (NULL == (uri = strchr (line, ' '))) 1537 if (NULL == (uri = memchr (line, ' ', line_len)))
1528 return MHD_NO; /* serious error */ 1538 return MHD_NO; /* serious error */
1529 uri[0] = '\0'; 1539 uri[0] = '\0';
1530 connection->method = line; 1540 connection->method = line;
1531 uri++; 1541 uri++;
1532 while (' ' == uri[0]) 1542 /* Skip any spaces. Not required by standard but allow
1543 to be more tolerant. */
1544 while (' ' == uri[0] && (size_t)(uri - line) < line_len)
1533 uri++; 1545 uri++;
1534 http_version = strchr (uri, ' '); 1546 if (uri - line == line_len)
1535 if (NULL != http_version)
1536 { 1547 {
1537 http_version[0] = '\0'; 1548 uri = "";
1538 http_version++; 1549 connection->version = "";
1550 args = NULL;
1551 }
1552 else
1553 {
1554 /* Search from back to accept misformed URI with space */
1555 http_version = line + line_len - 1;
1556 /* Skip any trailing spaces */
1557 while (' ' == http_version[0] && http_version > uri)
1558 http_version--;
1559 /* Find first space in reverse direction */
1560 while (' ' != http_version[0] && http_version > uri)
1561 http_version--;
1562 if (http_version > uri)
1563 {
1564 http_version[0] = '\0';
1565 connection->version = http_version + 1;
1566 args = memchr(uri, '?', http_version - uri);
1567 }
1568 else
1569 {
1570 connection->version = "";
1571 args = memchr(uri, '?', line_len - (uri - line));
1572 }
1539 } 1573 }
1540 if (NULL != daemon->uri_log_callback) 1574 if (NULL != daemon->uri_log_callback)
1541 connection->client_context 1575 connection->client_context
1542 = daemon->uri_log_callback (daemon->uri_log_callback_cls, 1576 = daemon->uri_log_callback (daemon->uri_log_callback_cls,
1543 uri, 1577 uri,
1544 connection); 1578 connection);
1545 args = strchr (uri, '?');
1546 if (NULL != args) 1579 if (NULL != args)
1547 { 1580 {
1548 args[0] = '\0'; 1581 args[0] = '\0';
@@ -1558,10 +1591,6 @@ parse_initial_message_line (struct MHD_Connection *connection,
1558 connection, 1591 connection,
1559 uri); 1592 uri);
1560 connection->url = uri; 1593 connection->url = uri;
1561 if (NULL == http_version)
1562 connection->version = "";
1563 else
1564 connection->version = http_version;
1565 return MHD_YES; 1594 return MHD_YES;
1566} 1595}
1567 1596
@@ -2416,6 +2445,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2416 unsigned int timeout; 2445 unsigned int timeout;
2417 const char *end; 2446 const char *end;
2418 char *line; 2447 char *line;
2448 size_t line_len;
2419 int client_close; 2449 int client_close;
2420 2450
2421 connection->in_idle = MHD_YES; 2451 connection->in_idle = MHD_YES;
@@ -2430,7 +2460,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2430 switch (connection->state) 2460 switch (connection->state)
2431 { 2461 {
2432 case MHD_CONNECTION_INIT: 2462 case MHD_CONNECTION_INIT:
2433 line = get_next_header_line (connection); 2463 line = get_next_header_line (connection, &line_len);
2434 /* Check for empty string, as we might want 2464 /* Check for empty string, as we might want
2435 to tolerate 'spurious' empty lines; also 2465 to tolerate 'spurious' empty lines; also
2436 NULL means we didn't get a full line yet. */ 2466 NULL means we didn't get a full line yet. */
@@ -2447,13 +2477,13 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2447 } 2477 }
2448 break; 2478 break;
2449 } 2479 }
2450 if (MHD_NO == parse_initial_message_line (connection, line)) 2480 if (MHD_NO == parse_initial_message_line (connection, line, line_len))
2451 CONNECTION_CLOSE_ERROR (connection, NULL); 2481 CONNECTION_CLOSE_ERROR (connection, NULL);
2452 else 2482 else
2453 connection->state = MHD_CONNECTION_URL_RECEIVED; 2483 connection->state = MHD_CONNECTION_URL_RECEIVED;
2454 continue; 2484 continue;
2455 case MHD_CONNECTION_URL_RECEIVED: 2485 case MHD_CONNECTION_URL_RECEIVED:
2456 line = get_next_header_line (connection); 2486 line = get_next_header_line (connection, NULL);
2457 if (NULL == line) 2487 if (NULL == line)
2458 { 2488 {
2459 if (MHD_CONNECTION_URL_RECEIVED != connection->state) 2489 if (MHD_CONNECTION_URL_RECEIVED != connection->state)
@@ -2481,7 +2511,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2481 connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED; 2511 connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED;
2482 continue; 2512 continue;
2483 case MHD_CONNECTION_HEADER_PART_RECEIVED: 2513 case MHD_CONNECTION_HEADER_PART_RECEIVED:
2484 line = get_next_header_line (connection); 2514 line = get_next_header_line (connection, NULL);
2485 if (NULL == line) 2515 if (NULL == line)
2486 { 2516 {
2487 if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED) 2517 if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
@@ -2571,7 +2601,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2571 } 2601 }
2572 break; 2602 break;
2573 case MHD_CONNECTION_BODY_RECEIVED: 2603 case MHD_CONNECTION_BODY_RECEIVED:
2574 line = get_next_header_line (connection); 2604 line = get_next_header_line (connection, NULL);
2575 if (NULL == line) 2605 if (NULL == line)
2576 { 2606 {
2577 if (connection->state != MHD_CONNECTION_BODY_RECEIVED) 2607 if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
@@ -2599,7 +2629,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2599 connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED; 2629 connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED;
2600 continue; 2630 continue;
2601 case MHD_CONNECTION_FOOTER_PART_RECEIVED: 2631 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
2602 line = get_next_header_line (connection); 2632 line = get_next_header_line (connection, NULL);
2603 if (NULL == line) 2633 if (NULL == line)
2604 { 2634 {
2605 if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED) 2635 if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)