예제 #1
0
/********************************************************************
 * Function:
 *
 * Purpose:
 *
 * Arguments:
 *
 * Returns:
 *
 ********************************************************************/
void * DCE2_ReAlloc(void *old_mem, uint32_t old_size, uint32_t new_size, DCE2_MemType mtype)
{
    void *new_mem;
    DCE2_Ret status;

    if (dce2_mem_state == DCE2_MEM_STATE__MEMCAP)
        return NULL;

    if (old_mem == NULL)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) Old memory passed in was NULL.",
                 __FILE__, __LINE__);
        return NULL;
    }
    else if (new_size < old_size)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) New size is less than old size.",
                 __FILE__, __LINE__);
        return NULL;
    }
    else if (new_size == old_size)
    {
        return old_mem;
    }

    if (DCE2_CheckMemcap(new_size - old_size, mtype) == DCE2_MEMCAP_EXCEEDED)
        return NULL;

    new_mem = DCE2_Alloc(new_size, mtype);
    if (new_mem == NULL)
        return NULL;

    status = DCE2_Memcpy(new_mem, old_mem, old_size,
                         new_mem, (void *)((uint8_t *)new_mem + new_size));

    if (status != DCE2_RET__SUCCESS)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) Failed to copy old memory into new memory.",
                 __FILE__, __LINE__);
        DCE2_Free(new_mem, new_size, mtype);
        return NULL;
    }

    DCE2_Free(old_mem, old_size, mtype);

    return new_mem;
}
예제 #2
0
/********************************************************************
 * Function: DCE2_GetDebugLevel()
 *
 * Gets the debugging level set by the DCE2 debugging environment
 * variable on the first call.  Subsequent calls will used the
 * cached value.
 *
 * Arguments: None
 *
 * Returns:
 *  uint32_t
 *      The debugging level set by the environment variable.
 *
 ********************************************************************/
static uint32_t DCE2_GetDebugLevel(void)
{
    static int debug_init = 0;
    static uint32_t debug_level = 0;
    const char* value;

    if (debug_init)
        return debug_level;

    value = getenv(DCE2_DEBUG_VARIABLE);

    if (value != NULL)
    {
        char *endptr;

        debug_level = _dpd.SnortStrtoul(value, &endptr, 0);
        if ((errno == ERANGE) || (*endptr != '\0'))
        {
            DCE2_Log(DCE2_LOG_TYPE__WARN,
                     "\"%s\" value out of range or not a number: %s. "
                     "Debugging will not be turned on.",
                     DCE2_DEBUG_VARIABLE, value);

            debug_level = 0;
        }
    }

    debug_init = 1;

    return debug_level;
}
예제 #3
0
파일: dce2_utils.c 프로젝트: nirosen/Snort
/********************************************************************
 * Function:
 *
 * Purpose:
 *
 * Arguments:
 *
 * Returns:
 *
 ********************************************************************/
DCE2_Ret DCE2_BufferAddData(
    DCE2_Buffer *buf, const uint8_t *data,
    uint32_t data_len, uint32_t offset,
    DCE2_BufferMinAddFlag mflag)
{
    DCE2_Ret status;

    if ((buf == NULL) || (data == NULL))
        return DCE2_RET__ERROR;

    /* Return success for this since ultimately nothing _was_ added */
    if (data_len == 0)
        return DCE2_RET__SUCCESS;

    if ( !offset )
        offset = DCE2_BufferLength(buf);

    if (buf->data == NULL)
    {
        uint32_t size = offset + data_len;

        if ((size < buf->min_add_size) && (mflag == DCE2_BUFFER_MIN_ADD_FLAG__USE))
            size = buf->min_add_size;

        buf->data = (uint8_t *)DCE2_Alloc(size, buf->mtype);
        if (buf->data == NULL)
            return DCE2_RET__ERROR;

        buf->size = size;
    }
    else if ((offset + data_len) > buf->size)
    {
        uint8_t *tmp;
        uint32_t new_size = offset + data_len;

        if (((new_size - buf->size) < buf->min_add_size) && (mflag == DCE2_BUFFER_MIN_ADD_FLAG__USE))
            new_size += buf->min_add_size;

        tmp = (uint8_t *)DCE2_ReAlloc(buf->data, buf->size, new_size, buf->mtype);
        if (tmp == NULL)
            return DCE2_RET__ERROR;

        buf->data = tmp;
        buf->size = new_size;
    }

    status = DCE2_Memcpy(buf->data + offset, data, data_len, buf->data, buf->data + buf->size);
    if (status != DCE2_RET__SUCCESS)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) Failed to copy data into buffer.", __FILE__, __LINE__);
        return DCE2_RET__ERROR;
    }

    buf->len = offset + data_len;

    return DCE2_RET__SUCCESS;
}
예제 #4
0
/******************************************************************
 * Function: DCE2_Reset()
 *
 * Purpose: Reset the preprocessor to a post configuration state.
 *
 * Arguments:
 *  int - signal that caused the reset
 *  void * - pointer to data
 *
 * Returns: None
 *
 ******************************************************************/
static void DCE2_Reset(int signal, void *data)
{
    if (!DCE2_CStackIsEmpty(dce2_pkt_stack))
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) Packet stack is not empty when it should be.",
                 __FILE__, __LINE__);

        DCE2_CStackEmpty(dce2_pkt_stack);
    }
}
예제 #5
0
/*********************************************************************
 * Function:
 *
 * Purpose:
 *
 * Arguments:
 *
 * Returns:
 *
 *********************************************************************/
