]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #684 in SNORT/snort3 from appid_port2x_deltas to master
authorHui Cao (huica) <huica@cisco.com>
Thu, 27 Oct 2016 16:27:53 +0000 (12:27 -0400)
committerHui Cao (huica) <huica@cisco.com>
Thu, 27 Oct 2016 16:27:53 +0000 (12:27 -0400)
Squashed commit of the following:

commit f0cfd6beb8a5fdc2a9f97e997eed31ee5eb8e08e
Author: davis mcpherson <davmcphe.cisco.com>
Date:   Wed Oct 26 16:26:38 2016 -0400

    use 'free' to free hsession ptrs

commit b7fa07525538c46fff16c2f3ba97bc9f6ffe8216
Author: davis mcpherson <davmcphe.cisco.com>
Date:   Wed Oct 26 14:29:28 2016 -0400

    patch to support initializing appid http header ptrs and lengths via pub/sub interface with nhttp inspector

commit a007538457b691e3644eecc389755b65a0d06de9
Author: davis mcpherson <davmcphe.cisco.com>
Date:   Mon Oct 24 08:15:04 2016 -0400

    move stmp detector tests for clients from client_plugins dir to detector_plugins dir

commit 1915d11be99da837f6703a7574d696f8753032d5
Author: davis mcpherson <davmcphe.cisco.com>
Date:   Fri Oct 21 17:09:49 2016 -0400

    port changes for lua detector chp http pattern management

commit aaaa8490e52a7c5537a5034dce9ac23f7206d6f5
Author: davis mcpherson <davmcphe.cisco.com>
Date:   Fri Oct 21 12:50:28 2016 -0400

    port appid 2.x changes that converted smtp to detector model from separate client/service plugins

    removed deprecated client/service source files for smtp detectors

commit c76a8ec0d2911841b3f00801e038486ce3d06319
Author: davis mcpherson <davmcphe.cisco.com>
Date:   Thu Oct 20 16:21:37 2016 -0400

    port of appid deltas from 2.x to the third party module support code

commit 34886ef8ed672dfc43f7c4d4a72a1f8af007185b
Author: davis mcpherson <davmcphe.cisco.com>
Date:   Thu Oct 20 12:06:42 2016 -0400

    port 2.x changes to logic that syncs ids used by appid and snort for various protocols

commit 444e20cd2414b27ea1d0dd5a4283cb750b88e3c5
Author: davis mcpherson <davmcphe.cisco.com>
Date:   Thu Oct 20 11:20:54 2016 -0400

    port of appid changes since initial snapshot that are related to adding regex matching for http fields, application id updates, and changes to appid api methods

77 files changed:
configure.ac
src/network_inspectors/appid/CMakeLists.txt
src/network_inspectors/appid/Makefile.am
src/network_inspectors/appid/appid_api.cc
src/network_inspectors/appid/appid_api.h
src/network_inspectors/appid/appid_http_event_handler.cc
src/network_inspectors/appid/appid_inspector.cc
src/network_inspectors/appid/appid_session.cc
src/network_inspectors/appid/appid_session.h
src/network_inspectors/appid/application_ids.h
src/network_inspectors/appid/client_plugins/client_app_aim.cc
src/network_inspectors/appid/client_plugins/client_app_api.h
src/network_inspectors/appid/client_plugins/client_app_base.cc
src/network_inspectors/appid/client_plugins/client_app_bit.cc
src/network_inspectors/appid/client_plugins/client_app_bit_tracker.cc
src/network_inspectors/appid/client_plugins/client_app_msn.cc
src/network_inspectors/appid/client_plugins/client_app_rtp.cc
src/network_inspectors/appid/client_plugins/client_app_smtp.cc [deleted file]
src/network_inspectors/appid/client_plugins/client_app_smtp.h [deleted file]
src/network_inspectors/appid/client_plugins/client_app_ssh.cc
src/network_inspectors/appid/client_plugins/client_app_timbuktu.cc
src/network_inspectors/appid/client_plugins/client_app_tns.cc
src/network_inspectors/appid/client_plugins/client_app_vnc.cc
src/network_inspectors/appid/client_plugins/client_app_ym.cc
src/network_inspectors/appid/client_plugins/test/Makefile.am [deleted file]
src/network_inspectors/appid/detector_plugins/detector_base.cc
src/network_inspectors/appid/detector_plugins/detector_dns.cc
src/network_inspectors/appid/detector_plugins/detector_http.cc
src/network_inspectors/appid/detector_plugins/detector_http.h
src/network_inspectors/appid/detector_plugins/detector_imap.cc
src/network_inspectors/appid/detector_plugins/detector_kerberos.cc
src/network_inspectors/appid/detector_plugins/detector_pattern.cc
src/network_inspectors/appid/detector_plugins/detector_pop3.cc
src/network_inspectors/appid/detector_plugins/detector_sip.cc
src/network_inspectors/appid/detector_plugins/detector_smtp.cc [new file with mode: 0644]
src/network_inspectors/appid/detector_plugins/detector_smtp.h [moved from src/network_inspectors/appid/service_plugins/service_smtp.h with 95% similarity]
src/network_inspectors/appid/detector_plugins/test/CMakeLists.txt [moved from src/network_inspectors/appid/client_plugins/test/CMakeLists.txt with 68% similarity]
src/network_inspectors/appid/detector_plugins/test/Makefile.am [new file with mode: 0644]
src/network_inspectors/appid/detector_plugins/test/detector_smtp_test.cc [moved from src/network_inspectors/appid/client_plugins/test/client_app_smtp_test.cc with 99% similarity]
src/network_inspectors/appid/lua_detector_api.cc
src/network_inspectors/appid/service_plugins/service_api.h
src/network_inspectors/appid/service_plugins/service_base.cc
src/network_inspectors/appid/service_plugins/service_battle_field.cc
src/network_inspectors/appid/service_plugins/service_bgp.cc
src/network_inspectors/appid/service_plugins/service_bit.cc
src/network_inspectors/appid/service_plugins/service_bootp.cc
src/network_inspectors/appid/service_plugins/service_dcerpc.cc
src/network_inspectors/appid/service_plugins/service_direct_connect.cc
src/network_inspectors/appid/service_plugins/service_flap.cc
src/network_inspectors/appid/service_plugins/service_ftp.cc
src/network_inspectors/appid/service_plugins/service_irc.cc
src/network_inspectors/appid/service_plugins/service_lpr.cc
src/network_inspectors/appid/service_plugins/service_mdns.cc
src/network_inspectors/appid/service_plugins/service_mysql.cc
src/network_inspectors/appid/service_plugins/service_netbios.cc
src/network_inspectors/appid/service_plugins/service_nntp.cc
src/network_inspectors/appid/service_plugins/service_ntp.cc
src/network_inspectors/appid/service_plugins/service_radius.cc
src/network_inspectors/appid/service_plugins/service_rexec.cc
src/network_inspectors/appid/service_plugins/service_rfb.cc
src/network_inspectors/appid/service_plugins/service_rlogin.cc
src/network_inspectors/appid/service_plugins/service_rpc.cc
src/network_inspectors/appid/service_plugins/service_rshell.cc
src/network_inspectors/appid/service_plugins/service_rsync.cc
src/network_inspectors/appid/service_plugins/service_rtmp.cc
src/network_inspectors/appid/service_plugins/service_smtp.cc [deleted file]
src/network_inspectors/appid/service_plugins/service_snmp.cc
src/network_inspectors/appid/service_plugins/service_ssh.cc
src/network_inspectors/appid/service_plugins/service_ssl.cc
src/network_inspectors/appid/service_plugins/service_telnet.cc
src/network_inspectors/appid/service_plugins/service_tftp.cc
src/network_inspectors/appid/service_plugins/service_timbuktu.cc
src/network_inspectors/appid/service_plugins/service_tns.cc
src/network_inspectors/appid/test/appid_http_event_test.cc
src/network_inspectors/appid/thirdparty_appid_types.h
src/pub_sub/http_events.cc
src/pub_sub/http_events.h

index 83defd843d499c41ce6c809ce8b2e5b44dc834bf..357c3882d8ad6bef9de9a8dab95c0e1531308f5e 100644 (file)
@@ -1147,7 +1147,7 @@ src/stream/file/Makefile \
 src/network_inspectors/Makefile \
 src/network_inspectors/appid/Makefile \
 src/network_inspectors/appid/test/Makefile \
-src/network_inspectors/appid/client_plugins/test/Makefile \
+src/network_inspectors/appid/detector_plugins/test/Makefile \
 src/network_inspectors/appid/service_plugins/test/Makefile \
 src/network_inspectors/arp_spoof/Makefile \
 src/network_inspectors/binder/Makefile \
index 41bc93c010673ddc0d59ac6de31fbfd300a6be7b..8cd0159f27ea7c2d41da013b4eaabe66c6065822 100644 (file)
@@ -14,8 +14,6 @@ set ( CP_APPID_SOURCES
        client_plugins/client_app_msn.cc
        client_plugins/client_app_msn.h
        client_plugins/client_app_rtp.cc
-       client_plugins/client_app_smtp.cc
-       client_plugins/client_app_smtp.h
        client_plugins/client_app_ssh.cc
        client_plugins/client_app_timbuktu.cc
        client_plugins/client_app_tns.cc
@@ -76,8 +74,6 @@ set ( SP_APPID_SOURCES
        service_plugins/service_rsync.h
        service_plugins/service_rtmp.cc
        service_plugins/service_rtmp.h
-       service_plugins/service_smtp.cc
-       service_plugins/service_smtp.h
        service_plugins/service_snmp.cc
        service_plugins/service_snmp.h
        service_plugins/service_ssh.cc
@@ -108,6 +104,8 @@ set ( DP_APPID_SOURCES
        detector_plugins/detector_pop3.cc
        detector_plugins/detector_sip.cc
        detector_plugins/detector_sip.h
+       detector_plugins/detector_smtp.cc
+       detector_plugins/detector_smtp.h
        detector_plugins/http_url_patterns.cc
        detector_plugins/http_url_patterns.h
 )
@@ -200,7 +198,7 @@ set ( APPID_SOURCES
 target_include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} )
 
 add_subdirectory(service_plugins/test)
-add_subdirectory(client_plugins/test)
+add_subdirectory(detector_plugins/test)
 add_subdirectory(test)
 
 #install (FILES ${APPID_INCLUDES}
index 44f94fc85b145ded29fef8a1e7963e5434b8da51..1329d91c4757e8f7f996f24a041460cbc9cf0d57 100644 (file)
@@ -14,8 +14,6 @@ client_plugins/client_app_config.h \
 client_plugins/client_app_msn.cc \
 client_plugins/client_app_msn.h \
 client_plugins/client_app_rtp.cc \
-client_plugins/client_app_smtp.cc \
-client_plugins/client_app_smtp.h \
 client_plugins/client_app_ssh.cc \
 client_plugins/client_app_timbuktu.cc \
 client_plugins/client_app_tns.cc \
@@ -38,6 +36,8 @@ detector_plugins/detector_pattern.h \
 detector_plugins/detector_pop3.cc \
 detector_plugins/detector_sip.cc \
 detector_plugins/detector_sip.h \
+detector_plugins/detector_smtp.cc \
+detector_plugins/detector_smtp.h \
 detector_plugins/http_url_patterns.cc \
 detector_plugins/http_url_patterns.h
 
@@ -93,8 +93,6 @@ service_plugins/service_rsync.cc \
 service_plugins/service_rsync.h \
 service_plugins/service_rtmp.cc \
 service_plugins/service_rtmp.h \
-service_plugins/service_smtp.cc \
-service_plugins/service_smtp.h \
 service_plugins/service_snmp.cc \
 service_plugins/service_snmp.h \
 service_plugins/service_ssh.cc \
@@ -195,6 +193,6 @@ $(util_file_list)
 if ENABLE_UNIT_TESTS
 SUBDIRS=test\
 service_plugins/test \
-client_plugins/test
+detector_plugins/test
 endif
 
index c7798a0b512aab4d9f36d1ebf54843fc0b4be492..b4e7aefdee474fb45ca4bdaf082ba32a69285313 100644 (file)
@@ -358,31 +358,45 @@ char* AppIdApi::get_http_request_body(AppIdSession* asd)
 uint16_t AppIdApi::get_http_uri_offset(AppIdSession* asd)
 {
     if (asd && asd->hsession)
-        return asd->hsession->uriOffset;
+        return asd->hsession->fieldOffset[REQ_URI_FID];
     return 0;
 }
 
 uint16_t AppIdApi::get_http_uri_end_offset(AppIdSession* asd)
 {
     if (asd && asd->hsession)
-        return asd->hsession->uriEndOffset;
+        return asd->hsession->fieldEndOffset[REQ_URI_FID];
     return 0;
 }
 
 uint16_t AppIdApi::get_http_cookie_offset(AppIdSession* asd)
 {
     if (asd && asd->hsession)
-        return asd->hsession->cookieOffset;
+        return asd->hsession->fieldOffset[REQ_COOKIE_FID];
     return 0;
 }
 
 uint16_t AppIdApi::get_http_cookie_end_offset(AppIdSession* asd)
 {
     if (asd && asd->hsession)
-        return asd->hsession->cookieEndOffset;
+        return asd->hsession->fieldEndOffset[REQ_COOKIE_FID];
     return 0;
 }
 
+uint16_t getHttpFieldOffset(AppIdSession* asd, HTTP_FIELD_ID fieldId)
+{
+    if (asd && asd->hsession && fieldId >= 0 && fieldId <= HTTP_FIELD_MAX)
+        return asd->hsession->fieldOffset[fieldId];
+    return 0;
+}
+
+uint16_t getHttpFieldEndOffset(AppIdSession* asd, HTTP_FIELD_ID fieldId)
+{
+    if (asd && asd->hsession && fieldId >= 0 && fieldId <= HTTP_FIELD_MAX)
+        return asd->hsession->fieldEndOffset[fieldId];
+     return 0;
+}
+
 SEARCH_SUPPORT_TYPE AppIdApi::get_http_search(AppIdSession* asd)
 {
     if (asd)
@@ -520,7 +534,7 @@ uint32_t AppIdApi::produce_ha_state(Flow* flow, uint8_t* buf)
 }
 
 uint32_t AppIdApi::consume_ha_state(Flow* flow, const uint8_t* buf, uint8_t, IpProtocol proto,
-    sfip_t* ip)
+    sfip_t* ip, uint16_t port)
 {
     AppIdSessionHA* appHA = (AppIdSessionHA*)buf;
     if (appHA->flags & APPID_HA_FLAGS_APP)
@@ -530,8 +544,9 @@ uint32_t AppIdApi::consume_ha_state(Flow* flow, const uint8_t* buf, uint8_t, IpP
 
         if (!asd)
         {
-            asd = new AppIdSession(proto, ip);
+            asd = new AppIdSession(proto, ip, port);
             flow->set_flow_data(asd);
+            asd->serviceAppId = appHA->appId[1];
             if (asd->serviceAppId == APP_ID_FTP_CONTROL)
             {
                 asd->set_session_flags(APPID_SESSION_CLIENT_DETECTED |
index ba2caa0e36a5b132a4d0b09a4a0e83ac03a80263..943b8612be0fff79abf34ab6697fe692ee32f981 100644 (file)
@@ -236,8 +236,8 @@ public:
     void free_smb_fp_data(AppIdSession*, FpSMBData*);
     char* get_netbios_name(AppIdSession*);
     uint32_t produce_ha_state(Flow* flow, uint8_t* buf);
-    uint32_t consume_ha_state(Flow* flow, const uint8_t* buf, uint8_t length,
-            IpProtocol proto, sfip_t* ip);
+    uint32_t consume_ha_state(Flow* flow, const uint8_t* buf, uint8_t length, IpProtocol proto,
+        sfip_t* ip, uint16_t initiatorPort);
     AppIdSession* get_appid_data(Flow* flow);
     char* get_dns_query(AppIdSession*, uint8_t* query_len);
     uint16_t get_dns_query_offset(AppIdSession*);
@@ -246,6 +246,8 @@ public:
     uint32_t get_dns_ttl(AppIdSession*);
     char* get_http_new_field(AppIdSession*, HTTP_FIELD_ID);
     void free_http_new_field(AppIdSession*, HTTP_FIELD_ID);
+    uint16_t get_http_field_offset(AppIdSession*, HTTP_FIELD_ID);
+    uint16_t get_http_field_end_offset(AppIdSession*, HTTP_FIELD_ID);
 };
 
 SO_PUBLIC extern AppIdApi appid_api;
index 0c6ef23138e5e91ba7b73ac3d09c49f1520fa865..bc14515c194e8b1a465170ce6df7bb9c9d7020c1 100644 (file)
@@ -28,8 +28,8 @@
 #include "thirdparty_appid_utils.h"
 #include "utils/util.h"
 
-static void replace_header_data(char **data, const uint8_t *header_start,
-    unsigned header_length)
+static void replace_header_data(char **data, uint16_t &datalen, const uint8_t *header_start,
+    int32_t header_length)
 {
     if(header_length <= 0)
         return;
@@ -39,14 +39,16 @@ static void replace_header_data(char **data, const uint8_t *header_start,
         snort_free(*data);
     
     *data = snort_strndup((char*)header_start, header_length);
+    datalen = header_length;
 }
 
 void HttpEventHandler::handle(DataEvent& event, Flow* flow)
 {
     AppIdSession* session;
     int direction;
+    uint16_t tmplen;
     const uint8_t* header_start;
-    unsigned header_length;
+    int32_t header_length;
     HttpEvent* http_event = (HttpEvent*)&event;
 
     assert(flow);
@@ -64,39 +66,68 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow)
         header_start = http_event->get_host(header_length);
         if(header_length > 0)
         {
-            replace_header_data(&session->hsession->host, header_start,
-                header_length);
+            replace_header_data(&session->hsession->host,
+                session->hsession->host_buflen, header_start, header_length);
             session->scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
 
             header_start = http_event->get_uri(header_length);
-            replace_header_data(&session->hsession->url, header_start,
-                header_length);
+            if(header_length > 0)
+            {
+                replace_header_data(&session->hsession->uri,
+                    session->hsession->uri_buflen, header_start,
+                    header_length);
+
+                if(session->hsession->url)
+                    snort_free(session->hsession->url);
+                tmplen = sizeof(HTTP_PREFIX) + session->hsession->host_buflen +
+                    session->hsession->uri_buflen + 1;
+                session->hsession->url = (char*)snort_calloc(tmplen);
+                strcpy(session->hsession->url, HTTP_PREFIX);
+                strncat(session->hsession->url, session->hsession->host,
+                    session->hsession->host_buflen);
+                strncat(session->hsession->url, session->hsession->uri,
+                    session->hsession->uri_buflen);
+            }
         }
 
         header_start = http_event->get_user_agent(header_length);
         if(header_length > 0)
         {
-            replace_header_data(&session->hsession->useragent, header_start,
+            replace_header_data(&session->hsession->useragent,
+                session->hsession->useragent_buflen, header_start,
                 header_length);
             session->scan_flags |= SCAN_HTTP_USER_AGENT_FLAG;
         }
 
+        header_start = http_event->get_cookie(header_length);
+        replace_header_data(&session->hsession->cookie,
+            session->hsession->cookie_buflen, header_start, header_length);
+
         header_start = http_event->get_referer(header_length);
-        replace_header_data(&session->hsession->referer, header_start,
-            header_length);
+        replace_header_data(&session->hsession->referer,
+            session->hsession->referer_buflen, header_start, header_length);
 
         header_start = http_event->get_x_working_with(header_length);
-        replace_header_data(&session->hsession->x_working_with, header_start,
-            header_length);
+        replace_header_data(&session->hsession->x_working_with, tmplen,
+            header_start, header_length);
+
+        // FIXIT-M: Should we get request body (may be expensive to copy)?
+        //      It is not currently set in callback in 2.9.x, only via 
+        //      third-party.
     }
     else    // Response headers.
     {
         header_start = http_event->get_content_type(header_length);
-        replace_header_data(&session->hsession->content_type, header_start,
+        replace_header_data(&session->hsession->content_type,
+            session->hsession->content_type_buflen, header_start,
             header_length);
 
+        header_start = http_event->get_location(header_length);
+        replace_header_data(&session->hsession->location,
+            session->hsession->location_buflen, header_start, header_length);
+
         header_start = http_event->get_server(header_length);
-        replace_header_data(&session->hsession->server, header_start,
+        replace_header_data(&session->hsession->server, tmplen, header_start,
             header_length);
 
         int32_t responseCodeNum = http_event->get_response_code();
@@ -109,15 +140,21 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow)
             {
                 snort_free(session->hsession->response_code);
                 session->hsession->response_code = snort_strdup(tmpstr);
+                session->hsession->response_code_buflen = strlen(tmpstr);
             }
         }
+
+        // FIXIT-M: Get Location header data.
+        // FIXIT-M: Should we get response body (may be expensive to copy)?
+        //      It is not currently set in callback in 2.9.x, only via 
+        //      third-party.
     }
 
     //  The Via header can be in both the request and response.
     header_start = http_event->get_via(header_length);
     if(header_length > 0)
     {
-        replace_header_data(&session->hsession->via, header_start,
+        replace_header_data(&session->hsession->via, tmplen, header_start,
             header_length);
         session->scan_flags |= SCAN_HTTP_VIA_FLAG;
     }
@@ -126,8 +163,8 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow)
     session->set_session_flags(APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_HTTP_SESSION);
     if (direction == APP_ID_FROM_INITIATOR)
         appid_stats.http_flows++;
-    flow->set_application_ids(session->pick_service_app_id(), 
-        session->pick_client_app_id(), session->pick_payload_app_id(), 
+    flow->set_application_ids(session->pick_service_app_id(),
+        session->pick_client_app_id(), session->pick_payload_app_id(),
         session->pick_misc_app_id());
 }
 
index 27b9143607e96759e712ed5af4751261915780ad..18ce2366c8c5085a77d12b2940ea3c5d9ca16721 100644 (file)
@@ -87,8 +87,6 @@ bool AppIdInspector::configure(SnortConfig*)
     // FIXIT-M some of this stuff may be needed in some fashion...
 #ifdef REMOVED_WHILE_NOT_IN_USE
     _dpd.registerGeAppId(getOpenAppId);
-    if (!thirdparty_appid_module)
-        _dpd.streamAPI->register_http_header_callback(httpHeaderCallback);
     _dpd.registerSslAppIdLookup(sslAppGroupIdLookup);
 
     // FIXIT-M AppID will need to register for SIP events for sip detection to work...
@@ -244,97 +242,6 @@ SO_PUBLIC const BaseApi* snort_plugins[] =
 const BaseApi* nin_appid = &appid_inspector_api.base;
 #endif
 
-#ifdef REMOVED_WHILE_NOT_IN_USE
-// FIXIT-M This is to be replace with snort3 inspection events
-void httpHeaderCallback(Packet* p, HttpParsedHeaders* const headers)
-{
-    AppIdSession* asd;
-    int direction;
-    AppIdConfig* pConfig = AppIdConfig::get_appid_config();
-
-    if (thirdparty_appid_module)
-        return;
-    if (!p || !(asd = appid_api.get_appid_data(p->flow)))
-        return;
-
-    direction = p->is_from_client() ? APP_ID_FROM_INITIATOR : APP_ID_FROM_RESPONDER;
-
-    if (!asd->hsession)
-        asd->hsession = (decltype(asd->hsession))snort_calloc(sizeof(httpSession));
-
-    if (direction == APP_ID_FROM_INITIATOR)
-    {
-        if (headers->host.start)
-        {
-            snort_free(asd->hsession->host);
-            asd->hsession->host = snort_strndup((char*)headers->host.start, headers->host.len);
-            asd->scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
-
-            if (headers->url.start)
-            {
-                snort_free(asd->hsession->url);
-                asd->hsession->url = (char*)snort_calloc(sizeof(HTTP_PREFIX) +
-                    headers->host.len + headers->url.len);
-                strcpy(asd->hsession->url, HTTP_PREFIX);
-                strncat(asd->hsession->url, (char*)headers->host.start, headers->host.len);
-                strncat(asd->hsession->url, (char*)headers->url.start, headers->url.len);
-                asd->scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
-            }
-        }
-        if (headers->userAgent.start)
-        {
-            snort_free(asd->hsession->useragent);
-            asd->hsession->useragent = snort_strndup((char*)headers->userAgent.start,
-                headers->userAgent.len);
-            asd->scan_flags |= SCAN_HTTP_USER_AGENT_FLAG;
-        }
-        if (headers->referer.start)
-        {
-            snort_free(asd->hsession->referer);
-            asd->hsession->referer = snort_strndup((char*)headers->referer.start,
-                headers->referer.len);
-        }
-        if (headers->via.start)
-        {
-            snort_free(asd->hsession->via);
-            asd->hsession->via = snort_strndup((char*)headers->via.start, headers->via.len);
-            asd->scan_flags |= SCAN_HTTP_VIA_FLAG;
-        }
-    }
-    else
-    {
-        if (headers->via.start)
-        {
-            snort_free(asd->hsession->via);
-            asd->hsession->via = snort_strndup((char*)headers->via.start, headers->via.len);
-            asd->scan_flags |= SCAN_HTTP_VIA_FLAG;
-        }
-        if (headers->contentType.start)
-        {
-            snort_free(asd->hsession->content_type);
-            asd->hsession->content_type = snort_strndup((char*)headers->contentType.start,
-                headers->contentType.len);
-        }
-        if (headers->responseCode.start)
-        {
-            long responseCodeNum;
-            responseCodeNum = strtoul((char*)headers->responseCode.start, nullptr, 10);
-            if (responseCodeNum > 0 && responseCodeNum < 700)
-            {
-                snort_free(asd->hsession->response_code);
-                asd->hsession->response_code = snort_strndup((char*)headers->responseCode.start,
-                    headers->responseCode.len);
-            }
-        }
-    }
-
-    asd->processHTTPPacket(p, direction, headers, pConfig);
-    asd->set_session_flags(APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_HTTP_SESSION);
-    p->flow->set_application_ids(asd->pick_service_app_id(), asd->pick_client_app_id(),
-            asd->pick_payload_app_id(), asd->pick_misc_app_id());
-}
-#endif
-
 /**
  * @returns 1 if some appid is found, 0 otherwise.
  */
index 3f1b46b10a1351c342b18ff38510c9cf48539dce..56a66c0ea1508ef88c49908c9392b83a9e628330 100644 (file)
@@ -55,22 +55,15 @@ unsigned AppIdSession::flow_id = 0;
 THREAD_LOCAL AppIdFlowData* AppIdSession::fd_free_list = nullptr;
 THREAD_LOCAL uint32_t AppIdSession::appid_flow_data_id = 0;
 
-// FIXIT-L - determine reason for this mapping and whether we still need it snort3 or can harmonize the IDs used
-static int16_t snortId_for_ftp;
+static int16_t snortId_for_unsynchronized;
 static int16_t snortId_for_ftp_data;
-static int16_t snortId_for_imap;
-static int16_t snortId_for_pop3;
-static int16_t snortId_for_smtp;
 static int16_t snortId_for_http2;
 
 void map_app_names_to_snort_ids()
 {
     /* init globals for snortId compares */
-    snortId_for_ftp      = FindProtocolReference("ftp");
+    snortId_for_unsynchronized = AddProtocolReference("unsynchronized");
     snortId_for_ftp_data = FindProtocolReference("ftp-data");
-    snortId_for_imap     = FindProtocolReference("imap");
-    snortId_for_pop3     = FindProtocolReference("pop3");
-    snortId_for_smtp     = FindProtocolReference("smtp");
     snortId_for_http2    = FindProtocolReference("http2");
 }
 
@@ -110,92 +103,34 @@ void AppIdSession::set_session_logging_state(const Packet* pkt, int direction)
     return;
 }
 
-// FIXIT-M this function does work that probably should be in http inspector, appid should leverage that if possible
-static inline void getOffsetsFromRebuilt(Packet* pkt, httpSession* hsession)
-{
-// size of "GET /\r\n\r\n"
-    constexpr auto MIN_HTTP_REQ_HEADER_SIZE = sizeof("GET /\r\n\r\n");
-    const uint8_t cookieStr[] = "Cookie: ";
-    unsigned cookieStrLen = sizeof(cookieStr)-1;
-    const uint8_t crlf[] = "\r\n";
-    unsigned crlfLen = sizeof(crlf)-1;
-    const uint8_t crlfcrlf[] = "\r\n\r\n";
-    unsigned crlfcrlfLen = sizeof(crlfcrlf)-1;
-    const uint8_t* p;
-    uint8_t* headerEnd;
-    uint16_t headerSize;
-
-    if (!pkt || !pkt->data || pkt->dsize < MIN_HTTP_REQ_HEADER_SIZE)
-        return;
-
-    p = pkt->data;
-
-    if (!(headerEnd = (uint8_t*)service_strstr(p, pkt->dsize, crlfcrlf, crlfcrlfLen)))
-        return;
-
-    headerEnd += crlfcrlfLen;
-
-    headerSize = headerEnd - p;
-
-    //uri offset is the index of the first char after the first space in the data
-    if (!(p = (uint8_t*)memchr(pkt->data, ' ', headerSize)))
-        return;
-    hsession->uriOffset = ++p - pkt->data;
-    headerSize = headerEnd - p;
-
-    //uri end offset is the index of the first CRLF sequence after uri offset
-    if (!(p = (uint8_t*)service_strstr(p, headerSize, crlf, crlfLen)))
-    {
-        // clear uri offset if we can't find an end offset
-        hsession->uriOffset = 0;
-        return;
-    }
-    hsession->uriEndOffset = p - pkt->data;
-    headerSize = headerEnd - p;
-
-    //cookie offset is the index of the first char after the cookie header, "Cookie: "
-    if (!(p = (uint8_t*)service_strstr(p, headerSize, cookieStr, cookieStrLen)))
-        return;
-    hsession->cookieOffset = p + cookieStrLen - pkt->data;
-    headerSize = headerEnd - p;
-
-    //cookie end offset is the index of the first CRLF sequence after cookie offset
-    if (!(p = (uint8_t*)service_strstr(p, headerSize, crlf, crlfLen)))
-    {
-        // clear cookie offset if we can't find a cookie end offset
-        hsession->cookieOffset = 0;
-        return;
-    }
-    hsession->cookieEndOffset = p - pkt->data;
-}
-
-
 AppIdSession* AppIdSession::allocate_session(const Packet* p, IpProtocol proto, int direction)
 {
     const sfip_t* ip;
+    uint16_t port = 0;
 
     ip = (direction == APP_ID_FROM_INITIATOR)
         ? p->ptrs.ip_api.get_src() : p->ptrs.ip_api.get_dst();
-    AppIdSession* data = new AppIdSession(proto, ip);
-
     if ( ( proto == IpProtocol::TCP || proto == IpProtocol::UDP ) && ( p->ptrs.sp != p->ptrs.dp ) )
-        data->common.initiator_port =
-            (direction == APP_ID_FROM_INITIATOR) ? p->ptrs.sp : p->ptrs.dp;
+        port = (direction == APP_ID_FROM_INITIATOR) ? p->ptrs.sp : p->ptrs.dp;
+
+    AppIdSession* data = new AppIdSession(proto, ip, port);
+
     data->flow = p->flow;
     data->stats.firstPktsecond = p->pkth->ts.tv_sec;
     data->set_session_logging_state(p, direction);
-
+    data->snort_id = snortId_for_unsynchronized;
     p->flow->set_flow_data(data);
     return data;
 }
 
-AppIdSession::AppIdSession(IpProtocol proto, const sfip_t* ip)
+AppIdSession::AppIdSession(IpProtocol proto, const sfip_t* ip, uint16_t port)
     : FlowData(flow_id), protocol(proto)
 {
     service_ip.clear();
     session_id = ++appid_flow_data_id;
     common.flow_type = APPID_FLOW_TYPE_NORMAL;
     common.initiator_ip = *ip;
+    common.initiator_port = port;
     config = AppIdConfig::get_appid_config();
     app_info_mgr = &AppInfoManager::get_instance();
     if (thirdparty_appid_module)
@@ -239,7 +174,8 @@ AppIdSession* AppIdSession::create_future_session(const Packet* ctrlPkt, const s
 
     assert(type != PktType::NONE);
 
-    AppIdSession* asd = new AppIdSession(proto, cliIp);
+    // FIXIT-M - port parameter passed in as 0 since we may not know client port, verify this is correct
+    AppIdSession* asd = new AppIdSession(proto, cliIp, 0);
     asd->common.policyId = appIdPolicyId;
 
     // FIXIT-M expect session control packet support not ported to snort3 yet
@@ -403,7 +339,7 @@ bool AppIdSession::is_packet_ignored(Packet* p)
 
 // FIXIT-M - Need to convert this _dpd stream api call to the correct snort++ method
 #ifdef REMOVED_WHILE_NOT_IN_USE
-    bool is_http2     = _dpd.streamAPI->is_session_http2(p->flow);
+    bool is_http2     = false; // _dpd.streamAPI->is_session_http2(p->flow);
 #else
     bool is_http2     = false;
 #endif
@@ -423,15 +359,17 @@ bool AppIdSession::is_packet_ignored(Packet* p)
     {
         if ( p->is_rebuilt() && !p->flow->is_proxied() )
         {
+            // FIXIT-M - latest 2.9 checks direction in this if statement below:
+            //             ( (direction == APP_ID_FROM_INITIATOR) &&... ) do we need to add this?
             if (asd && asd->hsession && asd->hsession->get_offsets_from_rebuilt)
             {
-                getOffsetsFromRebuilt(p, asd->hsession);
+                httpGetNewOffsetsFromPacket(p, asd->hsession);
                 if (asd->session_logging_enabled)
                     LogMessage(
                         "AppIdDbg %s offsets from rebuilt packet: uri: %u-%u cookie: %u-%u\n",
-                        asd->session_logging_id, asd->hsession->uriOffset,
-                        asd->hsession->uriEndOffset, asd->hsession->cookieOffset,
-                        asd->hsession->cookieEndOffset);
+                        asd->session_logging_id,
+                        asd->hsession->fieldOffset[REQ_URI_FID], asd->hsession->fieldEndOffset[REQ_URI_FID],
+                        asd->hsession->fieldOffset[REQ_COOKIE_FID], asd->hsession->fieldEndOffset[REQ_COOKIE_FID]);
             }
             appid_stats.ignored_packets++;
             return true;
@@ -443,6 +381,20 @@ bool AppIdSession::is_packet_ignored(Packet* p)
 
 static int ptype_scan_counts[NUMBER_OF_PTYPES];
 
+#ifdef REMOVED_WHILE_NOT_IN_USE
+static inline bool checkThirdPartyReinspect(const Packet* p, AppIdSession* asd)
+{
+    return p->dsize && !asd->get_session_flags(APPID_SESSION_NO_TPI) &&
+                    asd->get_session_flags(APPID_SESSION_HTTP_SESSION) && TPIsAppIdDone(asd->tpsession);
+}
+
+#else
+static inline bool checkThirdPartyReinspect(const Packet*, AppIdSession*)
+{
+    return false;
+}
+#endif
+
 #ifdef REMOVED_WHILE_NOT_IN_USE
 void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
         AppId* proto_list, ThirdPartyAppIDAttributeData* attribute_data)
@@ -483,33 +435,8 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
 
         if (get_session_flags(APPID_SESSION_SPDY_SESSION))
         {
-            if (attribute_data->spdyRequesHost)
-            {
-                if (session_logging_enabled)
-                    LogMessage("AppIdDbg %s SPDY host is %s\n", session_logging_id,
-                        attribute_data->spdyRequesHost);
-                if (hsession->host)
-                {
-                    snort_free(hsession->host);
-                    hsession->chp_finished = 0;
-                }
-                hsession->host = snort_strdup(attribute_data->spdyRequesHost);
-                scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
-            }
-            if (attribute_data->spdyRequestPath)
-            {
-                if (session_logging_enabled)
-                    LogMessage("AppIdDbg %s SPDY URI is %s\n", session_logging_id,
-                        attribute_data->spdyRequestPath);
-                if (hsession->uri)
-                {
-                    snort_free(hsession->uri);
-                    hsession->chp_finished = 0;
-                }
-                hsession->uri = snort_strdup(attribute_data->spdyRequestPath);
-            }
             if (attribute_data->spdyRequestScheme &&
-                attribute_data->spdyRequesHost &&
+                attribute_data->spdyRequestHost &&
                 attribute_data->spdyRequestPath)
             {
                 static const char httpsScheme[] = "https";
@@ -533,48 +460,77 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                 }
 
                 size = strlen(scheme) +
-                    strlen(attribute_data->spdyRequesHost) +
+                    strlen(attribute_data->spdyRequestHost) +
                     strlen(attribute_data->spdyRequestPath) +
                     sizeof("://");    // see sprintf() format
                 hsession->url = (char*)snort_calloc(size);
                 sprintf(hsession->url, "%s://%s%s",
-                    scheme, attribute_data->spdyRequesHost, attribute_data->spdyRequestPath);
+                    scheme, attribute_data->spdyRequestHost, attribute_data->spdyRequestPath);
                 scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
+
+                snort_free(attribute_data->spdyRequestScheme);
+                attribute_data->spdyRequestScheme = nullptr;
             }
-            if (attribute_data->spdyRequestScheme)
+            else if (attribute_data->spdyRequestScheme)
             {
                 snort_free(attribute_data->spdyRequestScheme);
                 attribute_data->spdyRequestScheme = nullptr;
             }
-            if (attribute_data->spdyRequesHost)
+
+            if (attribute_data->spdyRequestHost)
             {
-                snort_free(attribute_data->spdyRequesHost);
-                attribute_data->spdyRequesHost = nullptr;
+                if (hsession->host)
+                {
+                    snort_free(hsession->host);
+                    hsession->chp_finished = 0;
+                }
+                hsession->host = attribute_data->spdyRequestHost;
+                attribute_data->spdyRequestHost = nullptr;
+                hsession->fieldOffset[REQ_HOST_FID] = attribute_data->spdyRequestHostOffset;
+                hsession->fieldEndOffset[REQ_HOST_FID] = attribute_data->spdyRequestHostEndOffset;
+                if(session_logging_enabled)
+                    LogMessage("AppIdDbg %s SPDY Host (%u-%u) is %s\n", session_logging_id,
+                                hsession->fieldOffset[REQ_HOST_FID], hsession->fieldEndOffset[REQ_HOST_FID], hsession->host);
+                scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
             }
+
             if (attribute_data->spdyRequestPath)
             {
-                snort_free(attribute_data->spdyRequestPath);
+                if (hsession->uri)
+                {
+                    free(hsession->uri);
+                    hsession->chp_finished = 0;
+                }
+                hsession->uri = attribute_data->spdyRequestPath;
                 attribute_data->spdyRequestPath = nullptr;
+                hsession->fieldOffset[REQ_URI_FID] = attribute_data->spdyRequestPathOffset;
+                hsession->fieldEndOffset[REQ_URI_FID] = attribute_data->spdyRequestPathEndOffset;
+                if(session_logging_enabled)
+                    LogMessage("AppIdDbg %s SPDY URI (%u-%u) is %s\n", session_logging_id,
+                                hsession->fieldOffset[REQ_URI_FID], hsession->fieldEndOffset[REQ_URI_FID], hsession->uri);
             }
         }
         else
         {
-            if (attribute_data->httpRequesHost)
+            if (attribute_data->httpRequestHost)
             {
-                if (session_logging_enabled)
-                    LogMessage("AppIdDbg %s HTTP host is %s\n", session_logging_id,
-                        attribute_data->httpRequesHost);
                 if (hsession->host)
                 {
                     snort_free(hsession->host);
                     if (!get_session_flags(APPID_SESSION_APP_REINSPECT))
                         hsession->chp_finished = 0;
                 }
-                hsession->host = attribute_data->httpRequesHost;
-                attribute_data->httpRequesHost = nullptr;
+                hsession->host = attribute_data->httpRequestHost;
+                hsession->host_buflen = attribute_data->httpRequestHostLen;
+                hsession->fieldOffset[REQ_HOST_FID] = attribute_data->httpRequestHostOffset;
+                hsession->fieldEndOffset[REQ_HOST_FID] = attribute_data->httpRequestHostEndOffset;
+                attribute_data->httpRequestHost = nullptr;
+                if (session_logging_enabled)
+                    LogMessage("AppIdDbg %s HTTP host is %s\n",
+                               session_logging_id, attribute_data->httpRequestHost);
                 scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
             }
-            if (attribute_data->httpRequesUrl)
+            if (attribute_data->httpRequestUrl)
             {
                 static const char httpScheme[] = "http://";
 
@@ -588,21 +544,21 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                 //change http to https if session was decrypted.
                 if (get_session_flags(APPID_SESSION_DECRYPTED)
                     &&
-                    memcmp(attribute_data->httpRequesUrl, httpScheme, sizeof(httpScheme)-1) == 0)
+                    memcmp(attribute_data->httpRequestUrl, httpScheme, sizeof(httpScheme)-1) == 0)
                 {
-                    hsession->url = (char*)snort_calloc(strlen(attribute_data->httpRequesUrl) + 2);
+                    hsession->url = (char*)snort_calloc(strlen(attribute_data->httpRequestUrl) + 2);
 
                     if (hsession->url)
                         sprintf(hsession->url, "https://%s",
-                            attribute_data->httpRequesUrl + sizeof(httpScheme)-1);
+                            attribute_data->httpRequestUrl + sizeof(httpScheme)-1);
 
-                    snort_free(attribute_data->httpRequesUrl);
-                    attribute_data->httpRequesUrl = nullptr;
+                    snort_free(attribute_data->httpRequestUrl);
+                    attribute_data->httpRequestUrl = nullptr;
                 }
                 else
                 {
-                    hsession->url = attribute_data->httpRequesUrl;
-                    attribute_data->httpRequesUrl = nullptr;
+                    hsession->url = attribute_data->httpRequestUrl;
+                    attribute_data->httpRequestUrl = nullptr;
                 }
 
                 scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
@@ -616,15 +572,14 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                         hsession->chp_finished = 0;
                 }
                 hsession->uri = attribute_data->httpRequestUri;
-                hsession->uriOffset = attribute_data->httpRequestUriOffset;
-                hsession->uriEndOffset = attribute_data->httpRequestUriEndOffset;
+                hsession->uri_buflen = attribute_data->httpRequestUriLen;
+                hsession->fieldOffset[REQ_URI_FID] = attribute_data->httpRequestUriOffset;
+                hsession->fieldEndOffset[REQ_URI_FID] = attribute_data->httpRequestUriEndOffset;
                 attribute_data->httpRequestUri = nullptr;
-                attribute_data->httpRequestUriOffset = 0;
-                attribute_data->httpRequestUriEndOffset = 0;
                 if (session_logging_enabled)
                     LogMessage("AppIdDbg %s uri (%u-%u) is %s\n", session_logging_id,
-                        hsession->uriOffset, hsession->uriEndOffset,
-                        hsession->uri);
+                               hsession->fieldOffset[REQ_URI_FID], hsession->fieldEndOffset[REQ_URI_FID],
+                               hsession->uri);
             }
         }
         if (attribute_data->httpRequestVia)
