Esempio n. 1
0
static int FlowBitsTestSig04(void)
{
    Signature *s = NULL;
    DetectEngineCtx *de_ctx = NULL;
    int idx = 0;

    de_ctx = DetectEngineCtxInit();
    FAIL_IF_NULL(de_ctx);

    de_ctx->flags |= DE_QUIET;

    s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"isset option\"; flowbits:isset,fbt; content:\"GET \"; sid:1;)");
    FAIL_IF_NULL(s);

    idx = VariableNameGetIdx(de_ctx, "fbt", VAR_TYPE_FLOW_BIT);
    FAIL_IF(idx != 1);

    DetectEngineCtxFree(de_ctx);
    PASS;
}
Esempio n. 2
0
int DetectXbitSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr)
{
    DetectXbitsData *cd = NULL;
    SigMatch *sm = NULL;
    uint8_t fb_cmd = 0;
    uint8_t hb_dir = 0;
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];
    char fb_cmd_str[16] = "", fb_name[256] = "";
    char hb_dir_str[16] = "";
    enum VarTypes var_type = VAR_TYPE_NOT_SET;
    int expire = 30;

    ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS);
    if (ret != 2 && ret != 3 && ret != 4 && ret != 5) {
        SCLogError(SC_ERR_PCRE_MATCH, "\"%s\" is not a valid setting for xbits.", rawstr);
        return -1;
    }
    SCLogDebug("ret %d, %s", ret, rawstr);
    res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, fb_cmd_str, sizeof(fb_cmd_str));
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
        return -1;
    }

    if (ret >= 3) {
        res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, fb_name, sizeof(fb_name));
        if (res < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
            goto error;
        }
        if (ret >= 4) {
            res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 3, hb_dir_str, sizeof(hb_dir_str));
            if (res < 0) {
                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
                goto error;
            }
            SCLogDebug("hb_dir_str %s", hb_dir_str);
            if (strlen(hb_dir_str) > 0) {
                if (strcmp(hb_dir_str, "ip_src") == 0) {
                    hb_dir = DETECT_XBITS_TRACK_IPSRC;
                    var_type = VAR_TYPE_HOST_BIT;
                } else if (strcmp(hb_dir_str, "ip_dst") == 0) {
                    hb_dir = DETECT_XBITS_TRACK_IPDST;
                    var_type = VAR_TYPE_HOST_BIT;
                } else if (strcmp(hb_dir_str, "ip_pair") == 0) {
                    hb_dir = DETECT_XBITS_TRACK_IPPAIR;
                    var_type = VAR_TYPE_IPPAIR_BIT;
                } else {
                    // TODO
                    goto error;
                }
            }

            if (ret >= 5) {
                char expire_str[16] = "";
                res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 4, expire_str, sizeof(expire_str));
                if (res < 0) {
                    SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
                    goto error;
                }
                SCLogDebug("expire_str %s", expire_str);
                expire = atoi(expire_str);
                SCLogDebug("expire %d", expire);
            }
        }
    }

    if (strcmp(fb_cmd_str,"noalert") == 0) {
        fb_cmd = DETECT_XBITS_CMD_NOALERT;
    } else if (strcmp(fb_cmd_str,"isset") == 0) {
        fb_cmd = DETECT_XBITS_CMD_ISSET;
    } else if (strcmp(fb_cmd_str,"isnotset") == 0) {
        fb_cmd = DETECT_XBITS_CMD_ISNOTSET;
    } else if (strcmp(fb_cmd_str,"set") == 0) {
        fb_cmd = DETECT_XBITS_CMD_SET;
    } else if (strcmp(fb_cmd_str,"unset") == 0) {
        fb_cmd = DETECT_XBITS_CMD_UNSET;
    } else if (strcmp(fb_cmd_str,"toggle") == 0) {
        fb_cmd = DETECT_XBITS_CMD_TOGGLE;
    } else {
        SCLogError(SC_ERR_UNKNOWN_VALUE, "ERROR: flowbits action \"%s\" is not supported.", fb_cmd_str);
        goto error;
    }

    switch (fb_cmd) {
        case DETECT_XBITS_CMD_NOALERT:
            if (strlen(fb_name) != 0)
                goto error;
            s->flags |= SIG_FLAG_NOALERT;
            return 0;
        case DETECT_XBITS_CMD_ISNOTSET:
        case DETECT_XBITS_CMD_ISSET:
        case DETECT_XBITS_CMD_SET:
        case DETECT_XBITS_CMD_UNSET:
        case DETECT_XBITS_CMD_TOGGLE:
        default:
            if (strlen(fb_name) == 0)
                goto error;
            break;
    }

    cd = SCMalloc(sizeof(DetectXbitsData));
    if (unlikely(cd == NULL))
        goto error;

    cd->idx = VariableNameGetIdx(de_ctx, fb_name, var_type);
    cd->cmd = fb_cmd;
    cd->tracker = hb_dir;
    cd->type = var_type;
    cd->expire = expire;

    SCLogDebug("idx %" PRIu32 ", cmd %s, name %s",
        cd->idx, fb_cmd_str, strlen(fb_name) ? fb_name : "(none)");

    /* Okay so far so good, lets get this into a SigMatch
     * and put it in the Signature. */
    sm = SigMatchAlloc();
    if (sm == NULL)
        goto error;

    sm->type = DETECT_XBITS;
    sm->ctx = (void *)cd;

    switch (fb_cmd) {
        case DETECT_XBITS_CMD_NOALERT:
            /* nothing to do */
            break;

        case DETECT_XBITS_CMD_ISNOTSET:
        case DETECT_XBITS_CMD_ISSET:
            /* checks, so packet list */
            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
            break;

        case DETECT_XBITS_CMD_SET:
        case DETECT_XBITS_CMD_UNSET:
        case DETECT_XBITS_CMD_TOGGLE:
            /* modifiers, only run when entire sig has matched */
            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_POSTMATCH);
            break;
    }

    return 0;

