diff options
Diffstat (limited to 'src/daemon/connection.c')
-rw-r--r-- | src/daemon/connection.c | 69 |
1 files changed, 50 insertions, 19 deletions
diff --git a/src/daemon/connection.c b/src/daemon/connection.c index 272fb802..ec261963 100644 --- a/src/daemon/connection.c +++ b/src/daemon/connection.c | |||
@@ -41,6 +41,12 @@ | |||
41 | #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n" | 41 | #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n" |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * Response used when the request (http header) is too big to | ||
45 | * be processed. | ||
46 | */ | ||
47 | #define REQUEST_TOO_BIG "" | ||
48 | |||
49 | /** | ||
44 | * Get all of the headers from the request. | 50 | * Get all of the headers from the request. |
45 | * | 51 | * |
46 | * @param iterator callback to call on each header; | 52 | * @param iterator callback to call on each header; |
@@ -146,16 +152,14 @@ MHD_connection_get_fdset(struct MHD_Connection * connection, | |||
146 | fd = connection->socket_fd; | 152 | fd = connection->socket_fd; |
147 | if (fd == -1) | 153 | if (fd == -1) |
148 | return MHD_YES; | 154 | return MHD_YES; |
149 | if ( (connection->read_close == 0) && | 155 | if ( (connection->read_close == MHD_NO) && |
150 | ( (connection->headersReceived == 0) || | 156 | ( (connection->headersReceived == 0) || |
151 | (connection->readLoc < connection->read_buffer_size) ) ) { | 157 | (connection->readLoc < connection->read_buffer_size) ) ) { |
152 | FD_SET(fd, read_fd_set); | 158 | FD_SET(fd, read_fd_set); |
153 | if (fd > *max_fd) | 159 | if (fd > *max_fd) |
154 | *max_fd = fd; | 160 | *max_fd = fd; |
155 | } else { | 161 | } else { |
156 | 162 | if ( (connection->read_close == MHD_NO) && | |
157 | |||
158 | if ( (connection->read_close == 0) && | ||
159 | ( (connection->headersReceived == 1) && | 163 | ( (connection->headersReceived == 1) && |
160 | (connection->post_processed == MHD_NO) && | 164 | (connection->post_processed == MHD_NO) && |
161 | (connection->readLoc == connection->read_buffer_size) ) ) { | 165 | (connection->readLoc == connection->read_buffer_size) ) ) { |
@@ -188,17 +192,32 @@ MHD_connection_get_fdset(struct MHD_Connection * connection, | |||
188 | 192 | ||
189 | /** | 193 | /** |
190 | * We ran out of memory processing the | 194 | * We ran out of memory processing the |
191 | * header. Handle it properly. | 195 | * header. Handle it properly by stopping to read data |
196 | * and sending a HTTP 413 or HTTP 414 response. | ||
197 | * | ||
198 | * @param status_code the response code to send (413 or 414) | ||
192 | */ | 199 | */ |
193 | static void | 200 | static void |
194 | MHD_excessive_header_handler(struct MHD_Connection * connection) { | 201 | MHD_excessive_data_handler(struct MHD_Connection * connection, |
202 | unsigned int status_code) { | ||
203 | struct MHD_Response * response; | ||
204 | |||
195 | /* die, header far too long to be reasonable; | 205 | /* die, header far too long to be reasonable; |
196 | FIXME: send proper response to client | 206 | FIXME: send proper response to client |
197 | (stop reading, queue proper response) */ | 207 | (stop reading, queue proper response) */ |
208 | connection->read_close = MHD_YES; | ||
209 | connection->headersReceived = MHD_YES; | ||
210 | connection->bodyReceived = MHD_YES; | ||
198 | MHD_DLOG(connection->daemon, | 211 | MHD_DLOG(connection->daemon, |
199 | "Received excessively long header line, closing connection.\n"); | 212 | "Received excessively long header, closing connection.\n"); |
200 | CLOSE(connection->socket_fd); | 213 | response = MHD_create_response_from_data(strlen(REQUEST_TOO_BIG), |
201 | connection->socket_fd = -1; | 214 | REQUEST_TOO_BIG, |
215 | MHD_NO, | ||
216 | MHD_NO); | ||
217 | MHD_queue_response(connection, | ||
218 | status_code, | ||
219 | response); | ||
220 | MHD_destroy_response(response); | ||
202 | } | 221 | } |
203 | 222 | ||
204 | /** | 223 | /** |
@@ -230,7 +249,10 @@ MHD_get_next_header_line(struct MHD_Connection * connection) { | |||
230 | connection->read_buffer_size, | 249 | connection->read_buffer_size, |
231 | connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE); | 250 | connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE); |
232 | if (rbuf == NULL) { | 251 | if (rbuf == NULL) { |
233 | MHD_excessive_header_handler(connection); | 252 | MHD_excessive_data_handler(connection, |
253 | (connection->url != NULL) | ||
254 | ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE | ||
255 | : MHD_HTTP_REQUEST_URI_TOO_LONG); | ||
234 | } else { | 256 | } else { |
235 | connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; | 257 | connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; |
236 | connection->read_buffer = rbuf; | 258 | connection->read_buffer = rbuf; |
@@ -265,7 +287,8 @@ MHD_connection_add_header(struct MHD_Connection * connection, | |||
265 | if (hdr == NULL) { | 287 | if (hdr == NULL) { |
266 | MHD_DLOG(connection->daemon, | 288 | MHD_DLOG(connection->daemon, |
267 | "Not enough memory to allocate header record!\n"); | 289 | "Not enough memory to allocate header record!\n"); |
268 | MHD_excessive_header_handler(connection); | 290 | MHD_excessive_data_handler(connection, |
291 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | ||
269 | return MHD_NO; | 292 | return MHD_NO; |
270 | } | 293 | } |
271 | hdr->next = connection->headers_received; | 294 | hdr->next = connection->headers_received; |
@@ -360,7 +383,8 @@ MHD_parse_cookie_header(struct MHD_Connection * connection) { | |||
360 | if (cpy == NULL) { | 383 | if (cpy == NULL) { |
361 | MHD_DLOG(connection->daemon, | 384 | MHD_DLOG(connection->daemon, |
362 | "Not enough memory to parse cookies!\n"); | 385 | "Not enough memory to parse cookies!\n"); |
363 | MHD_excessive_header_handler(connection); | 386 | MHD_excessive_data_handler(connection, |
387 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | ||
364 | return MHD_NO; | 388 | return MHD_NO; |
365 | } | 389 | } |
366 | memcpy(cpy, | 390 | memcpy(cpy, |
@@ -483,7 +507,8 @@ MHD_parse_connection_headers(struct MHD_Connection * connection) { | |||
483 | strlen(last)+1, | 507 | strlen(last)+1, |
484 | strlen(line) + strlen(last) + 1); | 508 | strlen(line) + strlen(last) + 1); |
485 | if (last == NULL) { | 509 | if (last == NULL) { |
486 | MHD_excessive_header_handler(connection); | 510 | MHD_excessive_data_handler(connection, |
511 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | ||
487 | break; | 512 | break; |
488 | } | 513 | } |
489 | tmp = line; | 514 | tmp = line; |
@@ -620,8 +645,10 @@ MHD_test_post_data(struct MHD_Connection * connection) { | |||
620 | const char * encoding; | 645 | const char * encoding; |
621 | void * buf; | 646 | void * buf; |
622 | 647 | ||
623 | if (0 != strcasecmp(connection->method, | 648 | if ( (connection->method == NULL) || |
624 | MHD_HTTP_METHOD_POST)) | 649 | (connection->response != NULL) || |
650 | (0 != strcasecmp(connection->method, | ||
651 | MHD_HTTP_METHOD_POST)) ) | ||
625 | return MHD_NO; | 652 | return MHD_NO; |
626 | encoding = MHD_lookup_connection_value(connection, | 653 | encoding = MHD_lookup_connection_value(connection, |
627 | MHD_HEADER_KIND, | 654 | MHD_HEADER_KIND, |
@@ -711,6 +738,8 @@ MHD_call_connection_handler(struct MHD_Connection * connection) { | |||
711 | struct MHD_Access_Handler * ah; | 738 | struct MHD_Access_Handler * ah; |
712 | unsigned int processed; | 739 | unsigned int processed; |
713 | 740 | ||
741 | if (connection->response != NULL) | ||
742 | return; /* already queued a response */ | ||
714 | if (connection->headersReceived == 0) | 743 | if (connection->headersReceived == 0) |
715 | abort(); /* bad timing... */ | 744 | abort(); /* bad timing... */ |
716 | ah = MHD_find_access_handler(connection); | 745 | ah = MHD_find_access_handler(connection); |
@@ -778,7 +807,8 @@ MHD_connection_handle_read(struct MHD_Connection * connection) { | |||
778 | if (tmp == NULL) { | 807 | if (tmp == NULL) { |
779 | MHD_DLOG(connection->daemon, | 808 | MHD_DLOG(connection->daemon, |
780 | "Not enough memory for reading headers!\n"); | 809 | "Not enough memory for reading headers!\n"); |
781 | MHD_excessive_header_handler(connection); | 810 | MHD_excessive_data_handler(connection, |
811 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | ||
782 | return MHD_NO; | 812 | return MHD_NO; |
783 | } | 813 | } |
784 | connection->read_buffer = tmp; | 814 | connection->read_buffer = tmp; |
@@ -824,8 +854,9 @@ MHD_connection_handle_read(struct MHD_Connection * connection) { | |||
824 | (connection->uploadSize == connection->readLoc) ) | 854 | (connection->uploadSize == connection->readLoc) ) |
825 | if (MHD_NO == MHD_parse_post_data(connection)) | 855 | if (MHD_NO == MHD_parse_post_data(connection)) |
826 | connection->post_processed = MHD_NO; | 856 | connection->post_processed = MHD_NO; |
827 | if ( (connection->post_processed == MHD_NO) || | 857 | if ( ( (connection->post_processed == MHD_NO) || |
828 | (connection->read_buffer_size == connection->readLoc) ) | 858 | (connection->read_buffer_size == connection->readLoc) ) && |
859 | (connection->method != NULL) ) | ||
829 | MHD_call_connection_handler(connection); | 860 | MHD_call_connection_handler(connection); |
830 | } | 861 | } |
831 | return MHD_YES; | 862 | return MHD_YES; |
@@ -1065,7 +1096,7 @@ MHD_connection_handle_write(struct MHD_Connection * connection) { | |||
1065 | connection->messagePos = 0; | 1096 | connection->messagePos = 0; |
1066 | connection->method = NULL; | 1097 | connection->method = NULL; |
1067 | connection->url = NULL; | 1098 | connection->url = NULL; |
1068 | if ( (connection->read_close != 0) || | 1099 | if ( (connection->read_close == MHD_YES) || |
1069 | (0 != strcasecmp(MHD_HTTP_VERSION_1_1, | 1100 | (0 != strcasecmp(MHD_HTTP_VERSION_1_1, |
1070 | connection->version)) ) { | 1101 | connection->version)) ) { |
1071 | /* closed for reading => close for good! */ | 1102 | /* closed for reading => close for good! */ |