void DCE2_Detect(DCE2_SsnData *sd)
{
    SFSnortPacket *top_pkt = (SFSnortPacket *)DCE2_CStackTop(dce2_pkt_stack);
    PROFILE_VARS;

    if (top_pkt == NULL)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) No packet on top of stack.",
                 __FILE__, __LINE__);
        return;
    }

    DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Detecting ------------------------------------------------\n"));
    DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, " Rule options:\n"));
    DCE2_DEBUG_CODE(DCE2_DEBUG__ROPTIONS, DCE2_PrintRoptions(&sd->ropts););
예제 #6
0
/*********************************************************************
 * Function:
 *
 * Purpose:
 *
 * Arguments:
 *
 * Returns:
 *
 *********************************************************************/
void DCE2_PopPkt(void)
{
    SFSnortPacket *pop_pkt = (SFSnortPacket *)DCE2_CStackPop(dce2_pkt_stack);
    PROFILE_VARS;

    PREPROC_PROFILE_START(dce2_pstat_log);

    if (pop_pkt == NULL)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) No packet to pop off stack.",
                 __FILE__, __LINE__);
        PREPROC_PROFILE_END(dce2_pstat_log);
        return;
    }

    _dpd.pushAlerts();
    _dpd.logAlerts((void *)pop_pkt);
    _dpd.resetAlerts();
    _dpd.popAlerts();

    PREPROC_PROFILE_END(dce2_pstat_log);
}
예제 #7
0
파일: dce2_cl.c 프로젝트: jasonish/snort
/********************************************************************
 * Function: DCE2_ClFragReassemble()
 *
 * Reassembles fragments into reassembly buffer and copies to
 * reassembly packet.
 *
 * Arguments:
 *  DCE2_SsnData *
 *      Pointer to the session data structure.
 *  DCE2_ClActTracker *
 *      Pointer to the connectionless activity tracker.
 *  DceRpcClHdr *
 *      Pointer to the connectionless header in the packet.
 *
 * Returns: None
 *
 ********************************************************************/
static void DCE2_ClFragReassemble(DCE2_SsnData *sd, DCE2_ClActTracker *at, const DceRpcClHdr *cl_hdr)
{
    DCE2_ClFragTracker *ft = &at->frag_tracker;
    DCE2_ClFragNode *fnode;
    uint8_t *rdata = dce2_cl_rbuf;
    uint16_t rlen = sizeof(dce2_cl_rbuf);
    uint32_t stub_len = 0;
    const uint8_t *stub_data = NULL;
    SFSnortPacket *rpkt = NULL;
    PROFILE_VARS;

    PREPROC_PROFILE_START(dce2_pstat_cl_reass);

    for (fnode = (DCE2_ClFragNode *)DCE2_ListFirst(ft->frags);
         fnode != NULL;
         fnode = (DCE2_ClFragNode *)DCE2_ListNext(ft->frags))
    {
        if (fnode->frag_len > rlen)
        {
            DCE2_Log(DCE2_LOG_TYPE__WARN,
                     "%s(%d) Size of fragments exceeds reassembly buffer size. "
                     "Using as many fragments as will fit.", __FILE__, __LINE__);
            break;
        }

        if (DCE2_Memcpy(rdata, fnode->frag_data, fnode->frag_len, rdata, rdata + rlen) != DCE2_RET__SUCCESS)
        {
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Failed to copy data into fragment "
                     "reassembly buffer.", __FILE__, __LINE__);
            break;
        }

        DCE2_MOVE(rdata, rlen, fnode->frag_len);
        stub_len += fnode->frag_len;
    }

    switch (sd->trans)
    {
        case DCE2_TRANS_TYPE__UDP:
            rpkt = DCE2_GetRpkt(sd->wire_pkt, DCE2_RPKT_TYPE__UDP_CL_FRAG, dce2_cl_rbuf, stub_len);
            if (rpkt == NULL)
            {
                DCE2_Log(DCE2_LOG_TYPE__ERROR,
                         "%s(%d) Failed to create reassembly packet.",
                         __FILE__, __LINE__);
                PREPROC_PROFILE_END(dce2_pstat_cl_reass);
                return;
            }

            DCE2_ClSetRdata(at, cl_hdr, (uint8_t *)rpkt->payload,
                            (uint16_t)(rpkt->payload_size - DCE2_MOCK_HDR_LEN__CL));

            stub_data = rpkt->payload + DCE2_MOCK_HDR_LEN__CL;

            break;

        default:
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Invalid transport type: %d",
                     __FILE__, __LINE__, sd->trans);
            return;
    }

    PREPROC_PROFILE_END(dce2_pstat_cl_reass);

    if (DCE2_PushPkt(rpkt) != DCE2_RET__SUCCESS)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) Failed to push packet onto packet stack.",
                 __FILE__, __LINE__);
        return;
    }

    /* Cache relevant values for rule option processing */
    sd->ropts.first_frag = 1;
    DCE2_CopyUuid(&sd->ropts.iface, &ft->iface, DCERPC_BO_FLAG__NONE);
    sd->ropts.iface_vers = ft->iface_vers;
    sd->ropts.hdr_byte_order = DceRpcClByteOrder(cl_hdr);

    if (ft->data_byte_order != DCE2_SENTINEL)
        sd->ropts.data_byte_order = ft->data_byte_order;
    else
        sd->ropts.data_byte_order = DceRpcClByteOrder(cl_hdr);

    if (ft->opnum != DCE2_SENTINEL)
        sd->ropts.opnum = ft->opnum;
    else
        sd->ropts.opnum = DceRpcClOpnum(cl_hdr);

    sd->ropts.stub_data = stub_data;

    DCE2_Detect(sd);
    DCE2_PopPkt();

    dce2_stats.cl_frag_reassembled++;
}
예제 #8
0
/********************************************************************
 * Function:
 *
 * Purpose:
 *
 * Arguments:
 *
 * Returns:
 *
 ********************************************************************/