error:
    if (cd != NULL)
        SCFree(cd);
    if (sm != NULL)
        SCFree(sm);
    return -1;
}
Esempio n. 3
0
static int DetectFlowvarSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr)
{
    DetectFlowvarData *fd = NULL;
    SigMatch *sm = NULL;
    char *varname = NULL, *varcontent = NULL;
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];
    const char *str_ptr;
    uint8_t *content = NULL;
    uint16_t contentlen = 0;
    uint32_t contentflags = 0;

    ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS);
    if (ret != 3) {
        SCLogError(SC_ERR_PCRE_MATCH, "\"%s\" is not a valid setting for flowvar.", rawstr);
        return -1;
    }

    res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
        return -1;
    }
    varname = (char *)str_ptr;

    res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
        return -1;
    }
    varcontent = (char *)str_ptr;

    res = DetectContentDataParse("flowvar", varcontent, &content, &contentlen, &contentflags);
    if (res == -1)
        goto error;

    fd = SCMalloc(sizeof(DetectFlowvarData));
    if (unlikely(fd == NULL))
        goto error;
    memset(fd, 0x00, sizeof(*fd));

    fd->content = SCMalloc(contentlen);
    if (unlikely(fd->content == NULL))
        goto error;

    memcpy(fd->content, content, contentlen);
    fd->content_len = contentlen;
    fd->flags = contentflags;

    fd->name = SCStrdup(varname);
    if (unlikely(fd->name == NULL))
        goto error;
    fd->idx = VariableNameGetIdx(de_ctx, varname, VAR_TYPE_FLOW_VAR);

    /* Okay so far so good, lets get this into a SigMatch
     * and put it in the Signature. */
    sm = SigMatchAlloc();
    if (unlikely(sm == NULL))
        goto error;

    sm->type = DETECT_FLOWVAR;
    sm->ctx = (SigMatchCtx *)fd;

    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);

    SCFree(content);
    return 0;

