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_cutter.h author Tom Peters <thopeter@cisco.com>
00019
00020 #ifndef HTTP_CUTTER_H
00021 #define HTTP_CUTTER_H
00022
00023 #include <cassert>
00024
00025 #include "http_enum.h"
00026 #include "http_event_gen.h"
00027 #include "http_infractions.h"
00028
00029 //-------------------------------------------------------------------------
00030 // HttpCutter class and subclasses
00031 //-------------------------------------------------------------------------
00032
00033 class HttpCutter
00034 {
00035 public:
00036 virtual ~HttpCutter() = default;
00037 virtual HttpEnums::ScanResult cut(const uint8_t* buffer, uint32_t length,
00038 HttpInfractions* infractions, HttpEventGen* events, uint32_t flow_target,
00039 uint32_t flow_max) = 0;
00040 uint32_t get_num_flush() const { return num_flush; }
00041 uint32_t get_octets_seen() const { return octets_seen; }
00042 uint32_t get_num_excess() const { return num_crlf; }
00043 virtual uint32_t get_num_head_lines() const { return 0; }
00044 virtual bool get_is_broken_chunk() const { return false; }
00045 virtual uint32_t get_num_good_chunks() const { return 0; }
00046
00047 protected:
00048 // number of octets processed by previous cut() calls that returned NOTFOUND
00049 uint32_t octets_seen = 0;
00050 uint32_t num_crlf = 0;
00051 uint32_t num_flush = 0;
00052 };
00053
00054 class HttpStartCutter : public HttpCutter
00055 {
00056 public:
00057 HttpEnums::ScanResult cut(const uint8_t* buffer, uint32_t length,
00058 HttpInfractions* infractions, HttpEventGen* events, uint32_t, uint32_t) override;
00059
00060 protected:
00061 enum ValidationResult { V_GOOD, V_BAD, V_TBD };
00062
00063 private:
00064 static const int MAX_LEADING_WHITESPACE = 20;
00065 virtual ValidationResult validate(uint8_t octet, HttpInfractions*, HttpEventGen*) = 0;
00066 bool validated = false;
00067 };
00068
00069 class HttpRequestCutter : public HttpStartCutter
00070 {
00071 private:
00072 uint32_t octets_checked = 0;
00073 ValidationResult validate(uint8_t octet, HttpInfractions*, HttpEventGen*) override;
00074 };
00075
00076 class HttpStatusCutter : public HttpStartCutter
00077 {
00078 private:
00079 uint32_t octets_checked = 0;
00080 ValidationResult validate(uint8_t octet, HttpInfractions*, HttpEventGen*) override;
00081 };
00082
00083 class HttpHeaderCutter : public HttpCutter
00084 {
00085 public:
00086 HttpEnums::ScanResult cut(const uint8_t* buffer, uint32_t length,
00087 HttpInfractions* infractions, HttpEventGen* events, uint32_t, uint32_t) override;
00088 uint32_t get_num_head_lines() const override { return num_head_lines; }
00089
00090 private:
00091 enum LineEndState { ZERO, HALF, ONE, THREEHALF };
00092 LineEndState state = ONE;
00093 int32_t num_head_lines = 0;
00094 };
00095
00096 class HttpBodyClCutter : public HttpCutter
00097 {
00098 public:
00099 explicit HttpBodyClCutter(int64_t expected_length) : remaining(expected_length)
00100 { assert(remaining > 0); }
00101 HttpEnums::ScanResult cut(const uint8_t*, uint32_t length, HttpInfractions*, HttpEventGen*,
00102 uint32_t flow_target, uint32_t flow_max) override;
00103
00104 private:
00105 int64_t remaining;
00106 };
00107
00108 class HttpBodyOldCutter : public HttpCutter
00109 {
00110 public:
00111 HttpEnums::ScanResult cut(const uint8_t*, uint32_t, HttpInfractions*, HttpEventGen*,
00112 uint32_t flow_target, uint32_t) override;
00113 };
00114
00115 class HttpBodyChunkCutter : public HttpCutter
00116 {
00117 public:
00118 HttpEnums::ScanResult cut(const uint8_t* buffer, uint32_t length,
00119 HttpInfractions* infractions, HttpEventGen* events, uint32_t flow_target, uint32_t)
00120 override;
00121 bool get_is_broken_chunk() const override { return curr_state == HttpEnums::CHUNK_BAD; }
00122 uint32_t get_num_good_chunks() const override { return num_good_chunks; }
00123
00124 private:
00125 uint32_t data_seen = 0;
00126 HttpEnums::ChunkState curr_state = HttpEnums::CHUNK_NEWLINES;
00127 uint32_t expected = 0;
00128 uint32_t num_zeros = 0;
00129 uint32_t digits_seen = 0;
00130 bool new_section = false;
00131 uint32_t num_good_chunks = 0; // that end in the current section
00132 };
00133
00134 #endif
00135
END OF CODE