@@ -692,6 +647,7 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                     hsession->chp_finished = 0;
             }
             hsession->response_code = attribute_data->httpResponseCode;
+            hsession->response_code_buflen = attribute_data->httpResponseCodeLen;
             attribute_data->httpResponseCode = nullptr;
         }
         // Check to see if we've got an upgrade to HTTP/2 (if enabled).
@@ -715,8 +671,7 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
             snort_free(attribute_data->httpResponseUpgrade);
             attribute_data->httpResponseUpgrade = nullptr;
         }
-        if (!config->mod_config->referred_appId_disabled &&
-            attribute_data->httpRequestReferer)
+        if (attribute_data->httpRequestReferer)
         {
             if (session_logging_enabled)
                 LogMessage("AppIdDbg %s referrer is %s\n", session_logging_id,
@@ -728,8 +683,16 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                     hsession->chp_finished = 0;
             }
             hsession->referer = attribute_data->httpRequestReferer;
+            hsession->referer_buflen = attribute_data->httpRequestRefererLen;
             attribute_data->httpRequestReferer = nullptr;
+            hsession->fieldOffset[REQ_REFERER_FID] = attribute_data->httpRequestRefererOffset;
+            hsession->fieldEndOffset[REQ_REFERER_FID] = attribute_data->httpRequestRefererEndOffset;
+            if (session_logging_enabled)
+                LogMessage("AppIdDbg %s Referer (%u-%u) is %s\n", session_logging_id,
+                             hsession->fieldOffset[REQ_REFERER_FID], hsession->fieldEndOffset[REQ_REFERER_FID],
+                             hsession->referer);
         }
+
         if (attribute_data->httpRequestCookie)
         {
             if (hsession->cookie)
@@ -739,15 +702,16 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                     hsession->chp_finished = 0;
             }
             hsession->cookie = attribute_data->httpRequestCookie;
-            hsession->cookieOffset = attribute_data->httpRequestCookieOffset;
-            hsession->cookieEndOffset = attribute_data->httpRequestCookieEndOffset;
+            hsession->cookie_buflen = attribute_data->httpRequestCookieLen;
+            hsession->fieldOffset[REQ_COOKIE_FID] = attribute_data->httpRequestCookieOffset;
+            hsession->fieldEndOffset[REQ_COOKIE_FID] = attribute_data->httpRequestCookieEndOffset;
             attribute_data->httpRequestCookie = nullptr;
             attribute_data->httpRequestCookieOffset = 0;
             attribute_data->httpRequestCookieEndOffset = 0;
             if (session_logging_enabled)
                 LogMessage("AppIdDbg %s cookie (%u-%u) is %s\n", session_logging_id,
-                    hsession->cookieOffset, hsession->cookieEndOffset,
-                    hsession->cookie);
+                           hsession->fieldOffset[REQ_COOKIE_FID], hsession->fieldEndOffset[REQ_COOKIE_FID],
+                           hsession->cookie);
         }
         if (attribute_data->httpResponseContent)
         {
@@ -758,6 +722,7 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                     hsession->chp_finished = 0;
             }
             hsession->content_type = attribute_data->httpResponseContent;
+            hsession->content_type_buflen = attribute_data->httpResponseContentLen;
             attribute_data->httpResponseContent = nullptr;
             scan_flags |= SCAN_HTTP_CONTENT_TYPE_FLAG;
         }
@@ -770,6 +735,7 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                     hsession->chp_finished = 0;
             }
             hsession->location = attribute_data->httpResponseLocation;
+            hsession->location_buflen = attribute_data->httpResponseLocationLen;
             attribute_data->httpResponseLocation = nullptr;
         }
         if (attribute_data->httpRequestBody)
@@ -784,6 +750,7 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                     hsession->chp_finished = 0;
             }
             hsession->req_body = attribute_data->httpRequestBody;
+            hsession->req_body_buflen = attribute_data->httpRequestBodyLen;
             attribute_data->httpRequestBody = nullptr;
         }
         if (ptype_scan_counts[BODY_PT] && attribute_data->httpResponseBody)
@@ -795,6 +762,7 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
                     hsession->chp_finished = 0;
             }
             hsession->body = attribute_data->httpResponseBody;
+            hsession->body_buflen = attribute_data->httpResponseBodyLen;
             attribute_data->httpResponseBody = nullptr;
         }
         if (attribute_data->numXffFields)
