/** * \brief Given a BmCtx structure, recreate the pre/suffixes for * nocase * * \retval BmCtx pointer to the already created BmCtx (with BoyerMooreCtxInit()) * \param str pointer to the pattern string * \param size length of the string */ void BoyerMooreCtxToNocase(BmCtx *bm_ctx, uint8_t *needle, uint16_t needle_len) { /* Store the content as lower case to make searching faster */ memcpy_tolower(needle, needle, needle_len); /* Prepare bad chars with nocase chars */ PreBmBcNocase(needle, needle_len, bm_ctx->bmBc); /* Prepare good Suffixes with nocase chars */ PreBmGsNocase(needle, needle_len, bm_ctx->bmGs); }
/** * \brief Figured out the FP and their respective content ids for all the * sigs in the engine. * * \param de_ctx Detection engine context. * * \retval 0 On success. * \retval -1 On failure. */ int DetectSetFastPatternAndItsId(DetectEngineCtx *de_ctx) { uint32_t struct_total_size = 0; uint32_t content_total_size = 0; Signature *s = NULL; /* Count the amount of memory needed to store all the structures * and the content of those structures. This will over estimate the * true size, since duplicates are removed below, but counted here. */ for (s = de_ctx->sig_list; s != NULL; s = s->next) { RetrieveFPForSig(s); if (s->mpm_sm != NULL) { DetectContentData *cd = (DetectContentData *)s->mpm_sm->ctx; struct_total_size += sizeof(DetectFPAndItsId); content_total_size += cd->content_len; } } /* array hash buffer - i've run out of ideas to name it */ uint8_t *ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size)); if (unlikely(ahb == NULL)) return -1; uint8_t *content = NULL; uint8_t content_len = 0; PatIntId max_id = 0; DetectFPAndItsId *struct_offset = (DetectFPAndItsId *)ahb; uint8_t *content_offset = ahb + struct_total_size; for (s = de_ctx->sig_list; s != NULL; s = s->next) { if (s->mpm_sm != NULL) { int sm_list = SigMatchListSMBelongsTo(s, s->mpm_sm); BUG_ON(sm_list == -1); DetectContentData *cd = (DetectContentData *)s->mpm_sm->ctx; DetectFPAndItsId *dup = (DetectFPAndItsId *)ahb; if (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) { content = cd->content + cd->fp_chop_offset; content_len = cd->fp_chop_len; } else { content = cd->content; content_len = cd->content_len; } uint32_t flags = cd->flags & DETECT_CONTENT_NOCASE; /* Check for content already found on the same list */ for (; dup != struct_offset; dup++) { if (dup->content_len != content_len) continue; if (dup->sm_list != sm_list) continue; if (dup->flags != flags) continue; /* Check for pattern matching a duplicate. Use case insensitive matching * for case insensitive patterns. */ if (flags & DETECT_CONTENT_NOCASE) { if (SCMemcmpLowercase(dup->content, content, content_len) != 0) continue; } else { /* Case sensitive matching */ if (SCMemcmp(dup->content, content, content_len) != 0) continue; } /* Found a match with a previous pattern. */ break; } if (dup != struct_offset) { /* Exited for-loop before the end, so found an existing match. * Use its ID. */ cd->id = dup->id; continue; } /* Not found, so new content. Give it a new ID and add it * to the array. Copy the content at the end of the * content array. */ struct_offset->id = max_id++; cd->id = struct_offset->id; struct_offset->content_len = content_len; struct_offset->sm_list = sm_list; struct_offset->content = content_offset; struct_offset->flags = flags; content_offset += content_len; if (flags & DETECT_CONTENT_NOCASE) { /* Need to store case-insensitive patterns as lower case * because SCMemcmpLowercase() above assumes that all * patterns are stored lower case so that it doesn't * need to relower its first argument. */ memcpy_tolower(struct_offset->content, content, content_len); } else { memcpy(struct_offset->content, content, content_len); } struct_offset++; } /* if (s->mpm_sm != NULL) */ } /* for */ de_ctx->max_fp_id = max_id; SCFree(ahb); return 0; }
/** * \internal * \brief Add a pattern to the mpm-ac context. * * \param mpm_ctx Mpm context. * \param pat Pointer to the pattern. * \param patlen Length of the pattern. * \param pid Pattern id * \param sid Signature id (internal id). * \param flags Pattern's MPM_PATTERN_* flags. * * \retval 0 On success. * \retval -1 On failure. */ int MpmAddPattern(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags) { SCLogDebug("Adding pattern for ctx %p, patlen %"PRIu16" and pid %" PRIu32, mpm_ctx, patlen, pid); if (patlen == 0) { SCLogWarning(SC_ERR_INVALID_ARGUMENTS, "pattern length 0"); return 0; } if (flags & MPM_PATTERN_CTX_OWNS_ID) pid = UINT_MAX; /* check if we have already inserted this pattern */ MpmPattern *p = MpmInitHashLookup(mpm_ctx, pat, patlen, flags, pid); if (p == NULL) { SCLogDebug("Allocing new pattern"); /* p will never be NULL */ p = MpmAllocPattern(mpm_ctx); p->len = patlen; p->flags = flags; if (flags & MPM_PATTERN_CTX_OWNS_ID) p->id = mpm_ctx->max_pat_id++; else p->id = pid; p->original_pat = SCMalloc(patlen); if (p->original_pat == NULL) goto error; mpm_ctx->memory_cnt++; mpm_ctx->memory_size += patlen; memcpy(p->original_pat, pat, patlen); p->ci = SCMalloc(patlen); if (p->ci == NULL) goto error; mpm_ctx->memory_cnt++; mpm_ctx->memory_size += patlen; memcpy_tolower(p->ci, pat, patlen); /* setup the case sensitive part of the pattern */ if (p->flags & MPM_PATTERN_FLAG_NOCASE) { /* nocase means no difference between cs and ci */ p->cs = p->ci; } else { if (memcmp(p->ci, pat, p->len) == 0) { /* no diff between cs and ci: pat is lowercase */ p->cs = p->ci; } else { p->cs = SCMalloc(patlen); if (p->cs == NULL) goto error; mpm_ctx->memory_cnt++; mpm_ctx->memory_size += patlen; memcpy(p->cs, pat, patlen); } } /* put in the pattern hash */ MpmInitHashAdd(mpm_ctx, p); mpm_ctx->pattern_cnt++; if (mpm_ctx->maxlen < patlen) mpm_ctx->maxlen = patlen; if (mpm_ctx->minlen == 0) { mpm_ctx->minlen = patlen; } else { if (mpm_ctx->minlen > patlen) mpm_ctx->minlen = patlen; } /* we need the max pat id */ if (p->id > mpm_ctx->max_pat_id) mpm_ctx->max_pat_id = p->id; p->sids_size = 1; p->sids = SCMalloc(p->sids_size * sizeof(SigIntId)); BUG_ON(p->sids == NULL); p->sids[0] = sid; } else { /* we can be called multiple times for the same sid in the case * of the 'single' modus. Here multiple rule groups share the * same mpm ctx and might be adding the same pattern to the * mpm_ctx */ int found = 0; uint32_t x = 0; for (x = 0; x < p->sids_size; x++) { if (p->sids[x] == sid) { found = 1; break; } } if (!found) { SigIntId *sids = SCRealloc(p->sids, (sizeof(SigIntId) * (p->sids_size + 1))); BUG_ON(sids == NULL); p->sids = sids; p->sids[p->sids_size] = sid; p->sids_size++; } } return 0; error: MpmFreePattern(mpm_ctx, p); return -1; }