diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2023-06-12 20:22:34 +0300 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2023-06-20 22:59:07 +0300 |
commit | eaf1fa0889e9f9621f115ad5f13084e693ddb981 (patch) | |
tree | 8b6411cc48e50413269a12141bf4e7cc91186807 /src/microhttpd/internal.h | |
parent | 69da856991eeb4fabf519552ff4c55708cb56d0a (diff) | |
download | libmicrohttpd-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.h | 69 |
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 | }; |