@@ -833,10 +801,10 @@ void AppIdSession::ProcessThirdPartyResults(Packet* p, int confidence,
 
         if (!hsession->url)
         {
-            if (attribute_data->httpRequesUrl)
+            if (attribute_data->httpRequestUrl)
             {
-                hsession->url = attribute_data->httpRequesUrl;
-                attribute_data->httpRequesUrl = nullptr;
+                hsession->url = attribute_data->httpRequestUrl;
+                attribute_data->httpRequestUrl = nullptr;
                 scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
             }
         }
@@ -979,19 +947,19 @@ bool AppIdSession::do_third_party_discovery(IpProtocol protocol, const sfip_t* i
 
         if (p->dsize || config->mod_config->tp_allow_probes)
         {
-            if (protocol != IpProtocol::TCP || !p->dsize || (p->packet_flags & PKT_STREAM_ORDER_OK)
-                    || config->mod_config->tp_allow_probes)
+            if (protocol != IpProtocol::TCP || (p->packet_flags & PKT_STREAM_ORDER_OK)
+                            || config->mod_config->tp_allow_probes)
             {
+
+                Profile tpLibPerfStats_profile_context(tpLibPerfStats);
+                if (!tpsession)
                 {
-                    Profile tpLibPerfStats_profile_context(tpLibPerfStats);
-                    if (!tpsession)
-                    {
-                        if (!(tpsession = thirdparty_appid_module->session_create()))
-                            FatalError("Could not allocate tpsession data");
-                    }; // debug output of packet content
-                    thirdparty_appid_module->session_process(tpsession, p, direction, &tp_app_id, &tp_confidence,
-                            &tp_proto_list, &tp_attribute_data);
-                }
+                    if (!(tpsession = thirdparty_appid_module->session_create()))
+                        FatalError("Could not allocate tpsession data");
+                }; // debug output of packet content
+                thirdparty_appid_module->session_process(tpsession, p, direction, &tp_app_id, &tp_confidence,
+                                                         &tp_proto_list, &tp_attribute_data);
+
                 isTpAppidDiscoveryDone = true;
                 if (thirdparty_appid_module->session_state_get(tpsession) == TP_STATE_CLASSIFIED)
                     clear_session_flags(APPID_SESSION_APP_REINSPECT);
@@ -999,16 +967,6 @@ bool AppIdSession::do_third_party_discovery(IpProtocol protocol, const sfip_t* i
                 if (session_logging_enabled)
                     LogMessage("AppIdDbg %s 3rd party returned %d\n", session_logging_id, tp_app_id);
 
-                if (app_info_mgr->get_app_info_flags(tp_app_id, APPINFO_FLAG_IGNORE))
-                {
-                    if (session_logging_enabled)
-                        LogMessage("AppIdDbg %s 3rd party ignored\n", session_logging_id);
-
-                    if (get_session_flags(APPID_SESSION_HTTP_SESSION))
-                        tp_app_id = APP_ID_HTTP;
-                    else
-                        tp_app_id = APP_ID_NONE;
-                }
                 // For now, third party can detect HTTP/2 (w/o metadata) for
                 // some cases.  Treat it like HTTP w/ is_http2 flag set.
                 if ((tp_app_id == APP_ID_HTTP2) && (tp_confidence == 100))
@@ -1024,6 +982,23 @@ bool AppIdSession::do_third_party_discovery(IpProtocol protocol, const sfip_t* i
                     client_app_id = tp_app_id;
 
                 ProcessThirdPartyResults(p, tp_confidence, tp_proto_list, tp_attribute_data);
+
+                if (get_session_flags(APPID_SESSION_SSL_SESSION) &&
+                                !(scan_flags & SCAN_SSL_HOST_FLAG))
+                {
+                    setSSLSquelch(p, 1, tp_app_id);
+                }
+
+                if (app_info_mgr->get_app_info_flags(tp_app_id, APPINFO_FLAG_IGNORE))
+                {
+                    if (session_logging_enabled)
+                        LogMessage("AppIdDbg %s 3rd party ignored\n", session_logging_id);
+
+                    if (get_session_flags(APPID_SESSION_HTTP_SESSION))
+                        tp_app_id = APP_ID_HTTP;
+                    else
+                        tp_app_id = APP_ID_NONE;
+                }
             }
             else
             {
@@ -1034,11 +1009,13 @@ bool AppIdSession::do_third_party_discovery(IpProtocol protocol, const sfip_t* i
                     LogMessage("AppIdDbg %s 3rd party packet out-of-order\n", session_logging_id);
                 }
             }
+
             if (thirdparty_appid_module->session_state_get(tpsession) == TP_STATE_MONITORING)
             {
                 thirdparty_appid_module->disable_flags(tpsession,
                         TP_SESSION_FLAG_ATTRIBUTE | TP_SESSION_FLAG_TUNNELING | TP_SESSION_FLAG_FUTUREFLOW);
             }
+
             if (tp_app_id == APP_ID_SSL &&
                 (Stream::get_application_protocol_id(p->flow) == snortId_for_ftp_data))
             {
@@ -1046,6 +1023,7 @@ bool AppIdSession::do_third_party_discovery(IpProtocol protocol, const sfip_t* i
                 //  to APP_ID_NONE so the FTP preprocessor picks up the flow.
                 tp_app_id = APP_ID_NONE;
             }
+
             if (tp_app_id > APP_ID_NONE
                     && (!get_session_flags(APPID_SESSION_APP_REINSPECT) || payload_app_id > APP_ID_NONE))
             {
@@ -1059,7 +1037,18 @@ bool AppIdSession::do_third_party_discovery(IpProtocol protocol, const sfip_t* i
                         tp_payload_app_id = tp_app_id;
 
                     tp_app_id = APP_ID_HTTP;
+                    // Handle HTTP tunneling and SSL possibly then being used in that tunnel
+                    if (tp_app_id == APP_ID_HTTP_TUNNEL)
+                        set_payload_app_id_data(APP_ID_HTTP_TUNNEL, NULL);
+                    if ((payload_app_id == APP_ID_HTTP_TUNNEL) && (tp_app_id == APP_ID_SSL))
+                        set_payload_app_id_data(APP_ID_HTTP_SSL_TUNNEL, NULL);
+
                     processHTTPPacket(p, direction, nullptr);
+
+                    // If SSL over HTTP tunnel, make sure Snort knows that it's encrypted.
+                    if (payload_app_id == APP_ID_HTTP_SSL_TUNNEL)
+                        snort_app_id = APP_ID_SSL;
+
                     if (TPIsAppIdAvailable(tpsession) && tp_app_id == APP_ID_HTTP
                             && !get_session_flags(APPID_SESSION_APP_REINSPECT))
                     {
@@ -1091,8 +1080,7 @@ bool AppIdSession::do_third_party_discovery(IpProtocol protocol, const sfip_t* i
                     if (tp_app_id == APP_ID_SSL)
                     {
                         tp_app_id = porAppId;
-                        //SSL policy needs to determine IMAPS/POP3S etc before appId sees first
-                        // server packet
+                        //SSL policy determines IMAPS/POP3S etc before appId sees first server packet
                         portServiceAppId = porAppId;
                         if (session_logging_enabled)
                             LogMessage("AppIdDbg %s SSL is service %d, portServiceAppId %d\n", session_logging_id,
@@ -1117,8 +1105,8 @@ bool AppIdSession::do_third_party_discovery(IpProtocol protocol, const sfip_t* i
             }
             else
             {
-                if (protocol != IpProtocol::TCP || !p->dsize
-                        || (p->packet_flags & (PKT_STREAM_ORDER_OK | PKT_STREAM_ORDER_BAD)))
+                if (protocol != IpProtocol::TCP ||
+                                (p->packet_flags & (PKT_STREAM_ORDER_OK | PKT_STREAM_ORDER_BAD)))
                 {
                     if (direction == APP_ID_FROM_INITIATOR)
                     {
@@ -1500,9 +1488,17 @@ void AppIdSession::do_application_discovery(Packet* p)
     {
         if (!asd)
         {
+            uint16_t port = 0;
+
             ip = (direction == APP_ID_FROM_INITIATOR) ?
                             p->ptrs.ip_api.get_src() : p->ptrs.ip_api.get_dst();
-            AppIdSession* tmp_session = new AppIdSession(protocol, ip);
+            if ((protocol == IpProtocol::TCP || protocol == IpProtocol::UDP)
+                 && p->ptrs.sp != p->ptrs.dp)
+             {
+                 port = (direction == APP_ID_FROM_INITIATOR) ? p->ptrs.sp : p->ptrs.dp;
+             }
+
+            AppIdSession* tmp_session = new AppIdSession(protocol, ip, port);
 
             if ((flow_flags & APPID_SESSION_BIDIRECTIONAL_CHECKED) ==
             APPID_SESSION_BIDIRECTIONAL_CHECKED)
@@ -1510,15 +1506,6 @@ void AppIdSession::do_application_discovery(Packet* p)
             else
                 tmp_session->common.flow_type = APPID_FLOW_TYPE_TMP;
             tmp_session->common.flags = flow_flags;
-            tmp_session->common.initiator_ip = *ip;
-            if ((protocol == IpProtocol::TCP || protocol == IpProtocol::UDP)
-                && p->ptrs.sp != p->ptrs.dp)
-            {
-                tmp_session->common.initiator_port =
-                                (direction == APP_ID_FROM_INITIATOR) ? p->ptrs.sp : p->ptrs.dp;
-            }
-            else
-                tmp_session->common.initiator_port = 0;
             tmp_session->common.policyId = appIdPolicyId;
             p->flow->set_flow_data(tmp_session);
         }
@@ -1651,27 +1638,14 @@ void AppIdSession::do_application_discovery(Packet* p)
     asd->check_app_detection_restart();
 
     //restart inspection by 3rd party
-    if (!asd->get_session_flags(APPID_SESSION_NO_TPI))
+    if (!asd->tp_reinspect_by_initiator && (direction == APP_ID_FROM_INITIATOR) && checkThirdPartyReinspect(p, asd))
     {
-        if (TPIsAppIdDone(asd->tpsession) && asd->get_session_flags(
-            APPID_SESSION_HTTP_SESSION) && p->dsize)
-        {
-            if (asd->tp_reinspect_by_initiator)
-            {
-                asd->clear_session_flags(APPID_SESSION_APP_REINSPECT);
-                if (direction == APP_ID_FROM_RESPONDER)
-                    asd->tp_reinspect_by_initiator = 0; //toggle at OK response
-            }
-            else if (direction == APP_ID_FROM_INITIATOR)
-            {
-                asd->tp_reinspect_by_initiator = 1;     //once per request
-                asd->set_session_flags(APPID_SESSION_APP_REINSPECT);
-                if (asd->session_logging_enabled)
-                    LogMessage("AppIdDbg %s 3rd party allow reinspect http\n",
-                            asd->session_logging_id);
-                asd->clear_http_field();
-            }
-        }
+        asd->tp_reinspect_by_initiator = true;
+        asd->set_session_flags(APPID_SESSION_APP_REINSPECT);
+        if (asd->session_logging_enabled)
+            LogMessage("AppIdDbg %s 3rd party allow reinspect http\n",
+                    asd->session_logging_id);
+        asd->clear_http_field();
     }
 
     if (asd->tp_app_id == APP_ID_SSH && asd->payload_app_id != APP_ID_SFTP &&
@@ -1693,14 +1667,39 @@ void AppIdSession::do_application_discovery(Packet* p)
     isTpAppidDiscoveryDone = asd->do_third_party_discovery(protocol, ip, p, direction);
 #endif
 
-    if (direction == APP_ID_FROM_RESPONDER && !asd->get_session_flags(
-        APPID_SESSION_PORT_SERVICE_DONE|APPID_SESSION_SYN_RST))
+    if ( asd->tp_reinspect_by_initiator && checkThirdPartyReinspect(p, asd) )
     {
-        asd->set_session_flags(APPID_SESSION_PORT_SERVICE_DONE);
-        asd->portServiceAppId = getPortServiceId(protocol, p->ptrs.sp, asd->config);
-        if (asd->session_logging_enabled)
-            LogMessage("AppIdDbg %s port service %d\n", asd->session_logging_id,
-                asd->portServiceAppId);
+        asd->clear_session_flags(APPID_SESSION_APP_REINSPECT);
+        if (direction == APP_ID_FROM_RESPONDER)
+            asd->tp_reinspect_by_initiator = false; //toggle at OK response
+    }
+
+    if ( !asd->get_session_flags(APPID_SESSION_PORT_SERVICE_DONE) )
+    {
+        switch (protocol)
+        {
+        case IpProtocol::TCP:
+            if (asd->get_session_flags(APPID_SESSION_SYN_RST)) // TCP-specific exception
+                break;
+            // fall through to next test
+        case IpProtocol::UDP:
+            // Both TCP and UDP need this test to be made
+            //  against only the p->src_port of the response.
+            // For all other cases the port parameter is never checked.
+            if (direction != APP_ID_FROM_RESPONDER)
+                break;
+            // fall through to all other cases
+        // All protocols other than TCP and UDP come straight here.
+        default:
+            {
+                asd->portServiceAppId = getPortServiceId(protocol, p->ptrs.sp, asd->config);
+                if (asd->session_logging_enabled)
+                     LogMessage("AppIdDbg %s port service %d\n",
+                                asd->session_logging_id, asd->portServiceAppId);
+                asd->set_session_flags(APPID_SESSION_PORT_SERVICE_DONE);
+            }
+            break;
+        }
     }
 
     /* Length-based detectors. */
@@ -1740,6 +1739,7 @@ void AppIdSession::do_application_discovery(Packet* p)
         else if (asd->get_session_flags(APPID_SESSION_SSL_SESSION) && asd->tsession)
             asd->examine_ssl_metadata(p);
     }
+    // FIXIT-M - snort 2.x has added a check for midstream pickup to this if, do we need that?
     else if (protocol != IpProtocol::TCP || !p->dsize || (p->packet_flags & PKT_STREAM_ORDER_OK))
     {
         // FIXIT-M commented out assignment causes analysis warning
@@ -2279,35 +2279,58 @@ void AppIdSession::set_client_app_id_data(AppId clientAppId, char** version)
 
 void AppIdSession::sync_with_snort_id(AppId newAppId, Packet* p)
 {
-    AppInfoTableEntry* entry;
-    int16_t tempSnortId = snort_id;
-
-    if (tempSnortId == UNSYNCED_SNORT_ID)
-        tempSnortId = snort_id = p->flow->ssn_state.application_protocol;
+    if (newAppId  > APP_ID_NONE && newAppId < SF_APPID_MAX)
+    {
+        // Certain AppIds are not useful to identifying snort preprocessor choices
+        switch (newAppId)
+        {
+        case APP_ID_FTPS:
+        case APP_ID_FTPSDATA:
+
+            // These all are variants of HTTPS
+        case APP_ID_DDM_SSL:
+        case APP_ID_MSFT_GC_SSL:
+        case APP_ID_NSIIOPS:
+        case APP_ID_SF_APPLIANCE_MGMT:
+        case APP_ID_HTTPS:
+
+        case APP_ID_IMAPS:
+        case APP_ID_IRCS:
+        case APP_ID_LDAPS:
+        case APP_ID_NNTPS:
+        case APP_ID_POP3S:
+        case APP_ID_SMTPS:
+        case APP_ID_SSHELL:
+        case APP_ID_TELNETS:
+            return;
 
-    if (tempSnortId == snortId_for_ftp || tempSnortId == snortId_for_ftp_data ||
-        tempSnortId == snortId_for_imap || tempSnortId == snortId_for_pop3 ||
-        tempSnortId == snortId_for_smtp || tempSnortId == snortId_for_http2)
-    {
-        return; // These preprocessors, in snort proper, already know and expect these to remain
-                // unchanged.
-    }
-    if ((entry = app_info_mgr->get_app_info_entry(newAppId)) && (tempSnortId = entry->snortId))
-    {
-        // Snort has a separate protocol ID for HTTP/2.  We don't.  So, when we
-        // talk to them about it, we have to play by their rules.
-        if ((newAppId == APP_ID_HTTP) && (is_http2))
-            tempSnortId = snortId_for_http2;
+        case APP_ID_HTTP:
+            if (is_http2)
+                newAppId = APP_ID_HTTP2;
+            break;
+        default:
+            break;
+        }
 
-        if (tempSnortId != snort_id)
+        AppInfoTableEntry *entry = app_info_mgr->get_app_info_entry(newAppId);
+        if ( entry )
         {
-            if (session_logging_enabled)
-                if (tempSnortId == snortId_for_http2)
-                    LogMessage("AppIdDbg %s Telling Snort that it's HTTP/2\n",
-                        session_logging_id);
+            int16_t tempSnortId = entry->snortId;
+            // A particular APP_ID_xxx may not be assigned a service_snort_key value
+            // in the rna_app.yaml file entry; so ignore the tempSnortId == 0 case.
+            if( tempSnortId == 0 && (newAppId == APP_ID_HTTP2))
+                tempSnortId = snortId_for_http2;
+
+            if ( tempSnortId != snort_id )
+            {
+                snort_id = tempSnortId;
+                if (session_logging_enabled)
+                    if (tempSnortId == snortId_for_http2)
+                        LogMessage("AppIdDbg %s Telling Snort that it's HTTP/2\n",
+                                   session_logging_id);
 
-            p->flow->ssn_state.application_protocol = tempSnortId;
-            snort_id = tempSnortId;
+                p->flow->ssn_state.application_protocol = tempSnortId;
+            }
         }
     }
 }
@@ -2591,14 +2614,15 @@ void AppIdSession::free_http_session_data()
 
     clear_http_field();
 
-    for (i = 0; i < NUMBER_OF_PTYPES; i++)
-    {
-        if (nullptr != hsession->new_field[i])
+    if (hsession->new_field_contents)
+        for (i = 0; i < NUMBER_OF_PTYPES; i++)
         {
-            snort_free(hsession->new_field[i]);
-            hsession->new_field[i] = nullptr;
+            if (nullptr != hsession->new_field[i])
+            {
+                snort_free(hsession->new_field[i]);
+                hsession->new_field[i] = nullptr;
+            }
         }
-    }
     if (hsession->fflow)
     {
         snort_free(hsession->fflow);
@@ -3056,19 +3080,18 @@ void AppIdSession::clear_app_id_data()
         thirdparty_appid_module->session_delete(tpsession, 1);
 }
 
-int AppIdSession::initial_CHP_sweep(char** chp_buffers, MatchedCHPAction** ppmatches)
+int AppIdSession::initial_CHP_sweep(char** chp_buffers, uint16_t* chp_buffer_lengths, MatchedCHPAction** ppmatches)
 {
     CHPApp* cah = nullptr;
     int longest = 0;
-    int size, i;
     CHPTallyAndActions chp;
     chp.matches = *ppmatches;
 
-    for (i = 0; i <= MAX_KEY_PATTERN; i++)
+    for (unsigned i = 0; i <= MAX_KEY_PATTERN; i++)
     {
         ppmatches[i] = nullptr;
-        if (chp_buffers[i] && (size = strlen(chp_buffers[i])))
-            scan_key_chp((PatternType)i, chp_buffers[i], size, chp);
+        if (chp_buffers[i] && chp_buffer_lengths[i])
+            scan_key_chp((PatternType)i, chp_buffers[i], chp_buffer_lengths[i], chp);
     }
     if (chp.match_tally.empty())
         return 0;
@@ -3091,7 +3114,7 @@ int AppIdSession::initial_CHP_sweep(char** chp_buffers, MatchedCHPAction** ppmat
     {
         // We were planning to pass along the content of ppmatches to the second phase and let
         // them be freed inside scanCHP, but we have no candidate so we free here
-        for (i = 0; i <= MAX_KEY_PATTERN; i++)
+        for (unsigned i = 0; i <= MAX_KEY_PATTERN; i++)
         {
             if (ppmatches[i])
             {
@@ -3106,7 +3129,7 @@ int AppIdSession::initial_CHP_sweep(char** chp_buffers, MatchedCHPAction** ppmat
        candidate has been chosen and it is pointed to by cah
        we will preserve any match sets until the calls to scanCHP()
       ***************************************************************/
-    for (i = 0; i < NUMBER_OF_PTYPES; i++)
+    for (unsigned i = 0; i < NUMBER_OF_PTYPES; i++)
     {
         ptype_scan_counts[i] = cah->ptype_scan_counts[i];
         hsession->ptype_req_counts[i] = cah->ptype_req_counts[i] +
@@ -3164,7 +3187,7 @@ void AppIdSession::clearMiscHttpFlags()
 
 void AppIdSession::processCHP(char** version, Packet* p)
 {
-    int i, size;
+    int i;
     int found_in_buffer = 0;
     char* user = nullptr;
     AppId chp_final;
@@ -3184,6 +3207,18 @@ void AppIdSession::processCHP(char** version, Packet* p)
         http_session->body,
     };
 
+    uint16_t chp_buffer_lengths[NUMBER_OF_PTYPES] = {
+        http_session->useragent_buflen,
+        http_session->host_buflen,
+        http_session->referer_buflen,
+        http_session->uri_buflen,
+        http_session->cookie_buflen,
+        http_session->req_body_buflen,
+        http_session->content_type_buflen,
+        http_session->location_buflen,
+        http_session->body_buflen,
+    };
+
     char* chp_rewritten[NUMBER_OF_PTYPES] =
     {
         nullptr,nullptr,nullptr,
@@ -3213,51 +3248,68 @@ void AppIdSession::processCHP(char** version, Packet* p)
             }
         }
 
-        if (!initial_CHP_sweep(chp_buffers, chp_matches))
+        if (!initial_CHP_sweep(chp_buffers, chp_buffer_lengths, chp_matches))
             http_session->chp_finished = 1; // this is a failure case.
     }
+
     if (!http_session->chp_finished && http_session->chp_candidate)
     {
         for (i = 0; i < NUMBER_OF_PTYPES; i++)
         {
-            if (ptype_scan_counts[i] && chp_buffers[i] && (size = strlen(chp_buffers[i])) > 0)
+            if ( !ptype_scan_counts[i] )
+                continue;
+
+            if ( chp_buffers[i] && chp_buffer_lengths[i] )
             {
                 found_in_buffer = 0;
-                ret = scan_chp((PatternType)i, chp_buffers[i], size, chp_matches[i], version, &user,
-                        &chp_rewritten[i], &found_in_buffer, http_session, p);
+                ret = scan_chp((PatternType)i, chp_buffers[i], chp_buffer_lengths[i], chp_matches[i], version, &user,
+                               &chp_rewritten[i], &found_in_buffer, http_session, p);
                 chp_matches[i] = nullptr; // freed by scanCHP()
                 http_session->total_found += found_in_buffer;
-                http_session->num_scans--;
-                ptype_scan_counts[i] = 0;
-                // Give up if scanCHP returns nothing, OR
-                // (if we did not match the right numbher of patterns in this field AND EITHER
-                // (there is no match quota [all must match]) OR
-                // (the total number of matches is less than our match quota))
-                if (!ret ||
-                    (found_in_buffer < http_session->ptype_req_counts[i] &&
-                    (!http_session->num_matches ||
-                    http_session->total_found < http_session->num_matches)))
+                if (!ret || found_in_buffer < http_session->ptype_req_counts[i])
                 {
-                    http_session->chp_candidate = 0;
-                    break;
+                    // No match at all or the required matches for the field was NOT made
+                    if (!http_session->num_matches)
+                    {
+                        // num_matches == 0 means: all must succeed
+                        // give up early
+                        http_session->chp_candidate = 0;
+                        break;
+                    }
                 }
-                /* We are finished if we have a num_matches target and we've met it or
-                   if we have done all the scans */
-                if (!http_session->num_scans ||
-                    (http_session->num_matches && http_session->total_found >=
-                    http_session->num_matches))
+            }
+            else
+            {
+                if (!http_session->num_matches)
                 {
-                    http_session->chp_finished = 1;
+                    // num_matches == 0 means: all must succeed  give up early
+                    http_session->chp_candidate = 0;
                     break;
                 }
             }
-            else if (ptype_scan_counts[i] && !http_session->chp_hold_flow)
+
+            // Decrement the expected scan count toward 0.
+            ptype_scan_counts[i] = 0;
+            http_session->num_scans--;
+            // if we have reached the end of the list of scans (which have something to do), then num_scans == 0
+            if (http_session->num_scans == 0)
             {
-                /* we have a scan count, but nothing in the buffer, so we should drop out of CHP */
-                http_session->chp_candidate = 0;
+                // we finished the last scan
+                // either the num_matches value was zero and we failed early-on or we need to check for the min.
+                if (http_session->num_matches &&
+                                http_session->total_found < http_session->num_matches)
+                {
+                    // There was a minimum scans match count (num_matches != 0)
+                    // And we did not reach that minimum
+                    http_session->chp_candidate = 0;
+                    break;
+                }
+                // All required matches were met.
+                http_session->chp_finished = 1;
                 break;
             }
         }
+
         if (!http_session->chp_candidate)
         {
             http_session->chp_finished = 1;
@@ -3287,25 +3339,17 @@ void AppIdSession::processCHP(char** version, Packet* p)
         }
         if (http_session->chp_candidate && http_session->chp_finished)
         {
-            chp_final = http_session->chp_alt_candidate ?
-                http_session->chp_alt_candidate :
-                http_session->chp_candidate >> CHP_APPID_BITS_FOR_INSTANCE; // transform the
-                                                                            // instance into the
-                                                                            // appId.
+            chp_final = http_session->chp_alt_candidate ? http_session->chp_alt_candidate :
+                            CHP_APPIDINSTANCE_TO_ID(http_session->chp_candidate);
+
             if (http_session->app_type_flags & APP_TYPE_SERVICE)
-            {
                 set_service_appid_data(chp_final, nullptr, version);
-            }
 
             if (http_session->app_type_flags & APP_TYPE_CLIENT)
-            {
                 set_client_app_id_data(chp_final, version);
-            }
 
             if (http_session->app_type_flags & APP_TYPE_PAYLOAD)
-            {
                 set_payload_app_id_data((ApplicationId)chp_final, version);
-            }
 
             if (http_session->fflow && http_session->fflow->flow_prepared)
             {
@@ -3326,6 +3370,7 @@ void AppIdSession::processCHP(char** version, Packet* p)
                     username_service = serviceAppId;
                 set_session_flags(APPID_SESSION_LOGIN_SUCCEEDED);
             }
+
             for (i = 0; i < NUMBER_OF_PTYPES; i++)
             {
                 if (nullptr != chp_rewritten[i])
@@ -3336,6 +3381,7 @@ void AppIdSession::processCHP(char** version, Packet* p)
                     if (http_session->new_field[i])
                         snort_free(http_session->new_field[i]);
                     http_session->new_field[i] = chp_rewritten[i];
+                    http_session->new_field_contents = true;
                     chp_rewritten[i] = nullptr;
                 }
             }
@@ -3368,6 +3414,7 @@ void AppIdSession::processCHP(char** version, Packet* p)
 }
 
 int AppIdSession::processHTTPPacket(int direction)
+
 {
     Profile http_profile_context(httpPerfStats);
     constexpr auto RESPONSE_CODE_LENGTH = 3;
@@ -3386,7 +3433,6 @@ int AppIdSession::processHTTPPacket(int direction)
     char* useragent;
     char* referer;
     char* via;
-    AppInfoTableEntry* entry;
 
     http_session = hsession;
     if (!http_session)
@@ -3416,9 +3462,8 @@ int AppIdSession::processHTTPPacket(int direction)
         if (http_session->response_code)
         {
             set_session_flags(APPID_SESSION_RESPONSE_CODE_CHECKED);
-            if (strlen(http_session->response_code) != RESPONSE_CODE_LENGTH)
-            {
-                /* received bad response code. Stop processing this asd */
+            if (http_session->response_code_buflen != RESPONSE_CODE_LENGTH)            {
+                /* received bad response code. Stop processing this session */
                 clear_app_id_data();
                 if (session_logging_enabled)
                     LogMessage("AppIdDbg %s bad http response code\n", session_logging_id);
@@ -3500,8 +3545,7 @@ int AppIdSession::processHTTPPacket(int direction)
                     }
                     if (local_subtype)
                     {
-                        for (tmpSubtype = &subtype; *tmpSubtype; tmpSubtype =
-                            &(*tmpSubtype)->next)
+                        for (tmpSubtype = &subtype; *tmpSubtype; tmpSubtype = &(*tmpSubtype)->next)
                             ;
 
                         *tmpSubtype = local_subtype;
@@ -3518,15 +3562,16 @@ int AppIdSession::processHTTPPacket(int direction)
             }
 
             // Scan User-Agent for Browser types or Skype
-            if ((scan_flags & SCAN_HTTP_USER_AGENT_FLAG) && client_app_id <=  APP_ID_NONE
-                    && useragent && (size = strlen(useragent)) > 0)
+            if ((scan_flags & SCAN_HTTP_USER_AGENT_FLAG) && client_app_id <= APP_ID_NONE
+                    && useragent && http_session->useragent_buflen)
             {
                 if (version)
                 {
                     snort_free(version);
                     version = nullptr;
                 }
-                identify_user_agent((uint8_t*)useragent, size, &service_id, &client_id, &version);
+                identify_user_agent((uint8_t*)useragent, http_session->useragent_buflen,
+                    &service_id, &client_id, &version);
                 if (session_logging_enabled && service_id > APP_ID_NONE &&
                         service_id != APP_ID_HTTP && serviceAppId != service_id)
                     LogMessage("AppIdDbg %s User Agent is service %d\n", session_logging_id,
@@ -3647,11 +3692,13 @@ int AppIdSession::processHTTPPacket(int direction)
 
         if (client_app_id == APP_ID_APPLE_CORE_MEDIA)
         {
+            AppInfoTableEntry* entry;
+
             if (tp_payload_app_id > APP_ID_NONE)
             {
                 entry = app_info_mgr->get_app_info_entry(tp_payload_app_id);
                 // only move tpPayloadAppId to client if its got a clientAppId
-                if (entry->clientId > APP_ID_NONE)
+                if (entry && entry->clientId > APP_ID_NONE)
                 {
                     misc_app_id = client_app_id;
                     client_app_id = tp_payload_app_id;
@@ -3661,7 +3708,7 @@ int AppIdSession::processHTTPPacket(int direction)
             {
                 entry =  app_info_mgr->get_app_info_entry(payload_app_id);
                 // only move payloadAppId to client if it has a ClientAppid
-                if (entry->clientId > APP_ID_NONE)
+                if (entry && entry->clientId > APP_ID_NONE)
                 {
                     misc_app_id = client_app_id;
                     client_app_id = payload_app_id;
index 8e05b525a6810c6735012d8c90bc330388246f6a..f147091638aedd6f3d8980e31ab7266e7d5f2b0e 100644 (file)
@@ -115,28 +115,35 @@ struct fflow_info
 struct httpSession
 {
     char* host;
+    uint16_t host_buflen;
     char* url;
     char* uri;
+    uint16_t uri_buflen;
     char* via;
     char* useragent;
+    uint16_t useragent_buflen;
     char* response_code;
+    uint16_t response_code_buflen;
     char* referer;
+    uint16_t referer_buflen;
     char* cookie;
+    uint16_t cookie_buflen;
     char* content_type;
+    uint16_t content_type_buflen;
     char* location;
+    uint16_t location_buflen;
     char* body;
+    uint16_t body_buflen;
     char* req_body;
+    uint16_t req_body_buflen;
     char* server;
     char* x_working_with;
     char* new_field[HTTP_FIELD_MAX+1];
-
-    uint16_t uriOffset;
-    uint16_t uriEndOffset;
-    uint16_t cookieOffset;
-    uint16_t cookieEndOffset;
-
+    uint16_t new_field_len[HTTP_FIELD_MAX+1];
+    uint16_t fieldOffset[HTTP_FIELD_MAX+1];
+    uint16_t fieldEndOffset[HTTP_FIELD_MAX+1];
     fflow_info* fflow;
-
+    bool new_field_contents;
     int chp_finished;
     AppId chp_candidate;
     AppId chp_alt_candidate;
@@ -147,9 +154,7 @@ struct httpSession
     int num_matches;
     int num_scans;
     int get_offsets_from_rebuilt;
-    bool skip_simple_detect;    // Flag to indicate if simple detection of client ID, payload ID,
-                                // etc
-                                // should be skipped
+    bool skip_simple_detect;
     sfip_t* xffAddr;
     const char** xffPrecedence;
     int numXffFields;
@@ -187,16 +192,12 @@ struct tlsSession
     int tls_orgUnit_strlen;
 };
 
-/* The UNSYNCED_SNORT_ID value is to cheaply insure we get
-   the value from snort rather than assume */
-#define UNSYNCED_SNORT_ID   0x5555
-
 void map_app_names_to_snort_ids();
 
 class AppIdSession : public FlowData
 {
 public:
-    AppIdSession(IpProtocol, const sfip_t*);
+    AppIdSession(IpProtocol, const sfip_t*, uint16_t port);
     ~AppIdSession();
 
     static AppIdSession* allocate_session(const Packet*, IpProtocol, int);
@@ -207,7 +208,7 @@ public:
 
     AppIdConfig* config = nullptr;
     CommonAppIdData common;
-    AppIdSession* next = nullptr;
+    //AppIdSession* next = nullptr;
     Flow* flow = nullptr;
     AppIdFlowData* flowData = nullptr;
     AppInfoManager* app_info_mgr = nullptr;
@@ -263,10 +264,10 @@ public:
     void* tpsession = nullptr;
     uint16_t init_tpPackets = 0;
     uint16_t resp_tpPackets = 0;
-    uint8_t tp_reinspect_by_initiator = 0;
+    bool tp_reinspect_by_initiator = false;
     char* payload_version = nullptr;
     uint16_t session_packet_count = 0;
-    int16_t snort_id = UNSYNCED_SNORT_ID;
+    int16_t snort_id = 0;
 
     /* Length-based detectors. */
     LengthKey length_sequence;
@@ -351,6 +352,8 @@ public:
     AppId fw_pick_payload_app_id();
     AppId fw_pick_referred_payload_app_id();
     bool is_ssl_session_decrypted();
+    int processHTTPPacket(Packet*, int, HttpParsedHeaders* const);
+
 private:
     bool do_client_discovery(int, Packet*);
     bool do_service_discovery(IpProtocol, int, AppId, AppId,  Packet*);
@@ -373,7 +376,7 @@ private:
     void stop_rna_service_inspection(Packet*,  int);
     void set_session_logging_state(const Packet* pkt, int direction);
     void clear_app_id_data();
-    int initial_CHP_sweep(char**, MatchedCHPAction**);
+    int initial_CHP_sweep(char**, uint16_t*, MatchedCHPAction**);
     void clearMiscHttpFlags();
     void processCHP(char**, Packet*);
 
@@ -383,7 +386,6 @@ private:
     void checkTerminateTpModule(uint16_t tpPktCount);
     bool do_third_party_discovery(IpProtocol, const sfip_t*,  Packet*, int&);
     void pickHttpXffAddress(Packet*, ThirdPartyAppIDAttributeData*);
-
 #endif
 
     void create_session_logging_id(int direction, Packet* pkt);
index 74369e70750438ddc0953c5e5ef1ff2b1a05ac73..3a84907a7694540220fc0c1b1f496874d3855988 100644 (file)
@@ -245,8 +245,6 @@ enum ApplicationId : int32_t
     APP_ID_ICAP                           = 216,
     APP_ID_ICA                            = 217,
     APP_ID_ICESHARE                       = 218,
-    APP_ID_ICMP                           = 219,
-    APP_ID_ICMPV6                         = 220,
     APP_ID_ICP                            = 221,
     APP_ID_ICQ2GO                         = 222,
     APP_ID_IDP                            = 223,
@@ -989,6 +987,7 @@ enum ApplicationId : int32_t
     APP_ID_AOL                            = 1419,
     APP_ID_MDNS                           = 1755,
     APP_ID_APPLE_CORE_MEDIA               = 2253,
+    APP_ID_HTTP_TUNNEL                    = 2296,
     APP_ID_ULTRASURF                      = 2634,
     APP_ID_LYCOS                          = 2775,
     APP_ID_DOGPILE                        = 2804,
@@ -997,6 +996,9 @@ enum ApplicationId : int32_t
     APP_ID_ANYCONNECT                     = 2921,
     APP_ID_ANYCONNECT_SSL_CLIENT          = 2922,
     APP_ID_ANYCONNECT_IPSEC_CLIENT        = 2923,
+    APP_ID_ICMP                           = 3501,
+    APP_ID_ICMPV6                         = 3558,
+    APP_ID_HTTP_SSL_TUNNEL                = 3860,
     APP_ID_FTP_ACTIVE                     = 4002,
     APP_ID_FTP_PASSIVE                    = 4003,
     APP_ID_UNKNOWN_UI                     = 65535  // this causes the UI to render Unknown instead of pending or blank
index dc82b8b5c70713c6e3df8047f4f04b08ff9d53d9..0f898c8025a60424b3b7d80caceb0e23f6c2b993 100644 (file)
@@ -74,7 +74,7 @@ THREAD_LOCAL AIM_CLIENT_APP_CONFIG aim_config;
 
 #define MAX_VERSION_SIZE    64
 
-static CLIENT_APP_RETCODE aim_init(const IniClientAppAPI* const, SF_LIST* config);
+static CLIENT_APP_RETCODE aim_init(const InitClientAppAPI* const, SF_LIST* config);
 static CLIENT_APP_RETCODE aim_validate( const uint8_t* data, uint16_t size, const int dir,
         AppIdSession*, Packet*, Detector*);
 
@@ -123,7 +123,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_AOL_INSTANT_MESSENGER, APPINFO_FLAG_CLIENT_ADDITIONAL | APPINFO_FLAG_CLIENT_USER },
 };
 
-static CLIENT_APP_RETCODE aim_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE aim_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     aim_config.enabled = 1;
 
index ce97190515c58b107f26667ea711624c4276a3fc..e09c4999757559aa005696cf61babccc02a33234 100644 (file)
@@ -59,7 +59,7 @@ struct RNAClientAppModuleConfigItem
 using RNAClientAppFCN = CLIENT_APP_RETCODE(*)( const uint8_t* data, uint16_t size, const int dir,
     AppIdSession*, Packet*, Detector*);
 
-struct IniClientAppAPI
+struct InitClientAppAPI
 {
     void (* RegisterPattern)(RNAClientAppFCN, IpProtocol proto, const uint8_t* const pattern,
         unsigned size, int position);
@@ -78,7 +78,7 @@ struct FinalizeClientAppAPI
     void* data = nullptr;
 };
 
-using RNAClientAppInitFCN = CLIENT_APP_RETCODE(*)(const IniClientAppAPI* const, SF_LIST* config);
+using RNAClientAppInitFCN = CLIENT_APP_RETCODE(*)(const InitClientAppAPI* const, SF_LIST* config);
 using RNAClientAppFinalizeFCN = CLIENT_APP_RETCODE (*)(const FinalizeClientAppAPI* const);
 using RNAClientAppCleanFCN = void(*)();
 
index 4085f4e72aa32e83dde4e4d2cfd921fb69220415..22c9f8191e252b96c2548414c378d3220a252334 100644 (file)
@@ -41,7 +41,6 @@
 #include "fw_appid.h"
 #include "client_app_api.h"
 #include "client_app_base.h"
-#include "client_app_smtp.h"
 #include "client_app_msn.h"
 #include "client_app_aim.h"
 #include "client_app_ym.h"
@@ -85,7 +84,7 @@ static void CClientAppRegisterPatternNoCase(RNAClientAppFCN fcn, IpProtocol prot
     const uint8_t* const pattern, unsigned size, int position);
 static void appSetClientValidator(RNAClientAppFCN fcn, AppId appId, unsigned extractsInfo);
 
-static IniClientAppAPI client_init_api =
+static InitClientAppAPI client_init_api =
 {
     &CClientAppRegisterPattern,
     &LuaClientAppRegisterPattern,
@@ -113,7 +112,6 @@ extern RNAClientAppModule http_client_mod;
 
 static RNAClientAppModule* static_client_list[] =
 {
-    &smtp_client_mod,
     &ssh_client_mod,
     &msn_client_mod,
     &aim_client_mod,
@@ -337,6 +335,9 @@ int ClientAppLoadCallback(void* symbol)
         li->module = cam;
         cam->api = &client_app_api;
         cam->flow_data_index = client_module_index | APPID_SESSION_DATA_CLIENT_MODSTATE_BIT;
+        if (cam->init && cam->init(&client_init_api, nullptr))
+            ErrorMessage("Error initializing client %s\n", cam->name);
+
         client_module_index++;
     }
     /*Can't set cam->userData to nullptr because Lua detectors use it although C detectors don't
@@ -870,26 +871,8 @@ static void ClientAppID(Packet* p, const int /*direction*/, AppIdSession* asd)
             break;
         }
     }
-    FreeClientPatternList(&match_list);
 
-    if (sflist_count(asd->candidate_client_list) == 0)
-    {
-        client = nullptr;
-        switch (p->ptrs.dp)
-        {
-        case 465:
-            if (asd->get_session_flags(APPID_SESSION_DECRYPTED))
-                client = &smtp_client_mod;
-            break;
-        default:
-            break;
-        }
-        if (client != nullptr)
-        {
-            sflist_add_tail(asd->candidate_client_list, (void*)client);
-            asd->num_candidate_clients_tried++;
-        }
-    }
+    FreeClientPatternList(&match_list);
 }
 
 int AppIdDiscoverClientApp(Packet* p, int direction, AppIdSession* rnaData)
index ff12bcd1009f76da6740219995886f40152447c8..aa6ebf9108c0ffc676ec7a0b28ec58d6fbb45539 100644 (file)
@@ -71,7 +71,7 @@ struct BIT_CLIENT_APP_CONFIG
 
 THREAD_LOCAL BIT_CLIENT_APP_CONFIG bit_config;
 
-static CLIENT_APP_RETCODE bit_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE bit_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE bit_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
 
@@ -109,7 +109,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_BITTORRENT, 0 }
 };
 
-static CLIENT_APP_RETCODE bit_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE bit_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
     RNAClientAppModuleConfigItem* item;
index eaff50aec39142db8ccbb412a5cbe367b9ac87c0..63e7db63bc1683aa904ea851817e1500ad96efef 100644 (file)
@@ -70,7 +70,7 @@ struct BIT_CLIENT_APP_CONFIG
 
 THREAD_LOCAL BIT_CLIENT_APP_CONFIG udp_bit_config;
 
-static CLIENT_APP_RETCODE udp_bit_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE udp_bit_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE udp_bit_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
 
@@ -110,7 +110,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_BITTRACKER_CLIENT, 0 }
 };
 
-static CLIENT_APP_RETCODE udp_bit_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE udp_bit_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
 
index 0b04ee9031fb375ace60fbd7911e5b56946755b8..9f4bebd747758ebbf847b70b080831f42d483899 100644 (file)
@@ -69,7 +69,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_MSNP, APPINFO_FLAG_CLIENT_ADDITIONAL }
 };
 
-static CLIENT_APP_RETCODE msn_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE msn_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     RNAClientAppModuleConfigItem* item;
     msn_config.enabled = 1;
index 3e9c5e96620ff9ae9097ae3cc7ca7863c0b167f0..1e403a7e5521d7a276ad153a8ee63dd7b293b840 100644 (file)
@@ -82,7 +82,7 @@ struct RTP_CLIENT_APP_CONFIG
 
 THREAD_LOCAL RTP_CLIENT_APP_CONFIG rtp_config;
 
-static CLIENT_APP_RETCODE rtp_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE rtp_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE rtp_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
 
@@ -231,7 +231,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_RTP, 0 }
 };
 
-static CLIENT_APP_RETCODE rtp_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE rtp_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
 
diff --git a/src/network_inspectors/appid/client_plugins/client_app_smtp.cc b/src/network_inspectors/appid/client_plugins/client_app_smtp.cc
deleted file mode 100644 (file)
index 53971f5..0000000
+++ /dev/null
@@ -1,696 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2016 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2005-2013 Sourcefire, Inc.
-//
-// 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.
-//--------------------------------------------------------------------------
-
-// client_app_smtp.cc author Sourcefire Inc.
-
-#include "client_app_smtp.h"
-
-#include "main/snort_debug.h"
-#include "protocols/packet.h"
-#include "utils/sflsq.h"
-#include "utils/util.h"
-
-#include "app_info_table.h"
-#include "appid_api.h"
-#include "application_ids.h"
-#include "appid_module.h"
-
-#define  UNIT_TESTING 0
-
-#if UNIT_TESTING
-#include "fw_appid.h"
-#endif
-
-enum SMTPState
-{
-    SMTP_STATE_NONE,
-    SMTP_STATE_HELO,
-    SMTP_STATE_MAIL_FROM,
-    SMTP_STATE_RCPT_TO,
-    SMTP_STATE_DATA,
-    SMTP_STATE_MESSAGE,
-    SMTP_STATE_GET_PRODUCT_VERSION,
-    SMTP_STATE_SKIP_LINE,
-    SMTP_STATE_CONNECTION_ERROR,
-    SMTP_STATE_STARTTLS
-};
-
-#define MAX_VERSION_SIZE    64
-#define MAX_HEADER_LINE_SIZE 1024
-
-#if UNIT_TESTING
-char* stateName [] =
-{
-    "SMTP_STATE_NONE",
-    "SMTP_STATE_HELO",
-    "SMTP_STATE_MAIL_FROM",
-    "SMTP_STATE_RCPT_TO",
-    "SMTP_STATE_DATA",
-    "SMTP_STATE_MESSAGE",
-    "SMTP_STATE_GET_PRODUCT_VERSION",
-    "SMTP_STATE_SKIP_LINE",
-    "SMTP_STATE_CONNECTION_ERROR",
-    "SMTP_STATE_STARTTLS"
-};
-#endif
-
-/* flag values for ClientSMTPData */
-#define CLIENT_FLAG_STARTTLS_SENT   0x01
-#define CLIENT_FLAG_SMTPS           0x02
-
-struct ClientSMTPData
-{
-    int flags;
-    SMTPState state;
-    SMTPState nextstate;
-    uint8_t version[MAX_VERSION_SIZE];
-    unsigned pos;
-    uint8_t* headerline;
-};
-
-struct SMTP_CLIENT_APP_CONFIG
-{
-    int enabled;
-};
-
-THREAD_LOCAL SMTP_CLIENT_APP_CONFIG smtp_config;
-
-static CLIENT_APP_RETCODE smtp_init(const IniClientAppAPI* const init_api, SF_LIST* config);
-static CLIENT_APP_RETCODE smtp_validate(const uint8_t* data, uint16_t size, const int dir,
-    AppIdSession* asd, Packet* pkt, struct Detector* userData);
-
-SO_PUBLIC RNAClientAppModule smtp_client_mod =
-{
-    "SMTP",                 // name
-    IpProtocol::TCP,            // proto
-    &smtp_init,             // init
-    nullptr,                // clean
-    &smtp_validate,         // validate
-    1,                      // minimum_matches
-    nullptr,                // api
-    nullptr,                // userData
-    0,                      // precedence
-    nullptr,                // finalize,
-    1,                      // provides_user
-    0                       // flow_data_index
-};
-
-struct Client_App_Pattern
-{
-    const uint8_t* pattern;
-    unsigned length;
-    int index;
-    unsigned appId;
-};
-
-#define HELO "HELO "
-#define EHLO "EHLO "
-#define MAILFROM "MAIL FROM:"
-#define RCPTTO "RCPT TO:"
-#define DATA "DATA"
-#define RSET "RSET"
-#define AUTH "AUTH PLAIN"
-#define STARTTLS "STARTTLS"
-
-#define STARTTLS_COMMAND_SUCCESS "220 "
-
-#define MICROSOFT "Microsoft "
-#define OUTLOOK "Outlook"
-#define EXPRESS "Express "
-#define IMO "IMO, "
-
-#define XMAILER "X-Mailer: "
-#define USERAGENT "User-Agent: "
-
-static const uint8_t APP_SMTP_OUTLOOK[] = "Microsoft Outlook";
-static const uint8_t APP_SMTP_OUTLOOK_EXPRESS[] = "Microsoft Outlook Express ";
-static const uint8_t APP_SMTP_IMO[] = "IMO, ";
-static const uint8_t APP_SMTP_EVOLUTION[] = "Ximian Evolution ";
-static const uint8_t APP_SMTP_LOTUS_NOTES[] =  "Lotus Notes ";
-static const uint8_t APP_SMTP_APPLEMAIL[] =  "Apple Mail (";
-static const uint8_t APP_SMTP_EUDORA[] =  "QUALCOMM Windows Eudora Version ";
-static const uint8_t APP_SMTP_EUDORAPRO[] =  "Windows Eudora Pro Version ";
-static const uint8_t APP_SMTP_AOL[] =  "AOL ";
-static const uint8_t APP_SMTP_MUTT[] =  "Mutt/";
-static const uint8_t APP_SMTP_KMAIL[] =  "KMail/";
-static const uint8_t APP_SMTP_MTHUNDERBIRD[] =  "Mozilla Thunderbird ";
-static const uint8_t APP_SMTP_THUNDERBIRD[] =  "Thunderbird ";
-static const uint8_t APP_SMTP_MOZILLA[] = "Mozilla";
-static const uint8_t APP_SMTP_THUNDERBIRD_SHORT[] = "Thunderbird/";
-
-static Client_App_Pattern patterns[] =
-{
-    { (uint8_t*)HELO, sizeof(HELO)-1, -1, APP_ID_SMTP },
-    { (uint8_t*)EHLO, sizeof(EHLO)-1, -1, APP_ID_SMTP },
-    { APP_SMTP_OUTLOOK,         sizeof(APP_SMTP_OUTLOOK)-1,        -1, APP_ID_OUTLOOK },
-    { APP_SMTP_OUTLOOK_EXPRESS, sizeof(APP_SMTP_OUTLOOK_EXPRESS)-1,-1, APP_ID_OUTLOOK_EXPRESS },
-    { APP_SMTP_IMO,             sizeof(APP_SMTP_IMO)-1,            -1, APP_ID_SMTP_IMO },
-    { APP_SMTP_EVOLUTION,       sizeof(APP_SMTP_EVOLUTION)-1,      -1, APP_ID_EVOLUTION },
-    { APP_SMTP_LOTUS_NOTES,      sizeof(APP_SMTP_LOTUS_NOTES)-1,     -1, APP_ID_LOTUS_NOTES },
-    { APP_SMTP_APPLEMAIL,       sizeof(APP_SMTP_APPLEMAIL)-1,      -1, APP_ID_APPLE_EMAIL },
-    { APP_SMTP_EUDORA,          sizeof(APP_SMTP_EUDORA)-1,         -1, APP_ID_EUDORA },
-    { APP_SMTP_EUDORAPRO,       sizeof(APP_SMTP_EUDORAPRO)-1,      -1, APP_ID_EUDORA_PRO },
-    { APP_SMTP_AOL,             sizeof(APP_SMTP_AOL)-1,            -1, APP_ID_AOL_EMAIL },
-    { APP_SMTP_MUTT,            sizeof(APP_SMTP_MUTT)-1,           -1, APP_ID_MUTT },
-    { APP_SMTP_KMAIL,           sizeof(APP_SMTP_KMAIL)-1,          -1, APP_ID_KMAIL },
-    { APP_SMTP_MTHUNDERBIRD,    sizeof(APP_SMTP_MTHUNDERBIRD)-1,   -1, APP_ID_THUNDERBIRD },
-    { APP_SMTP_THUNDERBIRD,     sizeof(APP_SMTP_THUNDERBIRD)-1,    -1, APP_ID_THUNDERBIRD },
-};
-
-static AppRegistryEntry appIdRegistry[] =
-{
-    { APP_ID_THUNDERBIRD, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_OUTLOOK, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_KMAIL, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_EUDORA_PRO, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_EVOLUTION, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_SMTP_IMO, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_EUDORA, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_LOTUS_NOTES, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_APPLE_EMAIL, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_AOL_EMAIL, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_MUTT, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_SMTP, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_OUTLOOK_EXPRESS, APPINFO_FLAG_CLIENT_ADDITIONAL },
-    { APP_ID_SMTPS, APPINFO_FLAG_CLIENT_ADDITIONAL }
-};
-
-static CLIENT_APP_RETCODE smtp_init(const IniClientAppAPI* const init_api, SF_LIST* config)
-{
-    unsigned i;
-
-    smtp_config.enabled = 1;
-
-    if (config)
-    {
-        SF_LNODE* cursor;
-        RNAClientAppModuleConfigItem* item;
-
-        for (item = (RNAClientAppModuleConfigItem*)sflist_first(config, &cursor);
-            item;
-            item = (RNAClientAppModuleConfigItem*)sflist_next(&cursor))
-        {
-            DebugFormat(DEBUG_LOG,"Processing %s: %s\n",item->name, item->value);
-            if (strcasecmp(item->name, "enabled") == 0)
-            {
-                smtp_config.enabled = atoi(item->value);
-            }
-        }
-    }
-
-    if (smtp_config.enabled)
-    {
-        for (i=0; i < sizeof(patterns)/sizeof(*patterns); i++)
-        {
-            init_api->RegisterPattern(&smtp_validate, IpProtocol::TCP, patterns[i].pattern,
-                patterns[i].length, patterns[i].index);
-        }
-    }
-
-    unsigned j;
-    for (j=0; j < sizeof(appIdRegistry)/sizeof(*appIdRegistry); j++)
-    {
-        DebugFormat(DEBUG_LOG,"registering appId: %d\n",appIdRegistry[j].appId);
-        init_api->RegisterAppId(&smtp_validate, appIdRegistry[j].appId,
-            appIdRegistry[j].additionalInfo);
-    }
-
-    return CLIENT_APP_SUCCESS;
-}
-
-/*
- *    product - The product data should not include any characters
- *              after the end of the product version (e.g. no CR, LF, etc).
- *    prefix_len - The number of characters that are the prefix to the version,
- *              including the NUL terminating character.
- */
-static int extract_version_and_add_client_app(ApplicationId clientId, const int prefix_len,
-        const uint8_t* product, const uint8_t* product_end, ClientSMTPData* const client_data,
-        AppIdSession* asd, AppId appId, PegCount *stat_counter)
-{
-    const uint8_t* p;
-    uint8_t* v;
-    uint8_t* v_end;
-
-    v_end = client_data->version;
-    v_end += MAX_VERSION_SIZE - 1;
-
-    //  The prefix_len includes the NUL character, but product does not, so
-    //  subtract 1 from length to skip.
-    p = product + prefix_len - 1;
-    if (p >= product_end || isspace(*p))
-        return 1;
-    for (v=client_data->version; v<v_end && p < product_end; v++,p++)
-    {
-        *v = *p;
-    }
-    *v = 0;
-    smtp_client_mod.api->add_app(asd, appId, clientId, (char*)client_data->version);
-    (*stat_counter)++;
-    return 0;
-}
-
-
-/*
- *  Identify the product and version of the SMTP client.
- *
- *  Returns 0 if a recognized product is found.  Otherwise returns 1.
- */
-static int IdentifyClientVersion(ClientSMTPData* const fd, const uint8_t* product,
-    const uint8_t* data_end, AppIdSession* asd, Packet*)
-{
-    const uint8_t* p;
-    uint8_t* v;
-    uint8_t* v_end;
-    unsigned len;
-    unsigned sublen;
-    AppId appId = (fd->flags & CLIENT_FLAG_SMTPS) ?  APP_ID_SMTPS : APP_ID_SMTP;
-
-    v_end = fd->version;
-    v_end += MAX_VERSION_SIZE - 1;
-    len = data_end - product;
-    if (len >= sizeof(MICROSOFT) && memcmp(product, MICROSOFT, sizeof(MICROSOFT)-1) == 0)
-    {
-        p = product + sizeof(MICROSOFT) - 1;
-
-        if (data_end-p >= (int)sizeof(OUTLOOK) && memcmp(p, OUTLOOK, sizeof(OUTLOOK)-1) == 0)
-        {
-            p += sizeof(OUTLOOK) - 1;
-            if (p >= data_end)
-                return 1;
-            if (*p == ',')
-            {
-                p++;
-                if (p >= data_end || *p != ' ')
-                    return 1;
-                return extract_version_and_add_client_app(APP_ID_OUTLOOK, 
-                    2, p, data_end, fd, asd, appId,
-                    &appid_stats.smtp_microsoft_outlook_clients);
-            }
-            else if (*p == ' ')
-            {
-                p++;
-                if (data_end-p >= (int)sizeof(EXPRESS) && memcmp(p, EXPRESS, sizeof(EXPRESS)-1) == 0)
-                {
-                    return extract_version_and_add_client_app(APP_ID_OUTLOOK_EXPRESS, 
-                        sizeof(EXPRESS), p, data_end, fd, asd, appId,
-                        &appid_stats.smtp_microsoft_outlook_express_clients);
-                }
-                else if (data_end-p >= (int)sizeof(IMO) && memcmp(p, IMO, sizeof(IMO)-1) == 0)
-                {
-                    return extract_version_and_add_client_app(APP_ID_OUTLOOK, 
-                        sizeof(IMO), p, data_end, fd, asd, appId,
-                        &appid_stats.smtp_microsoft_outlook_imo_clients);
-                }
-            }
-        }
-    }
-    else if (len >= sizeof(APP_SMTP_EVOLUTION) && memcmp(product, APP_SMTP_EVOLUTION,
-        sizeof(APP_SMTP_EVOLUTION)-1) == 0)
-    {
-        return extract_version_and_add_client_app(APP_ID_EVOLUTION, 
-            sizeof(APP_SMTP_EVOLUTION), product, data_end, fd, asd, appId,
-            &appid_stats.smtp_evolution_clients);
-    }
-    else if (len >= sizeof(APP_SMTP_LOTUS_NOTES) && memcmp(product, APP_SMTP_LOTUS_NOTES,
-        sizeof(APP_SMTP_LOTUS_NOTES)-1) == 0)
-    {
-        return extract_version_and_add_client_app(APP_ID_LOTUS_NOTES, 
-            sizeof(APP_SMTP_LOTUS_NOTES), product, data_end, fd, asd, appId,
-            &appid_stats.smtp_lotus_notes_clients);
-    }
-    else if (len >= sizeof(APP_SMTP_APPLEMAIL) && memcmp(product, APP_SMTP_APPLEMAIL,
-        sizeof(APP_SMTP_APPLEMAIL)-1) == 0)
-    {
-        p = product + sizeof(APP_SMTP_APPLEMAIL) - 1;
-        if (p >= data_end || *(data_end - 1) != ')' || *p == ')' || isspace(*p))
-            return 1;
-        for (v=fd->version; v<v_end && p < data_end-1; v++,p++)
-        {
-            *v = *p;
-        }
-        *v = 0;
-        smtp_client_mod.api->add_app(asd, appId, APP_ID_APPLE_EMAIL, (char*)fd->version);
-        appid_stats.smtp_applemail_clients++;
-        return 0;
-    }
-    else if (len >= sizeof(APP_SMTP_EUDORA) && memcmp(product, APP_SMTP_EUDORA,
-        sizeof(APP_SMTP_EUDORA)-1) == 0)
-    {
-        return extract_version_and_add_client_app(APP_ID_EUDORA, 
-            sizeof(APP_SMTP_EUDORA), product, data_end, fd, asd, appId,
-            &appid_stats.smtp_eudora_clients);
-    }
-    else if (len >= sizeof(APP_SMTP_EUDORAPRO) && memcmp(product, APP_SMTP_EUDORAPRO,
-        sizeof(APP_SMTP_EUDORAPRO)-1) == 0)
-    {
-        return extract_version_and_add_client_app(APP_ID_EUDORA_PRO, 
-            sizeof(APP_SMTP_EUDORAPRO), product, data_end, fd, asd, appId,
-            &appid_stats.smtp_eudora_pro_clients);
-    }
-    else if (len >= sizeof(APP_SMTP_AOL) && memcmp(product, APP_SMTP_AOL, 
-        sizeof(APP_SMTP_AOL)-1) == 0)
-    {
-        return extract_version_and_add_client_app(APP_ID_AOL_EMAIL, 
-            sizeof(APP_SMTP_AOL), product, data_end, fd, asd, appId,
-            &appid_stats.smtp_aol_clients);
-    }
-    else if (len >= sizeof(APP_SMTP_MUTT) && memcmp(product, APP_SMTP_MUTT, 
-        sizeof(APP_SMTP_MUTT)-1) == 0)
-    {
-        return extract_version_and_add_client_app(APP_ID_MUTT, 
-            sizeof(APP_SMTP_MUTT), product, data_end, fd, asd, appId,
-            &appid_stats.smtp_mutt_clients);
-    }
-    else if (len >= sizeof(APP_SMTP_KMAIL) && memcmp(product, APP_SMTP_KMAIL,
-        sizeof(APP_SMTP_KMAIL)-1) == 0)
-    {
-        return extract_version_and_add_client_app(APP_ID_KMAIL, 
-            sizeof(APP_SMTP_KMAIL), product, data_end, fd, asd, appId,
-            &appid_stats.smtp_kmail_clients);
-    }
-    else if (len >= sizeof(APP_SMTP_THUNDERBIRD) && memcmp(product, APP_SMTP_THUNDERBIRD,
-        sizeof(APP_SMTP_THUNDERBIRD)-1) == 0)
-    {
-        return extract_version_and_add_client_app(APP_ID_THUNDERBIRD, 
-            sizeof(APP_SMTP_THUNDERBIRD), product, data_end, fd, asd, appId,
-            &appid_stats.smtp_thunderbird_clients);
-    }
-    else if (len >= sizeof(APP_SMTP_MTHUNDERBIRD) && memcmp(product, APP_SMTP_MTHUNDERBIRD,
-        sizeof(APP_SMTP_MTHUNDERBIRD)-1) == 0)
-    {
-        return extract_version_and_add_client_app(APP_ID_THUNDERBIRD, 
-            sizeof(APP_SMTP_MTHUNDERBIRD), product, data_end, fd, asd, appId,
-            &appid_stats.smtp_thunderbird_clients);
-    }
-    else if (len >= sizeof(APP_SMTP_MOZILLA) && memcmp(product, APP_SMTP_MOZILLA,
-        sizeof(APP_SMTP_MOZILLA)-1) == 0)
-    {
-        for (p = product + sizeof(APP_SMTP_MOZILLA) - 1; p < data_end; p++)
-        {
-            if (*p == 'T')
-            {
-                sublen = data_end - p;
-                if (sublen >= sizeof(APP_SMTP_THUNDERBIRD_SHORT) && memcmp(p,
-                    APP_SMTP_THUNDERBIRD_SHORT, sizeof(APP_SMTP_THUNDERBIRD_SHORT)-1) == 0)
-                {
-                    return extract_version_and_add_client_app(
-                        APP_ID_THUNDERBIRD, sizeof(APP_SMTP_THUNDERBIRD_SHORT),
-                        p, data_end, fd, asd, appId,
-                        &appid_stats.smtp_thunderbird_clients);
-                }
-            }
-        }
-    }
-
-    return 1;
-}
-
-static void freeData(void* data)
-{
-    ClientSMTPData* fd = (ClientSMTPData*)data;
-    snort_free(fd->headerline);
-    snort_free(fd);
-}
-
-static CLIENT_APP_RETCODE smtp_validate(const uint8_t* data, uint16_t size, const int dir,
-    AppIdSession* asd, Packet* pkt, struct Detector*)
-{
-    ClientSMTPData* fd;
-    const uint8_t* end;
-#if UNIT_TESTING
-    SMTPState currState = SMTP_STATE_NONE;
-#endif
-
-    fd = (ClientSMTPData*)smtp_client_mod.api->data_get(asd, smtp_client_mod.flow_data_index);
-    if (!fd)
-    {
-        fd = (ClientSMTPData*)snort_calloc(sizeof(ClientSMTPData));
-        if (!fd)
-            return CLIENT_APP_ENOMEM;
-        if (smtp_client_mod.api->data_add(asd, fd, smtp_client_mod.flow_data_index, &freeData))
-        {
-            snort_free(fd);
-            return CLIENT_APP_ENOMEM;
-        }
-        fd->state = SMTP_STATE_HELO;
-    }
-
-    if (dir != APP_ID_FROM_INITIATOR)
-    {
-        if ( (fd->flags & CLIENT_FLAG_STARTTLS_SENT) &&
-            !memcmp(data,STARTTLS_COMMAND_SUCCESS,sizeof(STARTTLS_COMMAND_SUCCESS)-1) )
-        {
-            fd->flags &= ~(CLIENT_FLAG_STARTTLS_SENT);
-            fd->flags |= CLIENT_FLAG_SMTPS;
-            asd->clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS); // we no longer need
-                                                                             // to examine the
-                                                                             // response.
-            if (!asd->get_session_flags(APPID_SESSION_DECRYPTED))
-            {
-                /* Because we can't see any further info without decryption we settle for
-                   plain APP_ID_SMTPS instead of perhaps finding data that would make calling
-                   IdentifyClientVersion() worthwhile, So set the appid and call it good. */
-                smtp_client_mod.api->add_app(asd, APP_ID_SMTPS, APP_ID_SMTPS, nullptr);
-                goto done;
-            }
-        }
-        return CLIENT_APP_INPROCESS;
-    }
-    if (asd->get_session_flags(APPID_SESSION_ENCRYPTED))
-    {
-        if (!asd->get_session_flags(APPID_SESSION_DECRYPTED))
-            return CLIENT_APP_INPROCESS;
-    }
-
-    for (end = data + size; data < end; data++)
-    {
-#if UNIT_TESTING
-        if (session_logging_enabled && currState != fd->state)
-        {
-            DEBUG_WRAP(DebugMessage(DEBUG_APPID, "AppIdDbg %s SMTP client state %s\n",
-                session_logging_id, stateName[fd->state]); );
-            currState = fd->state;
-        }
-#endif
-        switch (fd->state)
-        {
-        case SMTP_STATE_HELO:
-            if (*data == HELO[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(HELO))
-                {
-                    fd->pos = 0;
-                    fd->nextstate = SMTP_STATE_MAIL_FROM;
-                    fd->state = SMTP_STATE_SKIP_LINE;
-                }
-            }
-            else if (*data == EHLO[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(EHLO))
-                {
-                    fd->pos = 0;
-                    fd->nextstate = SMTP_STATE_MAIL_FROM;
-                    fd->state = SMTP_STATE_SKIP_LINE;
-                }
-            }
-            else
-                goto done;
-            break;
-
-        case SMTP_STATE_MAIL_FROM:
-            if (*data == MAILFROM[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(MAILFROM))
-                {
-                    fd->pos = 0;
-                    fd->nextstate = SMTP_STATE_RCPT_TO;
-                    fd->state = SMTP_STATE_SKIP_LINE;
-                }
-            }
-            else if (*data == RSET[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(RSET))
-                {
-                    fd->pos = 0;
-                    fd->nextstate = fd->state;
-                    fd->state = SMTP_STATE_SKIP_LINE;
-                }
-            }
-            else if (*data == AUTH[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(AUTH))
-                {
-                    fd->pos = 0;
-                    fd->nextstate = fd->state;
-                    fd->state = SMTP_STATE_SKIP_LINE;
-                }
-            }
-            else if (*data == STARTTLS[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(STARTTLS))
-                {
-                    fd->flags |= CLIENT_FLAG_STARTTLS_SENT;
-                    fd->pos = 0;
-                    fd->nextstate = fd->state;
-                    fd->state = SMTP_STATE_SKIP_LINE;
-                    asd->set_session_flags(APPID_SESSION_ENCRYPTED);
-                }
-            }
-            else
-                goto done;
-            break;
-
-        case SMTP_STATE_RCPT_TO:
-            if (*data == RCPTTO[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(RCPTTO))
-                {
-                    fd->pos = 0;
-                    fd->nextstate = SMTP_STATE_DATA;
-                    fd->state = SMTP_STATE_SKIP_LINE;
-                }
-            }
-            else
-                goto done;
-            break;
-
-        case SMTP_STATE_DATA:
-            if (*data == DATA[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(DATA))
-                {
-                    fd->pos = 0;
-                    fd->nextstate = SMTP_STATE_MESSAGE;
-                    fd->state = SMTP_STATE_SKIP_LINE;
-                }
-            }
-            else if (*data == RCPTTO[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(RCPTTO))
-                {
-                    fd->pos = 0;
-                    fd->nextstate = fd->state;
-                    fd->state = SMTP_STATE_SKIP_LINE;
-                }
-            }
-            break;
-
-        case SMTP_STATE_MESSAGE:
-            if (*data == '.')
-            {
-                unsigned len = end - data;
-                if (len == 0 ||
-                    (len >= 1 && data[1] == 0x0A) ||
-                    (len >= 2 && data[1] == 0x0D && data[2] == 0x0A))
-                {
-                    AppId appId = (fd->flags & CLIENT_FLAG_SMTPS) ?  APP_ID_SMTPS : APP_ID_SMTP;
-                    smtp_client_mod.api->add_app(asd, appId, appId, nullptr);
-                    goto done;
-                }
-            }
-            else if (*data == XMAILER[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(XMAILER))
-                {
-                    fd->pos = 0;
-                    fd->state = SMTP_STATE_GET_PRODUCT_VERSION;
-                }
-            }
-            else if (*data == USERAGENT[fd->pos])
-            {
-                fd->pos++;
-                if (fd->pos == strlen(USERAGENT))
-                {
-                    fd->pos = 0;
-                    fd->state = SMTP_STATE_GET_PRODUCT_VERSION;
-                }
-            }
-            else if (!isprint(*data) && *data != 0x09)
-                goto done;
-            else
-            {
-                fd->pos = 0;
-                fd->nextstate = fd->state;
-                fd->state = SMTP_STATE_SKIP_LINE;
-            }
-            break;
-
-        case SMTP_STATE_GET_PRODUCT_VERSION:
-            if (*data == 0x0D)
-            {
-                if (fd->headerline && fd->pos)
-                {
-                    IdentifyClientVersion(fd, fd->headerline, fd->headerline + fd->pos, asd, pkt);
-                    snort_free(fd->headerline);
-                    fd->headerline = nullptr;
-                }
-                goto done;
-            }
-            else if (!isprint(*data))
-            {
-                snort_free(fd->headerline);
-                fd->headerline = nullptr;
-                goto done;
-            }
-            else
-            {
-                if (!fd->headerline)
-                {
-                    if (!(fd->headerline = (uint8_t*)snort_calloc(MAX_HEADER_LINE_SIZE)))
-                        goto done;
-                }
-
-                if (fd->pos < (MAX_HEADER_LINE_SIZE-1))
-                    fd->headerline[fd->pos++] = *data;
-            }
-            break;
-
-        case SMTP_STATE_SKIP_LINE:
-            if (*data == 0x0A)
-            {
-                fd->pos = 0;
-                fd->state = fd->nextstate;
-                fd->nextstate = SMTP_STATE_NONE;
-            }
-            else if (!(*data == 0x0D || isprint(*data)))
-                goto done;
-            break;
-
-        default:
-            goto done;
-        }
-    }
-    return CLIENT_APP_INPROCESS;
-
-done:
-    asd->set_session_flags(APPID_SESSION_CLIENT_DETECTED);
-    return CLIENT_APP_SUCCESS;
-}
-
diff --git a/src/network_inspectors/appid/client_plugins/client_app_smtp.h b/src/network_inspectors/appid/client_plugins/client_app_smtp.h
deleted file mode 100644 (file)
index fabcb6c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2016 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2005-2013 Sourcefire, Inc.
-//
-// 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.
-//--------------------------------------------------------------------------
-
-// client_app_smtp.h author Sourcefire Inc.
-
-#ifndef CLIENT_APP_SMTP_H
-#define CLIENT_APP_SMTP_H
-
-#include "client_app_api.h"
-
-extern RNAClientAppModule smtp_client_mod;
-
-#endif
-
index 3bf64bac0b60aef7ffd6347f90c3716e3db24c4f..27ac8cc3787a2b89cd81bf9db7629170b0302967 100644 (file)
@@ -153,7 +153,7 @@ struct SSH_CLIENT_CONFIG
 
 THREAD_LOCAL SSH_CLIENT_CONFIG ssh_client_config;
 
-static CLIENT_APP_RETCODE ssh_client_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE ssh_client_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE ssh_client_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd,  Packet* pkt, struct Detector* userData);
 
@@ -199,7 +199,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_OPENSSH, APPINFO_FLAG_CLIENT_ADDITIONAL }
 };
 
-static CLIENT_APP_RETCODE ssh_client_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE ssh_client_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
 
index d6b3e2e24076909639e52e234ec1045ce84e6299..8e91368d5bc4ee567a663bfe9f3c806a77b1de0b 100644 (file)
@@ -68,7 +68,7 @@ struct TIMBUKTU_CLIENT_APP_CONFIG
 
 THREAD_LOCAL TIMBUKTU_CLIENT_APP_CONFIG timbuktu_config;
 
-static CLIENT_APP_RETCODE timbuktu_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE timbuktu_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE timbuktu_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
 
@@ -106,7 +106,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_TIMBUKTU, 0 }
 };
 
-static CLIENT_APP_RETCODE timbuktu_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE timbuktu_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
 
index 34c7e1ff77e068c87730146d2f0854fabaec0096..bef4e86671a1d166ee908359c58bc78b37e68a1c 100644 (file)
@@ -129,7 +129,7 @@ static const char* msg_type[] =
 #endif
 THREAD_LOCAL TNS_CLIENT_APP_CONFIG tns_config;
 
-static CLIENT_APP_RETCODE tns_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE tns_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE tns_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
 
@@ -167,7 +167,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_ORACLE_DATABASE, APPINFO_FLAG_CLIENT_ADDITIONAL | APPINFO_FLAG_CLIENT_USER }
 };
 
-static CLIENT_APP_RETCODE tns_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE tns_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
 
index 9fee88d90f794c333344356866d08c05a656ba98..fc6c9605c18abcdda65407532cac5bee0e358fe6 100644 (file)
@@ -55,7 +55,7 @@ struct VNC_CLIENT_APP_CONFIG
 
 THREAD_LOCAL VNC_CLIENT_APP_CONFIG vnc_config;
 
-static CLIENT_APP_RETCODE vnc_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE vnc_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE vnc_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
 
@@ -95,7 +95,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_VNC_RFB, APPINFO_FLAG_CLIENT_ADDITIONAL }
 };
 
-static CLIENT_APP_RETCODE vnc_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE vnc_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
 
index 3fd3a50b7bd28dcc65c1503a7baa62ff1f298fa1..bde086cb6ca51d16c099733a19890c1f8f1a4632 100644 (file)
@@ -39,7 +39,7 @@ THREAD_LOCAL YM_CLIENT_APP_CONFIG ym_config;
 
 #define MAX_VERSION_SIZE    64
 
-static CLIENT_APP_RETCODE ym_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE ym_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE ym_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
 
@@ -80,7 +80,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_YAHOO_MSG, APPINFO_FLAG_CLIENT_ADDITIONAL }
 };
 
-static CLIENT_APP_RETCODE ym_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE ym_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
 
diff --git a/src/network_inspectors/appid/client_plugins/test/Makefile.am b/src/network_inspectors/appid/client_plugins/test/Makefile.am
deleted file mode 100644 (file)
index 3af23bf..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-AM_DEFAULT_SOURCE_EXT = .cc
-
-check_PROGRAMS = \
-client_app_smtp_test
-
-TESTS = $(check_PROGRAMS)
-
-client_app_smtp_test_CPPFLAGS = -I$(top_srcdir)/src/network_inspectors/appid @AM_CPPFLAGS@ @CPPUTEST_CPPFLAGS@
-
-client_app_smtp_test_LDADD = \
-../../appid_stats_counter.o \
-../../../../utils/libutils.a \
-@CPPUTEST_LDFLAGS@
-
index a5f0cf5d80fd199139c45a33b6d3de53b635cc56..be47f60e8b94c50aa0b9312e86f03e2324f44657 100644 (file)
@@ -25,6 +25,7 @@
 #include "detector_api.h"
 #include "log/messages.h"
 #include "service_plugins/service_base.h"
+#include "detector_plugins/detector_smtp.h"
 
 static void* detector_flowdata_get(AppIdSession* asd, unsigned detector_id);
 static int detector_flowdata_add(AppIdSession* asd, void* data, unsigned detector_id,
@@ -44,6 +45,7 @@ static RNADetectorValidationModule* static_detector_list[]
 {
     &imap_detector_mod,
     &pop3_detector_mod,
+    &smtp_detector_mod,
     &kerberos_detector_mod
 };
 const uint32_t NUM_STATIC_DETECTORS =
index 5cb44ffa7b76450e397b8c827198045f4cb8a5b3..bebd51350ce9f01d8242393b3f85451d10783ff6 100644 (file)
@@ -143,7 +143,7 @@ struct MatchedDNSPatterns
     MatchedDNSPatterns* next;
 };
 
-static int dns_service_init(const IniServiceAPI* const);
+static int dns_service_init(const InitServiceAPI* const);
 static int dns_udp_validate(ServiceValidationArgs*);
 static int dns_tcp_validate(ServiceValidationArgs*);
 
@@ -198,8 +198,8 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_DNS, APPINFO_FLAG_SERVICE_UDP_REVERSED | APPINFO_FLAG_SERVICE_ADDITIONAL }
 };
 
-static CLIENT_APP_RETCODE dns_udp_client_init(const IniClientAppAPI* const, SF_LIST*);
-static CLIENT_APP_RETCODE dns_tcp_client_init(const IniClientAppAPI* const, SF_LIST*);
+static CLIENT_APP_RETCODE dns_udp_client_init(const InitClientAppAPI* const, SF_LIST*);
+static CLIENT_APP_RETCODE dns_tcp_client_init(const InitClientAppAPI* const, SF_LIST*);
 static CLIENT_APP_RETCODE dns_udp_client_validate(const uint8_t*, uint16_t, const int,
         AppIdSession*, Packet*, Detector*);
 static CLIENT_APP_RETCODE dns_tcp_client_validate(const uint8_t*, uint16_t, const int,
@@ -244,12 +244,12 @@ struct ServiceDnsConfig
 };
 static THREAD_LOCAL ServiceDnsConfig serviceDnsConfig;      // DNS service configuration
 
-static CLIENT_APP_RETCODE dns_udp_client_init(const IniClientAppAPI* const, SF_LIST*)
+static CLIENT_APP_RETCODE dns_udp_client_init(const InitClientAppAPI* const, SF_LIST*)
 {
     return CLIENT_APP_SUCCESS;
 }
 
-static CLIENT_APP_RETCODE dns_tcp_client_init(const IniClientAppAPI* const, SF_LIST*)
+static CLIENT_APP_RETCODE dns_tcp_client_init(const InitClientAppAPI* const, SF_LIST*)
 {
     return CLIENT_APP_SUCCESS;
 }
@@ -312,7 +312,7 @@ int dns_host_detector_process_patterns()
     return retVal;
 }
 
-static int dns_service_init(const IniServiceAPI* const init_api)
+static int dns_service_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index eaaf62610aa97d09194a482306a41c6e482d744f..be97f20bee065b0d30066dc8bcda0fcaaf235f67 100644 (file)
@@ -344,6 +344,7 @@ public:
     tMlmpTree* RTMPHosUrlMatcher = nullptr;
     SearchTool* header_matcher = nullptr;
     SearchTool* content_type_matcher = nullptr;
+    SearchTool* field_matcher = nullptr;
     SearchTool* chp_matchers[MAX_PATTERN_TYPE + 1] = { nullptr };
     HosUrlPatternsList* hosUrlPatternsList = nullptr;
 };
@@ -421,6 +422,48 @@ void insert_http_pattern_element(enum httpPatternType pType, HTTPListElement* el
     }
 }
 
+void remove_http_patterns_for_id( AppId id )
+{
+    // Walk the list of all the patterns we have inserted, searching for this appIdInstance and free them.
+    // The purpose is for the 14 and 15 to be used together to only set the APPINFO_FLAG_SEARCH_ENGINE flag
+    // If the reserved pattern is not used, it is a mixed use case and should just behave normally.
+    CHPListElement* chpa = nullptr;
+    CHPListElement* prev_chpa = nullptr;
+    CHPListElement* tmp_chpa = httpPatternLists->chpList;
+    while (tmp_chpa)
+    {
+        if (tmp_chpa->chp_action.appIdInstance == id)
+        {
+            // advance the tmp_chpa pointer by removing the item pointed to. Keep prev_chpa unchanged.
+
+            // 1) unlink the struct, 2) free strings and then 3) free the struct.
+            chpa = tmp_chpa; // preserve this pointer to be freed at the end.
+            if (prev_chpa == NULL)
+            {
+                // Remove from head
+                httpPatternLists->chpList = tmp_chpa->next;
+                tmp_chpa = httpPatternLists->chpList;
+            }
+            else
+            {
+                // Remove from middle of list.
+                prev_chpa->next = tmp_chpa->next;
+                tmp_chpa = prev_chpa->next;
+            }
+            snort_free(chpa->chp_action.pattern);
+            if (chpa->chp_action.action_data)
+                snort_free(chpa->chp_action.action_data);
+            snort_free(chpa);
+        }
+        else
+        {
+            // advance both pointers
+            prev_chpa = tmp_chpa;
+            tmp_chpa = tmp_chpa->next;
+        }
+    }
+}
+
 void insert_content_type_pattern(HTTPListElement* element)
 {
     element->next = httpPatternLists->contentTypePatternList;
@@ -603,7 +646,7 @@ static int http_pattern_match(void* id, void*, int index, void* data, void*)
     MatchedPatterns** matches = (MatchedPatterns**)data;
     DetectorHTTPPattern* target = (DetectorHTTPPattern*)id;
 
-    /* make sure we haven't already seen this pattern */
+    // make sure we haven't already seen this pattern
     for (tmp = matches; *tmp; tmp = &(*tmp)->next)
         cm = *tmp;
 
@@ -709,19 +752,16 @@ static SearchTool* processContentTypePatterns(DetectorHTTPPattern* patternList,
 
     for (uint32_t i = 0; i < patternListCount; i++)
     {
-        patternMatcher->add(patternList[i].pattern,
-            patternList[i].pattern_size,
-            &patternList[i],
-            false);
+        patternMatcher->add(patternList[i].pattern, patternList[i].pattern_size,
+            &patternList[i], false);
     }
 
-    /* Add patterns from Lua API */
+    // Add patterns from Lua API
     for (element = luaPatternList; element; element = element->next)
     {
         patternMatcher->add(element->detectorHTTPPattern.pattern,
             element->detectorHTTPPattern.pattern_size,
-            &element->detectorHTTPPattern,
-            false);
+            &element->detectorHTTPPattern, false);
     }
 
     patternMatcher->prep();
@@ -767,6 +807,102 @@ static SearchTool* registerHeaderPatterns(HeaderPattern* patternList, size_t pat
     return patternMatcher;
 }
 
+#define HTTP_FIELD_PREFIX_USER_AGENT    "\r\nUser-Agent: "
+#define HTTP_FIELD_PREFIX_USER_AGENT_SIZE (sizeof(HTTP_FIELD_PREFIX_USER_AGENT)-1)
+#define HTTP_FIELD_PREFIX_HOST    "\r\nHost: "
+#define HTTP_FIELD_PREFIX_HOST_SIZE (sizeof(HTTP_FIELD_PREFIX_HOST)-1)
+#define HTTP_FIELD_PREFIX_REFERER    "\r\nReferer: "
+#define HTTP_FIELD_PREFIX_REFERER_SIZE (sizeof(HTTP_FIELD_PREFIX_REFERER)-1)
+#define HTTP_FIELD_PREFIX_URI    " "
+#define HTTP_FIELD_PREFIX_URI_SIZE (sizeof(HTTP_FIELD_PREFIX_URI)-1)
+#define HTTP_FIELD_PREFIX_COOKIE    "\r\nCookie: "
+#define HTTP_FIELD_PREFIX_COOKIE_SIZE (sizeof(HTTP_FIELD_PREFIX_COOKIE)-1)
+
+typedef struct _FIELD_PATTERN
+{
+    PatternType patternType;
+    uint8_t* data;
+    unsigned length;
+} FieldPattern;
+
+static FieldPattern http_field_patterns[] =
+{
+    {URI_PT, (uint8_t*) HTTP_FIELD_PREFIX_URI, HTTP_FIELD_PREFIX_URI_SIZE},
+    {HOST_PT, (uint8_t*) HTTP_FIELD_PREFIX_HOST,HTTP_FIELD_PREFIX_HOST_SIZE},
+    {REFERER_PT, (uint8_t*) HTTP_FIELD_PREFIX_REFERER, HTTP_FIELD_PREFIX_REFERER_SIZE},
+    {COOKIE_PT, (uint8_t*) HTTP_FIELD_PREFIX_COOKIE, HTTP_FIELD_PREFIX_COOKIE_SIZE},
+    {AGENT_PT, (uint8_t*) HTTP_FIELD_PREFIX_USER_AGENT,HTTP_FIELD_PREFIX_USER_AGENT_SIZE},
+};
+
+static SearchTool* processHttpFieldPatterns(FieldPattern* patternList, size_t patternListCount)
+{
+    u_int32_t i;
+
+    SearchTool* patternMatcher = new SearchTool("ac_full");
+
+    for (i=0; i < patternListCount; i++)
+        patternMatcher->add( (char  *)patternList[i].data, patternList[i].length,
+                             &patternList[i], false);
+
+    patternMatcher->prep();
+    return patternMatcher;
+}
+
+typedef struct fieldPatternData_t
+{
+    const uint8_t*payload;
+    unsigned length;
+    httpSession *hsession;
+} FieldPatternData;
+
+static int http_field_pattern_match(void *id, void *, int index, void *data, void *)
+{
+    static const uint8_t crlf[] = "\r\n";
+    static unsigned crlfLen = sizeof(crlf)-1;
+    FieldPatternData *pFieldData = (FieldPatternData*)data;
+    FieldPattern *target = (FieldPattern  *)id;
+    const uint8_t* p;
+    unsigned fieldOffset = target->length + index;
+    unsigned remainingLength = pFieldData->length - fieldOffset;
+
+    if (!(p = (uint8_t*)service_strstr(&pFieldData->payload[fieldOffset], remainingLength, crlf, crlfLen)))
+    {
+        return 1;
+    }
+    pFieldData->hsession->fieldOffset[target->patternType] = (uint16_t)fieldOffset;
+    pFieldData->hsession->fieldEndOffset[target->patternType] = p - pFieldData->payload;
+    return 1;
+}
+
+void httpGetNewOffsetsFromPacket(Packet *pkt, httpSession *hsession)
+{
+    constexpr auto MIN_HTTP_REQ_HEADER_SIZE = (sizeof("GET /\r\n\r\n") - 1);
+    static const uint8_t crlfcrlf[] = "\r\n\r\n";
+    static unsigned crlfcrlfLen = sizeof(crlfcrlf) - 1;
+    uint8_t*headerEnd;
+    unsigned fieldId;
+    FieldPatternData patternMatchData;
+
+    for (fieldId = AGENT_PT; fieldId <= COOKIE_PT; fieldId++)
+        hsession->fieldOffset[fieldId] = 0;
+
+
+    if (!pkt->data || pkt->dsize < MIN_HTTP_REQ_HEADER_SIZE)
+        return;
+
+    patternMatchData.hsession = hsession;
+    patternMatchData.payload = pkt->data;
+
+    if (!(headerEnd = (uint8_t*)service_strstr(pkt->data, pkt->dsize, crlfcrlf, crlfcrlfLen)))
+        return;
+
+    headerEnd += crlfcrlfLen;
+    patternMatchData.length = (unsigned)(headerEnd - pkt->data);
+    detectorHttpConfig->field_matcher->find_all((char*)pkt->data, patternMatchData.length,
+                   &http_field_pattern_match, false, (void*)(&patternMatchData));
+
+}
+
 int finalize_http_detector()
 {
     size_t upc = 0;
@@ -812,6 +948,11 @@ int finalize_http_detector()
     if (!detectorHttpConfig->content_type_matcher)
         return -1;
 
+    numPatterns = sizeof(http_field_patterns)/sizeof(*http_field_patterns);
+    detectorHttpConfig->field_matcher = processHttpFieldPatterns(http_field_patterns, numPatterns);
+    if (!detectorHttpConfig->field_matcher)
+        return -1;
+
     if (!processCHPList(httpPatternLists->chpList))
         return -1;
 
@@ -825,6 +966,7 @@ void clean_http_detector()
     delete detectorHttpConfig->client_agent_matcher;
     delete detectorHttpConfig->header_matcher;
     delete detectorHttpConfig->content_type_matcher;
+    delete detectorHttpConfig->field_matcher;
 
     for (size_t i = 0; i <= MAX_PATTERN_TYPE; i++)
          delete detectorHttpConfig->chp_matchers[i];
@@ -902,7 +1044,7 @@ static char* normalize_userid(char* user)
     int i, old_size;
     int percent_count = 0;
     char a, b;
-    char* tmp_ret, * tmp_user;
+    char* tmp_ret, *tmp_user;
 
     old_size = strlen(user);
 
@@ -2388,10 +2530,10 @@ bool is_webdav_found(HeaderMatchedPatterns* hmp)
 // knowledge" case for HTTP/2 (i.e., the client knows the server supports
 // HTTP/2 and jumps right in with the preface).
 
-static CLIENT_APP_RETCODE http_client_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE http_client_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE http_client_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
-static int http_service_init(const IniServiceAPI* const init_api);
+static int http_service_init(const InitServiceAPI* const init_api);
 static int http_service_validate(ServiceValidationArgs* args);
 
 static AppRegistryEntry appIdRegistry[] =
@@ -2474,7 +2616,7 @@ RNAServiceValidationModule http_service_mod =
     0
 };
 
-static CLIENT_APP_RETCODE http_client_init(const IniClientAppAPI* const init_api, SF_LIST*)
+static CLIENT_APP_RETCODE http_client_init(const InitClientAppAPI* const init_api, SF_LIST*)
 {
     if (AppIdConfig::get_appid_config()->mod_config->http2_detection_enabled)
     {
@@ -2512,7 +2654,7 @@ static CLIENT_APP_RETCODE http_client_validate(const uint8_t*, uint16_t, const i
     return CLIENT_APP_SUCCESS;
 }
 
-static int http_service_init(const IniServiceAPI* const init_api)
+static int http_service_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index b5edaac0bddbdf5a133955b1517d3390d269bf13..ad026b35e345c4a891a7d582781d4d7783759801 100644 (file)
@@ -159,12 +159,15 @@ int finalize_http_detector();
 void clean_http_detector();
 void insert_chp_pattern(CHPListElement* chpa);
 void insert_http_pattern_element(enum httpPatternType pType, HTTPListElement* element);
+void remove_http_patterns_for_id( AppId id );
 void insert_content_type_pattern(HTTPListElement* element);
 void insert_url_pattern(DetectorAppUrlPattern* pattern);
 void insert_rtmp_url_pattern(DetectorAppUrlPattern* pattern);
 void insert_app_url_pattern(DetectorAppUrlPattern* pattern);
 int get_appid_by_pattern(const uint8_t*, unsigned, char**);
 int get_http_header_location(const uint8_t*, unsigned, HttpId, int*, int*, HeaderMatchedPatterns*);
+void httpGetNewOffsetsFromPacket(Packet *pkt, httpSession *hsession);
+
 inline void free_matched_chp_actions(MatchedCHPAction* ma)
 {
        MatchedCHPAction* tmp;
index 4d861d5e21ac74f3a542d44f4a5e6edcf7e3fb70..749a1f573e9376c44d44759400168999f63e4999 100644 (file)
@@ -74,7 +74,7 @@ struct ClientAppData
 
 static CLIENT_APP_CONFIG ca_config;
 
-static CLIENT_APP_RETCODE init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static void clean();
 static CLIENT_APP_RETCODE validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, Detector* userData);
@@ -230,7 +230,7 @@ struct ServiceIMAPData
 #endif
 };
 
-static int imap_init(const IniServiceAPI* const init_api);
+static int imap_init(const InitServiceAPI* const init_api);
 static int imap_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -287,7 +287,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_IMAPS, APPINFO_FLAG_CLIENT_USER }
 };
 
-static CLIENT_APP_RETCODE init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
     RNAClientAppModuleConfigItem* item;
@@ -336,7 +336,7 @@ static CLIENT_APP_RETCODE init(const IniClientAppAPI* const init_api, SF_LIST* c
     return CLIENT_APP_SUCCESS;
 }
 
-static int imap_init(const IniServiceAPI* const init_api)
+static int imap_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPatternUser(&imap_validate, IpProtocol::TCP, (uint8_t*)IMAP_PATTERN,
         sizeof(IMAP_PATTERN)-1, 0, "imap");
index f239560c67d1084fc8c4192ee99c4a074598d459..8248783f85640765bfa0b25502acfac3cd754e4b 100644 (file)
@@ -110,7 +110,7 @@ struct DetectorData
 
 static KRB_CLIENT_APP_CONFIG krb_client_config;
 
-static CLIENT_APP_RETCODE krb_client_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE krb_client_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE krb_client_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
 
@@ -149,7 +149,7 @@ static Detector_Pattern client_patterns[] =
     { TGS_REQ_4, sizeof(TGS_REQ_4)-1 },
 };
 
-static int krb_server_init(const IniServiceAPI* const init_api);
+static int krb_server_init(const InitServiceAPI* const init_api);
 static int krb_server_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -209,7 +209,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_KERBEROS, APPINFO_FLAG_CLIENT_USER | APPINFO_FLAG_SERVICE_ADDITIONAL }
 };
 