void DCE2_RegMem(uint32_t size, DCE2_MemType mtype)
{
    switch (mtype)
    {
        case DCE2_MEM_TYPE__CONFIG:
            dce2_memory.config += size;
            if (dce2_memory.config > dce2_memory.config_max)
                dce2_memory.config_max = dce2_memory.config;
            break;

        case DCE2_MEM_TYPE__ROPTION:
            dce2_memory.roptions += size;
            if (dce2_memory.roptions > dce2_memory.roptions_max)
                dce2_memory.roptions_max = dce2_memory.roptions;
            break;

        case DCE2_MEM_TYPE__RT:
            dce2_memory.rt += size;
            if (dce2_memory.rt > dce2_memory.rt_max)
                dce2_memory.rt_max = dce2_memory.rt;
            break;

        case DCE2_MEM_TYPE__INIT:
            dce2_memory.init += size;
            if (dce2_memory.init > dce2_memory.init_max)
                dce2_memory.init_max = dce2_memory.init;
            break;

        case DCE2_MEM_TYPE__SMB_SSN:
        case DCE2_MEM_TYPE__SMB_SEG:
        case DCE2_MEM_TYPE__SMB_UID:
        case DCE2_MEM_TYPE__SMB_TID:
        case DCE2_MEM_TYPE__SMB_FID:
        case DCE2_MEM_TYPE__SMB_UT:
        case DCE2_MEM_TYPE__SMB_PM:
            DCE2_RegMemSmb(size, mtype);
            break;

        case DCE2_MEM_TYPE__TCP_SSN:
            dce2_memory.tcp_ssn += size;
            if (dce2_memory.tcp_ssn > dce2_memory.tcp_ssn_max)
                dce2_memory.tcp_ssn_max = dce2_memory.tcp_ssn;

            dce2_memory.tcp_total += size;
            if (dce2_memory.tcp_total > dce2_memory.tcp_total_max)
                dce2_memory.tcp_total_max = dce2_memory.tcp_total;

            break;

        case DCE2_MEM_TYPE__CO_SEG:
        case DCE2_MEM_TYPE__CO_FRAG:
        case DCE2_MEM_TYPE__CO_CTX:
            DCE2_RegMemCo(size, mtype);
            break;

        case DCE2_MEM_TYPE__UDP_SSN:
            dce2_memory.udp_ssn += size;
            if (dce2_memory.udp_ssn > dce2_memory.udp_ssn_max)
                dce2_memory.udp_ssn_max = dce2_memory.udp_ssn;

            dce2_memory.udp_total += size;
            if (dce2_memory.udp_total > dce2_memory.udp_total_max)
                dce2_memory.udp_total_max = dce2_memory.udp_total;

            break;

        case DCE2_MEM_TYPE__HTTP_SSN:
            dce2_memory.http_ssn += size;
            if (dce2_memory.http_ssn > dce2_memory.http_ssn_max)
                dce2_memory.http_ssn_max = dce2_memory.http_ssn;

            dce2_memory.http_total += size;
            if (dce2_memory.http_total > dce2_memory.http_total_max)
                dce2_memory.http_total_max = dce2_memory.http_total;

            break;

        case DCE2_MEM_TYPE__CL_ACT:
        case DCE2_MEM_TYPE__CL_FRAG:
            DCE2_RegMemCl(size, mtype);
            break;

        default:
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Invalid memory type: %d",
                     __FILE__, __LINE__, mtype);
            break;
    }

    switch (mtype)
    {
        case DCE2_MEM_TYPE__CONFIG:
        case DCE2_MEM_TYPE__ROPTION:
        case DCE2_MEM_TYPE__RT:
        case DCE2_MEM_TYPE__INIT:
            break;
        default:
            dce2_memory.rtotal += size;
            if (dce2_memory.rtotal > dce2_memory.rtotal_max)
                dce2_memory.rtotal_max = dce2_memory.rtotal;
    }

    dce2_memory.total += size;
    if (dce2_memory.total > dce2_memory.total_max)
        dce2_memory.total_max = dce2_memory.total;
}
예제 #9
0
/********************************************************************
 * Function:
 *
 * Purpose:
 *
 * Arguments:
 *
 * Returns:
 *
 ********************************************************************/