error:
    if (fd != NULL)
        DetectFlowvarDataFree(fd);
    if (sm != NULL)
        SCFree(sm);
    if (content != NULL)
        SCFree(content);
    return -1;
}
Esempio n. 4
0
static int FlowBitsTestSig08(void)
{
    uint8_t *buf = (uint8_t *)
                    "GET /one/ HTTP/1.1\r\n"
                    "Host: one.example.org\r\n"
                    "\r\n";
    uint16_t buflen = strlen((char *)buf);
    Packet *p = SCMalloc(SIZE_OF_PACKET);
    if (unlikely(p == NULL))
        return 0;
    Signature *s = NULL;
    ThreadVars th_v;
    DetectEngineThreadCtx *det_ctx = NULL;
    DetectEngineCtx *de_ctx = NULL;
    Flow f;
    GenericVar flowvar, *gv = NULL;
    int result = 0;
    int idx = 0;

    memset(p, 0, SIZE_OF_PACKET);
    memset(&th_v, 0, sizeof(th_v));
    memset(&f, 0, sizeof(Flow));
    memset(&flowvar, 0, sizeof(GenericVar));

    FLOW_INITIALIZE(&f);
    p->flow = &f;
    p->flow->flowvar = &flowvar;

    p->src.family = AF_INET;
    p->dst.family = AF_INET;
    p->payload = buf;
    p->payload_len = buflen;
    p->proto = IPPROTO_TCP;

    de_ctx = DetectEngineCtxInit();

    if (de_ctx == NULL) {
        goto end;
    }

    de_ctx->flags |= DE_QUIET;

    s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit set\"; flowbits:set,myflow2; sid:10;)");

    if (s == NULL) {
        goto end;
    }

    s = s->next  = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit unset\"; flowbits:toggle,myflow2; sid:11;)");

    if (s == NULL) {
        goto end;
    }

    SigGroupBuild(de_ctx);
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);

    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);

    idx = VariableNameGetIdx(de_ctx, "myflow", VAR_TYPE_FLOW_BIT);

    gv = p->flow->flowvar;

    for ( ; gv != NULL; gv = gv->next) {
        if (gv->type == DETECT_FLOWBITS && gv->idx == idx) {
                result = 1;
        }
    }

    SigGroupCleanup(de_ctx);
    SigCleanSignatures(de_ctx);

    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
    DetectEngineCtxFree(de_ctx);

    if(gv) GenericVarFree(gv);
    FLOW_DESTROY(&f);

    SCFree(p);
    PASS_IF(result == 0);
end:

    if (de_ctx != NULL) {
        SigGroupCleanup(de_ctx);
        SigCleanSignatures(de_ctx);
    }

    if (det_ctx != NULL) {
        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
    }

    if (de_ctx != NULL) {
        DetectEngineCtxFree(de_ctx);
    }

    if(gv) GenericVarFree(gv);
    FLOW_DESTROY(&f);

    SCFree(p);
    PASS_IF(result == 0);
}
Esempio n. 5
0
static int FlowBitsTestSig04(void)
{
    uint8_t *buf = (uint8_t *)
                    "GET /one/ HTTP/1.1\r\n"
                    "Host: one.example.org\r\n"
                    "\r\n";
    uint16_t buflen = strlen((char *)buf);
    Packet *p = SCMalloc(SIZE_OF_PACKET);
    if (unlikely(p == NULL))
        return 0;
    Signature *s = NULL;
    ThreadVars th_v;
    DetectEngineThreadCtx *det_ctx = NULL;
    DetectEngineCtx *de_ctx = NULL;
    int result = 0;
    int idx = 0;

    memset(&th_v, 0, sizeof(th_v));
    memset(p, 0, SIZE_OF_PACKET);
    p->src.family = AF_INET;
    p->dst.family = AF_INET;
    p->payload = buf;
    p->payload_len = buflen;
    p->proto = IPPROTO_TCP;

    de_ctx = DetectEngineCtxInit();

    if (de_ctx == NULL) {
        goto end;
    }

    de_ctx->flags |= DE_QUIET;

    s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"isset option\"; flowbits:isset,fbt; content:\"GET \"; sid:1;)");

    idx = VariableNameGetIdx(de_ctx, "fbt", VAR_TYPE_FLOW_BIT);

    if (s == NULL || idx != 1) {
        goto end;
    }

    SigGroupBuild(de_ctx);
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);

    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);

    result = 1;

    SigGroupCleanup(de_ctx);
    SigCleanSignatures(de_ctx);

    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
    DetectEngineCtxFree(de_ctx);
    SCFree(p);
    PASS_IF(result);