-static CLIENT_APP_RETCODE krb_client_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE krb_client_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
     RNAClientAppModuleConfigItem* item;
@@ -258,7 +258,7 @@ static CLIENT_APP_RETCODE krb_client_init(const IniClientAppAPI* const init_api,
     return CLIENT_APP_SUCCESS;
 }
 
-static int krb_server_init(const IniServiceAPI* const init_api)
+static int krb_server_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
 
index 9990ce8cc07c7b05008104f39fc251efddf82ed6..a3f15ba128e133d9eb9b557e83acb0255ae30792 100644 (file)
@@ -34,15 +34,15 @@ static THREAD_LOCAL ClientPortPattern clientPortPattern;
 static int service_validate(ServiceValidationArgs* args);
 static int csdPatternTreeSearch(const uint8_t* data, uint16_t size, IpProtocol protocol, Packet* pkt,
     const RNAServiceElement** serviceData, bool isClient);
-static int pattern_service_init(const IniServiceAPI* const iniServiceApi);
+static int pattern_service_init(const InitServiceAPI* const iniServiceApi);
 static void pattern_service_clean();
-static CLIENT_APP_RETCODE client_init(const IniClientAppAPI* const init_api, SF_LIST* config);
-static CLIENT_APP_RETCODE client_init_tcp(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE client_init(const InitClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE client_init_tcp(const InitClientAppAPI* const init_api, SF_LIST* config);
 static CLIENT_APP_RETCODE client_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
 static void client_clean();
-static const IniServiceAPI* iniServiceApi;
-static const IniClientAppAPI* iniClientApi;
+static const InitServiceAPI* iniServiceApi;
+static const InitClientAppAPI* iniClientApi;
 
 static const RNAServiceElement svc_element =
 {
@@ -183,7 +183,7 @@ static void read_patterns(PortPatternNode* portPatternList, PatternService** ser
 }
 
 // Register ports for detectors which have a pattern associated with it.
-static void install_ports(PatternService* serviceList, const IniServiceAPI* const iniServiceApi)
+static void install_ports(PatternService* serviceList, const InitServiceAPI* const iniServiceApi)
 {
     PatternService* ps;
     PortNode* port;
@@ -507,7 +507,7 @@ void finalize_service_port_patterns()
     dumpPatterns("Server", service_port_patterns.servicePortPattern);
 }
 
-static int pattern_service_init(const IniServiceAPI* const init_api)
+static int pattern_service_init(const InitServiceAPI* const init_api)
 {
     iniServiceApi = init_api;
 
@@ -747,14 +747,14 @@ fail:
     return SERVICE_NOMATCH;
 }
 
-static CLIENT_APP_RETCODE client_init(const IniClientAppAPI* const init_api, SF_LIST*)
+static CLIENT_APP_RETCODE client_init(const InitClientAppAPI* const init_api, SF_LIST*)
 {
     iniClientApi = init_api;
 
     return CLIENT_APP_SUCCESS;
 }
 
-static CLIENT_APP_RETCODE client_init_tcp(const IniClientAppAPI* const, SF_LIST*)
+static CLIENT_APP_RETCODE client_init_tcp(const InitClientAppAPI* const, SF_LIST*)
 {
     return CLIENT_APP_SUCCESS;
 }
index 71e71c04a9817c541a234669e84b885cdfa5489d..d6ed6440925455dc2483dad3d9adb6666f1dd5ee 100644 (file)
@@ -58,7 +58,7 @@ struct ClientPOP3Data
 
 static POP3_CLIENT_APP_CONFIG pop3_config;
 
-static CLIENT_APP_RETCODE pop3_ca_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE pop3_ca_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static void pop3_ca_clean();
 static CLIENT_APP_RETCODE pop3_ca_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, struct Detector* userData);
@@ -192,7 +192,7 @@ struct ServicePOP3Data
     int error;
 };
 
-static int pop3_init(const IniServiceAPI* const init_api);
+static int pop3_init(const InitServiceAPI* const init_api);
 static int pop3_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -246,7 +246,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_POP3S, APPINFO_FLAG_SERVICE_ADDITIONAL | APPINFO_FLAG_CLIENT_USER }
 };
 
