Exemplo n.º 1
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;
}
Exemplo n.º 2
0
/* Main runtime entry point */
static void ProcessModbus(void *ipacketp, void *contextp)
{
    SFSnortPacket *packetp = (SFSnortPacket *)ipacketp;
    modbus_session_data_t *sessp;
    PROFILE_VARS;

    // preconditions - what we registered for
    assert(IsTCP(packetp) && packetp->payload && packetp->payload_size);

    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.sessionAPI->get_application_data(packetp->stream_session, 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) && ModbusIsPafActive(packetp) )
    {
        if ( sessp )
        {
            sessp->unit = 0;
            sessp->func = 0;
        }
        /* 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 Stream 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 */
    if (ModbusDecode(modbus_eval_config, packetp) == MODBUS_FAIL)
    {
        sessp->unit = 0;
        sessp->func = 0;
    }

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