void DCE2_UnRegMem(uint32_t size, DCE2_MemType mtype)
{
    switch (mtype)
    {
        case DCE2_MEM_TYPE__CONFIG:
            dce2_memory.config -= size;
            break;
        case DCE2_MEM_TYPE__ROPTION:
            dce2_memory.roptions -= size;
            break;
        case DCE2_MEM_TYPE__RT:
            dce2_memory.rt -= size;
            break;
        case DCE2_MEM_TYPE__INIT:
            dce2_memory.init -= size;
            break;
        case DCE2_MEM_TYPE__SMB_SSN:
            dce2_memory.smb_total -= size;
            dce2_memory.smb_ssn -= size;
            break;
        case DCE2_MEM_TYPE__SMB_SEG:
            dce2_memory.smb_total -= size;
            dce2_memory.smb_seg -= size;
            break;
        case DCE2_MEM_TYPE__SMB_UID:
            dce2_memory.smb_total -= size;
            dce2_memory.smb_uid -= size;
            break;
        case DCE2_MEM_TYPE__SMB_TID:
            dce2_memory.smb_total -= size;
            dce2_memory.smb_tid -= size;
            break;
        case DCE2_MEM_TYPE__SMB_FID:
            dce2_memory.smb_total -= size;
            dce2_memory.smb_fid -= size;
            break;
        case DCE2_MEM_TYPE__SMB_UT:
            dce2_memory.smb_total -= size;
            dce2_memory.smb_ut -= size;
            break;
        case DCE2_MEM_TYPE__SMB_PM:
            dce2_memory.smb_total -= size;
            dce2_memory.smb_pm -= size;
            break;
        case DCE2_MEM_TYPE__TCP_SSN:
            dce2_memory.tcp_total -= size;
            dce2_memory.tcp_ssn -= size;
            break;
        case DCE2_MEM_TYPE__CO_SEG:
            dce2_memory.co_total -= size;
            dce2_memory.co_seg -= size;
            break;
        case DCE2_MEM_TYPE__CO_FRAG:
            dce2_memory.co_total -= size;
            dce2_memory.co_frag -= size;
            break;
        case DCE2_MEM_TYPE__CO_CTX:
            dce2_memory.co_total -= size;
            dce2_memory.co_ctx -= size;
            break;
        case DCE2_MEM_TYPE__UDP_SSN:
            dce2_memory.udp_total -= size;
            dce2_memory.udp_ssn -= size;
            break;
        case DCE2_MEM_TYPE__CL_ACT:
            dce2_memory.cl_total -= size;
            dce2_memory.cl_act -= size;
            break;
        case DCE2_MEM_TYPE__HTTP_SSN:
            dce2_memory.http_total -= size;
            dce2_memory.http_ssn -= size;
            break;
        case DCE2_MEM_TYPE__CL_FRAG:
            dce2_memory.cl_total -= size;
            dce2_memory.cl_frag -= size;
            break;
        default:
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Invalid memory type: %d",
                     __FILE__, __LINE__, mtype);
            break;
    }

    switch (mtype)
    {
        case DCE2_MEM_TYPE__CONFIG:
        case DCE2_MEM_TYPE__ROPTION:
        case DCE2_MEM_TYPE__RT:
        case DCE2_MEM_TYPE__INIT:
            break;
        default:
            dce2_memory.rtotal -= size;
    }

    dce2_memory.total -= size;
}
예제 #10
0
/********************************************************************
 * Function:
 *
 * Must have allocated data in buffer and data_len must fit in
 * buffer.
 *
 * Arguments:
 *
 * Returns:
 *
 ********************************************************************/
DCE2_Ret DCE2_BufferMoveData(DCE2_Buffer *buf, uint32_t data_offset,
                             const uint8_t *move, uint32_t move_len)
{
    DCE2_Ret status;
    uint8_t *offset, *end;

    if ((buf == NULL) || (buf->data == NULL) || (move == NULL))
        return DCE2_RET__ERROR;

    /* Return success for this since ultimately nothing _was_ moved */
    if (move_len == 0)
        return DCE2_RET__SUCCESS;

    offset = buf->data + data_offset;
    end = buf->data + buf->len;

    /* Moved data must be within current data */
    if ((move < buf->data) || ((move + move_len) > end))
        return DCE2_RET__ERROR;

    /* No move required */
    if (move == offset)
        return DCE2_RET__SUCCESS;

    /* Would have to do two moves.  One for the data and one to realign data
     * with start of moved data.  Don't want to succeed on the first and fail
     * on the second and leave the buffer in a bad state.  Don't want to use
     * an offset in data buffer because want to keep the size the same. */
    if (move == buf->data)
    {
        uint32_t tmp_size = buf->len;
        uint8_t *tmp = (uint8_t *)DCE2_Alloc(tmp_size, buf->mtype);
        uint8_t *tmp_offset, *tmp_end;
        uint32_t new_len;

        if (tmp == NULL)
            return DCE2_RET__ERROR;

        tmp_offset = tmp + data_offset;
        tmp_end = tmp + tmp_size;

        status = DCE2_Memcpy(tmp, buf->data, buf->len, tmp, tmp_end);
        if (status != DCE2_RET__SUCCESS)
        {
            DCE2_Free((void *)tmp, tmp_size, buf->mtype);
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Failed to move data in buffer.", __FILE__, __LINE__);
            return DCE2_RET__ERROR;
        }

        status = DCE2_Memmove(tmp_offset, tmp, move_len, tmp_offset, tmp_end);
        if (status != DCE2_RET__SUCCESS)
        {
            DCE2_Free((void *)tmp, tmp_size, buf->mtype);
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Failed to move data in buffer.", __FILE__, __LINE__);
            return DCE2_RET__ERROR;
        }

        if (tmp_offset > (tmp + move_len))
            tmp_offset = tmp + move_len;

        new_len = tmp_end - tmp_offset;

        status = DCE2_Memcpy(buf->data, tmp_offset, new_len, buf->data, end);
        if (status != DCE2_RET__SUCCESS)
        {
            DCE2_Free((void *)tmp, tmp_size, buf->mtype);
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Failed to move data in buffer.", __FILE__, __LINE__);
            return DCE2_RET__ERROR;
        }

        buf->len = new_len;

        DCE2_Free((void *)tmp, tmp_size, buf->mtype);
    }
    else
    {
        status = DCE2_Memmove(offset, move, move_len, offset, end);
        if (status != DCE2_RET__SUCCESS)
        {
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Failed to move data in buffer", __FILE__, __LINE__);
            return DCE2_RET__ERROR;
        }

        /* If we have a new end of data, adjust length */
        if ((move + move_len) == end)
            buf->len = data_offset + move_len;
    }

    return DCE2_RET__SUCCESS;
}
예제 #11
0
/*********************************************************************
 * Function:
 *
 * Purpose:
 *
 * Arguments:
 *
 * Returns:
 *
 *********************************************************************/