-static CLIENT_APP_RETCODE pop3_ca_init(const IniClientAppAPI* const init_api, SF_LIST* config)
+static CLIENT_APP_RETCODE pop3_ca_init(const InitClientAppAPI* const init_api, SF_LIST* config)
 {
     unsigned i;
     RNAClientAppModuleConfigItem* item;
@@ -302,7 +302,7 @@ static CLIENT_APP_RETCODE pop3_ca_init(const IniClientAppAPI* const init_api, SF
     return CLIENT_APP_SUCCESS;
 }
 
-static int pop3_init(const IniServiceAPI* const init_api)
+static int pop3_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPatternUser(&pop3_validate, IpProtocol::TCP, (uint8_t*)POP3_OK,
         sizeof(POP3_OK)-1, 0, "pop3");
index 835f7dc2c0faf98dd53c70899259315d0e108ffd..bfc494267dfe61503bfd6645716aa9e62599efdb 100644 (file)
@@ -97,11 +97,11 @@ struct DetectorSipConfig
 
 static THREAD_LOCAL DetectorSipConfig detector_sip_config;
 
-static CLIENT_APP_RETCODE sip_client_init(const IniClientAppAPI* const init_api, SF_LIST* config);
+static CLIENT_APP_RETCODE sip_client_init(const InitClientAppAPI* const init_api, SF_LIST* config);
 static void sip_clean();
 static CLIENT_APP_RETCODE sip_client_validate(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, Packet* pkt, Detector* userData);
-static CLIENT_APP_RETCODE sip_tcp_client_init(const IniClientAppAPI* const init_api,
+static CLIENT_APP_RETCODE sip_tcp_client_init(const InitClientAppAPI* const init_api,
     SF_LIST* config);
 static CLIENT_APP_RETCODE sip_tcp_client_validate(const uint8_t* data, uint16_t size,
     const int dir, AppIdSession* asd, Packet* pkt, Detector* userData);
@@ -179,7 +179,7 @@ struct ServiceSIPData
     char vendor[MAX_VENDOR_SIZE];
 };
 
-static int sip_service_init(const IniServiceAPI* const init_api);
+static int sip_service_init(const InitServiceAPI* const init_api);
 static int sip_service_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -213,7 +213,7 @@ SO_PUBLIC RNAServiceValidationModule sip_service_mod =
     0
 };
 
-static CLIENT_APP_RETCODE sip_client_init(const IniClientAppAPI* const init_api, SF_LIST*)
+static CLIENT_APP_RETCODE sip_client_init(const InitClientAppAPI* const init_api, SF_LIST*)
 {
     unsigned i;
 
@@ -256,7 +256,7 @@ static void sip_clean()
         clean_sip_server();
 }
 
-static CLIENT_APP_RETCODE sip_tcp_client_init(const IniClientAppAPI* const init_api,
+static CLIENT_APP_RETCODE sip_tcp_client_init(const InitClientAppAPI* const init_api,
         SF_LIST* config)
 {
     unsigned i;
@@ -687,7 +687,7 @@ void SipSessionSnortCallback(void*, ServiceEventType, void* data)
     SipSessionCbServiceProcess(p, headers, dialog, asd);
 }
 
-static int sip_service_init(const IniServiceAPI* const init_api)
+static int sip_service_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&sip_service_validate, IpProtocol::UDP,
             (const uint8_t*)SIP_BANNER, SIP_BANNER_LEN, 0, svc_name);
