Esempio n. 1
0
static int FlowStorageTest02(void) {
    Flow *f = NULL;

    StorageInit();

    int id1 = FlowStorageRegister("test", sizeof(void *), NULL, StorageTestFree);
    if (id1 < 0)
        goto error;

    if (StorageFinalize() < 0)
        goto error;

    FlowInitConfig(FLOW_QUIET);
    f = FlowAlloc();
    if (f == NULL) {
        goto error;
    }

    void *ptr = FlowGetStorageById(f, id1);
    if (ptr != NULL) {
        goto error;
    }

    void *ptr1a = SCMalloc(128);
    if (ptr1a == NULL) {
        goto error;
    }
    FlowSetStorageById(f, id1, ptr1a);

    void *ptr1b = FlowGetStorageById(f, id1);
    if (ptr1a != ptr1b) {
        goto error;
    }


    FlowClearMemory(f, 0);
    FlowFree(f);
    FlowShutdown();
    StorageCleanup();
    return 1;
error:
    if (f != NULL) {
        FlowClearMemory(f, 0);
        FlowFree(f);
    }
    FlowShutdown();
    StorageCleanup();
    return 0;
}
Esempio n. 2
0
/**
 * \brief This function is used to add a tag to a session (type session)
 *        or update it if it's already installed. The number of times to
 *        allow an update is limited by DETECT_TAG_MATCH_LIMIT. This way
 *        repetitive matches to the same rule are limited of setting tags,
 *        to avoid DOS attacks
 *
 * \param p pointer to the current packet
 * \param tde pointer to the new DetectTagDataEntry
 *
 * \retval 0 if the tde was added succesfuly
 * \retval 1 if an entry of this sid/gid already exist and was updated
 */
int TagFlowAdd(Packet *p, DetectTagDataEntry *tde)
{
    uint8_t updated = 0;
    uint16_t num_tags = 0;
    DetectTagDataEntry *iter = NULL;

    if (p->flow == NULL)
        return 1;

    FLOWLOCK_WRLOCK(p->flow);
    iter = FlowGetStorageById(p->flow, flow_tag_id);
    if (iter != NULL) {
        /* First iterate installed entries searching a duplicated sid/gid */
        for (; iter != NULL; iter = iter->next) {
            num_tags++;

            if (iter->sid == tde->sid && iter->gid == tde->gid) {
                iter->cnt_match++;

                /* If so, update data, unless the maximum MATCH limit is
                 * reached. This prevents possible DOS attacks */
                if (iter->cnt_match < DETECT_TAG_MATCH_LIMIT) {
                    /* Reset time and counters */
                    iter->first_ts = iter->last_ts = tde->first_ts;
                    iter->packets = 0;
                    iter->bytes = 0;
                }
                updated = 1;
                break;
            }
        }
    }

    /* If there was no entry of this rule, prepend the new tde */
    if (updated == 0 && num_tags < DETECT_TAG_MAX_TAGS) {
        DetectTagDataEntry *new_tde = DetectTagDataCopy(tde);
        if (new_tde != NULL) {
            new_tde->next = FlowGetStorageById(p->flow, flow_tag_id);
            FlowSetStorageById(p->flow, flow_tag_id, new_tde);
            (void) SC_ATOMIC_ADD(num_tags, 1);
        }
    } else if (num_tags == DETECT_TAG_MAX_TAGS) {
        SCLogDebug("Max tags for sessions reached (%"PRIu16")", num_tags);
    }

    FLOWLOCK_UNLOCK(p->flow);
    return updated;
}
Esempio n. 3
0
/**
 * Function doing a lookup in expectation list and updating Flow if needed.
 *
 * This function lookup for a existing expectation that could match the Flow.
 * If found and if the expectation contains data it store the data in the
 * expectation storage of the Flow.
 *
 * \return an AppProto value if found
 * \return ALPROTO_UNKNOWN if not found
 */
