aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-10-25 14:40:02 +0200
committerChristian Grothoff <christian@grothoff.org>2019-10-25 14:43:36 +0200
commit185f740e0684a8758cbf381fe5c44b3ed72d4a40 (patch)
tree854e7f65dede4766b179bf875b68e4aeeb453a9e
parent3e2ba2b1ced0b4c9d13961e89e43c3932399f6d6 (diff)
downloadlibmicrohttpd-185f740e0684a8758cbf381fe5c44b3ed72d4a40.tar.gz
libmicrohttpd-185f740e0684a8758cbf381fe5c44b3ed72d4a40.zip
allow clients to override sanity check for content-length header
-rw-r--r--ChangeLog3
-rw-r--r--doc/libmicrohttpd.texi14
-rw-r--r--src/include/microhttpd.h40
-rw-r--r--src/microhttpd/connection.c5
-rw-r--r--src/microhttpd/daemon.c14
-rw-r--r--src/microhttpd/internal.h6
-rw-r--r--src/microhttpd/response.c32
7 files changed, 92 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index e1996aab..8fa9b832 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
1Fri 25 Oct 2019 02:31:59 PM CEST
2 Introduce MHD_RF_INSANITY_HEADER_CONTENT_LENGTH. -CG
3
1Thu 17 Oct 2019 04:50:52 PM CEST 4Thu 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.
776It is not recommended to set it to -1 on publicly available servers as 776It is not recommended to set it to -1 on publicly available servers as
777it may potentially lower level of protection. 777it may potentially lower level of protection.
778 778
779@item MHD_OPTION_SERVER_INSANITY
780@cindex testing
781Allows the application to disable certain sanity precautions in MHD. With
782these, the client can break the HTTP protocol, so this should never be used in
783production. 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
787Right 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
1208as the ``Host'' header is missing and is mandatory in HTTP 1.1, but it 1217as the ``Host'' header is missing and is mandatory in HTTP 1.1, but it
1209should succeed when interpreted with HTTP 1.0. 1218should succeed when interpreted with HTTP 1.0.
1219
1220@item MHD_RF_INSANITY_HEADER_CONTENT_LENGTH
1221Disable sanity check preventing clients from manually
1222setting 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 */
1716enum 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);
2185exit: 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;
2745cleanup: 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)
6550thread_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
6574free_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