diff --git a/src/network_inspectors/appid/detector_plugins/detector_smtp.cc b/src/network_inspectors/appid/detector_plugins/detector_smtp.cc
new file mode 100644 (file)
index 0000000..9de1c35
--- /dev/null
@@ -0,0 +1,1035 @@
+/*
+** Copyright (C) 2014-2016 Cisco and/or its affiliates. All rights reserved.
+** Copyright (C) 2005-2013 Sourcefire, Inc.
+**
+** 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.
+*/
+
+
+#include "detector_smtp.h"
+
+#include "main/snort_debug.h"
+#include "utils/util.h"
+#include "utils/sflsq.h"
+
+#include "application_ids.h"
+#include "detector_api.h"
+#include "client_plugins/client_app_api.h"
+#include "service_plugins/service_util.h"
+#include "app_info_table.h"
+#include "appid_api.h"
+#include "appid_module.h"
+
+enum SMTPClientState
+{
+    SMTP_CLIENT_STATE_NONE,
+    SMTP_CLIENT_STATE_HELO,
+    SMTP_CLIENT_STATE_MAIL_FROM,
+    SMTP_CLIENT_STATE_RCPT_TO,
+    SMTP_CLIENT_STATE_DATA,
+    SMTP_CLIENT_STATE_MESSAGE,
+    SMTP_CLIENT_STATE_GET_PRODUCT_VERSION,
+    SMTP_CLIENT_STATE_SKIP_LINE,
+    SMTP_CLIENT_STATE_CONNECTION_ERROR,
+    SMTP_CLIENT_STATE_STARTTLS
+};
+
+#define MAX_HEADER_LINE_SIZE 1024
+
+#ifdef UNIT_TESTING
+char* stateName [] =
+{
+    "SMTP_CLIENT_STATE_NONE",
+    "SMTP_CLIENT_STATE_HELO",
+    "SMTP_CLIENT_STATE_MAIL_FROM",
+    "SMTP_CLIENT_STATE_RCPT_TO",
+    "SMTP_CLIENT_STATE_DATA",
+    "SMTP_CLIENT_STATE_MESSAGE",
+    "SMTP_CLIENT_STATE_GET_PRODUCT_VERSION",
+    "SMTP_CLIENT_STATE_SKIP_LINE",
+    "SMTP_CLIENT_STATE_CONNECTION_ERROR",
+    "SMTP_CLIENT_STATE_STARTTLS"
+};
+#endif
+
+/* flag values for ClientSMTPData */
+#define CLIENT_FLAG_STARTTLS_SUCCESS    0x01
+#define CLIENT_FLAG_SMTPS               0x02
+
+#define MAX_VERSION_SIZE    64
+#define SSL_WAIT_PACKETS    8  // This many un-decrypted packets without a HELO and we quit.
+
+struct ClientSMTPData
+{
+    int flags;
+    SMTPClientState state;
+    SMTPClientState nextstate;
+    uint8_t version[MAX_VERSION_SIZE];
+    unsigned pos;
+    uint8_t* headerline;
+    int decryption_countdown;
+};
+
+struct SMTP_CLIENT_APP_CONFIG
+{
+    int enabled;
+};
+
+
+THREAD_LOCAL SMTP_CLIENT_APP_CONFIG smtp_config;
+
+static CLIENT_APP_RETCODE smtp_ca_init(const InitClientAppAPI* const init_api, SF_LIST *config);
+static CLIENT_APP_RETCODE smtp_ca_validate(const uint8_t* data, uint16_t size, const int dir,
+    AppIdSession* asd, Packet* pkt, struct Detector* userData);
+
+static RNAClientAppModule  smtp_client_mod =
+{
+    "SMTP",                 // name
+    IpProtocol::TCP,            // proto
+    &smtp_ca_init,             // init
+    nullptr,                // clean
+    &smtp_ca_validate,         // validate
+    1,                      // minimum_matches
+    nullptr,                // api
+    nullptr,                // userData
+    0,                      // precedence
+    nullptr,                // finalize,
+    1,                      // provides_user
+    0                       // flow_data_index
+};
+
+struct Client_App_Pattern
+{
+    const uint8_t* pattern;
+    unsigned length;
+    int index;
+    unsigned appId;
+};
+
+#define HELO "HELO "
+#define EHLO "EHLO "
+#define MAILFROM "MAIL FROM:"
+#define RCPTTO "RCPT TO:"
+#define DATA "DATA"
+#define RSET "RSET"
+#define AUTH "AUTH PLAIN"
+#define STARTTLS "STARTTLS"
+
+#define STARTTLS_COMMAND_SUCCESS "220 "
+
+#define MICROSOFT "Microsoft "
+#define OUTLOOK "Outlook"
+#define EXPRESS "Express "
+#define IMO "IMO, "
+
+#define XMAILER "X-Mailer: "
+#define USERAGENT "User-Agent: "
+
+static const uint8_t APP_SMTP_OUTLOOK[] = "Microsoft Outlook";
+static const uint8_t APP_SMTP_OUTLOOK_EXPRESS[] = "Microsoft Outlook Express ";
+static const uint8_t APP_SMTP_IMO[] = "IMO, ";
+static const uint8_t APP_SMTP_EVOLUTION[] = "Ximian Evolution ";
+static const uint8_t APP_SMTP_LOTUS_NOTES[] =  "Lotus Notes ";
+static const uint8_t APP_SMTP_APPLEMAIL[] =  "Apple Mail (";
+static const uint8_t APP_SMTP_EUDORA[] =  "QUALCOMM Windows Eudora Version ";
+static const uint8_t APP_SMTP_EUDORAPRO[] =  "Windows Eudora Pro Version ";
+static const uint8_t APP_SMTP_AOL[] =  "AOL ";
+static const uint8_t APP_SMTP_MUTT[] =  "Mutt/";
+static const uint8_t APP_SMTP_KMAIL[] =  "KMail/";
+static const uint8_t APP_SMTP_MTHUNDERBIRD[] =  "Mozilla Thunderbird ";
+static const uint8_t APP_SMTP_THUNDERBIRD[] =  "Thunderbird ";
+static const uint8_t APP_SMTP_MOZILLA[] = "Mozilla";
+static const uint8_t APP_SMTP_THUNDERBIRD_SHORT[] = "Thunderbird/";
+
+static Client_App_Pattern patterns[] =
+{
+    {(uint8_t*)HELO, sizeof(HELO)-1, -1, APP_ID_SMTP},
+    {(uint8_t*)EHLO, sizeof(EHLO)-1, -1, APP_ID_SMTP},
+       {APP_SMTP_OUTLOOK,         sizeof(APP_SMTP_OUTLOOK)-1,        -1, APP_ID_OUTLOOK},
+       {APP_SMTP_OUTLOOK_EXPRESS, sizeof(APP_SMTP_OUTLOOK_EXPRESS)-1,-1, APP_ID_OUTLOOK_EXPRESS},
+       {APP_SMTP_IMO,             sizeof(APP_SMTP_IMO)-1,            -1, APP_ID_SMTP_IMO},
+       {APP_SMTP_EVOLUTION,       sizeof(APP_SMTP_EVOLUTION)-1,      -1, APP_ID_EVOLUTION},
+       {APP_SMTP_LOTUS_NOTES,      sizeof(APP_SMTP_LOTUS_NOTES)-1,     -1, APP_ID_LOTUS_NOTES},
+       {APP_SMTP_APPLEMAIL,       sizeof(APP_SMTP_APPLEMAIL)-1,      -1, APP_ID_APPLE_EMAIL},
+       {APP_SMTP_EUDORA,          sizeof(APP_SMTP_EUDORA)-1,         -1, APP_ID_EUDORA},
+       {APP_SMTP_EUDORAPRO,       sizeof(APP_SMTP_EUDORAPRO)-1,      -1, APP_ID_EUDORA_PRO},
+       {APP_SMTP_AOL,             sizeof(APP_SMTP_AOL)-1,            -1, APP_ID_AOL_EMAIL},
+       {APP_SMTP_MUTT,            sizeof(APP_SMTP_MUTT)-1,           -1, APP_ID_MUTT},
+       {APP_SMTP_KMAIL,           sizeof(APP_SMTP_KMAIL)-1,          -1, APP_ID_KMAIL},
+       {APP_SMTP_MTHUNDERBIRD,    sizeof(APP_SMTP_MTHUNDERBIRD)-1,   -1, APP_ID_THUNDERBIRD},
+       {APP_SMTP_THUNDERBIRD,     sizeof(APP_SMTP_THUNDERBIRD)-1,    -1, APP_ID_THUNDERBIRD},
+};
+
+static AppRegistryEntry clientAppIdRegistry[] =
+{
+    {APP_ID_THUNDERBIRD, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_OUTLOOK, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_KMAIL, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_EUDORA_PRO, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_EVOLUTION, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_SMTP_IMO, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_EUDORA, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_LOTUS_NOTES, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_APPLE_EMAIL, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_AOL_EMAIL, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_MUTT, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_SMTP, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_OUTLOOK_EXPRESS, APPINFO_FLAG_CLIENT_ADDITIONAL},
+    {APP_ID_SMTPS, APPINFO_FLAG_CLIENT_ADDITIONAL}
+};
+
+static CLIENT_APP_RETCODE smtp_ca_init(const InitClientAppAPI* const init_api, SF_LIST* config)
+{
+    unsigned i;
+
+    smtp_config.enabled = 1;
+
+    if (config)
+    {
+        SF_LNODE* cursor;
+        RNAClientAppModuleConfigItem* item;
+
+        for (item = (RNAClientAppModuleConfigItem*)sflist_first(config, &cursor);
+            item;
+            item = (RNAClientAppModuleConfigItem*)sflist_next(&cursor))
+        {
+            DebugFormat(DEBUG_LOG,"Processing %s: %s\n",item->name, item->value);
+            if (strcasecmp(item->name, "enabled") == 0)
+            {
+                smtp_config.enabled = atoi(item->value);
+            }
+        }
+    }
+
+    if (smtp_config.enabled)
+    {
+        for (i=0; i < sizeof(patterns)/sizeof(*patterns); i++)
+        {
+            init_api->RegisterPattern(&smtp_ca_validate, IpProtocol::TCP, patterns[i].pattern,
+                                      patterns[i].length, patterns[i].index);
+        }
+    }
+
+       unsigned j;
+       for (j=0; j < sizeof(clientAppIdRegistry)/sizeof(*clientAppIdRegistry); j++)
+       {
+           DebugFormat(DEBUG_LOG,"registering appId: %d\n",clientAppIdRegistry[j].appId);
+               init_api->RegisterAppId(&smtp_ca_validate, clientAppIdRegistry[j].appId,
+                                       clientAppIdRegistry[j].additionalInfo);
+       }
+
+    return CLIENT_APP_SUCCESS;
+}
+
+#define SMTP_PORT   25
+#define SMTPS_DEPRECATED_PORT   465
+#define SMTP_CLOSING_CONN "closing connection\x0d\x0a"
+
+enum SMTPServiceState
+{
+    SMTP_SERVICE_STATE_CONNECTION,
+    SMTP_SERVICE_STATE_HELO,
+    SMTP_SERVICE_STATE_TRANSFER,
+    SMTP_SERVICE_STATE_CONNECTION_ERROR,
+    SMTP_SERVICE_STATE_STARTTLS,
+    SMTP_SERVICE_STATE_SSL_HANDSHAKE
+};
+
+struct ServiceSMTPData
+{
+    SMTPServiceState state;
+    int code;
+    int multiline;
+    int set_flags;
+    bool detected;
+};
+
+#pragma pack(1)
+
+struct ServiceSMTPCode
+{
+    uint8_t code[3];
+    uint8_t sp;
+};
+
+#pragma pack()
+
+static int smtp_svc_init(const InitServiceAPI* const init_api);
+static int smtp_svc_validate(ServiceValidationArgs* args);
+
+static const RNAServiceElement svc_element =
+{
+    nullptr,
+    &smtp_svc_validate,
+    nullptr,
+    DETECTOR_TYPE_DECODER,
+    1,
+    1,
+    0,
+    "smtp"
+};
+
+static RNAServiceValidationPort pp[] =
+{
+    {&smtp_svc_validate, SMTP_PORT, IpProtocol::TCP, 0},
+    {&smtp_svc_validate, SMTPS_DEPRECATED_PORT, IpProtocol::TCP, 0},
+    { nullptr, 0, IpProtocol::PROTO_NOT_SET, 0 }
+};
+
+static RNAServiceValidationModule smtp_service_mod =
+{
+    "SMTP",
+    &smtp_svc_init,
+    pp,
+    nullptr,
+    nullptr,
+    0,
+    nullptr,
+    0
+};
+
+static AppRegistryEntry appIdRegistry[] =
+{
+    {APP_ID_SMTP,  0},
+    {APP_ID_SMTPS, 0}
+};
+
+struct SMTPDetectorData
+{
+    ClientSMTPData client;
+    ServiceSMTPData server;
+    int need_continue;
+    int watch_for_deprecated_port;
+};
+
+SO_PUBLIC RNADetectorValidationModule smtp_detector_mod =
+{
+    &smtp_service_mod,
+    &smtp_client_mod,
+    nullptr,
+    0
+};
+
+static int smtp_svc_init(const InitServiceAPI* const init_api)
+{
+    const char SMTP_PATTERN1[] = "220 ";
+    const char SMTP_PATTERN2[] = "220-";
+    const char SMTP_PATTERN3[] = "SMTP";
+    const char SMTP_PATTERN4[] = "smtp";
+
+    init_api->RegisterPattern(&smtp_svc_validate, IpProtocol::TCP, (uint8_t*)SMTP_PATTERN1,
+        sizeof(SMTP_PATTERN1) - 1, 0, "smtp");
+    init_api->RegisterPattern(&smtp_svc_validate, IpProtocol::TCP, (uint8_t*)SMTP_PATTERN2,
+        sizeof(SMTP_PATTERN2) - 1, 0, "smtp");
+    init_api->RegisterPattern(&smtp_svc_validate, IpProtocol::TCP, (uint8_t*)SMTP_PATTERN3,
+        sizeof(SMTP_PATTERN3) - 1, -1, "smtp");
+    init_api->RegisterPattern(&smtp_svc_validate, IpProtocol::TCP, (uint8_t*)SMTP_PATTERN4,
+        sizeof(SMTP_PATTERN4) - 1, -1, "smtp");
+
+       unsigned i;
+       for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
+       {
+        DebugFormat(DEBUG_LOG,"registering appId: %d\n",appIdRegistry[i].appId);
+               init_api->RegisterAppId(&smtp_svc_validate, appIdRegistry[i].appId,
+                                       appIdRegistry[i].additionalInfo);
+       }
+
+    return 0;
+}
+
+/*
+ *    product - The product data should not include any characters
+ *              after the end of the product version (e.g. no CR, LF, etc).
+ *    prefix_len - The number of characters that are the prefix to the version,
+ *              including the NUL terminating character.
+ */
+static int extract_version_and_add_client_app(ApplicationId clientId, const int prefix_len,
+        const uint8_t* product, const uint8_t* product_end, ClientSMTPData* const client_data,
+        AppIdSession* asd, AppId appId, PegCount* stat_counter)
+{
+    const uint8_t* p;
+    uint8_t* v;
+    uint8_t* v_end;
+
+    v_end = client_data->version;
+    v_end += MAX_VERSION_SIZE - 1;
+
+    //  The prefix_len includes the NUL character, but product does not, so
+    //  subtract 1 from length to skip.
+    p = product + prefix_len - 1;
+    if (p >= product_end || isspace(*p))
+        return 1;
+    for (v=client_data->version; v<v_end && p < product_end; v++,p++)
+    {
+        *v = *p;
+    }
+    *v = 0;
+    smtp_client_mod.api->add_app(asd, appId, clientId, (char*)client_data->version);
+    (*stat_counter)++;
+    return 0;
+}
+
+
+/*
+ *  Identify the product and version of the SMTP client.
+ *
+ *  Returns 0 if a recognized product is found.  Otherwise returns 1.
+ */
+static int IdentifyClientVersion(ClientSMTPData* const fd, const uint8_t* product,
+    const uint8_t* data_end, AppIdSession* asd, Packet*)
+{
+    const uint8_t* p;
+    uint8_t* v;
+    uint8_t* v_end;
+    unsigned len;
+    unsigned sublen;
+    AppId appId = (fd->flags & CLIENT_FLAG_SMTPS) ?  APP_ID_SMTPS : APP_ID_SMTP;
+
+    v_end = fd->version;
+    v_end += MAX_VERSION_SIZE - 1;
+    len = data_end - product;
+    if (len >= sizeof(MICROSOFT) && memcmp(product, MICROSOFT, sizeof(MICROSOFT)-1) == 0)
+    {
+        p = product + sizeof(MICROSOFT) - 1;
+
+        if (data_end-p >= (int)sizeof(OUTLOOK) && memcmp(p, OUTLOOK, sizeof(OUTLOOK)-1) == 0)
+        {
+            p += sizeof(OUTLOOK) - 1;
+            if (p >= data_end)
+                return 1;
+            if (*p == ',')
+            {
+                p++;
+                if (p >= data_end || *p != ' ')
+                    return 1;
+                return extract_version_and_add_client_app(APP_ID_OUTLOOK,
+                    2, p, data_end, fd, asd, appId,
+                    &appid_stats.smtp_microsoft_outlook_clients);
+            }
+            else if (*p == ' ')
+            {
+                p++;
+                if (data_end-p >= (int)sizeof(EXPRESS) && memcmp(p, EXPRESS, sizeof(EXPRESS)-1) == 0)
+                {
+                    return extract_version_and_add_client_app(APP_ID_OUTLOOK_EXPRESS,
+                        sizeof(EXPRESS), p, data_end, fd, asd, appId,
+                        &appid_stats.smtp_microsoft_outlook_express_clients);
+                }
+                else if (data_end-p >= (int)sizeof(IMO) && memcmp(p, IMO, sizeof(IMO)-1) == 0)
+                {
+                    return extract_version_and_add_client_app(APP_ID_OUTLOOK,
+                        sizeof(IMO), p, data_end, fd, asd, appId,
+                        &appid_stats.smtp_microsoft_outlook_imo_clients);
+                }
+            }
+        }
+    }
+    else if (len >= sizeof(APP_SMTP_EVOLUTION) && memcmp(product, APP_SMTP_EVOLUTION,
+        sizeof(APP_SMTP_EVOLUTION)-1) == 0)
+    {
+        return extract_version_and_add_client_app(APP_ID_EVOLUTION,
+            sizeof(APP_SMTP_EVOLUTION), product, data_end, fd, asd, appId,
+            &appid_stats.smtp_evolution_clients);
+    }
+    else if (len >= sizeof(APP_SMTP_LOTUS_NOTES) && memcmp(product, APP_SMTP_LOTUS_NOTES,
+        sizeof(APP_SMTP_LOTUS_NOTES)-1) == 0)
+    {
+        return extract_version_and_add_client_app(APP_ID_LOTUS_NOTES,
+            sizeof(APP_SMTP_LOTUS_NOTES), product, data_end, fd, asd, appId,
+            &appid_stats.smtp_lotus_notes_clients);
+    }
+    else if (len >= sizeof(APP_SMTP_APPLEMAIL) && memcmp(product, APP_SMTP_APPLEMAIL,
+        sizeof(APP_SMTP_APPLEMAIL)-1) == 0)
+    {
+        p = product + sizeof(APP_SMTP_APPLEMAIL) - 1;
+        if (p >= data_end || *(data_end - 1) != ')' || *p == ')' || isspace(*p))
+            return 1;
+        for (v=fd->version; v<v_end && p < data_end-1; v++,p++)
+        {
+            *v = *p;
+        }
+        *v = 0;
+        smtp_client_mod.api->add_app(asd, appId, APP_ID_APPLE_EMAIL, (char*)fd->version);
+        appid_stats.smtp_applemail_clients++;
+        return 0;
+    }
+    else if (len >= sizeof(APP_SMTP_EUDORA) && memcmp(product, APP_SMTP_EUDORA,
+        sizeof(APP_SMTP_EUDORA)-1) == 0)
+    {
+        return extract_version_and_add_client_app(APP_ID_EUDORA,
+            sizeof(APP_SMTP_EUDORA), product, data_end, fd, asd, appId,
+            &appid_stats.smtp_eudora_clients);
+    }
+    else if (len >= sizeof(APP_SMTP_EUDORAPRO) && memcmp(product, APP_SMTP_EUDORAPRO,
+        sizeof(APP_SMTP_EUDORAPRO)-1) == 0)
+    {
+        return extract_version_and_add_client_app(APP_ID_EUDORA_PRO,
+            sizeof(APP_SMTP_EUDORAPRO), product, data_end, fd, asd, appId,
+            &appid_stats.smtp_eudora_pro_clients);
+    }
+    else if (len >= sizeof(APP_SMTP_AOL) && memcmp(product, APP_SMTP_AOL,
+        sizeof(APP_SMTP_AOL)-1) == 0)
+    {
+        return extract_version_and_add_client_app(APP_ID_AOL_EMAIL,
+            sizeof(APP_SMTP_AOL), product, data_end, fd, asd, appId,
+            &appid_stats.smtp_aol_clients);
+    }
+    else if (len >= sizeof(APP_SMTP_MUTT) && memcmp(product, APP_SMTP_MUTT,
+        sizeof(APP_SMTP_MUTT)-1) == 0)
+    {
+        return extract_version_and_add_client_app(APP_ID_MUTT,
+            sizeof(APP_SMTP_MUTT), product, data_end, fd, asd, appId,
+            &appid_stats.smtp_mutt_clients);
+    }
+    else if (len >= sizeof(APP_SMTP_KMAIL) && memcmp(product, APP_SMTP_KMAIL,
+        sizeof(APP_SMTP_KMAIL)-1) == 0)
+    {
+        return extract_version_and_add_client_app(APP_ID_KMAIL,
+            sizeof(APP_SMTP_KMAIL), product, data_end, fd, asd, appId,
+            &appid_stats.smtp_kmail_clients);
+    }
+    else if (len >= sizeof(APP_SMTP_THUNDERBIRD) && memcmp(product, APP_SMTP_THUNDERBIRD,
+        sizeof(APP_SMTP_THUNDERBIRD)-1) == 0)
+    {
+        return extract_version_and_add_client_app(APP_ID_THUNDERBIRD,
+            sizeof(APP_SMTP_THUNDERBIRD), product, data_end, fd, asd, appId,
+            &appid_stats.smtp_thunderbird_clients);
+    }
+    else if (len >= sizeof(APP_SMTP_MTHUNDERBIRD) && memcmp(product, APP_SMTP_MTHUNDERBIRD,
+        sizeof(APP_SMTP_MTHUNDERBIRD)-1) == 0)
+    {
+        return extract_version_and_add_client_app(APP_ID_THUNDERBIRD,
+            sizeof(APP_SMTP_MTHUNDERBIRD), product, data_end, fd, asd, appId,
+            &appid_stats.smtp_thunderbird_clients);
+    }
+    else if (len >= sizeof(APP_SMTP_MOZILLA) && memcmp(product, APP_SMTP_MOZILLA,
+        sizeof(APP_SMTP_MOZILLA)-1) == 0)
+    {
+        for (p = product + sizeof(APP_SMTP_MOZILLA) - 1; p < data_end; p++)
+        {
+            if (*p == 'T')
+            {
+                sublen = data_end - p;
+                if (sublen >= sizeof(APP_SMTP_THUNDERBIRD_SHORT) && memcmp(p,
+                    APP_SMTP_THUNDERBIRD_SHORT, sizeof(APP_SMTP_THUNDERBIRD_SHORT)-1) == 0)
+                {
+                    return extract_version_and_add_client_app(
+                        APP_ID_THUNDERBIRD, sizeof(APP_SMTP_THUNDERBIRD_SHORT),
+                        p, data_end, fd, asd, appId,
+                        &appid_stats.smtp_thunderbird_clients);
+                }
+            }
+        }
+    }
+
+    return 1;
+}
+
+
+static void smtp_free_state(void *data)
+{
+    SMTPDetectorData* dd = (SMTPDetectorData*)data;
+    ClientSMTPData *cd;
+
+    if (dd)
+    {
+        cd = &dd->client;
+        if (cd->headerline)
+            snort_free(cd->headerline);
+        snort_free(dd);
+    }
+}
+static inline SMTPDetectorData* smtp_get_SMTPDetectorData(AppIdSession* asd)
+{
+    SMTPDetectorData* dd = (SMTPDetectorData*)smtp_detector_mod.api->data_get(asd, smtp_detector_mod.flow_data_index);
+    if (dd)
+        return dd;
+
+    dd = (SMTPDetectorData*)snort_calloc(1, sizeof(*dd));
+    if (smtp_detector_mod.api->data_add(asd, dd, smtp_detector_mod.flow_data_index, &smtp_free_state))
+    {
+        snort_free(dd);
+        return nullptr;
+    }
+
+    dd->server.state = SMTP_SERVICE_STATE_CONNECTION;
+    dd->server.detected = false;
+    dd->client.state = SMTP_CLIENT_STATE_HELO;
+    dd->need_continue = 1;
+    dd->watch_for_deprecated_port = 1;
+
+    asd->set_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
+    return dd;
+}
+
+// #define UNIT_TEST_SKIP
+static CLIENT_APP_RETCODE smtp_ca_validate(const uint8_t* data, uint16_t size, const int dir,
+    AppIdSession* asd, Packet* pkt, struct Detector*)
+{
+    SMTPDetectorData* dd;
+    ClientSMTPData* fd;
+    const uint8_t* end;
+    unsigned len;
+#ifdef UNIT_TESTING
+    SMTPClientState currState = SMTP_CLIENT_STATE_NONE;
+#endif
+
+    if (!(dd = smtp_get_SMTPDetectorData(asd)))
+        return CLIENT_APP_ENOMEM;
+
+    fd = &dd->client;
+
+    if (dir != APP_ID_FROM_INITIATOR)
+        return CLIENT_APP_INPROCESS;
+
+    if (asd->get_session_flags(APPID_SESSION_ENCRYPTED | APPID_SESSION_DECRYPTED) == APPID_SESSION_ENCRYPTED)
+    {
+        if ((fd->flags & CLIENT_FLAG_STARTTLS_SUCCESS))
+        {
+            fd->decryption_countdown--;
+            if (!fd->decryption_countdown)
+#ifdef UNIT_TEST_SKIP
+            if (asd->session_packet_count == 0)
+#endif
+            {
+                fd->flags |= CLIENT_FLAG_SMTPS; // report as SMTPS
+                asd->clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
+                /* Because we can't see any further info without decryption we settle for
+                   plain APP_ID_SMTPS instead of perhaps finding data that would make calling
+                   ExtractVersion() worthwhile, So set the appid and call it good. */
+                smtp_client_mod.api->add_app(asd, APP_ID_SMTPS, APP_ID_SMTPS, nullptr);
+                goto done;
+            }
+        }
+        return CLIENT_APP_INPROCESS;
+    }
+
+
+    for (end = data + size; data < end; data++)
+    {
+#ifdef UNIT_TESTING
+    if (app_id_debug_session_flag && currState != fd->state)
+    {
+        DEBUG_WRAP(DebugMessage(DEBUG_APPID, "AppIdDbg %s SMTP client state %s\n", app_id_debug_session, stateName[fd->state]););
+        currState = fd->state;
+    }
+#endif
+        len = end - data;
+        switch (fd->state)
+        {
+        case SMTP_CLIENT_STATE_HELO:
+            if (len >= (sizeof(HELO)-1) && strncasecmp((const char*)data, HELO, sizeof(HELO)-1) == 0)
+            {
+                data += (sizeof(HELO)-1)-1;
+                fd->nextstate = SMTP_CLIENT_STATE_MAIL_FROM;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            else if (len >= (sizeof(EHLO)-1) && strncasecmp((const char*)data, EHLO, sizeof(EHLO)-1) == 0)
+            {
+                data += (sizeof(EHLO)-1)-1;
+                fd->nextstate = SMTP_CLIENT_STATE_MAIL_FROM;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            else goto done;
+            break;
+
+        case SMTP_CLIENT_STATE_MAIL_FROM:
+            if (len >= (sizeof(MAILFROM)-1) && strncasecmp((const char*)data, MAILFROM, sizeof(MAILFROM)-1) == 0)
+            {
+                data += (sizeof(MAILFROM)-1)-1;
+                fd->nextstate = SMTP_CLIENT_STATE_RCPT_TO;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            else if (len >= (sizeof(RSET)-1) && strncasecmp((const char*)data, RSET, sizeof(RSET)-1) == 0)
+            {
+                data += (sizeof(RSET)-1)-1;
+                fd->nextstate = fd->state;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            else if (len >= (sizeof(AUTH)-1) && strncasecmp((const char*)data, AUTH, sizeof(AUTH)-1) == 0)
+            {
+                data += (sizeof(AUTH)-1)-1;
+                fd->nextstate = fd->state;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            else if (len >= (sizeof(STARTTLS)-1) && strncasecmp((const char*)data, STARTTLS, sizeof(STARTTLS)-1) == 0)
+            {
+                data += (sizeof(STARTTLS)-1)-1;
+                dd->server.state = SMTP_SERVICE_STATE_STARTTLS;
+                fd->nextstate = fd->state;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            else goto done;
+            break;
+        case SMTP_CLIENT_STATE_RCPT_TO:
+            if (len >= (sizeof(RCPTTO)-1) && strncasecmp((const char*)data, RCPTTO, sizeof(RCPTTO)-1) == 0)
+            {
+                data += (sizeof(RCPTTO)-1)-1;
+                fd->nextstate = SMTP_CLIENT_STATE_DATA;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            else
+                goto done;
+            break;
+
+        case SMTP_CLIENT_STATE_DATA:
+            if (len >= (sizeof(DATA)-1) && strncasecmp((const char*)data, DATA, sizeof(DATA)-1) == 0)
+            {
+                data += (sizeof(DATA)-1)-1;
+                fd->nextstate = SMTP_CLIENT_STATE_MESSAGE;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            else if (len >= (sizeof(RCPTTO)-1) && strncasecmp((const char*)data, RCPTTO, sizeof(RCPTTO)-1) == 0)
+            {
+                data += (sizeof(RCPTTO)-1)-1;
+                fd->nextstate = fd->state;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            break;
+        case SMTP_CLIENT_STATE_MESSAGE:
+            if (*data == '.')
+            {
+                if (len == 0 ||
+                    (len >= 1 && data[1] == '\n') ||
+                    (len >= 2 && data[1] == '\r' && data[2] == '\n'))
+                {
+                    smtp_client_mod.api->add_app(asd, APP_ID_SMTP, APP_ID_SMTP, nullptr);
+                    goto done;
+                }
+            }
+            else if (len >= (sizeof(XMAILER)-1) && strncasecmp((const char*)data, XMAILER, sizeof(XMAILER)-1) == 0)
+            {
+                data += (sizeof(XMAILER)-1)-1;
+                fd->state = SMTP_CLIENT_STATE_GET_PRODUCT_VERSION;
+            }
+            else if (len >= (sizeof(USERAGENT)-1) && strncasecmp((const char*)data, USERAGENT, sizeof(USERAGENT)-1) == 0)
+            {
+                data += (sizeof(USERAGENT)-1)-1;
+                fd->state = SMTP_CLIENT_STATE_GET_PRODUCT_VERSION;
+            }
+            else if (!isprint(*data) && *data != '\t')
+                goto done;
+            else
+            {
+                fd->nextstate = fd->state;
+                fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
+            }
+            break;
+
+        case SMTP_CLIENT_STATE_GET_PRODUCT_VERSION:
+            if (*data == '\r')
+            {
+                if (fd->headerline && fd->pos)
+                {
+                    IdentifyClientVersion(fd, fd->headerline, fd->headerline + fd->pos, asd, pkt);
+                    snort_free(fd->headerline);
+                    fd->headerline = nullptr;
+                    fd->pos = 0;
+                }
+                goto done;
+            }
+            else if (!isprint(*data))
+            {
+                snort_free(fd->headerline);
+                fd->headerline = nullptr;
+                fd->pos = 0;
+                goto done;
+            }
+            else
+            {
+                if (!fd->headerline)
+                    fd->headerline = (uint8_t*)snort_alloc(MAX_HEADER_LINE_SIZE);
+
+                if (fd->pos < (MAX_HEADER_LINE_SIZE-1))
+                    fd->headerline[fd->pos++] = *data;
+            }
+            break;
+
+        case SMTP_CLIENT_STATE_SKIP_LINE:
+            if (*data == '\n')
+            {
+                fd->pos = 0;
+                fd->state = fd->nextstate;
+                fd->nextstate = SMTP_CLIENT_STATE_NONE;
+            }
+            else if (!(*data == '\r' || isprint(*data)))
+                goto done;
+            break;
+
+        default:
+            goto done;
+        }
+    }
+    return CLIENT_APP_INPROCESS;
+
+done:
+    dd->need_continue = 0;
+    asd->set_session_flags(APPID_SESSION_CLIENT_DETECTED);
+    return CLIENT_APP_SUCCESS;
+}
+
+static inline int smtp_validate_reply(const uint8_t*data, uint16_t* offset, uint16_t size,
+    int* multi, int* code)
+{
+    const ServiceSMTPCode* code_hdr;
+    int tmp;
+
+    // Trim any blank lines (be a little tolerant)
+    for (; *offset<size; (*offset)++)
+    {
+        if (data[*offset] != 0x0D && data[*offset] != 0x0A)
+            break;
+    }
+
+    if (size - *offset < (int)sizeof(ServiceSMTPCode))
+    {
+        for (; *offset<size; (*offset)++)
+        {
+            if (!isspace(data[*offset]))
+                return -1;
+        }
+        return 0;
+    }
+
+    code_hdr = (ServiceSMTPCode* )(data + *offset);
+
+    if (code_hdr->code[0] < '1' || code_hdr->code[0] > '5')
+        return -1;
+    tmp = (code_hdr->code[0] - '0') * 100;
+
+    if (code_hdr->code[1] < '0' || code_hdr->code[1] > '5')
+        return -1;
+    tmp += (code_hdr->code[1] - '0') * 10;
+
+    if (!isdigit(code_hdr->code[2]))
+        return -1;
+    tmp += code_hdr->code[2] - '0';
+
+    if (*multi && tmp != *code)
+        return -1;
+    *code = tmp;
+    if (code_hdr->sp == '-') *multi = 1;
+    else if (code_hdr->sp == ' ')
+        *multi = 0;
+    else
+        return -1;
+
+    // We have a valid code, now we need to see if the rest of the line is okay
+    *offset += sizeof(ServiceSMTPCode);
+    for (; *offset < size; (*offset)++)
+    {
+        if (data[*offset] == 0x0D)
+        {
+            (*offset)++;
+            if (*offset >= size)
+                return -1;
+            if (data[*offset] != 0x0A)
+                return -1;
+        }
+
+        if (data[*offset] == 0x0A)
+        {
+            if (*multi)
+            {
+                if ((*offset + 1) >= size)
+                    return 0;
+
+                if (size - (*offset + 1) < (int)sizeof(ServiceSMTPCode))
+                    return -1;
+
+                code_hdr = (ServiceSMTPCode*)(data + *offset + 1);
+
+                if (code_hdr->code[0] < '1' || code_hdr->code[0] > '5')
+                    return -1;
+                tmp = (code_hdr->code[0] - '0') * 100;
+
+                if (code_hdr->code[1] < '1' || code_hdr->code[1] > '5')
+                    return -1;
+                tmp += (code_hdr->code[1] - '0') * 10;
+
+                if (!isdigit(code_hdr->code[2]))
+                    return -1;
+                tmp += code_hdr->code[2] - '0';
+
+                if (tmp != *code)
+                    return -1;
+
+                if (code_hdr->sp == ' ') *multi = 0;
+                else if (code_hdr->sp != '-')
+                    return -1;
+
+                *offset += sizeof(ServiceSMTPCode);
+            }
+            else
+            {
+                (*offset)++;
+                return *code;
+            }
+        }
+        else if (!isprint(data[*offset]))
+            return -1;
+    }
+
+    return 0;
+}
+
+static int smtp_svc_validate(ServiceValidationArgs* args)
+{
+    SMTPDetectorData* dd;
+    ServiceSMTPData* fd;
+    AppIdSession* asd = args->asd;
+    const uint8_t* data = args->data;
+    uint16_t size = args->size;
+    uint16_t offset;
+
+    if (!(dd = smtp_get_SMTPDetectorData(asd)))
+        return SERVICE_ENOMEM;
+
+    if (!size)
+        goto inprocess;
+
+    // Whether this is bound for the client detector or not, if client doesn't care
+    //  then clear the APPID_SESSION_CONTINUE flag and we will be done sooner.
+    if (dd->need_continue == 0)
+    {
+        dd->need_continue--; // don't come through again.
+        asd->clear_session_flags(APPID_SESSION_CONTINUE);
+        if (dd->client.flags & CLIENT_FLAG_SMTPS)
+        {
+            // client side gave up because everything is encrypted.
+            smtp_service_mod.api->add_service(asd, args->pkt, args->dir, &svc_element,
+                                       APP_ID_SMTPS, nullptr, nullptr, nullptr);
+            return SERVICE_SUCCESS;
+        }
+        else if (asd->get_session_flags(APPID_SESSION_SERVICE_DETECTED))
+        {
+            // Client made it's decision so we are totally done.
+            return SERVICE_SUCCESS;
+        }
+        // We arrive here because the service side is not done yet.
+    }
+
+    if (args->dir != APP_ID_FROM_RESPONDER)
+        goto inprocess; // allow client validator to have it's shot.
+
+    if (dd->watch_for_deprecated_port)
+    {
+        dd->watch_for_deprecated_port = 0;
+        // If we have caught a response on port 465 that isn't encrypted+decrypted it isn't SMTP at all.
+        // The new IANA assignment for this port is non-SSL and NOT SMTP. Only an old server will survive the test.
+        if (args->pkt->ptrs.sp == SMTPS_DEPRECATED_PORT && !asd->get_session_flags(APPID_SESSION_DECRYPTED))
+        {
+            // This is not an SMTPS port because we have not ALREADY gone through the SSL handshake
+            goto fail;
+        }
+    }
+
+    fd = &dd->server;
+
+    offset = 0;
+    while (offset < size)
+    {
+        if (smtp_validate_reply(data, &offset, size, &fd->multiline, &fd->code) < 0)
+        {
+            if (!(dd->client.flags & CLIENT_FLAG_STARTTLS_SUCCESS))
+                goto fail;
+            goto inprocess;
+        }
+        if (!fd->code) goto inprocess;
+        switch (fd->state)
+        {
+        case SMTP_SERVICE_STATE_CONNECTION:
+            switch (fd->code)
+            {
+            case 220:
+                fd->state = SMTP_SERVICE_STATE_HELO;
+                break;
+            case 421:
+                if (service_strstr(data, size, (const uint8_t*)SMTP_CLOSING_CONN, sizeof(SMTP_CLOSING_CONN)-1))
+                    goto success;
+            case 520:
+            case 554:
+                fd->state = SMTP_SERVICE_STATE_CONNECTION_ERROR;
+                break;
+            default:
+                goto fail;
+            }
+            break;
+        case SMTP_SERVICE_STATE_HELO:
+            switch (fd->code)
+            {
+            case 250:
+                fd->state = SMTP_SERVICE_STATE_TRANSFER;
+                break;
+            case 500:
+            case 501:
+            case 504:
+                break;
+            case 421:
+            case 553:
+                fd->state = SMTP_SERVICE_STATE_CONNECTION_ERROR;
+                break;
+            default:
+                goto fail;
+            }
+            break;
+        case SMTP_SERVICE_STATE_STARTTLS:
+            // success or fail, return client to connection-complete state.
+            dd->client.state = SMTP_CLIENT_STATE_HELO;
+            fd->state = SMTP_SERVICE_STATE_HELO;
+            if (fd->code == 220)
+            {
+                asd->set_session_flags(APPID_SESSION_ENCRYPTED);
+                // Now we wonder if the decryption mechanism is in place, so...
+                dd->client.flags |= CLIENT_FLAG_STARTTLS_SUCCESS;
+                dd->client.decryption_countdown = SSL_WAIT_PACKETS; // start a countdown
+                goto inprocess;
+            }
+            /* STARTTLS failed. */
+            break;
+        case SMTP_SERVICE_STATE_TRANSFER:
+            goto success;
+        case SMTP_SERVICE_STATE_CONNECTION_ERROR:
+        default:
+            goto fail;
+        }
+    }
+
+inprocess:
+    smtp_service_mod.api->service_inprocess(asd, args->pkt, args->dir, &svc_element);
+    return SERVICE_INPROCESS;
+
+success:
+    if (dd->need_continue > 0)
+        asd->set_session_flags(APPID_SESSION_CONTINUE);
+
+    smtp_service_mod.api->add_service(asd, args->pkt, args->dir, &svc_element,
+                                      APP_ID_SMTP, nullptr, nullptr, nullptr);
+    if (!fd->detected)
+    {
+        if(fd->state == SMTP_SERVICE_STATE_STARTTLS)
+            appid_stats.smtps_flows++;
+        else
+            appid_stats.smtp_flows++;
+        fd->detected = true;
+    }
+    return SERVICE_SUCCESS;
+
+fail:
+    smtp_service_mod.api->fail_service(asd, args->pkt, args->dir, &svc_element,
+                                       smtp_service_mod.flow_data_index);
+    return SERVICE_NOMATCH;
+}
similarity index 95%
rename from src/network_inspectors/appid/service_plugins/service_smtp.h
rename to src/network_inspectors/appid/detector_plugins/detector_smtp.h
index 2318aaef912708fbc7cf3ae96608ccfcda37bcb1..a972d66751582d076bf335ecc218a863cd8de734 100644 (file)
@@ -24,7 +24,8 @@
 
 #include "detector_plugins/detector_api.h"
 
-extern RNAServiceValidationModule smtp_service_mod;
+extern RNADetectorValidationModule smtp_detector_mod;
+
 
 #endif
 
similarity index 68%
rename from src/network_inspectors/appid/client_plugins/test/CMakeLists.txt
rename to src/network_inspectors/appid/detector_plugins/test/CMakeLists.txt
index 0f73377be162ca7caf8aff45626c6efecc14aecb..be643af7d90c96db1cd2a71f421b556f20e11888 100644 (file)
@@ -5,7 +5,7 @@ set (
 
 add_library(smtp_test_depends_on_lib ../../appid_stats_counter.cc)
 
-add_cpputest(client_app_smtp_test smtp_test_depends_on_lib ${SMTP_TEST_LIBS})
+add_cpputest(detector_smtp_test smtp_test_depends_on_lib ${SMTP_TEST_LIBS})
 
 include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} )
 
diff --git a/src/network_inspectors/appid/detector_plugins/test/Makefile.am b/src/network_inspectors/appid/detector_plugins/test/Makefile.am
new file mode 100644 (file)
index 0000000..b768f87
--- /dev/null
@@ -0,0 +1,15 @@
+
+AM_DEFAULT_SOURCE_EXT = .cc
+
+check_PROGRAMS = \
+detector_smtp_test
+
+TESTS = $(check_PROGRAMS)
+
+detector_smtp_test_CPPFLAGS = -I$(top_srcdir)/src/network_inspectors/appid @AM_CPPFLAGS@ @CPPUTEST_CPPFLAGS@
+
+detector_smtp_test_LDADD = \
+../../appid_stats_counter.o \
+../../../../utils/libutils.a \
+@CPPUTEST_LDFLAGS@
+
similarity index 99%
rename from src/network_inspectors/appid/client_plugins/test/client_app_smtp_test.cc
rename to src/network_inspectors/appid/detector_plugins/test/detector_smtp_test.cc
index 7768d032c91e97555d7ad7f062b0d91d045a48a4..4a56f700cb173017c8d290041eb17b7db7aacadc 100644 (file)
@@ -19,7 +19,7 @@
 // client_app_smtp_test.cc author Steve Chew <stechew@cisco.com>
 // unit test for client_app_smtp
 
-#include "network_inspectors/appid/client_plugins/client_app_smtp.cc"
+#include "network_inspectors/appid/detector_plugins/detector_smtp.cc"
 
 #include <CppUTest/CommandLineTestRunner.h>
 #include <CppUTest/TestHarness.h>
index c229a5a355e557f23bf686a5a1dae2c4cc001ebd..19735ff71c58064730e2f8fdd18589be1b01f84e 100644 (file)
@@ -1703,12 +1703,13 @@ static int detector_add_chp_action(AppId appIdInstance, int isKeyPattern, Patter
     uint precedence;
     CHPListElement* chpa;
     CHPApp* chpapp;
+    AppInfoManager& app_info_mgr = AppInfoManager::get_instance();
 
     //find the CHP App for this
     if (!(chpapp = (decltype(chpapp))sfxhash_find(CHP_glossary, &appIdInstance)))
     {
         ErrorMessage(
-            "LuaDetectorApi:Invalid attempt to add a CHP action for unknown appId %d, instance %d. - pattern:\"%s\" - action \"%s\"",
+            "LuaDetectorApi:Invalid attempt to add a CHP action for unknown appId %d, instance %d. - pattern:\"%s\" - action \"%s\"\n",
             CHP_APPIDINSTANCE_TO_ID(appIdInstance), CHP_APPIDINSTANCE_TO_INSTANCE(appIdInstance),
             patternData, optionalActionData ? optionalActionData : "");
         snort_free(patternData);
@@ -1728,8 +1729,36 @@ static int detector_add_chp_action(AppId appIdInstance, int isKeyPattern, Patter
     precedence = chpapp->ptype_scan_counts[patternType]++;
     // at runtime we'll want to know how many of each type of pattern we are looking for.
     if (actionType == REWRITE_FIELD || actionType == INSERT_FIELD)
-        chpapp->ptype_rewrite_insert_used[patternType]=1; // true.
-    else if (actionType != ALTERNATE_APPID)
+    {
+        if (!app_info_mgr.get_app_info_flags(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SUPPORTED_SEARCH))
+        {
+            ErrorMessage( "LuaDetectorApi: CHP action type, %d, requires previous use of action type, %d, (see appId %d, pattern=\"%s\").\n",
+                         actionType, GET_OFFSETS_FROM_REBUILT,
+                         CHP_APPIDINSTANCE_TO_ID(appIdInstance), patternData);
+            snort_free(patternData);
+            if (optionalActionData)
+                snort_free(optionalActionData);
+            return 0;
+        }
+        switch (patternType)
+        {
+        // permitted pattern type (modifiable HTTP/SPDY request field)
+        case AGENT_PT:
+        case HOST_PT:
+        case REFERER_PT:
+        case URI_PT:
+        case COOKIE_PT:
+            break;
+        default:
+            ErrorMessage( "LuaDetectorApi: CHP action type, %d, on unsupported pattern type, %d, (see appId %d, pattern=\"%s\").\n",
+                         actionType, patternType, CHP_APPIDINSTANCE_TO_ID(appIdInstance), patternData);
+            snort_free(patternData);
+            if (optionalActionData)
+                snort_free(optionalActionData);
+            return 0;
+        }
+    }
+    else if (actionType != ALTERNATE_APPID && actionType != DEFER_TO_SIMPLE_DETECT)
         chpapp->ptype_req_counts[patternType]++;
 
     chpa = (CHPListElement*)snort_calloc(sizeof(CHPListElement));
@@ -1748,14 +1777,19 @@ static int detector_add_chp_action(AppId appIdInstance, int isKeyPattern, Patter
     if (actionType == GET_OFFSETS_FROM_REBUILT)
     {
         /* This is a search engine and it is SUPPORTED for safe-search packet rewrite */
-        AppInfoManager::get_instance().set_app_info_flags(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SEARCH_ENGINE |
+        app_info_mgr.set_app_info_flags(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SEARCH_ENGINE |
             APPINFO_FLAG_SUPPORTED_SEARCH);
     }
     else if (actionType == SEARCH_UNSUPPORTED)
     {
         /* This is a search engine and it is UNSUPPORTED for safe-search packet rewrite */
-        AppInfoManager::get_instance().set_app_info_flags(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SEARCH_ENGINE);
+        app_info_mgr.set_app_info_flags(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SEARCH_ENGINE);
     }
+    else if (actionType == DEFER_TO_SIMPLE_DETECT && strcmp(patternData,"<ignore-all-patterns>") == 0)
+    {
+        remove_http_patterns_for_id(appIdInstance);
+    }
+
     return 0;
 }
 
index 7261aa6302a4d6c0941c55fe94113336d18a609e..1af223c49fb83e176752ff69cc9cecec35df3eab 100644 (file)
@@ -65,13 +65,13 @@ struct CleanServiceAPI
     AppIdConfig* pAppidConfig;  ///< AppId context for which this API should be used
 };
 
-struct IniServiceAPI;
-using RNAServiceValidationInitFCN = int(*)(const IniServiceAPI* const);
+struct InitServiceAPI;
+using RNAServiceValidationInitFCN = int(*)(const InitServiceAPI* const);
 using RNAServiceValidationCleanFCN = void(*)();
 
 struct RNAServiceValidationPort;
 struct RNAServiceValidationModule;
-struct IniServiceAPI
+struct InitServiceAPI
 {
     void (* RegisterPattern)( RNAServiceValidationFCN, IpProtocol proto, const uint8_t* pattern,
         unsigned size, int position, const char* name);
index ca787ae6a40ccff8bf22965a9d380267aa1c22e6..412bb05f1b69d01449df67207509692f7871b85e 100644 (file)
@@ -48,7 +48,6 @@
 #include "service_rshell.h"
 #include "service_rsync.h"
 #include "service_rtmp.h"
-#include "service_smtp.h"
 #include "service_snmp.h"
 #include "service_ssh.h"
 #include "service_ssl.h"
@@ -193,7 +192,7 @@ static void appSetServiceValidator( RNAServiceValidationFCN, AppId, unsigned ext
 static int CServiceAddPort(const RNAServiceValidationPort*, RNAServiceValidationModule*);
 static void CServiceRemovePorts(RNAServiceValidationFCN validate);
 
-static IniServiceAPI svc_init_api =
+static InitServiceAPI svc_init_api =
 {
     &CServiceRegisterPattern,
     &CServiceAddPort,
@@ -232,7 +231,6 @@ static RNAServiceValidationModule* static_service_list[] =
     &rshell_service_mod,
     &rsync_service_mod,
     &rtmp_service_mod,
-    &smtp_service_mod,
     &snmp_service_mod,
     &ssh_service_mod,
     &ssl_service_mod,
index 0c7a55fcc15c09c73c24e766b298924657b359f0..83f42a2fa0b0171cb5ccc7b89fcf4d2cb54c3803 100644 (file)
@@ -44,7 +44,7 @@ struct ServiceData
     uint32_t packetCount;
 };
 
-static int battle_field_init(const IniServiceAPI* const init_api);
+static int battle_field_init(const InitServiceAPI* const init_api);
 static int battle_field_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -96,7 +96,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_BATTLEFIELD, 0 }
 };
 
-static int battle_field_init(const IniServiceAPI* const init_api)
+static int battle_field_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&battle_field_validate, IpProtocol::TCP, (uint8_t*)PATTERN_HELLO,
         sizeof(PATTERN_HELLO)-1,  5, "battle_field");
index b9b5aa02be267cb44bdf9e1f4af7b1abf0631e45..27e5392b830c35f177ca9ba373e678fb6e6828d3 100644 (file)
@@ -86,7 +86,7 @@ struct ServiceBGPV1Open
 
 #pragma pack()
 
-static int bgp_init(const IniServiceAPI* const init_api);
+static int bgp_init(const InitServiceAPI* const init_api);
 static int bgp_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -130,7 +130,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_BGP, 0 }
 };
 
-static int bgp_init(const IniServiceAPI* const init_api)
+static int bgp_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&bgp_validate, IpProtocol::TCP, BGP_PATTERN,
             sizeof(BGP_PATTERN), 0, "bgp");
index ba54191b0da0e892c8eca730cd4f4a3105c7f7c9..758af5adfa1dd8886318f38ec71ec35463d956f1 100644 (file)
@@ -66,7 +66,7 @@ struct ServiceBITMsg
 };
 #pragma pack()
 
-static int bit_init(const IniServiceAPI* const init_api);
+static int bit_init(const InitServiceAPI* const init_api);
 static int bit_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -112,7 +112,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_BITTORRENT, 0 }
 };
 
-static int bit_init(const IniServiceAPI* const init_api)
+static int bit_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&bit_validate, IpProtocol::TCP, (const uint8_t*)BIT_BANNER,
         sizeof(BIT_BANNER)-1, 0, svc_name);
index 7fccf531b3ab8ea18e04a552b8677c0ae2d2ed38..f801abb901c17dfd85a5c7f85f6d7684fa897bb1 100644 (file)
@@ -66,7 +66,7 @@ struct ServiceDHCPOption
 
 #pragma pack()
 
-static int bootp_init(const IniServiceAPI* const init_api);
+static int bootp_init(const InitServiceAPI* const init_api);
 static int bootp_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -105,7 +105,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_DHCP, APPINFO_FLAG_SERVICE_ADDITIONAL | APPINFO_FLAG_SERVICE_UDP_REVERSED }
 };
 
-static int bootp_init(const IniServiceAPI* const init_api)
+static int bootp_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index 1525ccb48e35ad675005a88d6a41077381c58850..8b0090f29d7d85faf2775e3457ec73da7353f496 100644 (file)
@@ -36,7 +36,7 @@ struct ServiceDCERPCData
     unsigned count;
 };
 