end:

    if (de_ctx != NULL) {
        SigGroupCleanup(de_ctx);
        SigCleanSignatures(de_ctx);
    }

    if (det_ctx != NULL) {
        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
    }

    if (de_ctx != NULL) {
        DetectEngineCtxFree(de_ctx);
    }

    SCFree(p);
    PASS_IF(result);
}
Esempio n. 6
0
int DetectFlowbitSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr)
{
    DetectFlowbitsData *cd = NULL;
    SigMatch *sm = NULL;
    uint8_t fb_cmd = 0;
    char fb_cmd_str[16] = "", fb_name[256] = "";

    if (!DetectFlowbitParse(rawstr, fb_cmd_str, sizeof(fb_cmd_str), fb_name,
            sizeof(fb_name))) {
        return -1;
    }

    if (strcmp(fb_cmd_str,"noalert") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_NOALERT;
    } else if (strcmp(fb_cmd_str,"isset") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_ISSET;
    } else if (strcmp(fb_cmd_str,"isnotset") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_ISNOTSET;
    } else if (strcmp(fb_cmd_str,"set") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_SET;
    } else if (strcmp(fb_cmd_str,"unset") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_UNSET;
    } else if (strcmp(fb_cmd_str,"toggle") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_TOGGLE;
    } else {
        SCLogError(SC_ERR_UNKNOWN_VALUE, "ERROR: flowbits action \"%s\" is not supported.", fb_cmd_str);
        goto error;
    }

    switch (fb_cmd) {
        case DETECT_FLOWBITS_CMD_NOALERT:
            if (strlen(fb_name) != 0)
                goto error;
            s->flags |= SIG_FLAG_NOALERT;
            return 0;
        case DETECT_FLOWBITS_CMD_ISNOTSET:
        case DETECT_FLOWBITS_CMD_ISSET:
        case DETECT_FLOWBITS_CMD_SET:
        case DETECT_FLOWBITS_CMD_UNSET:
        case DETECT_FLOWBITS_CMD_TOGGLE:
        default:
            if (strlen(fb_name) == 0)
                goto error;
            break;
    }

    cd = SCMalloc(sizeof(DetectFlowbitsData));
    if (unlikely(cd == NULL))
        goto error;

    cd->idx = VariableNameGetIdx(de_ctx, fb_name, VAR_TYPE_FLOW_BIT);
    cd->cmd = fb_cmd;

    SCLogDebug("idx %" PRIu32 ", cmd %s, name %s",
        cd->idx, fb_cmd_str, strlen(fb_name) ? fb_name : "(none)");

    /* Okay so far so good, lets get this into a SigMatch
     * and put it in the Signature. */
    sm = SigMatchAlloc();
    if (sm == NULL)
        goto error;

    sm->type = DETECT_FLOWBITS;
    sm->ctx = (SigMatchCtx *)cd;

    switch (fb_cmd) {
        /* case DETECT_FLOWBITS_CMD_NOALERT can't happen here */

        case DETECT_FLOWBITS_CMD_ISNOTSET:
        case DETECT_FLOWBITS_CMD_ISSET:
            /* checks, so packet list */
            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
            break;

        case DETECT_FLOWBITS_CMD_SET:
        case DETECT_FLOWBITS_CMD_UNSET:
        case DETECT_FLOWBITS_CMD_TOGGLE:
            /* modifiers, only run when entire sig has matched */
            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_POSTMATCH);
            break;
    }

    return 0;

