📄 snort_stream5_udp.c
字号:
/**************************************************************************** * * Copyright (C) 2005-2008 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************/ #include "debug.h"#include "detect.h"#include "plugbase.h"#include "mstring.h"#include "sfxhash.h"#include "util.h"#include "decode.h"#include "stream5_common.h"#include "stream_api.h"#include "snort_stream5_session.h"#include "stream_ignore.h"#include "plugin_enum.h"#include "rules.h"#include "snort.h"#include "inline.h"#include "portscan.h" /* To know when to create sessions for all UDP */#include "dynamic-plugins/sp_dynamic.h"#include "profiler.h"#ifdef PERF_PROFILINGPreprocStats s5UdpPerfStats;#endif/* M A C R O S **************************************************//* actions */#define ACTION_NOTHING 0x00000000/* sender/responder ip/port dereference */#define udp_sender_ip lwSsn->client_ip#define udp_sender_port lwSsn->client_port#define udp_responder_ip lwSsn->server_ip#define udp_responder_port lwSsn->server_port/* D A T A S T R U C T U R E S ***********************************/typedef struct _UdpIgnoredRule{ OptTreeNode *otn; struct _UdpIgnoredRule *next;} UdpIgnoredRule;static UdpIgnoredRule *ignored_udp_rules = NULL;typedef struct _UdpSession{ Stream5LWSession *lwSsn; struct timeval ssn_time; //u_int8_t c_ttl; //u_int8_t s_ttl;} UdpSession;typedef struct _Stream5UdpPolicy{ u_int32_t session_timeout; u_int16_t flags; IpAddrSet *bound_addrs;} Stream5UdpPolicy;/* Mark specific ports as "to inspect, create session" */#define UDP_NONE 0x00#define UDP_INSPECT 0x01#define UDP_SESSION 0x02static u_int8_t udp_ports[MAX_PORTS+1];/* G L O B A L S **************************************************/static Stream5SessionCache *udp_lws_cache;static Stream5UdpPolicy **udpPolicyList = NULL; /* List of Policies configured */static u_int8_t numUdpPolicies = 0;static MemPool udp_session_mempool;/* P R O T O T Y P E S ********************************************/static void Stream5ParseUdpArgs(char *, Stream5UdpPolicy *);static void Stream5PrintUdpConfig(Stream5UdpPolicy *);void UdpSessionCleanup(Stream5LWSession *lwssn);static int ProcessUdp(Stream5LWSession *, Packet *, Stream5UdpPolicy *);void Stream5InitUdp(void){ /* Now UDP */ if((udp_lws_cache == NULL) && s5_global_config.track_udp_sessions) { udp_lws_cache = InitLWSessionCache(s5_global_config.max_udp_sessions, 30, 5, 0, &UdpSessionCleanup); if(!udp_lws_cache) { FatalError("Unable to init stream5 UDP session cache, no UDP " "stream inspection!\n"); } mempool_init(&udp_session_mempool, s5_global_config.max_udp_sessions, sizeof(UdpSession)); }}void Stream5UdpPolicyInit(char *args){ Stream5UdpPolicy *s5UdpPolicy; s5UdpPolicy = (Stream5UdpPolicy *) SnortAlloc(sizeof(Stream5UdpPolicy)); s5UdpPolicy->bound_addrs = (IpAddrSet *) SnortAlloc(sizeof(IpAddrSet)); Stream5ParseUdpArgs(args, s5UdpPolicy); /* Now add this context to the internal list */ if (udpPolicyList == NULL) { numUdpPolicies = 1; udpPolicyList = (Stream5UdpPolicy **)SnortAlloc(sizeof (Stream5UdpPolicy *) * numUdpPolicies); } else { Stream5UdpPolicy **tmpPolicyList = (Stream5UdpPolicy **)SnortAlloc(sizeof (Stream5UdpPolicy *) * (++numUdpPolicies)); memcpy(tmpPolicyList, udpPolicyList, sizeof(Stream5UdpPolicy *) * (numUdpPolicies-1)); free(udpPolicyList); udpPolicyList = tmpPolicyList; } udpPolicyList[numUdpPolicies-1] = s5UdpPolicy; Stream5PrintUdpConfig(s5UdpPolicy); return;}static void Stream5ParseUdpArgs(char *args, Stream5UdpPolicy *s5UdpPolicy){ char **toks; int num_toks; int i; char *index; char **stoks = NULL; int s_toks; char *endPtr = NULL; s5UdpPolicy->session_timeout = S5_DEFAULT_SSN_TIMEOUT; s5UdpPolicy->flags = 0; if(args != NULL && strlen(args) != 0) { toks = mSplit(args, ",", 6, &num_toks, 0); i=0; while(i < num_toks) { index = toks[i]; while(isspace((int)*index)) index++; stoks = mSplit(index, " ", 3, &s_toks, 0); if (s_toks == 0) { FatalError("%s(%d) => Missing parameter in Stream5 UDP config.\n", file_name, file_line); } if(!strcasecmp(stoks[0], "timeout")) { if(stoks[1]) { s5UdpPolicy->session_timeout = strtoul(stoks[1], &endPtr, 10); } if (!stoks[1] || (endPtr == &stoks[1][0])) { FatalError("%s(%d) => Invalid timeout in config file. Integer parameter required.\n", file_name, file_line); } if ((s5UdpPolicy->session_timeout > S5_MAX_SSN_TIMEOUT) || (s5UdpPolicy->session_timeout < S5_MIN_SSN_TIMEOUT)) { FatalError("%s(%d) => Invalid timeout in config file. " "Must be between %d and %d\n", file_name, file_line, S5_MIN_SSN_TIMEOUT, S5_MAX_SSN_TIMEOUT); } if (s_toks > 2) { FatalError("%s(%d) => Invalid Stream5 UDP Policy option. Missing comma?\n", file_name, file_line); } } else if (!strcasecmp(stoks[0], "ignore_any_rules")) { s5UdpPolicy->flags |= STREAM5_CONFIG_IGNORE_ANY; if (s_toks > 1) { FatalError("%s(%d) => Invalid Stream5 UDP Policy option. Missing comma?\n", file_name, file_line); } } else { FatalError("%s(%d) => Invalid Stream5 UDP Policy option\n", file_name, file_line); } mSplitFree(&stoks, s_toks); i++; } mSplitFree(&toks, num_toks); if(s5UdpPolicy->bound_addrs == NULL) { /* allocate and initializes the * IpAddrSet at the same time * set to "any" */ s5UdpPolicy->bound_addrs = (IpAddrSet *) SnortAlloc(sizeof(IpAddrSet)); } } return;}static void Stream5PrintUdpConfig(Stream5UdpPolicy *s5UdpPolicy){ LogMessage("Stream5 UDP Policy config:\n"); LogMessage(" Timeout: %d seconds\n", s5UdpPolicy->session_timeout); if (s5UdpPolicy->flags) { LogMessage(" Options:\n"); if (s5UdpPolicy->flags & STREAM5_CONFIG_IGNORE_ANY) { LogMessage(" Ignore Any -> Any Rules: YES\n"); } } //IpAddrSetPrint(" Bound Addresses:", s5UdpPolicy->bound_addrs);}int Stream5UdpOtnHasFlowOrFlowbit(OptTreeNode *otn){ if (otn->ds_list[PLUGIN_CLIENTSERVER] ||#ifdef DYNAMIC_PLUGIN DynamicHasFlow(otn) || DynamicHasFlowbit(otn) ||#endif otn->ds_list[PLUGIN_FLOWBIT]) { return 1; } return 0;}int Stream5UdpAnyAnyFlow(RuleTreeNode *rtn, int any_any_flow){ UdpIgnoredRule *ignored_rule; OptTreeNode *otn; int i; for (otn = rtn->down; otn; otn = otn->next) { /* Look for an OTN with flow or flowbits keyword */ if (Stream5UdpOtnHasFlowOrFlowbit(otn)) { for (i=1;i<=MAX_PORTS;i++) { /* track sessions for ALL ports becuase * of any -> any with flow/flowbits */ udp_ports[i] |= UDP_SESSION; } any_any_flow = 1; break; } else if (any_any_flow == 0) { if (!(udpPolicyList[0]->flags & STREAM5_CONFIG_IGNORE_ANY)) { /* Not ignoring any any rules... */ break; } /* if not, then ignore the content/pcre/etc */ if (otn->ds_list[PLUGIN_PATTERN_MATCH] || otn->ds_list[PLUGIN_PATTERN_MATCH_OR] || otn->ds_list[PLUGIN_PATTERN_MATCH_URI] ||#ifdef DYNAMIC_PLUGIN DynamicHasContent(otn) || DynamicHasByteTest(otn) || DynamicHasPCRE(otn) ||#endif otn->ds_list[PLUGIN_BYTE_TEST] || otn->ds_list[PLUGIN_PCRE]) { /* Ignoring this rule.... */ ignored_rule = SnortAlloc(sizeof(UdpIgnoredRule)); ignored_rule->otn = otn; ignored_rule->next = ignored_udp_rules; ignored_udp_rules = ignored_rule; } } } /* for (otn=...) */ return any_any_flow;}int Stream5VerifyUdpConfig(void){#ifdef PORTLISTS char *port_array = NULL; int num_ports = 0; int i;#else int16_t sport, dport;#endif RuleListNode *rule; RuleTreeNode *rtn; OptTreeNode *otn; UdpIgnoredRule *ignored_rule; extern RuleListNode *RuleLists; char inspectSrc, inspectDst; char buf[STD_BUF]; char six_sids = 0; int sids_ignored = 0; char any_any_flow = 0; if (!udp_lws_cache) return -1; if (numUdpPolicies < 1) return -1; /* Post-process UDP rules to establish UDP ports to inspect. */ for (rule=RuleLists; rule; rule=rule->next) { if(!rule->RuleList) continue; /* ** Get UDP rules */ if(rule->RuleList->UdpList) { for(rtn = rule->RuleList->UdpList; rtn != NULL; rtn = rtn->right) { inspectSrc = inspectDst = 0;#ifdef PORTLISTS if (PortObjectHasAny(rtn->src_portobject)) { inspectSrc = -1; } else { port_array = PortObjectCharPortArray(port_array, rtn->src_portobject, &num_ports); if (port_array && num_ports != 0) { inspectSrc = 1; for (i=0;i<SFPO_MAX_PORTS;i++) { if (port_array[i]) { udp_ports[i] |= UDP_INSPECT; /* port specific rule */ for (otn = rtn->down; otn; otn = otn->next) { /* Look for an OTN with flow or flowbits keyword */ if (Stream5UdpOtnHasFlowOrFlowbit(otn)) { udp_ports[i] |= UDP_SESSION; } } } } } } free(port_array); port_array = NULL; if (PortObjectHasAny(rtn->dst_portobject)) { inspectDst = -1; } else { port_array = PortObjectCharPortArray(port_array, rtn->dst_portobject, &num_ports); if (port_array && num_ports != 0) { inspectDst = 1; for (i=0;i<SFPO_MAX_PORTS;i++) { if (port_array[i]) { udp_ports[i] |= UDP_INSPECT; /* port specific rule */ for (otn = rtn->down; otn; otn = otn->next) { /* Look for an OTN with flow or flowbits keyword */ if (Stream5UdpOtnHasFlowOrFlowbit(otn)) { udp_ports[i] |= UDP_SESSION; } } } } } } free(port_array); port_array = NULL; if ((inspectSrc == -1) && (inspectDst == -1)) { /* any -> any rule */ if (any_any_flow == 0) { any_any_flow = Stream5UdpAnyAnyFlow(rtn, any_any_flow); } }#else sport = (int16_t)((rtn->hsp == rtn->lsp) ? rtn->hsp : -1); if (rtn->flags & ANY_SRC_PORT) { sport = -1; } if (sport > 0 && rtn->not_sp_flag > 0 ) { sport = -1; } /* Set the source port to inspect */ if (sport != -1) { udp_ports[sport] |= UDP_INSPECT; } dport = (int16_t)((rtn->hdp == rtn->ldp) ? rtn->hdp : -1); if (rtn->flags & ANY_DST_PORT) { dport = -1; } if (dport > 0 && rtn->not_dp_flag > 0 ) { dport = -1; } /* Set the dest port to inspect */ if (dport != -1) { inspectDst = 1; udp_ports[dport] |= UDP_INSPECT; } if (inspectSrc || inspectDst) { /* port specific rule */ for (otn = rtn->down; otn; otn = otn->next) { /* Look for an OTN with flow or flowbits keyword */ if (Stream5UdpOtnHasFlowOrFlowbit(otn)) { if (inspectSrc) { udp_ports[sport] |= UDP_SESSION; } if (inspectDst)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -