@ -23,13 +23,33 @@ use crate::detect::{
DetectHelperBufferRegister , DetectHelperKeywordRegister , DetectSignatureSetAppProto ,
SCSigTableElmt , SigMatchAppendSMToList ,
} ;
use crate ::ldap ::types ::ProtocolOpCode ;
use crate ::ldap ::types ::{ LdapMessage , ProtocolOpCode } ;
use std ::ffi ::CStr ;
use std ::os ::raw ::{ c_int , c_void } ;
use std ::str ::FromStr ;
#[ derive(Debug, PartialEq) ]
enum LdapIndex {
Any ,
All ,
Index ( i32 ) ,
}
#[ derive(Debug, PartialEq) ]
struct DetectLdapRespData {
/// Ldap response code
pub du8 : DetectUintData < u8 > ,
/// Index can be Any to match with any responses index,
/// All to match if all indices, or an i32 integer
/// Negative values represent back to front indexing.
pub index : LdapIndex ,
}
static mut G_LDAP_REQUEST_OPERATION_KW_ID : c_int = 0 ;
static mut G_LDAP_REQUEST_OPERATION_BUFFER_ID : c_int = 0 ;
static mut G_LDAP_RESPONSES_OPERATION_KW_ID : c_int = 0 ;
static mut G_LDAP_RESPONSES_OPERATION_BUFFER_ID : c_int = 0 ;
unsafe extern "C" fn ldap_parse_protocol_req_op (
ustr : * const std ::os ::raw ::c_char ,
@ -88,6 +108,117 @@ unsafe extern "C" fn ldap_detect_request_free(_de: *mut c_void, ctx: *mut c_void
rs_detect_u8_free ( ctx ) ;
}
fn aux_ldap_parse_protocol_resp_op ( s : & str ) -> Option < DetectLdapRespData > {
let parts : Vec < & str > = s . split ( ',' ) . collect ( ) ;
if parts . len ( ) > 2 {
return None ;
}
let index = if parts . len ( ) = = 2 {
match parts [ 1 ] {
"all" = > LdapIndex ::All ,
"any" = > LdapIndex ::Any ,
_ = > {
let i32_index = i32 ::from_str ( parts [ 1 ] ) . ok ( ) ? ;
LdapIndex ::Index ( i32_index )
}
}
} else {
LdapIndex ::Any
} ;
if let Some ( ctx ) = detect_parse_uint_enum ::< u8 , ProtocolOpCode > ( parts [ 0 ] ) {
let du8 = ctx ;
return Some ( DetectLdapRespData { du8 , index } ) ;
}
return None ;
}
unsafe extern "C" fn ldap_parse_protocol_resp_op (
ustr : * const std ::os ::raw ::c_char ,
) -> * mut DetectUintData < u8 > {
let ft_name : & CStr = CStr ::from_ptr ( ustr ) ; //unsafe
if let Ok ( s ) = ft_name . to_str ( ) {
if let Some ( ctx ) = aux_ldap_parse_protocol_resp_op ( s ) {
let boxed = Box ::new ( ctx ) ;
return Box ::into_raw ( boxed ) as * mut _ ;
}
}
return std ::ptr ::null_mut ( ) ;
}
unsafe extern "C" fn ldap_detect_responses_operation_setup (
de : * mut c_void , s : * mut c_void , raw : * const libc ::c_char ,
) -> c_int {
if DetectSignatureSetAppProto ( s , ALPROTO_LDAP ) ! = 0 {
return - 1 ;
}
let ctx = ldap_parse_protocol_resp_op ( raw ) as * mut c_void ;
if ctx . is_null ( ) {
return - 1 ;
}
if SigMatchAppendSMToList (
de ,
s ,
G_LDAP_RESPONSES_OPERATION_KW_ID ,
ctx ,
G_LDAP_RESPONSES_OPERATION_BUFFER_ID ,
)
. is_null ( )
{
ldap_detect_responses_free ( std ::ptr ::null_mut ( ) , ctx ) ;
return - 1 ;
}
return 0 ;
}
unsafe extern "C" fn ldap_detect_responses_operation_match (
_de : * mut c_void , _f : * mut c_void , _flags : u8 , _state : * mut c_void , tx : * mut c_void ,
_sig : * const c_void , ctx : * const c_void ,
) -> c_int {
let tx = cast_pointer ! ( tx , LdapTransaction ) ;
let ctx = cast_pointer ! ( ctx , DetectLdapRespData ) ;
match ctx . index {
LdapIndex ::Any = > {
for response in & tx . responses {
let option : u8 = response . protocol_op . to_u8 ( ) ;
if rs_detect_u8_match ( option , & ctx . du8 ) = = 1 {
return 1 ;
}
}
return 0 ;
}
LdapIndex ::All = > {
for response in & tx . responses {
let option : u8 = response . protocol_op . to_u8 ( ) ;
if rs_detect_u8_match ( option , & ctx . du8 ) = = 0 {
return 0 ;
}
}
return 1 ;
}
LdapIndex ::Index ( idx ) = > {
let index = if idx < 0 {
// negative values for backward indexing.
( ( tx . responses . len ( ) as i32 ) + idx ) as usize
} else {
idx as usize
} ;
if tx . responses . len ( ) < = index {
return 0 ;
}
let response : & LdapMessage = & tx . responses [ index ] ;
let option : u8 = response . protocol_op . to_u8 ( ) ;
return rs_detect_u8_match ( option , & ctx . du8 ) ;
}
}
}
unsafe extern "C" fn ldap_detect_responses_free ( _de : * mut c_void , ctx : * mut c_void ) {
// Just unbox...
let ctx = cast_pointer ! ( ctx , DetectLdapRespData ) ;
std ::mem ::drop ( Box ::from_raw ( ctx ) ) ;
}
#[ no_mangle ]
pub unsafe extern "C" fn ScDetectLdapRegister ( ) {
let kw = SCSigTableElmt {
@ -106,4 +237,21 @@ pub unsafe extern "C" fn ScDetectLdapRegister() {
false , //to client
true , //to server
) ;
let kw = SCSigTableElmt {
name : b "ldap.responses.operation\0" . as_ptr ( ) as * const libc ::c_char ,
desc : b "match LDAP responses operation\0" . as_ptr ( ) as * const libc ::c_char ,
url : b "/rules/ldap-keywords.html#ldap.responses.operation\0" . as_ptr ( )
as * const libc ::c_char ,
AppLayerTxMatch : Some ( ldap_detect_responses_operation_match ) ,
Setup : ldap_detect_responses_operation_setup ,
Free : Some ( ldap_detect_responses_free ) ,
flags : 0 ,
} ;
G_LDAP_RESPONSES_OPERATION_KW_ID = DetectHelperKeywordRegister ( & kw ) ;
G_LDAP_RESPONSES_OPERATION_BUFFER_ID = DetectHelperBufferRegister (
b" ldap.responses.operation \0 " . as_ptr ( ) as * const libc ::c_char ,
ALPROTO_LDAP ,
true , //to client
false , //to server
) ;
}