diff options
author | Christian Grothoff <christian@grothoff.org> | 2008-03-26 23:49:22 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2008-03-26 23:49:22 +0000 |
commit | 58107ded22da4953cafad9aece5cd9880036203d (patch) | |
tree | 4d07f0d44b01b20691738cfdb768547f5a3375d0 | |
parent | 6ad8fb11df7a8e44b9a94b620843892cea7cb47a (diff) | |
download | libmicrohttpd-58107ded22da4953cafad9aece5cd9880036203d.tar.gz libmicrohttpd-58107ded22da4953cafad9aece5cd9880036203d.zip |
more complete fix
-rw-r--r-- | src/daemon/connection.c | 112 |
1 files changed, 78 insertions, 34 deletions
diff --git a/src/daemon/connection.c b/src/daemon/connection.c index 70401e02..6964104c 100644 --- a/src/daemon/connection.c +++ b/src/daemon/connection.c | |||
@@ -61,6 +61,15 @@ | |||
61 | */ | 61 | */ |
62 | #define REQUEST_LACKS_HOST "" | 62 | #define REQUEST_LACKS_HOST "" |
63 | 63 | ||
64 | /** | ||
65 | * Response text used when the request (http header) is | ||
66 | * malformed. | ||
67 | * | ||
68 | * Intentionally empty here to keep our memory footprint | ||
69 | * minimal. | ||
70 | */ | ||
71 | #define REQUEST_MALFORMED "" | ||
72 | |||
64 | #define EXTRA_CHECKS MHD_YES | 73 | #define EXTRA_CHECKS MHD_YES |
65 | 74 | ||
66 | #if EXTRA_CHECKS | 75 | #if EXTRA_CHECKS |
@@ -534,15 +543,16 @@ build_header_response (struct MHD_Connection *connection) | |||
534 | } | 543 | } |
535 | 544 | ||
536 | /** | 545 | /** |
537 | * We ran out of memory processing the | 546 | * We encountered an error processing the request. |
538 | * header. Handle it properly by stopping to read data | 547 | * Handle it properly by stopping to read data |
539 | * and sending a HTTP 413 or HTTP 414 response. | 548 | * and sending the indicated response code and message. |
540 | * | 549 | * |
541 | * @param status_code the response code to send (413 or 414) | 550 | * @param status_code the response code to send (400, 413 or 414) |
542 | */ | 551 | */ |
543 | static void | 552 | static void |
544 | excessive_data_handler (struct MHD_Connection *connection, | 553 | transmit_error_response (struct MHD_Connection *connection, |
545 | unsigned int status_code) | 554 | unsigned int status_code, |
555 | const char * message) | ||
546 | { | 556 | { |
547 | struct MHD_Response *response; | 557 | struct MHD_Response *response; |
548 | 558 | ||
@@ -551,10 +561,12 @@ excessive_data_handler (struct MHD_Connection *connection, | |||
551 | connection->read_closed = MHD_YES; | 561 | connection->read_closed = MHD_YES; |
552 | #if HAVE_MESSAGES | 562 | #if HAVE_MESSAGES |
553 | MHD_DLOG (connection->daemon, | 563 | MHD_DLOG (connection->daemon, |
554 | "Received excessively long header, closing connection.\n"); | 564 | "Error %u (`%s') processing request, closing connection.\n", |
565 | status_code, | ||
566 | message); | ||
555 | #endif | 567 | #endif |
556 | response = MHD_create_response_from_data (strlen (REQUEST_TOO_BIG), | 568 | response = MHD_create_response_from_data (strlen (message), |
557 | REQUEST_TOO_BIG, MHD_NO, MHD_NO); | 569 | (void*)message, MHD_NO, MHD_NO); |
558 | MHD_queue_response (connection, status_code, response); | 570 | MHD_queue_response (connection, status_code, response); |
559 | EXTRA_CHECK (connection->response != NULL); | 571 | EXTRA_CHECK (connection->response != NULL); |
560 | MHD_destroy_response (response); | 572 | MHD_destroy_response (response); |
@@ -632,10 +644,11 @@ MHD_connection_get_fdset (struct MHD_Connection *connection, | |||
632 | if ((connection->read_buffer_offset == connection->read_buffer_size) | 644 | if ((connection->read_buffer_offset == connection->read_buffer_size) |
633 | && (MHD_NO == try_grow_read_buffer (connection))) | 645 | && (MHD_NO == try_grow_read_buffer (connection))) |
634 | { | 646 | { |
635 | excessive_data_handler (connection, | 647 | transmit_error_response (connection, |
636 | (connection->url != NULL) | 648 | (connection->url != NULL) |
637 | ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE | 649 | ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE |
638 | : MHD_HTTP_REQUEST_URI_TOO_LONG); | 650 | : MHD_HTTP_REQUEST_URI_TOO_LONG, |
651 | REQUEST_TOO_BIG); | ||
639 | continue; | 652 | continue; |
640 | } | 653 | } |
641 | if (MHD_NO == connection->read_closed) | 654 | if (MHD_NO == connection->read_closed) |
@@ -748,10 +761,11 @@ get_next_header_line (struct MHD_Connection *connection) | |||
748 | MHD_BUF_INC_SIZE); | 761 | MHD_BUF_INC_SIZE); |
749 | if (rbuf == NULL) | 762 | if (rbuf == NULL) |
750 | { | 763 | { |
751 | excessive_data_handler (connection, | 764 | transmit_error_response (connection, |
752 | (connection->url != NULL) | 765 | (connection->url != NULL) |
753 | ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE | 766 | ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE |
754 | : MHD_HTTP_REQUEST_URI_TOO_LONG); | 767 | : MHD_HTTP_REQUEST_URI_TOO_LONG, |
768 | REQUEST_TOO_BIG); | ||
755 | } | 769 | } |
756 | else | 770 | else |
757 | { | 771 | { |
@@ -789,7 +803,8 @@ connection_add_header (struct MHD_Connection *connection, | |||
789 | MHD_DLOG (connection->daemon, | 803 | MHD_DLOG (connection->daemon, |
790 | "Not enough memory to allocate header record!\n"); | 804 | "Not enough memory to allocate header record!\n"); |
791 | #endif | 805 | #endif |
792 | excessive_data_handler (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | 806 | transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, |
807 | REQUEST_TOO_BIG); | ||
793 | return MHD_NO; | 808 | return MHD_NO; |
794 | } | 809 | } |
795 | hdr->next = connection->headers_received; | 810 | hdr->next = connection->headers_received; |
@@ -856,7 +871,8 @@ parse_cookie_header (struct MHD_Connection *connection) | |||
856 | #if HAVE_MESSAGES | 871 | #if HAVE_MESSAGES |
857 | MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n"); | 872 | MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n"); |
858 | #endif | 873 | #endif |
859 | excessive_data_handler (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | 874 | transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, |
875 | REQUEST_TOO_BIG); | ||
860 | return MHD_NO; | 876 | return MHD_NO; |
861 | } | 877 | } |
862 | memcpy (cpy, hdr, strlen (hdr) + 1); | 878 | memcpy (cpy, hdr, strlen (hdr) + 1); |
@@ -1152,7 +1168,7 @@ do_read (struct MHD_Connection *connection) | |||
1152 | * header (or footer). Validate (check for ":") and prepare | 1168 | * header (or footer). Validate (check for ":") and prepare |
1153 | * to process. | 1169 | * to process. |
1154 | */ | 1170 | */ |
1155 | static void | 1171 | static int |
1156 | process_header_line (struct MHD_Connection *connection, char *line) | 1172 | process_header_line (struct MHD_Connection *connection, char *line) |
1157 | { | 1173 | { |
1158 | char *colon; | 1174 | char *colon; |
@@ -1167,7 +1183,7 @@ process_header_line (struct MHD_Connection *connection, char *line) | |||
1167 | "Received malformed line (no colon), closing connection.\n"); | 1183 | "Received malformed line (no colon), closing connection.\n"); |
1168 | #endif | 1184 | #endif |
1169 | connection->state = MHD_CONNECTION_CLOSED; | 1185 | connection->state = MHD_CONNECTION_CLOSED; |
1170 | return; | 1186 | return MHD_NO; |
1171 | } | 1187 | } |
1172 | /* zero-terminate header */ | 1188 | /* zero-terminate header */ |
1173 | colon[0] = '\0'; | 1189 | colon[0] = '\0'; |
@@ -1181,6 +1197,7 @@ process_header_line (struct MHD_Connection *connection, char *line) | |||
1181 | with a space...) */ | 1197 | with a space...) */ |
1182 | connection->last = line; | 1198 | connection->last = line; |
1183 | connection->colon = colon; | 1199 | connection->colon = colon; |
1200 | return MHD_YES; | ||
1184 | } | 1201 | } |
1185 | 1202 | ||
1186 | /** | 1203 | /** |
@@ -1190,8 +1207,9 @@ process_header_line (struct MHD_Connection *connection, char *line) | |||
1190 | * @param line the current input line | 1207 | * @param line the current input line |
1191 | * @param kind if the line is complete, add a header | 1208 | * @param kind if the line is complete, add a header |
1192 | * of the given kind | 1209 | * of the given kind |
1210 | * @return MHD_YES if the line was processed successfully | ||
1193 | */ | 1211 | */ |
1194 | static void | 1212 | static int |
1195 | process_broken_line (struct MHD_Connection *connection, | 1213 | process_broken_line (struct MHD_Connection *connection, |
1196 | char *line, enum MHD_ValueKind kind) | 1214 | char *line, enum MHD_ValueKind kind) |
1197 | { | 1215 | { |
@@ -1209,28 +1227,38 @@ process_broken_line (struct MHD_Connection *connection, | |||
1209 | strlen (line) + strlen (last) + 1); | 1227 | strlen (line) + strlen (last) + 1); |
1210 | if (last == NULL) | 1228 | if (last == NULL) |
1211 | { | 1229 | { |
1212 | excessive_data_handler (connection, | 1230 | transmit_error_response (connection, |
1213 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | 1231 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, |
1214 | return; | 1232 | REQUEST_TOO_BIG); |
1233 | return MHD_NO; | ||
1215 | } | 1234 | } |
1216 | tmp = line; | 1235 | tmp = line; |
1217 | while ((tmp[0] == ' ') || (tmp[0] == '\t')) | 1236 | while ((tmp[0] == ' ') || (tmp[0] == '\t')) |
1218 | tmp++; /* skip whitespace at start of 2nd line */ | 1237 | tmp++; /* skip whitespace at start of 2nd line */ |
1219 | strcat (last, tmp); | 1238 | strcat (last, tmp); |
1220 | connection->last = last; | 1239 | connection->last = last; |
1221 | return; /* possibly more than 2 lines... */ | 1240 | return MHD_YES; /* possibly more than 2 lines... */ |
1222 | } | 1241 | } |
1223 | if ( (last != NULL) && | 1242 | EXTRA_CHECK ( (last != NULL) && (connection->colon != NULL) ); |
1224 | (connection->colon != NULL) && | 1243 | if ( (MHD_NO == connection_add_header (connection, |
1225 | (MHD_NO == connection_add_header (connection, | ||
1226 | last, connection->colon, kind)) ) | 1244 | last, connection->colon, kind)) ) |
1227 | { | 1245 | { |
1228 | excessive_data_handler (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | 1246 | transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, |
1229 | return; | 1247 | REQUEST_TOO_BIG); |
1248 | return MHD_NO; | ||
1230 | } | 1249 | } |
1231 | /* we still have the current line to deal with... */ | 1250 | /* we still have the current line to deal with... */ |
1232 | if (strlen (line) != 0) | 1251 | if (strlen (line) != 0) |
1233 | process_header_line (connection, line); | 1252 | { |
1253 | if (MHD_NO == process_header_line (connection, line)) | ||
1254 | { | ||
1255 | transmit_error_response(connection, | ||
1256 | MHD_HTTP_BAD_REQUEST, | ||
1257 | REQUEST_MALFORMED); | ||
1258 | return MHD_NO; | ||
1259 | } | ||
1260 | } | ||
1261 | return MHD_YES; | ||
1234 | } | 1262 | } |
1235 | 1263 | ||
1236 | /** | 1264 | /** |
@@ -1613,14 +1641,22 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1613 | connection->state = MHD_CONNECTION_HEADERS_RECEIVED; | 1641 | connection->state = MHD_CONNECTION_HEADERS_RECEIVED; |
1614 | continue; | 1642 | continue; |
1615 | } | 1643 | } |
1616 | process_header_line (connection, line); | 1644 | if (MHD_NO == process_header_line (connection, line)) |
1645 | { | ||
1646 | transmit_error_response(connection, | ||
1647 | MHD_HTTP_BAD_REQUEST, | ||
1648 | REQUEST_MALFORMED); | ||
1649 | break; | ||
1650 | } | ||
1617 | connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED; | 1651 | connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED; |
1618 | continue; | 1652 | continue; |
1619 | case MHD_CONNECTION_HEADER_PART_RECEIVED: | 1653 | case MHD_CONNECTION_HEADER_PART_RECEIVED: |
1620 | line = get_next_header_line (connection); | 1654 | line = get_next_header_line (connection); |
1621 | if (line == NULL) | 1655 | if (line == NULL) |
1622 | break; | 1656 | break; |
1623 | process_broken_line (connection, line, MHD_HEADER_KIND); | 1657 | if (MHD_NO == |
1658 | process_broken_line (connection, line, MHD_HEADER_KIND)) | ||
1659 | continue; | ||
1624 | if (strlen (line) == 0) | 1660 | if (strlen (line) == 0) |
1625 | { | 1661 | { |
1626 | connection->state = MHD_CONNECTION_HEADERS_RECEIVED; | 1662 | connection->state = MHD_CONNECTION_HEADERS_RECEIVED; |
@@ -1682,14 +1718,22 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1682 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 1718 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; |
1683 | continue; | 1719 | continue; |
1684 | } | 1720 | } |
1685 | process_header_line (connection, line); | 1721 | if (MHD_NO == process_header_line (connection, line)) |
1722 | { | ||
1723 | transmit_error_response(connection, | ||
1724 | MHD_HTTP_BAD_REQUEST, | ||
1725 | REQUEST_MALFORMED); | ||
1726 | break; | ||
1727 | } | ||
1686 | connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED; | 1728 | connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED; |
1687 | continue; | 1729 | continue; |
1688 | case MHD_CONNECTION_FOOTER_PART_RECEIVED: | 1730 | case MHD_CONNECTION_FOOTER_PART_RECEIVED: |
1689 | line = get_next_header_line (connection); | 1731 | line = get_next_header_line (connection); |
1690 | if (line == NULL) | 1732 | if (line == NULL) |
1691 | break; | 1733 | break; |
1692 | process_broken_line (connection, line, MHD_FOOTER_KIND); | 1734 | if (MHD_NO == |
1735 | process_broken_line (connection, line, MHD_FOOTER_KIND)) | ||
1736 | continue; | ||
1693 | if (strlen (line) == 0) | 1737 | if (strlen (line) == 0) |
1694 | { | 1738 | { |
1695 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 1739 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; |