diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-10-25 14:40:02 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-10-25 14:43:36 +0200 |
commit | 185f740e0684a8758cbf381fe5c44b3ed72d4a40 (patch) | |
tree | 854e7f65dede4766b179bf875b68e4aeeb453a9e | |
parent | 3e2ba2b1ced0b4c9d13961e89e43c3932399f6d6 (diff) | |
download | libmicrohttpd-185f740e0684a8758cbf381fe5c44b3ed72d4a40.tar.gz libmicrohttpd-185f740e0684a8758cbf381fe5c44b3ed72d4a40.zip |
allow clients to override sanity check for content-length header
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | doc/libmicrohttpd.texi | 14 | ||||
-rw-r--r-- | src/include/microhttpd.h | 40 | ||||
-rw-r--r-- | src/microhttpd/connection.c | 5 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 14 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 6 | ||||
-rw-r--r-- | src/microhttpd/response.c | 32 |
7 files changed, 92 insertions, 22 deletions
@@ -1,3 +1,6 @@ | |||
1 | Fri 25 Oct 2019 02:31:59 PM CEST | ||
2 | Introduce MHD_RF_INSANITY_HEADER_CONTENT_LENGTH. -CG | ||
3 | |||
1 | Thu 17 Oct 2019 04:50:52 PM CEST | 4 | Thu 17 Oct 2019 04:50:52 PM CEST |
2 | Integrate 0-byte send() method for uncorking for old FreeBSD/OS X | 5 | Integrate 0-byte send() method for uncorking for old FreeBSD/OS X |
3 | systems into new mhd_send.c logic for uncorking. | 6 | systems into new mhd_send.c logic for uncorking. |
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi index 99f0e997..4814b3c6 100644 --- a/doc/libmicrohttpd.texi +++ b/doc/libmicrohttpd.texi | |||
@@ -776,6 +776,15 @@ in header field names. This is disallowed by the standard. | |||
776 | It is not recommended to set it to -1 on publicly available servers as | 776 | It is not recommended to set it to -1 on publicly available servers as |
777 | it may potentially lower level of protection. | 777 | it may potentially lower level of protection. |
778 | 778 | ||
779 | @item MHD_OPTION_SERVER_INSANITY | ||
780 | @cindex testing | ||
781 | Allows the application to disable certain sanity precautions in MHD. With | ||
782 | these, the client can break the HTTP protocol, so this should never be used in | ||
783 | production. The options are, however, useful for testing HTTP clients against | ||
784 | "broken" server implementations. This argument must be followed by an | ||
785 | @code{unsigned int}, corresponding to an @code{enum MHD_DisableSanityCheck}. | ||
786 | |||
787 | Right now, no sanity checks can be disabled. | ||
779 | 788 | ||
780 | @item MHD_OPTION_SOCK_ADDR | 789 | @item MHD_OPTION_SOCK_ADDR |
781 | @cindex bind, restricting bind | 790 | @cindex bind, restricting bind |
@@ -1207,6 +1216,11 @@ GET / HTTP/1.1 | |||
1207 | 1216 | ||
1208 | as the ``Host'' header is missing and is mandatory in HTTP 1.1, but it | 1217 | as the ``Host'' header is missing and is mandatory in HTTP 1.1, but it |
1209 | should succeed when interpreted with HTTP 1.0. | 1218 | should succeed when interpreted with HTTP 1.0. |
1219 | |||
1220 | @item MHD_RF_INSANITY_HEADER_CONTENT_LENGTH | ||
1221 | Disable sanity check preventing clients from manually | ||
1222 | setting the HTTP content length option. | ||
1223 | |||
1210 | @end table | 1224 | @end table |
1211 | @end deftp | 1225 | @end deftp |
1212 | 1226 | ||
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index e6090fbb..3387e500 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -132,7 +132,7 @@ typedef intptr_t ssize_t; | |||
132 | * Current version of the library. | 132 | * Current version of the library. |
133 | * 0x01093001 = 1.9.30-1. | 133 | * 0x01093001 = 1.9.30-1. |
134 | */ | 134 | */ |
135 | #define MHD_VERSION 0x00096701 | 135 | #define MHD_VERSION 0x00096702 |
136 | 136 | ||
137 | /** | 137 | /** |
138 | * MHD-internal return code for "YES". | 138 | * MHD-internal return code for "YES". |
@@ -1691,10 +1691,35 @@ enum MHD_OPTION | |||
1691 | * followed by a argument of type `gnutls_certificate_retrieve_function3 *`. | 1691 | * followed by a argument of type `gnutls_certificate_retrieve_function3 *`. |
1692 | * This option provides an | 1692 | * This option provides an |
1693 | * alternative/extension to #MHD_OPTION_HTTPS_CERT_CALLBACK. | 1693 | * alternative/extension to #MHD_OPTION_HTTPS_CERT_CALLBACK. |
1694 | * You must use this version if you want to use OCSP stapling. | 1694 | * You must use this version if you want to use OCSP stapling. |
1695 | * Using this option requires GnuTLS 3.6.3 or higher. | 1695 | * Using this option requires GnuTLS 3.6.3 or higher. |
1696 | */ | 1696 | */ |
1697 | MHD_OPTION_HTTPS_CERT_CALLBACK2 = 31 | 1697 | MHD_OPTION_HTTPS_CERT_CALLBACK2 = 31, |
1698 | |||
1699 | /** | ||
1700 | * Allows the application to disable certain sanity precautions | ||
1701 | * in MHD. With these, the client can break the HTTP protocol, | ||
1702 | * so this should never be used in production. The options are, | ||
1703 | * however, useful for testing HTTP clients against "broken" | ||
1704 | * server implementations. | ||
1705 | * This argument must be followed by an "unsigned int", corresponding | ||
1706 | * to an `enum MHD_DisableSanityCheck`. | ||
1707 | */ | ||
1708 | MHD_OPTION_SERVER_INSANITY = 32 | ||
1709 | }; | ||
1710 | |||
1711 | |||
1712 | /** | ||
1713 | * Bitfield for the #MHD_OPTION_SERVER_INSANITY specifying | ||
1714 | * which santiy checks should be disabled. | ||
1715 | */ | ||
1716 | enum MHD_DisableSanityCheck | ||
1717 | { | ||
1718 | /** | ||
1719 | * All sanity checks are enabled. | ||
1720 | */ | ||
1721 | MHD_DSC_SANE = 0 | ||
1722 | |||
1698 | }; | 1723 | }; |
1699 | 1724 | ||
1700 | 1725 | ||
@@ -2924,7 +2949,14 @@ enum MHD_ResponseFlags | |||
2924 | * #MHD_RF_HTTP_VERSION_1_0_ONLY flag, the response's HTTP version will | 2949 | * #MHD_RF_HTTP_VERSION_1_0_ONLY flag, the response's HTTP version will |
2925 | * always be set to 1.0 and "Connection" headers are still supported. | 2950 | * always be set to 1.0 and "Connection" headers are still supported. |
2926 | */ | 2951 | */ |
2927 | MHD_RF_HTTP_VERSION_1_0_RESPONSE = 2 | 2952 | MHD_RF_HTTP_VERSION_1_0_RESPONSE = 2, |
2953 | |||
2954 | /** | ||
2955 | * Disable sanity check preventing clients from manually | ||
2956 | * setting the HTTP content length option. | ||
2957 | */ | ||
2958 | MHD_RF_INSANITY_HEADER_CONTENT_LENGTH = 4 | ||
2959 | |||
2928 | 2960 | ||
2929 | }; | 2961 | }; |
2930 | 2962 | ||
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 1dbbbd82..2ef0b989 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -1430,8 +1430,9 @@ build_header_response (struct MHD_Connection *connection) | |||
1430 | (MHD_HTTP_NO_CONTENT != rc) && | 1430 | (MHD_HTTP_NO_CONTENT != rc) && |
1431 | (MHD_HTTP_NOT_MODIFIED != rc) && | 1431 | (MHD_HTTP_NOT_MODIFIED != rc) && |
1432 | (MHD_HTTP_OK <= rc) && | 1432 | (MHD_HTTP_OK <= rc) && |
1433 | (NULL == /* this should always succeed due to check in | 1433 | (NULL == /* this COULD fail if the check in |
1434 | MHD_add_response_header() */ | 1434 | MHD_add_response_header() was bypassed |
1435 | via #MHD_RF_INSANITY_HEADER_CONTENT_LENGTH */ | ||
1435 | MHD_get_response_header (response, | 1436 | MHD_get_response_header (response, |
1436 | MHD_HTTP_HEADER_CONTENT_LENGTH)) && | 1437 | MHD_HTTP_HEADER_CONTENT_LENGTH)) && |
1437 | (may_add_content_length) && | 1438 | (may_add_content_length) && |
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 1e5716e3..aec6aa86 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -2182,7 +2182,7 @@ thread_main_handle_connection (void *data) | |||
2182 | MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN : | 2182 | MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN : |
2183 | MHD_REQUEST_TERMINATED_WITH_ERROR); | 2183 | MHD_REQUEST_TERMINATED_WITH_ERROR); |
2184 | MHD_connection_handle_idle (con); | 2184 | MHD_connection_handle_idle (con); |
2185 | exit: | 2185 | exit: |
2186 | if (NULL != con->response) | 2186 | if (NULL != con->response) |
2187 | { | 2187 | { |
2188 | MHD_destroy_response (con->response); | 2188 | MHD_destroy_response (con->response); |
@@ -2742,7 +2742,7 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
2742 | #endif | 2742 | #endif |
2743 | } | 2743 | } |
2744 | return MHD_YES; | 2744 | return MHD_YES; |
2745 | cleanup: | 2745 | cleanup: |
2746 | if (NULL != daemon->notify_connection) | 2746 | if (NULL != daemon->notify_connection) |
2747 | daemon->notify_connection (daemon->notify_connection_cls, | 2747 | daemon->notify_connection (daemon->notify_connection_cls, |
2748 | connection, | 2748 | connection, |
@@ -5062,6 +5062,11 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
5062 | daemon->uri_log_callback_cls = va_arg (ap, | 5062 | daemon->uri_log_callback_cls = va_arg (ap, |
5063 | void *); | 5063 | void *); |
5064 | break; | 5064 | break; |
5065 | case MHD_OPTION_SERVER_INSANITY: | ||
5066 | daemon->insanity_level = (enum MHD_DisableSanityCheck) | ||
5067 | va_arg (ap, | ||
5068 | unsigned int); | ||
5069 | break; | ||
5065 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) | 5070 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) |
5066 | case MHD_OPTION_THREAD_POOL_SIZE: | 5071 | case MHD_OPTION_THREAD_POOL_SIZE: |
5067 | daemon->worker_pool_size = va_arg (ap, | 5072 | daemon->worker_pool_size = va_arg (ap, |
@@ -5404,6 +5409,7 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
5404 | case MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE: | 5409 | case MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE: |
5405 | case MHD_OPTION_LISTENING_ADDRESS_REUSE: | 5410 | case MHD_OPTION_LISTENING_ADDRESS_REUSE: |
5406 | case MHD_OPTION_LISTEN_BACKLOG_SIZE: | 5411 | case MHD_OPTION_LISTEN_BACKLOG_SIZE: |
5412 | case MHD_OPTION_SERVER_INSANITY: | ||
5407 | if (MHD_YES != parse_options (daemon, | 5413 | if (MHD_YES != parse_options (daemon, |
5408 | servaddr, | 5414 | servaddr, |
5409 | opt, | 5415 | opt, |
@@ -6547,7 +6553,7 @@ MHD_start_daemon_va (unsigned int flags, | |||
6547 | return daemon; | 6553 | return daemon; |
6548 | 6554 | ||
6549 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) | 6555 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) |
6550 | thread_failed: | 6556 | thread_failed: |
6551 | /* If no worker threads created, then shut down normally. Calling | 6557 | /* If no worker threads created, then shut down normally. Calling |
6552 | MHD_stop_daemon (as we do below) doesn't work here since it | 6558 | MHD_stop_daemon (as we do below) doesn't work here since it |
6553 | assumes a 0-sized thread pool means we had been in the default | 6559 | assumes a 0-sized thread pool means we had been in the default |
@@ -6571,7 +6577,7 @@ thread_failed: | |||
6571 | return NULL; | 6577 | return NULL; |
6572 | #endif | 6578 | #endif |
6573 | 6579 | ||
6574 | free_and_fail: | 6580 | free_and_fail: |
6575 | /* clean up basic memory state in 'daemon' and return NULL to | 6581 | /* clean up basic memory state in 'daemon' and return NULL to |
6576 | indicate failure */ | 6582 | indicate failure */ |
6577 | #ifdef EPOLL_SUPPORT | 6583 | #ifdef EPOLL_SUPPORT |
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index fa66d265..8f7192e7 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -1461,6 +1461,12 @@ struct MHD_Daemon | |||
1461 | size_t thread_stack_size; | 1461 | size_t thread_stack_size; |
1462 | 1462 | ||
1463 | /** | 1463 | /** |
1464 | * Our #MHD_OPTION_SERVER_INSANITY level, bits indicating | ||
1465 | * which sanity checks are off. | ||
1466 | */ | ||
1467 | enum MHD_DisableSanityCheck insanity_level; | ||
1468 | |||
1469 | /** | ||
1464 | * Number of worker daemons | 1470 | * Number of worker daemons |
1465 | */ | 1471 | */ |
1466 | unsigned int worker_pool_size; | 1472 | unsigned int worker_pool_size; |
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c index 112a622a..968fc8c9 100644 --- a/src/microhttpd/response.c +++ b/src/microhttpd/response.c | |||
@@ -147,8 +147,10 @@ MHD_add_response_header (struct MHD_Response *response, | |||
147 | /* NOTE: for compressed bodies, use the "Content-encoding" header */ | 147 | /* NOTE: for compressed bodies, use the "Content-encoding" header */ |
148 | return MHD_NO; | 148 | return MHD_NO; |
149 | } | 149 | } |
150 | if (MHD_str_equal_caseless_ (header, | 150 | if ( (0 == (MHD_RF_INSANITY_HEADER_CONTENT_LENGTH |
151 | MHD_HTTP_HEADER_CONTENT_LENGTH)) | 151 | & response->flags)) && |
152 | (MHD_str_equal_caseless_ (header, | ||
153 | MHD_HTTP_HEADER_CONTENT_LENGTH)) ) | ||
152 | { | 154 | { |
153 | /* MHD will set Content-length if allowed and possible, | 155 | /* MHD will set Content-length if allowed and possible, |
154 | reject attempt by application */ | 156 | reject attempt by application */ |
@@ -838,17 +840,20 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh, | |||
838 | return MHD_YES; | 840 | return MHD_YES; |
839 | } | 841 | } |
840 | else | 842 | else |
841 | #else | 843 | #endif |
842 | { | 844 | { |
843 | if (0 == | 845 | if (0 == |
844 | MHD_socket_cork_ (connection->socket_fd, | 846 | MHD_socket_cork_ (connection->socket_fd, |
845 | true)) | 847 | true)) |
848 | { | ||
846 | connection->sk_cork_on = true; | 849 | connection->sk_cork_on = true; |
847 | } | ||
848 | #endif | ||
849 | case MHD_UPGRADE_ACTION_CORK_OFF: | ||
850 | if (! connection->sk_cork_on) | ||
851 | return MHD_YES; | 850 | return MHD_YES; |
851 | } | ||
852 | return MHD_NO; | ||
853 | } | ||
854 | case MHD_UPGRADE_ACTION_CORK_OFF: | ||
855 | if (! connection->sk_cork_on) | ||
856 | return MHD_YES; | ||
852 | #ifdef HTTPS_SUPPORT | 857 | #ifdef HTTPS_SUPPORT |
853 | if (0 != (daemon->options & MHD_USE_TLS) ) | 858 | if (0 != (daemon->options & MHD_USE_TLS) ) |
854 | { | 859 | { |
@@ -857,17 +862,20 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh, | |||
857 | return MHD_YES; | 862 | return MHD_YES; |
858 | } | 863 | } |
859 | else | 864 | else |
860 | #else | 865 | #endif |
861 | { | 866 | { |
862 | if (0 == | 867 | if (0 == |
863 | MHD_socket_cork_ (connection->socket_fd, | 868 | MHD_socket_cork_ (connection->socket_fd, |
864 | false)) | 869 | false)) |
870 | { | ||
865 | connection->sk_cork_on = false; | 871 | connection->sk_cork_on = false; |
866 | } | 872 | return MHD_YES; |
867 | #endif | 873 | } |
868 | default: | ||
869 | /* we don't understand this one */ | ||
870 | return MHD_NO; | 874 | return MHD_NO; |
875 | } | ||
876 | default: | ||
877 | /* we don't understand this one */ | ||
878 | return MHD_NO; | ||
871 | } | 879 | } |
872 | } | 880 | } |
873 | 881 | ||