error:
    if (cd != NULL)
        SCFree(cd);
    if (sm != NULL)
        SCFree(sm);
    return -1;
}
Esempio n. 7
0
static int DetectFlowvarSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr)
{
    DetectFlowvarData *cd = NULL;
    SigMatch *sm = NULL;
    char *str = rawstr;
    char dubbed = 0;
    uint16_t len;
    char *varname = NULL, *varcontent = NULL;
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];

    ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS);
    if (ret != 3) {
        SCLogError(SC_ERR_PCRE_MATCH, "\"%s\" is not a valid setting for flowvar.", rawstr);
        return -1;
    }

    const char *str_ptr;
    res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
        return -1;
    }
    varname = (char *)str_ptr;

    if (ret > 2) {
        res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
        if (res < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
            return -1;
        }
        varcontent = (char *)str_ptr;
    }

    if (varcontent[0] == '\"' && varcontent[strlen(varcontent)-1] == '\"') {
        str = SCStrdup(varcontent+1);
        str[strlen(varcontent)-2] = '\0';
        dubbed = 1;
    }

    len = strlen(str);
    if (len == 0) {
        if (dubbed) SCFree(str);
        return -1;
    }

    cd = SCMalloc(sizeof(DetectFlowvarData));
    if (cd == NULL)
        goto error;

    char converted = 0;

    {
        uint16_t i, x;
        uint8_t bin = 0, binstr[3] = "", binpos = 0;
        for (i = 0, x = 0; i < len; i++) {
            // printf("str[%02u]: %c\n", i, str[i]);
            if (str[i] == '|') {
                if (bin) {
                    bin = 0;
                } else {
                    bin = 1;
                }
            } else {
                if (bin) {
                    if (isdigit(str[i]) ||
                        str[i] == 'A' || str[i] == 'a' ||
                        str[i] == 'B' || str[i] == 'b' ||
                        str[i] == 'C' || str[i] == 'c' ||
                        str[i] == 'D' || str[i] == 'd' ||
                        str[i] == 'E' || str[i] == 'e' ||
                        str[i] == 'F' || str[i] == 'f') {
                        // printf("part of binary: %c\n", str[i]);

                        binstr[binpos] = (char)str[i];
                        binpos++;

                        if (binpos == 2) {
                            uint8_t c = strtol((char *)binstr, (char **) NULL, 16) & 0xFF;
                            binpos = 0;
                            str[x] = c;
                            x++;
                            converted = 1;
                        }
                    } else if (str[i] == ' ') {
                        // printf("space as part of binary string\n");
                    }
                } else {
                    str[x] = str[i];
                    x++;
                }
            }
        }
#ifdef DEBUG
        if (SCLogDebugEnabled()) {
            for (i = 0; i < x; i++) {
                if (isprint(str[i])) printf("%c", str[i]);
                else                 printf("\\x%02u", str[i]);
            }
            printf("\n");
        }
#endif

        if (converted)
            len = x;
    }

    cd->content = SCMalloc(len);
    if (cd->content == NULL) {
        if (dubbed) SCFree(str);
        SCFree(cd);
        return -1;
    }

    cd->name = SCStrdup(varname);
    cd->idx = VariableNameGetIdx(varname,DETECT_FLOWVAR);
    memcpy(cd->content, str, len);
    cd->content_len = len;
    cd->flags = 0;

    /* Okay so far so good, lets get this into a SigMatch
     * and put it in the Signature. */
    sm = SigMatchAlloc();
    if (sm == NULL)
        goto error;

    sm->type = DETECT_FLOWVAR;
    sm->ctx = (void *)cd;

    SigMatchAppendPacket(s, sm);

    if (dubbed) SCFree(str);
    return 0;

