diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-02-04 11:44:04 +0000 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-02-04 11:44:04 +0000 |
commit | 101e71a8cf90c3b12c66f5a40436509ea1bc4184 (patch) | |
tree | b57513b85bf0437c9b5e07683b2644b234a47f14 /src/microhttpd | |
parent | b2a05d373cfec12f26bd71de7a1d63741b8b5e15 (diff) | |
download | libmicrohttpd-101e71a8cf90c3b12c66f5a40436509ea1bc4184.tar.gz libmicrohttpd-101e71a8cf90c3b12c66f5a40436509ea1bc4184.zip |
Added some buffer overrun protection, fixed handling of misformed URI with spaces.
Diffstat (limited to 'src/microhttpd')
-rw-r--r-- | src/microhttpd/connection.c | 68 |
1 files changed, 49 insertions, 19 deletions
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 | */ |
1333 | static char * | 1335 | static char * |
1334 | get_next_header_line (struct MHD_Connection *connection) | 1336 | get_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 | */ |
1517 | static int | 1526 | static int |
1518 | parse_initial_message_line (struct MHD_Connection *connection, | 1527 | parse_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) |