From: Steve Chew (stechew) Date: Mon, 12 May 2025 20:37:27 +0000 (+0000) Subject: Pull request #4738: pub_sub: Can now get all headers, response str and method from... X-Git-Tag: 3.8.1.0~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b79ba287263b6f6b640a0b5f1ea066041c5d6299;p=thirdparty%2Fsnort3.git Pull request #4738: pub_sub: Can now get all headers, response str and method from HttpEvent. Merge in SNORT/snort3 from ~STECHEW/snort3:update_http_event to master Squashed commit of the following: commit 0e25d6025597408baa71bb7b0396c2affc7f746b Author: Steve Chew Date: Sat May 10 15:58:00 2025 -0400 pub_sub: Can now get all headers, response str and method from HttpEvent. --- diff --git a/src/pub_sub/http_events.cc b/src/pub_sub/http_events.cc index 9805e3b23..75676adde 100644 --- a/src/pub_sub/http_events.cc +++ b/src/pub_sub/http_events.cc @@ -47,6 +47,12 @@ const uint8_t* HttpEvent::get_header(unsigned id, uint64_t sub_id, int32_t& leng } } +// Returns all HTTP headers plus cookies. +const uint8_t* HttpEvent::get_all_raw_headers(int32_t& length) +{ + return get_header(HttpEnums::HTTP_BUFFER_RAW_HEADER, 0, length); +} + const uint8_t* HttpEvent::get_content_type(int32_t& length) { return get_header(HttpEnums::HTTP_BUFFER_HEADER, @@ -115,6 +121,11 @@ const uint8_t* HttpEvent::get_referer(int32_t& length) length); } +const uint8_t* HttpEvent::get_response_phrase(int32_t &length) +{ + return get_header(HttpEnums::HTTP_BUFFER_STAT_MSG, 0, length); +} + int32_t HttpEvent::get_response_code() { return http_msg_header->get_status_code_num(); @@ -164,6 +175,11 @@ const uint8_t* HttpEvent::get_x_working_with(int32_t& length) HttpEnums::HEAD_X_WORKING_WITH, length); } +const uint8_t* HttpEvent::get_method(int32_t& length) +{ + return get_header(HttpEnums::HTTP_BUFFER_METHOD, 0, length); +} + bool HttpEvent::contains_webdav_method() { HttpEnums::MethodId method = http_msg_header->get_method_id(); diff --git a/src/pub_sub/http_events.h b/src/pub_sub/http_events.h index 1d8a9b1bb..debe7f87a 100644 --- a/src/pub_sub/http_events.h +++ b/src/pub_sub/http_events.h @@ -37,12 +37,14 @@ public: HttpEvent(HttpMsgHeader* http_msg_header_, bool httpx, int64_t stream_id) : http_msg_header(http_msg_header_), is_httpx(httpx), httpx_stream_id(stream_id) { } + const uint8_t* get_all_raw_headers(int32_t &length); // Returns all HTTP headers plus cookies. const uint8_t* get_content_type(int32_t &length); const uint8_t* get_cookie(int32_t &length); const uint8_t* get_authority(int32_t &length); const uint8_t* get_uri_host(int32_t &length); const uint8_t* get_uri_query(int32_t &length); const uint8_t* get_location(int32_t &length); + const uint8_t* get_method(int32_t &length); const uint8_t* get_referer(int32_t &length); const uint8_t* get_server(int32_t &length); const uint8_t* get_trueip_addr(int32_t& length); @@ -50,6 +52,7 @@ public: const uint8_t* get_user_agent(int32_t &length); const uint8_t* get_via(int32_t &length); const uint8_t* get_x_working_with(int32_t &length); + const uint8_t* get_response_phrase(int32_t &length); int32_t get_response_code(); bool contains_webdav_method(); bool get_is_httpx() const; diff --git a/src/pub_sub/test/pub_sub_http_event_test.cc b/src/pub_sub/test/pub_sub_http_event_test.cc index a963e8476..0851de65f 100644 --- a/src/pub_sub/test/pub_sub_http_event_test.cc +++ b/src/pub_sub/test/pub_sub_http_event_test.cc @@ -49,8 +49,13 @@ void Field::set(const Field& input) } const Field Field::FIELD_NULL { STAT_NO_SOURCE }; -const Field& HttpMsgSection::get_classic_buffer(unsigned, uint64_t, uint64_t) -{ return Field::FIELD_NULL; } +const Field& HttpMsgSection::get_classic_buffer(unsigned buffer_type, uint64_t, uint64_t) +{ + mock().actualCall("get_classic_buffer").withParameter("buffer_type", buffer_type); + Field *out = (Field*)mock().getData("output").getObjectPointer(); + return (*out); +} + const Field& HttpMsgHeader::get_true_ip_addr() { Field *out = (Field*)mock().getData("output").getObjectPointer(); @@ -113,6 +118,55 @@ TEST(pub_sub_http_event_test, true_ip_addr) mock().checkExpectations(); } +TEST(pub_sub_http_event_test, get_method) +{ + const uint8_t* header_start; + int32_t header_length; + + mock().expectOneCall("get_classic_buffer").withParameter("buffer_type", HttpEnums::HTTP_BUFFER_METHOD); + Field input(7, (const uint8_t*) "CONNECT"); + mock().setDataObject("output", "Field", &input); + HttpEvent event(nullptr, false, 0); + header_start = event.get_method(header_length); + CHECK(7 == header_length); + CHECK(memcmp(header_start, "CONNECT", 7) == 0); + mock().checkExpectations(); +} + +TEST(pub_sub_http_event_test, get_response_phrase) +{ + const uint8_t* header_start; + int32_t header_length; + + mock().expectOneCall("get_classic_buffer").withParameter("buffer_type", HttpEnums::HTTP_BUFFER_STAT_MSG); + + Field input(7, (const uint8_t*) "CONNECT"); + mock().setDataObject("output", "Field", &input); + HttpEvent event(nullptr, false, 0); + header_start = event.get_response_phrase(header_length); + CHECK(7 == header_length); + CHECK(memcmp(header_start, "CONNECT", 7) == 0); + mock().checkExpectations(); +} + +TEST(pub_sub_http_event_test, get_all_raw_headers) +{ + const char* headers = "Content-Type: application/pdf\n" + "Content-Length: 20000\n"; + int32_t header_length = strlen(headers); + const uint8_t* header_start; + int32_t discovered_length; + + mock().expectOneCall("get_classic_buffer").withParameter("buffer_type", HttpEnums::HTTP_BUFFER_RAW_HEADER); + Field input(header_length, (const uint8_t*) headers); + mock().setDataObject("output", "Field", &input); + HttpEvent event(nullptr, false, 0); + header_start = event.get_all_raw_headers(discovered_length); + CHECK(discovered_length == header_length); + CHECK(memcmp(header_start, headers, header_length) == 0); + mock().checkExpectations(); +} + int main(int argc, char** argv) { return CommandLineTestRunner::RunAllTests(argc, argv);