use std::ptr;
use crate::core::*;
use crate::smb::smb::*;
use crate::dcerpc::detect::{DCEIfaceData, DCEOpnumData, DETECT_DCE_OPNUM_RANGE_UNINITIALIZED};
#[no_mangle]
pub unsafe extern "C" fn rs_smb_tx_get_share(tx: &mut SMBTransaction,
buffer: *mut *const u8,
buffer_len: *mut u32)
-> u8
{
match tx.type_data {
Some(SMBTransactionTypeData::TREECONNECT(ref x)) => {
SCLogDebug!("is_pipe {}", x.is_pipe);
if !x.is_pipe {
*buffer = x.share_name.as_ptr();
*buffer_len = x.share_name.len() as u32;
return 1;
}
}
_ => {
}
}
*buffer = ptr::null();
*buffer_len = 0;
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn rs_smb_tx_get_named_pipe(tx: &mut SMBTransaction,
buffer: *mut *const u8,
buffer_len: *mut u32)
-> u8
{
match tx.type_data {
Some(SMBTransactionTypeData::TREECONNECT(ref x)) => {
SCLogDebug!("is_pipe {}", x.is_pipe);
if x.is_pipe {
*buffer = x.share_name.as_ptr();
*buffer_len = x.share_name.len() as u32;
return 1;
}
}
_ => {
}
}
*buffer = ptr::null();
*buffer_len = 0;
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn rs_smb_tx_get_stub_data(tx: &mut SMBTransaction,
direction: u8,
buffer: *mut *const u8,
buffer_len: *mut u32)
-> u8
{
match tx.type_data {
Some(SMBTransactionTypeData::DCERPC(ref x)) => {
let vref = if direction == STREAM_TOSERVER {
&x.stub_data_ts
} else {
&x.stub_data_tc
};
if vref.len() > 0 {
*buffer = vref.as_ptr();
*buffer_len = vref.len() as u32;
return 1;
}
}
_ => {
}
}
*buffer = ptr::null();
*buffer_len = 0;
return 0;
}
#[no_mangle]
pub extern "C" fn rs_smb_tx_match_dce_opnum(tx: &mut SMBTransaction,
dce_data: &mut DCEOpnumData)
-> u8
{
SCLogDebug!("rs_smb_tx_get_dce_opnum: start");
match tx.type_data {
Some(SMBTransactionTypeData::DCERPC(ref x)) => {
if x.req_cmd == 1 { for range in dce_data.data.iter() {
if range.range2 == DETECT_DCE_OPNUM_RANGE_UNINITIALIZED {
if range.range1 == x.opnum as u32 {
return 1;
} else if range.range1 <= x.opnum as u32 && range.range2 >= x.opnum as u32 {
return 1;
}
}
}
}
}
_ => {
}
}
return 0;
}
#[inline]
fn match_version(op: u8, them: u16, us: u16) -> bool {
let result = match op {
0 => { true
},
1 => { them < us
},
2 => { them > us
},
3 => { them == us
},
4 => { them != us
},
_ => {
panic!("called with invalid op {}", op);
},
};
result
}
#[no_mangle]
pub extern "C" fn rs_smb_tx_get_dce_iface(state: &mut SMBState,
tx: &mut SMBTransaction,
dce_data: &mut DCEIfaceData)
-> u8
{
let if_uuid = dce_data.if_uuid.as_slice();
let if_op = dce_data.op;
let if_version = dce_data.version;
let is_dcerpc_request = match tx.type_data {
Some(SMBTransactionTypeData::DCERPC(ref x)) => { x.req_cmd == 1 },
_ => { false },
};
if !is_dcerpc_request {
return 0;
}
let ifaces = match state.dcerpc_ifaces {
Some(ref x) => x,
_ => {
return 0;
},
};
SCLogDebug!("looking for UUID {:?}", if_uuid);
for i in ifaces {
SCLogDebug!("stored UUID {:?} acked {} ack_result {}", i, i.acked, i.ack_result);
if i.acked && i.ack_result == 0 && i.uuid == if_uuid {
if match_version(if_op as u8, if_version as u16, i.ver) {
return 1;
}
}
}
return 0;
}