static int DetectHttpUriSetup (DetectEngineCtx *de_ctx, Signature *s, char *str) { DetectContentData *cd = NULL; SigMatch *sm = NULL; if (str != NULL && strcmp(str, "") != 0) { SCLogError(SC_ERR_INVALID_ARGUMENT, "http_uri shouldn't be supplied with " " an argument"); return -1; } sm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); if (sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "\"http_uri\" keyword " "found inside the rule without a content context. " "Please use a \"content\" keyword before using the " "\"http_uri\" keyword"); return -1; } cd = (DetectContentData *)sm->ctx; /* http_uri should not be used with the rawbytes rule */ if (cd->flags & DETECT_CONTENT_RAWBYTES) { SCLogError(SC_ERR_INVALID_SIGNATURE, "http_uri rule can not " "be used with the rawbytes rule keyword"); return -1; } if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains a non http " "alproto set"); goto error; } if (cd->flags & DETECT_CONTENT_WITHIN || cd->flags & DETECT_CONTENT_DISTANCE) { SigMatch *pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, sm->prev, DETECT_PCRE, sm->prev); /* pm can be NULL now. To accomodate parsing sigs like - * content:one; http_modifier; content:two; distance:0; http_modifier */ if (pm != NULL) { if (pm->type == DETECT_CONTENT) { DetectContentData *tmp_cd = (DetectContentData *)pm->ctx; tmp_cd->flags &= ~DETECT_CONTENT_RELATIVE_NEXT; } else { DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; tmp_pd->flags &= ~DETECT_PCRE_RELATIVE_NEXT; } } /* if (pm != NULL) */ /* reassigning pm */ pm = SigMatchGetLastSMFromLists(s, 2, DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH]); if (pm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "uricontent seen with a " "distance or within without a previous http_uri " "content. Invalidating signature."); goto error; } DetectContentData *tmp_cd = (DetectContentData *)pm->ctx; tmp_cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; } cd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, cd, DETECT_URICONTENT); sm->type = DETECT_URICONTENT; /* transfer the sm from the pmatch list to hcbdmatch list */ SigMatchTransferSigMatchAcrossLists(sm, &s->sm_lists[DETECT_SM_LIST_PMATCH], &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], &s->sm_lists[DETECT_SM_LIST_UMATCH], &s->sm_lists_tail[DETECT_SM_LIST_UMATCH]); /* Flagged the signature as to inspect the app layer data */ s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_HTTP; return 0; error: return -1; }
/** * \brief This function is used to add the parsed isdataatdata into the current * signature. * \param de_ctx pointer to the Detection Engine Context * \param s pointer to the Current Signature * \param isdataatstr pointer to the user provided isdataat options * * \retval 0 on Success * \retval -1 on Failure */ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatstr) { DetectIsdataatData *idad = NULL; SigMatch *sm = NULL; SigMatch *dm = NULL; SigMatch *pm = NULL; SigMatch *prev_pm = NULL; char *offset = NULL; idad = DetectIsdataatParse(isdataatstr, &offset); if (idad == NULL) goto error; sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_ISDATAAT; sm->ctx = (void *)idad; if (s->alproto == ALPROTO_DCERPC && idad->flags & ISDATAAT_RELATIVE) { pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); dm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); if (pm == NULL) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DMATCH); } else if (dm == NULL) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DMATCH); } else if (pm->idx > dm->idx) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_PMATCH); } else { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DMATCH); } prev_pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, sm->prev, DETECT_BYTEJUMP, sm->prev, DETECT_PCRE, sm->prev); if (prev_pm == NULL) { SCLogDebug("No preceding content or pcre keyword. Possible " "since this is a dce alproto sig."); if (offset != NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " "seen in isdataat - %s", offset); goto error; } return 0; } } else if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) { if (idad->flags & ISDATAAT_RELATIVE) { pm = SigMatchGetLastSMFromLists(s, 10, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH]); if (pm == NULL) { idad->flags &= ~ISDATAAT_RELATIVE; } s->flags |= SIG_FLAG_APPLAYER; AppLayerHtpEnableResponseBodyCallback(); SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH); } else { s->flags |= SIG_FLAG_APPLAYER; AppLayerHtpEnableResponseBodyCallback(); SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH); } if (pm == NULL) { SCLogDebug("No preceding content or pcre keyword. Possible " "since this is a file_data sig."); if (offset != NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " "seen in isdataat - %s", offset); goto error; } return 0; } prev_pm = pm; } else { if (!(idad->flags & ISDATAAT_RELATIVE)) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_PMATCH); if (offset != NULL) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(offset, s, SigMatchListSMBelongsTo(s, sm)); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " "seen in isdataat - %s\n", offset); goto error; } DetectIsdataatData *isdd = sm->ctx; isdd->dataat = ((DetectByteExtractData *)bed_sm->ctx)->local_id; isdd->flags |= ISDATAAT_OFFSET_BE; SCFree(offset); } return 0; } pm = SigMatchGetLastSMFromLists(s, 56, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_UMATCH]); if (pm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "isdataat relative seen " "without a previous content uricontent, " "http_client_body, http_header, http_raw_header, " "http_method, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code, byte_test, " "byte_extract, byte_jump or http_user_agent keyword"); goto error; } else { int list_type = SigMatchListSMBelongsTo(s, pm); if (list_type == -1) { goto error; } SigMatchAppendSMToList(s, sm, list_type); } /* else - if (pm == NULL) */ prev_pm = pm; } if (offset != NULL) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(offset, s, SigMatchListSMBelongsTo(s, sm)); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " "seen in isdataat - %s\n", offset); goto error; } DetectIsdataatData *isdd = sm->ctx; isdd->dataat = ((DetectByteExtractData *)bed_sm->ctx)->local_id; isdd->flags |= ISDATAAT_OFFSET_BE; SCFree(offset); } DetectContentData *cd = NULL; DetectPcreData *pe = NULL; switch (prev_pm->type) { case DETECT_CONTENT: /* Set the relative next flag on the prev sigmatch */ cd = (DetectContentData *)prev_pm->ctx; if (cd == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; break; case DETECT_PCRE: pe = (DetectPcreData *)prev_pm->ctx; if (pe == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } pe->flags |= DETECT_PCRE_RELATIVE_NEXT; break; case DETECT_BYTEJUMP: case DETECT_BYTETEST: case DETECT_BYTE_EXTRACT: SCLogDebug("Do nothing for byte_jump, byte_test, byte_extract"); break; default: /* this will never hit */ SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } /* switch */ return 0; error: return -1; }
/** * \brief This function is used to add the parsed isdataatdata into the current * signature. * \param de_ctx pointer to the Detection Engine Context * \param s pointer to the Current Signature * \param isdataatstr pointer to the user provided isdataat options * * \retval 0 on Success * \retval -1 on Failure */ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, char *isdataatstr) { DetectIsdataatData *idad = NULL; SigMatch *sm = NULL; SigMatch *dm = NULL; SigMatch *pm = NULL; SigMatch *prev_pm = NULL; idad = DetectIsdataatParse(isdataatstr); if (idad == NULL) goto error; sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_ISDATAAT; sm->ctx = (void *)idad; if (s->alproto == ALPROTO_DCERPC && idad->flags & ISDATAAT_RELATIVE) { pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); dm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); if (pm == NULL) { SigMatchAppendDcePayload(s, sm); } else if (dm == NULL) { SigMatchAppendDcePayload(s, sm); } else if (pm->idx > dm->idx) { SigMatchAppendPayload(s, sm); } else { SigMatchAppendDcePayload(s, sm); } prev_pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, sm->prev, DETECT_BYTEJUMP, sm->prev, DETECT_PCRE, sm->prev); } else { pm = SigMatchGetLastSMFromLists(s, 30, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_AL_HTTP_RAW_HEADER, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); if (pm == NULL) { if (idad->flags & ISDATAAT_RELATIVE) { SCLogError(SC_ERR_INVALID_SIGNATURE, "isdataat relative seen " "without a previous content uricontent, " "http_client_body, http_header, http_raw_header, " "http_method or http_cookie keyword"); goto error; } else { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_PMATCH); } } else { int list_type; if (pm->type == DETECT_PCRE || pm->type == DETECT_BYTEJUMP) { list_type = SigMatchListSMBelongsTo(s, pm); if (list_type == -1) { goto error; } } else { switch (pm->type) { case DETECT_CONTENT: list_type = DETECT_SM_LIST_PMATCH; break; case DETECT_URICONTENT: list_type = DETECT_SM_LIST_UMATCH; break; case DETECT_AL_HTTP_CLIENT_BODY: list_type = DETECT_SM_LIST_HCBDMATCH; break; case DETECT_AL_HTTP_RAW_HEADER: list_type = DETECT_SM_LIST_HRHDMATCH; break; case DETECT_AL_HTTP_HEADER: list_type = DETECT_SM_LIST_HHDMATCH; break; case DETECT_AL_HTTP_METHOD: list_type = DETECT_SM_LIST_HMDMATCH; break; case DETECT_AL_HTTP_COOKIE: list_type = DETECT_SM_LIST_HCDMATCH; break; } /* switch */ } /* else */ SigMatchAppendSMToList(s, sm, list_type); } /* else - if (pm == NULL) */ prev_pm = pm; } if (!(idad->flags & ISDATAAT_RELATIVE)) { return 0; } if (prev_pm == NULL) { if (s->alproto == ALPROTO_DCERPC) { SCLogDebug("No preceding content or pcre keyword. Possible " "since this is a dce alproto sig."); return 0; } else { SCLogError(SC_ERR_INVALID_SIGNATURE, "No preceding content, pcre, " "uricontent, http_client_body, http_header, " "http_raw_header, http_method or http_cookie keyword"); goto error; } } DetectContentData *cd = NULL; DetectPcreData *pe = NULL; switch (prev_pm->type) { case DETECT_CONTENT: case DETECT_URICONTENT: case DETECT_AL_HTTP_CLIENT_BODY: case DETECT_AL_HTTP_HEADER: case DETECT_AL_HTTP_RAW_HEADER: case DETECT_AL_HTTP_METHOD: case DETECT_AL_HTTP_COOKIE: /* Set the relative next flag on the prev sigmatch */ cd = (DetectContentData *)prev_pm->ctx; if (cd == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; break; case DETECT_PCRE: pe = (DetectPcreData *)prev_pm->ctx; if (pe == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } pe->flags |= DETECT_PCRE_RELATIVE_NEXT; break; case DETECT_BYTEJUMP: SCLogDebug("Do nothing for bytejump"); break; default: /* this will never hit */ SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } /* switch */ return 0; error: //if (idad != NULL) // DetectIsdataatFree(idad); //if (sm != NULL) // SCFree(sm); return -1; }
int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr) { char *str = offsetstr; char dubbed = 0; SigMatch *pm = NULL; int ret = -1; /* strip "'s */ if (offsetstr[0] == '\"' && offsetstr[strlen(offsetstr)-1] == '\"') { str = SCStrdup(offsetstr+1); if (unlikely(str == NULL)) goto end; str[strlen(offsetstr) - 2] = '\0'; dubbed = 1; } /* retrive the sm to apply the depth against */ if (s->list != DETECT_SM_LIST_NOTSET) { pm = SigMatchGetLastSMFromLists(s, 2, DETECT_CONTENT, s->sm_lists_tail[s->list]); } else { pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); } if (pm == NULL) { SCLogError(SC_ERR_OFFSET_MISSING_CONTENT, "offset needs " "preceding content, uricontent option, http_client_body, " "http_server_body, http_header option, http_raw_header option, " "http_method option, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code, http_user_agent or " "file_data/dce_stub_data sticky buffer options"); goto end; } /* verify other conditions */ DetectContentData *cd = (DetectContentData *)pm->ctx; if (cd->flags & DETECT_CONTENT_OFFSET) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use multiple offsets for the same content. "); goto end; } if ((cd->flags & DETECT_CONTENT_WITHIN) || (cd->flags & DETECT_CONTENT_DISTANCE)) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use a relative " "keyword like within/distance with a absolute " "relative keyword like depth/offset for the same " "content." ); goto end; } if (cd->flags & DETECT_CONTENT_NEGATED && cd->flags & DETECT_CONTENT_FAST_PATTERN) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "negated keyword set along with a fast_pattern"); goto end; } if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "keyword set along with a fast_pattern:only;"); goto end; } if (str[0] != '-' && isalpha((unsigned char)str[0])) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(str, s, SigMatchListSMBelongsTo(s, pm)); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "unknown byte_extract var " "seen in offset - %s\n", str); goto end; } cd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; cd->flags |= DETECT_CONTENT_OFFSET_BE; } else { cd->offset = (uint32_t)atoi(str); if (cd->depth != 0) { if (cd->depth < cd->content_len) { SCLogDebug("depth increased to %"PRIu32" to match pattern len", cd->content_len); cd->depth = cd->content_len; } /* Updating the depth as is relative to the offset */ cd->depth += cd->offset; } } cd->flags |= DETECT_CONTENT_OFFSET; ret = 0; end: if (dubbed) SCFree(str); return ret; }
static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depthstr) { char *str = depthstr; char dubbed = 0; SigMatch *pm = NULL; DetectContentData *cd = NULL; /* strip "'s */ if (depthstr[0] == '\"' && depthstr[strlen(depthstr) - 1] == '\"') { str = SCStrdup(depthstr + 1); if (str == NULL) goto error; str[strlen(depthstr) - 2] = '\0'; dubbed = 1; } switch (s->alproto) { case ALPROTO_DCERPC: /* add to the latest content keyword from either dmatch or pmatch */ pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); if (pm == NULL) { SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs " "preceding content option for dcerpc sig"); if (dubbed) SCFree(str); return -1; } break; default: pm = SigMatchGetLastSMFromLists(s, 24, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH]); if (pm == NULL) { SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs " "preceding content, uricontent option, http_client_body, " "http_server_body, http_header option, http_raw_header option, " "http_method option, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code or http_user_agent option"); if (dubbed) SCFree(str); return -1; } break; } /* i swear we will clean this up :). Use a single version for all. Using * separate versions for all now, to avoiding breaking any code */ switch (pm->type) { case DETECT_CONTENT: cd = (DetectContentData *)pm->ctx; if (cd == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "invalid argument"); if (dubbed) SCFree(str); return -1; } if (cd->flags & DETECT_CONTENT_NEGATED) { if (cd->flags & DETECT_CONTENT_FAST_PATTERN) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "negated keyword set along with a fast_pattern"); goto error; } } else { if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "keyword set along with a fast_pattern:only;"); goto error; } } if (cd->flags & DETECT_CONTENT_WITHIN || cd->flags & DETECT_CONTENT_DISTANCE) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use a relative keyword " "with a non-relative keyword for the same content." ); goto error; } if (cd->flags & DETECT_CONTENT_DEPTH) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use multiple depths for the same content."); goto error; } if (str[0] != '-' && isalpha(str[0])) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(str, s, SigMatchListSMBelongsTo(s, pm)); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "unknown byte_extract var " "seen in depth - %s\n", str); goto error; } cd->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; cd->flags |= DETECT_CONTENT_DEPTH_BE; } else { cd->depth = (uint32_t)atoi(str); if (cd->depth < cd->content_len) { uint32_t content_len = cd->content_len; SCLogError(SC_ERR_INVALID_SIGNATURE, "depth - %"PRIu16 " smaller than content length - %"PRIu32, cd->depth, content_len); goto error; } /* Now update the real limit, as depth is relative to the offset */ cd->depth += cd->offset; } cd->flags |= DETECT_CONTENT_DEPTH; break; default: SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs a preceding " "content (or uricontent) option"); goto error; } if (dubbed) SCFree(str); return 0; error: if (dubbed) SCFree(str); return -1; }
/** \brief Setup within pattern (content/uricontent) modifier. * * \todo apply to uricontent * * \retval 0 ok * \retval -1 error, sig needs to be invalidated */ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withinstr) { char *str = withinstr; char dubbed = 0; SigMatch *pm = NULL; /* strip "'s */ if (withinstr[0] == '\"' && withinstr[strlen(withinstr)-1] == '\"') { str = SCStrdup(withinstr+1); if (str == NULL) goto error; str[strlen(withinstr)-2] = '\0'; dubbed = 1; } /* if we still haven't found that the sig is related to DCERPC, * it's a direct entry into Signature->[DETECT_SM_LIST_PMATCH] */ if (s->alproto == ALPROTO_DCERPC) { SigMatch *dcem = NULL; SigMatch *dm = NULL; SigMatch *pm1 = NULL; SigMatch *pm1_ots = NULL; SigMatch *pm2_ots = NULL; dcem = SigMatchGetLastSMFromLists(s, 6, DETECT_DCE_IFACE, s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_DCE_OPNUM, s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_DCE_STUB_DATA, s->sm_lists_tail[DETECT_SM_LIST_AMATCH]); pm1_ots = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); if (pm1_ots != NULL && pm1_ots->prev != NULL) { pm2_ots = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, pm1_ots->prev, DETECT_PCRE, pm1_ots->prev, DETECT_BYTEJUMP, pm1_ots->prev); } dm = SigMatchGetLastSMFromLists(s, 2, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); pm1 = SigMatchGetLastSMFromLists(s, 2, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); if (dm == NULL && pm1 == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "\"within\" requires a " "preceding content keyword"); goto error; } if (dm == NULL) { if (pm2_ots == NULL) { if (pm1->idx > dcem->idx) { /* transfer pm1 to dmatch list and within is against this */ SigMatchTransferSigMatchAcrossLists(pm1, &s->sm_lists[DETECT_SM_LIST_PMATCH], &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], &s->sm_lists[DETECT_SM_LIST_DMATCH], &s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); pm = pm1; } else { /* within is against pm1 and we continue this way */ pm = pm1; } } else if (pm2_ots->idx > dcem->idx) { /* within is against pm1, pm = pm1; */ pm = pm1; } else if (pm1->idx > dcem->idx) { /* transfer pm1 to dmatch list and within is against this */ SigMatchTransferSigMatchAcrossLists(pm1, &s->sm_lists[DETECT_SM_LIST_PMATCH], &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], &s->sm_lists[DETECT_SM_LIST_DMATCH], &s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); pm = pm1; } else { /* within is against pm1 and we continue this way */ pm = pm1; } } else { if (pm1 == NULL) { /* within is against dm and continue this way */ pm = dm; } else if (dm->idx > pm1->idx) { /* within is against dm */ pm = dm; } else if (pm2_ots == NULL || pm2_ots->idx < dcem->idx) { /* trasnfer pm1 to dmatch list and pm = pm1 */ SigMatchTransferSigMatchAcrossLists(pm1, &s->sm_lists[DETECT_SM_LIST_PMATCH], &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], &s->sm_lists[DETECT_SM_LIST_DMATCH], &s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); pm = pm1; } else { /* within is against pm1, pm = pm1 */ pm = pm1; } } } else { pm = SigMatchGetLastSMFromLists(s, 24, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "\"within\" requires " "preceding content, uricontent, http_client_body, " "http_server_body, http_header, http_raw_header, " "http_method, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code or http_user_agent " "option"); if (dubbed) SCFree(str); return -1; } } DetectContentData *cd = NULL; DetectPcreData *pe = NULL; switch (pm->type) { case DETECT_CONTENT: cd = (DetectContentData *)pm->ctx; if (cd == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "content error"); goto error; } if (cd->flags & DETECT_CONTENT_NEGATED) { if (cd->flags & DETECT_CONTENT_FAST_PATTERN) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "negated keyword set along with a fast_pattern"); goto error; } } else { if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "keyword set along with a fast_pattern:only"); goto error; } } if (cd->flags & DETECT_CONTENT_DEPTH || cd->flags & DETECT_CONTENT_OFFSET) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use a relative keyword " "with a non-relative keyword for the same content" ); goto error; } if (str[0] != '-' && isalpha(str[0])) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(str, s, SigMatchListSMBelongsTo(s, pm)); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "unknown byte_extract var " "seen in within - %s\n", str); goto error; } cd->within = ((DetectByteExtractData *)bed_sm->ctx)->local_id; cd->flags |= DETECT_CONTENT_WITHIN_BE; } else { cd->within = strtol(str, NULL, 10); if (cd->within < (int32_t)cd->content_len) { SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is " "less than the content length \"%"PRIu32"\" which is invalid, since " "this will never match. Invalidating signature", cd->within, cd->content_len); goto error; } } cd->flags |= DETECT_CONTENT_WITHIN; pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, pm->prev, DETECT_PCRE, pm->prev, DETECT_BYTEJUMP, pm->prev); if (pm == NULL) { if (s->alproto == ALPROTO_DCERPC) { SCLogDebug("content relative without a previous content based " "keyword. Holds good only in the case of DCERPC " "alproto like now."); } else { //SCLogError(SC_ERR_INVALID_SIGNATURE, "No related " // "previous-previous content or pcre keyword"); //goto error; ; } } else { switch (pm->type) { case DETECT_CONTENT: /* Set the relative next flag on the prev sigmatch */ cd = (DetectContentData *)pm->ctx; if (cd == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "content error"); goto error; } cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "previous keyword " "has a fast_pattern:only; set. Can't " "have relative keywords around a fast_pattern " "only content"); goto error; } break; case DETECT_PCRE: pe = (DetectPcreData *) pm->ctx; if (pe == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "pcre error"); goto error; } pe->flags |= DETECT_PCRE_RELATIVE_NEXT; break; case DETECT_BYTEJUMP: SCLogDebug("no setting relative_next for bytejump. We " "have no use for it"); break; default: /* this will never hit */ SCLogError(SC_ERR_INVALID_SIGNATURE, "unsupported type %d", pm->type); break; } } break; default: SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs two " "preceding content or uricontent options"); goto error; } if (dubbed) SCFree(str); return 0; error: if (dubbed) SCFree(str); return -1; }
int DetectReplaceSetup(DetectEngineCtx *de_ctx, Signature *s, char *replacestr) { uint8_t *content = NULL; uint16_t len = 0; uint32_t flags = 0; SigMatch *pm = NULL; DetectContentData *ud = NULL; int ret = DetectContentDataParse("replace", replacestr, &content, &len, &flags); if (ret == -1) goto error; if (flags & DETECT_CONTENT_NEGATED) { SCLogError(SC_ERR_INVALID_VALUE, "Can't negate replacement string: %s", replacestr); goto error; } switch (run_mode) { case RUNMODE_NFQ: case RUNMODE_IPFW: break; default: SCLogWarning(SC_ERR_RUNMODE, "Can't use 'replace' keyword in non IPS mode: %s", s->sig_str); /* this is a success, having the alert is interesting */ return 0; } /* add to the latest "content" keyword from either dmatch or pmatch */ pm = SigMatchGetLastSMFromLists(s, 2, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); if (pm == NULL) { SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "replace needs" "preceding content option for raw sig"); SCFree(content); return -1; } /* we can remove this switch now with the unified structure */ ud = (DetectContentData *)pm->ctx; if (ud == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "invalid argument"); SCFree(content); return -1; } if (ud->flags & DETECT_CONTENT_NEGATED) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "negated keyword set along with a replacement"); goto error; } if (ud->content_len != len) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a content " "length different from replace length"); goto error; } ud->replace = SCMalloc(len); if (ud->replace == NULL) { goto error; } memcpy(ud->replace, content, len); ud->replace_len = len; ud->flags |= DETECT_CONTENT_REPLACE; /* want packet matching only won't be able to replace data with * a flow. */ s->flags |= SIG_FLAG_REQUIRE_PACKET; SCFree(content); return 0; error: SCFree(content); return -1; }
int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, char *optstr) { DetectBytejumpData *data = NULL; SigMatch *sm = NULL; char *offset = NULL; data = DetectBytejumpParse(optstr, &offset); if (data == NULL) goto error; sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_BYTEJUMP; sm->ctx = (void *)data; /* check bytejump modifiers against the signature alproto. In case they conflict * chuck out invalid signature */ if (data->flags & DETECT_BYTEJUMP_DCE) { if (s->alproto != ALPROTO_DCERPC) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Non dce alproto sig has " "bytetest with dce enabled"); goto error; } if ( (data->flags & DETECT_BYTEJUMP_STRING) || (data->flags & DETECT_BYTEJUMP_LITTLE) || (data->flags & DETECT_BYTEJUMP_BIG) || (data->flags & DETECT_BYTEJUMP_BEGIN) || (data->base == DETECT_BYTEJUMP_BASE_DEC) || (data->base == DETECT_BYTEJUMP_BASE_HEX) || (data->base == DETECT_BYTEJUMP_BASE_OCT) ) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "Invalid option. " "DCERPC rule holds an invalid modifier for bytejump."); goto error; } } if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) { if (data->flags & DETECT_BYTEJUMP_RELATIVE) { SigMatch *prev_sm = NULL; prev_sm = SigMatchGetLastSMFromLists(s, 8, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH]); if (prev_sm == NULL) { data->flags &= ~DETECT_BYTEJUMP_RELATIVE; } s->flags |= SIG_FLAG_APPLAYER; AppLayerHtpEnableResponseBodyCallback(); SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH); } else { s->flags |= SIG_FLAG_APPLAYER; AppLayerHtpEnableResponseBodyCallback(); SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH); } } else if (s->alproto == ALPROTO_DCERPC && (data->flags & DETECT_BYTEJUMP_RELATIVE)) { SigMatch *pm = NULL; SigMatch *dm = NULL; pm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); dm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_DMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_DMATCH]); if (pm == NULL) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DMATCH); } else if (dm == NULL) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DMATCH); } else if (pm->idx > dm->idx) { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_PMATCH); } else { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DMATCH); } } else { SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_PMATCH); } if (offset != NULL) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(offset, s, SigMatchListSMBelongsTo(s, sm)); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown byte_extract var " "seen in byte_jump - %s\n", offset); goto error; } DetectBytejumpData *bjd = sm->ctx; bjd->offset = ((DetectByteExtractData *)bed_sm->ctx)->local_id; bjd->flags |= DETECT_BYTEJUMP_OFFSET_BE; SCFree(offset); } if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) { return 0; } if ( !(data->flags & DETECT_BYTEJUMP_RELATIVE)) { return(0); } SigMatch *prev_sm = NULL; prev_sm = SigMatchGetLastSMFromLists(s, 6, DETECT_CONTENT, sm->prev, DETECT_BYTEJUMP, sm->prev, DETECT_PCRE, sm->prev); if (prev_sm == NULL) { if (s->alproto == ALPROTO_DCERPC) { SCLogDebug("No preceding content or pcre keyword. Possible " "since this is an alproto sig."); return 0; } else { SCLogError(SC_ERR_INVALID_SIGNATURE, "No preceding content " "or uricontent or pcre option"); return -1; } } DetectContentData *cd = NULL; DetectPcreData *pe = NULL; switch (prev_sm->type) { case DETECT_CONTENT: /* Set the relative next flag on the prev sigmatch */ cd = (DetectContentData *)prev_sm->ctx; if (cd == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; break; case DETECT_PCRE: pe = (DetectPcreData *)prev_sm->ctx; if (pe == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } pe->flags |= DETECT_PCRE_RELATIVE_NEXT; break; case DETECT_BYTEJUMP: SCLogDebug("No setting relative_next for bytejump. We " "have no use for it"); break; default: /* this will never hit */ SCLogError(SC_ERR_INVALID_SIGNATURE, "Unknown previous-" "previous keyword!"); return -1; } /* switch */ return 0; error: if (data != NULL) DetectBytejumpFree(data); if (sm != NULL) SCFree(sm); return -1; }
static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, char *distancestr) { char *str = distancestr; char dubbed = 0; SigMatch *pm = NULL; int ret = -1; /* strip "'s */ if (distancestr[0] == '\"' && distancestr[strlen(distancestr) - 1] == '\"') { str = SCStrdup(distancestr + 1); if (unlikely(str == NULL)) goto end; str[strlen(distancestr) - 2] = '\0'; dubbed = 1; } /* retrive the sm to apply the depth against */ if (s->list != DETECT_SM_LIST_NOTSET) { pm = SigMatchGetLastSMFromLists(s, 2, DETECT_CONTENT, s->sm_lists_tail[s->list]); } else { pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_FILEDATA], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); } if (pm == NULL) { SCLogError(SC_ERR_OFFSET_MISSING_CONTENT, "distance needs " "preceding content, uricontent option, http_client_body, " "http_server_body, http_header option, http_raw_header option, " "http_method option, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code, http_user_agent or " "file_data/dce_stub_data sticky buffer option"); goto end; } /* verify other conditions */ DetectContentData *cd = (DetectContentData *)pm->ctx; if (cd->flags & DETECT_CONTENT_DISTANCE) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use multiple distances for the same content."); goto end; } if ((cd->flags & DETECT_CONTENT_DEPTH) || (cd->flags & DETECT_CONTENT_OFFSET)) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use a relative " "keyword like within/distance with a absolute " "relative keyword like depth/offset for the same " "content." ); goto end; } if (cd->flags & DETECT_CONTENT_NEGATED && cd->flags & DETECT_CONTENT_FAST_PATTERN) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "negated keyword set along with a fast_pattern"); goto end; } if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "keyword set along with a fast_pattern:only;"); goto end; } if (str[0] != '-' && isalpha((unsigned char)str[0])) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(str, s); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "unknown byte_extract var " "seen in distance - %s\n", str); goto end; } cd->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; cd->flags |= DETECT_CONTENT_DISTANCE_BE; } else { cd->distance = strtol(str, NULL, 10); } cd->flags |= DETECT_CONTENT_DISTANCE; SigMatch *prev_pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, pm->prev, DETECT_PCRE, pm->prev); if (prev_pm == NULL) { ret = 0; goto end; } if (prev_pm->type == DETECT_CONTENT) { DetectContentData *cd = (DetectContentData *)prev_pm->ctx; if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "previous keyword " "has a fast_pattern:only; set. Can't " "have relative keywords around a fast_pattern " "only content"); goto end; } cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; } else if (prev_pm->type == DETECT_PCRE) { DetectPcreData *pd = (DetectPcreData *)prev_pm->ctx; pd->flags |= DETECT_PCRE_RELATIVE_NEXT; } ret = 0; end: if (dubbed) SCFree(str); return ret; }
/** * \internal * \brief Apply the nocase keyword to the last pattern match, either content or uricontent * \param det_ctx detection engine ctx * \param s signature * \param nullstr should be null * \retval 0 ok * \retval -1 failure */ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nullstr) { SCEnter(); SigMatch *pm = NULL; int ret = -1; if (nullstr != NULL) { SCLogError(SC_ERR_INVALID_VALUE, "nocase has value"); goto end; } /* retrive the sm to apply the depth against */ if (s->list != DETECT_SM_LIST_NOTSET) { pm = SigMatchGetLastSMFromLists(s, 2, DETECT_CONTENT, s->sm_lists_tail[s->list]); } else { pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_FILEDATA], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); } if (pm == NULL) { SCLogError(SC_ERR_NOCASE_MISSING_PATTERN, "nocase needs " "preceding content, uricontent option, http_client_body, " "http_server_body, http_header option, http_raw_header option, " "http_method option, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code, http_user_agent or " "file_data/dce_stub_data sticky buffer options"); goto end; } /* verify other conditions. */ DetectContentData *cd = (DetectContentData *)pm->ctx;; if (cd->flags & DETECT_CONTENT_NOCASE) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use multiple nocase modifiers with the same content"); goto end; } /* for consistency in later use (e.g. by MPM construction and hashing), * coerce the content string to lower-case. */ for (uint8_t *c = cd->content; c < cd->content + cd->content_len; c++) { *c = u8_tolower(*c); } cd->flags |= DETECT_CONTENT_NOCASE; /* Recreate the context with nocase chars */ SpmDestroyCtx(cd->spm_ctx); cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 1, de_ctx->spm_global_thread_ctx); if (cd->spm_ctx == NULL) { goto end; } ret = 0; end: SCReturnInt(ret); }
static int DetectHttpCookieSetup (DetectEngineCtx *de_ctx, Signature *s, char *str) { DetectContentData *cd = NULL; SigMatch *sm = NULL; if (str != NULL && strcmp(str, "") != 0) { SCLogError(SC_ERR_INVALID_ARGUMENT, "http_cookie shouldn't be supplied " "with an argument"); return -1; } if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL) { SCLogError(SC_ERR_HTTP_COOKIE_NEEDS_PRECEEDING_CONTENT, "http_cookie " "found inside the rule, without any preceding content keywords"); return -1; } sm = SigMatchGetLastSMFromLists(s, 2, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); if (sm == NULL) { SCLogWarning(SC_ERR_HTTP_COOKIE_NEEDS_PRECEEDING_CONTENT, "http_cookie " "found inside the rule, without a content context. Please use a " "content keyword before using http_cookie"); return -1; } cd = (DetectContentData *)sm->ctx; /* http_cookie should not be used with the rawbytes rule */ if (cd->flags & DETECT_CONTENT_RAWBYTES) { SCLogError(SC_ERR_HTTP_COOKIE_INCOMPATIBLE_WITH_RAWBYTES, "http_cookie " "rule can not be used with the rawbytes rule keyword"); return -1; } if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains keywords" "that conflict with http_cookie"); goto error; } if ((cd->flags & DETECT_CONTENT_WITHIN) || (cd->flags & DETECT_CONTENT_DISTANCE)) { SigMatch *pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, sm->prev, DETECT_PCRE, sm->prev); if (pm != NULL) { /* pm is never NULL. So no NULL check */ if (pm->type == DETECT_CONTENT) { DetectContentData *tmp_cd = (DetectContentData *)pm->ctx; tmp_cd->flags &= ~DETECT_CONTENT_RELATIVE_NEXT; } else { DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; tmp_pd->flags &= ~DETECT_PCRE_RELATIVE_NEXT; } } /* if (pm != NULL) */ /* please note. reassigning pm */ pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_HTTP_COOKIE_RELATIVE_MISSING, "http_cookie with " "a distance or within requires preceding http_cookie " "content, but none was found"); goto error; } if (pm->type == DETECT_PCRE) { DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT; } else { DetectContentData *tmp_cd = (DetectContentData *)pm->ctx; tmp_cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; } } cd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, cd, DETECT_SM_LIST_HCDMATCH); sm->type = DETECT_CONTENT; /* transfer the sm from the pmatch list to hcdmatch list */ SigMatchTransferSigMatchAcrossLists(sm, &s->sm_lists[DETECT_SM_LIST_PMATCH], &s->sm_lists_tail[DETECT_SM_LIST_PMATCH], &s->sm_lists[DETECT_SM_LIST_HCDMATCH], &s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); /* flag the signature to indicate that we scan the app layer data */ s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_HTTP; return 0; error: return -1; }
static int DetectBase64DecodeSetup(DetectEngineCtx *de_ctx, Signature *s, char *str) { uint32_t bytes = 0; uint32_t offset = 0; uint8_t relative = 0; DetectBase64Decode *data = NULL; int sm_list; SigMatch *sm = NULL; SigMatch *pm = NULL; if (str != NULL) { if (!DetectBase64DecodeParse(str, &bytes, &offset, &relative)) { goto error; } } data = SCCalloc(1, sizeof(DetectBase64Decode)); if (unlikely(data == NULL)) { goto error; } data->bytes = bytes; data->offset = offset; data->relative = relative; if (s->list != DETECT_SM_LIST_NOTSET) { sm_list = s->list; #if 0 if (data->relative) { pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, s->sm_lists_tail[sm_list], DETECT_PCRE, s->sm_lists_tail[sm_list]); } #endif } else { /* Copied from detect-isdataat.c. */ pm = SigMatchGetLastSMFromLists(s, 168, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_FILEDATA], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_FILEDATA], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_FILEDATA], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_BYTETEST, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_FILEDATA], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_BYTEJUMP, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_FILEDATA], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_BYTE_EXTRACT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_FILEDATA], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_ISDATAAT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); if (pm == NULL) { sm_list = DETECT_SM_LIST_PMATCH; } else { sm_list = SigMatchListSMBelongsTo(s, pm); if (sm_list < 0) { goto error; } } } sm = SigMatchAlloc(); if (sm == NULL) { goto error; } sm->type = DETECT_BASE64_DECODE; sm->ctx = (SigMatchCtx *)data; SigMatchAppendSMToList(s, sm, sm_list); if (!data->bytes) { data->bytes = BASE64_DECODE_MAX; } if (data->bytes > de_ctx->base64_decode_max_len) { de_ctx->base64_decode_max_len = data->bytes; } return 0; error: if (data != NULL) { SCFree(data); } return -1; }