From: Russ Combs Date: Tue, 7 Apr 2015 18:43:58 +0000 (-0400) Subject: new http refactoring and cleanup X-Git-Tag: 3.0.0-233~1005 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=488a08161df9d3dc15b8d8db1cf88ad99eb77cca;p=thirdparty%2Fsnort3.git new http refactoring and cleanup --- diff --git a/ChangeLog b/ChangeLog index f5e7b5990..98674fa33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ Pending - build 145 --- merge in new http changes: events from splitter plus additional - refactoring and cleanup +-- new http refactoring and cleanup +-- new http changes - events from splitter -- fix dns assertion; remove unused variables 15/03/31 - build 144 diff --git a/src/detection/detection_util.h b/src/detection/detection_util.h index 60279b8f5..7538ccd2e 100644 --- a/src/detection/detection_util.h +++ b/src/detection/detection_util.h @@ -36,6 +36,8 @@ #include "detect.h" #include "snort.h" #include "snort_debug.h" +// FIXIT-L temporary +#include "service_inspectors/nhttp_inspect/nhttp_inspect.h" #define DECODE_BLEN 65535 @@ -84,6 +86,8 @@ extern SO_PUBLIC THREAD_LOCAL DataPointer g_file_data; static inline void ClearHttpBuffers(void) { http_mask = 0; + // FIXIT-L temporary + NHttpInspect::latest_section = nullptr; } static inline uint32_t GetHttpBufferMask(void) diff --git a/src/service_inspectors/nhttp_inspect/nhttp_enum.h b/src/service_inspectors/nhttp_inspect/nhttp_enum.h index 701240ff8..77e200681 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_enum.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_enum.h @@ -29,132 +29,111 @@ static const int DATABLOCKSIZE = 16384; static const uint32_t NHTTP_GID = 219; // Field status codes for when no valid value is present in length or integer value. Positive -// values are actual length -// or field value. -typedef enum { STAT_NOSOURCE=-6, STAT_NOTCONFIGURED=-5, STAT_NOTCOMPUTE=-4, STAT_INSUFMEMORY=-3, - STAT_PROBLEMATIC=-2, - STAT_NOTPRESENT=-1, STAT_EMPTYSTRING=0, STAT_OTHER=1 } StatusCode; +// values are actual length or field value. +enum StatusCode { STAT_NOSOURCE=-6, STAT_NOTCONFIGURED=-5, STAT_NOTCOMPUTE=-4, STAT_INSUFMEMORY=-3, + STAT_PROBLEMATIC=-2, STAT_NOTPRESENT=-1, STAT_EMPTYSTRING=0, STAT_OTHER=1 }; // Message originator--client or server -typedef enum { SRC__NOTCOMPUTE=-4, SRC_CLIENT=0, SRC_SERVER=1 } SourceId; +enum SourceId { SRC__NOTCOMPUTE=-4, SRC_CLIENT=0, SRC_SERVER=1 }; // Type of message section -typedef enum { SEC_DISCARD = -10, SEC_CLOSED = -9, SEC_ABORT = -8, SEC__NOTCOMPUTE=-4, - SEC__NOTPRESENT=-1, - SEC_REQUEST = 2, SEC_STATUS, SEC_HEADER, SEC_BODY, SEC_CHUNK, - SEC_TRAILER } SectionType; +enum SectionType { SEC_DISCARD = -10, SEC_CLOSED = -9, SEC_ABORT = -8, SEC__NOTCOMPUTE=-4, + SEC__NOTPRESENT=-1, SEC_REQUEST = 2, SEC_STATUS, SEC_HEADER, SEC_BODY, SEC_CHUNK, + SEC_TRAILER }; // Result of scanning by splitter -typedef enum { SCAN_NOTFOUND, SCAN_FOUND, SCAN_DISCARD, SCAN_DISCARD_CONTINUE, - SCAN_ABORT } ScanResult; +enum ScanResult { SCAN_NOTFOUND, SCAN_FOUND, SCAN_DISCARD, SCAN_DISCARD_CONTINUE, SCAN_ABORT }; // Result of processing a message section--what needs to happen next -typedef enum { RES_INSPECT, RES_IGNORE, RES_AGGREGATE } ProcessResult; +enum ProcessResult { RES_INSPECT, RES_IGNORE, RES_AGGREGATE }; // List of possible HTTP versions. Version 0.9 omitted because 0.9 predates creation of the -// HTTP/X.Y token. There would -// never be a message with "HTTP/0.9" -typedef enum { VERS__NOSOURCE=-6, VERS__NOTCOMPUTE=-4, VERS__PROBLEMATIC=-2, VERS__NOTPRESENT=-1, - VERS__OTHER=1, - VERS_1_0, VERS_1_1, VERS_2_0 } VersionId; +// HTTP/X.Y token. There would never be a message with "HTTP/0.9" +enum VersionId { VERS__NOSOURCE=-6, VERS__NOTCOMPUTE=-4, VERS__PROBLEMATIC=-2, VERS__NOTPRESENT=-1, + VERS__OTHER=1, VERS_1_0, VERS_1_1, VERS_2_0 }; // Every request method we have ever heard of -typedef enum { METH__NOSOURCE=-6, METH__NOTCOMPUTE=-4, METH__INSUFMEMORY=-3, METH__PROBLEMATIC=-2, - METH__NOTPRESENT=-1, - METH__OTHER=1, METH_OPTIONS, METH_GET, METH_HEAD, METH_POST, METH_PUT, METH_DELETE, - METH_TRACE, METH_CONNECT, - METH_PROPFIND, METH_PROPPATCH, METH_MKCOL, METH_COPY, METH_MOVE, METH_LOCK, - METH_UNLOCK, METH_VERSION_CONTROL, - METH_REPORT, METH_CHECKOUT, METH_CHECKIN, METH_UNCHECKOUT, METH_MKWORKSPACE, - METH_UPDATE, METH_LABEL, METH_MERGE, - METH_BASELINE_CONTROL, METH_MKACTIVITY, METH_ORDERPATCH, METH_ACL, METH_PATCH, - METH_SEARCH, METH_BCOPY, METH_BDELETE, - METH_BMOVE, METH_BPROPFIND, METH_BPROPPATCH, METH_NOTIFY, METH_POLL, METH_SUBSCRIBE, - METH_UNSUBSCRIBE, - METH_X_MS_ENUMATTS, METH_BIND, METH_LINK, METH_MKCALENDAR, METH_MKREDIRECTREF, - METH_REBIND, METH_UNBIND, METH_UNLINK, - METH_UPDATEREDIRECTREF } MethodId; +enum MethodId { METH__NOSOURCE=-6, METH__NOTCOMPUTE=-4, METH__INSUFMEMORY=-3, METH__PROBLEMATIC=-2, + METH__NOTPRESENT=-1, METH__OTHER=1, METH_OPTIONS, METH_GET, METH_HEAD, METH_POST, METH_PUT, + METH_DELETE, METH_TRACE, METH_CONNECT, METH_PROPFIND, METH_PROPPATCH, METH_MKCOL, METH_COPY, + METH_MOVE, METH_LOCK, METH_UNLOCK, METH_VERSION_CONTROL, METH_REPORT, METH_CHECKOUT, + METH_CHECKIN, METH_UNCHECKOUT, METH_MKWORKSPACE, METH_UPDATE, METH_LABEL, METH_MERGE, + METH_BASELINE_CONTROL, METH_MKACTIVITY, METH_ORDERPATCH, METH_ACL, METH_PATCH, METH_SEARCH, + METH_BCOPY, METH_BDELETE, METH_BMOVE, METH_BPROPFIND, METH_BPROPPATCH, METH_NOTIFY, METH_POLL, + METH_SUBSCRIBE, METH_UNSUBSCRIBE, METH_X_MS_ENUMATTS, METH_BIND, METH_LINK, METH_MKCALENDAR, + METH_MKREDIRECTREF, METH_REBIND, METH_UNBIND, METH_UNLINK, METH_UPDATEREDIRECTREF }; // URI formats -typedef enum { URI__NOSOURCE=-6, URI__NOTCOMPUTE=-4, URI__PROBLEMATIC=-2, URI_ASTERISK = 2, - URI_AUTHORITY, URI_ABSPATH, - URI_ABSOLUTE } UriType; +enum UriType { URI__NOSOURCE=-6, URI__NOTCOMPUTE=-4, URI__PROBLEMATIC=-2, URI_ASTERISK = 2, + URI_AUTHORITY, URI_ABSPATH, URI_ABSOLUTE }; // URI schemes -typedef enum { SCH__NOSOURCE=-6, SCH__NOTCOMPUTE=-4, SCH__INSUFMEMORY=-3, SCH__NOTPRESENT=-1, - SCH_OTHER = 1, SCH_HTTP, - SCH_HTTPS, SCH_FTP, SCH_GOPHER, SCH_FILE } SchemeId; +enum SchemeId { SCH__NOSOURCE=-6, SCH__NOTCOMPUTE=-4, SCH__INSUFMEMORY=-3, SCH__NOTPRESENT=-1, + SCH_OTHER = 1, SCH_HTTP, SCH_HTTPS, SCH_FTP, SCH_GOPHER, SCH_FILE }; // Every header we have ever heard of -typedef enum { HEAD__NOTCOMPUTE=-4, HEAD__INSUFMEMORY=-3, HEAD__PROBLEMATIC=-2, HEAD__NOTPRESENT= - -1, HEAD__OTHER=1, - HEAD_CACHE_CONTROL, HEAD_CONNECTION, HEAD_DATE, HEAD_PRAGMA, HEAD_TRAILER, - HEAD_COOKIE, HEAD_SET_COOKIE, - HEAD_TRANSFER_ENCODING, HEAD_UPGRADE, HEAD_VIA, HEAD_WARNING, HEAD_ACCEPT, - HEAD_ACCEPT_CHARSET, HEAD_ACCEPT_ENCODING, - HEAD_ACCEPT_LANGUAGE, HEAD_AUTHORIZATION, HEAD_EXPECT, HEAD_FROM, HEAD_HOST, - HEAD_IF_MATCH, HEAD_IF_MODIFIED_SINCE, - HEAD_IF_NONE_MATCH, HEAD_IF_RANGE, HEAD_IF_UNMODIFIED_SINCE, HEAD_MAX_FORWARDS, - HEAD_PROXY_AUTHORIZATION, HEAD_RANGE, - HEAD_REFERER, HEAD_TE, HEAD_USER_AGENT, HEAD_ACCEPT_RANGES, HEAD_AGE, HEAD_ETAG, - HEAD_LOCATION, HEAD_PROXY_AUTHENTICATE, - HEAD_RETRY_AFTER, HEAD_SERVER, HEAD_VARY, HEAD_WWW_AUTHENTICATE, HEAD_ALLOW, - HEAD_CONTENT_ENCODING, HEAD_CONTENT_LANGUAGE, - HEAD_CONTENT_LENGTH, HEAD_CONTENT_LOCATION, HEAD_CONTENT_MD5, HEAD_CONTENT_RANGE, - HEAD_CONTENT_TYPE, HEAD_EXPIRES, - HEAD_LAST_MODIFIED, HEAD_X_FORWARDED_FOR, HEAD_TRUE_CLIENT_IP, - HEAD__MAXVALUE } HeaderId; +enum HeaderId { HEAD__NOTCOMPUTE=-4, HEAD__INSUFMEMORY=-3, HEAD__PROBLEMATIC=-2, + HEAD__NOTPRESENT=-1, HEAD__OTHER=1, HEAD_CACHE_CONTROL, HEAD_CONNECTION, HEAD_DATE, + HEAD_PRAGMA, HEAD_TRAILER, HEAD_COOKIE, HEAD_SET_COOKIE, HEAD_TRANSFER_ENCODING, HEAD_UPGRADE, + HEAD_VIA, HEAD_WARNING, HEAD_ACCEPT, HEAD_ACCEPT_CHARSET, HEAD_ACCEPT_ENCODING, + HEAD_ACCEPT_LANGUAGE, HEAD_AUTHORIZATION, HEAD_EXPECT, HEAD_FROM, HEAD_HOST, HEAD_IF_MATCH, + HEAD_IF_MODIFIED_SINCE, HEAD_IF_NONE_MATCH, HEAD_IF_RANGE, HEAD_IF_UNMODIFIED_SINCE, + HEAD_MAX_FORWARDS, HEAD_PROXY_AUTHORIZATION, HEAD_RANGE, HEAD_REFERER, HEAD_TE, + HEAD_USER_AGENT, HEAD_ACCEPT_RANGES, HEAD_AGE, HEAD_ETAG, HEAD_LOCATION, + HEAD_PROXY_AUTHENTICATE, HEAD_RETRY_AFTER, HEAD_SERVER, HEAD_VARY, HEAD_WWW_AUTHENTICATE, + HEAD_ALLOW, HEAD_CONTENT_ENCODING, HEAD_CONTENT_LANGUAGE, HEAD_CONTENT_LENGTH, + HEAD_CONTENT_LOCATION, HEAD_CONTENT_MD5, HEAD_CONTENT_RANGE, HEAD_CONTENT_TYPE, HEAD_EXPIRES, + HEAD_LAST_MODIFIED, HEAD_X_FORWARDED_FOR, HEAD_TRUE_CLIENT_IP, HEAD__MAXVALUE }; // All the infractions we might find while parsing and analyzing a message -typedef enum +enum Infraction { INF_TRUNCATED = 0, - INF_HEADTOOLONG, - INF_BADREQLINE, - INF_BADSTATLINE, - INF_TOOMANYHEADERS, - INF_BADHEADER, - INF_BADSTATCODE, - INF_UNKNOWNVERSION, - INF_BADVERSION, - INF_NOSCRATCH, - INF_BADHEADERREPS, - INF_BADHEADERDATA, + INF_HEAD_TOO_LONG, + INF_BAD_REQ_LINE, + INF_BAD_STAT_LINE, + INF_TOO_MANY_HEADERS, + INF_BAD_HEADER, + INF_BAD_STAT_CODE, + INF_UNKNOWN_VERSION, + INF_BAD_VERSION, + INF_NO_SCRATCH, + INF_BAD_HEADER_REPS, + INF_BAD_HEADER_DATA, INF_FIXIT_L_UNUSED, - INF_BADCHUNKSIZE, - INF_BADPHRASE, - INF_BADURI, - INF_BADPORT, - INF_URINEEDNORM, - INF_URIPERCENTNORMAL, - INF_URIPERCENTASCII, - INF_URIPERCENTUTF8, - INF_URIPERCENTUCODE, - INF_URIPERCENTOTHER, - INF_URIBADCHAR, - INF_URI8BITCHAR, - INF_URIMULTISLASH, - INF_URIBACKSLASH, - INF_URISLASHDOT, - INF_URISLASHDOTDOT, - INF_URIROOTTRAV, - INF_TOOMUCHLEADINGWS, - INF_ENDLESSHEADER, - INF_LFWITHOUTCR, -} Infraction; + INF_BAD_CHUNK_SIZE, + INF_BAD_PHRASE, + INF_BAD_URI, + INF_BAD_PORT, + INF_URI_NEED_NORM, + INF_URI_PERCENT_NORMAL, + INF_URI_PERCENT_ASCII, + INF_URI_PERCENT_UTF8, + INF_URI_PERCENT_UCODE, + INF_URI_PERCENT_OTHER, + INF_URI_BAD_CHAR, + INF_URI_8BIT_CHAR, + INF_URI_MULTISLASH, + INF_URI_BACKSLASH, + INF_URI_SLASH_DOT, + INF_URI_SLASH_DOT_DOT, + INF_URI_ROOT_TRAV, + INF_TOO_MUCH_LEADING_WS, + INF_ENDLESS_HEADER, + INF_LF_WITHOUT_CR, +}; // Formats for output from a header normalization function -typedef enum { NORM_NULL, NORM_FIELD, NORM_INT64, NORM_ENUM64, NORM_ENUM64LIST } NormFormat; +enum NormFormat { NORM_NULL, NORM_FIELD, NORM_INT64, NORM_ENUM64, NORM_ENUM64LIST }; // Types of character for URI scanning -typedef enum { CHAR_NORMAL=2, CHAR_PERCENT, CHAR_PATH, CHAR_INVALID, CHAR_EIGHTBIT } CharAction; +enum CharAction { CHAR_NORMAL=2, CHAR_PERCENT, CHAR_PATH, CHAR_INVALID, CHAR_EIGHTBIT }; // Transfer codings -typedef enum { TRANSCODE__OTHER=1, TRANSCODE_CHUNKED, TRANSCODE_IDENTITY, TRANSCODE_GZIP, - TRANSCODE_COMPRESS, - TRANSCODE_DEFLATE } Transcoding; +enum Transcoding { TRANSCODE__OTHER=1, TRANSCODE_CHUNKED, TRANSCODE_IDENTITY, TRANSCODE_GZIP, + TRANSCODE_COMPRESS, TRANSCODE_DEFLATE }; -typedef enum +enum EventSid { // FIXIT-L limit 64 before code changes required EVENT_ASCII = 1, EVENT_DOUBLE_DECODE, @@ -209,7 +188,7 @@ typedef enum EVENT_PDF_PARSE_FAILURE, EVENT_LOSS_OF_SYNC, EVENT_MAXVALUE -} EventSid; +}; extern const int8_t as_hex[256]; } // end namespace NHttpEnums diff --git a/src/service_inspectors/nhttp_inspect/nhttp_event_gen.h b/src/service_inspectors/nhttp_inspect/nhttp_event_gen.h index 2aa9f407a..c4914be0e 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_event_gen.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_event_gen.h @@ -36,7 +36,7 @@ public: void reset() { events_generated = 0; } void create_event(NHttpEnums::EventSid sid) { - assert((sid > 0) && (sid <= 64)); + assert(((int)sid > 0) && ((int)sid <= 64)); if ((events_generated & (((uint64_t)1) << (sid-1))) == 0) { SnortEventqAdd(NHttpEnums::NHTTP_GID, (uint32_t)sid); diff --git a/src/service_inspectors/nhttp_inspect/nhttp_field.cc b/src/service_inspectors/nhttp_inspect/nhttp_field.cc index 54cbfbfe3..4e5a5ea87 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_field.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_field.cc @@ -40,8 +40,8 @@ void Field::print(FILE* output, const char* name, bool int_vals) const fprintf(output, "\n"); return; } - const int32_t print_length = (length <= 1200) ? length : 1200; // Limit the amount of data - // printed + // Limit the amount of data printed + const int32_t print_length = (length <= 1200) ? length : 1200; for (int k=0; k < print_length; k++) { if ((start[k] >= 0x20) && (start[k] <= 0x7E)) diff --git a/src/service_inspectors/nhttp_inspect/nhttp_infractions.h b/src/service_inspectors/nhttp_inspect/nhttp_infractions.h index a4636fd0d..eabab65af 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_infractions.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_infractions.h @@ -30,7 +30,8 @@ class NHttpInfractions { public: NHttpInfractions() { } - NHttpInfractions(int inf) : infractions(((uint64_t)1) << inf) { assert((inf >= 0) && (inf < 64)); } + NHttpInfractions(int inf) : infractions(((uint64_t)1) << inf) + { assert((inf >= 0) && (inf < 64)); } void reset() { infractions = 0; } bool none_found() const { return infractions == 0; } NHttpInfractions& operator+=(const NHttpInfractions& rhs) @@ -41,8 +42,8 @@ public: { return (lhs.infractions & rhs.infractions) != 0; } // The following method is for convenience of debug and test output only! The 64-bit - // implementation will not be big enough forever and this interface cannot be all over the - // code. + // implementation will not be big enough forever and this interface cannot be all over + // the code. uint64_t get_raw() const { return infractions; } private: diff --git a/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc b/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc index 4538be216..1b353561d 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc @@ -31,6 +31,7 @@ #include "nhttp_msg_chunk.h" #include "nhttp_msg_trailer.h" #include "nhttp_test_manager.h" +#include "nhttp_field.h" #include "nhttp_inspect.h" using namespace NHttpEnums; @@ -47,6 +48,8 @@ NHttpInspect::NHttpInspect(bool test_input, bool test_output) } } +THREAD_LOCAL NHttpMsgSection* NHttpInspect::latest_section = nullptr; + bool NHttpInspect::get_buf(InspectionBuffer::Type ibt, Packet*, InspectionBuffer& b) { switch ( ibt ) @@ -67,15 +70,16 @@ bool NHttpInspect::get_buf(InspectionBuffer::Type ibt, Packet*, InspectionBuffer bool NHttpInspect::get_buf(unsigned id, Packet*, InspectionBuffer& b) { - const HttpBuffer* h = GetHttpBuffer((HTTP_BUFFER)id); + if (latest_section == nullptr) + return false; - if (!h) - { + const Field& legacy = latest_section->get_legacy(id); + + if (legacy.length <= 0) return false; - } - b.data = h->buf; - b.len = h->length; + b.data = legacy.start; + b.len = legacy.length; return true; } @@ -86,27 +90,25 @@ ProcessResult NHttpInspect::process(const uint8_t* data, const uint16_t dsize, F NHttpFlowData::nhttp_flow_id); assert(session_data != nullptr); - NHttpMsgSection* msg_section = nullptr; - switch (session_data->section_type[source_id]) { case SEC_REQUEST: - msg_section = new NHttpMsgRequest(data, dsize, session_data, source_id, buf_owner); + latest_section = new NHttpMsgRequest(data, dsize, session_data, source_id, buf_owner); break; case SEC_STATUS: - msg_section = new NHttpMsgStatus(data, dsize, session_data, source_id, buf_owner); + latest_section = new NHttpMsgStatus(data, dsize, session_data, source_id, buf_owner); break; case SEC_HEADER: - msg_section = new NHttpMsgHeader(data, dsize, session_data, source_id, buf_owner); + latest_section = new NHttpMsgHeader(data, dsize, session_data, source_id, buf_owner); break; case SEC_BODY: - msg_section = new NHttpMsgBody(data, dsize, session_data, source_id, buf_owner); + latest_section = new NHttpMsgBody(data, dsize, session_data, source_id, buf_owner); break; case SEC_CHUNK: - msg_section = new NHttpMsgChunk(data, dsize, session_data, source_id, buf_owner); + latest_section = new NHttpMsgChunk(data, dsize, session_data, source_id, buf_owner); break; case SEC_TRAILER: - msg_section = new NHttpMsgTrailer(data, dsize, session_data, source_id, buf_owner); + latest_section = new NHttpMsgTrailer(data, dsize, session_data, source_id, buf_owner); break; default: assert(0); @@ -117,19 +119,13 @@ ProcessResult NHttpInspect::process(const uint8_t* data, const uint16_t dsize, F return RES_IGNORE; } - msg_section->analyze(); - msg_section->update_flow(); - msg_section->gen_events(); - - ProcessResult return_value = msg_section->worth_detection(); - if (return_value == RES_INSPECT) - { - msg_section->legacy_clients(); - } + latest_section->analyze(); + latest_section->update_flow(); + latest_section->gen_events(); if (NHttpTestManager::use_test_output()) { - msg_section->print_section(NHttpTestManager::get_output_file()); + latest_section->print_section(NHttpTestManager::get_output_file()); fflush(NHttpTestManager::get_output_file()); if (NHttpTestManager::use_test_input()) { @@ -143,6 +139,6 @@ ProcessResult NHttpInspect::process(const uint8_t* data, const uint16_t dsize, F fflush(stdout); } - return return_value; + return latest_section->worth_detection(); } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_inspect.h b/src/service_inspectors/nhttp_inspect/nhttp_inspect.h index 921e81fb8..068160d05 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_inspect.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_inspect.h @@ -29,6 +29,7 @@ #include "nhttp_stream_splitter.h" class NHttpApi; +class NHttpMsgSection; class NHttpInspect : public Inspector { @@ -48,6 +49,8 @@ public: NHttpStreamSplitter(is_client_to_server, this); } + static THREAD_LOCAL NHttpMsgSection* latest_section; // FIXIT-L temporarily public + private: friend NHttpApi; friend NHttpStreamSplitter; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc index b6b4eccd6..42e4b6be0 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc @@ -47,6 +47,8 @@ void NHttpMsgBody::analyze() if (tcp_close && (body_octets < data_length)) infractions += INF_TRUNCATED; + // FIXIT-L try to find a more logical location for this + set_file_data((uint8_t*)data.start, (unsigned)data.length); } void NHttpMsgBody::gen_events() @@ -87,17 +89,3 @@ void NHttpMsgBody::update_flow() } } -// Legacy support function. Puts message fields into the buffers used by old Snort. -void NHttpMsgBody::legacy_clients() -{ - ClearHttpBuffers(); - legacy_request(); - legacy_status(); - legacy_header(false); - if (data.length > 0) - { - SetHttpBuffer(HTTP_BUFFER_CLIENT_BODY, data.start, (unsigned)data.length); - set_file_data((uint8_t*)data.start, (unsigned)data.length); - } -} - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_body.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_body.h index a302063eb..5e4ef2071 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_body.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_body.h @@ -36,7 +36,7 @@ public: void print_section(FILE* output) override; void gen_events() override; void update_flow() override; - void legacy_clients() override; + Field& get_data() { return data; } protected: int64_t data_length; // FIXIT-M this has no meaning in chunk subclass. Potential source of errors. diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc index 1b2b9d527..56a2a41c7 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc @@ -62,7 +62,7 @@ void NHttpMsgHeadShared::parse_header_block() } if (bytes_used < msg_text.length) { - infractions += INF_TOOMANYHEADERS; + infractions += INF_TOO_MANY_HEADERS; } } @@ -118,7 +118,7 @@ void NHttpMsgHeadShared::parse_header_lines() } else { - infractions += INF_BADHEADER; + infractions += INF_BAD_HEADER; } } } @@ -129,7 +129,7 @@ void NHttpMsgHeadShared::derive_header_name_id(int index) uint8_t* lower_name; if ((lower_name = scratch_pad.request(header_name[index].length)) == nullptr) { - infractions += INF_NOSCRATCH; + infractions += INF_NO_SCRATCH; header_name_id[index] = HEAD__INSUFMEMORY; return; } @@ -149,7 +149,7 @@ const Field& NHttpMsgHeadShared::get_header_value_norm(NHttpEnums::HeaderId head void NHttpMsgHeadShared::gen_events() { - if (infractions && INF_TOOMANYHEADERS) + if (infractions && INF_TOO_MANY_HEADERS) events.create_event(EVENT_MAX_HEADERS); } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_header.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_header.cc index 8a5c2773f..7cb55c5ff 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_header.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_header.cc @@ -54,8 +54,6 @@ void NHttpMsgHeader::print_section(FILE* output) void NHttpMsgHeader::update_flow() { - const uint64_t disaster_mask = 0; - // The following logic to determine body type is by no means the last word on this topic. // FIXIT-H need to distinguish methods such as POST that should have a body from those that // should not. @@ -66,11 +64,6 @@ void NHttpMsgHeader::update_flow() session_data->type_expected[source_id] = SEC_CLOSED; session_data->half_reset(source_id); } - else if (infractions && disaster_mask) - { - session_data->type_expected[source_id] = SEC_ABORT; - session_data->half_reset(source_id); - } else if ((source_id == SRC_SERVER) && ((status_code_num <= 199) || (status_code_num == 204) || (status_code_num == 304))) { @@ -139,12 +132,3 @@ ProcessResult NHttpMsgHeader::worth_detection() ? RES_INSPECT : RES_IGNORE; } -// Legacy support function. Puts message fields into the buffers used by old Snort. -void NHttpMsgHeader::legacy_clients() -{ - ClearHttpBuffers(); - legacy_request(); - legacy_status(); - legacy_header(false); -} - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_header.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_header.h index 69024db77..6b063dd8b 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_header.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_header.h @@ -35,7 +35,6 @@ public: void gen_events() override; void update_flow() override; NHttpEnums::ProcessResult worth_detection() override; - void legacy_clients() override; }; #endif diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc index 727bd2083..163cf14fa 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc @@ -51,7 +51,7 @@ void NHttpMsgRequest::parse_start_line() if (start_line.start[start_line.length-9] != ' ') { // space before "HTTP" missing or in wrong place - infractions += INF_BADREQLINE; + infractions += INF_BAD_REQ_LINE; return; } @@ -64,7 +64,7 @@ void NHttpMsgRequest::parse_start_line() if (space >= start_line.length-9) { // leading space or no space - infractions += INF_BADREQLINE; + infractions += INF_BAD_REQ_LINE; return; } @@ -112,27 +112,27 @@ void NHttpMsgRequest::gen_events() events.create_event(EVENT_UNKNOWN_METHOD); // URI character encoding events - if (uri && (uri->get_uri_infractions() && INF_URIPERCENTASCII)) + if (uri && (uri->get_uri_infractions() && INF_URI_PERCENT_ASCII)) events.create_event(EVENT_ASCII); - if (uri && (uri->get_uri_infractions() && INF_URIPERCENTUCODE)) + if (uri && (uri->get_uri_infractions() && INF_URI_PERCENT_UCODE)) events.create_event(EVENT_U_ENCODE); - if (uri && (uri->get_uri_infractions() && INF_URI8BITCHAR)) + if (uri && (uri->get_uri_infractions() && INF_URI_8BIT_CHAR)) events.create_event(EVENT_BARE_BYTE); - if (uri && (uri->get_uri_infractions() && INF_URIPERCENTUTF8)) + if (uri && (uri->get_uri_infractions() && INF_URI_PERCENT_UTF8)) events.create_event(EVENT_UTF_8); - if (uri && (uri->get_uri_infractions() && INF_URIBADCHAR)) + if (uri && (uri->get_uri_infractions() && INF_URI_BAD_CHAR)) events.create_event(EVENT_NON_RFC_CHAR); // URI path events - if (uri && (uri->get_path_infractions() && INF_URIMULTISLASH)) + if (uri && (uri->get_path_infractions() && INF_URI_MULTISLASH)) events.create_event(EVENT_MULTI_SLASH); - if (uri && (uri->get_path_infractions() && INF_URIBACKSLASH)) + if (uri && (uri->get_path_infractions() && INF_URI_BACKSLASH)) events.create_event(EVENT_IIS_BACKSLASH); - if (uri && (uri->get_path_infractions() && INF_URISLASHDOT)) + if (uri && (uri->get_path_infractions() && INF_URI_SLASH_DOT)) events.create_event(EVENT_SELF_DIR_TRAV); - if (uri && (uri->get_path_infractions() && INF_URISLASHDOTDOT)) + if (uri && (uri->get_path_infractions() && INF_URI_SLASH_DOT_DOT)) events.create_event(EVENT_DIR_TRAV); - if (uri && (uri->get_path_infractions() && INF_URIROOTTRAV)) + if (uri && (uri->get_path_infractions() && INF_URI_ROOT_TRAV)) events.create_event(EVENT_WEBROOT_DIR); } @@ -176,15 +176,13 @@ void NHttpMsgRequest::print_section(FILE* output) void NHttpMsgRequest::update_flow() { - const uint64_t disaster_mask = INF_BADREQLINE; - // The following logic to determine body type is by no means the last word on this topic. if (tcp_close) { session_data->type_expected[source_id] = SEC_CLOSED; session_data->half_reset(source_id); } - else if (infractions && disaster_mask) + else if (infractions && INF_BAD_REQ_LINE) { session_data->type_expected[source_id] = SEC_ABORT; session_data->half_reset(source_id); @@ -200,10 +198,3 @@ void NHttpMsgRequest::update_flow() session_data->section_type[source_id] = SEC__NOTCOMPUTE; } -// Legacy support function. Puts message fields into the buffers used by old Snort. -void NHttpMsgRequest::legacy_clients() -{ - ClearHttpBuffers(); - legacy_request(); -} - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_request.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_request.h index 38e2326e7..16e199dc6 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_request.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_request.h @@ -39,7 +39,6 @@ public: void print_section(FILE* output) override; void gen_events() override; void update_flow() override; - void legacy_clients() override; const Field& get_method() { return method; } const Field& get_uri(); const Field& get_uri_norm_legacy(); diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc index e75938d10..c5d0a4d27 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc @@ -29,6 +29,7 @@ #include "nhttp_msg_request.h" #include "nhttp_msg_status.h" #include "nhttp_msg_head_shared.h" +#include "nhttp_msg_body.h" using namespace NHttpEnums; @@ -54,15 +55,13 @@ void NHttpMsgSection::print_message_title(FILE* output, const char* title) const msg_text.print(output, "Input"); } -void NHttpMsgSection::print_message_wrapup(FILE* output) const +void NHttpMsgSection::print_message_wrapup(FILE* output) { fprintf(output, "Infractions: %" PRIx64 ", Events: %" PRIx64 ", TCP Close: %s\n", infractions.get_raw(), events.get_raw(), tcp_close ? "True" : "False"); - fprintf(output, "Interface to old clients. http_mask = %x.\n", http_mask); - for (int i=0; i < HTTP_BUFFER_MAX; i++) + for (unsigned k=1; k < HTTP_BUFFER_MAX; k++) { - if ((1 << i) & http_mask) - Field(http_buffer[i].length, http_buffer[i].buf).print(output, http_buffer_name[i]); + get_legacy(k).print(output, http_buffer_name[k]); } if (g_file_data.len > 0) { @@ -73,84 +72,78 @@ void NHttpMsgSection::print_message_wrapup(FILE* output) const fprintf(output, "\n"); } -void NHttpMsgSection::legacy_request() +const Field& NHttpMsgSection::get_legacy(unsigned buffer_id) { - NHttpMsgRequest* const request = transaction->get_request(); - if (request == nullptr) - return; - if (request->get_method().length > 0) + // When current section is trailers, that is what will be used for header and cookie buffers. + switch (buffer_id) { - SetHttpBuffer(HTTP_BUFFER_METHOD, request->get_method().start, - (unsigned)request->get_method().length); - } - if (request->get_uri().length > 0) - { - SetHttpBuffer(HTTP_BUFFER_RAW_URI, request->get_uri().start, - (unsigned)request->get_uri().length); - } - if (request->get_uri_norm_legacy().length > 0) - { - SetHttpBuffer(HTTP_BUFFER_URI, request->get_uri_norm_legacy().start, - (unsigned)request->get_uri_norm_legacy().length); - } -} - -void NHttpMsgSection::legacy_status() -{ - NHttpMsgStatus* const status = transaction->get_status(); - if (status == nullptr) - return; - if (status->get_status_code().length > 0) - { - SetHttpBuffer(HTTP_BUFFER_STAT_CODE, status->get_status_code().start, - (unsigned)status->get_status_code().length); - } - if (status->get_reason_phrase().length > 0) - { - SetHttpBuffer(HTTP_BUFFER_STAT_MSG, status->get_reason_phrase().start, - (unsigned)status->get_reason_phrase().length); - } -} - -void NHttpMsgSection::legacy_header(bool use_trailer) -{ - NHttpMsgHeadShared* const header = use_trailer ? - (NHttpMsgHeadShared*)transaction->get_trailer(source_id) : - (NHttpMsgHeadShared*)transaction->get_header(source_id); - if (header == nullptr) - return; - - if (header->get_headers().length > 0) - { - SetHttpBuffer(HTTP_BUFFER_RAW_HEADER, header->get_headers().start, - (unsigned)header->get_headers().length); - SetHttpBuffer(HTTP_BUFFER_HEADER, header->get_headers().start, - (unsigned)header->get_headers().length); - } - - legacy_cookie(header, source_id); -} - -// FIXIT-M there can be multiple cookie headers in one message. -void NHttpMsgSection::legacy_cookie(NHttpMsgHeadShared* header, SourceId source_id) -{ - HeaderId cookie_head = (source_id == SRC_CLIENT) ? HEAD_COOKIE : HEAD_SET_COOKIE; - - for (int k=0; k < header->get_num_headers(); k++) - { - if (header->get_header_name_id(k) == cookie_head) + case HTTP_BUFFER_CLIENT_BODY: + { + NHttpMsgBody* body = transaction->get_body(); + return (body != nullptr) ? body->get_data() : Field::FIELD_NULL; + } + case HTTP_BUFFER_COOKIE: + { + NHttpMsgHeadShared* header = transaction->get_latest_header(source_id); + if (header == nullptr) + return Field::FIELD_NULL; + HeaderId cookie_head = (source_id == SRC_CLIENT) ? HEAD_COOKIE : HEAD_SET_COOKIE; + return header->get_header_value_norm(cookie_head); + } + case HTTP_BUFFER_HEADER: + { + NHttpMsgHeadShared* header = transaction->get_latest_header(source_id); + return (header != nullptr) ? header->get_headers() : Field::FIELD_NULL; + } + case HTTP_BUFFER_METHOD: + { + NHttpMsgRequest* request = transaction->get_request(); + return (request != nullptr) ? request->get_method() : Field::FIELD_NULL; + } + case HTTP_BUFFER_RAW_COOKIE: + { + NHttpMsgHeadShared* header = transaction->get_latest_header(source_id); + if (header == nullptr) + return Field::FIELD_NULL; + HeaderId cookie_head = (source_id == SRC_CLIENT) ? HEAD_COOKIE : HEAD_SET_COOKIE; + // FIXIT-M there can be multiple cookie header in one message. + for (int k=0; k < header->get_num_headers(); k++) { - if (header->get_header_value(k).length > 0) - SetHttpBuffer(HTTP_BUFFER_RAW_COOKIE, header->get_header_value(k).start, - (unsigned)header->get_header_value(k).length); - break; + if (header->get_header_name_id(k) == cookie_head) + { + return header->get_header_value(k); + } } - } - - if (header->get_header_value_norm(cookie_head).length > 0) - { - SetHttpBuffer(HTTP_BUFFER_COOKIE, header->get_header_value_norm(cookie_head).start, - (unsigned)header->get_header_value_norm(cookie_head).length); + return Field::FIELD_NULL; + } + case HTTP_BUFFER_RAW_HEADER: + { + NHttpMsgHeadShared* header = transaction->get_latest_header(source_id); + return (header != nullptr) ? header->get_headers() : Field::FIELD_NULL; + } + case HTTP_BUFFER_RAW_URI: + { + NHttpMsgRequest* request = transaction->get_request(); + return (request != nullptr) ? request->get_uri() : Field::FIELD_NULL; + } + case HTTP_BUFFER_STAT_CODE: + { + NHttpMsgStatus* status = transaction->get_status(); + return (status != nullptr) ? status->get_status_code() : Field::FIELD_NULL; + } + case HTTP_BUFFER_STAT_MSG: + { + NHttpMsgStatus* status = transaction->get_status(); + return (status != nullptr) ? status->get_reason_phrase() : Field::FIELD_NULL; + } + case HTTP_BUFFER_URI: + { + NHttpMsgRequest* request = transaction->get_request(); + return (request != nullptr) ? request->get_uri_norm_legacy() : Field::FIELD_NULL; + } + default: + assert(0); + return Field::FIELD_NULL; } } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_section.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_section.h index fd64a0621..4f6aed28f 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_section.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_section.h @@ -20,6 +20,8 @@ #ifndef NHTTP_MSG_SECTION_H #define NHTTP_MSG_SECTION_H +#include "detection/detection_util.h" + #include "nhttp_scratch_pad.h" #include "nhttp_field.h" #include "nhttp_flow_data.h" @@ -46,8 +48,7 @@ public: // Manages the splitter and communication between message sections virtual void update_flow() = 0; - // Populates the raw and normalized buffer interface used by old Snort - virtual void legacy_clients() = 0; + const Field& get_legacy(unsigned buffer_id); // Should this section be sent directly to detection after inspection? virtual NHttpEnums::ProcessResult worth_detection() { return NHttpEnums::RES_INSPECT; } @@ -63,11 +64,7 @@ protected: // Convenience methods void print_message_title(FILE* output, const char* title) const; - void print_message_wrapup(FILE* output) const; - void legacy_request(); - void legacy_status(); - void legacy_header(bool use_trailer); - void legacy_cookie(NHttpMsgHeadShared* header, NHttpEnums::SourceId source_id); + void print_message_wrapup(FILE* output); const Field msg_text; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_start.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_start.cc index fe231b891..ff7ab2810 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_start.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_start.cc @@ -46,14 +46,14 @@ void NHttpMsgStart::derive_version_id() if (version.length != 8) { version_id = VERS__PROBLEMATIC; - infractions += INF_BADVERSION; + infractions += INF_BAD_VERSION; return; } if (memcmp(version.start, "HTTP/", 5) || (version.start[6] != '.')) { version_id = VERS__PROBLEMATIC; - infractions += INF_BADVERSION; + infractions += INF_BAD_VERSION; } else if ((version.start[5] == '1') && (version.start[7] == '1')) { @@ -71,12 +71,12 @@ void NHttpMsgStart::derive_version_id() (version.start[7] >= '0') && (version.start[7] <= '9')) { version_id = VERS__OTHER; - infractions += INF_UNKNOWNVERSION; + infractions += INF_UNKNOWN_VERSION; } else { version_id = VERS__PROBLEMATIC; - infractions += INF_BADVERSION; + infractions += INF_BAD_VERSION; } } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc index 8d9e2fc87..b579387bb 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc @@ -55,7 +55,7 @@ void NHttpMsgStatus::parse_start_line() // as error. HTTP/X.Y### if ((start_line.length < 13) || (start_line.start[8] != ' ') || (start_line.start[12] != ' ')) { - infractions += INF_BADSTATLINE; + infractions += INF_BAD_STAT_LINE; return; } version.start = start_line.start; @@ -69,7 +69,7 @@ void NHttpMsgStatus::parse_start_line() if ((reason_phrase.start[k] <= 31) || (reason_phrase.start[k] >= 127)) { // Illegal character in reason phrase - infractions += INF_BADPHRASE; + infractions += INF_BAD_PHRASE; break; } } @@ -93,7 +93,7 @@ void NHttpMsgStatus::derive_status_code_num() '0') || (status_code.start[1] > '9') || (status_code.start[2] < '0') || (status_code.start[2] > '9')) { - infractions += INF_BADSTATCODE; + infractions += INF_BAD_STAT_CODE; status_code_num = STAT_PROBLEMATIC; return; } @@ -101,7 +101,7 @@ void NHttpMsgStatus::derive_status_code_num() (status_code.start[2] - '0'); if ((status_code_num < 100) || (status_code_num > 599)) { - infractions += INF_BADSTATCODE; + infractions += INF_BAD_STAT_CODE; } } @@ -118,15 +118,13 @@ void NHttpMsgStatus::print_section(FILE* output) void NHttpMsgStatus::update_flow() { - const uint64_t disaster_mask = INF_BADSTATLINE; - // The following logic to determine body type is by no means the last word on this topic. if (tcp_close) { session_data->type_expected[source_id] = SEC_CLOSED; session_data->half_reset(source_id); } - else if (infractions && disaster_mask) + else if (infractions && INF_BAD_STAT_LINE) { session_data->type_expected[source_id] = SEC_ABORT; session_data->half_reset(source_id); @@ -142,11 +140,3 @@ void NHttpMsgStatus::update_flow() session_data->section_type[source_id] = SEC__NOTCOMPUTE; } -// Legacy support function. Puts message fields into the buffers used by old Snort. -void NHttpMsgStatus::legacy_clients() -{ - ClearHttpBuffers(); - legacy_request(); - legacy_status(); -} - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_status.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_status.h index 35d63823b..b8f836e5b 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_status.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_status.h @@ -36,7 +36,6 @@ public: void print_section(FILE* output) override; void gen_events() override; void update_flow() override; - void legacy_clients() override; const Field& get_status_code() { return status_code; } const Field& get_reason_phrase() { return reason_phrase; } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.cc index b937e5dee..091e48a2d 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.cc @@ -70,12 +70,3 @@ ProcessResult NHttpMsgTrailer::worth_detection() return (msg_text.length > 0) ? RES_INSPECT : RES_IGNORE; } -// Legacy support function. Puts message fields into the buffers used by old Snort. -void NHttpMsgTrailer::legacy_clients() -{ - ClearHttpBuffers(); - legacy_request(); - legacy_status(); - legacy_header(true); -} - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.h index 0e9b8c3ca..69ae8f45a 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.h @@ -35,7 +35,6 @@ public: void gen_events() override; void update_flow() override; NHttpEnums::ProcessResult worth_detection() override; - void legacy_clients() override; }; #endif diff --git a/src/service_inspectors/nhttp_inspect/nhttp_normalizers.cc b/src/service_inspectors/nhttp_inspect/nhttp_normalizers.cc index 3bfe3ece6..9c6665cdd 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_normalizers.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_normalizers.cc @@ -43,12 +43,12 @@ int32_t norm_decimal_integer(const uint8_t* in_buf, int32_t in_length, uint8_t* non_leading_zeros++; if (non_leading_zeros > 18) { - infractions += INF_BADHEADERDATA; + infractions += INF_BAD_HEADER_DATA; return STAT_PROBLEMATIC; } if ((value < 0) || (value > 9)) { - infractions += INF_BADHEADERDATA; + infractions += INF_BAD_HEADER_DATA; return STAT_PROBLEMATIC; } total = total*10 + value; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_splitter.cc b/src/service_inspectors/nhttp_inspect/nhttp_splitter.cc index d473fc8c6..ba392bad6 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_splitter.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_splitter.cc @@ -40,7 +40,7 @@ ScanResult NHttpStartSplitter::split(const uint8_t* buffer, uint32_t length, } else { - infractions += INF_TOOMUCHLEADINGWS; + infractions += INF_TOO_MUCH_LEADING_WS; events.create_event(EVENT_LOSS_OF_SYNC); return SCAN_ABORT; } @@ -102,7 +102,7 @@ ScanResult NHttpHeaderSplitter::split(const uint8_t* buffer, uint32_t length, // Alert on \n not preceded by \r. Correct cases are \r\n\r\n and \r\n. if (!((num_crlf == 4) || ((num_crlf == 2) && (first_lf == 0)))) { - infractions += INF_LFWITHOUTCR; + infractions += INF_LF_WITHOUT_CR; events.create_event(EVENT_IIS_DELIMITER); } num_flush = k + 1 + peek_octets; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc b/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc index d621e425b..c55afe0fc 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc @@ -163,7 +163,7 @@ StreamSplitter::Status NHttpStreamSplitter::scan(Flow* flow, const uint8_t* data case SCAN_NOTFOUND: if (splitter->get_octets_seen() == MAXOCTETS) { - session_data->infractions[source_id] += INF_ENDLESSHEADER; + session_data->infractions[source_id] += INF_ENDLESS_HEADER; session_data->events[source_id].create_event(EVENT_LOSS_OF_SYNC); // FIXIT-H need to process this data (except chunk header) not just discard it. session_data->type_expected[source_id] = SEC_ABORT; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_transaction.cc b/src/service_inspectors/nhttp_inspect/nhttp_transaction.cc index d88990cac..e6ae64a25 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_transaction.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_transaction.cc @@ -25,6 +25,7 @@ #include "nhttp_msg_status.h" #include "nhttp_msg_header.h" #include "nhttp_msg_trailer.h" +#include "nhttp_msg_body.h" using namespace NHttpEnums; @@ -76,8 +77,7 @@ NHttpTransaction* NHttpTransaction::attach_my_transaction(NHttpFlowData* session } else if (!session_data->add_to_pipeline(session_data->transaction[SRC_CLIENT])) { - // The pipeline is full and just overflowed. FIXIT-M we should alert and set - // infraction. + // The pipeline is full and just overflowed. FIXIT-M alert and set infraction. delete session_data->transaction[SRC_CLIENT]; } } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_transaction.h b/src/service_inspectors/nhttp_inspect/nhttp_transaction.h index fff88540f..00fb88ff5 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_transaction.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_transaction.h @@ -28,6 +28,8 @@ class NHttpMsgStatus; class NHttpMsgHeader; class NHttpMsgTrailer; class NHttpMsgSection; +class NHttpMsgBody; +class NHttpMsgHeadShared; class NHttpTransaction { @@ -44,19 +46,22 @@ public: NHttpMsgHeader* get_header(NHttpEnums::SourceId source_id) const { return header[source_id]; } void set_header(NHttpMsgHeader* header_, NHttpEnums::SourceId source_id) - { - header[source_id] = - header_; - } + { header[source_id] = header_; } NHttpMsgTrailer* get_trailer(NHttpEnums::SourceId source_id) const + { return trailer[source_id]; } + void set_trailer(NHttpMsgTrailer* trailer_, NHttpEnums::SourceId source_id) + { trailer[source_id] = trailer_; } + + NHttpMsgBody* get_body() const { return latest_body; } + void set_body(NHttpMsgBody* latest_body_) { latest_body = latest_body_; } + + // Convenience method + NHttpMsgHeadShared* get_latest_header(NHttpEnums::SourceId source_id) { - return trailer[source_id]; + return (trailer[source_id] != nullptr) ? (NHttpMsgHeadShared*)trailer[source_id] : + (NHttpMsgHeadShared*)header[source_id]; } - void set_trailer(NHttpMsgTrailer* trailer_, NHttpEnums::SourceId - source_id) { trailer[source_id] = trailer_; } - - void set_body(NHttpMsgSection* latest_body_) { latest_body = latest_body_; } private: NHttpTransaction() = default; @@ -65,7 +70,7 @@ private: NHttpMsgStatus* status = nullptr; NHttpMsgHeader* header[2] = { nullptr, nullptr }; NHttpMsgTrailer* trailer[2] = { nullptr, nullptr }; - NHttpMsgSection* latest_body = nullptr; + NHttpMsgBody* latest_body = nullptr; }; #endif diff --git a/src/service_inspectors/nhttp_inspect/nhttp_uri.cc b/src/service_inspectors/nhttp_inspect/nhttp_uri.cc index 589696992..327fb2cff 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_uri.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_uri.cc @@ -94,7 +94,7 @@ void NHttpUri::parse_uri() } else { - format_infractions += INF_BADURI; + format_infractions += INF_BAD_URI; uri_type = URI__PROBLEMATIC; scheme.length = STAT_PROBLEMATIC; authority.length = STAT_PROBLEMATIC; @@ -119,7 +119,7 @@ SchemeId NHttpUri::get_scheme_id() uint8_t* lower_scheme; if ((lower_scheme = scratch_pad.request(scheme.length)) == nullptr) { - scheme_infractions += INF_NOSCRATCH; + scheme_infractions += INF_NO_SCRATCH; scheme_id = SCH__INSUFMEMORY; return scheme_id; } @@ -205,7 +205,7 @@ int32_t NHttpUri::get_port_value() port_value = port_value * 10 + (port.start[k] - '0'); if ((port.start[k] < '0') || (port.start[k] > '9') || (port_value > 65535)) { - port_infractions += INF_BADPORT; + port_infractions += INF_BAD_PORT; port_value = STAT_PROBLEMATIC; break; } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.cc b/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.cc index 9e136ae07..b97f412fd 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_uri_norm.cc @@ -77,7 +77,7 @@ bool UriNormalizer::no_path_check(const uint8_t* in_buf, int32_t in_length, { if ((uri_char[in_buf[k]] == CHAR_NORMAL) || (uri_char[in_buf[k]] == CHAR_PATH)) continue; - infractions += INF_URINEEDNORM; + infractions += INF_URI_NEED_NORM; return false; } return true; @@ -93,7 +93,7 @@ bool UriNormalizer::path_check(const uint8_t* in_buf, int32_t in_length, continue; if ((in_buf[k] == '/') && ((k == 0) || (in_buf[k-1] != '/'))) continue; - infractions += INF_URINEEDNORM; + infractions += INF_URI_NEED_NORM; return false; } return true; @@ -112,11 +112,11 @@ int32_t UriNormalizer::norm_char_clean(const uint8_t* in_buf, int32_t in_length, out_buf[length++] = in_buf[k]; break; case CHAR_INVALID: - infractions += INF_URIBADCHAR; + infractions += INF_URI_BAD_CHAR; out_buf[length++] = in_buf[k]; break; case CHAR_EIGHTBIT: - infractions += INF_URI8BITCHAR; + infractions += INF_URI_8BIT_CHAR; out_buf[length++] = in_buf[k]; break; case CHAR_PERCENT: @@ -129,16 +129,16 @@ int32_t UriNormalizer::norm_char_clean(const uint8_t* in_buf, int32_t in_length, { // Normal % escape of an ASCII special character that is supposed to be // escaped - infractions += INF_URIPERCENTNORMAL; + infractions += INF_URI_PERCENT_NORMAL; out_buf[length++] = '%'; } else { // Suspicious % escape of an ASCII character that does not need to be // escaped - infractions += INF_URIPERCENTASCII; + infractions += INF_URI_PERCENT_ASCII; if (uri_char[value] == CHAR_INVALID) - infractions += INF_URIBADCHAR; + infractions += INF_URI_BAD_CHAR; out_buf[length++] = value; k += 2; } @@ -146,7 +146,7 @@ int32_t UriNormalizer::norm_char_clean(const uint8_t* in_buf, int32_t in_length, else { // UTF-8 decoding not implemented yet - infractions += INF_URIPERCENTUTF8; + infractions += INF_URI_PERCENT_UTF8; out_buf[length++] = '%'; } } @@ -155,13 +155,13 @@ int32_t UriNormalizer::norm_char_clean(const uint8_t* in_buf, int32_t in_length, && (as_hex[in_buf[k+4]] != -1) && (as_hex[in_buf[k+5]] != -1)) { // 'u' UTF-16 decoding not implemented yet - infractions += INF_URIPERCENTUCODE; + infractions += INF_URI_PERCENT_UCODE; out_buf[length++] = '%'; } else { // Don't recognize it - infractions += INF_URIPERCENTOTHER; + infractions += INF_URI_PERCENT_OTHER; out_buf[length++] = '%'; } break; @@ -181,7 +181,7 @@ int32_t UriNormalizer::norm_backslash(const uint8_t* in_buf, int32_t in_length, else { out_buf[k] = '/'; - infractions += INF_URIBACKSLASH; + infractions += INF_URI_BACKSLASH; } } return in_length; @@ -205,13 +205,13 @@ int32_t UriNormalizer::norm_path_clean(const uint8_t* in_buf, int32_t in_length, // Ignore this slash if it directly follows another slash else if ((k < in_length) && (length >= 1) && (out_buf[length-1] == '/')) { - infractions += INF_URIMULTISLASH; + infractions += INF_URI_MULTISLASH; } // This slash is the end of a /./ pattern, ignore this slash and remove the period from the // output else if ((length >= 2) && (out_buf[length-1] == '.') && (out_buf[length-2] == '/')) { - infractions += INF_URISLASHDOT; + infractions += INF_URI_SLASH_DOT; length -= 1; } // This slash is the end of a /../ pattern, normalization depends on whether there is a @@ -219,7 +219,7 @@ int32_t UriNormalizer::norm_path_clean(const uint8_t* in_buf, int32_t in_length, else if ((length >= 3) && (out_buf[length-1] == '.') && (out_buf[length-2] == '.') && (out_buf[length-3] == '/')) { - infractions += INF_URISLASHDOTDOT; + infractions += INF_URI_SLASH_DOT_DOT; // Traversing above the root of the absolute path. A path of the form // /../../../foo/bar/whatever cannot be further normalized. Instead of taking away a // directory we leave the .. and write out the new slash. This code can write out the @@ -229,7 +229,7 @@ int32_t UriNormalizer::norm_path_clean(const uint8_t* in_buf, int32_t in_length, ((length >= 6) && (out_buf[length-4] == '.') && (out_buf[length-5] == '.') && (out_buf[length-6] == '/'))) { - infractions += INF_URIROOTTRAV; + infractions += INF_URI_ROOT_TRAV; out_buf[length++] = '/'; } // Remove the previous directory from the output. "/foo/bar/../" becomes "/foo/"