aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/internal.h
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2023-06-12 20:22:34 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2023-06-20 22:59:07 +0300
commiteaf1fa0889e9f9621f115ad5f13084e693ddb981 (patch)
tree8b6411cc48e50413269a12141bf4e7cc91186807 /src/microhttpd/internal.h
parent69da856991eeb4fabf519552ff4c55708cb56d0a (diff)
downloadlibmicrohttpd-eaf1fa0889e9f9621f115ad5f13084e693ddb981.tar.gz
libmicrohttpd-eaf1fa0889e9f9621f115ad5f13084e693ddb981.zip
Re-implemented parsing of the request headers and footers from scratch.
* The new algorithm parse the headers in one pass (including folded headers) thus multiple passes over the same memory area are avoided (efficiency for large headers should be improved). * Strict implementation of RFC 9110 and 9112 requirements, including replacing or reporting error for unacceptable characters. * Implemented various levels of strictness for requests interpretations: three levels within RFC requirements (more strict and more secure; less strict and more compatible with various clients; balanced (default)), one more relaxed level with violation of RFC's SHOULD/SHOULD NOT, one even more relaxed level with violation of MUST/MUST NOT, one stricter level then required by RFC, but absolutely compatible with clients following RFC's MUST/MUST NOT, and one more even stricter level compatible with clients following both MUST/MUST NOT and SHOULD/SHOULD NOT. * Added detection and handling of more erroneous situations, like space at the start of the first line (as recommended by RFC). * Added more detailed responses for invalid requests with descriptions of the found problems (as recommended by RFC). * If many chars have been replaced, only summary is reported instead of flooding logs with messages when request is badly constructed. * Whitespaces in headers values are trimmed at start and at the end. No need to handle extra spaces in the app or when using headers in other MHD parts, like cookie parsing. * In overall: increased flexibility, the security must be improved, much better compliance with the standards.
Diffstat (limited to 'src/microhttpd/internal.h')
-rw-r--r--src/microhttpd/internal.h69
1 files changed, 57 insertions, 12 deletions
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 4f991140..e07ad6de 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -623,18 +623,20 @@ enum MHD_CONNECTION_STATE
623 623
624 /** 624 /**
625 * We got the URL (and request type and version). Wait for a header line. 625 * We got the URL (and request type and version). Wait for a header line.
626 *
627 * A milestone state. No received data is processed in this state.
626 */ 628 */
627 MHD_CONNECTION_REQ_LINE_RECEIVED = MHD_CONNECTION_REQ_LINE_RECEIVING + 1, 629 MHD_CONNECTION_REQ_LINE_RECEIVED = MHD_CONNECTION_REQ_LINE_RECEIVING + 1,
628 630
629 /** 631 /**
630 * We got part of a multi-line request header. Wait for the rest. 632 * Receiving request headers. Wait for the rest of the headers.
631 */ 633 */
632 MHD_CONNECTION_HEADER_PART_RECEIVED = MHD_CONNECTION_REQ_LINE_RECEIVED + 1, 634 MHD_CONNECTION_REQ_HEADERS_RECEIVING = MHD_CONNECTION_REQ_LINE_RECEIVED + 1,
633 635
634 /** 636 /**
635 * We got the request headers. Process them. 637 * We got the request headers. Process them.
636 */ 638 */
637 MHD_CONNECTION_HEADERS_RECEIVED = MHD_CONNECTION_HEADER_PART_RECEIVED + 1, 639 MHD_CONNECTION_HEADERS_RECEIVED = MHD_CONNECTION_REQ_HEADERS_RECEIVING + 1,
638 640
639 /** 641 /**
640 * We have processed the request headers. Send 100 continue. 642 * We have processed the request headers. Send 100 continue.
@@ -652,20 +654,23 @@ enum MHD_CONNECTION_STATE
652 MHD_CONNECTION_BODY_RECEIVING = MHD_CONNECTION_CONTINUE_SENDING + 1, 654 MHD_CONNECTION_BODY_RECEIVING = MHD_CONNECTION_CONTINUE_SENDING + 1,
653 655
654 /** 656 /**
655 * We got the request body. Wait for a line of the footer. 657 * We got the request body.
658 *
659 * A milestone state. No received data is processed in this state.
656 */ 660 */
657 MHD_CONNECTION_BODY_RECEIVED = MHD_CONNECTION_BODY_RECEIVING + 1, 661 MHD_CONNECTION_BODY_RECEIVED = MHD_CONNECTION_BODY_RECEIVING + 1,
658 662
659 /** 663 /**
660 * We got part of a line of the footer. Wait for the 664 * We are reading the request footers.
661 * rest.
662 */ 665 */
663 MHD_CONNECTION_FOOTER_PART_RECEIVED = MHD_CONNECTION_BODY_RECEIVED + 1, 666 MHD_CONNECTION_FOOTERS_RECEIVING = MHD_CONNECTION_BODY_RECEIVED + 1,
664 667
665 /** 668 /**
666 * We received the entire footer. 669 * We received the entire footer.
670 *
671 * A milestone state. No received data is processed in this state.
667 */ 672 */
668 MHD_CONNECTION_FOOTERS_RECEIVED = MHD_CONNECTION_FOOTER_PART_RECEIVED + 1, 673 MHD_CONNECTION_FOOTERS_RECEIVED = MHD_CONNECTION_FOOTERS_RECEIVING + 1,
669 674
670 /** 675 /**
671 * We received the entire request. 676 * We received the entire request.
@@ -985,6 +990,41 @@ struct MHD_HeaderProcessing
985 * The position of the last processed character 990 * The position of the last processed character
986 */ 991 */
987 size_t proc_pos; 992 size_t proc_pos;
993
994 /**
995 * The position of the first whitespace character in current contiguous
996 * whitespace block.
997 * Zero when no whitespace found or found non-whitespace character after
998 * whitespace.
999 * Must be zero, if the current character is not whitespace.
1000 */
1001 size_t ws_start;
1002
1003 /**
1004 * Indicates that end of the header (field) name found.
1005 * Must be false until the first colon in line is found.
1006 */
1007 bool name_end_found;
1008
1009 /**
1010 * The length of the header name.
1011 * Must be zero until the first colon in line is found.
1012 * Name always starts at zero position.
1013 */
1014 size_t name_len;
1015
1016 /**
1017 * The position of the first character of the header value.
1018 * Zero when the first character has not been found yet.
1019 */
1020 size_t value_start;
1021
1022 /**
1023 * Line starts with whitespace.
1024 * It's meaningful only for the first line, as other lines should be handled
1025 * as "folded".
1026 */
1027 bool starts_with_ws;
988}; 1028};
989 1029
990/** 1030/**
@@ -1151,6 +1191,11 @@ struct MHD_Request
1151 size_t num_cr_sp_replaced; 1191 size_t num_cr_sp_replaced;
1152 1192
1153 /** 1193 /**
1194 * The number of header lines skipped because they have no colon
1195 */
1196 size_t skipped_broken_lines;
1197
1198 /**
1154 * The data of the request line / request headers processing 1199 * The data of the request line / request headers processing
1155 */ 1200 */
1156 union MHD_HeadersProcessing hdrs; 1201 union MHD_HeadersProcessing hdrs;
@@ -1158,8 +1203,8 @@ struct MHD_Request
1158 /** 1203 /**
1159 * Last incomplete header line during parsing of headers. 1204 * Last incomplete header line during parsing of headers.
1160 * Allocated in pool. Only valid if state is 1205 * Allocated in pool. Only valid if state is
1161 * either #MHD_CONNECTION_HEADER_PART_RECEIVED or 1206 * either #MHD_CONNECTION_REQ_HEADERS_RECEIVING or
1162 * #MHD_CONNECTION_FOOTER_PART_RECEIVED. 1207 * #MHD_CONNECTION_FOOTERS_RECEIVING.
1163 */ 1208 */
1164 char *last; 1209 char *last;
1165 1210
@@ -1167,8 +1212,8 @@ struct MHD_Request
1167 * Position after the colon on the last incomplete header 1212 * Position after the colon on the last incomplete header
1168 * line during parsing of headers. 1213 * line during parsing of headers.
1169 * Allocated in pool. Only valid if state is 1214 * Allocated in pool. Only valid if state is
1170 * either #MHD_CONNECTION_HEADER_PART_RECEIVED or 1215 * either #MHD_CONNECTION_REQ_HEADERS_RECEIVING or
1171 * #MHD_CONNECTION_FOOTER_PART_RECEIVED. 1216 * #MHD_CONNECTION_FOOTERS_RECEIVING.
1172 */ 1217 */
1173 char *colon; 1218 char *colon;
1174}; 1219};