00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 //
00004 // This program is free software; you can redistribute it and/or modify it
00005 // under the terms of the GNU General Public License Version 2 as published
00006 // by the Free Software Foundation. You may not use, modify or distribute
00007 // this program under any other version of the GNU General Public License.
00008 //
00009 // This program is distributed in the hope that it will be useful, but
00010 // WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program; if not, write to the Free Software Foundation, Inc.,
00016 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017 //--------------------------------------------------------------------------
00018 // http_flow_data.h author Tom Peters <thopeter@cisco.com>
00019
00020 #ifndef HTTP_FLOW_DATA_H
00021 #define HTTP_FLOW_DATA_H
00022
00023 #include <zlib.h>
00024
00025 #include <cstdio>
00026
00027 #include "flow/flow.h"
00028 #include "mime/file_mime_process.h"
00029 #include "utils/util_utf.h"
00030 #include "decompress/file_decomp.h"
00031
00032 #include "http_cutter.h"
00033 #include "http_infractions.h"
00034 #include "http_event_gen.h"
00035
00036 class HttpTransaction;
00037 class HttpJsNorm;
00038 class HttpMsgSection;
00039
00040 class HttpFlowData : public FlowData
00041 {
00042 public:
00043 HttpFlowData();
00044 ~HttpFlowData() override;
00045 static unsigned inspector_id;
00046 static void init() { inspector_id = FlowData::create_flow_data_id(); printf("inspector_id is %d\n", inspector_id);}
00047
00048 int get_section_type(int source_id);
00049
00050
00051 friend class HttpInspect;
00052 friend class HttpMsgSection;
00053 friend class HttpMsgStart;
00054 friend class HttpMsgRequest;
00055 friend class HttpMsgStatus;
00056 friend class HttpMsgHeader;
00057 friend class HttpMsgHeadShared;
00058 friend class HttpMsgTrailer;
00059 friend class HttpMsgBody;
00060 friend class HttpMsgBodyChunk;
00061 friend class HttpMsgBodyCl;
00062 friend class HttpMsgBodyOld;
00063 friend class HttpStreamSplitter;
00064 friend class HttpTransaction;
00065 #if defined(REG_TEST) || defined(UNIT_TEST)
00066 friend class HttpUnitTestSetup;
00067 #endif
00068
00069 private:
00070 // Convenience routines
00071 void half_reset(HttpEnums::SourceId source_id);
00072 void trailer_prep(HttpEnums::SourceId source_id);
00073
00074 // 0 element refers to client request, 1 element refers to server response
00075
00076 // FIXIT-P reorganize HttpFlowData to minimize void space
00077
00078 // *** StreamSplitter internal data - scan()
00079 HttpCutter* cutter[2] = { nullptr, nullptr };
00080
00081 // *** StreamSplitter internal data - reassemble()
00082 uint8_t* section_buffer[2] = { nullptr, nullptr };
00083 uint32_t section_total[2] = { 0, 0 };
00084 uint32_t section_offset[2] = { 0, 0 };
00085 HttpEnums::ChunkState chunk_state[2] = { HttpEnums::CHUNK_NEWLINES,
00086 HttpEnums::CHUNK_NEWLINES };
00087 uint32_t chunk_expected_length[2] = { 0, 0 };
00088 uint32_t running_total[2] = { 0, 0 };
00089
00090 // *** StreamSplitter internal data - scan() => reassemble()
00091 uint32_t num_excess[2] = { 0, 0 };
00092 bool is_broken_chunk[2] = { false, false };
00093 uint32_t num_good_chunks[2] = { 0, 0 };
00094 uint32_t octets_expected[2] = { 0, 0 };
00095 bool strict_length[2] = { false, false };
00096
00097 // *** StreamSplitter => Inspector (facts about the most recent message section)
00098 HttpEnums::SectionType section_type[2] = { HttpEnums::SEC__NOT_COMPUTE,
00099 HttpEnums::SEC__NOT_COMPUTE };
00100 // HttpEnums::SectionType saved_section_type[2] = { HttpEnums::SEC__NOT_COMPUTE,
00101 // HttpEnums::SEC__NOT_COMPUTE };
00102 bool tcp_close[2] = { false, false };
00103 int32_t num_head_lines[2] = { HttpEnums::STAT_NOT_PRESENT, HttpEnums::STAT_NOT_PRESENT };
00104 bool zero_byte_workaround[2];
00105
00106 // Infractions and events are associated with a specific message and are stored in the
00107 // transaction for that message. But StreamSplitter splits the start line before there is
00108 // a transaction and needs a place to put the problems it finds. Hence infractions and events
00109 // are created before there is a transaction to associate them with and stored here until
00110 // attach_my_transaction() takes them away and resets these to nullptr. The accessor methods
00111 // hide this from StreamSplitter.
00112 HttpInfractions* infractions[2] = { new HttpInfractions, new HttpInfractions };
00113 HttpEventGen* events[2] = { new HttpEventGen, new HttpEventGen };
00114 HttpInfractions* get_infractions(HttpEnums::SourceId source_id);
00115 HttpEventGen* get_events(HttpEnums::SourceId source_id);
00116
00117 // *** Inspector => StreamSplitter (facts about the message section that is coming next)
00118 HttpEnums::SectionType type_expected[2] = { HttpEnums::SEC_REQUEST, HttpEnums::SEC_STATUS };
00119 // length of the data from Content-Length field
00120 int64_t data_length[2] = { HttpEnums::STAT_NOT_PRESENT, HttpEnums::STAT_NOT_PRESENT };
00121 uint32_t section_size_target[2] = { 0, 0 };
00122 uint32_t section_size_max[2] = { 0, 0 };
00123 HttpEnums::CompressId compression[2] = { HttpEnums::CMP_NONE, HttpEnums::CMP_NONE };
00124 z_stream* compress_stream[2] = { nullptr, nullptr };
00125 uint64_t zero_nine_expected = 0;
00126
00127 // *** Inspector's internal data about the current message
00128 HttpEnums::VersionId version_id[2] = { HttpEnums::VERS__NOT_PRESENT,
00129 HttpEnums::VERS__NOT_PRESENT };
00130 HttpEnums::MethodId method_id = HttpEnums::METH__NOT_PRESENT;
00131 int32_t status_code_num = HttpEnums::STAT_NOT_PRESENT;
00132 int64_t file_depth_remaining[2] = { HttpEnums::STAT_NOT_PRESENT,
00133 HttpEnums::STAT_NOT_PRESENT };
00134 int64_t detect_depth_remaining[2] = { HttpEnums::STAT_NOT_PRESENT,
00135 HttpEnums::STAT_NOT_PRESENT };
00136 MimeSession* mime_state[2] = { nullptr, nullptr };
00137 UtfDecodeSession* utf_state = nullptr; // SRC_SERVER only
00138 fd_session_t* fd_state = nullptr; // SRC_SERVER only
00139 struct FdCallbackContext
00140 {
00141 HttpInfractions* infractions = nullptr;
00142 HttpEventGen* events = nullptr;
00143 };
00144 FdCallbackContext fd_alert_context; // SRC_SERVER only
00145 uint64_t expected_trans_num[2] = { 1, 1 };
00146 HttpMsgSection* latest_section = nullptr;
00147
00148 // number of user data octets seen so far (regular body or chunks)
00149 int64_t body_octets[2] = { HttpEnums::STAT_NOT_PRESENT, HttpEnums::STAT_NOT_PRESENT };
00150
00151 // Transaction management including pipelining
00152 // FIXIT-L pipeline deserves to be its own class
00153 HttpTransaction* transaction[2] = { nullptr, nullptr };
00154 static const int MAX_PIPELINE = 100; // requests seen - responses seen <= MAX_PIPELINE
00155 HttpTransaction** pipeline = nullptr;
00156 int pipeline_front = 0;
00157 int pipeline_back = 0;
00158 bool pipeline_overflow = false;
00159 bool pipeline_underflow = false;
00160
00161 bool add_to_pipeline(HttpTransaction* latest);
00162 HttpTransaction* take_from_pipeline();
00163 void delete_pipeline();
00164
00165 #ifdef REG_TEST
00166 void show(FILE* out_file) const;
00167
00168 static uint64_t instance_count;
00169 uint64_t seq_num;
00170 #endif
00171 };
00172
00173 #endif
00174
END OF CODE