DCE2_Ret DCE2_AddDataToRpkt(SFSnortPacket *rpkt, DCE2_RpktType rtype,
                            const uint8_t *data, uint32_t data_len)
{
    int hdr_overhead = 0;
    const uint8_t *pkt_data_end;
    const uint8_t *payload_end;
    DCE2_Ret status;

    if ((rpkt == NULL) || (data == NULL) || (data_len == 0))
        return DCE2_RET__ERROR;

    if (rpkt->payload == NULL)
        return DCE2_RET__ERROR;

    /* This is a check to make sure we don't overwrite header data */
    switch (rtype)
    {
        case DCE2_RPKT_TYPE__SMB_CO_SEG:
            if (DCE2_SsnFromClient(rpkt))
                hdr_overhead = DCE2_MOCK_HDR_LEN__SMB_CLI;
            else
                hdr_overhead = DCE2_MOCK_HDR_LEN__SMB_SRV;
            break;

        case DCE2_RPKT_TYPE__SMB_CO_FRAG:
            if (DCE2_SsnFromClient(rpkt))
                hdr_overhead = DCE2_MOCK_HDR_LEN__SMB_CLI + DCE2_MOCK_HDR_LEN__CO_CLI;
            else
                hdr_overhead = DCE2_MOCK_HDR_LEN__SMB_SRV + DCE2_MOCK_HDR_LEN__CO_SRV;
            break;

        case DCE2_RPKT_TYPE__TCP_CO_FRAG:
            if (DCE2_SsnFromClient(rpkt))
                hdr_overhead = DCE2_MOCK_HDR_LEN__CO_CLI;
            else
                hdr_overhead = DCE2_MOCK_HDR_LEN__CO_SRV;
            break;

        case DCE2_RPKT_TYPE__UDP_CL_FRAG:
            hdr_overhead = DCE2_MOCK_HDR_LEN__CL;
            break;

        default:
            break;
    }

    if (rpkt->payload_size < hdr_overhead)
        return DCE2_RET__ERROR;

    pkt_data_end = rpkt->pkt_data + rpkt->max_payload;
    payload_end = rpkt->payload + rpkt->payload_size;

    if ((payload_end + data_len) > pkt_data_end)
        data_len = pkt_data_end - payload_end;

    status = DCE2_Memcpy((void *)payload_end, (void *)data, (size_t)data_len,
                         (void *)payload_end, (void *)pkt_data_end);

    if (status != DCE2_RET__SUCCESS)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) Failed to copy data into reassembly packet.",
                 __FILE__, __LINE__);
        return DCE2_RET__ERROR;
    }

    rpkt->payload_size += (uint16_t)data_len;
    // there is room for optimization here since the update was done
    // earlier - that my be eliminated, but only in this case one
    // approach is to move the updates to push pkt - but don't want
    // to update non-dce2 pseudo pkts; perhaps a flag check there
    // will suffice.
    _dpd.encodeUpdate(rpkt);

    if (rpkt->family == AF_INET)
    {
        rpkt->ip4h->ip_len = rpkt->ip4_header->data_length;
    }
    else
    {
        IP6RawHdr* ip6h = (IP6RawHdr*)rpkt->raw_ip6_header;
        if ( ip6h ) rpkt->ip6h->len = ip6h->ip6_payload_len;
    }
    return DCE2_RET__SUCCESS;
}
예제 #12
0
/*********************************************************************
 * Function:
 *
 * Purpose:
 *
 * Arguments:
 *
 * Returns:
 *
 *********************************************************************/
