From: Russ Combs (rucombs) Date: Thu, 3 Nov 2016 15:52:54 +0000 (-0400) Subject: Merge pull request #683 in SNORT/snort3 from appid_sip to master X-Git-Tag: 3.0.0-233~204 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ea1fd13f1295c5068ac31ef4660be776f03b3152;p=thirdparty%2Fsnort3.git Merge pull request #683 in SNORT/snort3 from appid_sip to master Squashed commit of the following: commit e3763a9177b370e6de5e00a315b22a40321048ec Author: Carter Waxman Date: Wed Nov 2 11:05:16 2016 -0400 Updated build dependency fix commit f9a3162c78f4472b29928f981d1c1cfc0d3ea4c6 Author: Carter Waxman Date: Fri Oct 28 17:56:08 2016 -0400 fixed expect cache session data insertion commit e3c70ad588df032b1d0dc89bdcfc6090e88ffe58 Author: Carter Waxman Date: Fri Oct 21 11:06:48 2016 -0400 Encapsulated dialog commit cc96d7f938375a78519543f4fc68d735f7cac9eb Author: Carter Waxman Date: Wed Oct 19 12:03:03 2016 -0400 Encapsulated sipMsg commit c79a09e1f82b3698c1808ecb51f84e648687c5d5 Author: Carter Waxman Date: Fri Oct 14 14:58:13 2016 -0400 Implemented SipEventHandler --- diff --git a/src/flow/expect_cache.cc b/src/flow/expect_cache.cc index 30cd584b0..04162d242 100644 --- a/src/flow/expect_cache.cc +++ b/src/flow/expect_cache.cc @@ -346,7 +346,7 @@ int ExpectCache::add_flow(const Packet *ctrlPkt, last = nullptr; break; } - fd = fd->next; + lfd = lfd->next; } } } diff --git a/src/network_inspectors/appid/appid_inspector.cc b/src/network_inspectors/appid/appid_inspector.cc index 8cab9c50d..fd7aaedcc 100644 --- a/src/network_inspectors/appid/appid_inspector.cc +++ b/src/network_inspectors/appid/appid_inspector.cc @@ -44,6 +44,7 @@ #include "detector_plugins/detector_sip.h" #include "detector_plugins/detector_pattern.h" #include "appid_http_event_handler.h" +#include "pub_sub/sip_events.h" static void dump_appid_stats() { @@ -79,6 +80,7 @@ bool AppIdInspector::configure(SnortConfig*) get_data_bus().subscribe(HTTP_REQUEST_HEADER_EVENT_KEY, new HttpEventHandler(HttpEventHandler::REQUEST_EVENT)); get_data_bus().subscribe(HTTP_RESPONSE_HEADER_EVENT_KEY, new HttpEventHandler(HttpEventHandler::RESPONSE_EVENT)); + get_data_bus().subscribe(SIP_EVENT_TYPE_SIP_DIALOG_KEY, new SipEventHandler()); return active_config->init_appid(); @@ -86,11 +88,6 @@ bool AppIdInspector::configure(SnortConfig*) #ifdef REMOVED_WHILE_NOT_IN_USE _dpd.registerGeAppId(getOpenAppId); _dpd.registerSslAppIdLookup(sslAppGroupIdLookup); - - // FIXIT-M AppID will need to register for SIP events for sip detection to work... - if (_dpd.streamAPI->service_event_subscribe(PP_SIP, SIP_EVENT_TYPE_SIP_DIALOG, - SipSessionSnortCallback) == false) - DynamicPreprocessorFatalMessage("failed to subscribe to SIP_DIALOG\n"); #endif } diff --git a/src/network_inspectors/appid/appid_module.cc b/src/network_inspectors/appid/appid_module.cc index a0e9640bb..3cb005531 100644 --- a/src/network_inspectors/appid/appid_module.cc +++ b/src/network_inspectors/appid/appid_module.cc @@ -84,6 +84,8 @@ const PegInfo appid_pegs[] = { "rsync_flows", "count of rsync service flows discovered by appid" }, { "rtmp_flows", "count of rtmp flows discovered by appid" }, { "rtp_clients", "count of rtp clients discovered by appid" }, + { "sip_clients", "count of SIP clients discovered by appid" }, + { "sip_flows", "count of SIP flows discovered by appid" }, { "smtp_aol_clients", "count of AOL smtp clients discovered by appid" }, { "smtp_applemail_clients", "count of Apple Mail smtp clients discovered by appid" }, { "smtp_eudora_clients", "count of Eudora smtp clients discovered by appid" }, diff --git a/src/network_inspectors/appid/appid_module.h b/src/network_inspectors/appid/appid_module.h index 204e7b490..55516f69d 100644 --- a/src/network_inspectors/appid/appid_module.h +++ b/src/network_inspectors/appid/appid_module.h @@ -76,6 +76,8 @@ struct AppIdStats PegCount rsync_flows; PegCount rtmp_flows; PegCount rtp_clients; + PegCount sip_clients; + PegCount sip_flows; PegCount smtp_aol_clients; PegCount smtp_applemail_clients; PegCount smtp_eudora_clients; diff --git a/src/network_inspectors/appid/detector_plugins/detector_sip.cc b/src/network_inspectors/appid/detector_plugins/detector_sip.cc index 4fb0ff5fb..2a048bec2 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_sip.cc +++ b/src/network_inspectors/appid/detector_plugins/detector_sip.cc @@ -21,15 +21,18 @@ #include "detector_sip.h" -#include "http_url_patterns.h" +#include "appid/appid_module.h" +#include "appid_utils/sf_mlmp.h" #include "fw_appid.h" +#include "http_url_patterns.h" #include "service_plugins/service_base.h" -#include "appid_utils/sf_mlmp.h" #include "utils/util.h" #include "log/messages.h" #include "main/snort_debug.h" -#include "service_inspectors/sip/sip_common.h" +#include "pub_sub/sip_events.h" + +using namespace std; static const char SIP_REGISTER_BANNER[] = "REGISTER "; static const char SIP_INVITE_BANNER[] = "INVITE "; @@ -62,7 +65,7 @@ static const unsigned MAX_VENDOR_SIZE = 64; enum SIPState { - SIP_STATE_INIT=0, + SIP_STATE_INIT = 0, SIP_STATE_REGISTER, SIP_STATE_CALL }; @@ -78,12 +81,12 @@ enum tSIP_FLAGS struct ClientSIPData { - void* owner; - SIPState state; - uint32_t flags; - char* userName; - char* clientUserAgent; - char* from; + void* owner = nullptr; + SIPState state = SIP_STATE_INIT; + uint32_t flags = 0; + const string* user_name = nullptr; + const string* client_user_agent = nullptr; + const string* from = nullptr; }; struct DetectorSipConfig @@ -105,7 +108,7 @@ static CLIENT_APP_RETCODE sip_tcp_client_init(const InitClientAppAPI* const init 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); -static int get_sip_client_app(void* patternMatcher, char* pattern, uint32_t patternLen, +static int get_sip_client_app(void* patternMatcher, const char* pattern, uint32_t patternLen, AppId* ClientAppId, char** clientVersion); static void clean_sip_ua(); static void clean_sip_server(); @@ -300,25 +303,18 @@ static CLIENT_APP_RETCODE sip_tcp_client_init(const InitClientAppAPI* const init } static void clientDataFree(void* data) -{ - ClientSIPData* fd = (ClientSIPData*)data; - snort_free(fd->from); - snort_free(fd->clientUserAgent); - snort_free(fd->userName); - free (fd); -} +{ delete (ClientSIPData*)data; } // static const char* const SIP_USRNAME_BEGIN_MARKER = "data_get(asd, + ClientSIPData* fd = (ClientSIPData*)sip_udp_client_mod.api->data_get(asd, sip_udp_client_mod.flow_data_index); - if (!fd) + + if( !fd ) { - fd = (ClientSIPData*)snort_calloc(sizeof(ClientSIPData)); + fd = new ClientSIPData(); sip_udp_client_mod.api->data_add(asd, fd, sip_udp_client_mod.flow_data_index, &clientDataFree); fd->owner = &sip_udp_client_mod; @@ -350,7 +346,7 @@ static int sipAppAddPattern(DetectorAppSipPattern** patternList, AppId ClientApp return 0; } -int sipUaPatternAdd( AppId ClientAppId, const char* clientVersion, const char* pattern) +int sipUaPatternAdd(AppId ClientAppId, const char* clientVersion, const char* pattern) { return sipAppAddPattern(&detector_sip_config.sip_ua_list, ClientAppId, clientVersion, pattern); } @@ -368,18 +364,18 @@ int finalize_sip_ua() DetectorAppSipPattern* patternNode; detector_sip_config.sip_ua_matcher = mlmpCreate(); - if (!detector_sip_config.sip_ua_matcher) + if( !detector_sip_config.sip_ua_matcher ) return -1; detector_sip_config.sip_server_matcher = mlmpCreate(); - if (!detector_sip_config.sip_server_matcher) + if( !detector_sip_config.sip_server_matcher ) { mlmpDestroy((tMlmpTree*)detector_sip_config.sip_ua_matcher); detector_sip_config.sip_ua_matcher = nullptr; return -1; } - for (patternNode = detector_sip_config.sip_ua_list; patternNode; patternNode = patternNode->next) + for( patternNode = detector_sip_config.sip_ua_list; patternNode; patternNode = patternNode->next ) { num_patterns = parseMultipleHTTPPatterns((const char*)patternNode->pattern.pattern, patterns, PATTERN_PART_MAX, 0); @@ -388,7 +384,7 @@ int finalize_sip_ua() mlmpAddPattern((tMlmpTree*)detector_sip_config.sip_ua_matcher, patterns, patternNode); } - for (patternNode = detector_sip_config.sip_server_list; patternNode; patternNode = patternNode->next) + for( patternNode = detector_sip_config.sip_server_list; patternNode; patternNode = patternNode->next ) { num_patterns = parseMultipleHTTPPatterns((const char*)patternNode->pattern.pattern, patterns, PATTERN_PART_MAX, 0); @@ -406,13 +402,13 @@ static void clean_sip_ua() { DetectorAppSipPattern* node; - if (detector_sip_config.sip_ua_matcher) + if( detector_sip_config.sip_ua_matcher ) { mlmpDestroy((tMlmpTree*)detector_sip_config.sip_ua_matcher); detector_sip_config.sip_ua_matcher = nullptr; } - for (node = detector_sip_config.sip_ua_list; node; node = detector_sip_config.sip_ua_list) + for( node = detector_sip_config.sip_ua_list; node; node = detector_sip_config.sip_ua_list ) { detector_sip_config.sip_ua_list = node->next; snort_free((void*)node->pattern.pattern); @@ -425,13 +421,13 @@ static void clean_sip_server() { DetectorAppSipPattern* node; - if (detector_sip_config.sip_server_matcher) + if( detector_sip_config.sip_server_matcher ) { mlmpDestroy((tMlmpTree*)detector_sip_config.sip_server_matcher); detector_sip_config.sip_server_matcher = nullptr; } - for (node = detector_sip_config.sip_server_list; node; node = detector_sip_config.sip_server_list) + for( node = detector_sip_config.sip_server_list; node; node = detector_sip_config.sip_server_list ) { detector_sip_config.sip_server_list = node->next; snort_free((void*)node->pattern.pattern); @@ -440,13 +436,13 @@ static void clean_sip_server() } } -static int get_sip_client_app(void* patternMatcher, char* pattern, uint32_t patternLen, +static int get_sip_client_app(void* patternMatcher, const char* pattern, uint32_t patternLen, AppId* ClientAppId, char** clientVersion) { tMlmpPattern patterns[3]; DetectorAppSipPattern* data; - if (!pattern) + if( !pattern ) return 0; patterns[0].pattern = (uint8_t*)pattern; @@ -455,7 +451,7 @@ static int get_sip_client_app(void* patternMatcher, char* pattern, uint32_t patt data = (DetectorAppSipPattern*)mlmpMatchPatternGeneric((tMlmpTree*)patternMatcher, patterns); - if (data == nullptr) + if( !data ) return 0; *ClientAppId = data->userData.ClientAppId; @@ -471,7 +467,7 @@ static void createRtpFlow(AppIdSession* asd, const Packet* pkt, const sfip_t* cl fp = AppIdSession::create_future_session(pkt, cliIp, cliPort, srvIp, srvPort, proto, app_id, APPID_EARLY_SESSION_FLAG_FW_RULE); - if (fp) + if( fp ) { fp->client_app_id = asd->client_app_id; fp->payload_app_id = asd->payload_app_id; @@ -482,7 +478,7 @@ static void createRtpFlow(AppIdSession* asd, const Packet* pkt, const sfip_t* cl // create an RTCP flow as well fp2 = AppIdSession::create_future_session(pkt, cliIp, cliPort + 1, srvIp, srvPort + 1, proto, app_id, APPID_EARLY_SESSION_FLAG_FW_RULE); - if (fp2) + if( fp2 ) { fp2->client_app_id = asd->client_app_id; fp2->payload_app_id = asd->payload_app_id; @@ -491,41 +487,43 @@ static void createRtpFlow(AppIdSession* asd, const Packet* pkt, const sfip_t* cl } } -static int addFutureRtpFlows(AppIdSession* asd, const SipDialog* dialog, const Packet* p) +static void addFutureRtpFlows(SipEvent& event, AppIdSession* asd) { - SIP_MediaData* mdataA,* mdataB; + event.begin_media_sessions(); - // check the first media asd - if (nullptr == dialog->mediaSessions) - return -1; - // check the second media asd - if (nullptr == dialog->mediaSessions->nextS) - return -1; + auto session_a = event.next_media_session(); + auto session_b= event.next_media_session(); + + if( !session_a || !session_b ) + return; DebugFormat(DEBUG_SIP, "Adding future media sessions ID: %u and %u\n", - dialog->mediaSessions->sessionID, dialog->mediaSessions->nextS->sessionID); + session_b->get_id(), session_b->get_id()); - mdataA = dialog->mediaSessions->medias; - mdataB = dialog->mediaSessions->nextS->medias; - while ((nullptr != mdataA)&&(nullptr != mdataB)) + session_a->begin_media_data(); + session_b->begin_media_data(); + + auto media_a = session_a->next_media_data(); + auto media_b = session_b->next_media_data(); + + while( media_a && media_b ) { DebugFormat(DEBUG_SIP, "Adding future channels Source IP: %s Port: %hu\n", - sfip_to_str(&mdataA->maddress), mdataA->mport); + sfip_to_str(media_a->get_address()), media_a->get_port()); DebugFormat(DEBUG_SIP, "Adding future channels Destine IP: %s Port: %hu\n", - sfip_to_str(&mdataB->maddress), mdataB->mport); - - createRtpFlow(asd, p, &mdataA->maddress, mdataA->mport, &mdataB->maddress, - mdataB->mport, IpProtocol::UDP, APP_ID_RTP); - createRtpFlow(asd, p, &mdataB->maddress, mdataB->mport, &mdataA->maddress, - mdataA->mport, IpProtocol::UDP, APP_ID_RTP); - mdataA = mdataA->nextM; - mdataB = mdataB->nextM; + sfip_to_str(media_b->get_address()), media_b->get_port()); + + createRtpFlow(asd, event.get_packet(), media_a->get_address(), media_a->get_port(), + media_b->get_address(), media_b->get_port(), IpProtocol::UDP, APP_ID_RTP); + createRtpFlow(asd, event.get_packet(), media_b->get_address(), media_b->get_port(), + media_a->get_address(), media_b->get_port(), IpProtocol::UDP, APP_ID_RTP); + + media_a = session_a->next_media_data(); + media_b = session_b->next_media_data(); } - return 0; } -static void SipSessionCbClientProcess(const Packet* p, const SipHeaders* headers, const - SipDialog* dialog, AppIdSession* asd) +static void SipSessionCbClientProcess(SipEvent& event, AppIdSession* asd) { ClientSIPData* fd; AppId ClientAppId = APP_ID_SIP; @@ -534,78 +532,65 @@ static void SipSessionCbClientProcess(const Packet* p, const SipHeaders* headers fd = (ClientSIPData*)sip_udp_client_mod.api->data_get(asd, sip_udp_client_mod.flow_data_index); - if (!fd) + if( !fd ) { - fd = (ClientSIPData*)snort_calloc(sizeof(ClientSIPData)); + fd = new ClientSIPData(); sip_udp_client_mod.api->data_add(asd, fd, sip_udp_client_mod.flow_data_index, &clientDataFree); fd->owner = &sip_udp_client_mod; asd->set_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS); } - if (fd->owner != &sip_udp_client_mod && fd->owner != &sip_tcp_client_mod) + if( fd->owner != &sip_udp_client_mod && fd->owner != &sip_tcp_client_mod ) return; - direction = (p->is_from_client()) ? + direction = (event.get_packet()->is_from_client()) ? APP_ID_FROM_INITIATOR : APP_ID_FROM_RESPONDER; - if (headers->methodFlag == SIP_METHOD_INVITE && direction == APP_ID_FROM_INITIATOR) + if( event.is_invite() && direction == APP_ID_FROM_INITIATOR ) { - if (headers->from && headers->fromLen) - { - snort_free(fd->from); - fd->from = snort_strndup(headers->from, headers->fromLen); - } - - if (headers->userName && headers->userNameLen) - { - snort_free(fd->userName); - fd->userName = snort_strndup(headers->userName, headers->userNameLen); - } - if (headers->userAgent && headers->userAgentLen) - { - snort_free(fd->clientUserAgent); - fd->clientUserAgent = snort_strndup(headers->userAgent, headers->userAgentLen); - } + fd->from = event.get_from(); + fd->user_name = event.get_user_name(); + fd->client_user_agent = event.get_user_agent(); } - if (fd->clientUserAgent) + if( fd->client_user_agent ) { - if (get_sip_client_app(detector_sip_config.sip_ua_matcher, - fd->clientUserAgent, strlen(fd->clientUserAgent), &ClientAppId, &clientVersion)) + if( get_sip_client_app(detector_sip_config.sip_ua_matcher, + fd->client_user_agent->c_str(), fd->client_user_agent->size(), &ClientAppId, &clientVersion) ) goto success; } - if ( fd->from && !(fd->flags & SIP_FLAG_SERVER_CHECKED)) + if( fd->from && !(fd->flags & SIP_FLAG_SERVER_CHECKED) ) { fd->flags |= SIP_FLAG_SERVER_CHECKED; - if (get_sip_client_app(detector_sip_config.sip_server_matcher, - (char*)fd->from, strlen(fd->from), &ClientAppId, &clientVersion)) + if( get_sip_client_app(detector_sip_config.sip_server_matcher, + fd->from->c_str(), fd->from->size(), &ClientAppId, &clientVersion) ) goto success; } - if (!dialog || dialog->state != SIP_DLG_ESTABLISHED) + if( !event.is_dialog_established() ) return; success: //client detection successful sip_udp_client_mod.api->add_app(asd, APP_ID_SIP, ClientAppId, clientVersion); + appid_stats.sip_clients++; - if (fd->userName) - sip_udp_client_mod.api->add_user(asd, (char*)fd->userName, APP_ID_SIP, 1); + if( fd->user_name ) + sip_udp_client_mod.api->add_user(asd, fd->user_name->c_str(), APP_ID_SIP, 1); asd->set_session_flags(APPID_SESSION_CLIENT_DETECTED); } -static void SipSessionCbServiceProcess(const Packet* p, const SipHeaders* headers, const - SipDialog* dialog, AppIdSession* asd) +static void SipSessionCbServiceProcess(SipEvent& event, AppIdSession* asd) { ServiceSIPData* ss; int direction; ss = (ServiceSIPData*)sip_service_mod.api->data_get(asd, sip_service_mod.flow_data_index); - if (!ss) + if( !ss ) { ss = (ServiceSIPData*)snort_calloc(sizeof(ServiceSIPData)); sip_service_mod.api->data_add(asd, ss, sip_service_mod.flow_data_index, &snort_free); @@ -613,80 +598,42 @@ static void SipSessionCbServiceProcess(const Packet* p, const SipHeaders* header ss->serverPkt = 0; - direction = p->is_from_client() ? APP_ID_FROM_INITIATOR : APP_ID_FROM_RESPONDER; + direction = event.get_packet()->is_from_client() ? APP_ID_FROM_INITIATOR : APP_ID_FROM_RESPONDER; - if (direction == APP_ID_FROM_RESPONDER) + if( direction == APP_ID_FROM_RESPONDER ) { - if (headers->userAgent && headers->userAgentLen) + if( event.get_user_agent() ) { - memcpy(ss->vendor, headers->userAgent, - headers->userAgentLen > (MAX_VENDOR_SIZE - 1) ? (MAX_VENDOR_SIZE - 1) : - headers->userAgentLen); + memcpy(ss->vendor, event.get_user_agent()->c_str(), + event.get_user_agent()->size() > (MAX_VENDOR_SIZE - 1) ? (MAX_VENDOR_SIZE - 1) : + event.get_user_agent()->size()); } - else if (headers->server && headers->serverLen) + else if( event.get_server() ) { - memcpy(ss->vendor, headers->server, - headers->serverLen > (MAX_VENDOR_SIZE - 1) ? (MAX_VENDOR_SIZE - 1) : - headers->serverLen); + memcpy(ss->vendor, event.get_server()->c_str(), + event.get_server()->size() > (MAX_VENDOR_SIZE - 1) ? (MAX_VENDOR_SIZE - 1) : + event.get_server()->size()); } } - if (!dialog) + if( !event.has_dialog() ) return; - if (dialog->mediaUpdated) - addFutureRtpFlows(asd, dialog, p); + if( event.is_media_updated() ) + addFutureRtpFlows(event, asd); - if (dialog->state == SIP_DLG_ESTABLISHED) + if( event.is_dialog_established() ) { - if (!asd->get_session_flags(APPID_SESSION_SERVICE_DETECTED)) + if( !asd->get_session_flags(APPID_SESSION_SERVICE_DETECTED) ) { asd->set_session_flags(APPID_SESSION_CONTINUE); - sip_service_mod.api->add_service(asd, p, direction, &svc_element, + sip_service_mod.api->add_service(asd, event.get_packet(), direction, &svc_element, APP_ID_SIP, ss->vendor[0] ? ss->vendor : nullptr, nullptr, nullptr); + appid_stats.sip_flows++; } } } -void SipSessionSnortCallback(void*, ServiceEventType, void* data) -{ - AppIdSession* asd = nullptr; - SipEventData* eventData = (SipEventData*)data; - - const Packet* p = eventData->packet; - const SipHeaders* headers = eventData->headers; - const SipDialog* dialog = eventData->dialog; - -#ifdef DEBUG_APP_ID_SESSIONS - { - char src_ip[INET6_ADDRSTRLEN]; - char dst_ip[INET6_ADDRSTRLEN]; - const sfip_t* ip; - - src_ip[0] = 0; - ip = p->ptrs.ip_api.get_src(); - sfip_ntop(ip, src_ip, sizeof(src_ip)); - dst_ip[0] = 0; - ip = p->ptrs.ip_api.get_dst(); - sfip_ntop(ip, dst_ip, sizeof(dst_ip)); - fprintf(SF_DEBUG_FILE, "AppId Sip Snort Callback Session %s-%u -> %s-%u %d\n", src_ip, - (unsigned)p->src_port, dst_ip, (unsigned)p->dst_port, IsTCP(p) ? IpProtocol::TCP : - IpProtocol::UDP); - } -#endif - if(p->flow) - asd = appid_api.get_appid_data(p->flow); - - if(!asd) - { - WarningMessage("AppId Session does not exist.\n"); - return; - } - - SipSessionCbClientProcess(p, headers, dialog, asd); - SipSessionCbServiceProcess(p, headers, dialog, asd); -} - static int sip_service_init(const InitServiceAPI* const init_api) { init_api->RegisterPattern(&sip_service_validate, IpProtocol::UDP, @@ -765,3 +712,35 @@ static int sip_service_validate(ServiceValidationArgs* args) return SERVICE_INPROCESS; } +void SipEventHandler::handle(DataEvent& event, Flow* flow) +{ + AppIdSession* asd = nullptr; + +#ifdef DEBUG_APP_ID_SESSIONS + { + char src_ip[INET6_ADDRSTRLEN]; + char dst_ip[INET6_ADDRSTRLEN]; + const sfip_t* ip; + + src_ip[0] = 0; + ip = p->ptrs.ip_api.get_src(); + sfip_ntop(ip, src_ip, sizeof(src_ip)); + dst_ip[0] = 0; + ip = p->ptrs.ip_api.get_dst(); + sfip_ntop(ip, dst_ip, sizeof(dst_ip)); + fprintf(SF_DEBUG_FILE, "AppId Sip Snort Callback Session %s-%u -> %s-%u %d\n", src_ip, + (unsigned)p->src_port, dst_ip, (unsigned)p->dst_port, IsTCP(p) ? IpProtocol::TCP : + IpProtocol::UDP); + } +#endif + if( flow ) + asd = appid_api.get_appid_data(flow); + + if( !asd ) + return; + + SipSessionCbClientProcess((SipEvent&)event, asd); + SipSessionCbServiceProcess((SipEvent&)event, asd); +} + + diff --git a/src/network_inspectors/appid/detector_plugins/detector_sip.h b/src/network_inspectors/appid/detector_plugins/detector_sip.h index deb5b6e8c..23eb96e87 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_sip.h +++ b/src/network_inspectors/appid/detector_plugins/detector_sip.h @@ -24,8 +24,9 @@ // AppId structures for SIP detection -#include "detector_api.h" #include "appid_utils/sf_multi_mpse.h" +#include "detector_api.h" +#include "framework/data_bus.h" struct RNAServiceValidationModule; @@ -53,5 +54,11 @@ void SipSessionSnortCallback(void* ssnptr, ServiceEventType, void* eventData); int sipUaPatternAdd( AppId, const char* clientVersion, const char* uaPattern); int sipServerPatternAdd(AppId, const char* clientVersion, const char* uaPattern); int finalize_sip_ua(); + +class SipEventHandler : public DataHandler +{ +public: + void handle(DataEvent&, Flow*); +}; #endif diff --git a/src/pub_sub/CMakeLists.txt b/src/pub_sub/CMakeLists.txt index 68862c27f..5989a6b75 100644 --- a/src/pub_sub/CMakeLists.txt +++ b/src/pub_sub/CMakeLists.txt @@ -1,4 +1,6 @@ add_library( pub_sub STATIC http_events.cc http_events.h + sip_events.cc + sip_events.h ) diff --git a/src/pub_sub/Makefile.am b/src/pub_sub/Makefile.am index f52d3b369..4421082d6 100644 --- a/src/pub_sub/Makefile.am +++ b/src/pub_sub/Makefile.am @@ -3,9 +3,10 @@ noinst_LIBRARIES = libpub_sub.a libpub_sub_a_SOURCES = \ http_events.cc \ -http_events.h +http_events.h \ +sip_events.cc \ +sip_events.h #if ENABLE_UNIT_TESTS #SUBDIRS = test #endif - diff --git a/src/pub_sub/sip_events.cc b/src/pub_sub/sip_events.cc new file mode 100644 index 000000000..cd7829fb5 --- /dev/null +++ b/src/pub_sub/sip_events.cc @@ -0,0 +1,114 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +// sip_events.cc author Carter Waxman + +#include "sip_events.h" + +#include "service_inspectors/sip/sip_common.h" +#include "service_inspectors/sip/sip_dialog.h" + +using namespace std; + +SipEvent::SipEvent(const Packet* p, const SIPMsg* msg, const SIP_DialogData* dialog) +{ + this->p = p; + this->msg = msg; + this->dialog = dialog; + + if( msg->from ) + from = string(msg->from, msg->fromLen); + + if( msg->userName ) + user_name = string(msg->userName, msg->userNameLen); + + if( msg->userAgent ) + user_agent = string(msg->userAgent, msg->userAgentLen); + + if( msg->server ) + server = string(msg->server, msg->serverLen); +} + +SipEvent::~SipEvent() +{ + for( auto& session : sessions ) + delete session; +} + +bool SipEvent::is_invite() const +{ return msg->methodFlag == SIP_METHOD_INVITE; } + +bool SipEvent::is_media_updated() const +{ return msg->mediaUpdated; } + +bool SipEvent::has_dialog() const +{ return dialog; } + +bool SipEvent::is_dialog_established() const +{ return has_dialog() && dialog->state == SIP_DLG_ESTABLISHED; } + +void SipEvent::begin_media_sessions() +{ + if( has_dialog() ) + current_media_session = dialog->mediaSessions; +} + +SipEventMediaSession* SipEvent::next_media_session() +{ + if( !current_media_session ) + return nullptr; + + auto session = new SipEventMediaSession(current_media_session); + sessions.push_front(session); + + current_media_session = current_media_session->nextS; + + return session; +} + + +SipEventMediaSession::~SipEventMediaSession() +{ + for( auto& d : data ) + delete d; +} + +uint32_t SipEventMediaSession::get_id() const +{ return session->sessionID; } + +void SipEventMediaSession::begin_media_data() +{ current_media_data = session->medias; } + +SipEventMediaData* SipEventMediaSession::next_media_data() +{ + if( !current_media_data ) + return nullptr; + + auto d = new SipEventMediaData(current_media_data); + data.push_front(d); + + current_media_data = current_media_data->nextM; + + return d; +} + + +const sfip_t* SipEventMediaData::get_address() const +{ return &data->maddress; } + +uint16_t SipEventMediaData::get_port() const +{ return data->mport; } diff --git a/src/pub_sub/sip_events.h b/src/pub_sub/sip_events.h new file mode 100644 index 000000000..b956593f0 --- /dev/null +++ b/src/pub_sub/sip_events.h @@ -0,0 +1,120 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +// sip_events.h author Carter Waxman + +#ifndef SIP_EVENTS_H +#define SIP_EVENTS_H + +// This event conveys data published by the SIP service inspector to be consumed +// by data bus subscribers + +#include + +#include "framework/data_bus.h" +#include "protocols/packet.h" + +#define SIP_EVENT_TYPE_SIP_DIALOG_KEY "sip_event_type_sip_dialog" + +enum SipEventType +{ + SIP_EVENT_TYPE_SIP_DIALOG +}; + +struct SIPMsg; +struct SIP_DialogData; +struct SIP_MediaSession; +struct SIP_MediaData; + +class SipEventMediaData +{ +public: + SipEventMediaData(SIP_MediaData* data) + { this->data = data; } + + const sfip_t* get_address() const; + uint16_t get_port() const; + +private: + SIP_MediaData* data; +}; + +class SipEventMediaSession +{ +public: + SipEventMediaSession(SIP_MediaSession* session) + { this->session = session; } + + ~SipEventMediaSession(); + + uint32_t get_id() const; + + void begin_media_data(); + SipEventMediaData* next_media_data(); + +private: + SIP_MediaSession* session; + + std::list data; + SIP_MediaData* current_media_data = nullptr; +}; + +class SipEvent : public DataEvent +{ +public: + SipEvent(const Packet*, const SIPMsg*, const SIP_DialogData*); + ~SipEvent(); + + const Packet* get_packet() override + { return p; } + + const std::string* get_from() const + { return from.size() ? &from : nullptr; } + + const std::string* get_user_name() const + { return user_name.size() ? &user_name : nullptr; } + + const std::string* get_user_agent() const + { return user_agent.size() ? &user_agent : nullptr; } + + const std::string* get_server() const + { return server.size() ? &server : nullptr; } + + bool is_invite() const; + bool is_media_updated() const; + bool has_dialog() const; + bool is_dialog_established() const; + + void begin_media_sessions(); + SipEventMediaSession* next_media_session(); + +private: + const Packet* p; + + const SIPMsg* msg; + const SIP_DialogData* dialog; + + std::string from; + std::string user_name; + std::string user_agent; + std::string server; + + std::list sessions; + SIP_MediaSession* current_media_session = nullptr; +}; + +#endif diff --git a/src/service_inspectors/service_inspectors.cc b/src/service_inspectors/service_inspectors.cc index d3a14a004..f1b0a2812 100644 --- a/src/service_inspectors/service_inspectors.cc +++ b/src/service_inspectors/service_inspectors.cc @@ -27,7 +27,12 @@ extern const BaseApi* sin_imap; extern const BaseApi* sin_pop; extern const BaseApi* sin_smtp; +extern const BaseApi* sin_sip; extern const BaseApi* sin_ssl; +extern const BaseApi* ips_sip_body; +extern const BaseApi* ips_sip_header; +extern const BaseApi* ips_sip_method; +extern const BaseApi* ips_sip_stat_code; extern const BaseApi* ips_ssl_state; extern const BaseApi* ips_ssl_version; @@ -46,10 +51,6 @@ extern const BaseApi* ips_gtp_version; extern const BaseApi* ips_modbus_data; extern const BaseApi* ips_modbus_func; extern const BaseApi* ips_modbus_unit; -extern const BaseApi* ips_sip_body; -extern const BaseApi* ips_sip_header; -extern const BaseApi* ips_sip_method; -extern const BaseApi* ips_sip_stat_code; // FIXIT-L use snort_plugins aliases for static builds // so only one extern symbol per library is required @@ -82,7 +83,6 @@ extern const BaseApi* sin_gtp; extern const BaseApi* sin_modbus; extern const BaseApi* sin_http; extern const BaseApi* sin_rpc_decode; -extern const BaseApi* sin_sip; extern const BaseApi* sin_ssh; extern const BaseApi* sin_telnet; extern const BaseApi* sin_wizard; @@ -92,8 +92,14 @@ const BaseApi* service_inspectors[] = { sin_imap, sin_pop, + sin_sip, sin_smtp, sin_ssl, + + ips_sip_body, + ips_sip_header, + ips_sip_method, + ips_sip_stat_code, ips_ssl_state, ips_ssl_version, @@ -112,10 +118,6 @@ const BaseApi* service_inspectors[] = ips_modbus_data, ips_modbus_func, ips_modbus_unit, - ips_sip_body, - ips_sip_header, - ips_sip_method, - ips_sip_stat_code, ips_http_uri, ips_http_client_body, @@ -146,7 +148,6 @@ const BaseApi* service_inspectors[] = sin_modbus, sin_http, sin_rpc_decode, - sin_sip, sin_ssh, sin_telnet, sin_wizard, diff --git a/src/service_inspectors/sip/CMakeLists.txt b/src/service_inspectors/sip/CMakeLists.txt index 6bf263be0..2506f93d4 100644 --- a/src/service_inspectors/sip/CMakeLists.txt +++ b/src/service_inspectors/sip/CMakeLists.txt @@ -19,10 +19,11 @@ set( FILE_LIST ips_sip_method.cc ) -if (STATIC_INSPECTORS) +#FIXIT-M fix dependency loops +#if (STATIC_INSPECTORS) add_library( sip STATIC ${FILE_LIST}) -else (STATIC_INSPECTORS) - add_shared_library(sip inspectors ${FILE_LIST}) +#else (STATIC_INSPECTORS) +# add_shared_library(sip inspectors ${FILE_LIST}) -endif (STATIC_INSPECTORS) +#endif (STATIC_INSPECTORS) diff --git a/src/service_inspectors/sip/Makefile.am b/src/service_inspectors/sip/Makefile.am index ddec28ddf..3ed76b070 100644 --- a/src/service_inspectors/sip/Makefile.am +++ b/src/service_inspectors/sip/Makefile.am @@ -18,14 +18,14 @@ ips_sip.cc \ ips_sip_stat_code.cc \ ips_sip_method.cc -if STATIC_INSPECTORS +#if STATIC_INSPECTORS noinst_LIBRARIES = libsip.a libsip_a_SOURCES = $(file_list) -else -shlibdir = $(pkglibdir)/inspectors -shlib_LTLIBRARIES = libsip.la -libsip_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO -libsip_la_LDFLAGS = $(AM_LDFLAGS) -export-dynamic -shared -libsip_la_SOURCES = $(file_list) -endif +#else +#shlibdir = $(pkglibdir)/inspectors +#shlib_LTLIBRARIES = libsip.la +#libsip_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO +#libsip_la_LDFLAGS = $(AM_LDFLAGS) -export-dynamic -shared +#libsip_la_SOURCES = $(file_list) +#endif diff --git a/src/service_inspectors/sip/sip_common.h b/src/service_inspectors/sip/sip_common.h index e6c39fd5b..84d0b13b1 100644 --- a/src/service_inspectors/sip/sip_common.h +++ b/src/service_inspectors/sip/sip_common.h @@ -22,9 +22,11 @@ #ifndef SIP_COMMON_H #define SIP_COMMON_H +#include "framework/data_bus.h" + // Header containing datatypes/definitions shared by SSL inspector files. -typedef enum _SIP_method +enum SIPMethodsFlag { SIP_METHOD_NULL = 0, // 0x0000, SIP_METHOD_INVITE = 1, // 0x0001, @@ -43,7 +45,7 @@ typedef enum _SIP_method SIP_METHOD_PRACK = 14, // 0x2000, SIP_METHOD_USER_DEFINE = 15, // 0x4000, SIP_METHOD_USER_DEFINE_MAX = 32// 0x80000000, -} SIPMethodsFlag; +}; struct SipHeaders { @@ -103,17 +105,5 @@ struct SipDialog bool mediaUpdated; }; -struct SipEventData -{ - const Packet* packet; - const SipHeaders* headers; - const SipDialog* dialog; -}; - -enum SipEventType -{ - SIP_EVENT_TYPE_SIP_DIALOG -}; - #endif diff --git a/src/service_inspectors/sip/sip_dialog.cc b/src/service_inspectors/sip/sip_dialog.cc index 0e3d3fcc1..4b845bc54 100644 --- a/src/service_inspectors/sip/sip_dialog.cc +++ b/src/service_inspectors/sip/sip_dialog.cc @@ -31,6 +31,7 @@ #include "main/snort_config.h" #include "main/snort_debug.h" #include "main/snort_types.h" +#include "pub_sub/sip_events.h" #include "protocols/vlan.h" #include "sfip/sf_ip.h" #include "stream/stream.h" @@ -650,60 +651,11 @@ static int SIP_deleteDialog(SIP_DialogData* currDialog, SIP_DialogList* dList) return true; } -// FIXIT-H Publish event for appid -#if 0 -/********************************************************************* - * Update appId sip detector with parsed SIP message and dialog - * - * Arguments: - * Packet * - pointer to packet structure - * SIPMsg * - pointer to parserd SIP messgage - * SIPData * - pointer to SIP session - * - * Returns: - * None - * - *********************************************************************/ -static void sip_update_appid(const Packet* p, const SIPMsg* sipMsg, const SIP_DialogData* dialog) +static void sip_publish_data_bus(const Packet* p, const SIPMsg* sip_msg, const SIP_DialogData* dialog) { - SipHeaders hdrs; - SipDialog dlg; - SipEventData sipEventData; - - hdrs.callid = sipMsg->call_id; - hdrs.callidLen = sipMsg->callIdLen; - hdrs.methodFlag = sipMsg->methodFlag; - - hdrs.userAgent = sipMsg->userAgent; - hdrs.userAgentLen = sipMsg->userAgentLen; - hdrs.server = sipMsg->server; - hdrs.serverLen = sipMsg->serverLen; - hdrs.userName = sipMsg->userName; - hdrs.userNameLen = sipMsg->userNameLen; - hdrs.from = sipMsg->from; - hdrs.fromLen= sipMsg->fromLen; - - sipEventData.headers = &hdrs; - - if (dialog) - { - dlg.state = dialog->state; - dlg.mediaSessions = dialog->mediaSessions; - dlg.mediaUpdated = sipMsg->mediaUpdated; - sipEventData.dialog = &dlg; - } - else - { - sipEventData.dialog = NULL; - } - - sipEventData.packet = p; - - if (Stream::service_event_publish(PP_SIP, p->flow, SIP_EVENT_TYPE_SIP_DIALOG, &sipEventData) - == false) - ErrorMessage("failed to publish to SIP_DIALOG\n"); + SipEvent event(p, sip_msg, dialog); + get_data_bus().publish(SIP_EVENT_TYPE_SIP_DIALOG_KEY, event, p->flow); } -#endif /******************************************************************** * Function: SIP_updateDialog() @@ -722,10 +674,10 @@ static void sip_update_appid(const Packet* p, const SIPMsg* sipMsg, const SIP_Di int SIP_updateDialog(SIPMsg* sipMsg, SIP_DialogList* dList, Packet* p, SIP_PROTO_CONF* config) { SIP_DialogData* dialog; - SIP_DialogData* oldDialog = NULL; + SIP_DialogData* oldDialog = nullptr; int ret; - if ((NULL == sipMsg)||(0 == sipMsg->dlgID.callIdHash)) + if ((nullptr == sipMsg)||(0 == sipMsg->dlgID.callIdHash)) return false; DebugFormat(DEBUG_SIP, "Updating Dialog id: %u, From: %u, To: %u\n", @@ -735,7 +687,7 @@ int SIP_updateDialog(SIPMsg* sipMsg, SIP_DialogList* dList, Packet* p, SIP_PROTO /*Find out the dialog in the dialog list*/ - while (NULL != dialog) + while (nullptr != dialog) { DebugFormat(DEBUG_SIP, "Dialog id: %u, From: %u, To: %u\n", dialog->dlgID.callIdHash,dialog->dlgID.fromTagHash,dialog->dlgID.toTagHash); @@ -765,17 +717,12 @@ int SIP_updateDialog(SIPMsg* sipMsg, SIP_DialogList* dList, Packet* p, SIP_PROTO else ret = false; -// FIXIT-H Publish event for appid -#if 0 - for (dialog = dList->head; - dialog; - dialog = dialog->nextD) + for (dialog = dList->head; dialog; dialog = dialog->nextD) { if (sipMsg->dlgID.callIdHash == dialog->dlgID.callIdHash) break; } - sip_update_appid(p, sipMsg, dialog); -#endif + sip_publish_data_bus(p, sipMsg, dialog); return ret; }