示例#1
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++;
}
示例#2
0
文件: dce2_cl.c 项目: jasonish/snort
/********************************************************************
 * Function: DCE2_ClRequest()
 *
 * Handles a client request.
 *
 * 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.
 *  const uint8_t *
 *      Pointer to current position in the packet payload.
 *  uint16_t
 *      Length of packet payload left from current pointer
 *      position.
 *
 * Returns: None
 *
 ********************************************************************/
static void DCE2_ClRequest(DCE2_SsnData *sd, DCE2_ClActTracker *at, DceRpcClHdr *cl_hdr,
                           const uint8_t *data_ptr, uint16_t data_len)
{
    uint32_t seq_num = DceRpcClSeqNum(cl_hdr);

    DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__CL, "Processing Request ...\n"));

    if (seq_num > at->seq_num)
    {
        /* This is the normal case where the sequence number is incremented
         * for each request.  Set the new sequence number and mark it valid. */
        at->seq_num = seq_num;
        at->seq_num_invalid = 0;

        /* If there are any fragments, the new sequence number invalidates
         * all of the frags that might be currently stored. */
        DCE2_ClResetFragTracker(&at->frag_tracker);
    }
    else if ((seq_num < at->seq_num) || at->seq_num_invalid)
    {
#if 0
        /* If we get a seqence number less than what we're at, the
         * server won't look at it.  If we get the same sequence number,
         * but we've already processed a previous request, it's bad.
         * Fragments will have the same sequence number, but we won't
         * mark the seq number invalid until we've gotten all of them. */
        /* Comment for now since we're not able to detect retransmits */
        DCE2_Alert(sd, DCE2_EVENT__CL_BAD_SEQ_NUM, dce2_pdu_types[DceRpcClPduType(cl_hdr)]);
#endif
        return;
    }

    DCE2_ResetRopts(&sd->ropts);

    if (DceRpcClFrag(cl_hdr))  /* It's a frag */
    {
        dce2_stats.cl_fragments++;
        if (DCE2_GcDceDefrag())
        {
            DCE2_ClHandleFrag(sd, at, cl_hdr, data_ptr, data_len);
            return;
        }
    }
    else   /* It's a full request */
    {
        if ((at->frag_tracker.frags != NULL) &&
            !DCE2_ListIsEmpty(at->frag_tracker.frags))
        {
            /* If we get a full request, i.e. not a frag, any frags
             * we have collected are invalidated */
            DCE2_ClResetFragTracker(&at->frag_tracker);
        }
        else if (seq_num != DCE2_CL__MAX_SEQ_NUM)
        {
            /* This sequence number is now invalid. 0xffffffff is the end of
             * the sequence number space and can be reused */
            at->seq_num_invalid = 1;
        }
        else
        {
            /* Got the last sequence number in the sequence number space */
            dce2_stats.cl_max_seqnum++;
        }
    }

    /* Cache relevant values for rule option processing */
    sd->ropts.first_frag = DceRpcClFirstFrag(cl_hdr);
    DCE2_CopyUuid(&sd->ropts.iface, DceRpcClIface(cl_hdr), DceRpcClByteOrder(cl_hdr));
    sd->ropts.iface_vers = DceRpcClIfaceVers(cl_hdr);
    sd->ropts.hdr_byte_order = DceRpcClByteOrder(cl_hdr);
    sd->ropts.data_byte_order = DceRpcClByteOrder(cl_hdr);
    sd->ropts.opnum = DceRpcClOpnum(cl_hdr);
    sd->ropts.stub_data = (uint8_t *)cl_hdr + sizeof(DceRpcClHdr);

    DCE2_Detect(sd);
}
示例#3
0
文件: dce2_cl.c 项目: jasonish/snort
/********************************************************************
 * Function: DCE2_ClHandleFrag()
 *
 * Handles connectionless fragments.  Creates a new fragment list
 * if necessary and inserts fragment into list.  Sets rule option
 * values based on the fragment.
 *
 * 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.
 *  const uint8_t *
 *      Pointer to current position in the packet payload.
 *  uint16_t
 *      Length of packet payload left from current pointer
 *      position.
 *
 * Returns: None
 *
 ********************************************************************/
