From d41b5645efb283e112421db8422438c1806547da Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Wed, 30 Jun 2010 19:59:57 +0200 Subject: [PATCH] Make sure decoder event rules are inspected even if the packet is invalid and has no addesses or proto. Update fast log and alert debug log to display the alerts. Fixes #179. --- src/alert-debuglog.c | 45 ++++++++++++++++++++ src/alert-fastlog.c | 46 +++++++++++++++++++++ src/detect-decode-event.c | 1 + src/detect.c | 87 ++++++++++++++++++++++++++++++++++++--- src/detect.h | 4 ++ src/util-print.c | 22 ++++++++++ src/util-print.h | 5 ++- 7 files changed, 202 insertions(+), 8 deletions(-) diff --git a/src/alert-debuglog.c b/src/alert-debuglog.c index bd31517ecd..df2532271f 100644 --- a/src/alert-debuglog.c +++ b/src/alert-debuglog.c @@ -323,12 +323,57 @@ TmEcode AlertDebugLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq return TM_ECODE_OK; } +TmEcode AlertDebugLogDecoderEvent(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) +{ + AlertDebugLogThread *aft = (AlertDebugLogThread *)data; + int i; + char timebuf[64]; + + if (p->alerts.cnt == 0) + return TM_ECODE_OK; + + CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); + + SCMutexLock(&aft->file_ctx->fp_mutex); + + fprintf(aft->file_ctx->fp, "+================\n"); + fprintf(aft->file_ctx->fp, "TIME: %s\n", timebuf); + if (p->pcap_cnt > 0) { + fprintf(aft->file_ctx->fp, "PCAP PKT NUM: %"PRIu64"\n", p->pcap_cnt); + } + fprintf(aft->file_ctx->fp, "ALERT CNT: %" PRIu32 "\n", p->alerts.cnt); + + for (i = 0; i < p->alerts.cnt; i++) { + PacketAlert *pa = &p->alerts.alerts[i]; + + fprintf(aft->file_ctx->fp, "ALERT MSG [%02d]: %s\n", i, pa->msg); + fprintf(aft->file_ctx->fp, "ALERT GID [%02d]: %" PRIu32 "\n", i, pa->gid); + fprintf(aft->file_ctx->fp, "ALERT SID [%02d]: %" PRIu32 "\n", i, pa->sid); + fprintf(aft->file_ctx->fp, "ALERT REV [%02d]: %" PRIu32 "\n", i, pa->rev); + fprintf(aft->file_ctx->fp, "ALERT CLASS [%02d]: %s\n", i, pa->class_msg); + fprintf(aft->file_ctx->fp, "ALERT PRIO [%02d]: %" PRIu32 "\n", i, pa->prio); + } + + aft->file_ctx->alerts += p->alerts.cnt; + + fprintf(aft->file_ctx->fp, "PACKET LEN: %" PRIu32 "\n", p->pktlen); + fprintf(aft->file_ctx->fp, "PACKET:\n"); + PrintRawDataFp(aft->file_ctx->fp, p->pkt, p->pktlen); + + fflush(aft->file_ctx->fp); + SCMutexUnlock(&aft->file_ctx->fp_mutex); + + return TM_ECODE_OK; +} + TmEcode AlertDebugLog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { if (PKT_IS_IPV4(p)) { return AlertDebugLogIPv4(tv, p, data, pq, postpq); } else if (PKT_IS_IPV6(p)) { return AlertDebugLogIPv6(tv, p, data, pq, postpq); + } else { + return AlertDebugLogDecoderEvent(tv, p, data, pq, postpq); } return TM_ECODE_OK; diff --git a/src/alert-fastlog.c b/src/alert-fastlog.c index 2f3adec06f..fb701399fc 100644 --- a/src/alert-fastlog.c +++ b/src/alert-fastlog.c @@ -55,6 +55,7 @@ #include "util-mpm-b2g-cuda.h" #include "util-cuda-handlers.h" #include "util-privs.h" +#include "util-print.h" #define DEFAULT_LOG_FILENAME "fast.log" @@ -202,12 +203,57 @@ TmEcode AlertFastLogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, return TM_ECODE_OK; } +TmEcode AlertFastLogDecoderEvent(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) +{ + AlertFastLogThread *aft = (AlertFastLogThread *)data; + int i; + Reference *ref = NULL; + char timebuf[64]; + + if (p->alerts.cnt == 0) + return TM_ECODE_OK; + + CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); + + SCMutexLock(&aft->file_ctx->fp_mutex); + + aft->file_ctx->alerts += p->alerts.cnt; + + for (i = 0; i < p->alerts.cnt; i++) { + PacketAlert *pa = &p->alerts.alerts[i]; + + fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] [**] [Raw pkt: ", + timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio); + + PrintRawLineHexFp(aft->file_ctx->fp, p->pkt, p->pktlen < 32 ? p->pktlen : 32); + if (p->pcap_cnt != 0) { + fprintf(aft->file_ctx->fp, "] [pcap file packet: %"PRIu64"]", p->pcap_cnt); + } + + if(pa->references != NULL) { + fprintf(aft->file_ctx->fp," "); + for (ref = pa->references; ref != NULL; ref = ref->next) { + fprintf(aft->file_ctx->fp,"[Xref => %s%s]", ref->key, ref->reference); + } + } + + fprintf(aft->file_ctx->fp,"\n"); + + fflush(aft->file_ctx->fp); + } + SCMutexUnlock(&aft->file_ctx->fp_mutex); + + return TM_ECODE_OK; +} + TmEcode AlertFastLog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { if (PKT_IS_IPV4(p)) { return AlertFastLogIPv4(tv, p, data, pq, postpq); } else if (PKT_IS_IPV6(p)) { return AlertFastLogIPv6(tv, p, data, pq, postpq); + } else { + return AlertFastLogDecoderEvent(tv, p, data, pq, postpq); } return TM_ECODE_OK; diff --git a/src/detect-decode-event.c b/src/detect-decode-event.c index e4b26f901c..ab30ed2ead 100644 --- a/src/detect-decode-event.c +++ b/src/detect-decode-event.c @@ -59,6 +59,7 @@ void DetectDecodeEventRegister (void) { sigmatch_table[DETECT_DECODE_EVENT].Setup = DetectDecodeEventSetup; sigmatch_table[DETECT_DECODE_EVENT].Free = NULL; sigmatch_table[DETECT_DECODE_EVENT].RegisterTests = DecodeEventRegisterTests; + sigmatch_table[DETECT_DECODE_EVENT].flags |= SIGMATCH_DEONLY_COMPAT; const char *eb; int eo; diff --git a/src/detect.c b/src/detect.c index cca6d79a8e..16ed751f04 100644 --- a/src/detect.c +++ b/src/detect.c @@ -520,6 +520,12 @@ SigGroupHead *SigMatchSignaturesGetSgh(DetectEngineCtx *de_ctx, DetectEngineThre int f; SigGroupHead *sgh = NULL; + /* if the packet proto is 0 (not set), we're inspecting it against + * the decoder events sgh we have. */ + if (p->proto == 0 && p->events.cnt > 0) { + SCReturnPtr(de_ctx->decoder_event_sgh, "SigGroupHead"); + } + /* select the flow_gh */ if (p->flowflags & FLOW_PKT_TOCLIENT) f = 0; @@ -1222,8 +1228,10 @@ iponly: } return 1; } + /** - * \brief Check if the initialized signature is inspecting the packet payload + * \internal + * \brief Check if the initialized signature is inspecting the packet payload * \param de_ctx detection engine ctx * \param s the signature * \retval 1 sig is inspecting the payload @@ -1250,6 +1258,43 @@ static int SignatureIsInspectingPayload(DetectEngineCtx *de_ctx, Signature *s) { return 0; } +/** + * \internal + * \brief check if a signature is decoder event matching only + * \param de_ctx detection engine + * \param s the signature to test + * \retval 0 not a DEOnly sig + * \retval 1 DEOnly sig + */ +static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, Signature *s) { + if (s->pmatch != NULL) + return 0; + + if (s->umatch != NULL) + return 0; + + if (s->amatch != NULL) + return 0; + + SigMatch *sm = s->match; + if (sm == NULL) + goto deonly; + + for ( ;sm != NULL; sm = sm->next) { + if ( !(sigmatch_table[sm->type].flags & SIGMATCH_DEONLY_COMPAT)) + return 0; + } + +deonly: + if (!(de_ctx->flags & DE_QUIET)) { + SCLogDebug("DE-ONLY (%" PRIu32 "): source %s, dest %s", s->id, + s->flags & SIG_FLAG_SRC_ANY ? "ANY" : "SET", + s->flags & SIG_FLAG_DST_ANY ? "ANY" : "SET"); + } + + return 1; +} + /** * \brief Add all signatures to their own source address group * @@ -1303,6 +1348,9 @@ int SigAddressPrepareStage1(DetectEngineCtx *de_ctx) { cnt_payload++; SCLogDebug("Signature %"PRIu32" is considered \"Payload inspecting\"", tmp_s->id); + } else if (SignatureIsDEOnly(de_ctx, tmp_s) == 1) { + tmp_s->flags |= SIG_FLAG_DEONLY; + SCLogDebug("Signature %"PRIu32" is considered \"Decoder Event only\"", tmp_s->id); } if (tmp_s->flags & SIG_FLAG_APPLAYER) { @@ -1829,6 +1877,15 @@ error: return -1; } +/** + * \internal + * \brief add a decoder event signature to the detection engine ctx + */ +static void DetectEngineAddDecoderEventSig(DetectEngineCtx *de_ctx, Signature *s) { + SCLogDebug("adding signature %"PRIu32" to the decoder event sgh", s->id); + SigGroupHeadAppendSig(de_ctx, &de_ctx->decoder_event_sgh, s); +} + /** * \brief Fill the global src group head, with the sigs included * @@ -1866,13 +1923,15 @@ int SigAddressPrepareStage2(DetectEngineCtx *de_ctx) { /* now for every rule add the source group to our temp lists */ for (tmp_s = de_ctx->sig_list; tmp_s != NULL; tmp_s = tmp_s->next) { - //printf("SigAddressPrepareStage2 tmp_s->id %u\n", tmp_s->id); - if (!(tmp_s->flags & SIG_FLAG_IPONLY)) { + SCLogDebug("tmp_s->id %"PRIu32, tmp_s->id); + if (tmp_s->flags & SIG_FLAG_IPONLY) { + IPOnlyAddSignature(de_ctx, &de_ctx->io_ctx, tmp_s); + } else if (tmp_s->flags & SIG_FLAG_DEONLY) { + DetectEngineAddDecoderEventSig(de_ctx, tmp_s); + } else { DetectEngineLookupFlowAddSig(de_ctx, tmp_s, AF_INET); DetectEngineLookupFlowAddSig(de_ctx, tmp_s, AF_INET6); DetectEngineLookupFlowAddSig(de_ctx, tmp_s, AF_UNSPEC); - } else { - IPOnlyAddSignature(de_ctx, &de_ctx->io_ctx, tmp_s); } sigs++; @@ -2521,6 +2580,15 @@ error: return -1; } +static void DetectEngineBuildDecoderEventSgh(DetectEngineCtx *de_ctx) { + if (de_ctx->decoder_event_sgh == NULL) + return; + + uint32_t max_idx = DetectEngineGetMaxSigId(de_ctx); + SigGroupHeadSetSigCnt(de_ctx->decoder_event_sgh, max_idx); + SigGroupHeadBuildMatchArray(de_ctx, de_ctx->decoder_event_sgh, max_idx); +} + int SigAddressPrepareStage3(DetectEngineCtx *de_ctx) { int r; @@ -2587,6 +2655,9 @@ int SigAddressPrepareStage3(DetectEngineCtx *de_ctx) { } } + /* prepare the decoder event sgh */ + DetectEngineBuildDecoderEventSgh(de_ctx); + /* cleanup group head (uri)content_array's */ SigGroupHeadFreeMpmArrays(de_ctx); /* cleanup group head sig arrays */ @@ -2716,6 +2787,10 @@ int SigAddressPrepareStage4(DetectEngineCtx *de_ctx) { SigGroupHeadBuildHeadArray(de_ctx, sgh); } + if (de_ctx->decoder_event_sgh != NULL) { + SigGroupHeadBuildHeadArray(de_ctx, de_ctx->decoder_event_sgh); + } + SCFree(de_ctx->sgh_array); de_ctx->sgh_array_cnt = 0; de_ctx->sgh_array_size = 0; @@ -2740,7 +2815,7 @@ int SigAddressPrepareStage5(DetectEngineCtx *de_ctx) { for (f = 0; f < FLOW_STATES; f++) { printf("\n"); for (proto = 0; proto < 256; proto++) { - if (proto != 1) + if (proto != 0) continue; for (global_src_gr = de_ctx->flow_gh[f].src_gh[proto]->ipv4_head; global_src_gr != NULL; diff --git a/src/detect.h b/src/detect.h index d40d25605d..22ebb91b9f 100644 --- a/src/detect.h +++ b/src/detect.h @@ -487,6 +487,10 @@ typedef struct DetectEngineCtx_ { struct SigGroupHead_ **sgh_array; uint32_t sgh_array_cnt; uint32_t sgh_array_size; + + /** sgh for signatures that match against invalid packets. In those cases + * we can't lookup by proto, address, port as we don't have these */ + struct SigGroupHead_ *decoder_event_sgh; } DetectEngineCtx; /* Engine groups profiles (low, medium, high, custom) */ diff --git a/src/util-print.c b/src/util-print.c index 740bd7de5f..40357b477f 100644 --- a/src/util-print.c +++ b/src/util-print.c @@ -27,6 +27,28 @@ #include "util-error.h" #include "util-debug.h" +/** + * \brief print a buffer as hex on a single line + * + * Prints in the format "00 AA BB" + * + * \param fp FILE pointer to print to + * \param buf buffer to print from + * \param buflen length of the input buffer + */ +void PrintRawLineHexFp(FILE *fp, uint8_t *buf, uint32_t buflen) +{ + char nbuf[2048] = ""; + char temp[5] = ""; + uint32_t u = 0; + + for (u = 0; u < buflen; u++) { + snprintf(temp, sizeof(temp), "%02X ", buf[u]); + strlcat(nbuf, temp, sizeof(nbuf)); + } + fprintf(fp, "%s", nbuf); +} + void PrintRawUriFp(FILE *fp, uint8_t *buf, uint32_t buflen) { char nbuf[2048] = ""; diff --git a/src/util-print.h b/src/util-print.h index d273db17a5..94e6d807be 100644 --- a/src/util-print.h +++ b/src/util-print.h @@ -24,8 +24,9 @@ #ifndef __UTIL_PRINT_H__ #define __UTIL_PRINT_H__ -void PrintRawUriFp(FILE *fp, uint8_t *buf, uint32_t buflen); -void PrintRawDataFp(FILE *fp, uint8_t *buf, uint32_t buflen); +void PrintRawLineHexFp(FILE *, uint8_t *, uint32_t); +void PrintRawUriFp(FILE *, uint8_t *, uint32_t); +void PrintRawDataFp(FILE *, uint8_t *, uint32_t); #endif /* __UTIL_PRINT_H__ */