]>
Commit | Line | Data |
---|---|---|
db3b637a | 1 | /* Copyright (C) 2007-2020 Open Information Security Foundation |
ce019275 WM |
2 | * |
3 | * You can copy, redistribute or modify this Program under the terms of | |
4 | * the GNU General Public License version 2 as published by the Free | |
5 | * Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 | * GNU General Public License for more details. | |
0165b3f0 | 11 | * |
ce019275 WM |
12 | * You should have received a copy of the GNU General Public License |
13 | * version 2 along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
15 | * 02110-1301, USA. | |
16 | */ | |
17 | ||
60a99915 EL |
18 | /** |
19 | * \defgroup httplayer HTTP layer support | |
20 | * | |
21 | * @{ | |
22 | */ | |
23 | ||
ce019275 WM |
24 | /** |
25 | * \file | |
0165b3f0 | 26 | * |
07f7ba55 | 27 | * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com> |
0165b3f0 | 28 | * \author Pablo Rincon <pablo.rincon.crespo@gmail.com> |
07f7ba55 | 29 | * |
ce019275 | 30 | * This file provides a HTTP protocol support for the engine using HTP library. |
07f7ba55 GS |
31 | */ |
32 | ||
48248687 VJ |
33 | #ifndef __APP_LAYER_HTP_H__ |
34 | #define __APP_LAYER_HTP_H__ | |
07f7ba55 | 35 | |
a9cdd2bb | 36 | #include "util-radix-tree.h" |
e1022ee5 | 37 | #include "util-file.h" |
ced01da8 | 38 | #include "app-layer-htp-mem.h" |
6279da0f | 39 | #include "detect-engine-state.h" |
46e55f1e | 40 | #include "util-streaming-buffer.h" |
e82416a4 | 41 | #include "app-layer-htp-range.h" |
910922cd | 42 | #include "rust.h" |
a9cdd2bb | 43 | |
07f7ba55 GS |
44 | #include <htp/htp.h> |
45 | ||
6ebe7b7c | 46 | /* default request body limit */ |
2763a612 VJ |
47 | #define HTP_CONFIG_DEFAULT_REQUEST_BODY_LIMIT 4096U |
48 | #define HTP_CONFIG_DEFAULT_RESPONSE_BODY_LIMIT 4096U | |
49 | #define HTP_CONFIG_DEFAULT_REQUEST_INSPECT_MIN_SIZE 32768U | |
50 | #define HTP_CONFIG_DEFAULT_REQUEST_INSPECT_WINDOW 4096U | |
51 | #define HTP_CONFIG_DEFAULT_RESPONSE_INSPECT_MIN_SIZE 32768U | |
52 | #define HTP_CONFIG_DEFAULT_RESPONSE_INSPECT_WINDOW 4096U | |
fb496791 VJ |
53 | #define HTP_CONFIG_DEFAULT_FIELD_LIMIT_SOFT 9000U |
54 | #define HTP_CONFIG_DEFAULT_FIELD_LIMIT_HARD 18000U | |
a0ee6ade | 55 | |
9b5c9233 | 56 | #define HTP_CONFIG_DEFAULT_LZMA_LAYERS 0U |
61a6eaf3 JI |
57 | /* default libhtp lzma limit, taken from libhtp. */ |
58 | #define HTP_CONFIG_DEFAULT_LZMA_MEMLIMIT 1048576U | |
af4f8162 | 59 | #define HTP_CONFIG_DEFAULT_COMPRESSION_BOMB_LIMIT 1048576U |
a04b5566 PA |
60 | // 100000 usec is 0.1 sec |
61 | #define HTP_CONFIG_DEFAULT_COMPRESSION_TIME_LIMIT 100000 | |
61a6eaf3 | 62 | |
ff784075 EL |
63 | #define HTP_CONFIG_DEFAULT_RANDOMIZE 1 |
64 | #define HTP_CONFIG_DEFAULT_RANDOMIZE_RANGE 10 | |
65 | ||
a0ee6ade VJ |
66 | /** a boundary should be smaller in size */ |
67 | #define HTP_BOUNDARY_MAX 200U | |
6ebe7b7c | 68 | |
e6494114 | 69 | // 0x0001 not used |
64625675 | 70 | #define HTP_FLAG_STATE_CLOSED_TS 0x0002 /**< Flag to indicate that HTTP |
0165b3f0 | 71 | connection is closed */ |
64625675 AS |
72 | #define HTP_FLAG_STATE_CLOSED_TC 0x0004 /**< Flag to indicate that HTTP |
73 | connection is closed */ | |
64625675 AS |
74 | #define HTP_FLAG_STORE_FILES_TS 0x0040 |
75 | #define HTP_FLAG_STORE_FILES_TC 0x0080 | |
76 | #define HTP_FLAG_STORE_FILES_TX_TS 0x0100 | |
77 | #define HTP_FLAG_STORE_FILES_TX_TC 0x0200 | |
9878eca0 | 78 | |
23e01d23 VJ |
79 | enum { |
80 | HTP_BODY_REQUEST_NONE = 0, | |
3702a33a VJ |
81 | HTP_BODY_REQUEST_MULTIPART, /* POST, MP */ |
82 | HTP_BODY_REQUEST_POST, /* POST, no MP */ | |
23e01d23 VJ |
83 | HTP_BODY_REQUEST_PUT, |
84 | }; | |
85 | ||
f713b653 | 86 | enum { |
e21d8cdf | 87 | /* libhtp errors/warnings */ |
f713b653 VJ |
88 | HTTP_DECODER_EVENT_UNKNOWN_ERROR, |
89 | HTTP_DECODER_EVENT_GZIP_DECOMPRESSION_FAILED, | |
90 | HTTP_DECODER_EVENT_REQUEST_FIELD_MISSING_COLON, | |
93d121bf | 91 | HTTP_DECODER_EVENT_RESPONSE_FIELD_MISSING_COLON, |
f713b653 VJ |
92 | HTTP_DECODER_EVENT_INVALID_REQUEST_CHUNK_LEN, |
93 | HTTP_DECODER_EVENT_INVALID_RESPONSE_CHUNK_LEN, | |
94 | HTTP_DECODER_EVENT_INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST, | |
95 | HTTP_DECODER_EVENT_INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE, | |
96 | HTTP_DECODER_EVENT_INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST, | |
97 | HTTP_DECODER_EVENT_INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE, | |
9cbf9ef7 PA |
98 | HTTP_DECODER_EVENT_DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST, |
99 | HTTP_DECODER_EVENT_DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE, | |
f713b653 VJ |
100 | HTTP_DECODER_EVENT_100_CONTINUE_ALREADY_SEEN, |
101 | HTTP_DECODER_EVENT_UNABLE_TO_MATCH_RESPONSE_TO_REQUEST, | |
102 | HTTP_DECODER_EVENT_INVALID_SERVER_PORT_IN_REQUEST, | |
103 | HTTP_DECODER_EVENT_INVALID_AUTHORITY_PORT, | |
104 | HTTP_DECODER_EVENT_REQUEST_HEADER_INVALID, | |
93d121bf | 105 | HTTP_DECODER_EVENT_RESPONSE_HEADER_INVALID, |
f713b653 VJ |
106 | HTTP_DECODER_EVENT_MISSING_HOST_HEADER, |
107 | HTTP_DECODER_EVENT_HOST_HEADER_AMBIGUOUS, | |
108 | HTTP_DECODER_EVENT_INVALID_REQUEST_FIELD_FOLDING, | |
109 | HTTP_DECODER_EVENT_INVALID_RESPONSE_FIELD_FOLDING, | |
110 | HTTP_DECODER_EVENT_REQUEST_FIELD_TOO_LONG, | |
111 | HTTP_DECODER_EVENT_RESPONSE_FIELD_TOO_LONG, | |
9f519e95 | 112 | HTTP_DECODER_EVENT_REQUEST_SERVER_PORT_TCP_PORT_MISMATCH, |
cb150003 VJ |
113 | HTTP_DECODER_EVENT_URI_HOST_INVALID, |
114 | HTTP_DECODER_EVENT_HEADER_HOST_INVALID, | |
e78e33a4 | 115 | HTTP_DECODER_EVENT_METHOD_DELIM_NON_COMPLIANT, |
5ad7198d | 116 | HTTP_DECODER_EVENT_URI_DELIM_NON_COMPLIANT, |
52195a41 | 117 | HTTP_DECODER_EVENT_REQUEST_LINE_LEADING_WHITESPACE, |
d0cded25 VJ |
118 | HTTP_DECODER_EVENT_TOO_MANY_ENCODING_LAYERS, |
119 | HTTP_DECODER_EVENT_ABNORMAL_CE_HEADER, | |
a1c6e091 | 120 | HTTP_DECODER_EVENT_AUTH_UNRECOGNIZED, |
b6b7778e PA |
121 | HTTP_DECODER_EVENT_REQUEST_HEADER_REPETITION, |
122 | HTTP_DECODER_EVENT_RESPONSE_HEADER_REPETITION, | |
3e120668 PA |
123 | HTTP_DECODER_EVENT_RESPONSE_MULTIPART_BYTERANGES, |
124 | HTTP_DECODER_EVENT_RESPONSE_ABNORMAL_TRANSFER_ENCODING, | |
125 | HTTP_DECODER_EVENT_RESPONSE_CHUNKED_OLD_PROTO, | |
126 | HTTP_DECODER_EVENT_RESPONSE_INVALID_PROTOCOL, | |
127 | HTTP_DECODER_EVENT_RESPONSE_INVALID_STATUS, | |
128 | HTTP_DECODER_EVENT_REQUEST_LINE_INCOMPLETE, | |
8a339e73 | 129 | HTTP_DECODER_EVENT_DOUBLE_ENCODED_URI, |
b5f3e032 PA |
130 | HTTP_DECODER_EVENT_REQUEST_LINE_INVALID, |
131 | HTTP_DECODER_EVENT_REQUEST_BODY_UNEXPECTED, | |
e21d8cdf | 132 | |
c9c23d5c | 133 | HTTP_DECODER_EVENT_LZMA_MEMLIMIT_REACHED, |
af4f8162 | 134 | HTTP_DECODER_EVENT_COMPRESSION_BOMB, |
c9c23d5c | 135 | |
e82416a4 PA |
136 | HTTP_DECODER_EVENT_RANGE_INVALID, |
137 | ||
e21d8cdf VJ |
138 | /* suricata errors/warnings */ |
139 | HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR, | |
140 | HTTP_DECODER_EVENT_MULTIPART_NO_FILEDATA, | |
141 | HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER, | |
053c7288 PA |
142 | |
143 | HTTP_DECODER_EVENT_TOO_MANY_WARNINGS, | |
f713b653 VJ |
144 | }; |
145 | ||
d0f92e2a GL |
146 | typedef enum HtpSwfCompressType_ { |
147 | HTTP_SWF_COMPRESSION_NONE = 0, | |
148 | HTTP_SWF_COMPRESSION_ZLIB, | |
149 | HTTP_SWF_COMPRESSION_LZMA, | |
150 | HTTP_SWF_COMPRESSION_BOTH, | |
151 | } HtpSwfCompressType; | |
152 | ||
6fb808fc | 153 | typedef struct HTPCfgDir_ { |
24a2f515 VJ |
154 | uint32_t body_limit; |
155 | uint32_t inspect_min_size; | |
156 | uint32_t inspect_window; | |
6fb808fc VJ |
157 | StreamingBufferConfig sbcfg; |
158 | } HTPCfgDir; | |
159 | ||
2763a612 VJ |
160 | /** Need a linked list in order to keep track of these */ |
161 | typedef struct HTPCfgRec_ { | |
162 | htp_cfg_t *cfg; | |
163 | struct HTPCfgRec_ *next; | |
164 | ||
a8b971c7 VJ |
165 | int uri_include_all; /**< use all info in uri (bool) */ |
166 | ||
2763a612 | 167 | /** max size of the client body we inspect */ |
ff784075 EL |
168 | int randomize; |
169 | int randomize_range; | |
a459376d | 170 | int http_body_inline; |
46e55f1e | 171 | |
d0f92e2a GL |
172 | int swf_decompression_enabled; |
173 | HtpSwfCompressType swf_compression_type; | |
174 | uint32_t swf_decompress_depth; | |
175 | uint32_t swf_compress_depth; | |
176 | ||
6fb808fc VJ |
177 | HTPCfgDir request; |
178 | HTPCfgDir response; | |
2763a612 VJ |
179 | } HTPCfgRec; |
180 | ||
0165b3f0 | 181 | /** Struct used to hold chunks of a body on a request */ |
d378b76c | 182 | struct HtpBodyChunk_ { |
a0ee6ade | 183 | struct HtpBodyChunk_ *next; /**< Pointer to the next chunk */ |
bac6c3ab | 184 | int logged; |
269313a5 | 185 | StreamingBufferSegment sbseg; |
d378b76c VJ |
186 | } __attribute__((__packed__)); |
187 | typedef struct HtpBodyChunk_ HtpBodyChunk; | |
0165b3f0 PR |
188 | |
189 | /** Struct used to hold all the chunks of a body on a request */ | |
7a8cd61f VJ |
190 | typedef struct HtpBody_ { |
191 | HtpBodyChunk *first; /**< Pointer to the first chunk */ | |
192 | HtpBodyChunk *last; /**< Pointer to the last chunk */ | |
a0ee6ade | 193 | |
46e55f1e VJ |
194 | StreamingBuffer *sb; |
195 | ||
b402d971 VJ |
196 | /* Holds the length of the htp request body seen so far */ |
197 | uint64_t content_len_so_far; | |
d378b76c | 198 | /* parser tracker */ |
b402d971 | 199 | uint64_t body_parsed; |
d378b76c VJ |
200 | /* inspection tracker */ |
201 | uint64_t body_inspected; | |
0165b3f0 | 202 | } HtpBody; |
fc2f7f29 | 203 | |
de904db8 GL |
204 | #define HTP_CONTENTTYPE_SET BIT_U8(0) /**< We have the content type */ |
205 | #define HTP_BOUNDARY_SET BIT_U8(1) /**< We have a boundary string */ | |
206 | #define HTP_BOUNDARY_OPEN BIT_U8(2) /**< We have a boundary string */ | |
207 | #define HTP_FILENAME_SET BIT_U8(3) /**< filename is registered in the flow */ | |
208 | #define HTP_DONTSTORE BIT_U8(4) /**< not storing this file */ | |
209 | #define HTP_STREAM_DEPTH_SET BIT_U8(5) /**< stream-depth is set */ | |
23e01d23 | 210 | |
06a65cb4 PR |
211 | /** Now the Body Chunks will be stored per transaction, at |
212 | * the tx user data */ | |
66a3cd96 | 213 | typedef struct HtpTxUserData_ { |
5c6a65dc | 214 | /* Body of the request (if any) */ |
48cf0585 AS |
215 | uint8_t request_body_init; |
216 | uint8_t response_body_init; | |
c52fe9a5 | 217 | |
44022743 VJ |
218 | uint8_t request_has_trailers; |
219 | uint8_t response_has_trailers; | |
220 | ||
66a3cd96 | 221 | HtpBody request_body; |
b402d971 | 222 | HtpBody response_body; |
a0ee6ade | 223 | |
48cf0585 AS |
224 | bstr *request_uri_normalized; |
225 | ||
226 | uint8_t *request_headers_raw; | |
227 | uint8_t *response_headers_raw; | |
228 | uint32_t request_headers_raw_len; | |
229 | uint32_t response_headers_raw_len; | |
230 | ||
07c05f7d | 231 | /** Holds the boundary identification string if any (used on |
a0ee6ade VJ |
232 | * multipart/form-data only) |
233 | */ | |
6d60b3a7 | 234 | uint8_t *boundary; |
a0ee6ade | 235 | uint8_t boundary_len; |
6d60b3a7 | 236 | |
43c7fd75 VJ |
237 | uint8_t tsflags; |
238 | uint8_t tcflags; | |
b402d971 | 239 | |
d378b76c | 240 | uint8_t request_body_type; |
d378b76c | 241 | |
910922cd | 242 | AppLayerTxData tx_data; |
66a3cd96 | 243 | } HtpTxUserData; |
06a65cb4 | 244 | |
07f7ba55 | 245 | typedef struct HtpState_ { |
48cf0585 AS |
246 | /* Connection parser structure for each connection */ |
247 | htp_connp_t *connp; | |
248 | /* Connection structure for each connection */ | |
249 | htp_conn_t *conn; | |
07c05f7d | 250 | Flow *f; /**< Needed to retrieve the original flow when using HTPLib callbacks */ |
d4d18e31 | 251 | uint64_t transaction_cnt; |
d4d18e31 | 252 | uint64_t store_tx_id; |
d59ca75e VJ |
253 | FileContainer *files_ts; |
254 | FileContainer *files_tc; | |
feafc838 | 255 | const struct HTPCfgRec_ *cfg; |
d4d18e31 | 256 | uint16_t flags; |
3f5acc54 VJ |
257 | uint16_t events; |
258 | uint16_t htp_messages_offset; /**< offset into conn->messages list */ | |
9132e403 | 259 | uint32_t file_track_id; /**< used to assign file track ids to files */ |
e82416a4 | 260 | HttpRangeContainerBlock *file_range; /**< used to assign track ids to range file */ |
e02b74de VJ |
261 | uint64_t last_request_data_stamp; |
262 | uint64_t last_response_data_stamp; | |
07f7ba55 GS |
263 | } HtpState; |
264 | ||
6fa46d75 | 265 | /** part of the engine needs the request body (e.g. http_client_body keyword) */ |
92679442 | 266 | #define HTP_REQUIRE_REQUEST_BODY (1 << 0) |
6fa46d75 AS |
267 | /** part of the engine needs the request body multipart header (e.g. filename |
268 | * and / or fileext keywords) */ | |
92679442 | 269 | #define HTP_REQUIRE_REQUEST_MULTIPART (1 << 1) |
6fa46d75 | 270 | /** part of the engine needs the request file (e.g. log-file module) */ |
92679442 | 271 | #define HTP_REQUIRE_REQUEST_FILE (1 << 2) |
6fa46d75 | 272 | /** part of the engine needs the request body (e.g. file_data keyword) */ |
92679442 EL |
273 | #define HTP_REQUIRE_RESPONSE_BODY (1 << 3) |
274 | ||
3ae1854d | 275 | SC_ATOMIC_EXTERN(uint32_t, htp_config_flags); |
6fa46d75 | 276 | |
07f7ba55 | 277 | void RegisterHTPParsers(void); |
fc2f7f29 GS |
278 | void HTPAtExitPrintStats(void); |
279 | void HTPFreeConfig(void); | |
48248687 | 280 | |
0165b3f0 PR |
281 | void HtpBodyPrint(HtpBody *); |
282 | void HtpBodyFree(HtpBody *); | |
25a3a5c6 PR |
283 | /* To free the state from unittests using app-layer-htp */ |
284 | void HTPStateFree(void *); | |
97d49d8f | 285 | void AppLayerHtpEnableRequestBodyCallback(void); |
b402d971 | 286 | void AppLayerHtpEnableResponseBodyCallback(void); |
6d60b3a7 | 287 | void AppLayerHtpNeedFileInspection(void); |
6fca55e0 | 288 | void AppLayerHtpPrintStats(void); |
0165b3f0 | 289 | |
ab4b15c2 AS |
290 | void HTPConfigure(void); |
291 | ||
292 | void HtpConfigCreateBackup(void); | |
293 | void HtpConfigRestoreBackup(void); | |
294 | ||
7011bddf PA |
295 | void *HtpGetTxForH2(void *); |
296 | ||
48248687 | 297 | #endif /* __APP_LAYER_HTP_H__ */ |
07f7ba55 | 298 | |
60a99915 EL |
299 | /** |
300 | * @} | |
301 | */ |