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_flow_data.h author Tom Peters <thopeter@cisco.com>
19 
20 #ifndef HTTP_FLOW_DATA_H
21 #define HTTP_FLOW_DATA_H
22 
23 #include <zlib.h>
24 
25 #include <cstdio>
26 
27 #include "flow/flow.h"
28 #include "mime/file_mime_process.h"
29 #include "utils/util_utf.h"
30 #include "decompress/file_decomp.h"
31 
32 #include "http_common.h"
33 #include "http_enum.h"
34 #include "http_event.h"
35 
36 class HttpTransaction;
37 class HttpJsNorm;
38 class HttpMsgSection;
39 class HttpCutter;
40 class HttpQueryParser;
41 class JSIdentifierCtxBase;
42 
43 namespace snort
44 {
45 class JSNormalizer;
46 }
47 
48 class HttpFlowData : public snort::FlowData
49 {
50 public:
51     HttpFlowData(snort::Flow* flow);
52     ~HttpFlowData() override;
53     static unsigned inspector_id;
init()54     static void init() { inspector_id = snort::FlowData::create_flow_data_id(); }
55 
56     friend class HttpBodyCutter;
57     friend class HttpInspect;
58     friend class HttpJsNorm;
59     friend class HttpMsgSection;
60     friend class HttpMsgStart;
61     friend class HttpMsgRequest;
62     friend class HttpMsgStatus;
63     friend class HttpMsgHeader;
64     friend class HttpMsgHeadShared;
65     friend class HttpMsgTrailer;
66     friend class HttpMsgBody;
67     friend class HttpMsgBodyChunk;
68     friend class HttpMsgBodyCl;
69     friend class HttpMsgBodyH2;
70     friend class HttpMsgBodyOld;
71     friend class HttpQueryParser;
72     friend class HttpStreamSplitter;
73     friend class HttpTransaction;
74 #if defined(REG_TEST) || defined(UNIT_TEST)
75     friend class HttpUnitTestSetup;
76 #endif
77 
get_type_expected(HttpCommon::SourceId source_id)78     HttpEnums::SectionType get_type_expected(HttpCommon::SourceId source_id) const
79     { return type_expected[source_id]; }
80 
81     void finish_h2_body(HttpCommon::SourceId source_id, HttpEnums::H2BodyState state,
82         bool clear_partial_buffer);
83 
set_h2_body_state(HttpCommon::SourceId source_id,HttpEnums::H2BodyState state)84     void set_h2_body_state(HttpCommon::SourceId source_id, HttpEnums::H2BodyState state)
85     { h2_body_state[source_id] = state; }
86 
87     uint32_t get_h2_stream_id() const;
88 
89 private:
90     // HTTP/2 handling
91     bool for_http2 = false;
92     HttpEnums::H2BodyState h2_body_state[2] = { HttpEnums::H2_BODY_NOT_COMPLETE,
93          HttpEnums::H2_BODY_NOT_COMPLETE };
94     uint32_t h2_stream_id = 0;
95 
96     // Convenience routines
97     void half_reset(HttpCommon::SourceId source_id);
98     void trailer_prep(HttpCommon::SourceId source_id);
99     void garbage_collect();
100 
101     // 0 element refers to client request, 1 element refers to server response
102 
103     // *** StreamSplitter internal data - scan()
104     HttpCutter* cutter[2] = { nullptr, nullptr };
105 
106     // *** StreamSplitter internal data - reassemble()
107     uint8_t* section_buffer[2] = { nullptr, nullptr };
108     uint32_t section_offset[2] = { 0, 0 };
109     uint32_t chunk_expected_length[2] = { 0, 0 };
110     uint32_t running_total[2] = { 0, 0 };
111     HttpEnums::ChunkState chunk_state[2] = { HttpEnums::CHUNK_NEWLINES,
112         HttpEnums::CHUNK_NEWLINES };
113     uint32_t partial_raw_bytes[2] = { 0, 0 };
114     uint8_t* partial_buffer[2] = { nullptr, nullptr };
115     uint32_t partial_buffer_length[2] = { 0, 0 };
116 
117     // *** StreamSplitter internal data - scan() => reassemble()
118     uint32_t num_excess[2] = { 0, 0 };
119     uint32_t num_good_chunks[2] = { 0, 0 };
120     uint32_t octets_expected[2] = { 0, 0 };
121     bool is_broken_chunk[2] = { false, false };
122 
123     // *** StreamSplitter => Inspector (facts about the most recent message section)
124     HttpEnums::SectionType section_type[2] = { HttpEnums::SEC__NOT_COMPUTE,
125                                                 HttpEnums::SEC__NOT_COMPUTE };
126     int32_t octets_reassembled[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT };
127     int32_t num_head_lines[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT };
128     bool tcp_close[2] = { false, false };
129     bool partial_flush[2] = { false, false };
130     uint64_t last_connect_trans_w_early_traffic = 0;
131 
132     HttpInfractions* infractions[2] = { new HttpInfractions, new HttpInfractions };
133     HttpEventGen* events[2] = { new HttpEventGen, new HttpEventGen };
134 
135     // Infractions are associated with a specific message and are stored in the transaction for
136     // that message. But StreamSplitter splits the start line before there is a transaction and
137     // needs a place to put the problems it finds. Hence infractions are created before there is a
138     // transaction to associate them with and stored here until attach_my_transaction() takes them
139     // away and resets these to nullptr. The accessor method hides this from StreamSplitter.
140     HttpInfractions* get_infractions(HttpCommon::SourceId source_id);
141 
142     // *** Inspector => StreamSplitter (facts about the message section that is coming next)
143     HttpEnums::SectionType type_expected[2] = { HttpEnums::SEC_REQUEST, HttpEnums::SEC_STATUS };
144     uint64_t last_request_was_connect = false;
145     z_stream* compress_stream[2] = { nullptr, nullptr };
146     uint64_t zero_nine_expected = 0;
147     // length of the data from Content-Length field
148     int64_t data_length[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT };
149     uint32_t section_size_target[2] = { 0, 0 };
150     HttpEnums::CompressId compression[2] = { HttpEnums::CMP_NONE, HttpEnums::CMP_NONE };
151     HttpEnums::DetectionStatus detection_status[2] = { HttpEnums::DET_ON, HttpEnums::DET_ON };
152     bool stretch_section_to_packet[2] = { false, false };
153     bool accelerated_blocking[2] = { false, false };
154 
155     // *** Inspector's internal data about the current message
156     struct FdCallbackContext
157     {
158         HttpInfractions* infractions = nullptr;
159         HttpEventGen* events = nullptr;
160     };
161     FdCallbackContext fd_alert_context; // SRC_SERVER only
162     snort::MimeSession* mime_state[2] = { nullptr, nullptr };
163     snort::UtfDecodeSession* utf_state = nullptr; // SRC_SERVER only
164     fd_session_t* fd_state = nullptr; // SRC_SERVER only
165     int64_t file_depth_remaining[2] = { HttpCommon::STAT_NOT_PRESENT,
166         HttpCommon::STAT_NOT_PRESENT };
167     int64_t detect_depth_remaining[2] = { HttpCommon::STAT_NOT_PRESENT,
168         HttpCommon::STAT_NOT_PRESENT };
169     int32_t publish_depth_remaining[2] = { HttpCommon::STAT_NOT_PRESENT,
170         HttpCommon::STAT_NOT_PRESENT };
171     int32_t file_decomp_buffer_size_remaining[2] = { HttpCommon::STAT_NOT_PRESENT,
172         HttpCommon::STAT_NOT_PRESENT };
173     uint64_t expected_trans_num[2] = { 1, 1 };
174 
175     // number of user data octets seen so far (regular body or chunks)
176     int64_t body_octets[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT };
177     // normalized octets forwarded to file or MIME processing
178     int64_t file_octets[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT };
179     int32_t publish_octets[2] = { HttpCommon::STAT_NOT_PRESENT, HttpCommon::STAT_NOT_PRESENT };
180     uint32_t partial_inspected_octets[2] = { 0, 0 };
181     uint8_t* partial_detect_buffer[2] = { nullptr, nullptr };
182     uint32_t partial_detect_length[2] = { 0, 0 };
183     uint32_t partial_js_detect_length[2] = { 0, 0 };
184     int32_t status_code_num = HttpCommon::STAT_NOT_PRESENT;
185     HttpEnums::VersionId version_id[2] = { HttpEnums::VERS__NOT_PRESENT,
186                                             HttpEnums::VERS__NOT_PRESENT };
187     HttpEnums::MethodId method_id = HttpEnums::METH__NOT_PRESENT;
188 
189     // *** Transaction management including pipelining
190     static const int MAX_PIPELINE = 100;  // requests seen - responses seen <= MAX_PIPELINE
191     HttpTransaction* transaction[2] = { nullptr, nullptr };
192     HttpTransaction** pipeline = nullptr;
193     int16_t pipeline_front = 0;
194     int16_t pipeline_back = 0;
195     uint32_t pdu_idx = 0;
196     uint32_t js_pdu_idx = 0;
197     bool js_data_lost_once = false;
198     bool pipeline_overflow = false;
199     bool pipeline_underflow = false;
200 
201     bool add_to_pipeline(HttpTransaction* latest);
202     HttpTransaction* take_from_pipeline();
203     void delete_pipeline();
204 
205     // Transactions with uncleared sections awaiting deletion
206     HttpTransaction* discard_list = nullptr;
207 
208 
209     // Memory footprint required by zlib inflation. Formula from https://zlib.net/zlib_tech.html
210     // Accounts for a 32k sliding window and 11520 bytes of inflate_huft allocations
211     static const size_t zlib_inflate_memory = (1 << 15) + 1440*2*sizeof(int);
212 
213     // *** HttpJsNorm
214     JSIdentifierCtxBase* js_ident_ctx = nullptr;
215     snort::JSNormalizer* js_normalizer = nullptr;
216     bool js_continue = false;
217     bool js_built_in_event = false;
218 
219     void reset_js_pdu_idx();
220     void reset_js_ident_ctx();
221     snort::JSNormalizer& acquire_js_ctx(int32_t ident_depth, size_t norm_depth,
222         uint8_t max_template_nesting, uint32_t max_bracket_depth, uint32_t max_scope_depth,
223         const std::unordered_set<std::string>& ignored_ids);
224     void release_js_ctx();
225     bool is_pdu_missed();
226 
227     bool cutover_on_clear = false;
228     bool ssl_search_abandoned = false;
229 
230 #ifdef REG_TEST
231     static uint64_t instance_count;
232     uint64_t seq_num;
233 
234     void show(FILE* out_file) const;
235 #endif
236 };
237 
238 #endif
239 
240