Exemple #1
0
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;
}
Exemple #3
0
/**
 * \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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
/** \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;
}
Exemple #8
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
/**
 *  \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);
}
Exemple #11
0
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;
}