aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2008-03-26 23:49:22 +0000
committerChristian Grothoff <christian@grothoff.org>2008-03-26 23:49:22 +0000
commit58107ded22da4953cafad9aece5cd9880036203d (patch)
tree4d07f0d44b01b20691738cfdb768547f5a3375d0
parent6ad8fb11df7a8e44b9a94b620843892cea7cb47a (diff)
downloadlibmicrohttpd-58107ded22da4953cafad9aece5cd9880036203d.tar.gz
libmicrohttpd-58107ded22da4953cafad9aece5cd9880036203d.zip
more complete fix
-rw-r--r--src/daemon/connection.c112
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 */
543static void 552static void
544excessive_data_handler (struct MHD_Connection *connection, 553transmit_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 */
1155static void 1171static int
1156process_header_line (struct MHD_Connection *connection, char *line) 1172process_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 */
1194static void 1212static int
1195process_broken_line (struct MHD_Connection *connection, 1213process_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;