static DCE2_SsnData * DCE2_NewSession(SFSnortPacket *p, tSfPolicyId policy_id)
{
    DCE2_SsnData *sd = NULL;
    DCE2_TransType trans;
    const DCE2_ServerConfig *sc = DCE2_ScGetConfig(p);
    int autodetected = 0;
    PROFILE_VARS;

    PREPROC_PROFILE_START(dce2_pstat_new_session);

    DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Creating new session: "));
    trans = DCE2_GetTransport(p, sc, &autodetected);
    switch (trans)
    {
        case DCE2_TRANS_TYPE__SMB:
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "SMB transport ... "));
            sd = (DCE2_SsnData *)DCE2_SmbSsnInit(p);
            break;

        case DCE2_TRANS_TYPE__TCP:
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "TCP transport ... "));
            sd = (DCE2_SsnData *)DCE2_TcpSsnInit();
            break;

        case DCE2_TRANS_TYPE__UDP:
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "UDP transport ... "));
            sd = (DCE2_SsnData *)DCE2_UdpSsnInit();
            break;

        case DCE2_TRANS_TYPE__HTTP_PROXY:
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "RPC over HTTP proxy transport ... "));
            sd = (DCE2_SsnData *)DCE2_HttpProxySsnInit();
            break;

        case DCE2_TRANS_TYPE__HTTP_SERVER:
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "RPC over HTTP server transport ... "));
            sd = (DCE2_SsnData *)DCE2_HttpServerSsnInit();
            break;

        case DCE2_TRANS_TYPE__NONE:
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Not configured to "
                        "look at this traffic or unable to autodetect - not inspecting.\n"));
            PREPROC_PROFILE_END(dce2_pstat_new_session);
            return NULL;

        default:
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Invalid transport type: %d",
                     __FILE__, __LINE__, trans);
            PREPROC_PROFILE_END(dce2_pstat_new_session);
            return NULL;
    }

    if (sd == NULL)
    {
        PREPROC_PROFILE_END(dce2_pstat_new_session);
        return NULL;
    }

    DCE2_SsnSetAppData(p, (void *)sd, DCE2_SsnFree);

    dce2_stats.sessions++;
    DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Created (%p)\n", (void *)sd));

    sd->trans = trans;
    sd->server_policy = DCE2_ScPolicy(sc);
    sd->client_policy = DCE2_POLICY__WINXP;  // Default to Windows XP
    sd->sconfig = sc;
    sd->wire_pkt = p;

    sd->policy_id = policy_id;
    sd->config = dce2_config;
    ((DCE2_Config *)sfPolicyUserDataGet(sd->config, policy_id))->ref_count++;

    if (autodetected)
    {
        dce2_stats.sessions_autodetected++;

#ifdef DEBUG
        if (DCE2_SsnFromServer(p))
            dce2_stats.autoports[p->src_port][trans]++;
        else
            dce2_stats.autoports[p->dst_port][trans]++;
#endif

        DCE2_SsnSetAutodetected(sd, p);
    }

    /* If we've determined a transport, make sure we're doing
     * reassembly on the session */
    if (IsTCP(p))
    {
        int rs_dir = DCE2_SsnGetReassembly(p);

        if (!_dpd.isPafEnabled() && (rs_dir != SSN_DIR_BOTH))
        {
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN,
                        "Setting client/server reassembly to FOOTPRINT for this session.\n"));
            DCE2_SsnSetReassembly(p);
        }

        if (!DCE2_SsnIsRebuilt(p))
        {
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Got non-rebuilt packet\n"));

            if (DCE2_SsnIsStreamInsert(p))
            {
                DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Stream inserted - not inspecting.\n"));
                PREPROC_PROFILE_END(dce2_pstat_new_session);
                return NULL;
            }
            else if ((DCE2_SsnFromClient(p) && (rs_dir == SSN_DIR_FROM_SERVER))
                     || (DCE2_SsnFromServer(p) && (rs_dir == SSN_DIR_FROM_CLIENT))
                     || (rs_dir == SSN_DIR_BOTH))
            {
                /* Reassembly was already set for this session, but stream
                 * decided not to use the packet so it's probably not good */
                DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Got non-stream inserted packet - not inspecting\n"));
                PREPROC_PROFILE_END(dce2_pstat_new_session);
                return NULL;
            }
        }
    }

    PREPROC_PROFILE_END(dce2_pstat_new_session);
    return sd;
}
예제 #13
0
/*********************************************************************
 * Function: DCE2_GetRpkt()
 *
 * Purpose:
 *
 * Arguments:
 *  SFSnortPacket *  - pointer to packet off wire
 *  const uint8_t *  - pointer to data to attach to reassembly packet
 *  uint16_t - length of data
 *
 * Returns:
 *  SFSnortPacket * - pointer to reassembly packet
 *
 *********************************************************************/