-static int dcerpc_init(const IniServiceAPI* const init_api);
+static int dcerpc_init(const InitServiceAPI* const init_api);
 static int dcerpc_tcp_validate(ServiceValidationArgs* args);
 static int dcerpc_udp_validate(ServiceValidationArgs* args);
 
@@ -87,7 +87,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_DCE_RPC, 0 }
 };
 
-static int dcerpc_init(const IniServiceAPI* const init_api)
+static int dcerpc_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index 891c39ab5f2cb48f08bbb20b3ebb9bfdd9484aef..a904afec1775638a3ba690c845cdeb9a01d72c9a 100644 (file)
@@ -44,7 +44,7 @@ struct ServiceData
     uint32_t packetCount;
 };
 
-static int direct_connect_init(const IniServiceAPI* const init_api);
+static int direct_connect_init(const InitServiceAPI* const init_api);
 static int direct_connect_validate(ServiceValidationArgs* args);
 static int validateDirectConnectTcp(const uint8_t* data, uint16_t size, const int dir,
     AppIdSession* asd, const Packet* pkt, ServiceData* serviceData);
@@ -101,7 +101,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_DIRECT_CONNECT, 0 }
 };
 
-static int direct_connect_init(const IniServiceAPI* const init_api)
+static int direct_connect_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&direct_connect_validate, IpProtocol::TCP, (uint8_t*)PATTERN1,
         sizeof(PATTERN1)-1,  0, "direct_connect");
index 97654dbc003186d423500e4236feee8256a6f265..afa23ba4cf477a60125cd980f149feb9613b6966 100644 (file)
@@ -74,7 +74,7 @@ struct FLAPHeader
 
 #pragma pack()
 
-static int flap_init(const IniServiceAPI* const init_api);
+static int flap_init(const InitServiceAPI* const init_api);
 static int flap_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -116,7 +116,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_AOL_INSTANT_MESSENGER, 0 }
 };
 
-static int flap_init(const IniServiceAPI* const init_api)
+static int flap_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&flap_validate, IpProtocol::TCP, FLAP_PATTERN,
             sizeof(FLAP_PATTERN), 0, "flap");
index 74573a3dc330116b0655635c711670272122b152..6dfd871a241fe621cf0f258bda5a6c0f979be478 100644 (file)
@@ -82,7 +82,7 @@ struct ServiceFTPCode
 
 #pragma pack()
 
-static int ftp_init(const IniServiceAPI* const init_api);
+static int ftp_init(const InitServiceAPI* const init_api);
 static int ftp_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -130,7 +130,7 @@ static AppRegistryEntry appIdRegistry[] =
 
 static int16_t ftp_data_app_id = 0;
 
-static int ftp_init(const IniServiceAPI* const init_api)
+static int ftp_init(const InitServiceAPI* const init_api)
 {
     ftp_data_app_id = add_appid_protocol_reference("ftp-data");
 
index 8183a852d8dbca7fdd620c9331c6ab69681f8e88..67bf441783417c4291e9b9322a5f7d9829ed0c1b 100644 (file)
@@ -65,7 +65,7 @@ struct ServiceIRCData
     unsigned count;
 };
 
-static int irc_init(const IniServiceAPI* const init_api);
+static int irc_init(const InitServiceAPI* const init_api);
 static int irc_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -103,7 +103,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_IRCD, 0 }
 };
 
-static int irc_init(const IniServiceAPI* const init_api)
+static int irc_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index df424521a8b942f5f851bd8725345c1b00526d53..6acb90e4651a1057a818bc48fc65b6855a52f68f 100644 (file)
@@ -62,7 +62,7 @@ struct ServiceLPRData
     unsigned count;
 };
 
-static int lpr_init(const IniServiceAPI* const init_api);
+static int lpr_init(const InitServiceAPI* const init_api);
 static int lpr_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -100,7 +100,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_PRINTSRV, 0 }
 };
 
-static int lpr_init(const IniServiceAPI* const init_api)
+static int lpr_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index 82c2f832141a6fa80450b2e11d3eeda5e0bf9de5..af2ece3f6967fd9b7f25aa355fba84d4890a5cd0 100644 (file)
@@ -92,7 +92,7 @@ struct MdnsConfig
     MatchedPatterns* patternList;
 };
 
-static int MDNS_init(const IniServiceAPI* const init_api);
+static int MDNS_init(const InitServiceAPI* const init_api);
 static int ReferencePointer(const char* start_ptr,const char** resp_endptr,   int* start_index,
     uint16_t data_size, uint8_t* user_name_len, unsigned offset, const AppIdConfig* pConfig);
 static int MDNS_validate(ServiceValidationArgs* args);
@@ -140,7 +140,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_MDNS, APPINFO_FLAG_SERVICE_ADDITIONAL }
 };
 
-static int MDNS_init(const IniServiceAPI* const init_api)
+static int MDNS_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index 52a56a6c31b757c258be8d0e8069171a12270f83..97cdc633ca4a47781f7db4c3cae632726fb01ca6 100644 (file)
@@ -48,7 +48,7 @@ struct ServiceMYSQLHdr
 
 #pragma pack()
 
-static int svc_mysql_init(const IniServiceAPI* const init_api);
+static int svc_mysql_init(const InitServiceAPI* const init_api);
 static int svc_mysql_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element
@@ -86,7 +86,7 @@ static AppRegistryEntry appIdRegistry[]
     { APP_ID_MYSQL, APPINFO_FLAG_SERVICE_ADDITIONAL }
 };
 
-static int svc_mysql_init(const IniServiceAPI* const init_api)
+static int svc_mysql_init(const InitServiceAPI* const init_api)
 {
     for ( unsigned i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++ )
     {
index b020477582916e9fabf9a6a827bd0d13b1a852ac..34a9de9c3ed6e2122ebffd9d8ec0b1d4aa90f0da 100644 (file)
@@ -282,7 +282,7 @@ struct NBDgmError
 
 #pragma pack()
 
-static int netbios_init(const IniServiceAPI* const init_api);
+static int netbios_init(const InitServiceAPI* const init_api);
 static int nbns_validate(ServiceValidationArgs* args);
 static int nbss_validate(ServiceValidationArgs* args);
 static int nbdgm_validate(ServiceValidationArgs* args);
@@ -344,7 +344,7 @@ RNAServiceValidationModule netbios_service_mod
     0
 };
 
-static int netbios_init(const IniServiceAPI* const init_api)
+static int netbios_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&nbss_validate, IpProtocol::TCP, NB_SMB_BANNER,
         sizeof(NB_SMB_BANNER), -1, "netbios");
index b28482567168a6f3312f36d43e6d6e3ddb8eb76a..c796acfecf524740cf9c9a4eb904904d1bf5b64e 100644 (file)
@@ -62,7 +62,7 @@ struct ServiceNNTPCode
 
 #pragma pack()
 
-static int nntp_init(const IniServiceAPI* const init_api);
+static int nntp_init(const InitServiceAPI* const init_api);
 static int nntp_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -103,7 +103,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_NNTP, 0 }
 };
 
-static int nntp_init(const IniServiceAPI* const init_api)
+static int nntp_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&nntp_validate, IpProtocol::TCP, (uint8_t*)NNTP_PATTERN1,
         sizeof(NNTP_PATTERN1)-1, 0, "nntp");
index ebfe609851768e097592f6640430848d2ed5bc74..2735cf9f3749529f2a44257e8cf1b656f01f7f0f 100644 (file)
@@ -59,7 +59,7 @@ struct ServiceNTPOptional
 
 #pragma pack()
 
-static int ntp_init(const IniServiceAPI* const init_api);
+static int ntp_init(const InitServiceAPI* const init_api);
 static int ntp_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -98,7 +98,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_NTP, 0 }
 };
 
-static int ntp_init(const IniServiceAPI* const init_api)
+static int ntp_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index f449f67b8c5ebbef1f05b8f146f961da1903a611..806f6ae6317b9f163455897bc7778c300b5b6714 100644 (file)
@@ -61,7 +61,7 @@ struct RADIUSHeader
 
 #pragma pack()
 
-static int radius_init(const IniServiceAPI* const init_api);
+static int radius_init(const InitServiceAPI* const init_api);
 static int radius_validate(ServiceValidationArgs* args);
 static int radius_validate_accounting(ServiceValidationArgs* args);
 
@@ -116,7 +116,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_RADIUS, APPINFO_FLAG_SERVICE_UDP_REVERSED }
 };
 
-static int radius_init(const IniServiceAPI* const init_api)
+static int radius_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index 952b9f842000a8c2c5ee44b0b2e252418c6115ad..1b80016f764de7767d6495e3ce4675abcb94b058 100644 (file)
@@ -64,7 +64,7 @@ struct ServiceREXECData
     struct ServiceREXECData* child;
 };
 
-static int rexec_init(const IniServiceAPI* const init_api);
+static int rexec_init(const InitServiceAPI* const init_api);
 static int rexec_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -104,7 +104,7 @@ static AppRegistryEntry appIdRegistry[] =
 
 static int16_t app_id = 0;
 
-static int rexec_init(const IniServiceAPI* const init_api)
+static int rexec_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
 
index 1ba4061a74854d878e3489ec0be6a3fc19f25010..ebaa6c75cb0e04473b70e4a952e5c18487d4b66e 100644 (file)
@@ -32,7 +32,7 @@
 
 #define RFB_BANNER "RFB "
 
-static int rfb_init(const IniServiceAPI* const init_api);
+static int rfb_init(const InitServiceAPI* const init_api);
 static int rfb_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -78,7 +78,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_VNC_RFB, APPINFO_FLAG_SERVICE_ADDITIONAL }
 };
 
-static int rfb_init(const IniServiceAPI* const init_api)
+static int rfb_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&rfb_validate, IpProtocol::TCP, (uint8_t*)RFB_BANNER,
         sizeof(RFB_BANNER) - 1, 0, "rfb");
index b3e302ebf80bc36870ff702c3566bb7736d7e4b9..e7b8f1515c6bf35f211a62ffd6070cbaaafb6dfc 100644 (file)
@@ -44,7 +44,7 @@ struct ServiceRLOGINData
     RLOGINState state;
 };
 
-static int rlogin_init(const IniServiceAPI* const init_api);
+static int rlogin_init(const InitServiceAPI* const init_api);
 static int rlogin_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -82,7 +82,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_RLOGIN, 0 }
 };
 
-static int rlogin_init(const IniServiceAPI* const init_api)
+static int rlogin_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
index d9f0af384aed044191bdfc14b0e558150128c5ce..2e140cab6e329fc5ce25f219527ad6cc9cf12fae 100644 (file)
@@ -161,7 +161,7 @@ struct ServiceRPCData
     int once;
 };
 
-static int rpc_init(const IniServiceAPI* const init_api);
+static int rpc_init(const InitServiceAPI* const init_api);
 static int rpc_validate(ServiceValidationArgs* args);
 static int rpc_tcp_validate(ServiceValidationArgs* args);
 
@@ -241,7 +241,7 @@ static AppRegistryEntry appIdRegistry[] =
 
 static int16_t app_id = 0;
 
-static int rpc_init(const IniServiceAPI* const init_api)
+static int rpc_init(const InitServiceAPI* const init_api)
 {
     struct rpcent* rpc;
     RPCProgram* prog;
index b0a7433382a4491dcd919b4c8b3e59b04b72f039..d9a9dc9f7538a866dfc64cb23d77d6cfd8506f56 100644 (file)
@@ -55,7 +55,7 @@ struct ServiceRSHELLData
     ServiceRSHELLData* child;
 };
 
-static int rshell_init(const IniServiceAPI* const init_api);
+static int rshell_init(const InitServiceAPI* const init_api);
 static int rshell_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -95,7 +95,7 @@ static AppRegistryEntry appIdRegistry[] =
 
 static int16_t app_id = 0;
 
-static int rshell_init(const IniServiceAPI* const init_api)
+static int rshell_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
 
@@ -204,8 +204,10 @@ static int rshell_validate(ServiceValidationArgs* args)
                 }
                 pf->scan_flags |= SCAN_HOST_PORT_FLAG;
                 PopulateExpectedFlow(asd, pf,
+                    APPID_SESSION_CONTINUE |
+                    APPID_SESSION_REXEC_STDERR |
                     APPID_SESSION_NO_TPI |
-                    APPID_SESSION_IGNORE_HOST |
+                    APPID_SESSION_SERVICE_DETECTED |
                     APPID_SESSION_NOT_A_SERVICE |
                     APPID_SESSION_PORT_SERVICE_DONE);
                 pf->rnaServiceState = RNA_STATE_STATEFUL;
index 3cab8babb099ffb4eb5a466e74214985fc5fcdf5..e2bbcc3592bec7da88d438358c745f6a45e01d2d 100644 (file)
@@ -45,7 +45,7 @@ struct ServiceRSYNCData
     RSYNCState state;
 };
 
-static int rsync_init(const IniServiceAPI* const init_api);
+static int rsync_init(const InitServiceAPI* const init_api);
 static int rsync_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -83,7 +83,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_RSYNC, APPINFO_FLAG_SERVICE_ADDITIONAL }
 };
 
-static int rsync_init(const IniServiceAPI* const init_api)
+static int rsync_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&rsync_validate, IpProtocol::TCP, (uint8_t*)RSYNC_BANNER,
         sizeof(RSYNC_BANNER)-1, 0, "rsync");
index 0c030ef89c0e7eedcc9d4e4bd76ac21c3548f554..16b84483b76fb8b286711857e29e02377a19a068 100644 (file)
@@ -80,7 +80,7 @@ struct ServiceRTMPData
     char* pageUrl;
 };
 
-static int rtmp_init(const IniServiceAPI* const api);
+static int rtmp_init(const InitServiceAPI* const api);
 static int rtmp_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -119,7 +119,7 @@ static AppRegistryEntry appIdRegistry[] =
     { APP_ID_RTMP, APPINFO_FLAG_SERVICE_ADDITIONAL }
 };
 
