static int ps_tracker_lookup(PS_PKT *ps_pkt, PS_TRACKER **scanner, PS_TRACKER **scanned) { PS_HASH_KEY key; Packet *p; if (ps_pkt->pkt == NULL) return -1; p = (Packet *)ps_pkt->pkt; if (ps_get_proto(ps_pkt, &key.protocol) == -1) return -1; ps_pkt->proto = key.protocol; key.policyId = getRuntimePolicy(); /* ** Let's lookup the host that is being scanned, taking into account ** the pkt may be reversed. */ if (portscan_eval_config->detect_scan_type & (PS_TYPE_PORTSCAN | PS_TYPE_DECOYSCAN | PS_TYPE_DISTPORTSCAN)) { IP_CLEAR(key.scanner); if(ps_pkt->reverse_pkt) IP_COPY_VALUE(key.scanned, GET_SRC_IP(p)); else IP_COPY_VALUE(key.scanned, GET_DST_IP(p)); /* ** Get the scanned tracker. */ ps_tracker_get(scanned, &key); } /* ** Let's lookup the host that is scanning. */ if(portscan_eval_config->detect_scan_type & PS_TYPE_PORTSWEEP) { IP_CLEAR(key.scanned); if(ps_pkt->reverse_pkt) IP_COPY_VALUE(key.scanner, GET_DST_IP(p)); else IP_COPY_VALUE(key.scanner, GET_SRC_IP(p)); /* ** Get the scanner tracker */ ps_tracker_get(scanner, &key); } if ((*scanner == NULL) && (*scanned == NULL)) return -1; return 0; }
// *DROP* flags are set to mark the direction(s) for which traffic was // seen since last reset and then cleared after sending new attempt so // that we only send in the still active direction(s). void Stream5ActiveResponse(Packet* p, Stream5LWSession *lwssn) { Stream5Config *config = sfPolicyUserDataGet(s5_config, getRuntimePolicy()); uint8_t max = config->global_config->max_active_responses; if ( p->packet_flags & PKT_FROM_CLIENT ) lwssn->session_state |= STREAM5_STATE_DROP_CLIENT; else lwssn->session_state |= STREAM5_STATE_DROP_SERVER; if ( (lwssn->response_count < max) && Stream5GetExpire(p, lwssn) ) { uint32_t delay = config->global_config->min_response_seconds; EncodeFlags flags = ( (lwssn->session_state & STREAM5_STATE_DROP_CLIENT) && (lwssn->session_state & STREAM5_STATE_DROP_SERVER) ) ? ENC_FLAG_FWD : 0; // reverse dir is always true Active_KillSession(p, &flags); ++lwssn->response_count; Stream5SetExpire(p, lwssn, delay); lwssn->session_state &= ~(STREAM5_STATE_DROP_CLIENT|STREAM5_STATE_DROP_SERVER); } }
static tSFRFTrackingNode* _getSFRFTrackingNode( snort_ip_p ip, unsigned tid, time_t curTime ) { tSFRFTrackingNode* dynNode = NULL; tSFRFTrackingNodeKey key; SFXHASH_NODE * hnode = NULL; /* Setup key */ key.ip = *(IP_PTR(ip)); key.tid = tid; key.policyId = getRuntimePolicy(); /* * Check for any Permanent sid objects for this gid or add this one ... */ hnode = sfxhash_get_node(rf_hash, (void*)&key); if ( hnode && hnode->data ) { dynNode = (tSFRFTrackingNode*)hnode->data; if ( dynNode->filterState == FS_NEW ) { // first time initialization dynNode->tstart = curTime; #ifdef SFRF_OVER_RATE dynNode->tlast = curTime; #endif dynNode->filterState = FS_OFF; } } return dynNode; }
OptTreeNode * GenerateSnortEventOtn( uint32_t gen_id, uint32_t sig_id, uint32_t sig_rev, uint32_t classification, uint32_t priority, char *msg ) { OptTreeNode * p; RuleTreeNode *rtn = NULL; p = calloc( 1, sizeof(OptTreeNode) ); if(!p ) return 0; p->sigInfo.generator = gen_id; p->sigInfo.id = sig_id; p->sigInfo.rev = sig_rev; p->sigInfo.message = msg; p->sigInfo.priority = priority; p->sigInfo.class_id = classification; p->generated = 1; p->sigInfo.rule_type=SI_RULE_TYPE_PREPROC; /* TODO: could be detect ... */ p->sigInfo.rule_flushing=SI_RULE_FLUSHING_OFF; /* only standard rules do this */ p->event_data.sig_generator = gen_id; p->event_data.sig_id = sig_id; p->event_data.sig_rev = sig_rev; p->event_data.classification = classification; p->event_data.priority = priority; rtn = GenerateSnortEventRtn(p, getRuntimePolicy()); if( !rtn ) { free(p); return NULL; } DEBUG_WRAP( LogMessage("Generating OTN for GID: %u, SID: %u\n",gen_id,sig_id););
int file_eventq_add(uint32_t gid, uint32_t sid, char *msg, RuleType type) { OptTreeNode *otn; RuleTreeNode *rtn; int ret; otn = GetOTN(gid, sid, 1, 0, 3, msg); if (otn == NULL) return 0; rtn = getRtnFromOtn(otn, getRuntimePolicy()); if (rtn == NULL) { return 0; } rtn->type = type; ret = SnortEventqAdd(gid, sid, 1, 0, 3, msg, otn); return(ret); }
int Preprocess(Packet * p) { int retval = 0; tSfPolicyId policy_id = getRuntimePolicy(); SnortPolicy *policy = snort_conf->targeted_policies[policy_id]; #ifdef PPM_MGR uint64_t pktcnt=0; #endif PROFILE_VARS; if (policy == NULL) return -1; #ifdef PPM_MGR /* Begin Packet Performance Monitoring */ if( PPM_PKTS_ENABLED() ) { pktcnt = PPM_INC_PKT_CNT(); PPM_GET_TIME(); PPM_INIT_PKT_TIMER(); if( PPM_DEBUG_PKTS() ) { /* for debugging, info gathering, so don't worry about * (unsigned) casting of pktcnt, were not likely to debug * 4G packets */ LogMessage("PPM: Process-BeginPkt[%u] caplen=%u\n", (unsigned)pktcnt,p->pkth->caplen); } } #endif // If the packet has errors, we won't analyze it. if ( p->error_flags ) { DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "Packet errors = 0x%x, ignoring traffic!\n", p->error_flags););
/* Test a an event against the threshold database. Events without thresholding * objects are automatically loggable. * * @param pContext Threshold table pointer * @param gid Generator Id from the event * @param sid Signature Id from the event * @param sip Event/Packet Src IP address * @param dip Event/Packet Dst IP address * @param curTime Current Event/Packet time * @param op operation of type SFRF_COUNT_OPERATION * * @return -1 if packet is within dos_threshold and therefore action is allowed. * >=0 if packet violates a dos_threshold and therefore new_action should * replace rule action. new_action value is returned. */ int SFRF_TestThreshold( RateFilterConfig *config, unsigned gid, unsigned sid, snort_ip_p sip, snort_ip_p dip, time_t curTime, SFRF_COUNT_OPERATION op ) { SFGHASH *genHash; tSFRFSidNode* pSidNode; tSFRFConfigNode* cfgNode; int newStatus = -1; int status = -1; tSFRFGenHashKey key; tSfPolicyId policy_id = getRuntimePolicy(); #ifdef SFRF_DEBUG printf("--%d-%d-%d: %s() entering\n", 0, gid, sid, __func__); fflush(stdout); #endif if ( gid >= SFRF_MAX_GENID ) return status; /* bogus gid */ // Some events (like 'TCP connection closed' raised by preprocessor may // not have any configured threshold but may impact thresholds for other // events (like 'TCP connection opened' _updateDependentThresholds(config, gid, sid, sip, dip, curTime); /* * Get the hash table for this gid */ genHash = config->genHash [ gid ]; if ( !genHash ) { #ifdef SFRF_DEBUG printf("--SFRF_DEBUG: %d-%d-%d: no hash table entry for gid\n", 0, gid, sid); fflush(stdout); #endif return status; } /* * Check for any Permanent sid objects for this gid */ key.sid = sid; key.policyId = policy_id; pSidNode = (tSFRFSidNode*)sfghash_find( genHash, (void*)&key ); if ( !pSidNode ) { #ifdef SFRF_DEBUG printf("--SFRF_DEBUG: %d-%d-%d: no DOS THD object\n", 0, gid, sid); fflush(stdout); #endif return status; } /* No List of Threshold objects - bail and log it */ if ( !pSidNode->configNodeList ) { #ifdef SFRF_DEBUG printf("--SFRF_DEBUG: %d-%d-%d: No user configuration\n", 0, gid, sid); fflush(stdout); #endif return status; } /* For each permanent thresholding object, test/add/update the config object */ /* We maintain a list of thd objects for each gid+sid */ /* each object has it's own unique thd_id */ for ( cfgNode = (tSFRFConfigNode*)sflist_first(pSidNode->configNodeList); cfgNode != 0; cfgNode = (tSFRFConfigNode*)sflist_next(pSidNode->configNodeList) ) { switch (cfgNode->tracking) { case SFRF_TRACK_BY_SRC: if ( SFRF_AppliesTo(cfgNode, sip) ) { newStatus = SFRF_TestObject(cfgNode, sip, curTime, op); } break; case SFRF_TRACK_BY_DST: if ( SFRF_AppliesTo(cfgNode, dip) ) { newStatus = SFRF_TestObject(cfgNode, dip, curTime, op); } break; case SFRF_TRACK_BY_RULE: { snort_ip cleared; IP_CLEAR(cleared); newStatus = SFRF_TestObject(cfgNode, IP_ARG(cleared), curTime, op); } break; default: // error case break; } #ifdef SFRF_DEBUG printf("--SFRF_DEBUG: %d-%d-%d: Time %d, rate limit blocked: %d\n", cfgNode->tid, gid, sid, (unsigned)curTime, newStatus); fflush(stdout); #endif // rate limit is reached if ( newStatus >= 0 && (status == -1) ) { status = newStatus; } } // rate limit not reached return status; }
/* * Test a global thresholding object */ static inline int sfthd_test_global( SFXHASH *global_hash, THD_NODE * sfthd_node, unsigned gen_id, /* from current event */ unsigned sig_id, /* from current event */ snort_ip_p sip, /* " */ snort_ip_p dip, /* " */ time_t curtime ) { THD_IP_GNODE_KEY key; THD_IP_NODE data, *sfthd_ip_node; int status=0; snort_ip_p ip; tSfPolicyId policy_id = getRuntimePolicy(); #ifdef THD_DEBUG printf("THD_DEBUG-GLOBAL: gen_id=%u, sig_id=%u\n",gen_id,sig_id); printf("THD_DEBUG: Global THD_NODE IP=%s,",printIP((unsigned)sfthd_node->ip_address) ); printf(" MASK=%s\n",printIP((unsigned)sfthd_node->ip_mask) ); printf("THD_DEBUG: PKT SIP=%s\n",printIP((unsigned)sip) ); printf("THD_DEBUG: PKT DIP=%s\n",printIP((unsigned)dip) ); fflush(stdout); #endif /* -1 means don't do any limit or thresholding */ if ( sfthd_node->count == THD_NO_THRESHOLD) { #ifdef THD_DEBUG printf("\n...No Threshold applied for this object\n"); fflush(stdout); #endif return 0; } /* Get The correct IP */ if (sfthd_node->tracking == THD_TRK_SRC) ip = sip; else ip = dip; /* Check for and test Suppression of this event to this IP */ if( sfthd_node->type == THD_TYPE_SUPPRESS ) { #ifdef THD_DEBUG printf("THD_DEBUG: G-SUPPRESS NODE Testing...\n");fflush(stdout); #endif return sfthd_test_suppress(sfthd_node, ip); } /* * Go on and do standard thresholding */ /* Set up the key */ key.ip = IP_VAL(ip); key.gen_id = sfthd_node->gen_id; key.sig_id = sig_id; key.policyId = policy_id; /* Set up a new data element */ data.count = 1; data.prev = 0; data.tstart = data.tlast = curtime; /* Event time */ /* Check for any Permanent sig_id objects for this gen_id or add this one ... */ status = sfxhash_add(global_hash, (void*)&key, &data); if (status == SFXHASH_INTABLE) { /* Already in the table */ sfthd_ip_node = global_hash->cnode->data; /* Increment the event count */ sfthd_ip_node->count++; } else if (status != SFXHASH_OK) { /* hash error */ return 1; /* check the next threshold object */ } else { /* Was not in the table - it was added - work with our copy of the data */ sfthd_ip_node = &data; } return sfthd_test_non_suppress(sfthd_node, sfthd_ip_node, curtime); }
/*! * * Test a an event against the threshold database. * Events without thresholding objects are automatically * loggable. * * @param thd Threshold table pointer * @param gen_id Generator Id from the event * @param sig_id Signature Id from the event * @param sip Event/Packet Src IP address * @param dip Event/Packet Dst IP address * @param curtime Current Event/Packet time * * @return integer * @retval 0 : Event is loggable * @retval !0 : Event should not be logged (-1 suppressed, 1 filtered) * */ int sfthd_test_threshold( ThresholdObjects *thd_objs, THD_STRUCT *thd, unsigned gen_id, unsigned sig_id, snort_ip_p sip, snort_ip_p dip, long curtime ) { tThdItemKey key; SFGHASH * sfthd_hash; THD_ITEM * sfthd_item; THD_NODE * sfthd_node; THD_NODE * g_thd_node = NULL; #ifdef THD_DEBUG int cnt; #endif int status=0; tSfPolicyId policy_id = getRuntimePolicy(); if ((thd_objs == NULL) || (thd == NULL)) return 0; #ifdef CRIPPLE return 0; #endif #ifdef THD_DEBUG printf("sfthd_test_threshold...\n");fflush(stdout); #endif if( gen_id >= THD_MAX_GENID ) { #ifdef THD_DEBUG printf("THD_DEBUG: invalid gen_id=%u\n",gen_id); fflush(stdout); #endif return 0; /* bogus gen_id */ } /* * Get the hash table for this gen_id */ sfthd_hash = thd_objs->sfthd_array[gen_id]; if (sfthd_hash == NULL) { #ifdef THD_DEBUG printf("THD_DEBUG: no hash table entry for gen_id=%u\n",gen_id); fflush(stdout); #endif goto global_test; /* return 0; */ /* no threshold objects for this gen_id, log it ! */ } key.sig_id = sig_id; key.policyId = policy_id; /* * Check for any Permanent sig_id objects for this gen_id */ sfthd_item = (THD_ITEM *)sfghash_find(sfthd_hash, (void*)&key); if (sfthd_item == NULL) { #ifdef THD_DEBUG printf("THD_DEBUG: no THD objects for gen_id=%u, sig_id=%u\n",gen_id,sig_id); fflush(stdout); #endif /* no matching permanent sig_id objects so, log it ! */ goto global_test; } /* No List of Threshold objects - bail and log it */ if (sfthd_item->sfthd_node_list == NULL) { goto global_test; } /* For each permanent thresholding object, test/add/update the thd object */ /* We maintain a list of thd objects for each gen_id+sig_id */ /* each object has it's own unique thd_id */ /* Suppression nodes have a very high priority, so they are tested 1st */ #ifdef THD_DEBUG cnt=0; #endif for (sfthd_node = (THD_NODE *)sflist_first(sfthd_item->sfthd_node_list); sfthd_node != NULL; sfthd_node = (THD_NODE *)sflist_next(sfthd_item->sfthd_node_list)) { #ifdef THD_DEBUG cnt++; printf("THD_DEBUG: gen_id=%u sig_id=%u testing thd_id=%d thd_type=%d\n", gen_id, sig_id, sfthd_node->thd_id, sfthd_node->type); fflush(stdout); #endif /* * Test SUPPRESSION and THRESHOLDING */ status = sfthd_test_local(thd->ip_nodes, sfthd_node, sip, dip, curtime ); if( status < 0 ) /* -1 == Don't log and stop looking */ { #ifdef THD_DEBUG printf("THD_DEBUG: gen_id=%u sig_id=%u, UnLoggable\n\n",gen_id, sig_id,cnt); fflush(stdout); #endif return (status < -1) ? 1 : -1; /* !0 == Don't log it*/ } else if( status == 0 ) /* Log it and stop looking */ { #ifdef THD_DEBUG printf("THD_DEBUG: gen_id=%u sig_id=%u tested %d THD_NODE's, " "Loggable\n\n",sfthd_item->gen_id, sfthd_item->sig_id,cnt); fflush(stdout); #endif return 0; /* 0 == Log the event */ } /* status > 0 : Log it later but Keep looking * check the next threshold object for a blocking action ... */ } /* * Test for a global threshold object * we're here cause ther were no threshold objects for this gen_id/sig_id pair */ global_test: #ifdef THD_DEBUG printf("THD_DEBUG-GLOBAL: doing global object test\n"); #endif if (thd_objs->sfthd_garray && thd_objs->sfthd_garray[policy_id]) { g_thd_node = thd_objs->sfthd_garray[policy_id][gen_id]; } if( g_thd_node ) { status = sfthd_test_global( thd->ip_gnodes, g_thd_node, gen_id, sig_id, sip, dip, curtime ); if( status < 0 ) /* -1 == Don't log and stop looking */ { #ifdef THD_DEBUG printf("THD_DEBUG-GLOBAL: gen_id=%u sig_id=%u THD_NODE's, " "UnLoggable\n\n",gen_id, sig_id); fflush(stdout); #endif return (status < -1) ? 1 : -1; /* !0 == Don't log it*/ } /* Log it ! */ #ifdef THD_DEBUG printf("THD_DEBUG-GLOBAL: gen_id=%u sig_id=%u THD_NODE's, " "Loggable\n\n",gen_id, sig_id); fflush(stdout); #endif } else { #ifdef THD_DEBUG printf("THD_DEBUG-GLOBAL: no Global THD Object for gen_id=%u, " "sig_id=%u\n\n",gen_id, sig_id); fflush(stdout); #endif } return 0; /* Default: Log it if we did not block the logging action */ }
/* * Changed so events are inserted in action config order 'drop alert ...', * and sub sorted in each action group by priority or content length. * The sub sorting is done in fpFinalSelect inf fpdetect.c. Once the * events are inserted they can all be logged, as we only insert * g_event_queue.log_events into the queue. * ... Jan '06 */ int SnortEventqAdd(unsigned int gid, unsigned int sid, unsigned int rev, unsigned int classification, unsigned int pri, char *msg, void *rule_info) { EventNode *en; en = (EventNode *)sfeventq_event_alloc(snort_conf->event_queue[qIndex]); if(!en) return -1; en->gid = gid; en->sid = sid; en->rev = rev; en->classification = classification; en->priority = pri; en->msg = msg; en->rule_info = rule_info; /* * Check if we have a preprocessor or decoder event * Preprocessors and decoders may be configured to inspect * and alert in their principal configuration (legacy code) * this test than checks if the rule otn says they should * be enabled or not. The rule itself will decide if it should * be an alert or a drop (sdrop) condition. */ #ifdef PREPROCESSOR_AND_DECODER_RULE_EVENTS { struct _OptTreeNode * potn; /* every event should have a rule/otn */ potn = OtnLookup(snort_conf->otn_map, gid, sid); /* * if no rule otn exists for this event, than it was * not enabled via rules */ if (potn == NULL) { if (ScAutoGenPreprocDecoderOtns()) { /* Generate an OTN if configured to do so.... */ potn = GenerateSnortEventOtn(en->gid, en->sid, en->rev, en->classification, en->priority, en->msg); if (potn != NULL) OtnLookupAdd(snort_conf->otn_map, potn); } if (potn == NULL) { /* no otn found/created - do not add it to the queue */ return 0; } } else { tSfPolicyId policyId = getRuntimePolicy(); RuleTreeNode* rtn = getRtnFromOtn(potn, policyId); if ( !rtn ) { if ( ScAutoGenPreprocDecoderOtns() ) rtn = GenerateSnortEventRtn(potn, getRuntimePolicy()); if ( !rtn ) return 0; } } } #endif if (sfeventq_add(snort_conf->event_queue[qIndex], (void *)en)) { return -1; } s_events++; return 0; }