SFSnortPacket * DCE2_GetRpkt(const SFSnortPacket *wire_pkt, DCE2_RpktType rpkt_type,
                             const uint8_t *data, uint32_t data_len)
{
    DCE2_Ret status;
    SFSnortPacket *rpkt;
    uint16_t payload_len = 0;
    uint16_t data_overhead = 0;

    rpkt = dce2_rpkt[rpkt_type];

    switch (rpkt_type)
    {
        case DCE2_RPKT_TYPE__SMB_SEG:
            _dpd.encodeFormat(ENC_DYN_FWD, wire_pkt, rpkt, PSEUDO_PKT_SMB_SEG);
            break;

        case DCE2_RPKT_TYPE__SMB_TRANS:
            // TBD these memset()s could be encapsulated by the various
            // init functions which should also return the data_overhead.
            // Better still pass in rpkt and let the init function update
            // payload, etc.  Also, some memsets could probably be avoided
            // by explicitly setting the unitialized header fields.
            _dpd.encodeFormat(ENC_DYN_FWD, wire_pkt, rpkt, PSEUDO_PKT_SMB_TRANS);

            if (DCE2_SsnFromClient(wire_pkt))
            {
                data_overhead = DCE2_MOCK_HDR_LEN__SMB_CLI;
                memset((void*)rpkt->payload, 0, data_overhead);
                DCE2_SmbInitRdata((uint8_t *)rpkt->payload, FLAG_FROM_CLIENT);
            }
            else
            {
                data_overhead = DCE2_MOCK_HDR_LEN__SMB_SRV;
                memset((void*)rpkt->payload, 0, data_overhead);
                DCE2_SmbInitRdata((uint8_t *)rpkt->payload, FLAG_FROM_SERVER);
            }
            break;

        case DCE2_RPKT_TYPE__SMB_CO_SEG:
            _dpd.encodeFormat(ENC_DYN_FWD, wire_pkt, rpkt, PSEUDO_PKT_DCE_SEG);

            if (DCE2_SsnFromClient(wire_pkt))
            {
                data_overhead = DCE2_MOCK_HDR_LEN__SMB_CLI;
                memset((void*)rpkt->payload, 0, data_overhead);
                DCE2_SmbInitRdata((uint8_t *)rpkt->payload, FLAG_FROM_CLIENT);
            }
            else
            {
                data_overhead = DCE2_MOCK_HDR_LEN__SMB_SRV;
                memset((void*)rpkt->payload, 0, data_overhead);
                DCE2_SmbInitRdata((uint8_t *)rpkt->payload, FLAG_FROM_SERVER);
            }
            break;

        case DCE2_RPKT_TYPE__SMB_CO_FRAG:
            _dpd.encodeFormat(ENC_DYN_FWD, wire_pkt, rpkt, PSEUDO_PKT_DCE_FRAG);

            if (DCE2_SsnFromClient(wire_pkt))
            {
                data_overhead = DCE2_MOCK_HDR_LEN__SMB_CLI + DCE2_MOCK_HDR_LEN__CO_CLI;
                memset((void*)rpkt->payload, 0, data_overhead);
                DCE2_SmbInitRdata((uint8_t *)rpkt->payload, FLAG_FROM_CLIENT);
                DCE2_CoInitRdata((uint8_t *)rpkt->payload +
                    DCE2_MOCK_HDR_LEN__SMB_CLI, FLAG_FROM_CLIENT);
            }
            else
            {
                data_overhead = DCE2_MOCK_HDR_LEN__SMB_SRV + DCE2_MOCK_HDR_LEN__CO_SRV;
                memset((void*)rpkt->payload, 0, data_overhead);
                DCE2_SmbInitRdata((uint8_t *)rpkt->payload, FLAG_FROM_SERVER);
                DCE2_CoInitRdata((uint8_t *)rpkt->payload +
                    DCE2_MOCK_HDR_LEN__SMB_SRV, FLAG_FROM_SERVER);
            }
            break;

        case DCE2_RPKT_TYPE__TCP_CO_SEG:
            _dpd.encodeFormat(ENC_DYN_FWD, wire_pkt, rpkt, PSEUDO_PKT_DCE_SEG);
            break;

        case DCE2_RPKT_TYPE__TCP_CO_FRAG:
            _dpd.encodeFormat(ENC_DYN_FWD, wire_pkt, rpkt, PSEUDO_PKT_DCE_FRAG);

            if (DCE2_SsnFromClient(wire_pkt))
            {
                data_overhead = DCE2_MOCK_HDR_LEN__CO_CLI;
                memset((void*)rpkt->payload, 0, data_overhead);
                DCE2_CoInitRdata((uint8_t *)rpkt->payload, FLAG_FROM_CLIENT);
            }
            else
            {
                data_overhead = DCE2_MOCK_HDR_LEN__CO_SRV;
                memset((void*)rpkt->payload, 0, data_overhead);
                DCE2_CoInitRdata((uint8_t *)rpkt->payload, FLAG_FROM_SERVER);
            }
            break;

        case DCE2_RPKT_TYPE__UDP_CL_FRAG:
            _dpd.encodeFormat(ENC_DYN_FWD, wire_pkt, rpkt, PSEUDO_PKT_DCE_FRAG);
            data_overhead = DCE2_MOCK_HDR_LEN__CL;
            memset((void*)rpkt->payload, 0, data_overhead);
            DCE2_ClInitRdata((uint8_t *)rpkt->payload);
            break;

        default:
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Invalid reassembly packet type: %d",
                     __FILE__, __LINE__, rpkt_type);
            return NULL;
    }

    payload_len = rpkt->max_payload;

    if ((data_overhead + data_len) > payload_len)
        data_len -= (data_overhead + data_len) - payload_len;

    status = DCE2_Memcpy(
        (void *)(rpkt->payload + data_overhead),
        (void *)data, (size_t)data_len, (void *)rpkt->payload,
        (void *)((uint8_t *)rpkt->payload + payload_len));

    if (status != DCE2_RET__SUCCESS)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) Failed to copy data into reassembly packet.",
                 __FILE__, __LINE__);
        return NULL;
    }

    rpkt->payload_size = (uint16_t)(data_overhead + data_len);
    _dpd.encodeUpdate(rpkt);

    if (wire_pkt->family == AF_INET)
    {
        rpkt->ip4h->ip_len = rpkt->ip4_header->data_length;
    }
    else
    {
        IP6RawHdr* ip6h = (IP6RawHdr*)rpkt->raw_ip6_header;
        if ( ip6h ) rpkt->ip6h->len = ip6h->ip6_payload_len;
    }

    rpkt->flags |= FLAG_STREAM_EST;
    if (DCE2_SsnFromClient(wire_pkt))
        rpkt->flags |= FLAG_FROM_CLIENT;
    else
        rpkt->flags |= FLAG_FROM_SERVER;
    rpkt->stream_session = wire_pkt->stream_session;

    return rpkt;
}
예제 #14
0
/*********************************************************************
 * Function: DCE2_Process()
 *
 * Purpose: Main entry point for DCE/RPC processing.
 *
 * Arguments:
 *  SFSnortPacket * - pointer to packet structure
 *
 * Returns:
 *  DCE2_Ret - status
 *
 *********************************************************************/
