]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #194 in SNORT/snort3 from nhttp30C to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Wed, 16 Dec 2015 11:09:48 +0000 (06:09 -0500)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Wed, 16 Dec 2015 11:09:48 +0000 (06:09 -0500)
Squashed commit of the following:

commit f6bbe467682a6269af7ebbe9ce124b2010d2f152
Author: Tom Peters <thopeter@cisco.com>
Date:   Tue Dec 15 16:39:54 2015 -0500

    cmake fix

commit b62e8b4430330b6ffc01d5bfdb91dc2a06b8d78a
Author: Tom Peters <thopeter@cisco.com>
Date:   Wed Nov 11 17:47:18 2015 -0500

    NHI IPS rule options

28 files changed:
src/service_inspectors/nhttp_inspect/CMakeLists.txt
src/service_inspectors/nhttp_inspect/Makefile.am
src/service_inspectors/nhttp_inspect/ips_nhttp.cc [new file with mode: 0644]
src/service_inspectors/nhttp_inspect/ips_nhttp.h [new file with mode: 0644]
src/service_inspectors/nhttp_inspect/nhttp_api.cc
src/service_inspectors/nhttp_inspect/nhttp_api.h
src/service_inspectors/nhttp_inspect/nhttp_enum.h
src/service_inspectors/nhttp_inspect/nhttp_inspect.cc
src/service_inspectors/nhttp_inspect/nhttp_inspect.h
src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_body.h
src/service_inspectors/nhttp_inspect/nhttp_msg_body_chunk.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_body_cl.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_body_old.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.h
src/service_inspectors/nhttp_inspect/nhttp_msg_header.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_header.h
src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_request.h
src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_section.h
src/service_inspectors/nhttp_inspect/nhttp_msg_start.h
src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.h
src/service_inspectors/nhttp_inspect/nhttp_str_to_code.cc
src/service_inspectors/nhttp_inspect/nhttp_tables.cc
src/service_inspectors/nhttp_inspect/nhttp_transaction.h

index 37088181eb31df37c41545b6b3858df0e445fe96..153d82928b3d47cba372ee39ee8c494cc9ab45b2 100644 (file)
@@ -64,3 +64,6 @@ if (STATIC_INSPECTORS)
 else(STATIC_INSPECTORS)
     add_shared_library(nhttp_inspect inspectors ${FILE_LIST})
 endif(STATIC_INSPECTORS)
+
+add_shared_library(nhttp_inspect_opt inspectors ips_nhttp.cc ips_nhttp.h)
+
index c6bc8496fa94091f5f9c37ff6bf53e03a687423b..00454889087b301725a3a11ceeaf2ab93ac3979d 100644 (file)
@@ -44,5 +44,12 @@ libnhttp_inspect_la_LDFLAGS = -export-dynamic -shared
 libnhttp_inspect_la_SOURCES = $(file_list)
 endif
 
+optlibdir = $(pkglibdir)/inspectors
+
+optlib_LTLIBRARIES = libnhttp_inspect_opt.la
+libnhttp_inspect_opt_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
+libnhttp_inspect_opt_la_LDFLAGS = -export-dynamic -shared
+libnhttp_inspect_opt_la_SOURCES = ips_nhttp.cc ips_nhttp.h
+
 AM_CXXFLAGS = @AM_CXXFLAGS@
 
