use nom::number::Endianness;
use nom;
use std::cmp;
+use std::ffi::CString;
// Constant DCERPC UDP Header length
pub const DCERPC_HDR_LEN: u16 = 16;
pub const DCERPC_TYPE_RTS: u8 = 20;
pub const DCERPC_TYPE_UNKNOWN: u8 = 99;
+pub static mut ALPROTO_DCERPC: AppProto = ALPROTO_UNKNOWN;
+
pub fn dcerpc_type_string(t: u8) -> String {
match t {
DCERPC_TYPE_REQUEST => "REQUEST",
}
}
-#[no_mangle]
pub extern "C" fn rs_dcerpc_probe_tcp(_f: *const core::Flow, direction: u8, input: *const u8,
len: u32, rdir: *mut u8) -> AppProto
{
if direction & (core::STREAM_TOSERVER|core::STREAM_TOCLIENT) != dir {
unsafe { *rdir = dir };
}
- return 1;
+ return unsafe { ALPROTO_DCERPC };
+ }
+ return unsafe { core::ALPROTO_FAILED };
+}
+
+fn register_pattern_probe() -> i8 {
+ unsafe {
+ if AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP as u8, ALPROTO_DCERPC,
+ b"|05 00|\0".as_ptr() as *const std::os::raw::c_char, 2, 0,
+ core::STREAM_TOSERVER, rs_dcerpc_probe_tcp, 0, 0) < 0 {
+ SCLogDebug!("TOSERVER => AppLayerProtoDetectPMRegisterPatternCSwPP FAILED");
+ return -1;
+ }
+ if AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP as u8, ALPROTO_DCERPC,
+ b"|05 00|\0".as_ptr() as *const std::os::raw::c_char, 2, 0,
+ core::STREAM_TOCLIENT, rs_dcerpc_probe_tcp, 0, 0) < 0 {
+ SCLogDebug!("TOCLIENT => AppLayerProtoDetectPMRegisterPatternCSwPP FAILED");
+ return -1;
+ }
+ }
+
+ 0
+}
+
+
+// Parser name as a C style string.
+pub const PARSER_NAME: &'static [u8] = b"dcerpc\0";
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_register_parser() {
+ let default_port = CString::new("[0:65355]").unwrap();
+ let parser = RustParser {
+ name: PARSER_NAME.as_ptr() as *const std::os::raw::c_char,
+ default_port: default_port.as_ptr(),
+ ipproto: IPPROTO_TCP,
+ probe_ts: None,
+ probe_tc: None,
+ min_depth: 0,
+ max_depth: 16,
+ state_new: rs_dcerpc_state_new,
+ state_free: rs_dcerpc_state_free,
+ tx_free: rs_dcerpc_state_transaction_free,
+ parse_ts: rs_dcerpc_parse_request,
+ parse_tc: rs_dcerpc_parse_response,
+ get_tx_count: rs_dcerpc_get_tx_cnt,
+ get_tx: rs_dcerpc_get_tx,
+ tx_comp_st_ts: 1,
+ tx_comp_st_tc: 1,
+ tx_get_progress: rs_dcerpc_get_alstate_progress,
+ get_de_state: rs_dcerpc_get_tx_detect_state,
+ set_de_state: rs_dcerpc_set_tx_detect_state,
+ get_events: None,
+ get_eventinfo: None,
+ get_eventinfo_byid : None,
+ localstorage_new: None,
+ localstorage_free: None,
+ get_files: None,
+ get_tx_iterator: None,
+ get_tx_data: rs_dcerpc_get_tx_data,
+ apply_tx_config: None,
+ flags: APP_LAYER_PARSER_OPT_ACCEPT_GAPS,
+ truncate: None,
+ };
+
+ let ip_proto_str = CString::new("tcp").unwrap();
+
+ if AppLayerProtoDetectConfProtoDetectionEnabled(
+ ip_proto_str.as_ptr(),
+ parser.name,
+ ) != 0
+ {
+ let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
+ ALPROTO_DCERPC = alproto;
+ if register_pattern_probe() < 0 {
+ return;
+ }
+ if AppLayerParserConfParserEnabled(
+ ip_proto_str.as_ptr(),
+ parser.name,
+ ) != 0
+ {
+ let _ = AppLayerRegisterParser(&parser, alproto);
+ }
+ SCLogDebug!("Rust DCERPC parser registered.");
+ } else {
+ SCLogDebug!("Protocol detector and parser disabled for DCERPC.");
}
- return 0;
}
#[cfg(test)]
+++ /dev/null
-/* Copyright (C) 2007-2010 Open Information Security Foundation
- *
- * You can copy, redistribute or modify this Program under the terms of
- * the GNU General Public License version 2 as published by the Free
- * Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include "suricata-common.h"
-#include "suricata.h"
-
-#include "debug.h"
-#include "decode.h"
-#include "threads.h"
-
-#include "util-print.h"
-#include "util-pool.h"
-#include "util-debug.h"
-
-#include "flow-util.h"
-
-#include "detect-engine-state.h"
-
-#include "stream-tcp-private.h"
-#include "stream-tcp-reassemble.h"
-#include "stream-tcp.h"
-#include "stream.h"
-
-#include "app-layer-protos.h"
-#include "app-layer-parser.h"
-#include "app-layer.h"
-
-#include "util-spm.h"
-#include "util-unittest.h"
-
-#include "app-layer-dcerpc-common.h"
-#include "app-layer-dcerpc.h"
-
-static AppLayerResult DCERPCParseRequest(Flow *f, void *dcerpc_state,
- AppLayerParserState *pstate,
- const uint8_t *input, uint32_t input_len,
- void *local_data, const uint8_t flags)
-{
- if (input == NULL && input_len > 0) {
- AppLayerResult res = rs_parse_dcerpc_request_gap(dcerpc_state, input_len);
- SCLogDebug("DCERPC request GAP of %u bytes, retval %d", input_len, res.status);
- SCReturnStruct(res);
- } else {
- AppLayerResult res = rs_dcerpc_parse_request(
- f, dcerpc_state, pstate, input, input_len, local_data, flags);
- SCLogDebug("DCERPC request%s of %u bytes, retval %d",
- (input == NULL && input_len > 0) ? " is GAP" : "", input_len, res.status);
- SCReturnStruct(res);
- }
-}
-
-static AppLayerResult DCERPCParseResponse(Flow *f, void *dcerpc_state,
- AppLayerParserState *pstate,
- const uint8_t *input, uint32_t input_len,
- void *local_data, const uint8_t flags)
-{
- if (input == NULL && input_len > 0) {
- AppLayerResult res = rs_parse_dcerpc_response_gap(dcerpc_state, input_len);
- SCLogDebug("DCERPC response GAP of %u bytes, retval %d", input_len, res.status);
- SCReturnStruct(res);
- } else {
- AppLayerResult res = rs_dcerpc_parse_response(
- f, dcerpc_state, pstate, input, input_len, local_data, flags);
- SCLogDebug("DCERPC response%s of %u bytes, retval %d",
- (input == NULL && input_len > 0) ? " is GAP" : "", input_len, res.status);
- SCReturnStruct(res);
- }
-}
-
-static void *RustDCERPCStateNew(void *state_orig, AppProto proto_orig)
-{
- return rs_dcerpc_state_new(state_orig, proto_orig);
-}
-
-static void DCERPCStateFree(void *s)
-{
- return rs_dcerpc_state_free(s);
-}
-
-static int DCERPCSetTxDetectState(void *vtx, DetectEngineState *de_state)
-{
- return rs_dcerpc_set_tx_detect_state(vtx, de_state);
-}
-
-static DetectEngineState *DCERPCGetTxDetectState(void *vtx)
-{
- return rs_dcerpc_get_tx_detect_state(vtx);
-}
-
-static void DCERPCStateTransactionFree(void *state, uint64_t tx_id)
-{
- return rs_dcerpc_state_transaction_free(state, tx_id);
-}
-
-static void *DCERPCGetTx(void *state, uint64_t tx_id)
-{
- return rs_dcerpc_get_tx(state, tx_id);
-}
-
-static uint64_t DCERPCGetTxCnt(void *state)
-{
- return rs_dcerpc_get_tx_cnt(state);
-}
-
-static int DCERPCGetAlstateProgress(void *tx, uint8_t direction)
-{
- return rs_dcerpc_get_alstate_progress(tx, direction);
-}
-
-static uint16_t DCERPCTCPProbe(
- Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, uint8_t *rdir)
-{
- SCLogDebug("DCERPCTCPProbe");
-
- const int r = rs_dcerpc_probe_tcp(f, direction, input, len, rdir);
- switch (r) {
- case 1:
- return ALPROTO_DCERPC;
- case 0:
- return ALPROTO_UNKNOWN;
- case -1:
- default:
- return ALPROTO_FAILED;
- }
-}
-
-static int DCERPCRegisterPatternsForProtocolDetection(void)
-{
- if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0,
- STREAM_TOSERVER, DCERPCTCPProbe, 0, 0) < 0) {
- return -1;
- }
- if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0,
- STREAM_TOCLIENT, DCERPCTCPProbe, 0, 0) < 0) {
- return -1;
- }
-
- return 0;
-}
-
-void RegisterDCERPCParsers(void)
-{
- const char *proto_name = "dcerpc";
-
- if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
- AppLayerProtoDetectRegisterProtocol(ALPROTO_DCERPC, proto_name);
- if (DCERPCRegisterPatternsForProtocolDetection() < 0)
- return;
- } else {
- SCLogInfo("Protocol detection and parser disabled for %s protocol.",
- proto_name);
- return;
- }
-
- if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
- AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DCERPC, STREAM_TOSERVER,
- DCERPCParseRequest);
- AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DCERPC, STREAM_TOCLIENT,
- DCERPCParseResponse);
- AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_DCERPC, RustDCERPCStateNew,
- DCERPCStateFree);
- AppLayerParserRegisterParserAcceptableDataDirection(IPPROTO_TCP, ALPROTO_DCERPC, STREAM_TOSERVER);
-
-
- AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_DCERPC, DCERPCStateTransactionFree);
-
- AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_DCERPC,
- DCERPCGetTxDetectState, DCERPCSetTxDetectState);
-
- AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DCERPC, DCERPCGetTx);
- AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_DCERPC, rs_dcerpc_get_tx_data);
-
- AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_DCERPC, DCERPCGetTxCnt);
-
- AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_DCERPC, DCERPCGetAlstateProgress);
-
- AppLayerParserRegisterStateProgressCompletionStatus(ALPROTO_DCERPC, 1, 1);
-
- /* This parser accepts gaps. */
- AppLayerParserRegisterOptionFlags(IPPROTO_TCP, ALPROTO_DCERPC, APP_LAYER_PARSER_OPT_ACCEPT_GAPS);
-
- AppLayerParserRegisterTruncateFunc(IPPROTO_TCP, ALPROTO_DCERPC, rs_dcerpc_state_trunc);
- } else {
- SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
- "still on.", proto_name);
- }
- return;
-}