1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation. You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 //--------------------------------------------------------------------------
18 // http_inspect.cc author Tom Peters <thopeter@cisco.com>
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "http_inspect.h"
25
26 #include <cassert>
27 #include <iomanip>
28 #include <sstream>
29
30 #include "detection/detection_engine.h"
31 #include "detection/detection_util.h"
32 #include "service_inspectors/http2_inspect/http2_dummy_packet.h"
33 #include "service_inspectors/http2_inspect/http2_flow_data.h"
34 #include "log/unified2.h"
35 #include "protocols/packet.h"
36 #include "stream/stream.h"
37
38 #include "http_common.h"
39 #include "http_context_data.h"
40 #include "http_enum.h"
41 #include "http_js_norm.h"
42 #include "http_msg_body.h"
43 #include "http_msg_body_chunk.h"
44 #include "http_msg_body_cl.h"
45 #include "http_msg_body_h2.h"
46 #include "http_msg_body_old.h"
47 #include "http_msg_header.h"
48 #include "http_msg_request.h"
49 #include "http_msg_status.h"
50 #include "http_msg_trailer.h"
51 #include "http_test_manager.h"
52
53 using namespace snort;
54 using namespace HttpCommon;
55 using namespace HttpEnums;
56
GetUnreservedChars(const ByteBitSet & bitset)57 static std::string GetUnreservedChars(const ByteBitSet& bitset)
58 {
59 const ByteBitSet& def_bitset(HttpParaList::UriParam::UriParam::default_unreserved_char);
60 std::string chars;
61
62 for (unsigned char c = 1; c; ++c)
63 if (def_bitset[c] && !bitset[c])
64 chars += c;
65
66 return chars;
67 }
68
GetBadChars(const ByteBitSet & bitset)69 static std::string GetBadChars(const ByteBitSet& bitset)
70 {
71 std::stringstream ss;
72 ss << std::hex;
73
74 for (unsigned i = 0; i < bitset.size(); ++i)
75 if (bitset[i])
76 ss << " 0x" << std::setw(2) << std::setfill('0') << i;
77
78 auto str = ss.str();
79 if ( !str.empty() )
80 str.erase(0, 1);
81
82 return str;
83 }
84
85
GetXFFHeaders(const StrCode * header_list)86 static std::string GetXFFHeaders(const StrCode *header_list)
87 {
88 std::string hdr_list;
89 for (int idx = 0; header_list[idx].code; idx++)
90 {
91 hdr_list += header_list[idx].name;
92 hdr_list += " ";
93 }
94
95 // Remove the trailing whitespace, if any
96 if (hdr_list.length())
97 {
98 hdr_list.pop_back();
99 }
100 return hdr_list;
101 }
102
HttpInspect(const HttpParaList * params_)103 HttpInspect::HttpInspect(const HttpParaList* params_) :
104 params(params_),
105 xtra_trueip_id(Stream::reg_xtra_data_cb(get_xtra_trueip)),
106 xtra_uri_id(Stream::reg_xtra_data_cb(get_xtra_uri)),
107 xtra_host_id(Stream::reg_xtra_data_cb(get_xtra_host)),
108 xtra_jsnorm_id(Stream::reg_xtra_data_cb(get_xtra_jsnorm))
109 {
110 #ifdef REG_TEST
111 if (params->test_input)
112 {
113 HttpTestManager::activate_test_input(HttpTestManager::IN_HTTP);
114 }
115 if (params->test_output)
116 {
117 HttpTestManager::activate_test_output(HttpTestManager::IN_HTTP);
118 }
119 if ((params->test_input) || (params->test_output))
120 {
121 HttpTestManager::set_print_amount(params->print_amount);
122 HttpTestManager::set_print_hex(params->print_hex);
123 HttpTestManager::set_show_pegs(params->show_pegs);
124 HttpTestManager::set_show_scan(params->show_scan);
125 }
126 #endif
127
128 if (params->script_detection)
129 {
130 script_finder = new ScriptFinder(params->script_detection_handle);
131 }
132 }
133
configure(SnortConfig *)134 bool HttpInspect::configure(SnortConfig* )
135 {
136 params->js_norm_param.js_norm->configure();
137
138 return true;
139 }
140
show(const SnortConfig *) const141 void HttpInspect::show(const SnortConfig*) const
142 {
143 assert(params);
144
145 auto unreserved_chars = GetUnreservedChars(params->uri_param.unreserved_char);
146 auto bad_chars = GetBadChars(params->uri_param.bad_characters);
147 auto xff_headers = GetXFFHeaders(params->xff_headers);
148
149 std::string js_norm_ident_ignore;
150 for (auto s : params->js_norm_param.ignored_ids)
151 js_norm_ident_ignore += s + " ";
152
153 ConfigLogger::log_limit("request_depth", params->request_depth, -1LL);
154 ConfigLogger::log_limit("response_depth", params->response_depth, -1LL);
155 ConfigLogger::log_flag("unzip", params->unzip);
156 ConfigLogger::log_flag("normalize_utf", params->normalize_utf);
157 ConfigLogger::log_flag("decompress_pdf", params->decompress_pdf);
158 ConfigLogger::log_flag("decompress_swf", params->decompress_swf);
159 ConfigLogger::log_flag("decompress_zip", params->decompress_zip);
160 ConfigLogger::log_flag("decompress_vba", params->decompress_vba);
161 ConfigLogger::log_flag("script_detection", params->script_detection);
162 ConfigLogger::log_flag("normalize_javascript", params->js_norm_param.normalize_javascript);
163 ConfigLogger::log_value("max_javascript_whitespaces",
164 params->js_norm_param.max_javascript_whitespaces);
165 ConfigLogger::log_value("js_norm_bytes_depth", params->js_norm_param.js_norm_bytes_depth);
166 ConfigLogger::log_value("js_norm_identifier_depth", params->js_norm_param.js_identifier_depth);
167 ConfigLogger::log_value("js_norm_max_tmpl_nest", params->js_norm_param.max_template_nesting);
168 ConfigLogger::log_value("js_norm_max_bracket_depth", params->js_norm_param.max_bracket_depth);
169 ConfigLogger::log_value("js_norm_max_scope_depth", params->js_norm_param.max_scope_depth);
170 if (!js_norm_ident_ignore.empty())
171 ConfigLogger::log_list("js_norm_ident_ignore", js_norm_ident_ignore.c_str());
172 ConfigLogger::log_value("bad_characters", bad_chars.c_str());
173 ConfigLogger::log_value("ignore_unreserved", unreserved_chars.c_str());
174 ConfigLogger::log_flag("percent_u", params->uri_param.percent_u);
175 ConfigLogger::log_flag("utf8", params->uri_param.utf8);
176 ConfigLogger::log_flag("utf8_bare_byte", params->uri_param.utf8_bare_byte);
177 ConfigLogger::log_flag("iis_unicode", params->uri_param.iis_unicode);
178 ConfigLogger::log_value("iis_unicode_map_file", params->uri_param.iis_unicode_map_file.c_str());
179 ConfigLogger::log_value("iis_unicode_code_page", params->uri_param.iis_unicode_code_page);
180 ConfigLogger::log_flag("iis_double_decode", params->uri_param.iis_double_decode);
181 ConfigLogger::log_value("oversize_dir_length", params->uri_param.oversize_dir_length);
182 ConfigLogger::log_flag("backslash_to_slash", params->uri_param.backslash_to_slash);
183 ConfigLogger::log_flag("plus_to_space", params->uri_param.plus_to_space);
184 ConfigLogger::log_flag("simplify_path", params->uri_param.simplify_path);
185 ConfigLogger::log_value("xff_headers", xff_headers.c_str());
186 ConfigLogger::log_flag("request_body_app_detection", params->publish_request_body);
187 }
188
get_latest_is(const Packet * p)189 InspectSection HttpInspect::get_latest_is(const Packet* p)
190 {
191 HttpMsgSection* current_section = HttpContextData::get_snapshot(p);
192
193 if (current_section == nullptr)
194 return IS_NONE;
195
196 // FIXIT-L revisit why we need this check. We should not be getting a current section back
197 // for a raw packet but one of the test cases did exactly that.
198 if (!(p->packet_flags & PKT_PSEUDO))
199 return IS_NONE;
200
201 return current_section->get_inspection_section();
202 }
203
get_latest_src(const Packet * p)204 SourceId HttpInspect::get_latest_src(const Packet* p)
205 {
206 HttpMsgSection* current_section = HttpContextData::get_snapshot(p);
207
208 if (current_section == nullptr)
209 return SRC__NOT_COMPUTE;
210
211 return current_section->get_source_id();
212 }
213
get_buf(InspectionBuffer::Type ibt,Packet * p,InspectionBuffer & b)214 bool HttpInspect::get_buf(InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b)
215 {
216 switch (ibt)
217 {
218 case InspectionBuffer::IBT_KEY:
219 return get_buf(HTTP_BUFFER_URI, p, b);
220
221 case InspectionBuffer::IBT_HEADER:
222 if (get_latest_is(p) == IS_TRAILER)
223 return get_buf(HTTP_BUFFER_TRAILER, p, b);
224 else
225 return get_buf(HTTP_BUFFER_HEADER, p , b);
226
227 case InspectionBuffer::IBT_BODY:
228 return get_buf(HTTP_BUFFER_CLIENT_BODY, p, b);
229
230 case InspectionBuffer::IBT_RAW_KEY:
231 return get_buf(HTTP_BUFFER_RAW_URI, p , b);
232
233 case InspectionBuffer::IBT_RAW_HEADER:
234 if (get_latest_is(p) == IS_TRAILER)
235 return get_buf(HTTP_BUFFER_RAW_TRAILER, p, b);
236 else
237 return get_buf(HTTP_BUFFER_RAW_HEADER, p , b);
238
239 case InspectionBuffer::IBT_METHOD:
240 return get_buf(HTTP_BUFFER_METHOD, p , b);
241
242 case InspectionBuffer::IBT_STAT_CODE:
243 return get_buf(HTTP_BUFFER_STAT_CODE, p , b);
244
245 case InspectionBuffer::IBT_STAT_MSG:
246 return get_buf(HTTP_BUFFER_STAT_MSG, p , b);
247
248 case InspectionBuffer::IBT_COOKIE:
249 return get_buf(HTTP_BUFFER_COOKIE, p , b);
250
251 case InspectionBuffer::IBT_VBA:
252 return get_buf(BUFFER_VBA_DATA, p, b);
253
254 case InspectionBuffer::IBT_JS_DATA:
255 return get_buf(BUFFER_JS_DATA, p, b);
256
257 default:
258 return false;
259 }
260 }
261
get_buf(unsigned id,Packet * p,InspectionBuffer & b)262 bool HttpInspect::get_buf(unsigned id, Packet* p, InspectionBuffer& b)
263 {
264 Cursor c;
265 HttpBufferInfo buffer_info(id);
266
267 const Field& http_buffer = http_get_buf(c, p, buffer_info);
268
269 if (http_buffer.length() <= 0)
270 return false;
271
272 b.data = http_buffer.start();
273 b.len = http_buffer.length();
274 return true;
275 }
276
http_get_buf(Cursor & c,Packet * p,const HttpBufferInfo & buffer_info) const277 const Field& HttpInspect::http_get_buf(Cursor& c, Packet* p,
278 const HttpBufferInfo& buffer_info) const
279 {
280 HttpMsgSection* const current_section = HttpContextData::get_snapshot(p);
281
282 if (current_section == nullptr)
283 return Field::FIELD_NULL;
284
285 return current_section->get_classic_buffer(c, buffer_info);
286 }
287
http_get_num_headers(Packet * p,const HttpBufferInfo & buffer_info) const288 int32_t HttpInspect::http_get_num_headers(Packet* p,
289 const HttpBufferInfo& buffer_info) const
290 {
291 const HttpMsgSection* const current_section = HttpContextData::get_snapshot(p);
292
293 if (current_section == nullptr)
294 return STAT_NOT_COMPUTE;
295
296 return current_section->get_num_headers(buffer_info);
297 }
298
get_fp_buf(InspectionBuffer::Type ibt,Packet * p,InspectionBuffer & b)299 bool HttpInspect::get_fp_buf(InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b)
300 {
301 if (get_latest_is(p) == IS_NONE)
302 return false;
303
304 // Fast pattern buffers only supplied at specific times
305 switch (ibt)
306 {
307 case InspectionBuffer::IBT_KEY:
308 case InspectionBuffer::IBT_RAW_KEY:
309 // Many rules targeting POST feature http_uri fast pattern with http_client_body. We
310 // accept the performance hit of rerunning http_uri fast pattern with request body message
311 // sections
312 if (get_latest_src(p) != SRC_CLIENT)
313 return false;
314 break;
315 case InspectionBuffer::IBT_HEADER:
316 case InspectionBuffer::IBT_RAW_HEADER:
317 // http_header fast patterns for response bodies limited to first section
318 if ((get_latest_src(p) == SRC_SERVER) && (get_latest_is(p) == IS_BODY))
319 return false;
320 break;
321 case InspectionBuffer::IBT_BODY:
322 case InspectionBuffer::IBT_VBA:
323 case InspectionBuffer::IBT_JS_DATA:
324 if ((get_latest_is(p) != IS_FIRST_BODY) && (get_latest_is(p) != IS_BODY))
325 return false;
326 break;
327 case InspectionBuffer::IBT_METHOD:
328 if ((get_latest_src(p) != SRC_CLIENT) || (get_latest_is(p) == IS_BODY))
329 return false;
330 break;
331 case InspectionBuffer::IBT_STAT_CODE:
332 case InspectionBuffer::IBT_STAT_MSG:
333 if ((get_latest_src(p) != SRC_SERVER) || (get_latest_is(p) != IS_HEADER))
334 return false;
335 break;
336 case InspectionBuffer::IBT_COOKIE:
337 if (get_latest_is(p) != IS_HEADER)
338 return false;
339 break;
340 default:
341 break;
342 }
343 return get_buf(ibt, p, b);
344 }
345
get_xtra_trueip(Flow * flow,uint8_t ** buf,uint32_t * len,uint32_t * type)346 int HttpInspect::get_xtra_trueip(Flow* flow, uint8_t** buf, uint32_t* len, uint32_t* type)
347 {
348 HttpMsgSection* current_section = HttpContextData::get_snapshot(flow);
349
350 if (current_section == nullptr)
351 return 0;
352
353 HttpMsgHeader* const req_header = current_section->get_header(SRC_CLIENT);
354 if (req_header == nullptr)
355 return 0;
356 const Field& true_ip = req_header->get_true_ip_addr();
357 if (true_ip.length() <= 0)
358 return 0;
359
360 *buf = const_cast<uint8_t*>(true_ip.start());
361 *len = true_ip.length();
362 *type = (*len == 4) ? EVENT_INFO_XFF_IPV4 : EVENT_INFO_XFF_IPV6;
363 return 1;
364 }
365
get_xtra_uri(Flow * flow,uint8_t ** buf,uint32_t * len,uint32_t * type)366 int HttpInspect::get_xtra_uri(Flow* flow, uint8_t** buf, uint32_t* len, uint32_t* type)
367 {
368 HttpMsgSection* current_section = HttpContextData::get_snapshot(flow);
369
370 if (current_section == nullptr)
371 return 0;
372
373 HttpMsgRequest* const request = current_section->get_request();
374 if (request == nullptr)
375 return 0;
376 const Field& uri = request->get_uri();
377 if (uri.length() <= 0)
378 return 0;
379
380 *buf = const_cast<uint8_t*>(uri.start());
381 *len = uri.length();
382 *type = EVENT_INFO_HTTP_URI;
383
384 return 1;
385 }
386
get_xtra_host(Flow * flow,uint8_t ** buf,uint32_t * len,uint32_t * type)387 int HttpInspect::get_xtra_host(Flow* flow, uint8_t** buf, uint32_t* len, uint32_t* type)
388 {
389 HttpMsgSection* current_section = HttpContextData::get_snapshot(flow);
390
391 if (current_section == nullptr)
392 return 0;
393
394 HttpMsgHeader* const req_header = current_section->get_header(SRC_CLIENT);
395 if (req_header == nullptr)
396 return 0;
397 const Field& host = req_header->get_header_value_norm(HEAD_HOST);
398 if (host.length() <= 0)
399 return 0;
400
401 *buf = const_cast<uint8_t*>(host.start());
402 *len = host.length();
403 *type = EVENT_INFO_HTTP_HOSTNAME;
404
405 return 1;
406 }
407
408 // The name of this method reflects its legacy purpose. We actually return the normalized data
409 // from a response message body which may include other forms of normalization in addition to
410 // JavaScript normalization. But if you don't turn JavaScript normalization on you get nothing.
get_xtra_jsnorm(Flow * flow,uint8_t ** buf,uint32_t * len,uint32_t * type)411 int HttpInspect::get_xtra_jsnorm(Flow* flow, uint8_t** buf, uint32_t* len, uint32_t* type)
412 {
413 HttpMsgSection* current_section = HttpContextData::get_snapshot(flow);
414
415 if ((current_section == nullptr) ||
416 (current_section->get_source_id() != SRC_SERVER) ||
417 !current_section->get_params()->js_norm_param.normalize_javascript)
418 return 0;
419
420 HttpMsgBody* const body = current_section->get_body();
421 if (body == nullptr)
422 return 0;
423 assert((void*)body == (void*)current_section);
424 const Field& detect_data = body->get_detect_data();
425 if (detect_data.length() <= 0)
426 return 0;
427
428 *buf = const_cast<uint8_t*>(detect_data.start());
429 *len = detect_data.length();
430 *type = EVENT_INFO_JSNORM_DATA;
431
432 return 1;
433 }
434
disable_detection(Packet * p)435 void HttpInspect::disable_detection(Packet* p)
436 {
437 HttpFlowData* session_data = http_get_flow_data(p->flow);
438 if (session_data->for_http2)
439 p->disable_inspect = true;
440 else
441 {
442 assert(p->context);
443 DetectionEngine::disable_all(p);
444 }
445 }
446
http_get_flow_data(const Flow * flow)447 HttpFlowData* HttpInspect::http_get_flow_data(const Flow* flow)
448 {
449 Http2FlowData* h2i_flow_data = nullptr;
450 if (Http2FlowData::inspector_id != 0)
451 h2i_flow_data = (Http2FlowData*)flow->get_flow_data(Http2FlowData::inspector_id);
452 if (h2i_flow_data == nullptr)
453 return (HttpFlowData*)flow->get_flow_data(HttpFlowData::inspector_id);
454 else
455 return h2i_flow_data->get_hi_flow_data();
456 }
457
http_set_flow_data(Flow * flow,HttpFlowData * flow_data)458 void HttpInspect::http_set_flow_data(Flow* flow, HttpFlowData* flow_data)
459 {
460 // for_http2 set in HttpFlowData constructor after checking for h2i_flow_data
461 if (!flow_data->for_http2)
462 flow->set_flow_data(flow_data);
463 else
464 {
465 Http2FlowData* h2i_flow_data =
466 (Http2FlowData*)flow->get_flow_data(Http2FlowData::inspector_id);
467 assert(h2i_flow_data);
468 h2i_flow_data->set_hi_flow_data(flow_data);
469 }
470 }
471
eval(Packet * p)472 void HttpInspect::eval(Packet* p)
473 {
474 Profile profile(HttpModule::get_profile_stats());
475
476 const SourceId source_id = p->is_from_client() ? SRC_CLIENT : SRC_SERVER;
477
478 HttpFlowData* session_data = http_get_flow_data(p->flow);
479 if (session_data == nullptr)
480 {
481 assert(false);
482 return;
483 }
484
485 // FIXIT-M Workaround for unexpected eval() calls. Currently asserting when stream_user is in
486 // use due to calls to HttpInspect::eval on the raw stream_user packet
487 if ((session_data->section_type[source_id] == SEC__NOT_COMPUTE) ||
488 (session_data->type_expected[source_id] == SEC_ABORT) ||
489 (session_data->octets_reassembled[source_id] != p->dsize))
490 {
491 //assert(session_data->type_expected[source_id] != SEC_ABORT);
492 //assert(session_data->section_type[source_id] != SEC__NOT_COMPUTE);
493 //assert(session_data->octets_reassembled[source_id] == p->dsize);
494 session_data->type_expected[source_id] = SEC_ABORT;
495 return;
496 }
497
498 if (!session_data->for_http2)
499 HttpModule::increment_peg_counts(PEG_TOTAL_BYTES, p->dsize);
500
501 session_data->octets_reassembled[source_id] = STAT_NOT_PRESENT;
502
503 // Don't make pkt_data for headers available to detection
504 if ((session_data->section_type[source_id] == SEC_HEADER) ||
505 (session_data->section_type[source_id] == SEC_TRAILER))
506 {
507 p->set_detect_limit(0);
508 }
509
510 // Limit alt_dsize of message body sections to request/response depth
511 if ((session_data->detect_depth_remaining[source_id] > 0) &&
512 (session_data->detect_depth_remaining[source_id] < p->dsize))
513 {
514 p->set_detect_limit(session_data->detect_depth_remaining[source_id]);
515 }
516
517 if (!process(p->data, p->dsize, p->flow, source_id, true))
518 disable_detection(p);
519
520 #ifdef REG_TEST
521 else
522 {
523 if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
524 {
525 fprintf(HttpTestManager::get_output_file(), "Sent to detection %hu octets\n\n",
526 p->dsize);
527 fflush(HttpTestManager::get_output_file());
528 }
529 }
530 #endif
531
532 // If current transaction is complete then we are done with it. This is strictly a memory
533 // optimization not necessary for correct operation.
534 if ((source_id == SRC_SERVER) && (session_data->type_expected[SRC_SERVER] == SEC_STATUS) &&
535 session_data->transaction[SRC_SERVER]->final_response())
536 {
537 HttpTransaction::delete_transaction(session_data->transaction[SRC_SERVER], session_data);
538 session_data->transaction[SRC_SERVER] = nullptr;
539 }
540
541 // Whenever we process a packet we set these flags. If someone asks for an extra data
542 // buffer the JIT code will figure out if we actually have it.
543 SetExtraData(p, xtra_trueip_id);
544 SetExtraData(p, xtra_uri_id);
545 SetExtraData(p, xtra_host_id);
546 SetExtraData(p, xtra_jsnorm_id);
547 }
548
process(const uint8_t * data,const uint16_t dsize,Flow * const flow,SourceId source_id,bool buf_owner) const549 bool HttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow,
550 SourceId source_id, bool buf_owner) const
551 {
552 HttpMsgSection* current_section;
553 HttpFlowData* session_data = http_get_flow_data(flow);
554
555 if (!session_data->partial_flush[source_id])
556 HttpModule::increment_peg_counts(PEG_INSPECT);
557 else
558 HttpModule::increment_peg_counts(PEG_PARTIAL_INSPECT);
559
560 switch (session_data->section_type[source_id])
561 {
562 case SEC_REQUEST:
563 current_section = new HttpMsgRequest(
564 data, dsize, session_data, source_id, buf_owner, flow, params);
565 break;
566 case SEC_STATUS:
567 current_section = new HttpMsgStatus(
568 data, dsize, session_data, source_id, buf_owner, flow, params);
569 break;
570 case SEC_HEADER:
571 current_section = new HttpMsgHeader(
572 data, dsize, session_data, source_id, buf_owner, flow, params);
573 break;
574 case SEC_BODY_CL:
575 current_section = new HttpMsgBodyCl(
576 data, dsize, session_data, source_id, buf_owner, flow, params);
577 break;
578 case SEC_BODY_OLD:
579 current_section = new HttpMsgBodyOld(
580 data, dsize, session_data, source_id, buf_owner, flow, params);
581 break;
582 case SEC_BODY_CHUNK:
583 current_section = new HttpMsgBodyChunk(
584 data, dsize, session_data, source_id, buf_owner, flow, params);
585 break;
586 case SEC_BODY_H2:
587 current_section = new HttpMsgBodyH2(
588 data, dsize, session_data, source_id, buf_owner, flow, params);
589 break;
590 case SEC_TRAILER:
591 current_section = new HttpMsgTrailer(
592 data, dsize, session_data, source_id, buf_owner, flow, params);
593 break;
594 default:
595 assert(false);
596 if (buf_owner)
597 {
598 delete[] data;
599 }
600 return false;
601 }
602
603 current_section->analyze();
604 current_section->gen_events();
605 if (!session_data->partial_flush[source_id])
606 current_section->update_flow();
607 session_data->section_type[source_id] = SEC__NOT_COMPUTE;
608
609 #ifdef REG_TEST
610 if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
611 {
612 current_section->print_section(HttpTestManager::get_output_file());
613 fflush(HttpTestManager::get_output_file());
614 if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
615 {
616 printf("Finished processing section from test %" PRIi64 "\n",
617 HttpTestManager::get_test_number());
618 }
619 fflush(stdout);
620 }
621 #endif
622
623 current_section->publish();
624 return current_section->detection_required();
625 }
626
clear(Packet * p)627 void HttpInspect::clear(Packet* p)
628 {
629 Profile profile(HttpModule::get_profile_stats());
630
631 HttpFlowData* const session_data = http_get_flow_data(p->flow);
632
633 if (session_data == nullptr)
634 {
635 assert(false);
636 return;
637 }
638
639 Http2FlowData* h2i_flow_data = nullptr;
640 if (Http2FlowData::inspector_id != 0)
641 {
642 h2i_flow_data = (Http2FlowData*)p->flow->get_flow_data(Http2FlowData::inspector_id);
643 }
644
645 HttpMsgSection* current_section = nullptr;
646 if (h2i_flow_data != nullptr)
647 {
648 current_section = h2i_flow_data->get_hi_msg_section();
649 assert(current_section != nullptr);
650 h2i_flow_data->set_hi_msg_section(nullptr);
651 }
652 else
653 current_section = HttpContextData::clear_snapshot(p->context);
654
655 if ( current_section == nullptr )
656 {
657 //assert(false); //FIXIT-M This happens with stream_user
658 return;
659 }
660
661 current_section->clear();
662 HttpTransaction* current_transaction = current_section->get_transaction();
663
664 const SourceId source_id = current_section->get_source_id();
665
666 // FIXIT-M This check may not apply to the transaction attached to the packet
667 // in case of offload.
668 if (session_data->detection_status[source_id] == DET_DEACTIVATING)
669 {
670 if (source_id == SRC_CLIENT)
671 {
672 p->flow->set_to_server_detection(false);
673 }
674 else
675 {
676 p->flow->set_to_client_detection(false);
677 }
678 session_data->detection_status[source_id] = DET_OFF;
679 }
680
681 current_transaction->garbage_collect();
682 session_data->garbage_collect();
683
684 if (session_data->cutover_on_clear)
685 {
686 Flow* flow = p->flow;
687 flow->set_service(p, nullptr);
688 flow->free_flow_data(HttpFlowData::inspector_id);
689 }
690 }
691
692