Example #1
0
/*
 *  Check flow function
 *
 *          p: packet data structure, same as the one found in snort.
 *  flowFlags: data defined in the detection plugin for this rule option
 *
 * Returns:
 *    > 0 : match found
 *    = 0 : no match found
 *
 * Predefined constants:
 *    (see sf_snort_plugin_api.h for more values)
 *    RULE_MATCH   -  if packet flow matches rule
 *    RULE_NOMATCH -  if packet flow does not match rule
 *
 */
ENGINE_LINKAGE int checkFlow(void *p, FlowFlags *flowFlags)
{
    SFSnortPacket *sp = (SFSnortPacket *) p;

#define FLOW_DIRECTION_FLAGS (FLOW_ESTABLISHED | FLOW_TO_CLIENT | FLOW_TO_SERVER)

    /* Check that the flags set in the flow structure are the same ones
     * set in the packet -- covers established, and to/from client/server */
    if ((sp->flags & (flowFlags->flags & FLOW_DIRECTION_FLAGS)) != (flowFlags->flags & FLOW_DIRECTION_FLAGS))
        return RULE_NOMATCH;

    /* check if this rule only applies to reassembled */
    if (flowFlags->flags & FLOW_ONLY_REASSEMBLED)
    {
        if ( !(sp->flags & FLAG_REBUILT_STREAM)
#ifdef ENABLE_PAF
            && !PacketHasFullPDU(sp)
#endif
        )
            return RULE_NOMATCH;
    }
    /* check if this rule only applies to non-reassembled */
    if ((flowFlags->flags & FLOW_IGNORE_REASSEMBLED) &&
        (sp->flags & FLAG_REBUILT_STREAM))
        return RULE_NOMATCH;

    return RULE_MATCH;
}
Example #2
0
/* Modbus rule evaluation callback. */
int ModbusRuleEval(void *raw_packet, const uint8_t **cursor, void *data)
{
    SFSnortPacket *packet = (SFSnortPacket *)raw_packet;
    modbus_option_data_t *rule_data = (modbus_option_data_t *)data;
    modbus_session_data_t *session_data;

    /* The preprocessor only evaluates PAF-flushed PDUs. If the rule options
       don't check for this, they'll fire on stale session data when the
       original packet goes through before flushing. */
    if (!PacketHasFullPDU(packet) && ModbusIsPafActive(packet))
        return RULE_NOMATCH;

    session_data = (modbus_session_data_t *)
        _dpd.sessionAPI->get_application_data(packet->stream_session, PP_MODBUS);

    if ((packet->payload_size == 0 ) || (session_data == NULL))
    {
        return RULE_NOMATCH;
    }


    switch (rule_data->type)
    {
        case MODBUS_FUNC:
            if (session_data->func == rule_data->arg)
                return RULE_MATCH;
            break;

        case MODBUS_UNIT:
            if (session_data->unit == rule_data->arg)
                return RULE_MATCH;
            break;

        case MODBUS_DATA:
            /* XXX: If a PDU contains only the MBAP + Function, should this
               option fail or set the cursor to the end of the payload? */
            if (packet->payload_size < MODBUS_MIN_LEN)
                return RULE_NOMATCH;

            /* Modbus data is always directly after the function code. */
            *cursor = (const uint8_t *) (packet->payload + MODBUS_MIN_LEN);
            _dpd.SetAltDetect((uint8_t *)*cursor, (uint16_t)(packet->payload_size - MODBUS_MIN_LEN));

            return RULE_MATCH;
    }

    return RULE_NOMATCH;
}
Example #3
0
/* Main runtime entry point */
static void ProcessModbus(void *ipacketp, void *contextp)
{
    SFSnortPacket *packetp = (SFSnortPacket *)ipacketp;
    modbus_session_data_t *sessp;
    PROFILE_VARS;

    /* Sanity checks. Should this preprocessor run? */
    if (( !packetp ) ||
        ( !packetp->payload ) ||
        ( !packetp->payload_size ) ||
        ( !IPH_IS_VALID(packetp) ) ||
        ( !packetp->tcp_header ))
    {
        return;
    }

    PREPROC_PROFILE_START(modbusPerfStats);

    /* Fetch me a preprocessor config to use with this VLAN/subnet/etc.! */
    modbus_eval_config = sfPolicyUserDataGetCurrent(modbus_context_id);

    /* Look for a previously-allocated session data. */
    sessp = _dpd.streamAPI->get_application_data(packetp->stream_session_ptr, PP_MODBUS);
    
    if (sessp == NULL)
    {
        /* No existing session. Check those ports. */
        if (ModbusPortCheck(modbus_eval_config, packetp) != MODBUS_OK)
        {
            PREPROC_PROFILE_END(modbusPerfStats);
            return;
        }
    }

    if ( !PacketHasFullPDU(packetp) )
    {
        /* If a packet is rebuilt, but not a full PDU, then it's garbage that
           got flushed at the end of a stream. */
        if ( packetp->flags & (FLAG_REBUILT_STREAM|FLAG_PDU_HEAD) )
        {
            _dpd.alertAdd(GENERATOR_SPP_MODBUS, MODBUS_BAD_LENGTH, 1, 0, 3,
                          MODBUS_BAD_LENGTH_STR, 0);
        }

        PREPROC_PROFILE_END(modbusPerfStats);
        return;
    }
    
    if (sessp == NULL)
    {
        /* Create session data and attach it to the Stream5 session */
        sessp = ModbusCreateSessionData(packetp);

        if ( !sessp )
        {
            PREPROC_PROFILE_END(modbusPerfStats);
            return;
        }
    }

    /* When pipelined Modbus PDUs appear in a single TCP segment, the
       detection engine caches the results of the rule options after
       evaluating on the first PDU. Setting this flag stops the caching. */
    packetp->flags |= FLAG_ALLOW_MULTIPLE_DETECT;

    /* Do preprocessor-specific detection stuff here */
    ModbusDecode(modbus_eval_config, packetp);

    /* That's the end! */
    PREPROC_PROFILE_END(modbusPerfStats);
}
Example #4
0
/* Main runtime entry point */
static void ProcessDNP3(void *ipacketp, void *contextp)
{
    SFSnortPacket *packetp = (SFSnortPacket *)ipacketp;
    MemBucket *tmp_bucket = NULL;
    dnp3_session_data_t *sessp = NULL;
    PROFILE_VARS;

    /* Sanity checks. Should this preprocessor run? */
    if (( !packetp ) ||
        ( !packetp->payload ) ||
        ( !packetp->payload_size ) ||
        ( !IPH_IS_VALID(packetp) ) ||
        ( !packetp->tcp_header && !packetp->udp_header ))
    {
        return;
    }

    /* If TCP, require that PAF flushes full PDUs first. */
    if (packetp->tcp_header && !PacketHasFullPDU(packetp))
        return;

    PREPROC_PROFILE_START(dnp3PerfStats);

    /* When pipelined DNP3 PDUs appear in a single TCP segment or UDP packet,
       the detection engine caches the results of the rule options after
       evaluating on the first PDU. Setting this flag stops the caching. */
    packetp->flags |= FLAG_ALLOW_MULTIPLE_DETECT;

    /* Fetch me a preprocessor config to use with this VLAN/subnet/etc.! */
    dnp3_eval_config = sfPolicyUserDataGetCurrent(dnp3_context_id);

    /* Look for a previously-allocated session data. */
    tmp_bucket = _dpd.streamAPI->get_application_data(packetp->stream_session_ptr, PP_DNP3);

    if (tmp_bucket == NULL)
    {
        /* No existing session. Check those ports. */
        if (DNP3PortCheck(dnp3_eval_config, packetp) != DNP3_OK)
        {
            PREPROC_PROFILE_END(dnp3PerfStats);
            return;
        }

        /* Create session data and attach it to the Stream5 session */
        tmp_bucket = DNP3CreateSessionData(packetp);

        if (tmp_bucket == NULL)
        {
            /* Mempool was full, don't process this session. */
            static unsigned int times_mempool_alloc_failed = 0;

            /* Print a message, but only every 1000 times.
               Don't want to flood the log if there's a lot of DNP3 traffic. */
            if (times_mempool_alloc_failed % 1000)
            {
                _dpd.logMsg("WARNING: DNP3 memcap exceeded.\n");
            }
            times_mempool_alloc_failed++;

            PREPROC_PROFILE_END(dnp3PerfStats);
            return;
        }
    }

    sessp = (dnp3_session_data_t *) tmp_bucket->data;

    /* Set reassembly direction */
    if (packetp->flags & FLAG_FROM_CLIENT)
        sessp->direction = DNP3_CLIENT;
    else
        sessp->direction = DNP3_SERVER;

    /* Do preprocessor-specific detection stuff here */
    if (packetp->tcp_header)
    {
        /* Single PDU. PAF already split them up into separate pseudo-packets. */
        DNP3FullReassembly(dnp3_eval_config, sessp, packetp,
                           (uint8_t *)packetp->payload, packetp->payload_size);
    }
    else if (packetp->udp_header)
    {
        DNP3ProcessUDP(dnp3_eval_config, sessp, packetp);
    }

    /* That's the end! */
    PREPROC_PROFILE_END(dnp3PerfStats);
}