AppProto AppLayerExpectationHandle(Flow *f, int direction)
{
    AppProto alproto = ALPROTO_UNKNOWN;
    IPPair *ipp = NULL;
    Expectation *lexp = NULL;
    Expectation *pexp = NULL;

    int x = SC_ATOMIC_GET(expectation_count);
    if (x == 0) {
        return ALPROTO_UNKNOWN;
    }

    /* Call will take reference of the ip pair in 'ipp' */
    Expectation *exp = AppLayerExpectationLookup(f, direction, &ipp);
    if (exp == NULL)
        goto out;

    time_t ctime = f->lastts.tv_sec;

    pexp = NULL;
    while (exp) {
        lexp = exp->next;
        if ( (exp->direction & direction) &&
             ((exp->sp == 0) || (exp->sp == f->sp)) &&
             ((exp->dp == 0) || (exp->dp == f->dp))) {
            alproto = exp->alproto;
            f->alproto_ts = alproto;
            f->alproto_tc = alproto;
            void *fdata = FlowGetStorageById(f, g_expectation_id);
            if (fdata) {
                /* We already have an expectation so let's clean this one */
                ExpectationDataFree(exp->data);
            } else {
                /* Transfer ownership of Expectation data to the Flow */
                if (FlowSetStorageById(f, g_expectation_data_id, exp->data) != 0) {
                    SCLogDebug("Unable to set flow storage");
                }
            }
            exp->data = NULL;
            exp = RemoveExpectationAndGetNext(ipp, pexp, exp, lexp);
            continue;
        }
        /* Cleaning remove old entries */
        if (exp && (ctime > exp->ts.tv_sec + EXPECTATION_TIMEOUT)) {
            exp = RemoveExpectationAndGetNext(ipp, pexp, exp, lexp);
            continue;
        }
        pexp = exp;
        exp = lexp;
    }

out:
    if (ipp)
        IPPairRelease(ipp);
    return alproto;
}
Esempio n. 4
0
static int FlowStorageTest01(void) {
    Flow *f = NULL;

    StorageInit();

    int id1 = FlowStorageRegister("test", 8, StorageTestAlloc, StorageTestFree);
    if (id1 < 0)
        goto error;
    int id2 = FlowStorageRegister("variable", 24, StorageTestAlloc, StorageTestFree);
    if (id2 < 0)
        goto error;
    int id3 = FlowStorageRegister("store", sizeof(void *), StorageTestAlloc, StorageTestFree);
    if (id3 < 0)
        goto error;

    if (StorageFinalize() < 0)
        goto error;

    FlowInitConfig(FLOW_QUIET);

    f = FlowAlloc();
    if (f == NULL) {
        goto error;
    }

    void *ptr = FlowGetStorageById(f, id1);
    if (ptr != NULL) {
        goto error;
    }
    ptr = FlowGetStorageById(f, id2);
    if (ptr != NULL) {
        goto error;
    }
    ptr = FlowGetStorageById(f, id3);
    if (ptr != NULL) {
        goto error;
    }

    void *ptr1a = FlowAllocStorageById(f, id1);
    if (ptr1a == NULL) {
        goto error;
    }
    void *ptr2a = FlowAllocStorageById(f, id2);
    if (ptr2a == NULL) {
        goto error;
    }
    void *ptr3a = FlowAllocStorageById(f, id3);
    if (ptr3a == NULL) {
        goto error;
    }

    void *ptr1b = FlowGetStorageById(f, id1);
    if (ptr1a != ptr1b) {
        goto error;
    }
    void *ptr2b = FlowGetStorageById(f, id2);
    if (ptr2a != ptr2b) {
        goto error;
    }
    void *ptr3b = FlowGetStorageById(f, id3);
    if (ptr3a != ptr3b) {
        goto error;
    }

    FlowClearMemory(f, 0);
    FlowFree(f);
    FlowShutdown();
    StorageCleanup();
    return 1;
error:
    if (f != NULL) {
        FlowClearMemory(f, 0);
        FlowFree(f);
    }
    FlowShutdown();
    StorageCleanup();
    return 0;
}
Esempio n. 5
0
static void TagHandlePacketFlow(Flow *f, Packet *p)
{
    if (FlowGetStorageById(f, flow_tag_id) == NULL)
        return;

    DetectTagDataEntry *tde = NULL;
    DetectTagDataEntry *prev = NULL;
    DetectTagDataEntry *iter = FlowGetStorageById(f, flow_tag_id);
    uint8_t flag_added = 0;

    while (iter != NULL) {
        /* update counters */
        iter->last_ts = p->ts.tv_sec;
        switch (iter->metric) {
            case DETECT_TAG_METRIC_PACKET:
                iter->packets++;
                break;
            case DETECT_TAG_METRIC_BYTES:
                iter->bytes += GET_PKT_LEN(p);
                break;
        }

        /* If this packet triggered the rule with tag, we dont need
         * to log it (the alert will log it) */
        if (!(iter->flags & TAG_ENTRY_FLAG_SKIPPED_FIRST)) {
            iter->flags |= TAG_ENTRY_FLAG_SKIPPED_FIRST;
        } else {
            /* Update metrics; remove if tag expired; and set alerts */
            switch (iter->metric) {
                case DETECT_TAG_METRIC_PACKET:
                    if (iter->packets > iter->count) {
                        /* tag expired */
                        if (prev != NULL) {
                            tde = iter;
                            prev->next = iter->next;
                            iter = iter->next;
                            SCFree(tde);
                            (void) SC_ATOMIC_SUB(num_tags, 1);
                            continue;
                        } else {
                            FlowSetStorageById(p->flow, flow_tag_id, iter->next);
                            tde = iter;
                            iter = iter->next;
                            SCFree(tde);
                            (void) SC_ATOMIC_SUB(num_tags, 1);
                            continue;
                        }
                    } else if (flag_added == 0) {
                        /* It's matching the tag. Add it to be logged and
                         * update "flag_added" to add the packet once. */
                        p->flags |= PKT_HAS_TAG;
                        flag_added++;
                    }
                    break;
                case DETECT_TAG_METRIC_BYTES:
                    if (iter->bytes > iter->count) {
                        /* tag expired */
                        if (prev != NULL) {
                            tde = iter;
                            prev->next = iter->next;
                            iter = iter->next;
                            SCFree(tde);
                            (void) SC_ATOMIC_SUB(num_tags, 1);
                            continue;
                        } else {
                            FlowSetStorageById(p->flow, flow_tag_id, iter->next);
                            tde = iter;
                            iter = iter->next;
                            SCFree(tde);
                            (void) SC_ATOMIC_SUB(num_tags, 1);
                            continue;
                        }
                    } else if (flag_added == 0) {
                        /* It's matching the tag. Add it to be logged and
                         * update "flag_added" to add the packet once. */
                        p->flags |= PKT_HAS_TAG;
                        flag_added++;
                    }
                    break;
                case DETECT_TAG_METRIC_SECONDS:
                    /* last_ts handles this metric, but also a generic time based
                     * expiration to prevent dead sessions/hosts */
                    if (iter->last_ts - iter->first_ts > iter->count) {
                        /* tag expired */
                        if (prev != NULL) {
                            tde = iter;
                            prev->next = iter->next;
                            iter = iter->next;
                            SCFree(tde);
                            (void) SC_ATOMIC_SUB(num_tags, 1);
                            continue;
                        } else {
                            FlowSetStorageById(p->flow, flow_tag_id, iter->next);
                            tde = iter;
                            iter = iter->next;
                            SCFree(tde);
                            (void) SC_ATOMIC_SUB(num_tags, 1);
                            continue;
                        }
                    } else if (flag_added == 0) {
                        /* It's matching the tag. Add it to be logged and
                         * update "flag_added" to add the packet once. */
                        p->flags |= PKT_HAS_TAG;
                        flag_added++;
                    }
                    break;
            }

        }

        prev = iter;
        iter = iter->next;
    }
}