-static int rtmp_init(const IniServiceAPI* const init_api)
+static int rtmp_init(const InitServiceAPI* const init_api)
 {
     unsigned i;
     for (i = 0; i < (sizeof(appIdRegistry) / sizeof(*appIdRegistry)); i++)
diff --git a/src/network_inspectors/appid/service_plugins/service_smtp.cc b/src/network_inspectors/appid/service_plugins/service_smtp.cc
deleted file mode 100644 (file)
index 89bd835..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2016 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2005-2013 Sourcefire, Inc.
-//
-// 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.
-//--------------------------------------------------------------------------
-
-// service_smtp.cc author Sourcefire Inc.
-
-#include "service_smtp.h"
-
-#include "main/snort_debug.h"
-#include "utils/util.h"
-
-#include "service_util.h"
-#include "application_ids.h"
-#include "service_api.h"
-#include "appid_module.h"
-
-#define SMTP_PORT   25
-#define SMTP_CLOSING_CONN "closing connection\x0d\x0a"
-
-enum SMTPState
-{
-    SMTP_STATE_CONNECTION,
-    SMTP_STATE_HELO,
-    SMTP_STATE_TRANSFER,
-    SMTP_STATE_CONNECTION_ERROR,
-    SMTP_STATE_STARTTLS
-};
-
-struct ServiceSMTPData
-{
-    SMTPState state;
-    int code;
-    int multiline;
-    int set_flags;
-};
-
-#pragma pack(1)
-
-struct ServiceSMTPCode
-{
-    uint8_t code[3];
-    uint8_t sp;
-};
-
-#pragma pack()
-
-static int smtp_init(const IniServiceAPI* const init_api);
-static int smtp_validate(ServiceValidationArgs* args);
-
-static const RNAServiceElement svc_element =
-{
-    nullptr,
-    &smtp_validate,
-    nullptr,
-    DETECTOR_TYPE_DECODER,
-    1,
-    1,
-    0,
-    "smtp"
-};
-
-static const RNAServiceValidationPort pp[] =
-{
-    { &smtp_validate, 25, IpProtocol::TCP, 0 },
-    { nullptr, 0, IpProtocol::PROTO_NOT_SET, 0 }
-};
-
-RNAServiceValidationModule smtp_service_mod =
-{
-    "SMTP",
-    &smtp_init,
-    pp,
-    nullptr,
-    nullptr,
-    0,
-    nullptr,
-    0
-};
-
-static AppRegistryEntry appIdRegistry[] =
-{
-    { APP_ID_SMTP,  0 },
-    { APP_ID_SMTPS, 0 }
-};
-
-static int smtp_init(const IniServiceAPI* const init_api)
-{
-    const char SMTP_PATTERN1[] = "220 ";
-    const char SMTP_PATTERN2[] = "220-";
-    const char SMTP_PATTERN3[] = "SMTP";
-    const char SMTP_PATTERN4[] = "smtp";
-
-    init_api->RegisterPattern(&smtp_validate, IpProtocol::TCP, (uint8_t*)SMTP_PATTERN1,
-        sizeof(SMTP_PATTERN1) - 1, 0, "smtp");
-    init_api->RegisterPattern(&smtp_validate, IpProtocol::TCP, (uint8_t*)SMTP_PATTERN2,
-        sizeof(SMTP_PATTERN2) - 1, 0, "smtp");
-    init_api->RegisterPattern(&smtp_validate, IpProtocol::TCP, (uint8_t*)SMTP_PATTERN3,
-        sizeof(SMTP_PATTERN3) - 1, -1, "smtp");
-    init_api->RegisterPattern(&smtp_validate, IpProtocol::TCP, (uint8_t*)SMTP_PATTERN4,
-        sizeof(SMTP_PATTERN4) - 1, -1, "smtp");
-
-    unsigned i;
-    for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
-    {
-        DebugFormat(DEBUG_LOG,"registering appId: %d\n",appIdRegistry[i].appId);
-        init_api->RegisterAppId(&smtp_validate, appIdRegistry[i].appId,
-            appIdRegistry[i].additionalInfo);
-    }
-
-    return 0;
-}
-
-static int smtp_validate_reply(const uint8_t* data, uint16_t* offset,
-    uint16_t size, int* multi, int* code)
-{
-    const ServiceSMTPCode* code_hdr;
-    int tmp;
-
-    /* Trim any blank lines (be a little tolerant) */
-    for (; *offset<size; (*offset)++)
-    {
-        if (data[*offset] != 0x0D && data[*offset] != 0x0A)
-            break;
-    }
-
-    if (size - *offset < (int)sizeof(ServiceSMTPCode))
-    {
-        for (; *offset<size; (*offset)++)
-        {
-            if (!isspace(data[*offset]))
-                return -1;
-        }
-        return 0;
-    }
-
-    code_hdr = (ServiceSMTPCode*)(data + *offset);
-
-    if (code_hdr->code[0] < '1' || code_hdr->code[0] > '5')
-        return -1;
-    tmp = (code_hdr->code[0] - '0') * 100;
-
-    if (code_hdr->code[1] < '0' || code_hdr->code[1] > '5')
-        return -1;
-    tmp += (code_hdr->code[1] - '0') * 10;
-
-    if (!isdigit(code_hdr->code[2]))
-        return -1;
-    tmp += code_hdr->code[2] - '0';
-
-    if (*multi && tmp != *code)
-        return -1;
-    *code = tmp;
-    if (code_hdr->sp == '-')
-        *multi = 1;
-    else if (code_hdr->sp == ' ')
-        *multi = 0;
-    else
-        return -1;
-
-    /* We have a valid code, now we need to see if the rest of the line
-        is okay */
-
-    *offset += sizeof(ServiceSMTPCode);
-    for (; *offset < size; (*offset)++)
-    {
-        if (data[*offset] == 0x0D)
-        {
-            (*offset)++;
-            if (*offset >= size)
-                return -1;
-            if (data[*offset] != 0x0A)
-                return -1;
-        }
-        if (data[*offset] == 0x0A)
-        {
-            if (*multi)
-            {
-                if ((*offset + 1) >= size)
-                    return 0;
-
-                if (size - (*offset + 1) < (int)sizeof(ServiceSMTPCode))
-                    return -1;
-
-                code_hdr = (ServiceSMTPCode*)(data + *offset + 1);
-
-                if (code_hdr->code[0] < '1' || code_hdr->code[0] > '5')
-                    return -1;
-                tmp = (code_hdr->code[0] - '0') * 100;
-
-                if (code_hdr->code[1] < '1' || code_hdr->code[1] > '5')
-                    return -1;
-                tmp += (code_hdr->code[1] - '0') * 10;
-
-                if (!isdigit(code_hdr->code[2]))
-                    return -1;
-                tmp += code_hdr->code[2] - '0';
-
-                if (tmp != *code)
-                    return -1;
-
-                if (code_hdr->sp == ' ')
-                    *multi = 0;
-                else if (code_hdr->sp != '-')
-                    return -1;
-
-                *offset += sizeof(ServiceSMTPCode);
-            }
-            else
-            {
-                (*offset)++;
-                return *code;
-            }
-        }
-        else if (!isprint(data[*offset]))
-            return -1;
-    }
-
-    return 0;
-}
-
-static int smtp_validate(ServiceValidationArgs* args)
-{
-    ServiceSMTPData* fd;
-    AppIdSession* asd = args->asd;
-    const uint8_t* data = args->data;
-    uint16_t size = args->size;
-    uint16_t offset;
-
-    if (!size)
-        goto inprocess;
-    if (args->dir != APP_ID_FROM_RESPONDER)
-        goto inprocess;
-
-    fd = (ServiceSMTPData*)smtp_service_mod.api->data_get(asd, smtp_service_mod.flow_data_index);
-    if (!fd)
-    {
-        fd = (ServiceSMTPData*)snort_calloc(sizeof(ServiceSMTPData));
-        smtp_service_mod.api->data_add(asd, fd, smtp_service_mod.flow_data_index, &snort_free);
-        fd->state = SMTP_STATE_CONNECTION;
-    }
-    else
-    {
-        if (asd->get_session_flags(APPID_SESSION_ENCRYPTED) && fd->state == SMTP_STATE_TRANSFER)
-        {
-            fd->state = SMTP_STATE_STARTTLS;
-        }
-    }
-
-    if (!fd->set_flags)
-    {
-        fd->set_flags = 1;
-        asd->set_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
-    }
-
-    offset = 0;
-    while (offset < size)
-    {
-        if (smtp_validate_reply(data, &offset, size, &fd->multiline, &fd->code) < 0)
-            goto fail;
-        if (!fd->code)
-            goto inprocess;
-        switch (fd->state)
-        {
-        case SMTP_STATE_CONNECTION:
-            switch (fd->code)
-            {
-            case 220:
-                fd->state = SMTP_STATE_HELO;
-                break;
-            case 421:
-                if (service_strstr(data, size, (const uint8_t*)SMTP_CLOSING_CONN,
-                    sizeof(SMTP_CLOSING_CONN)-1))
-                    goto success;
-            case 520:
-                fd->state = SMTP_STATE_CONNECTION_ERROR;
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        case SMTP_STATE_HELO:
-            switch (fd->code)
-            {
-            case 250:
-                fd->state = SMTP_STATE_TRANSFER;
-                break;
-            case 500:
-            case 501:
-            case 504:
-                break;
-            case 421:
-            case 553:
-                fd->state = SMTP_STATE_CONNECTION_ERROR;
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        case SMTP_STATE_STARTTLS:
-            if (fd->code == 220)
-                goto success;
-            /* STARTTLS failed. */
-            asd->clear_session_flags(APPID_SESSION_ENCRYPTED); // not encrypted after all
-            fd->state = SMTP_STATE_HELO; // revert the state
-            break;
-        case SMTP_STATE_TRANSFER:
-            goto success;
-        case SMTP_STATE_CONNECTION_ERROR:
-        default:
-            goto fail;
-        }
-    }
-
-inprocess:
-    smtp_service_mod.api->service_inprocess(asd, args->pkt, args->dir, &svc_element);
-    return SERVICE_INPROCESS;
-
-success:
-    smtp_service_mod.api->add_service(asd, args->pkt, args->dir, &svc_element,
-        fd->state == SMTP_STATE_STARTTLS ? APP_ID_SMTPS : APP_ID_SMTP,
-        nullptr, nullptr, nullptr);
-    if (fd->state == SMTP_STATE_STARTTLS)
-        appid_stats.smtps_flows++;
-    else
-        appid_stats.smtp_flows++;
-
-    return SERVICE_SUCCESS;
-
-fail:
-    smtp_service_mod.api->fail_service(asd, args->pkt, args->dir, &svc_element,
-        smtp_service_mod.flow_data_index);
-    return SERVICE_NOMATCH;
-}
-
index 0920046c23d8c1330a012e4887f42e0d03a6e51c..83dcc8b8f218646a91b62f1dacd36bbd16610b31 100644 (file)
@@ -85,7 +85,7 @@ struct ServiceSNMPHeader
 
 #pragma pack()
 
-static int snmp_init(const IniServiceAPI* const init_api);
+static int snmp_init(const InitServiceAPI* const init_api);
 static int snmp_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -131,7 +131,7 @@ static AppRegistryEntry appIdRegistry[] =
 
 static int16_t app_id = 0;
 
-static int snmp_init(const IniServiceAPI* const init_api)
+static int snmp_init(const InitServiceAPI* const init_api)
 {
     app_id = add_appid_protocol_reference("snmp");
 
index 8e67314dddbcfc6b23f399f4e862d7964d774b4a..e7182d47620dc67e698864c21caff773173321d9 100644 (file)
@@ -127,7 +127,7 @@ struct ServiceSSHKeyExchangeFinal
 
 #pragma pack()
 
-static int ssh_init(const IniServiceAPI* const init_api);
+static int ssh_init(const InitServiceAPI* const init_api);
 static int ssh_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -165,7 +165,7 @@ static const AppRegistryEntry appIdRegistry[] =
     { APP_ID_SSH, APPINFO_FLAG_SERVICE_ADDITIONAL }
 };
 
-static int ssh_init(const IniServiceAPI* const init_api)
+static int ssh_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&ssh_validate, IpProtocol::TCP, (uint8_t*)SSH_BANNER,
         sizeof(SSH_BANNER) - 1, 0, "ssh");
index 020e92e50b99684b555ad167f86b2081114881ef..2a6e93e2af4bb5734b3eaa56584356f511a78292 100644 (file)
@@ -260,7 +260,7 @@ int ssl_detector_process_patterns()
     return retVal;
 }
 
-static int ssl_init(const IniServiceAPI* const api);
+static int ssl_init(const InitServiceAPI* const api);
 static int ssl_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -329,7 +329,7 @@ static const AppRegistryEntry appIdRegistry[] =
     { APP_ID_SSL, APPINFO_FLAG_SERVICE_ADDITIONAL }
 };
 
-static int ssl_init(const IniServiceAPI* const init_api)
+static int ssl_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&ssl_validate, IpProtocol::TCP, SSL_PATTERN_PCT,
         sizeof(SSL_PATTERN_PCT), 2, "ssl");
index acc0455d9431e27f5ae7fd1f530abdeef1c25e08..9cf8ef67038540e49ccdf8581ef82bf49d7f0a7e 100644 (file)
@@ -68,7 +68,7 @@ struct ServiceTelnetData
     unsigned count;
 };
 
-static int telnet_init(const IniServiceAPI* const init_api);
+static int telnet_init(const InitServiceAPI* const init_api);
 static int telnet_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -107,7 +107,7 @@ static const AppRegistryEntry appIdRegistry[] =
     { APP_ID_TELNET, 0 }
 };
 
-static int telnet_init(const IniServiceAPI* const init_api)
+static int telnet_init(const InitServiceAPI* const init_api)
 {
     for (unsigned i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
     {
index 04ef1e86774e0340e0588f346a46174d9de4f13a..1ac017f27b0fd44171a7c33e77367f4b26e56f0c 100644 (file)
@@ -76,7 +76,7 @@ struct ServiceTFTPHeader
 
 #pragma pack()
 
-static int tftp_init(const IniServiceAPI* const api);
+static int tftp_init(const InitServiceAPI* const api);
 static int tftp_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -116,7 +116,7 @@ static const AppRegistryEntry appIdRegistry[] =
 
 static int16_t app_id = 0;
 
-static int tftp_init(const IniServiceAPI* const init_api)
+static int tftp_init(const InitServiceAPI* const init_api)
 {
     app_id = add_appid_protocol_reference("tftp");
 
index 5e6e1a52671fcb57054ad1972b1af8c543bb969e..13d3b1fc9cd7b772fe927da816b8fd18e395e617 100644 (file)
@@ -58,7 +58,7 @@ struct ServiceTIMBUKTUMsg
 };
 #pragma pack()
 
-static int timbuktu_init(const IniServiceAPI* const init_api);
+static int timbuktu_init(const InitServiceAPI* const init_api);
 static int timbuktu_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -96,7 +96,7 @@ static const AppRegistryEntry appIdRegistry[] =
     { APP_ID_TIMBUKTU, 0 }
 };
 
-static int timbuktu_init(const IniServiceAPI* const init_api)
+static int timbuktu_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&timbuktu_validate, IpProtocol::TCP,
             (const uint8_t*)TIMBUKTU_BANNER, sizeof(TIMBUKTU_BANNER) - 1,
index 3f0874ded631745352340ae367597c576a96cdf7..7da715d4e9cb89f7d39edff252723b40a9dca627 100644 (file)
@@ -87,7 +87,7 @@ struct ServiceTNSMsg
 };
 #pragma pack()
 
-static int tns_init(const IniServiceAPI* const init_api);
+static int tns_init(const InitServiceAPI* const init_api);
 static int tns_validate(ServiceValidationArgs* args);
 
 static const RNAServiceElement svc_element =
@@ -125,7 +125,7 @@ static const AppRegistryEntry appIdRegistry[] =
     { APP_ID_ORACLE_TNS, APPINFO_FLAG_SERVICE_ADDITIONAL },
 };
 
-static int tns_init(const IniServiceAPI* const init_api)
+static int tns_init(const InitServiceAPI* const init_api)
 {
     init_api->RegisterPattern(&tns_validate, IpProtocol::TCP, (const uint8_t*)TNS_BANNER,
         TNS_BANNER_LEN, 2, svc_name);
index 34f219a753cfa359e2bd368302c35e826947d0ad..90dd451bc607d78c7c06e25c23c0ba9cf921c10e 100644 (file)
@@ -57,12 +57,14 @@ FlowData::~FlowData()
 void Flow::set_application_ids(AppId, AppId, AppId, AppId) { }
 
 const char *content_type = nullptr;
+const char *cookie = nullptr;
 const char *host = nullptr;
+const char *location = nullptr;
 const char *referer = nullptr;
 int32_t response_code = 0;
 const char *server = nullptr;
 const char *x_working_with = nullptr;
-const char *url = nullptr;
+const char *uri = nullptr;
 const char *useragent = nullptr;
 const char *via = nullptr;
 
@@ -85,6 +87,12 @@ const Field& HttpMsgSection::get_classic_buffer(unsigned id, uint64_t sub_id, ui
                 global_field.set(strlen(host), (const uint8_t*)host);
         }
 
+        if(sub_id == HttpEnums::HEAD_COOKIE)
+        {
+            if(cookie)
+                global_field.set(strlen(cookie), (const uint8_t*)cookie);
+        }
+
         if(sub_id == HttpEnums::HEAD_USER_AGENT)
         {
             if(useragent)
@@ -120,14 +128,20 @@ const Field& HttpMsgSection::get_classic_buffer(unsigned id, uint64_t sub_id, ui
             if(content_type)
                 global_field.set(strlen(content_type), (const uint8_t*)content_type);
         }
+
+        if(sub_id == HttpEnums::HEAD_LOCATION)
+        {
+            if(location)
+                global_field.set(strlen(location), (const uint8_t*)location);
+        }
     }
 
     if(id == HttpEnums::HTTP_BUFFER_URI)
     {
         if(sub_id == 0)
         {
-            if(url)
-                global_field.set(strlen(url), (const uint8_t*)url);
+            if(uri)
+                global_field.set(strlen(uri), (const uint8_t*)uri);
         }
     }
 
@@ -142,7 +156,7 @@ unsigned AppIdSession::flow_id = 0;
 AppIdSession *fake_session = nullptr;
 FakeHttpMsgHeader *fake_msg_header = nullptr;
 
-AppIdSession::AppIdSession(IpProtocol, const sfip_t*) : FlowData(flow_id, nullptr)
+AppIdSession::AppIdSession(IpProtocol, const sfip_t*, uint16_t) : FlowData(flow_id, nullptr)
 {
 }
 
@@ -151,15 +165,31 @@ AppIdSession::~AppIdSession()
     if(!hsession)
         return;
 
-    if(hsession->content_type) free(hsession->content_type);
-    if(hsession->host) free(hsession->host);
-    if(hsession->referer) free(hsession->referer);
-    if(hsession->response_code) free(hsession->response_code);
-    if(hsession->server) free(hsession->server);
-    if(hsession->url) free(hsession->url);
-    if(hsession->useragent) free(hsession->useragent);
-    if(hsession->via) free(hsession->via);
-    if(hsession->x_working_with) free(hsession->x_working_with);
+    if(hsession->content_type)
+        free(hsession->content_type);
+    if(hsession->cookie)
+        free(hsession->cookie);
+    if(hsession->host)
+        free(hsession->host);
+    if(hsession->location)
+        free(hsession->location);
+    if(hsession->referer)
+        free(hsession->referer);
+    if(hsession->response_code)
+        free(hsession->response_code);
+    if(hsession->server)
+        free(hsession->server);
+    if(hsession->uri)
+        free(hsession->uri);
+    if(hsession->url)
+        snort_free(hsession->url);
+    if(hsession->useragent)
+        free(hsession->useragent);
+    if(hsession->via)
+        free(hsession->via);
+    if(hsession->x_working_with)
+        free(hsession->x_working_with);
+
     snort_free(hsession);
 }
 
@@ -194,7 +224,7 @@ AppIdSession* AppIdApi::get_appid_data(Flow*)
     return fake_session;
 }
 
-const uint8_t* HttpEvent::get_content_type(unsigned &length)
+const uint8_t* HttpEvent::get_content_type(int32_t &length)
 {
     global_field.set(0, nullptr);
     if(content_type)
@@ -203,7 +233,16 @@ const uint8_t* HttpEvent::get_content_type(unsigned &length)
     return global_field.start;
 }
 
-const uint8_t* HttpEvent::get_host(unsigned &length)
+const uint8_t* HttpEvent::get_cookie(int32_t &length)
+{
+    global_field.set(0, nullptr);
+    if(cookie)
+        global_field.set(strlen(cookie), (const uint8_t*)cookie);
+    length = global_field.length;
+    return global_field.start;
+}
+
+const uint8_t* HttpEvent::get_host(int32_t &length)
 {
     global_field.set(0, nullptr);
     if(host)
@@ -212,7 +251,16 @@ const uint8_t* HttpEvent::get_host(unsigned &length)
     return global_field.start;
 }
 
-const uint8_t* HttpEvent::get_referer(unsigned &length)
+const uint8_t* HttpEvent::get_location(int32_t &length)
+{
+    global_field.set(0, nullptr);
+    if(location)
+        global_field.set(strlen(location), (const uint8_t*)location);
+    length = global_field.length;
+    return global_field.start;
+}
+
+const uint8_t* HttpEvent::get_referer(int32_t &length)
 {
     global_field.set(0, nullptr);
     if(referer)
@@ -226,7 +274,7 @@ int32_t HttpEvent::get_response_code()
     return response_code;
 }
 
-const uint8_t* HttpEvent::get_server(unsigned &length)
+const uint8_t* HttpEvent::get_server(int32_t &length)
 {
     global_field.set(0, nullptr);
     if(server)
@@ -235,16 +283,16 @@ const uint8_t* HttpEvent::get_server(unsigned &length)
     return global_field.start;
 }
 
-const uint8_t* HttpEvent::get_uri(unsigned &length)
+const uint8_t* HttpEvent::get_uri(int32_t &length)
 {
     global_field.set(0, nullptr);
-    if(url)
-        global_field.set(strlen(url), (const uint8_t*)url);
+    if(uri)
+        global_field.set(strlen(uri), (const uint8_t*)uri);
     length = global_field.length;
     return global_field.start;
 }
 
-const uint8_t* HttpEvent::get_user_agent(unsigned &length)
+const uint8_t* HttpEvent::get_user_agent(int32_t &length)
 {
     global_field.set(0, nullptr);
     if(useragent)
@@ -253,7 +301,7 @@ const uint8_t* HttpEvent::get_user_agent(unsigned &length)
     return global_field.start;
 }
 
-const uint8_t* HttpEvent::get_via(unsigned &length)
+const uint8_t* HttpEvent::get_via(int32_t &length)
 {
     global_field.set(0, nullptr);
     if(via)
@@ -262,7 +310,7 @@ const uint8_t* HttpEvent::get_via(unsigned &length)
     return global_field.start;
 }
 
-const uint8_t* HttpEvent::get_x_working_with(unsigned &length)
+const uint8_t* HttpEvent::get_x_working_with(int32_t &length)
 {
     global_field.set(0, nullptr);
     if(x_working_with)
@@ -311,7 +359,7 @@ TEST(appid_http_event, handle_null_msg_header)
 {
     FakeFlow flow;
     HttpEvent event(nullptr);
-    AppIdSession session(IpProtocol::TCP, nullptr);
+    AppIdSession session(IpProtocol::TCP, nullptr, 1492);
     HttpEventHandler event_handler(HttpEventHandler::REQUEST_EVENT);
     fake_session = &session;
 
@@ -322,8 +370,10 @@ TEST(appid_http_event, handle_null_msg_header)
 }
 
 #define CONTENT_TYPE "html/text"
+#define COOKIE "this is my request cookie content"
 #define HOST "www.google.com"
-#define URL "http://www.google.com/path/to/index.html"
+#define LOCATION "abc.yahoo.com"
+#define URI "/path/to/index.html"
 #define USERAGENT "Mozilla/5.0 (Macintosh; Intel Mac OS X)"
 #define REFERER "http://www.yahoo.com/search"
 #define RESPONSE_CODE 301
@@ -337,12 +387,14 @@ struct TestData
     unsigned scan_flags = 0;
     PegCount http_flows = 1;   // Default to 1 since most tests have 1.
     const char *content_type = nullptr;
+    const char *cookie = nullptr;
     const char *host = nullptr;
+    const char *location = nullptr;
     const char *referer = nullptr;
     int32_t response_code = 0;
     const char *server = nullptr;
     const char *x_working_with = nullptr;
-    const char *url = nullptr;
+    const char *uri = nullptr;
     const char *useragent = nullptr;
     const char *via = nullptr;
 };
@@ -351,20 +403,22 @@ void run_event_handler(TestData test_data, TestData *expect_data = nullptr)
 {
     FakeFlow flow;
     HttpEvent event(nullptr);
-    AppIdSession session(IpProtocol::TCP, nullptr);
+    AppIdSession session(IpProtocol::TCP, nullptr, 1492);
     FakeHttpMsgHeader http_msg_header;
     HttpEventHandler event_handler(test_data.type);
     fake_session = &session;
     fake_msg_header = &http_msg_header;
 
     host = test_data.host;
+    location = test_data.location;
     referer = test_data.referer;
     server = test_data.server;
     x_working_with = test_data.x_working_with;
-    url = test_data.url;
+    uri = test_data.uri;
     useragent = test_data.useragent;
     via = test_data.via;
     content_type = test_data.content_type;
+    cookie = test_data.cookie;
     response_code = test_data.response_code;
 
     if(expect_data == nullptr)
@@ -376,8 +430,10 @@ void run_event_handler(TestData test_data, TestData *expect_data = nullptr)
     LONGS_EQUAL(expect_data->scan_flags, session.scan_flags);
     LONGS_EQUAL(expect_data->http_flows, appid_stats.http_flows);
     STRCMP_EQUAL(expect_data->host, session.hsession->host);
-    STRCMP_EQUAL(expect_data->url, session.hsession->url);
+    STRCMP_EQUAL(expect_data->uri, session.hsession->uri);
     STRCMP_EQUAL(expect_data->content_type, session.hsession->content_type);
+    STRCMP_EQUAL(expect_data->cookie, session.hsession->cookie);
+    STRCMP_EQUAL(expect_data->location, session.hsession->location);
     STRCMP_EQUAL(expect_data->referer, session.hsession->referer);
     STRCMP_EQUAL(expect_data->server, session.hsession->server);
     STRCMP_EQUAL(expect_data->x_working_with, session.hsession->x_working_with);
@@ -412,12 +468,21 @@ TEST(appid_http_event, handle_msg_header_only_host)
     run_event_handler(test_data);
 }
 
-TEST(appid_http_event, handle_msg_header_host_and_url)
+TEST(appid_http_event, handle_msg_header_cookie)
+{
+    TestData test_data;
+    test_data.scan_flags = 0;
+    test_data.cookie = COOKIE;
+    
+    run_event_handler(test_data);
+}
+
+TEST(appid_http_event, handle_msg_header_host_and_uri)
 {
     TestData test_data;
     test_data.scan_flags = SCAN_HTTP_HOST_URL_FLAG;
     test_data.host = HOST;
-    test_data.url = URL;
+    test_data.uri = URI;
     
     run_event_handler(test_data);
 }
@@ -469,6 +534,17 @@ TEST(appid_http_event, handle_msg_header_content_type)
     run_event_handler(test_data);
 }
 
+TEST(appid_http_event, handle_msg_header_location)
+{
+    TestData test_data;
+    test_data.type = HttpEventHandler::RESPONSE_EVENT;
+    test_data.scan_flags = 0;
+    test_data.http_flows = 0;   //  Flows are only counted on request header
+    test_data.location = LOCATION;
+    
+    run_event_handler(test_data);
+}
+
 TEST(appid_http_event, handle_msg_header_server)
 {
     TestData test_data;
@@ -513,16 +589,18 @@ TEST(appid_http_event, handle_msg_header_all_response_headers)
     test_data.http_flows = 0;   //  Flows are only counted on request header
     test_data.response_code = RESPONSE_CODE;
     test_data.content_type = CONTENT_TYPE;
+    test_data.location = LOCATION;
     test_data.via = VIA;
 
     TestData expect_data = test_data;
 
     //  Fill in the request data too to demonstrate that it is not copied
     //  during response header handling.
-    test_data.url = URL;
+    test_data.uri = URI;
     test_data.host = HOST;
     test_data.referer = REFERER;
     test_data.useragent = USERAGENT;
+    test_data.cookie = COOKIE;
     
     run_event_handler(test_data, &expect_data);
 }
@@ -533,7 +611,8 @@ TEST(appid_http_event, handle_msg_header_all_request_headers)
     test_data.type = HttpEventHandler::REQUEST_EVENT;
     test_data.scan_flags = SCAN_HTTP_VIA_FLAG | SCAN_HTTP_USER_AGENT_FLAG |
         SCAN_HTTP_HOST_URL_FLAG;
-    test_data.url = URL;
+    test_data.uri = URI;
+    test_data.cookie = COOKIE;
     test_data.host = HOST;
     test_data.referer = REFERER;
     test_data.useragent = USERAGENT;
@@ -545,6 +624,7 @@ TEST(appid_http_event, handle_msg_header_all_request_headers)
     //  during response header handling.
     test_data.response_code = RESPONSE_CODE;
     test_data.content_type = CONTENT_TYPE;
+    test_data.location = LOCATION;
     
     run_event_handler(test_data, &expect_data);
 }
index 774d594ec128d5d50439d4ab163fc2f3bb35dfbb..437b4111bedbf7656a2dac642e5793e27a9f6f1d 100644 (file)
@@ -59,34 +59,54 @@ struct ThirdPartyAppIDAttributeData
 {
     char* spdyRequestPath;
     char* spdyRequestScheme;
-    char* spdyRequesHost;
-    char* httpRequesUrl;
+    char* spdyRequestHost;
+    char* httpRequestUrl;
     char* httpRequestUri;
+    uint16_t httpRequestUriLen;
     uint16_t httpRequestUriOffset;
     uint16_t httpRequestUriEndOffset;
-    char* httpRequesHost;
-    char* httpRequestCookie;
+    char *httpRequestHost;
+    uint16_t httpRequestHostLen;
+    char *httpRequestCookie;
+    uint16_t httpRequestCookieLen;
     uint16_t httpRequestCookieOffset;
     uint16_t httpRequestCookieEndOffset;
-    char* httpRequestVia;
-    char* httpResponseVia;
-    char* httpResponseUpgrade;
-    char* httpRequestUserAgent;
-    char* httpResponseVersion;
-    char* httpResponseCode;
-    char* httpResponseContent;
-    char* httpResponseLocation;
-    char* httpResponseBody;
-    char* httpRequestBody;
-    char* httpResponseServer;
-    char* httpRequestXWorkingWith;
-    char* tlsHost;
-    char* tlsCname;
-    char* tlsOrgUnit;
-    char* httpRequestReferer;
-    char* ftpCommandUser;
-    XffFieldValue xffFieldValue[HTTP_MAX_XFF_FIELDS];
+    char *httpRequestVia;
+    char *httpResponseVia;
+    char *httpResponseUpgrade;
+    char *httpRequestUserAgent;
+    uint16_t httpRequestUserAgentLen;
+    char *httpResponseVersion;
+    char *httpResponseCode;
+    uint16_t httpResponseCodeLen;
+    char *httpResponseContent;
+    uint16_t httpResponseContentLen;
+    char *httpResponseLocation;
+    uint16_t httpResponseLocationLen;
+    char *httpResponseBody;
+    uint16_t httpResponseBodyLen;
+    char *httpRequestBody;
+    uint16_t httpRequestBodyLen;
+    char *httpResponseServer;
+    char *httpRequestXWorkingWith;
+    char *tlsHost;
+    char *tlsCname;
+    char *tlsOrgUnit;
+    char *httpRequestReferer;
+    uint16_t httpRequestRefererLen;
+    char *ftpCommandUser;
+    struct XffFieldValue xffFieldValue[HTTP_MAX_XFF_FIELDS];
     uint8_t numXffFields;
+    uint16_t httpRequestUserAgentOffset;
+    uint16_t httpRequestUserAgentEndOffset;
+    uint16_t httpRequestHostOffset;
+    uint16_t httpRequestHostEndOffset;
+    uint16_t httpRequestRefererOffset;
+    uint16_t httpRequestRefererEndOffset;
+    uint16_t spdyRequestHostOffset;
+    uint16_t spdyRequestHostEndOffset;
+    uint16_t spdyRequestPathOffset;
+    uint16_t spdyRequestPathEndOffset;
 };
 
 #endif
index 1b2b58284f7f80b80e5d1d49b814ea5a3374f30f..a4881b903c2fe0d6eed8ea9de5410a8a622eab2e 100644 (file)
@@ -23,7 +23,7 @@
 #include "http_events.h"
 #include "service_inspectors/http_inspect/http_msg_header.h"
 
-const uint8_t* HttpEvent::get_header(unsigned id, uint64_t sub_id, unsigned& length)
+const uint8_t* HttpEvent::get_header(unsigned id, uint64_t sub_id, int32_t& length)
 {
     Field field;
     field = http_msg_header->get_classic_buffer(id, sub_id, 0);
@@ -39,19 +39,31 @@ const uint8_t* HttpEvent::get_header(unsigned id, uint64_t sub_id, unsigned& len
     }
 }
 
-const uint8_t* HttpEvent::get_content_type(unsigned& length)
+const uint8_t* HttpEvent::get_content_type(int32_t& length)
 {
     return get_header(HttpEnums::HTTP_BUFFER_HEADER, 
         HttpEnums::HEAD_CONTENT_TYPE, length);
 }
 
-const uint8_t* HttpEvent::get_host(unsigned& length)
+const uint8_t* HttpEvent::get_cookie(int32_t& length)
+{
+    return get_header(HttpEnums::HTTP_BUFFER_HEADER, HttpEnums::HEAD_COOKIE,
+        length);
+}
+
+const uint8_t* HttpEvent::get_host(int32_t& length)
 {
     return get_header(HttpEnums::HTTP_BUFFER_HEADER, HttpEnums::HEAD_HOST,
         length);
 }
 
-const uint8_t* HttpEvent::get_referer(unsigned& length)
+const uint8_t* HttpEvent::get_location(int32_t& length)
+{
+    return get_header(HttpEnums::HTTP_BUFFER_HEADER, HttpEnums::HEAD_LOCATION,
+        length);
+}
+
+const uint8_t* HttpEvent::get_referer(int32_t& length)
 {
     return get_header(HttpEnums::HTTP_BUFFER_HEADER, HttpEnums::HEAD_REFERER,
         length);
@@ -62,30 +74,30 @@ int32_t HttpEvent::get_response_code()
     return http_msg_header->get_status_code();
 }
 
-const uint8_t* HttpEvent::get_server(unsigned& length)
+const uint8_t* HttpEvent::get_server(int32_t& length)
 {
     return get_header(HttpEnums::HTTP_BUFFER_HEADER, HttpEnums::HEAD_SERVER,
         length);
 }
 
-const uint8_t* HttpEvent::get_uri(unsigned& length)
+const uint8_t* HttpEvent::get_uri(int32_t& length)
 {
     return get_header(HttpEnums::HTTP_BUFFER_URI, 0, length);
 }
 
-const uint8_t* HttpEvent::get_user_agent(unsigned& length)
+const uint8_t* HttpEvent::get_user_agent(int32_t& length)
 {
     return get_header(HttpEnums::HTTP_BUFFER_HEADER, HttpEnums::HEAD_USER_AGENT,
         length);
 }
 
-const uint8_t* HttpEvent::get_via(unsigned& length)
+const uint8_t* HttpEvent::get_via(int32_t& length)
 {
     return get_header(HttpEnums::HTTP_BUFFER_HEADER, HttpEnums::HEAD_VIA, 
         length);
 }
 
-const uint8_t* HttpEvent::get_x_working_with(unsigned& length)
+const uint8_t* HttpEvent::get_x_working_with(int32_t& length)
 {
     return get_header(HttpEnums::HTTP_BUFFER_HEADER, 
         HttpEnums::HEAD_X_WORKING_WITH, length);
index 4223080263505beda6713164ec6aa372473fbb8e..f7f90729074520ca6c3b4c6fd3ebd115d045a18e 100644 (file)
@@ -40,20 +40,22 @@ public:
     {
     }
 
-    const uint8_t* get_content_type(unsigned &length);
-    const uint8_t* get_host(unsigned &length);
-    const uint8_t* get_referer(unsigned &length);
-    const uint8_t* get_server(unsigned &length);
-    const uint8_t* get_uri(unsigned &length);
-    const uint8_t* get_user_agent(unsigned &length);
-    const uint8_t* get_via(unsigned &length);
-    const uint8_t* get_x_working_with(unsigned &length);
+    const uint8_t* get_content_type(int32_t &length);
+    const uint8_t* get_cookie(int32_t &length);
+    const uint8_t* get_host(int32_t &length);
+    const uint8_t* get_location(int32_t &length);
+    const uint8_t* get_referer(int32_t &length);
+    const uint8_t* get_server(int32_t &length);
+    const uint8_t* get_uri(int32_t &length);
+    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);
     int32_t get_response_code();
 
 private:
     HttpMsgHeader* const http_msg_header;
 
-    const uint8_t* get_header(unsigned, uint64_t, unsigned&);
+    const uint8_t* get_header(unsigned, uint64_t, int32_t&);
 
 };