/* * Function: FTPResetSession(FTP_SESSION *FtpSession, int first) * * Purpose: This function resets all the variables that need to be * initialized for a new Session. I've tried to keep this to * a minimum, so we don't have to worry about initializing big * structures. * * Arguments: FtpSession => pointer to the session to reset * first => indicator whether this is a new conf * * Returns: int => return code indicating error or success * */ static inline int FTPResetSession(FTP_SESSION *FtpSession) { FtpSession->ft_ssn.proto = FTPP_SI_PROTO_FTP; FtpSession->server.response.pipeline_req = 0; FtpSession->server.response.state = 0; FtpSession->client.request.pipeline_req = 0; FtpSession->client.state = 0; FtpSession->client_conf = NULL; FtpSession->server_conf = NULL; FtpSession->global_conf = NULL; FtpSession->encr_state = NO_STATE; IP_CLEAR(FtpSession->clientIP); FtpSession->clientPort = 0; IP_CLEAR(FtpSession->serverIP); FtpSession->serverPort = 0; FtpSession->data_chan_state = NO_STATE; FtpSession->data_chan_index = -1; FtpSession->data_xfer_index = -1; FtpSession->event_list.stack_count = 0; return FTPP_SUCCESS; }
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; }
static int ps_tracker_update_ip(PS_PKT *ps_pkt, PS_TRACKER *scanner, PS_TRACKER *scanned) { Packet *p; snort_ip cleared; IP_CLEAR(cleared); p = (Packet *)ps_pkt->pkt; if(p->iph) { if(p->icmph) { if(scanned) { ps_proto_update(&scanned->proto,0,1,CLEARED,0,0); scanned->priority_node = 1; } if(scanner) { ps_proto_update(&scanner->proto,0,1,CLEARED,0,0); scanner->priority_node = 1; } return 0; } } return 0; }
static int ps_tracker_update_udp(PS_PKT *ps_pkt, PS_TRACKER *scanner, PS_TRACKER *scanned) { Packet *p; snort_ip cleared; IP_CLEAR(cleared); p = (Packet *)ps_pkt->pkt; if(p->icmph) { if(scanned) { ps_proto_update(&scanned->proto,0,1,CLEARED,0,0); scanned->priority_node = 1; } if(scanner) { ps_proto_update(&scanner->proto,0,1,CLEARED,0,0); scanner->priority_node = 1; } } else if(p->udph) { if (stream_api && (stream_api->version >= STREAM_API_VERSION5) && p->ssnptr) { uint32_t direction = stream_api->get_packet_direction(p); if (direction == PKT_FROM_CLIENT) { if(scanned) { ps_proto_update(&scanned->proto,1,0, GET_SRC_IP(p),p->dp, packet_time()); } if(scanner) { ps_proto_update(&scanner->proto,1,0, GET_DST_IP(p),p->dp, packet_time()); } } else if (direction == PKT_FROM_SERVER) { if(scanned) ps_proto_update(&scanned->proto,-1,0,CLEARED,0,0); if(scanner) ps_proto_update(&scanner->proto,-1,0,CLEARED,0,0); } } } return 0; }
static int ps_tracker_update_icmp(PS_PKT *ps_pkt, PS_TRACKER *scanner, PS_TRACKER *scanned) { Packet *p; snort_ip cleared; IP_CLEAR(cleared); p = (Packet *)ps_pkt->pkt; if(p->icmph) { switch(p->icmph->type) { case ICMP_ECHO: case ICMP_TIMESTAMP: case ICMP_ADDRESS: case ICMP_INFO_REQUEST: if(scanner) { ps_proto_update(&scanner->proto,1,0, GET_DST_IP(p), 0, packet_time()); } break; case ICMP_DEST_UNREACH: if(scanner) { ps_proto_update(&scanner->proto,0,1,CLEARED,0,0); scanner->priority_node = 1; } break; default: break; } } return 0; }
/** ** Determine how to update the portscan counter depending on the type ** of TCP packet we have. ** ** We are concerned with three types of TCP packets: ** ** - initiating TCP packets (we don't care about flags) ** - TCP 3-way handshake packets (we decrement the counter) ** - TCP reset packets on unestablished streams. */ static int ps_tracker_update_tcp(PS_PKT *ps_pkt, PS_TRACKER *scanner, PS_TRACKER *scanned) { Packet *p; uint32_t session_flags; snort_ip cleared; IP_CLEAR(cleared); p = (Packet *)ps_pkt->pkt; /* ** Handle the initiating packet. ** ** If this what stream4 considers to be a valid initiator, then ** we will use the available stream4 information. Otherwise, we ** can just revert to flow and look for initiators and responders. ** ** For Stream5, depending on the configuration, there might not ** be a session created only based on the SYN packet. Stream5 ** by default has code that helps deal with SYN flood attacks, ** and may simply ignore the SYN. In this case, we fall through ** to the checks for specific TCP header files (SYN, SYN-ACK, RST). ** ** The "midstream" logic below says that, if we include sessions ** picked up midstream, then we don't care about the MIDSTREAM flag. ** Otherwise, only consider streams not picked up midstream. */ if(p->ssnptr && stream_api) { session_flags = stream_api->get_session_flags(p->ssnptr); if((session_flags & SSNFLAG_SEEN_CLIENT) && !(session_flags & SSNFLAG_SEEN_SERVER) && (portscan_eval_config->include_midstream || !(session_flags & SSNFLAG_MIDSTREAM))) { if(scanned) { ps_proto_update(&scanned->proto,1,0, GET_SRC_IP(p),p->dp, packet_time()); } if(scanner) { ps_proto_update(&scanner->proto,1,0, GET_DST_IP(p),p->dp, packet_time()); } } /* ** Handle the final packet of the three-way handshake. */ else if(p->packet_flags & PKT_STREAM_TWH) { if(scanned) { ps_proto_update(&scanned->proto,-1,0,CLEARED,0,0); } if(scanner) { ps_proto_update(&scanner->proto,-1,0,CLEARED,0,0); } } /* ** RST packet on unestablished streams */ else if((p->packet_flags & PKT_FROM_SERVER) && (p->tcph && (p->tcph->th_flags & TH_RST)) && (!(p->packet_flags & PKT_STREAM_EST) || (session_flags & SSNFLAG_MIDSTREAM))) { if(scanned) { ps_proto_update(&scanned->proto,0,1,CLEARED,0,0); scanned->priority_node = 1; } if(scanner) { ps_proto_update(&scanner->proto,0,1,CLEARED,0,0); scanner->priority_node = 1; } } /* ** We only get here on the server's response to the intial ** client connection. ** ** That's why we use the sp, because that's the port that is ** open. */ else if((p->packet_flags & PKT_FROM_SERVER) && !(p->packet_flags & PKT_STREAM_EST)) { if(scanned) { ps_update_open_ports(&scanned->proto, p->sp); } if(scanner) { if(scanner->proto.alerts == PS_ALERT_GENERATED) scanner->proto.alerts = PS_ALERT_OPEN_PORT; } } } /* ** Stream didn't create a session on the SYN packet, ** so check specifically for SYN here. */ else if (p->tcph && (p->tcph->th_flags == TH_SYN)) { /* No session established, packet only has SYN. SYN only ** packet always from client, so use dp. */ if(scanned) { ps_proto_update(&scanned->proto,1,0, GET_SRC_IP(p),p->dp, packet_time()); } if(scanner) { ps_proto_update(&scanner->proto,1,0, GET_DST_IP(p),p->dp, packet_time()); } } /* ** Stream didn't create a session on the SYN packet, ** so check specifically for SYN & ACK here. Clear based ** on the 'completion' of three-way handshake. */ else if(p->tcph && (p->tcph->th_flags == (TH_SYN|TH_ACK))) { if(scanned) { ps_proto_update(&scanned->proto,-1,0,CLEARED,0,0); } if(scanner) { ps_proto_update(&scanner->proto,-1,0,CLEARED,0,0); } } /* ** No session created, clear based on the RST on non ** established session. */ else if (p->tcph && (p->tcph->th_flags & TH_RST)) { if(scanned) { ps_proto_update(&scanned->proto,0,1,CLEARED,0,0); scanned->priority_node = 1; } if(scanner) { ps_proto_update(&scanner->proto,0,1,CLEARED,0,0); scanner->priority_node = 1; } } /* ** If we are an icmp unreachable, deal with it here. */ else if(p->icmph) { if(scanned) { ps_proto_update(&scanned->proto,0,1,CLEARED,0,0); scanned->priority_node = 1; } if(scanner) { ps_proto_update(&scanner->proto,0,1,CLEARED,0,0); scanner->priority_node = 1; } } return 0; }
/* 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; }
void ppm_pkt_log(ppm_cfg_t *ppm_cfg, Packet* p) { int filterEvent = 0; if (!ppm_cfg->max_pkt_ticks) return; ppm_cfg->pkt_event_cnt++; if (ppm_cfg->pkt_log & PPM_LOG_ALERT) { OptTreeNode* potn; Event ev; /* make sure we have an otn already in our table for this event */ potn = OtnLookup(snort_conf->otn_map, GENERATOR_PPM, PPM_EVENT_PACKET_ABORTED); if (potn == NULL) { /* have to make one */ potn = GenerateSnortEventOtn(GENERATOR_PPM, /* GID */ PPM_EVENT_PACKET_ABORTED, /* SID */ 1, /* Rev */ 0, /* classification */ 3, /* priority (low) */ PPM_EVENT_PACKET_ABORTED_STR /* msg string */); if (potn == NULL) return; OtnLookupAdd(snort_conf->otn_map, potn); } SetEvent(&ev, potn->sigInfo.generator, /* GID */ potn->sigInfo.id, /* SID */ potn->sigInfo.rev, /* Rev */ potn->sigInfo.class_id, /* classification */ potn->sigInfo.priority, /* priority (low) */ #if !defined(FEAT_OPEN_APPID) 0); #else /* defined(FEAT_OPEN_APPID) */ 0, NULL); #endif /* defined(FEAT_OPEN_APPID) */ if ( IPH_IS_VALID(p) ) { filterEvent = sfthreshold_test( potn->event_data.sig_generator, potn->event_data.sig_id, GET_SRC_IP(p), GET_DST_IP(p), p->pkth->ts.tv_sec); } else { snort_ip cleared; IP_CLEAR(cleared); filterEvent = sfthreshold_test( potn->event_data.sig_generator, potn->event_data.sig_id, IP_ARG(cleared), IP_ARG(cleared), p->pkth->ts.tv_sec); } if(filterEvent < 0) filterEvent = 0; else AlertAction(p, potn, &ev); }