THREAD_LOCAL ProfileStats dce2_udp_pstat_cl_frag;
THREAD_LOCAL ProfileStats dce2_udp_pstat_cl_reass;
+void DCE2_ClCleanTracker(DCE2_ClTracker* clt)
+{
+ if (clt == nullptr)
+ return;
+
+ /* Destroy activity trackers list - this will have the
+ * effect of freeing everything inside of it */
+ DCE2_ListDestroy(clt->act_trackers);
+ clt->act_trackers = nullptr;
+}
+
+// Tries to determine if a packet is likely to be DCE/RPC over UDP
+static DCE2_TransType DCE2_UdpAutodetect(const Packet* p)
+{
+ if (p->dsize >= sizeof(DceRpcClHdr))
+ {
+ const DceRpcClHdr* cl_hdr = (DceRpcClHdr*)p->data;
+
+ if ((DceRpcClRpcVers(cl_hdr) == DCERPC_PROTO_MAJOR_VERS__4) &&
+ ((DceRpcClPduType(cl_hdr) == DCERPC_PDU_TYPE__REQUEST) ||
+ (DceRpcClPduType(cl_hdr) == DCERPC_PDU_TYPE__RESPONSE) ||
+ (DceRpcClPduType(cl_hdr) == DCERPC_PDU_TYPE__FAULT) ||
+ (DceRpcClPduType(cl_hdr) == DCERPC_PDU_TYPE__REJECT) ||
+ (DceRpcClPduType(cl_hdr) == DCERPC_PDU_TYPE__FACK)) &&
+ ((DceRpcClLen(cl_hdr) != 0) &&
+ (DceRpcClLen(cl_hdr) + sizeof(DceRpcClHdr)) <= p->dsize))
+ {
+ return DCE2_TRANS_TYPE__UDP;
+ }
+ }
+
+ return DCE2_TRANS_TYPE__NONE;
+}
+
//-------------------------------------------------------------------------
// class stuff
//-------------------------------------------------------------------------
Dce2UdpFlowData::~Dce2UdpFlowData()
{
- // FIXIT-M add cl_tracker cleanup
+ DCE2_ClCleanTracker(&dce2_udp_session.cl_tracker);
}
unsigned Dce2UdpFlowData::flow_id = 0;
+DCE2_UdpSsnData* get_dce2_udp_session_data(Flow* flow)
+{
+ Dce2UdpFlowData* fd = (Dce2UdpFlowData*)flow->get_flow_data(Dce2UdpFlowData::flow_id);
+ return fd ? &fd->dce2_udp_session : nullptr;
+}
+
+static DCE2_UdpSsnData* set_new_dce2_udp_session(Packet* p)
+{
+ Dce2UdpFlowData* fd = new Dce2UdpFlowData;
+
+ memset(&fd->dce2_udp_session,0,sizeof(DCE2_UdpSsnData));
+ p->flow->set_flow_data(fd);
+ return(&fd->dce2_udp_session);
+}
+
+static DCE2_UdpSsnData* dce2_create_new_udp_session(Packet* p, dce2UdpProtoConf* config)
+{
+ DCE2_UdpSsnData* dce2_udp_sess = nullptr;
+ Profile profile(dce2_udp_pstat_new_session);
+
+ // FIXIT-M re-evaluate after infrastructure/binder support if autodetect here
+ // is necessary
+ if (DCE2_UdpAutodetect(p))
+ {
+ DebugMessage(DEBUG_DCE_UDP, "DCE over UDP packet detected\n");
+ DebugMessage(DEBUG_DCE_UDP, "Creating new session\n");
+
+ dce2_udp_sess = set_new_dce2_udp_session(p);
+
+ DCE2_ResetRopts(&dce2_udp_sess->sd.ropts);
+
+ dce2_udp_stats.udp_sessions++;
+ DebugFormat(DEBUG_DCE_UDP,"Created (%p)\n", (void*)dce2_udp_sess);
+
+ dce2_udp_sess->sd.trans = DCE2_TRANS_TYPE__UDP;
+ dce2_udp_sess->sd.wire_pkt = p;
+ dce2_udp_sess->sd.config = (void*)config;
+
+ DCE2_SsnSetAutodetected(&dce2_udp_sess->sd, p);
+ }
+
+ return dce2_udp_sess;
+}
+
+static DCE2_UdpSsnData* dce2_handle_udp_session(Packet* p, dce2UdpProtoConf* config)
+{
+ Profile profile(dce2_udp_pstat_session);
+
+ DCE2_UdpSsnData* dce2_udp_sess = get_dce2_udp_session_data(p->flow);
+
+ if (dce2_udp_sess == nullptr)
+ {
+ dce2_udp_sess = dce2_create_new_udp_session(p, config);
+ }
+ else
+ {
+ DCE2_SsnData* sd = (DCE2_SsnData*)dce2_udp_sess;
+ sd->wire_pkt = p;
+
+ if (DCE2_SsnAutodetected(sd) && !(p->packet_flags & sd->autodetect_dir))
+ {
+ /* Try to autodetect in opposite direction */
+ if (!DCE2_UdpAutodetect(p))
+ {
+ DebugMessage(DEBUG_DCE_UDP, "Bad autodetect.\n");
+ DCE2_SsnNoInspect(sd);
+ dce2_udp_stats.sessions_aborted++;
+ dce2_udp_stats.bad_autodetects++;
+ return nullptr;
+ }
+
+ DCE2_SsnClearAutodetected(sd);
+ }
+ }
+
+ DebugFormat(DEBUG_DCE_UDP, "Session pointer: %p\n", (void*)dce2_udp_sess);
+
+ return dce2_udp_sess;
+}
+
class Dce2Udp : public Inspector
{
public:
print_dce2_udp_conf(config);
}
-void Dce2Udp::eval(Packet*)
+void Dce2Udp::eval(Packet* p)
{
+ DCE2_UdpSsnData* dce2_udp_sess;
+ Profile profile(dce2_udp_pstat_main);
+ if (DCE2_SsnFromServer(p))
+ {
+ DebugMessage(DEBUG_DCE_UDP, "Packet from Server.\n");
+ }
+ else
+ {
+ DebugMessage(DEBUG_DCE_UDP, "Packet from Client.\n");
+ }
+
+ assert(p->flow);
+
+ dce2_udp_sess = dce2_handle_udp_session(p, &config);
+
+ if (dce2_udp_sess)
+ {
+ dce2_udp_stats.udp_pkts++;
+
+ if (!DCE2_SsnAutodetected(&dce2_udp_sess->sd))
+ DisableInspection();
+ }
}
//-------------------------------------------------------------------------