DCE2_Ret DCE2_Process(SFSnortPacket *p)
{
    tSfPolicyId policy_id = _dpd.getNapRuntimePolicy();
    DCE2_SsnData *sd = (DCE2_SsnData *)DCE2_SsnGetAppData(p);
    PROFILE_VARS;

    PREPROC_PROFILE_START(dce2_pstat_session);

    if ((sd != NULL) && DCE2_SsnNoInspect(sd))
    {
        DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Session set to "
                    "not inspect.  Returning\n"));
        PREPROC_PROFILE_END(dce2_pstat_session);
        return DCE2_RET__NOT_INSPECTED;
    }

    dce2_eval_config = (DCE2_Config *)sfPolicyUserDataGet(dce2_config, policy_id);
    if (sd != NULL)
        dce2_eval_config = (DCE2_Config *)sfPolicyUserDataGet(sd->config, sd->policy_id);

    if (dce2_eval_config == NULL)
    {
        PREPROC_PROFILE_END(dce2_pstat_session);
        return DCE2_RET__NOT_INSPECTED;
    }

    if (sd == NULL)
    {
        sd = DCE2_NewSession(p, policy_id);
        if (sd == NULL)
        {
            PREPROC_PROFILE_END(dce2_pstat_session);
            return DCE2_RET__NOT_INSPECTED;
        }
    }
    else
    {
        sd->wire_pkt = p;

        if (_dpd.isPafEnabled() && !DCE2_SsnIsPafActive(p))
        {
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "PAF was aborted on "
                        "one or both sides - aborting session inspection\n"));
            DCE2_SetNoInspect(sd);
            PREPROC_PROFILE_END(dce2_pstat_session);
            return DCE2_RET__NOT_INSPECTED;
        }

        if (IsTCP(p) && !DCE2_SsnIsRebuilt(p))
        {
            DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Got non-rebuilt packet "
                        "on session (%p)\n", (void *)sd));

            if (DCE2_SsnIsStreamInsert(p))
            {
                if (!_dpd.isPafEnabled())
                {
                    DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Flushing opposite direction.\n"));
                    DCE2_SsnFlush(p);
                }

                DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Stream inserted - not inspecting.\n"));
            }
            else
            {
                DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Got non-stream inserted packet "
                            "- not inspecting\n"));
            }

            PREPROC_PROFILE_END(dce2_pstat_session);
            return DCE2_RET__NOT_INSPECTED;
        }
        else if (DCE2_SsnAutodetected(sd) && !(p->flags & sd->autodetect_dir))
        {
            /* Try to autodetect in opposite direction */
            if ((sd->trans != DCE2_TRANS_TYPE__HTTP_PROXY) &&
                    (sd->trans != DCE2_TRANS_TYPE__HTTP_SERVER) &&
                    (DCE2_GetAutodetectTransport(p, sd->sconfig) != sd->trans))
            {
                DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Bad autodetect.\n"));

                DCE2_SetNoInspect(sd);
                dce2_stats.bad_autodetects++;

                PREPROC_PROFILE_END(dce2_pstat_session);
                return DCE2_RET__NOT_INSPECTED;
            }

            DCE2_SsnClearAutodetected(sd);
        }
    }

    DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MAIN, "Session pointer: %p\n", (void *)sd));

    if (IsTCP(p) && (DCE2_SetSsnState(sd, p) != DCE2_RET__SUCCESS))
    {
        PREPROC_PROFILE_END(dce2_pstat_session);
        return DCE2_RET__NOT_INSPECTED;
    }

    if (DCE2_PushPkt((void *)p) != DCE2_RET__SUCCESS)
    {
        DCE2_Log(DCE2_LOG_TYPE__ERROR,
                 "%s(%d) Failed to push packet onto packet stack.",
                 __FILE__, __LINE__);
        PREPROC_PROFILE_END(dce2_pstat_session);
        return DCE2_RET__NOT_INSPECTED;
    }

    p->flags |= FLAG_ALLOW_MULTIPLE_DETECT;
    dce2_detected = 0;

    PREPROC_PROFILE_END(dce2_pstat_session);

    switch (sd->trans)
    {
        case DCE2_TRANS_TYPE__SMB:
            DCE2_SmbProcess((DCE2_SmbSsnData *)sd);
            break;
        case DCE2_TRANS_TYPE__TCP:
            DCE2_TcpProcess((DCE2_TcpSsnData *)sd);
            break;
        case DCE2_TRANS_TYPE__UDP:
            DCE2_UdpProcess((DCE2_UdpSsnData *)sd);
            break;
        case DCE2_TRANS_TYPE__HTTP_PROXY:
            DCE2_HttpProcessProxy((DCE2_HttpSsnData *)sd);
            break;
        case DCE2_TRANS_TYPE__HTTP_SERVER:
            DCE2_HttpProcessServer((DCE2_HttpSsnData *)sd);
            break;
        default:
            DCE2_Log(DCE2_LOG_TYPE__ERROR,
                     "%s(%d) Invalid transport type: %d",
                     __FILE__, __LINE__, sd->trans);
            return DCE2_RET__NOT_INSPECTED;
    }

    if (sd->flags & DCE2_SSN_FLAG__NO_INSPECT)
    {
        DCE2_SetNoInspect(sd);
        DCE2_PopPkt();
        PREPROC_PROFILE_END(dce2_pstat_session);
        return DCE2_RET__NOT_INSPECTED;
    }

    if (!dce2_detected)
        DCE2_Detect(sd);

    DCE2_ResetRopts(&sd->ropts);
    DCE2_PopPkt();

    if (dce2_mem_state == DCE2_MEM_STATE__MEMCAP)
    {
        DCE2_SetNoInspect(sd);
        dce2_mem_state = DCE2_MEM_STATE__OKAY;
        return DCE2_RET__NOT_INSPECTED;
    }

    if (DCE2_SsnAutodetected(sd))
        return DCE2_RET__NOT_INSPECTED;

    return DCE2_RET__INSPECTED;
}