|
|
|
@ -685,6 +685,10 @@ end:
|
|
|
|
|
SCReturnPtr(smsg, "StreamMsg");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SMS_USE_FLOW_SGH 0x01
|
|
|
|
|
#define SMS_USED_PM 0x02
|
|
|
|
|
#define SMS_USED_STREAM_PM 0x04
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Signature match function
|
|
|
|
|
*
|
|
|
|
@ -693,28 +697,29 @@ end:
|
|
|
|
|
*/
|
|
|
|
|
int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
|
|
|
|
|
{
|
|
|
|
|
uint8_t sms_runflags = 0; /* function flags */
|
|
|
|
|
uint8_t alert_flags = 0;
|
|
|
|
|
uint16_t alproto = ALPROTO_UNKNOWN;
|
|
|
|
|
int match = 0;
|
|
|
|
|
|
|
|
|
|
int fmatch = 0;
|
|
|
|
|
uint32_t idx;
|
|
|
|
|
|
|
|
|
|
/* No need to perform any detection on this packet, if the the given flag is set.*/
|
|
|
|
|
if (p->flags & PKT_NOPACKET_INSPECTION)
|
|
|
|
|
return 0;
|
|
|
|
|
uint32_t cnt = 0;
|
|
|
|
|
uint8_t flags = 0; /* flow/state flags */
|
|
|
|
|
|
|
|
|
|
int match = 0, fmatch = 0;
|
|
|
|
|
Signature *s = NULL;
|
|
|
|
|
SigMatch *sm = NULL;
|
|
|
|
|
uint32_t idx;
|
|
|
|
|
uint16_t alproto = ALPROTO_UNKNOWN;
|
|
|
|
|
void *alstate = NULL;
|
|
|
|
|
uint8_t flags = 0;
|
|
|
|
|
uint32_t cnt = 0;
|
|
|
|
|
SigGroupHead *sgh = NULL;
|
|
|
|
|
char use_flow_sgh = FALSE;
|
|
|
|
|
StreamMsg *smsg = NULL;
|
|
|
|
|
char no_store_flow_sgh = FALSE;
|
|
|
|
|
uint8_t alert_flags = 0;
|
|
|
|
|
Signature *s = NULL;
|
|
|
|
|
SigMatch *sm = NULL;
|
|
|
|
|
|
|
|
|
|
SCEnter();
|
|
|
|
|
|
|
|
|
|
/* No need to perform any detection on this packet, if the the given flag is set.*/
|
|
|
|
|
if (p->flags & PKT_NOPACKET_INSPECTION) {
|
|
|
|
|
SCReturnInt(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCLogDebug("pcap_cnt %"PRIu64, p->pcap_cnt);
|
|
|
|
|
|
|
|
|
|
p->alerts.cnt = 0;
|
|
|
|
@ -731,34 +736,31 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
|
|
|
|
|
FlowIncrUsecnt(p->flow);
|
|
|
|
|
|
|
|
|
|
SCMutexLock(&p->flow->m);
|
|
|
|
|
{
|
|
|
|
|
/* Get the stored sgh from the flow (if any). Make sure we're not using
|
|
|
|
|
* the sgh for icmp error packets part of the same stream. */
|
|
|
|
|
if (IP_GET_IPPROTO(p) == p->flow->proto) { /* filter out icmp */
|
|
|
|
|
if (p->flowflags & FLOW_PKT_TOSERVER && p->flow->flags & FLOW_SGH_TOSERVER) {
|
|
|
|
|
det_ctx->sgh = p->flow->sgh_toserver;
|
|
|
|
|
sms_runflags |= SMS_USE_FLOW_SGH;
|
|
|
|
|
} else if (p->flowflags & FLOW_PKT_TOCLIENT && p->flow->flags & FLOW_SGH_TOCLIENT) {
|
|
|
|
|
det_ctx->sgh = p->flow->sgh_toclient;
|
|
|
|
|
sms_runflags |= SMS_USE_FLOW_SGH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the stored sgh from the flow (if any). Make sure we're not using
|
|
|
|
|
* the sgh for icmp error packets part of the same stream. */
|
|
|
|
|
if (IP_GET_IPPROTO(p) == p->flow->proto) { /* filter out icmp */
|
|
|
|
|
if (p->flowflags & FLOW_PKT_TOSERVER && p->flow->flags & FLOW_SGH_TOSERVER) {
|
|
|
|
|
sgh = p->flow->sgh_toserver;
|
|
|
|
|
use_flow_sgh = TRUE;
|
|
|
|
|
} else if (p->flowflags & FLOW_PKT_TOCLIENT && p->flow->flags & FLOW_SGH_TOCLIENT) {
|
|
|
|
|
sgh = p->flow->sgh_toclient;
|
|
|
|
|
use_flow_sgh = TRUE;
|
|
|
|
|
smsg = SigMatchSignaturesGetSmsg(p->flow, p, flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
smsg = SigMatchSignaturesGetSmsg(p->flow, p, flags);
|
|
|
|
|
} else {
|
|
|
|
|
no_store_flow_sgh = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Retrieve the app layer state and protocol and the tcp reassembled
|
|
|
|
|
* stream chunks. */
|
|
|
|
|
if (p->flowflags & FLOW_PKT_ESTABLISHED) {
|
|
|
|
|
alstate = AppLayerGetProtoStateFromPacket(p);
|
|
|
|
|
alproto = AppLayerGetProtoFromPacket(p);
|
|
|
|
|
SCLogDebug("alstate %p, alproto %u", alstate, alproto);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug("packet doesn't have established flag set");
|
|
|
|
|
/* Retrieve the app layer state and protocol and the tcp reassembled
|
|
|
|
|
* stream chunks. */
|
|
|
|
|
if (p->flowflags & FLOW_PKT_ESTABLISHED) {
|
|
|
|
|
alstate = AppLayerGetProtoStateFromPacket(p);
|
|
|
|
|
alproto = AppLayerGetProtoFromPacket(p);
|
|
|
|
|
SCLogDebug("alstate %p, alproto %u", alstate, alproto);
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug("packet doesn't have established flag set");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCMutexUnlock(&p->flow->m);
|
|
|
|
|
|
|
|
|
|
if (p->flowflags & FLOW_PKT_TOSERVER) {
|
|
|
|
@ -771,20 +773,20 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
|
|
|
|
|
SCLogDebug("p->flowflags 0x%02x", p->flowflags);
|
|
|
|
|
|
|
|
|
|
if ((p->flowflags & FLOW_PKT_TOSERVER && !(p->flowflags & FLOW_PKT_TOSERVER_IPONLY_SET)) ||
|
|
|
|
|
(p->flowflags & FLOW_PKT_TOCLIENT && !(p->flowflags & FLOW_PKT_TOCLIENT_IPONLY_SET))) {
|
|
|
|
|
(p->flowflags & FLOW_PKT_TOCLIENT && !(p->flowflags & FLOW_PKT_TOCLIENT_IPONLY_SET)))
|
|
|
|
|
{
|
|
|
|
|
SCLogDebug("testing against \"ip-only\" signatures");
|
|
|
|
|
|
|
|
|
|
IPOnlyMatchPacket(de_ctx, det_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p);
|
|
|
|
|
/* save in the flow that we scanned this direction... locking is
|
|
|
|
|
* done in the FlowSetIPOnlyFlag function. */
|
|
|
|
|
if (p->flow != NULL) {
|
|
|
|
|
FlowSetIPOnlyFlag(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
//if (p->flow != NULL && ((p->flowflags & FLOW_PKT_TOSERVER &&
|
|
|
|
|
// (p->flow->flags & FLOW_TOSERVER_IPONLY_SET)) ||
|
|
|
|
|
// (p->flowflags & FLOW_PKT_TOCLIENT &&
|
|
|
|
|
// (p->flow->flags & FLOW_TOCLIENT_IPONLY_SET)))) {
|
|
|
|
|
FlowSetIPOnlyFlag(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0);
|
|
|
|
|
|
|
|
|
|
} else if ((p->flowflags & FLOW_PKT_TOSERVER &&
|
|
|
|
|
(p->flow->flags & FLOW_TOSERVER_IPONLY_SET)) ||
|
|
|
|
|
(p->flowflags & FLOW_PKT_TOCLIENT &&
|
|
|
|
|
(p->flow->flags & FLOW_TOCLIENT_IPONLY_SET)))
|
|
|
|
|
{
|
|
|
|
|
/* Get the result of the first IPOnlyMatch() */
|
|
|
|
|
if (p->flow->flags & FLOW_ACTION_PASS) {
|
|
|
|
|
/* if it matched a "pass" rule, we have to let it go */
|
|
|
|
@ -793,29 +795,24 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
|
|
|
|
|
/* If we have a drop from IP only module,
|
|
|
|
|
* we will drop the rest of the flow packets
|
|
|
|
|
* This will apply only to inline/IPS */
|
|
|
|
|
if (p->flow != NULL &&
|
|
|
|
|
(p->flow->flags & FLOW_ACTION_DROP))
|
|
|
|
|
if (p->flow->flags & FLOW_ACTION_DROP)
|
|
|
|
|
{
|
|
|
|
|
alert_flags = PACKET_ALERT_FLAG_DROP_FLOW;
|
|
|
|
|
p->action |= ACTION_DROP;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(sms_runflags & SMS_USE_FLOW_SGH)) {
|
|
|
|
|
det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* no flow */
|
|
|
|
|
|
|
|
|
|
/* Even without flow we should match the packet src/dst */
|
|
|
|
|
IPOnlyMatchPacket(de_ctx, det_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* match the ip only signatures */
|
|
|
|
|
|
|
|
|
|
/* use the sgh from the flow unless we have no flow or the flow
|
|
|
|
|
* sgh wasn't initialized yet */
|
|
|
|
|
if (sgh == NULL && !use_flow_sgh) {
|
|
|
|
|
det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
|
|
|
|
|
} else {
|
|
|
|
|
det_ctx->sgh = sgh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if we didn't get a sig group head, we
|
|
|
|
|
* have nothing to do.... */
|
|
|
|
|
if (det_ctx->sgh == NULL) {
|
|
|
|
@ -829,6 +826,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
|
|
|
|
|
if (smsg != NULL && det_ctx->sgh->mpm_stream_ctx != NULL) {
|
|
|
|
|
cnt = StreamPatternSearch(th_v, det_ctx, p, smsg, flags);
|
|
|
|
|
SCLogDebug("cnt %u", cnt);
|
|
|
|
|
sms_runflags |= SMS_USED_STREAM_PM;
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug("smsg NULL (%p) or det_ctx->sgh->mpm_stream_ctx NULL (%p)", smsg, det_ctx->sgh->mpm_stream_ctx);
|
|
|
|
|
}
|
|
|
|
@ -846,22 +844,16 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug("search: (%p, maxlen %" PRIu32 ", sgh->sig_cnt %" PRIu32 ")",
|
|
|
|
|
det_ctx->sgh, det_ctx->sgh->mpm_content_maxlen, det_ctx->sgh->sig_cnt);
|
|
|
|
|
#if 0
|
|
|
|
|
if (det_ctx->sgh->mpm_content_maxlen == 1) det_ctx->pkts_searched1++;
|
|
|
|
|
else if (det_ctx->sgh->mpm_content_maxlen == 2) det_ctx->pkts_searched2++;
|
|
|
|
|
else if (det_ctx->sgh->mpm_content_maxlen == 3) det_ctx->pkts_searched3++;
|
|
|
|
|
else if (det_ctx->sgh->mpm_content_maxlen == 4) det_ctx->pkts_searched4++;
|
|
|
|
|
else det_ctx->pkts_searched++;
|
|
|
|
|
#endif
|
|
|
|
|
cnt = PacketPatternSearch(th_v, det_ctx, p);
|
|
|
|
|
SCLogDebug("post search: cnt %" PRIu32, cnt);
|
|
|
|
|
sms_runflags |= SMS_USED_PM;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
det_ctx->de_mpm_scanned_uri = FALSE;
|
|
|
|
|
|
|
|
|
|
/* stateful app layer detection */
|
|
|
|
|
if (p->flags & PKT_HAS_FLOW && alstate != NULL) {
|
|
|
|
|
det_ctx->de_mpm_scanned_uri = FALSE;
|
|
|
|
|
|
|
|
|
|
/* initialize to 0 (DE_STATE_MATCH_NOSTATE) */
|
|
|
|
|
memset(det_ctx->de_state_sig_array, 0x00, det_ctx->de_state_sig_array_len);
|
|
|
|
|
|
|
|
|
@ -928,7 +920,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
|
|
|
|
|
|
|
|
|
|
if (s->flags & SIG_FLAG_DSIZE && s->dsize_sm != NULL) {
|
|
|
|
|
if (sigmatch_table[DETECT_DSIZE].Match(th_v, det_ctx, p, s, s->dsize_sm) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
goto next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check the payload keywords. If we are a MPM sig and we've made
|
|
|
|
@ -1109,23 +1101,27 @@ end:
|
|
|
|
|
/* so now let's iterate the alerts and remove the ones after a pass rule
|
|
|
|
|
* matched (if any). This is done inside PacketAlertFinalize() */
|
|
|
|
|
/* PR: installed "tag" keywords are handled after the threshold inspection */
|
|
|
|
|
|
|
|
|
|
PacketAlertFinalize(de_ctx, det_ctx, p);
|
|
|
|
|
if (p->alerts.cnt > 0) {
|
|
|
|
|
SCPerfCounterAddUI64(det_ctx->counter_alerts, det_ctx->tv->sc_perf_pca, (uint64_t)p->alerts.cnt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* cleanup pkt specific part of the patternmatcher */
|
|
|
|
|
PacketPatternCleanup(th_v, det_ctx);
|
|
|
|
|
if (smsg != NULL) {
|
|
|
|
|
StreamPatternCleanup(th_v, det_ctx, smsg);
|
|
|
|
|
if (sms_runflags & SMS_USED_PM) {
|
|
|
|
|
PacketPatternCleanup(th_v, det_ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* store the found sgh (or NULL) in the flow to save us from looking it
|
|
|
|
|
* up again for the next packet. Also return any stream chunk we processed
|
|
|
|
|
* to the pool. */
|
|
|
|
|
if (p->flags & PKT_HAS_FLOW) {
|
|
|
|
|
if (sms_runflags & SMS_USED_STREAM_PM) {
|
|
|
|
|
StreamPatternCleanup(th_v, det_ctx, smsg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCMutexLock(&p->flow->m);
|
|
|
|
|
if (no_store_flow_sgh == FALSE) {
|
|
|
|
|
if (!(sms_runflags & SMS_USE_FLOW_SGH)) {
|
|
|
|
|
if (p->flowflags & FLOW_PKT_TOSERVER && !(p->flow->flags & FLOW_SGH_TOSERVER)) {
|
|
|
|
|
p->flow->sgh_toserver = det_ctx->sgh;
|
|
|
|
|
p->flow->flags |= FLOW_SGH_TOSERVER;
|
|
|
|
|