示例#1
0
/**
 * \brief Handle a packet and check if needs a threshold logic
 *
 * \param de_ctx Detection Context
 * \param sig Signature pointer
 * \param p Packet structure
 *
 * \retval 1 alert is not suppressed
 * \retval 0 alert is suppressed
 */
static int PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
                       Signature *s, Packet *p, uint16_t pos)
{
    SCEnter();
    int ret = 1;
    DetectThresholdData *td = NULL;
    SigMatch *sm = NULL;

    if (!(PKT_IS_IPV4(p) || PKT_IS_IPV6(p))) {
        SCReturnInt(1);
    }

    do {
        td = SigGetThresholdTypeIter(s, p, &sm);
        if (td != NULL) {
            SCLogDebug("td %p", td);
            ret = PacketAlertThreshold(de_ctx, det_ctx, td, p, s);
            if (ret == 0) {
                /* It doesn't match threshold, remove it */
                PacketAlertRemove(p, pos);
                break;
            }
        }
    } while (sm != NULL);

    SCReturnInt(ret);
}
/**
 * \brief Check the threshold of the sigs that match, set actions, break on pass action
 *        This function iterate the packet alerts array, removing those that didn't match
 *        the threshold, and those that match after a signature with the action "pass".
 *        The array is sorted by action priority/order
 * \param de_ctx detection engine context
 * \param det_ctx detection engine thread context
 * \param p pointer to the packet
 */
void PacketAlertFinalize(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p) {
    SCEnter();
    int i = 0;
    Signature *s = NULL;
    SigMatch *sm = NULL;

    while (i < p->alerts.cnt) {
        SCLogDebug("Sig->num: %"PRIu16, p->alerts.alerts[i].num);
        s = de_ctx->sig_array[p->alerts.alerts[i].num];

        int res = PacketAlertHandle(de_ctx, det_ctx, s, p, i);
        if (res > 0) {
            /* Now, if we have an alert, we have to check if we want
             * to tag this session or src/dst host */
            sm = s->sm_lists[DETECT_SM_LIST_TMATCH];
            while (sm) {
                /* tags are set only for alerts */
                sigmatch_table[sm->type].Match(NULL, det_ctx, p, s, sm);
                sm = sm->next;
            }

            if (s->flags & SIG_FLAG_IPONLY) {
                if (((p->flowflags & FLOW_PKT_TOSERVER) && !(p->flowflags & FLOW_PKT_TOSERVER_IPONLY_SET)) ||
                    ((p->flowflags & FLOW_PKT_TOCLIENT) && !(p->flowflags & FLOW_PKT_TOCLIENT_IPONLY_SET))) {
                    SCLogDebug("testing against \"ip-only\" signatures");

                    if (p->flow != NULL) {
                        /* Update flow flags for iponly */
                        FLOWLOCK_WRLOCK(p->flow);
                        FlowSetIPOnlyFlagNoLock(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0);

                        if (s->action & ACTION_DROP)
                            p->flow->flags |= FLOW_ACTION_DROP;
                        if (s->action & ACTION_REJECT)
                            p->flow->flags |= FLOW_ACTION_DROP;
                        if (s->action & ACTION_REJECT_DST)
                            p->flow->flags |= FLOW_ACTION_DROP;
                        if (s->action & ACTION_REJECT_BOTH)
                            p->flow->flags |= FLOW_ACTION_DROP;
                        if (s->action & ACTION_PASS) {
                            FlowSetNoPacketInspectionFlag(p->flow);
                        }
                        FLOWLOCK_UNLOCK(p->flow);
                    }
                }
            }

            /* set verdict on packet */
            p->action |= p->alerts.alerts[i].action;

            if (p->action & ACTION_PASS) {
                /* Ok, reset the alert cnt to end in the previous of pass
                 * so we ignore the rest with less prio */
                p->alerts.cnt = i;
                break;
            /* if the signature wants to drop, check if the
             * PACKET_ALERT_FLAG_DROP_FLOW flag is set. */
            } else if ((p->action & ACTION_DROP) &&
                    ((p->alerts.alerts[i].flags & PACKET_ALERT_FLAG_DROP_FLOW) ||
                         (s->flags & SIG_FLAG_APPLAYER))
                       && p->flow != NULL)
            {
                FLOWLOCK_WRLOCK(p->flow);
                /* This will apply only on IPS mode (check StreamTcpPacket) */
                p->flow->flags |= FLOW_ACTION_DROP;
                FLOWLOCK_UNLOCK(p->flow);
            }
        }

        /* Thresholding removes this alert */
        if (res == 0 || res == 2) {
            PacketAlertRemove(p, i);

            if (p->alerts.cnt == 0)
                break;
        } else {
            i++;
        }
    }

    /* At this point, we should have all the new alerts. Now check the tag
     * keyword context for sessions and hosts */
    TagHandlePacket(de_ctx, det_ctx, p);
}