diff --git a/src/service_inspectors/nhttp_inspect/ips_nhttp.cc b/src/service_inspectors/nhttp_inspect/ips_nhttp.cc
new file mode 100644 (file)
index 0000000..ba45e53
--- /dev/null
@@ -0,0 +1,863 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_nhttp.cc author Tom Peters <thopeter@cisco.com>
+
+#include <array>
+
+#include "protocols/packet.h"
+#include "flow/flow.h"
+#include "detection/detection_defines.h"
+#include "framework/cursor.h"
+
+#include "nhttp_inspect.h"
+#include "nhttp_msg_head_shared.h"
+#include "ips_nhttp.h"
+
+using namespace NHttpEnums;
+
+THREAD_LOCAL std::array<ProfileStats, PSI_MAX> NHttpCursorModule::http_ps;
+
+bool NHttpCursorModule::begin(const char*, int, SnortConfig*)
+{
+    para_list.reset();
+    sub_id = 0;
+    switch (buffer_index)
+    {
+    case NHTTP_BUFFER_URI:
+    case NHTTP_BUFFER_RAW_URI:
+    case NHTTP_BUFFER_STAT_CODE:
+    case NHTTP_BUFFER_STAT_MSG:
+    case NHTTP_BUFFER_VERSION:
+    case NHTTP_BUFFER_METHOD:
+        inspect_section = IS_START;
+        break;
+    case NHTTP_BUFFER_HEADER:
+    case NHTTP_BUFFER_RAW_HEADER:
+    case NHTTP_BUFFER_COOKIE:
+    case NHTTP_BUFFER_RAW_COOKIE:
+        inspect_section = IS_HEADER;
+        break;
+    case NHTTP_BUFFER_CLIENT_BODY:
+        inspect_section = IS_BODY;
+        break;
+    case NHTTP_BUFFER_TRAILER:
+    case NHTTP_BUFFER_RAW_TRAILER:
+        inspect_section = IS_TRAILER;
+        break;
+    default:
+        assert(false);
+    }
+    return true;
+}
+
+bool NHttpCursorModule::set(const char*, Value& v, SnortConfig*)
+{
+    if (v.is("field"))
+    {
+        if (sub_id != 0)
+            ParseError("Only specify one header field to match");
+        para_list.field = v.get_string();
+        const int32_t name_size = (para_list.field.size() <= MAX_FIELD_NAME_LENGTH) ?
+            para_list.field.size() : MAX_FIELD_NAME_LENGTH;
+        uint8_t lower_name[MAX_FIELD_NAME_LENGTH];
+        for (int32_t k=0; k < name_size; k++)
+        {
+            lower_name[k] = ((para_list.field[k] < 'A') || (para_list.field[k] > 'Z')) ?
+                para_list.field[k] : para_list.field[k] - ('A' - 'a');
+        }
+        sub_id = str_to_code(lower_name, name_size, NHttpMsgHeadShared::header_list);
+        if (sub_id == STAT_OTHER)
+            ParseError("Unrecognized header field name");
+    }
+    else if (v.is("with_header"))
+    {
+        para_list.with_header = true;
+        inspect_section = IS_HEADER;
+    }
+    else if (v.is("with_body"))
+    {
+        para_list.with_body = true;
+        inspect_section = IS_BODY;
+    }
+    else if (v.is("with_trailer"))
+    {
+        para_list.with_trailer = true;
+        inspect_section = IS_TRAILER;
+    }
+    else if (v.is("scheme"))
+    {
+        para_list.scheme = true;
+        sub_id = UC_SCHEME;
+    }
+    else if (v.is("host"))
+    {
+        para_list.host = true;
+        sub_id = UC_HOST;
+    }
+    else if (v.is("port"))
+    {
+        para_list.port = true;
+        sub_id = UC_PORT;
+    }
+    else if (v.is("path"))
+    {
+        para_list.path = true;
+        sub_id = UC_PATH;
+    }
+    else if (v.is("query"))
+    {
+        para_list.query = true;
+        sub_id = UC_QUERY;
+    }
+    else if (v.is("fragment"))
+    {
+        para_list.fragment = true;
+        sub_id = UC_FRAGMENT;
+    }
+    else
+    {
+        return false;
+    }
+    return true;
+}
+
+bool NHttpCursorModule::end(const char*, int, SnortConfig*)
+{
+    // Check for option conflicts
+    if (para_list.with_header + para_list.with_body + para_list.with_trailer > 1)
+        ParseError("Only specify one with_ option. Use the one that happens last.");
+    if (para_list.scheme + para_list.host + para_list.port + para_list.path + para_list.query +
+          para_list.fragment > 1)
+        ParseError("Only specify one part of the URI");
+    return true;
+}
+
+void NHttpCursorModule::NHttpRuleParaList::reset()
+{
+    field.clear();
+    with_header = false;
+    with_body = false;
+    with_trailer = false;
+    scheme = false;
+    host = false;
+    port = false;
+    path = false;
+    query = false;
+    fragment = false;
+}
+
+int NHttpIpsOption::eval(Cursor& c, Packet* p)
+{
+    Profile profile(NHttpCursorModule::http_ps[psi]);
+
+    if (!p->flow || !p->flow->gadget)
+        return DETECTION_OPTION_NO_MATCH;
+
+    if (NHttpInspect::get_latest_is() != inspect_section)
+        return DETECTION_OPTION_NO_MATCH;
+
+    InspectionBuffer hb;
+
+    if (! ((NHttpInspect*)(p->flow->gadget))->get_buf((unsigned)buffer_index, sub_id, nullptr, hb))
+        return DETECTION_OPTION_NO_MATCH;
+
+    c.set(key, hb.data, hb.len);
+
+    return DETECTION_OPTION_MATCH;
+}
+
+//-------------------------------------------------------------------------
+// http_uri
+//-------------------------------------------------------------------------
+
+static const Parameter http_uri_params[] =
+{
+    { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message headers" },
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { "scheme", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against scheme section of URI only" },
+    { "host", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against host section of URI only" },
+    { "port", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against port section of URI only" },
+    { "path", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against path section of URI only" },
+    { "query", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against query section of URI only" },
+    { "fragment", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against fragment section of URI only" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_uri"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the normalized URI buffer"
+
+static Module* uri_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_URI, CAT_SET_KEY, PSI_URI,
+        http_uri_params);
+}
+
+static const IpsApi uri_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        uri_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_client_body
+//-------------------------------------------------------------------------
+
+#undef IPS_OPT
+#define IPS_OPT "http_client_body"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the request body"
+
+static Module* client_body_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_CLIENT_BODY, CAT_SET_BODY,
+        PSI_CLIENT_BODY);
+}
+
+static const IpsApi client_body_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        client_body_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_method
+//-------------------------------------------------------------------------
+
+static const Parameter http_method_params[] =
+{
+    { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message headers" },
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_method"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the HTTP request method"
+
+static Module* method_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_METHOD, CAT_SET_OTHER, PSI_METHOD,
+        http_method_params);
+}
+
+static const IpsApi method_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        method_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_cookie
+//-------------------------------------------------------------------------
+
+static const Parameter http_cookie_params[] =
+{
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_cookie"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the HTTP cookie"
+
+static Module* cookie_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_COOKIE, CAT_SET_OTHER, PSI_COOKIE,
+        http_cookie_params);
+}
+
+static const IpsApi cookie_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        cookie_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_stat_code
+//-------------------------------------------------------------------------
+
+static const Parameter http_stat_code_params[] =
+{
+    { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message headers" },
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_stat_code"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the HTTP status code"
+
+static Module* stat_code_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_STAT_CODE, CAT_SET_OTHER,
+        PSI_STAT_CODE, http_stat_code_params);
+}
+
+static const IpsApi stat_code_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        stat_code_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_stat_msg
+//-------------------------------------------------------------------------
+
+static const Parameter http_stat_msg_params[] =
+{
+    { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message headers" },
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_stat_msg"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the HTTP status message"
+
+static Module* stat_msg_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_STAT_MSG, CAT_SET_OTHER,
+        PSI_STAT_MSG, http_stat_msg_params);
+}
+
+static const IpsApi stat_msg_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        stat_msg_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_uri
+//-------------------------------------------------------------------------
+
+static const Parameter http_raw_uri_params[] =
+{
+    { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message headers" },
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { "scheme", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against scheme section of URI only" },
+    { "host", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against host section of URI only" },
+    { "port", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against port section of URI only" },
+    { "path", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against path section of URI only" },
+    { "query", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against query section of URI only" },
+    { "fragment", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "match against fragment section of URI only" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_uri"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized URI"
+
+static Module* raw_uri_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_RAW_URI, CAT_SET_OTHER,
+        PSI_RAW_URI, http_raw_uri_params);
+}
+
+static const IpsApi raw_uri_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        raw_uri_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_header
+//-------------------------------------------------------------------------
+
+static const Parameter http_raw_header_params[] =
+{
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_header"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized headers"
+
+static Module* raw_header_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_RAW_HEADER, CAT_SET_OTHER,
+        PSI_RAW_HEADER, http_raw_header_params);
+}
+
+static const IpsApi raw_header_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        raw_header_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_cookie
+//-------------------------------------------------------------------------
+
+static const Parameter http_raw_cookie_params[] =
+{
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_cookie"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized cookie"
+
+static Module* raw_cookie_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_RAW_COOKIE, CAT_SET_OTHER,
+        PSI_RAW_COOKIE, http_raw_cookie_params);
+}
+
+static const IpsApi raw_cookie_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        raw_cookie_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_version
+//-------------------------------------------------------------------------
+
+static const Parameter http_version_params[] =
+{
+    { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message headers" },
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_version"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the version buffer"
+
+static Module* version_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_VERSION, CAT_SET_OTHER,
+        PSI_VERSION, http_version_params);
+}
+
+static const IpsApi version_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        version_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_header
+//-------------------------------------------------------------------------
+
+// FIXIT-M add match_unknown option to look at HEAD__UNKNOWN.
+// FIXIT-M if http_header is the fast pattern buffer and the content to be matched appears in the
+// normalized field but not in the raw field detection will fail.
+
+static const Parameter http_header_params[] =
+{
+    { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message body" },
+    { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
+        "Parts of this rule examine HTTP message trailers" },
+    { "field", Parameter::PT_STRING, nullptr, nullptr,
+        "Restrict to given header. Header name is case insensitive." },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_header"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the normalized headers"
+
+static Module* header_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_HEADER, CAT_SET_HEADER,
+        PSI_HEADER, http_header_params);
+}
+
+static const IpsApi header_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        header_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_trailer
+//-------------------------------------------------------------------------
+
+static const Parameter http_trailer_params[] =
+{
+    { "field", Parameter::PT_STRING, nullptr, nullptr, "restrict to given trailer" },
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+#undef IPS_OPT
+#define IPS_OPT "http_trailer"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the normalized trailers"
+
+static Module* trailer_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_TRAILER, CAT_SET_OTHER,
+        PSI_TRAILER, http_trailer_params);
+}
+
+static const IpsApi trailer_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        trailer_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// http_raw_trailer
+//-------------------------------------------------------------------------
+
+#undef IPS_OPT
+#define IPS_OPT "http_raw_trailer"
+#undef IPS_HELP
+#define IPS_HELP "rule option to set the detection cursor to the unnormalized trailers"
+
+static Module* raw_trailer_mod_ctor()
+{
+    return new NHttpCursorModule(IPS_OPT, IPS_HELP, NHTTP_BUFFER_RAW_TRAILER, CAT_SET_OTHER,
+        PSI_RAW_TRAILER);
+}
+
+static const IpsApi raw_trailer_api =
+{
+    {
+        PT_IPS_OPTION,
+        sizeof(IpsApi),
+        IPSAPI_VERSION,
+        1,
+        API_RESERVED,
+        API_OPTIONS,
+        IPS_OPT,
+        IPS_HELP,
+        raw_trailer_mod_ctor,
+        NHttpCursorModule::mod_dtor
+    },
+    OPT_TYPE_DETECTION,
+    0, PROTO_BIT__TCP,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    NHttpIpsOption::opt_ctor,
+    NHttpIpsOption::opt_dtor,
+    nullptr
+};
+
+//-------------------------------------------------------------------------
+// plugins
+//-------------------------------------------------------------------------
+
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+    &uri_api.base,
+    &client_body_api.base,
+    &method_api.base,
+    &cookie_api.base,
+    &stat_code_api.base,
+    &stat_msg_api.base,
+    &raw_uri_api.base,
+    &raw_header_api.base,
+    &raw_cookie_api.base,
+    &version_api.base,
+    &header_api.base,
+    &trailer_api.base,
+    &raw_trailer_api.base,
+    nullptr
+};
+
diff --git a/src/service_inspectors/nhttp_inspect/ips_nhttp.h b/src/service_inspectors/nhttp_inspect/ips_nhttp.h
new file mode 100644 (file)
index 0000000..564cad2
--- /dev/null
@@ -0,0 +1,108 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// ips_nhttp.h author Tom Peters <thopeter@cisco.com>
+
+#ifndef IPS_NHTTP_H
+#define IPS_NHTTP_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string>
+#include <array>
+
+#include "main/snort_types.h"
+#include "profiler/profiler.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+
+#include "nhttp_enum.h"
+
+enum PsIdx { PSI_URI, PSI_CLIENT_BODY, PSI_METHOD, PSI_COOKIE, PSI_STAT_CODE, PSI_STAT_MSG,
+    PSI_RAW_URI, PSI_RAW_HEADER, PSI_RAW_COOKIE, PSI_HEADER, PSI_VERSION, PSI_TRAILER,
+    PSI_RAW_TRAILER, PSI_MAX };
+
+class NHttpCursorModule : public Module
+{
+public:
+    NHttpCursorModule(const char* key_, const char* help, NHttpEnums::NHTTP_BUFFER buffer_index_,
+        CursorActionType cat_, PsIdx psi_) : Module(key_, help), key(key_),
+        buffer_index(buffer_index_), cat(cat_), psi(psi_) {}
+    NHttpCursorModule(const char* key_, const char* help, NHttpEnums::NHTTP_BUFFER buffer_index_,
+        CursorActionType cat_, PsIdx psi_, const Parameter params[]) : Module(key_, help, params),
+        key(key_), buffer_index(buffer_index_), cat(cat_), psi(psi_) {}
+    ProfileStats* get_profile() const override { return &http_ps[psi]; }
+    static void mod_dtor(Module* m) { delete m; }
+    bool begin(const char*, int, SnortConfig*) override;
+    bool set(const char*, Value&, SnortConfig*) override;
+    bool end(const char*, int, SnortConfig*) override;
+
+private:
+    friend class NHttpIpsOption;
+    static THREAD_LOCAL std::array<ProfileStats, PsIdx::PSI_MAX> http_ps;
+
+    struct NHttpRuleParaList
+    {
+    public:
+        std::string field;        // provide buffer containing specific header field
+        bool with_header;         // provide buffer with a later section than it appears in
+        bool with_body;
+        bool with_trailer;
+        bool scheme;              // provide buffer with one of the six URI subcomponents
+        bool host;
+        bool port;
+        bool path;
+        bool query;
+        bool fragment;
+
+        void reset();
+    };
+
+    const char* const key;
+    const NHttpEnums::NHTTP_BUFFER buffer_index;
+    const CursorActionType cat;
+    const PsIdx psi;
+
+    NHttpRuleParaList para_list;
+    NHttpEnums::InspectSection inspect_section;
+    unsigned sub_id;
+};
+
+class NHttpIpsOption : public IpsOption
+{
+public:
+    NHttpIpsOption(const NHttpCursorModule* cm) : IpsOption(cm->key), key(cm->key),
+        buffer_index(cm->buffer_index), cat(cm->cat), psi(cm->psi),
+        inspect_section(cm->inspect_section), sub_id(cm->sub_id) {}
+    CursorActionType get_cursor_type() const override { return cat; }
+    int eval(Cursor&, Packet*) override;
+    static IpsOption* opt_ctor(Module* m, OptTreeNode*)
+        { return new NHttpIpsOption((NHttpCursorModule*)m); }
+    static void opt_dtor(IpsOption* p) { delete p; }
+private:
+    const char* const key;
+    const NHttpEnums::NHTTP_BUFFER buffer_index;
+    const CursorActionType cat;
+    const PsIdx psi;
+    const NHttpEnums::InspectSection inspect_section;
+    const unsigned sub_id;
+};
+
+#endif
+
index cb10a5ee9bef3efdefea830018b6586414e8816b..d2b06830e7fd6b8762eb517e923f149359e75784 100644 (file)
@@ -45,6 +45,9 @@ const char* NHttpApi::legacy_buffers[] =
     "http_stat_code",
     "http_stat_msg",
     "http_uri",
+    "http_version",
+    "http_trailer",
+    "http_raw_trailer",
     nullptr
 };
 
@@ -72,8 +75,8 @@ const InspectApi NHttpApi::nhttp_api =
     NHttpApi::nhttp_tterm,
     NHttpApi::nhttp_ctor,
     NHttpApi::nhttp_dtor,
-    nullptr, // ssn
-    nullptr  // reset
+    nullptr,
+    nullptr
 };
 
 #ifdef BUILDING_SO
index e92c17a6d5c326babb23a85bca64325a6159089e..d1fc7f600a05e29adc2d5b2aebc5a8d9762bc9c6 100644 (file)
@@ -25,6 +25,7 @@
 #include "framework/inspector.h"
 
 #include "nhttp_module.h"
+#include "nhttp_flow_data.h"
 
 class NHttpApi
 {
index 23a7fcb31d1bb93f38dbe227b3db932df89b5f5e..8fec1726c156d674caacc8dfbc194f09192fcb38 100644 (file)
@@ -33,6 +33,7 @@ static const int FINAL_GZIP_BLOCK_SIZE = 2304; // compromise value, too big caus
 static const uint32_t NHTTP_GID = 219;
 static const int GZIP_WINDOWBITS = 31;
 static const int DEFLATE_WINDOWBITS = 15;
+static const int MAX_FIELD_NAME_LENGTH = 100;
 
 // Field status codes for when no valid value is present in length or integer value. Positive
 // values are actual length or field value.
@@ -49,9 +50,11 @@ enum SectionType { SEC_DISCARD = -19, SEC_ABORT = -18, SEC__NOTCOMPUTE=-14, SEC_
     SEC_BODY_OLD };
 
 // Message buffers available to clients
+// This enum must remain synchronized with legacy_buffers[]
 enum NHTTP_BUFFER { NHTTP_BUFFER_CLIENT_BODY = 1, NHTTP_BUFFER_COOKIE, NHTTP_BUFFER_HEADER,
     NHTTP_BUFFER_METHOD, NHTTP_BUFFER_RAW_COOKIE, NHTTP_BUFFER_RAW_HEADER, NHTTP_BUFFER_RAW_URI,
-    NHTTP_BUFFER_STAT_CODE, NHTTP_BUFFER_STAT_MSG, NHTTP_BUFFER_URI, NHTTP_BUFFER_MAX };
+    NHTTP_BUFFER_STAT_CODE, NHTTP_BUFFER_STAT_MSG, NHTTP_BUFFER_URI, NHTTP_BUFFER_VERSION,
+    NHTTP_BUFFER_TRAILER, NHTTP_BUFFER_RAW_TRAILER, NHTTP_BUFFER_MAX };
 
 // Result of scanning by splitter
 enum ScanResult { SCAN_NOTFOUND, SCAN_FOUND, SCAN_FOUND_PIECE, SCAN_DISCARD, SCAN_DISCARD_PIECE,
@@ -89,6 +92,12 @@ enum SchemeId { SCH__NOSOURCE=-16, SCH__NOTCOMPUTE=-14, SCH__INSUFMEMORY=-13, SC
 // Body compression tpyes
 enum CompressId { CMP_NONE=2, CMP_GZIP, CMP_DEFLATE };
 
+// Message section in which an IPS option provides the buffer
+enum InspectSection { IS_NONE, IS_START, IS_HEADER, IS_BODY, IS_TRAILER };
+
+// Part of the URI to be provided
+enum UriComponent { UC_SCHEME = 1, UC_HOST, UC_PORT, UC_PATH, UC_QUERY, UC_FRAGMENT };
+
 // Every header we have ever heard of
 enum HeaderId { HEAD__NOTCOMPUTE=-14, HEAD__INSUFMEMORY=-13, HEAD__PROBLEMATIC=-12,
     HEAD__NOTPRESENT=-11, HEAD__OTHER=1, HEAD_CACHE_CONTROL, HEAD_CONNECTION, HEAD_DATE,
index e6a4a25ea3198e1614525ce50029f0039ffadbd4..7bcbdd123ebbd388de83c094bde1838f3aa4ab4d 100644 (file)
@@ -22,6 +22,7 @@
 #include <assert.h>
 #include <stdio.h>
 
+#include "main/snort_types.h"
 #include "stream/stream_api.h"
 
 #include "nhttp_enum.h"
@@ -55,21 +56,18 @@ NHttpInspect::NHttpInspect(NHttpParaList params_) : params(params_)
 
 THREAD_LOCAL uint8_t NHttpInspect::body_buffer[MAX_OCTETS];
 
-THREAD_LOCAL NHttpMsgSection* NHttpInspect::latest_section = nullptr;
+SO_PUBLIC THREAD_LOCAL NHttpMsgSection* NHttpInspect::latest_section = nullptr;
 
 bool NHttpInspect::get_buf(InspectionBuffer::Type ibt, Packet*, InspectionBuffer& b)
 {
-    switch ( ibt )
+    switch (ibt)
     {
     case InspectionBuffer::IBT_KEY:
-        return get_buf(NHTTP_BUFFER_URI, nullptr, b);
-
+        return get_buf(NHTTP_BUFFER_URI, 0, nullptr, b);
     case InspectionBuffer::IBT_HEADER:
-        return get_buf(NHTTP_BUFFER_HEADER, nullptr, b);
-
+        return get_buf(NHTTP_BUFFER_HEADER, 0, nullptr, b);
     case InspectionBuffer::IBT_BODY:
-        return get_buf(NHTTP_BUFFER_CLIENT_BODY, nullptr, b);
-
+        return get_buf(NHTTP_BUFFER_CLIENT_BODY, 0, nullptr, b);
     default:
         return false;
     }
@@ -77,16 +75,23 @@ bool NHttpInspect::get_buf(InspectionBuffer::Type ibt, Packet*, InspectionBuffer
 
 bool NHttpInspect::get_buf(unsigned id, Packet*, InspectionBuffer& b)
 {
+    return get_buf(id, 0, nullptr, b);
+}
+
+SO_PUBLIC bool NHttpInspect::get_buf(unsigned id, unsigned sub_id, Packet*, InspectionBuffer& b)
+{
+    // FIXIT-L some day we should add support for accessing the request headers, trailers, and
+    // version from the response side of the transaction.
     if (latest_section == nullptr)
         return false;
 
-    const Field& legacy = latest_section->get_legacy(id);
+    const Field& buffer = latest_section->get_classic_buffer(id, sub_id);
 
-    if (legacy.length <= 0)
+    if (buffer.length <= 0)
         return false;
 
-    b.data = legacy.start;
-    b.len = legacy.length;
+    b.data = buffer.start;
+    b.len = buffer.length;
     return true;
 }
 
index 3d1bd8090516a7fe3766063d15708e7d6c14b964..93bd6a2ebc7cd7a87f768f2073514669dba949d2 100644 (file)
 #include "nhttp_enum.h"
 #include "nhttp_field.h"
 #include "nhttp_module.h"
+#include "nhttp_msg_section.h"
 #include "nhttp_stream_splitter.h"
 
 class NHttpApi;
-class NHttpMsgSection;
 
 class NHttpInspect : public Inspector
 {
@@ -41,8 +41,9 @@ public:
 
     NHttpInspect(NHttpParaList params_);
 
-    bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override;
-    bool get_buf(unsigned, Packet*, InspectionBuffer&) override;
+    bool get_buf(InspectionBuffer::Type ibt, Packet*, InspectionBuffer& b) override;
+    bool get_buf(unsigned id, Packet*, InspectionBuffer& b) override;
+    bool get_buf(unsigned id, unsigned sub_id, Packet*, InspectionBuffer& b);
     bool configure(SnortConfig*) override { return true; }
     void show(SnortConfig*) override { LogMessage("NHttpInspect\n"); }
     void eval(Packet*) override { }
@@ -54,6 +55,8 @@ public:
     {
         return new NHttpStreamSplitter(is_client_to_server, this);
     }
+    static NHttpEnums::InspectSection get_latest_is() { return (latest_section != nullptr) ?
+        latest_section->get_inspection_section() : NHttpEnums::IS_NONE; }
 private:
     friend NHttpApi;
     friend NHttpStreamSplitter;
index d5a99fb51000c6eaae9debcd334310cc3a7ec819..e9dc3fbba5475b77ec88243c6c255e3c8fb7f5f5 100644 (file)
@@ -27,6 +27,7 @@
 #include "mime/file_mime_process.h"
 
 #include "nhttp_enum.h"
+#include "nhttp_api.h"
 #include "nhttp_msg_request.h"
 #include "nhttp_msg_body.h"
 
@@ -127,3 +128,18 @@ void NHttpMsgBody::do_file_processing()
     }
 }
 
+#ifdef REG_TEST
+// Common elements of print_section() for body sections
+void NHttpMsgBody::print_body_section(FILE* output)
+{
+    detect_data.print(output, "Detect data");
+    get_classic_buffer(NHTTP_BUFFER_CLIENT_BODY, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_CLIENT_BODY-1]);
+    if (g_file_data.len > 0)
+    {
+        Field(g_file_data.len, g_file_data.data).print(output, "file_data");
+    }
+    NHttpMsgSection::print_message_wrapup(output);
+}
+#endif
+
index 978adb41785d3d3014815db43f7cc599e1ca18d9..1b23c5f1500099e1f547513ce43ff21a1d7bd889 100644 (file)
@@ -32,6 +32,8 @@ class NHttpMsgBody : public NHttpMsgSection
 public:
     void analyze() override;
     const Field& get_detect_buf() const override { return detect_data; }
+    NHttpEnums::InspectSection get_inspection_section() const override
+        { return NHttpEnums::IS_BODY; }
 
 protected:
     NHttpMsgBody(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
@@ -42,6 +44,10 @@ protected:
     int64_t body_octets;
     Field detect_data;
     Field file_data;
+
+#ifdef REG_TEST
+    void print_body_section(FILE* output);
+#endif
 };
 
 #endif
index c3e5293f4b7a680556bfaf3014b24fde54faf885..cb636524f108ccf8f367d5e27adc8e0e69a87f0f 100644 (file)
@@ -56,8 +56,7 @@ void NHttpMsgBodyChunk::print_section(FILE* output)
 {
     NHttpMsgSection::print_message_title(output, "chunked body");
     fprintf(output, "Cumulative octets %" PRIi64 "\n", body_octets);
-    detect_data.print(output, "Detect data");
-    NHttpMsgSection::print_message_wrapup(output);
+    print_body_section(output);
 }
 #endif
 
index 434aaf1777dc27d4065deb330cf7bb138d7ba71a..63989a3485dfbadb68986ae4095d5144a134e0d9 100644 (file)
@@ -58,8 +58,7 @@ void NHttpMsgBodyCl::print_section(FILE* output)
     NHttpMsgSection::print_message_title(output, "Content-Length body");
     fprintf(output, "Content-Length %" PRIi64 ", octets seen %" PRIi64 "\n", data_length,
         body_octets);
-    detect_data.print(output, "Detect data");
-    NHttpMsgSection::print_message_wrapup(output);
+    print_body_section(output);
 }
 #endif
 
index 8d78173d908d0c80aefcc12b253c2e4b5125e750..4e989572b23558ea2dbcc51e06bc9683ef2a2130 100644 (file)
@@ -45,10 +45,9 @@ void NHttpMsgBodyOld::update_flow()
 #ifdef REG_TEST
 void NHttpMsgBodyOld::print_section(FILE* output)
 {
-    NHttpMsgSection::print_message_title(output, "Old-style body");
+    NHttpMsgSection::print_message_title(output, "old-style body");
     fprintf(output, "octets seen %" PRIi64 "\n", body_octets);
-    detect_data.print(output, "Detect data");
-    NHttpMsgSection::print_message_wrapup(output);
+    print_body_section(output);
 }
 #endif
 
index 5a74afaf5c695f0bda09c46bbcc7244581ada312..cb4b363ebe3d8e1d21520ad1aaf4eb730c1e1b01 100644 (file)
@@ -45,6 +45,11 @@ public:
     const Field& get_header_value_norm(NHttpEnums::HeaderId header_id);
     int get_header_count(NHttpEnums::HeaderId header_id) const;
 
+    // Tables of header field names and header value names
+    static const StrCode header_list[];
+    static const StrCode trans_code_list[];
+    static const StrCode content_code_list[];
+
 protected:
     NHttpMsgHeadShared(const uint8_t* buffer, const uint16_t buf_size,
         NHttpFlowData* session_data_, NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
@@ -64,11 +69,6 @@ protected:
     // Master table of known header fields and their normalization strategies.
     static const HeaderNormalizer* const header_norms[];
 
-    // Tables of header field names and header value names
-    static const StrCode header_list[];
-    static const StrCode trans_code_list[];
-    static const StrCode content_code_list[];
-
     void parse_header_block();
     uint32_t find_header_end(const uint8_t* buffer, int32_t length, int& num_seps);
     void parse_header_lines();
index 60ba63147d1bda75f929ac17aa1c44b7feac5642..5b87294a7cbc8ce7184a8b4536f4b5bb67341b64 100644 (file)
@@ -26,6 +26,7 @@
 #include "file_api/file_service.h"
 #include "file_api/file_flows.h"
 
+#include "nhttp_api.h"
 #include "nhttp_msg_request.h"
 #include "nhttp_msg_header.h"
 
@@ -215,6 +216,14 @@ void NHttpMsgHeader::print_section(FILE* output)
 {
     NHttpMsgSection::print_message_title(output, "header");
     NHttpMsgHeadShared::print_headers(output);
+    get_classic_buffer(NHTTP_BUFFER_COOKIE, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_COOKIE-1]);
+    get_classic_buffer(NHTTP_BUFFER_HEADER, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_HEADER-1]);
+    get_classic_buffer(NHTTP_BUFFER_RAW_COOKIE, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_RAW_COOKIE-1]);
+    get_classic_buffer(NHTTP_BUFFER_RAW_HEADER, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_RAW_HEADER-1]);
     NHttpMsgSection::print_message_wrapup(output);
 }
 #endif
index c559d044673426eb4b9af6ceeec92eefcb531c03..42741d911ce5a7168cb2599189cd38ffd472353a 100644 (file)
@@ -35,6 +35,8 @@ public:
     NHttpMsgHeader(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
         NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
         const NHttpParaList* params_);
+    NHttpEnums::InspectSection get_inspection_section() const override
+        { return NHttpEnums::IS_HEADER; }
     void update_flow() override;
 private:
     // Dummy configurations to support MIME processing
index 769939ed2512eef564f9925bc44da065d5554e45..52f7669b06414dede9696a772338153ef667b7fc 100644 (file)
@@ -25,6 +25,7 @@
 #include "detection/detection_util.h"
 
 #include "nhttp_enum.h"
+#include "nhttp_api.h"
 #include "nhttp_msg_request.h"
 #include "nhttp_msg_header.h"
 
@@ -192,6 +193,14 @@ void NHttpMsgRequest::print_section(FILE* output)
         uri->get_fragment().print(output, "Fragment");
         uri->get_norm_fragment().print(output, "Normalized Fragment");
     }
+    get_classic_buffer(NHTTP_BUFFER_METHOD, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_METHOD-1]);
+    get_classic_buffer(NHTTP_BUFFER_RAW_URI, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_RAW_URI-1]);
+    get_classic_buffer(NHTTP_BUFFER_URI, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_URI-1]);
+    get_classic_buffer(NHTTP_BUFFER_VERSION, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_VERSION-1]);
     NHttpMsgSection::print_message_wrapup(output);
 }
 