error:
    if (dubbed) SCFree(str);
    if (cd) SCFree(cd);
    if (sm) SCFree(sm);
    return -1;
}
Esempio n. 8
0
int DetectFlowbitSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr)
{
    DetectFlowbitsData *cd = NULL;
    SigMatch *sm = NULL;
    char *fb_cmd_str = NULL, *fb_name = NULL;
    uint8_t fb_cmd = 0;
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];

    ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS);
    if (ret != 2 && ret != 3) {
        SCLogError(SC_ERR_PCRE_MATCH, "\"%s\" is not a valid setting for flowbits.", rawstr);
        return -1;
    }

    const char *str_ptr;
    res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
        return -1;
    }
    fb_cmd_str = (char *)str_ptr;

    if (ret == 3) {
        res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
        if (res < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
            goto error;
        }
        fb_name = (char *)str_ptr;
    }

    if (strcmp(fb_cmd_str,"noalert") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_NOALERT;
    } else if (strcmp(fb_cmd_str,"isset") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_ISSET;
    } else if (strcmp(fb_cmd_str,"isnotset") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_ISNOTSET;
    } else if (strcmp(fb_cmd_str,"set") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_SET;
    } else if (strcmp(fb_cmd_str,"unset") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_UNSET;
    } else if (strcmp(fb_cmd_str,"toggle") == 0) {
        fb_cmd = DETECT_FLOWBITS_CMD_TOGGLE;
    } else {
        SCLogError(SC_ERR_UNKNOWN_VALUE, "ERROR: flowbits action \"%s\" is not supported.", fb_cmd_str);
        goto error;
    }

    switch (fb_cmd) {
        case DETECT_FLOWBITS_CMD_NOALERT:
            if(fb_name != NULL)
                goto error;
            s->flags |= SIG_FLAG_NOALERT;
            return 0;
        case DETECT_FLOWBITS_CMD_ISNOTSET:
        case DETECT_FLOWBITS_CMD_ISSET:
        case DETECT_FLOWBITS_CMD_SET:
        case DETECT_FLOWBITS_CMD_UNSET:
        case DETECT_FLOWBITS_CMD_TOGGLE:
        default:
            if(fb_name == NULL)
                goto error;
            break;
    }

    cd = SCMalloc(sizeof(DetectFlowbitsData));
    if (unlikely(cd == NULL))
        goto error;

    cd->idx = VariableNameGetIdx(de_ctx, fb_name, DETECT_FLOWBITS);
    cd->cmd = fb_cmd;

    SCLogDebug("idx %" PRIu32 ", cmd %s, name %s",
        cd->idx, fb_cmd_str, fb_name ? fb_name : "(null)");

    pcre_free_substring(fb_name);
    fb_name = NULL;
    pcre_free_substring(fb_cmd_str);
    fb_cmd_str = NULL;

    /* Okay so far so good, lets get this into a SigMatch
     * and put it in the Signature. */
    sm = SigMatchAlloc();
    if (sm == NULL)
        goto error;

    sm->type = DETECT_FLOWBITS;
    sm->ctx = (void *)cd;

    switch (fb_cmd) {
        case DETECT_FLOWBITS_CMD_NOALERT:
            /* nothing to do */
            break;

        case DETECT_FLOWBITS_CMD_ISNOTSET:
        case DETECT_FLOWBITS_CMD_ISSET:
            /* checks, so packet list */
            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
            break;

        case DETECT_FLOWBITS_CMD_SET:
        case DETECT_FLOWBITS_CMD_UNSET:
        case DETECT_FLOWBITS_CMD_TOGGLE:
            /* modifiers, only run when entire sig has matched */
            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_POSTMATCH);
            break;
    }

    return 0;

error:
    if (fb_name != NULL)
        pcre_free_substring(fb_name);
    if (fb_cmd_str != NULL)
        pcre_free_substring(fb_cmd_str);
    if (cd != NULL)
        SCFree(cd);
    if (sm != NULL)
        SCFree(sm);
    return -1;
}
Esempio n. 9
0
/**
 * \brief This function is used to create a flowint, add/substract values,
 *        compare it with other flowints, etc
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param s  pointer to the current Signature
 * \param m pointer to the sigmatch that we will cast into DetectFlowintData
 *
 * \retval 0 no match, when a var doesn't exist
 * \retval 1 match, when a var is initialized well, add/substracted, or a true
 * condition
 */
int DetectFlowintMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
                        Packet *p, Signature *s, const SigMatchCtx *ctx)
{
    const DetectFlowintData *sfd = (const DetectFlowintData *)ctx;
    FlowVar *fv;
    FlowVar *fvt;
    uint32_t targetval;
    int ret = 0;

    /** ATM If we are going to compare the current var with another
     * that doesn't exist, the default value will be zero;
     * if you don't want this behaviour, you can use the keyword
     * "isset" to make it match or not before using the default
     * value of zero;
     * But it is mandatory that the current var exist, otherwise, it will
     * return zero(not match).
     */
    if (sfd->targettype == FLOWINT_TARGET_VAR) {
        uint16_t tvar_idx = VariableNameGetIdx(det_ctx->de_ctx, sfd->target.tvar.name, VAR_TYPE_FLOW_INT);

        fvt = FlowVarGet(p->flow, tvar_idx);
            /* We don't have that variable initialized yet */
        if (fvt == NULL)
            targetval = 0;
        else
            targetval = fvt->data.fv_int.value;
    } else {
        targetval = sfd->target.value;
    }

    SCLogDebug("Our var %s is at idx: %"PRIu16"", sfd->name, sfd->idx);

    if (sfd->modifier == FLOWINT_MODIFIER_SET) {
        FlowVarAddIntNoLock(p->flow, sfd->idx, targetval);
        SCLogDebug("Setting %s = %u", sfd->name, targetval);
        ret = 1;
        goto end;
    }

    fv = FlowVarGet(p->flow, sfd->idx);

    if (sfd->modifier == FLOWINT_MODIFIER_ISSET) {
        SCLogDebug(" Isset %s? = %u", sfd->name,(fv) ? 1 : 0);
        if (fv != NULL)
            ret = 1;
        goto end;
    }

    if (sfd->modifier == FLOWINT_MODIFIER_NOTSET) {
        SCLogDebug(" Not set %s? = %u", sfd->name,(fv) ? 0 : 1);
        if (fv == NULL)
            ret = 1;
        goto end;
    }

    if (fv != NULL && fv->datatype == FLOWVAR_TYPE_INT) {
        if (sfd->modifier == FLOWINT_MODIFIER_ADD) {
            SCLogDebug("Adding %u to %s", targetval, sfd->name);
            FlowVarAddIntNoLock(p->flow, sfd->idx, fv->data.fv_int.value +
                           targetval);
            ret = 1;
            goto end;
        }

        if (sfd->modifier == FLOWINT_MODIFIER_SUB) {
            SCLogDebug("Substracting %u to %s", targetval, sfd->name);
            FlowVarAddIntNoLock(p->flow, sfd->idx, fv->data.fv_int.value -
                           targetval);
            ret = 1;
            goto end;
        }

        switch(sfd->modifier) {
            case FLOWINT_MODIFIER_EQ:
                SCLogDebug("( %u EQ %u )", fv->data.fv_int.value, targetval);
                ret = (fv->data.fv_int.value == targetval);
                break;
            case FLOWINT_MODIFIER_NE:
                SCLogDebug("( %u NE %u )", fv->data.fv_int.value, targetval);
                ret = (fv->data.fv_int.value != targetval);
                break;
            case FLOWINT_MODIFIER_LT:
                SCLogDebug("( %u LT %u )", fv->data.fv_int.value, targetval);
                ret = (fv->data.fv_int.value < targetval);
                break;
            case FLOWINT_MODIFIER_LE:
                SCLogDebug("( %u LE %u )", fv->data.fv_int.value, targetval);
                ret = (fv->data.fv_int.value <= targetval);
                break;
            case FLOWINT_MODIFIER_GT:
                SCLogDebug("( %u GT %u )", fv->data.fv_int.value, targetval);
                ret = (fv->data.fv_int.value > targetval);
                break;
            case FLOWINT_MODIFIER_GE:
                SCLogDebug("( %u GE %u )", fv->data.fv_int.value, targetval);
                ret = (fv->data.fv_int.value >= targetval);
                break;
            default:
                SCLogDebug("Unknown Modifier!");
#ifdef DEBUG
                BUG_ON(1);
#endif
        }
    } else {
        /* allow a add on a non-existing var, it will init to the "add" value,
         * so implying a 0 set. */
        if (sfd->modifier == FLOWINT_MODIFIER_ADD) {
            SCLogDebug("Adding %u to %s (new var)", targetval, sfd->name);
            FlowVarAddIntNoLock(p->flow, sfd->idx, targetval);
            ret = 1;
        } else {
            SCLogDebug("Var not found!");
            /* It doesn't exist because it wasn't set
             * or it is a string var, that we don't compare here
             */
            ret = 0;
        }
    }

end:
    return ret;
}
Esempio n. 10
0
/**
 * \brief This function is used to parse a flowint option
 *
 * \param de_ctx pointer to the engine context
 * \param rawstr pointer to the string holding the options
 *
 * \retval NULL if invalid option
 * \retval DetectFlowintData pointer with the flowint parsed
 */
