Skip to content

Commit

Permalink
rust/ldap: add pdu frames
Browse files Browse the repository at this point in the history
This adds a pdu frame for both request and response, and removes invalid
returns in SCLdapParseRequest and SCLdapParseResponse.
  • Loading branch information
glongo committed Jul 19, 2024
1 parent 571a561 commit 881f52c
Showing 1 changed file with 73 additions and 14 deletions.
87 changes: 73 additions & 14 deletions rust/src/ldap/ldap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

use crate::applayer::{self, *};
use crate::conf::conf_get;
use crate::core::*;
use crate::core::{Flow, *};
use crate::frames::*;
use nom7 as nom;
use std;
use std::collections::VecDeque;
Expand All @@ -32,6 +33,11 @@ static mut LDAP_MAX_TX: usize = 256;

static mut ALPROTO_LDAP: AppProto = ALPROTO_UNKNOWN;

#[derive(AppLayerFrameType)]
pub enum LdapFrameType {
Pdu,
}

#[derive(AppLayerEvent)]
enum LdapEvent {
TooManyTransactions,
Expand Down Expand Up @@ -79,6 +85,8 @@ pub struct LdapState {
tx_id: u64,
transactions: VecDeque<LdapTransaction>,
tx_index_completed: usize,
request_frame: Option<Frame>,
response_frame: Option<Frame>,
}

impl State<LdapTransaction> for LdapState {
Expand All @@ -98,6 +106,8 @@ impl LdapState {
tx_id: 0,
transactions: VecDeque::new(),
tx_index_completed: 0,
request_frame: None,
response_frame: None,
}
}

Expand Down Expand Up @@ -158,24 +168,44 @@ impl LdapState {
})
}

fn parse_request(&mut self, input: &[u8]) -> AppLayerResult {
fn parse_request(&mut self, flow: *const Flow, stream_slice: StreamSlice) -> AppLayerResult {
let input = stream_slice.as_slice();
if input.is_empty() {
return AppLayerResult::ok();
}

let mut start = input;
while !start.is_empty() {
if self.request_frame.is_none() {
self.request_frame = Frame::new(
flow,
&stream_slice,
start,
-1_i64,
LdapFrameType::Pdu as u8,
None,
);
SCLogDebug!("ts: pdu {:?}", self.request_frame);
}
match ldap_parse_msg(start) {
Ok((rem, msg)) => {
start = rem;
let mut tx = self.new_tx();
let tx_id = tx.id();
let request = LdapMessage::from(msg);
tx.complete = match request.protocol_op {
ProtocolOp::UnbindRequest => true,
_ => false,
};
tx.request = Some(request);
self.transactions.push_back(tx);

let consumed = start.len() - rem.len();
start = rem;
if let Some(frame) = &self.request_frame {
frame.set_len(flow, consumed as i64);
frame.set_tx(flow, tx_id);
self.request_frame = None;
}
}
Err(nom::Err::Incomplete(_)) => {
let consumed = input.len() - start.len();
Expand All @@ -191,16 +221,27 @@ impl LdapState {
return AppLayerResult::ok();
}

fn parse_response(&mut self, input: &[u8]) -> AppLayerResult {
fn parse_response(&mut self, flow: *const Flow, stream_slice: StreamSlice) -> AppLayerResult {
let input = stream_slice.as_slice();
if input.is_empty() {
return AppLayerResult::ok();
}

let mut start = input;
while !start.is_empty() {
if self.response_frame.is_none() {
self.response_frame = Frame::new(
flow,
&stream_slice,
start,
-1_i64,
LdapFrameType::Pdu as u8,
None,
);
SCLogDebug!("tc: pdu {:?}", self.response_frame);
}
match ldap_parse_msg(start) {
Ok((rem, msg)) => {
start = rem;

let response = LdapMessage::from(msg);
if let Some(tx) = self.find_request(response.message_id) {
tx.complete = match response.protocol_op {
Expand All @@ -214,21 +255,43 @@ impl LdapState {
| ProtocolOp::ExtendedResponse(_) => true,
_ => false,
};
let tx_id = tx.id();
tx.responses.push_back(response);
let consumed = start.len() - rem.len();
if let Some(frame) = &self.response_frame {
frame.set_len(flow, consumed as i64);
frame.set_tx(flow, tx_id);
self.response_frame = None;
}
} else if let ProtocolOp::ExtendedResponse(_) = response.protocol_op {
// this is an unsolicited notification, which means
// there is no request
let mut tx = self.new_tx();
let tx_id = tx.id();
tx.complete = true;
tx.responses.push_back(response);
self.transactions.push_back(tx);
let consumed = start.len() - rem.len();
if let Some(frame) = &self.response_frame {
frame.set_len(flow, consumed as i64);
frame.set_tx(flow, tx_id);
self.response_frame = None;
}
} else {
let mut tx = self.new_tx();
tx.complete = true;
let tx_id = tx.id();
tx.responses.push_back(response);
self.transactions.push_back(tx);
self.set_event(LdapEvent::RequestNotFound);
let consumed = start.len() - rem.len();
if let Some(frame) = &self.response_frame {
frame.set_len(flow, consumed as i64);
frame.set_tx(flow, tx_id);
self.response_frame = None;
}
};
start = rem;
}
Err(nom::Err::Incomplete(_)) => {
let consumed = input.len() - start.len();
Expand Down Expand Up @@ -305,7 +368,7 @@ unsafe extern "C" fn SCLdapStateTxFree(state: *mut c_void, tx_id: u64) {

#[no_mangle]
unsafe extern "C" fn SCLdapParseRequest(
_flow: *const Flow, state: *mut c_void, pstate: *mut c_void, stream_slice: StreamSlice,
flow: *const Flow, state: *mut c_void, pstate: *mut c_void, stream_slice: StreamSlice,
_data: *const c_void,
) -> AppLayerResult {
if stream_slice.is_empty() {
Expand All @@ -316,14 +379,12 @@ unsafe extern "C" fn SCLdapParseRequest(
}
}
let state = cast_pointer!(state, LdapState);
state.parse_request(stream_slice.as_slice());

AppLayerResult::ok()
state.parse_request(flow, stream_slice)
}

#[no_mangle]
unsafe extern "C" fn SCLdapParseResponse(
_flow: *const Flow, state: *mut c_void, pstate: *mut c_void, stream_slice: StreamSlice,
flow: *const Flow, state: *mut c_void, pstate: *mut c_void, stream_slice: StreamSlice,
_data: *const c_void,
) -> AppLayerResult {
if stream_slice.is_empty() {
Expand All @@ -334,9 +395,7 @@ unsafe extern "C" fn SCLdapParseResponse(
}
}
let state = cast_pointer!(state, LdapState);
state.parse_response(stream_slice.as_slice());

AppLayerResult::ok()
state.parse_response(flow, stream_slice)
}

#[no_mangle]
Expand Down

0 comments on commit 881f52c

Please sign in to comment.