static void DCE2_ClHandleFrag(DCE2_SsnData *sd, DCE2_ClActTracker *at, DceRpcClHdr *cl_hdr,
                              const uint8_t *data_ptr, uint16_t data_len)
{
    DCE2_ClFragTracker *ft = &at->frag_tracker;
    DCE2_ClFragNode *fn;
    uint16_t frag_len;
    int status;
    PROFILE_VARS;

    PREPROC_PROFILE_START(dce2_pstat_cl_frag);

    /* If the frag length is less than data length there might be authentication
     * data that we don't want to include, otherwise just set to data len */
    if (DceRpcClLen(cl_hdr) < data_len)
        frag_len = DceRpcClLen(cl_hdr);
    else
        frag_len = data_len;

    if (frag_len == 0)
    {
        PREPROC_PROFILE_END(dce2_pstat_cl_frag);
        return;
    }

    if (frag_len > dce2_stats.cl_max_frag_size)
        dce2_stats.cl_max_frag_size = frag_len;

    if (DCE2_GcMaxFrag() && (frag_len > DCE2_GcMaxFragLen()))
        frag_len = DCE2_GcMaxFragLen();

    if (ft->frags == NULL)
    {
        /* Create new list if we don't have one already */
        ft->frags = DCE2_ListNew(DCE2_LIST_TYPE__SORTED, DCE2_ClFragCompare, DCE2_ClFragDataFree,
                                 NULL, DCE2_LIST_FLAG__NO_DUPS | DCE2_LIST_FLAG__INS_TAIL,
                                 DCE2_MEM_TYPE__CL_FRAG);

        if (ft->frags == NULL)
        {
            PREPROC_PROFILE_END(dce2_pstat_cl_frag);
            return;
        }
    }
    else
    {
        /* If we already have a fragment in the list with the same fragment number,
         * that fragment will take precedence over this fragment and this fragment
         * will not be used by the server */
        fn = (DCE2_ClFragNode *)DCE2_ListFind(ft->frags, (void *)(uintptr_t)DceRpcClFragNum(cl_hdr));
        if (fn != NULL)
        {
            PREPROC_PROFILE_END(dce2_pstat_cl_frag);
            return;
        }
    }

    /* Create a new frag node to insert into the list */
    fn = (DCE2_ClFragNode *)DCE2_Alloc(sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG);
    if (fn == NULL)
    {
        PREPROC_PROFILE_END(dce2_pstat_cl_frag);

        DCE2_ClFragReassemble(sd, at, cl_hdr);
        return;
    }

    fn->frag_number = DceRpcClFragNum(cl_hdr);
    fn->frag_len = frag_len;

    /* Allocate space for the fragment data */
    fn->frag_data = (uint8_t *)DCE2_Alloc(frag_len, DCE2_MEM_TYPE__CL_FRAG);
    if (fn->frag_data == NULL)
    {
        DCE2_Free((void *)fn, sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG);

        PREPROC_PROFILE_END(dce2_pstat_cl_frag);

        DCE2_ClFragReassemble(sd, at, cl_hdr);
        return;
    }

    /* Copy the fragment data in the packet to the space just allocated */
    status = DCE2_Memcpy(fn->frag_data, data_ptr, frag_len, fn->frag_data, fn->frag_data + frag_len);
    if (status != DCE2_RET__SUCCESS)
    {
        DCE2_Free((void *)fn->frag_data, frag_len, DCE2_MEM_TYPE__CL_FRAG);
        DCE2_Free((void *)fn, sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG);

        PREPROC_PROFILE_END(dce2_pstat_cl_frag);

        DCE2_ClFragReassemble(sd, at, cl_hdr);
        return;
    }

    if (DCE2_ListIsEmpty(ft->frags))
    {
        /* If this is the first fragment we've received, set interface uuid */
        DCE2_CopyUuid(&ft->iface, DceRpcClIface(cl_hdr), DceRpcClByteOrder(cl_hdr));
        ft->iface_vers = DceRpcClIfaceVers(cl_hdr);
    }

    if (DceRpcClLastFrag(cl_hdr))
    {
        /* Set number of expected frags on last frag */
        ft->num_expected_frags = DceRpcClFragNum(cl_hdr) + 1;
    }
    else if (DceRpcClFirstFrag(cl_hdr))
    {
        /* Set opum and byte order on first frag */
        ft->opnum = DceRpcClOpnum(cl_hdr);
        ft->data_byte_order = DceRpcClByteOrder(cl_hdr);
    }

    /* Insert frag node into the list */
    status = DCE2_ListInsert(ft->frags, (void *)(uintptr_t)fn->frag_number, (void *)fn);
    if (status != DCE2_RET__SUCCESS)
    {
        DCE2_Free((void *)fn->frag_data, frag_len, DCE2_MEM_TYPE__CL_FRAG);
        DCE2_Free((void *)fn, sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG);

        PREPROC_PROFILE_END(dce2_pstat_cl_frag);

        DCE2_ClFragReassemble(sd, at, cl_hdr);
        return;
    }

    /* Fragment number field in header is uint16_t */
    if ((ft->num_expected_frags != DCE2_SENTINEL) &&
        (uint16_t)ft->frags->num_nodes == (uint16_t)ft->num_expected_frags)
    {
        PREPROC_PROFILE_END(dce2_pstat_cl_frag);

        /* We got all of the frags - reassemble */
        DCE2_ClFragReassemble(sd, at, cl_hdr);
        at->seq_num_invalid = 1;

        return;
    }

    PREPROC_PROFILE_END(dce2_pstat_cl_frag);

    /* Cache relevant values for rule option processing */
    sd->ropts.first_frag = DceRpcClFirstFrag(cl_hdr);
    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 = (uint8_t *)cl_hdr + sizeof(DceRpcClHdr);

    DCE2_Detect(sd);
}
示例#4
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;
}