DetectFlowintData *DetectFlowintParse(DetectEngineCtx *de_ctx, char *rawstr)
{
    DetectFlowintData *sfd = NULL;
    char *varname = NULL;
    char *varval = NULL;
    char *modstr = NULL;
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];
    uint8_t modifier = FLOWINT_MODIFIER_UNKNOWN;
    unsigned long long value_long = 0;
    const char *str_ptr;

    ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr),
                     0, 0, ov, MAX_SUBSTRINGS);
    if (ret < 3 || ret > 4) {
        SCLogError(SC_ERR_PCRE_MATCH, "\"%s\" is not a valid setting for flowint(ret = %d).", rawstr, ret);
        return NULL;
    }

    /* Get our flowint varname */
    res = pcre_get_substring((char *) rawstr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
    if (res < 0 || str_ptr == NULL) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
        goto error;
    }
    varname = (char *)str_ptr;

    res = pcre_get_substring((char *) rawstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
    if (res < 0 || str_ptr == NULL) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
        goto error;
    }
    modstr = (char *)str_ptr;

    /* Get the modifier */
    if (strcmp("=", modstr) == 0)
        modifier = FLOWINT_MODIFIER_SET;
    if (strcmp("+", modstr) == 0)
        modifier = FLOWINT_MODIFIER_ADD;
    if (strcmp("-", modstr) == 0)
        modifier = FLOWINT_MODIFIER_SUB;

    if (strcmp("<", modstr) == 0)
        modifier = FLOWINT_MODIFIER_LT;
    if (strcmp("<=", modstr) == 0)
        modifier = FLOWINT_MODIFIER_LE;
    if (strcmp("!=", modstr) == 0)
        modifier = FLOWINT_MODIFIER_NE;
    if (strcmp("==", modstr) == 0)
        modifier = FLOWINT_MODIFIER_EQ;
    if (strcmp(">=", modstr) == 0)
        modifier = FLOWINT_MODIFIER_GE;
    if (strcmp(">", modstr) == 0)
        modifier = FLOWINT_MODIFIER_GT;
    if (strcmp("isset", modstr) == 0)
        modifier = FLOWINT_MODIFIER_ISSET;
    if (strcmp("notset", modstr) == 0)
        modifier = FLOWINT_MODIFIER_NOTSET;

    if (modifier == FLOWINT_MODIFIER_UNKNOWN) {
        SCLogError(SC_ERR_UNKNOWN_VALUE, "Unknown modifier");
        goto error;
    }

    sfd = SCMalloc(sizeof(DetectFlowintData));
    if (unlikely(sfd == NULL))
        goto error;

    /* If we need another arg, check it out(isset doesn't need another arg) */
    if (modifier != FLOWINT_MODIFIER_ISSET && modifier != FLOWINT_MODIFIER_NOTSET) {
        if (ret < 4)
            goto error;

        res = pcre_get_substring((char *) rawstr, ov, MAX_SUBSTRINGS, 3, &str_ptr);
        varval = (char *)str_ptr;
        if (res < 0 || varval == NULL || strcmp(varval, "") == 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
            goto error;
        }

        if (varval[0] >= '0' && varval[0] <= '9') { /* is digit, look at the regexp */
            sfd->targettype = FLOWINT_TARGET_VAL;
            value_long = atoll(varval);
            if (value_long > UINT32_MAX) {
                SCLogDebug("DetectFlowintParse: Cannot load this value."
                            " Values should be between 0 and %"PRIu32, UINT32_MAX);
                goto error;
            }
            sfd->target.value = (uint32_t) value_long;
        } else {
            sfd->targettype = FLOWINT_TARGET_VAR;
            sfd->target.tvar.name = SCStrdup(varval);
            if (unlikely(sfd->target.tvar.name == NULL)) {
                SCLogError(SC_ERR_MEM_ALLOC, "malloc from strdup failed");
                goto error;
            }
        }
    } else {
        sfd->targettype = FLOWINT_TARGET_SELF;
    }

    /* Set the name of the origin var to modify/compared with the target */
    sfd->name = SCStrdup(varname);
    if (unlikely(sfd->name == NULL)) {
        SCLogError(SC_ERR_MEM_ALLOC, "malloc from strdup failed");
        goto error;
    }
    if (de_ctx != NULL)
        sfd->idx = VariableNameGetIdx(de_ctx, varname, VAR_TYPE_FLOW_INT);
    sfd->modifier = modifier;

    pcre_free_substring(varname);
    pcre_free_substring(modstr);
    if (varval)
        pcre_free_substring(varval);
    return sfd;
error:
    if (varname)
        pcre_free_substring(varname);
    if (varval)
        pcre_free_substring(varval);
    if (modstr)
        pcre_free_substring(modstr);
    if (sfd != NULL)
        SCFree(sfd);
    return NULL;
}