index ccc310285e43019f1961130b4b56bc825549b31d..d83c6831de1a0de9755d35c8694760e71f634cb6 100644 (file)
@@ -42,6 +42,7 @@ public:
     const Field& get_method() { return method; }
     const Field& get_uri();
     const Field& get_uri_norm_legacy();
+    NHttpUri* get_nhttp_uri() { return uri; }
 
 #ifdef REG_TEST
     void print_section(FILE* output) override;
index 896d8116a23c664a0fc6f3a9a16e6b8bfa1ff4c1..16332690c6fbb51b61986b83223488a3a69080c9 100644 (file)
 
 #include "nhttp_enum.h"
 #include "nhttp_transaction.h"
-#include "nhttp_api.h"
 #include "nhttp_msg_section.h"
 #include "nhttp_msg_request.h"
 #include "nhttp_msg_status.h"
 #include "nhttp_msg_head_shared.h"
+#include "nhttp_msg_header.h"
+#include "nhttp_msg_trailer.h"
 #include "nhttp_msg_body.h"
 
 using namespace NHttpEnums;
@@ -78,10 +79,9 @@ void NHttpMsgSection::update_depth() const
     }
 }
 
-const Field& NHttpMsgSection::get_legacy(unsigned buffer_id)
+const Field& NHttpMsgSection::get_classic_buffer(unsigned id, unsigned sub_id)
 {
-    // When current section is trailers, that is what will be used for header and cookie buffers.
-    switch (buffer_id)
+    switch (id)
     {
     case NHTTP_BUFFER_CLIENT_BODY:
       {
@@ -96,16 +96,24 @@ const Field& NHttpMsgSection::get_legacy(unsigned buffer_id)
     // Currently "normalization" is aggregation of multiple cookies. That is correct for raw
     // cookies and all there is for normalized cookies.
       {
-        NHttpMsgHeadShared* header = transaction->get_latest_header(source_id);
+        NHttpMsgHeader* header = transaction->get_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 NHTTP_BUFFER_HEADER:
+    case NHTTP_BUFFER_TRAILER:
       {
-        NHttpMsgHeadShared* header = transaction->get_latest_header(source_id);
-        return (header != nullptr) ? header->get_headers() : Field::FIELD_NULL;
+        // FIXIT-L Someday want to be able to return field name or raw field value
+        NHttpMsgHeadShared* const header = (id == NHTTP_BUFFER_HEADER) ?
+            (NHttpMsgHeadShared*)transaction->get_header(source_id) :
+            (NHttpMsgHeadShared*)transaction->get_trailer(source_id);
+        if (header == nullptr)
+            return Field::FIELD_NULL;
+        if (sub_id == 0)
+            return header->get_headers();
+        return header->get_header_value_norm((HeaderId)sub_id);
       }
     case NHTTP_BUFFER_METHOD:
       {
@@ -114,14 +122,9 @@ const Field& NHttpMsgSection::get_legacy(unsigned buffer_id)
       }
     case NHTTP_BUFFER_RAW_HEADER:
       {
-        NHttpMsgHeadShared* header = transaction->get_latest_header(source_id);
+        NHttpMsgHeader* header = transaction->get_header(source_id);
         return (header != nullptr) ? header->get_headers() : Field::FIELD_NULL;
       }
-    case NHTTP_BUFFER_RAW_URI:
-      {
-        NHttpMsgRequest* request = transaction->get_request();
-        return (request != nullptr) ? request->get_uri() : Field::FIELD_NULL;
-      }
     case NHTTP_BUFFER_STAT_CODE:
       {
         NHttpMsgStatus* status = transaction->get_status();
@@ -132,10 +135,46 @@ const Field& NHttpMsgSection::get_legacy(unsigned buffer_id)
         NHttpMsgStatus* status = transaction->get_status();
         return (status != nullptr) ? status->get_reason_phrase() : Field::FIELD_NULL;
       }
+    case NHTTP_BUFFER_RAW_URI:
     case NHTTP_BUFFER_URI:
       {
+        const bool raw = (id == NHTTP_BUFFER_RAW_URI);
         NHttpMsgRequest* request = transaction->get_request();
-        return (request != nullptr) ? request->get_uri_norm_legacy() : Field::FIELD_NULL;
+        if (request == nullptr)
+            return Field::FIELD_NULL;
+        if (sub_id == 0)
+            return raw ? request->get_uri() : request->get_uri_norm_legacy();
+        NHttpUri* const uri = request->get_nhttp_uri();
+        if (uri == nullptr)
+            return Field::FIELD_NULL;
+        switch ((UriComponent)sub_id)
+        {
+        case UC_SCHEME:
+            return uri->get_scheme();
+        case UC_HOST:
+            return raw ? uri->get_host() : uri->get_norm_host();
+        case UC_PORT:
+            return uri->get_port();
+        case UC_PATH:
+            return raw ? uri->get_path() : uri->get_norm_path();
+        case UC_QUERY:
+            return raw ? uri->get_query() : uri->get_norm_query();
+        case UC_FRAGMENT:
+            return raw ? uri->get_fragment() : uri->get_norm_fragment();
+        }
+        assert(false);
+        return Field::FIELD_NULL;
+      }
+    case NHTTP_BUFFER_VERSION:
+      {
+        NHttpMsgStart* start = (source_id == SRC_CLIENT) ?
+            (NHttpMsgStart*)transaction->get_request() : (NHttpMsgStart*)transaction->get_status();
+        return (start != nullptr) ? start->get_version() : Field::FIELD_NULL;
+      }
+    case NHTTP_BUFFER_RAW_TRAILER:
+      {
+        NHttpMsgTrailer* trailer = transaction->get_trailer(source_id);
+        return (trailer != nullptr) ? trailer->get_headers() : Field::FIELD_NULL;
       }
     default:
         assert(false);
@@ -153,17 +192,9 @@ void NHttpMsgSection::print_message_title(FILE* output, const char* title) const
 
 void NHttpMsgSection::print_message_wrapup(FILE* output)
 {
-    fprintf(output, "Infractions: %016" PRIx64 " %016" PRIx64 ", Events: %016" PRIx64 " %016" PRIx64 ", TCP Close: %s\n",
-        infractions.get_raw2(), infractions.get_raw(), events.get_raw2(), events.get_raw(), tcp_close ? "True" : "False");
-    for (unsigned k=1; k < NHTTP_BUFFER_MAX; k++)
-    {
-        get_legacy(k).print(output, NHttpApi::legacy_buffers[k-1]);
-    }
-    if (g_file_data.len > 0)
-    {
-        Field(g_file_data.len, g_file_data.data).print(output, "file_data");
-    }
-    fprintf(output, "\n");
+    fprintf(output, "Infractions: %016" PRIx64 " %016" PRIx64 ", Events: %016" PRIx64 " %016"
+        PRIx64 ", TCP Close: %s\n\n", infractions.get_raw2(), infractions.get_raw(),
+        events.get_raw2(), events.get_raw(), tcp_close ? "True" : "False");
     session_data->show(output);
     fprintf(output, "\n");
 }
index 61ee7928117201288d2d127528c479a663cc6167..4a8058dcc67bf8763ab1b49fc6551df1d91e2603 100644 (file)
@@ -38,6 +38,7 @@ class NHttpMsgSection
 {
 public:
     virtual ~NHttpMsgSection() { if (delete_msg_on_destruct) delete[] msg_text.start; }
+    virtual NHttpEnums::InspectSection get_inspection_section() const = 0;
 
     // Minimum necessary processing for every message
     virtual void analyze() = 0;
@@ -45,7 +46,7 @@ public:
     // Manages the splitter and communication between message sections
     virtual void update_flow() = 0;
 
-    const Field& get_legacy(unsigned buffer_id);
+    const Field& get_classic_buffer(unsigned id, unsigned sub_id);
 
     // Provide buffer to be sent to detection
     virtual const Field& get_detect_buf() const { return msg_text; }
index bc44952d6e62196e00a0c602329ad7fa030802fc..e36a9bdbee3c2a66a9d6d49562edf653468022d4 100644 (file)
@@ -31,6 +31,9 @@ class NHttpMsgStart : public NHttpMsgSection
 {
 public:
     void analyze() override;
+    const Field& get_version() const { return version; }
+    NHttpEnums::InspectSection get_inspection_section() const override
+        { return NHttpEnums::IS_START; }
 
 protected:
     NHttpMsgStart(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
index d147ec06f6f5f3067aeb9fef4f65db98bb8ed05b..357f72f540ad78c2679e9b29cf2337f6d5780487 100644 (file)
@@ -25,6 +25,7 @@
 #include "detection/detection_util.h"
 
 #include "nhttp_enum.h"
+#include "nhttp_api.h"
 #include "nhttp_msg_status.h"
 #include "nhttp_msg_header.h"
 
@@ -170,6 +171,12 @@ void NHttpMsgStatus::print_section(FILE* output)
     fprintf(output, "Version Id: %d\n", version_id);
     fprintf(output, "Status Code Num: %d\n", status_code_num);
     reason_phrase.print(output, "Reason Phrase");
+    get_classic_buffer(NHTTP_BUFFER_STAT_CODE, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_STAT_CODE-1]);
+    get_classic_buffer(NHTTP_BUFFER_STAT_MSG, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_STAT_MSG-1]);
+    get_classic_buffer(NHTTP_BUFFER_VERSION, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_VERSION-1]);
     NHttpMsgSection::print_message_wrapup(output);
 }
 #endif
index 9f8517970b91de9714588439097ee81e3b124e0b..7059ee247c2d70ab0a54dd8d375783fb7199f0c2 100644 (file)
@@ -24,6 +24,7 @@
 #include "detection/detection_util.h"
 
 #include "nhttp_enum.h"
+#include "nhttp_api.h"
 #include "nhttp_msg_trailer.h"
 
 using namespace NHttpEnums;
@@ -49,6 +50,10 @@ void NHttpMsgTrailer::print_section(FILE* output)
 {
     NHttpMsgSection::print_message_title(output, "trailer");
     NHttpMsgHeadShared::print_headers(output);
+    get_classic_buffer(NHTTP_BUFFER_TRAILER, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_TRAILER-1]);
+    get_classic_buffer(NHTTP_BUFFER_RAW_TRAILER, 0).print(output,
+        NHttpApi::legacy_buffers[NHTTP_BUFFER_RAW_TRAILER-1]);
     NHttpMsgSection::print_message_wrapup(output);
 }
 #endif
index 71d26f4e734fff4ce2dc7d57079892129e5a2415..8bc46a1c0093f530381f250347ec44dd3922b7b6 100644 (file)
@@ -32,6 +32,8 @@ public:
     NHttpMsgTrailer(const uint8_t* buffer, const uint16_t buf_size, NHttpFlowData* session_data_,
         NHttpEnums::SourceId source_id_, bool buf_owner, Flow* flow_,
         const NHttpParaList* params_);
+    NHttpEnums::InspectSection get_inspection_section() const override
+        { return NHttpEnums::IS_TRAILER; }
     void update_flow() override;
 
 #ifdef REG_TEST
index 7dc65db50e4f09e62793e1102646ca499fc21449..6b64704ad3b5a0b7c9f2e327e39e393dbf71a905 100644 (file)
 
 #include <string.h>
 
+#include "main/snort_types.h"
+
 #include "nhttp_enum.h"
 #include "nhttp_str_to_code.h"
 
 // Need to replace this simple algorithm for better performance FIXIT-P
-int32_t str_to_code(const uint8_t* text, const int32_t text_len, const StrCode table[])
+SO_PUBLIC int32_t str_to_code(const uint8_t* text, const int32_t text_len, const StrCode table[])
 {
     for (int32_t k=0; table[k].name != nullptr; k++)
     {
index 3cf403d3b02479070076c7121381003830cb598c..839a45a7b4565a1d746eb8be0b2466cda39cd200 100644 (file)
@@ -101,7 +101,7 @@ const StrCode NHttpUri::scheme_list[] =
     { 0,                       nullptr }
 };
 
-const StrCode NHttpMsgHeadShared::header_list[] =
+SO_PUBLIC const StrCode NHttpMsgHeadShared::header_list[] =
 {
     { HEAD_CACHE_CONTROL,        "cache-control" },
     { HEAD_CONNECTION,           "connection" },
index 00fb88ff5038bee83cf0133670f36ec4f14f8b17..64c1b8b552ce53cc19e8fcffbc02e0ad1f9fd05d 100644 (file)
@@ -56,13 +56,6 @@ public:
     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] != nullptr) ? (NHttpMsgHeadShared*)trailer[source_id] :
-            (NHttpMsgHeadShared*)header[source_id];
-    }
-
 private:
     NHttpTransaction() = default;