Coverage Report

Created: 2026-09-28 07:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/rust/src/ldap/ldap.rs
Line
Count
Source
1
/* Copyright (C) 2024 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
// Author: Giuseppe Longo <giuseppe@glongo.it>
19
// Author: Pierre Chifflier <chifflier@wzdftpd.net>
20
21
use crate::applayer::{self, *};
22
use crate::conf::conf_get;
23
use crate::core::*;
24
use crate::direction::Direction;
25
use crate::flow::Flow;
26
use crate::frames::*;
27
use ldap_parser::asn1_rs::ToStatic;
28
use nom7 as nom;
29
use std;
30
use std::collections::VecDeque;
31
use std::ffi::CString;
32
use std::os::raw::{c_char, c_int, c_void};
33
use suricata_sys::sys::{
34
    AppLayerParserState, AppProto, SCAppLayerParserConfParserEnabled,
35
    SCAppLayerParserRegisterLogger, SCAppLayerParserStateIssetFlag,
36
    SCAppLayerProtoDetectConfProtoDetectionEnabled, SCAppLayerRequestProtocolTLSUpgrade,
37
};
38
39
use super::types::*;
40
use ldap_parser::ldap::*;
41
42
static LDAP_MAX_TX_DEFAULT: usize = 256;
43
static mut LDAP_MAX_TX: usize = LDAP_MAX_TX_DEFAULT;
44
45
static mut LDAP_MAX_RESPONSES: usize = 1024;
46
47
pub(super) static mut ALPROTO_LDAP: AppProto = ALPROTO_UNKNOWN;
48
49
const STARTTLS_OID: &str = "1.3.6.1.4.1.1466.20037";
50
51
#[derive(AppLayerFrameType)]
52
pub enum LdapFrameType {
53
    Pdu,
54
}
55
56
#[derive(AppLayerEvent)]
57
enum LdapEvent {
58
    TooManyTransactions,
59
    InvalidData,
60
    RequestNotFound,
61
    IncompleteData,
62
    TooManyResponses,
63
}
64
65
#[derive(Debug)]
66
pub struct LdapTransaction {
67
    pub tx_id: u64,
68
    pub request: Option<LdapMessage<'static>>,
69
    pub responses: VecDeque<LdapMessage<'static>>,
70
    complete: bool,
71
72
    tx_data: AppLayerTxData,
73
}
74
75
impl Default for LdapTransaction {
76
0
    fn default() -> Self {
77
0
        Self::new()
78
0
    }
79
}
80
81
impl LdapTransaction {
82
368k
    pub fn new() -> LdapTransaction {
83
368k
        Self {
84
368k
            tx_id: 0,
85
368k
            request: None,
86
368k
            responses: VecDeque::new(),
87
368k
            complete: false,
88
368k
            tx_data: AppLayerTxData::new(),
89
368k
        }
90
368k
    }
91
5.76k
    fn set_event(&mut self, e: LdapEvent) {
92
5.76k
        self.tx_data.set_event(e as u8);
93
5.76k
    }
94
}
95
96
impl Transaction for LdapTransaction {
97
24.0M
    fn id(&self) -> u64 {
98
24.0M
        self.tx_id
99
24.0M
    }
100
}
101
102
#[derive(Default)]
103
pub struct LdapState {
104
    state_data: AppLayerStateData,
105
    tx_id: u64,
106
    transactions: VecDeque<LdapTransaction>,
107
    request_frame: Option<Frame>,
108
    response_frame: Option<Frame>,
109
    request_gap: bool,
110
    response_gap: bool,
111
    request_tls: bool,
112
    has_starttls: bool,
113
}
114
115
impl State<LdapTransaction> for LdapState {
116
8.11M
    fn get_transaction_count(&self) -> usize {
117
8.11M
        self.transactions.len()
118
8.11M
    }
119
120
15.6M
    fn get_transaction_by_index(&self, index: usize) -> Option<&LdapTransaction> {
121
15.6M
        self.transactions.get(index)
122
15.6M
    }
123
}
124
125
impl LdapState {
126
4.61k
    pub fn new() -> Self {
127
4.61k
        Self {
128
4.61k
            state_data: AppLayerStateData::new(),
129
4.61k
            tx_id: 0,
130
4.61k
            transactions: VecDeque::new(),
131
4.61k
            request_frame: None,
132
4.61k
            response_frame: None,
133
4.61k
            request_gap: false,
134
4.61k
            response_gap: false,
135
4.61k
            request_tls: false,
136
4.61k
            has_starttls: false,
137
4.61k
        }
138
4.61k
    }
139
140
    // Free a transaction by ID.
141
321k
    fn free_tx(&mut self, tx_id: u64) {
142
321k
        let len = self.transactions.len();
143
321k
        let mut found = false;
144
321k
        let mut index = 0;
145
2.27M
        for i in 0..len {
146
2.27M
            let tx = &self.transactions[i];
147
2.27M
            if tx.tx_id == tx_id + 1 {
148
321k
                found = true;
149
321k
                index = i;
150
321k
                break;
151
1.95M
            }
152
        }
153
321k
        if found {
154
321k
            self.transactions.remove(index);
155
321k
        }
156
321k
    }
157
158
0
    pub fn get_tx(&mut self, tx_id: u64) -> Option<&LdapTransaction> {
159
0
        self.transactions.iter().find(|tx| tx.tx_id == tx_id + 1)
160
0
    }
161
162
368k
    pub fn new_tx(&mut self) -> Option<LdapTransaction> {
163
368k
        if self.transactions.len() > unsafe { LDAP_MAX_TX } {
164
20.6k
            for tx_old in &mut self.transactions {
165
20.5k
                if !tx_old.complete {
166
16.2k
                    tx_old.tx_data.updated_tc = true;
167
16.2k
                    tx_old.tx_data.updated_ts = true;
168
16.2k
                    tx_old.complete = true;
169
16.2k
                    tx_old
170
16.2k
                        .tx_data
171
16.2k
                        .set_event(LdapEvent::TooManyTransactions as u8);
172
16.2k
                }
173
            }
174
80
            return None;
175
368k
        }
176
368k
        let mut tx = LdapTransaction::new();
177
368k
        self.tx_id += 1;
178
368k
        tx.tx_id = self.tx_id;
179
368k
        return Some(tx);
180
368k
    }
181
182
175k
    fn set_event(&mut self, e: LdapEvent) {
183
175k
        if let Some(tx) = self.transactions.back_mut() {
184
174k
            tx.tx_data.set_event(e as u8);
185
174k
        }
186
175k
    }
187
188
249k
    fn find_request(&mut self, message_id: MessageID) -> Option<&mut LdapTransaction> {
189
3.23M
        self.transactions.iter_mut().find(|tx| {
190
3.23M
            tx.request
191
3.23M
                .as_ref()
192
3.23M
                .is_some_and(|req| req.message_id == message_id)
193
3.23M
        })
194
249k
    }
195
196
239k
    fn parse_request(&mut self, flow: *mut Flow, stream_slice: StreamSlice) -> AppLayerResult {
197
239k
        let input = stream_slice.as_slice();
198
239k
        if input.is_empty() {
199
0
            return AppLayerResult::ok();
200
239k
        }
201
202
239k
        if self.has_starttls {
203
0
            unsafe {
204
0
                SCAppLayerRequestProtocolTLSUpgrade(flow);
205
0
            }
206
0
            return AppLayerResult::ok();
207
239k
        }
208
209
239k
        if self.request_gap {
210
0
            if ldap_parse_msg(input).is_err() {
211
0
                return AppLayerResult::ok();
212
0
            }
213
0
            self.request_gap = false;
214
239k
        }
215
216
239k
        let mut start = input;
217
416k
        while !start.is_empty() {
218
331k
            if self.request_frame.is_none() {
219
331k
                self.request_frame = Frame::new(
220
331k
                    flow,
221
331k
                    &stream_slice,
222
331k
                    start,
223
331k
                    -1_i64,
224
331k
                    LdapFrameType::Pdu as u8,
225
331k
                    None,
226
331k
                );
227
331k
                SCLogDebug!("ts: pdu {:?}", self.request_frame);
228
331k
            }
229
331k
            match ldap_parse_msg(start) {
230
176k
                Ok((rem, request)) => {
231
176k
                    let tx = self.new_tx();
232
176k
                    if tx.is_none() {
233
39
                        return AppLayerResult::err();
234
176k
                    }
235
176k
                    let mut tx = tx.unwrap();
236
176k
                    let tx_id = tx.id();
237
                    // check if STARTTLS was requested
238
176k
                    if let ProtocolOp::ExtendedRequest(request) = &request.protocol_op {
239
1.33k
                        if request.request_name.0 == STARTTLS_OID {
240
0
                            self.request_tls = true;
241
1.33k
                        }
242
175k
                    }
243
176k
                    tx.complete |= tx_is_complete(&request.protocol_op, Direction::ToServer);
244
176k
                    tx.request = Some(request.to_static());
245
176k
                    self.transactions.push_back(tx);
246
176k
                    sc_app_layer_parser_trigger_raw_stream_inspection(
247
176k
                        flow,
248
176k
                        Direction::ToServer as i32,
249
                    );
250
176k
                    let consumed = start.len() - rem.len();
251
176k
                    start = rem;
252
176k
                    self.set_frame_ts(flow, tx_id, consumed as i64);
253
                }
254
                Err(nom::Err::Incomplete(_)) => {
255
153k
                    let consumed = input.len() - start.len();
256
153k
                    let needed = start.len() + 1;
257
153k
                    return AppLayerResult::incomplete(consumed as u32, needed as u32);
258
                }
259
                Err(_) => {
260
845
                    self.set_event(LdapEvent::InvalidData);
261
845
                    return AppLayerResult::err();
262
                }
263
            }
264
        }
265
266
85.2k
        return AppLayerResult::ok();
267
239k
    }
268
269
240k
    fn parse_response(&mut self, flow: *mut Flow, stream_slice: StreamSlice) -> AppLayerResult {
270
240k
        let input = stream_slice.as_slice();
271
240k
        if input.is_empty() {
272
0
            return AppLayerResult::ok();
273
240k
        }
274
275
240k
        if self.response_gap {
276
0
            if ldap_parse_msg(input).is_err() {
277
0
                return AppLayerResult::ok();
278
0
            }
279
0
            self.response_gap = false;
280
240k
        }
281
282
240k
        let mut start = input;
283
473k
        while !start.is_empty() {
284
388k
            if self.response_frame.is_none() {
285
388k
                self.response_frame = Frame::new(
286
388k
                    flow,
287
388k
                    &stream_slice,
288
388k
                    start,
289
388k
                    -1_i64,
290
388k
                    LdapFrameType::Pdu as u8,
291
388k
                    None,
292
388k
                );
293
388k
                SCLogDebug!("tc: pdu {:?}", self.response_frame);
294
388k
            }
295
388k
            match ldap_parse_msg(start) {
296
232k
                Ok((rem, response)) => {
297
                    // check if STARTTLS was requested
298
232k
                    if self.request_tls {
299
0
                        if let ProtocolOp::ExtendedResponse(response) = &response.protocol_op {
300
0
                            if response.result.result_code == ResultCode(0) {
301
0
                                SCLogDebug!("LDAP: STARTTLS detected");
302
0
                                self.has_starttls = true;
303
0
                            }
304
0
                            self.request_tls = false;
305
0
                        }
306
232k
                    }
307
232k
                    if let Some(tx) = self.find_request(response.message_id) {
308
61.2k
                        tx.complete |= tx_is_complete(&response.protocol_op, Direction::ToClient);
309
61.2k
                        let tx_id = tx.id();
310
61.2k
                        tx.tx_data.updated_tc = true;
311
61.2k
                        if tx.responses.len() < unsafe { LDAP_MAX_RESPONSES } {
312
55.7k
                            tx.responses.push_back(response.to_static());
313
55.7k
                        } else {
314
5.52k
                            tx.set_event(LdapEvent::TooManyResponses);
315
5.52k
                        }
316
61.2k
                        sc_app_layer_parser_trigger_raw_stream_inspection(
317
61.2k
                            flow,
318
61.2k
                            Direction::ToClient as i32,
319
                        );
320
61.2k
                        let consumed = start.len() - rem.len();
321
61.2k
                        self.set_frame_tc(flow, tx_id, consumed as i64);
322
171k
                    } else if let ProtocolOp::ExtendedResponse(_) = response.protocol_op {
323
                        // this is an unsolicited notification, which means
324
                        // there is no request
325
605
                        let tx = self.new_tx();
326
605
                        if tx.is_none() {
327
2
                            return AppLayerResult::err();
328
603
                        }
329
603
                        let mut tx = tx.unwrap();
330
603
                        let tx_id = tx.id();
331
603
                        tx.complete = true;
332
603
                        tx.responses.push_back(response.to_static());
333
603
                        self.transactions.push_back(tx);
334
603
                        sc_app_layer_parser_trigger_raw_stream_inspection(
335
603
                            flow,
336
603
                            Direction::ToClient as i32,
337
                        );
338
603
                        let consumed = start.len() - rem.len();
339
603
                        self.set_frame_tc(flow, tx_id, consumed as i64);
340
                    } else {
341
170k
                        let tx = self.new_tx();
342
170k
                        if tx.is_none() {
343
34
                            return AppLayerResult::err();
344
170k
                        }
345
170k
                        let mut tx = tx.unwrap();
346
170k
                        tx.complete = true;
347
170k
                        let tx_id = tx.id();
348
170k
                        tx.responses.push_back(response.to_static());
349
170k
                        self.transactions.push_back(tx);
350
170k
                        sc_app_layer_parser_trigger_raw_stream_inspection(
351
170k
                            flow,
352
170k
                            Direction::ToClient as i32,
353
                        );
354
170k
                        self.set_event(LdapEvent::RequestNotFound);
355
170k
                        let consumed = start.len() - rem.len();
356
170k
                        self.set_frame_tc(flow, tx_id, consumed as i64);
357
                    };
358
232k
                    start = rem;
359
                }
360
                Err(nom::Err::Incomplete(_)) => {
361
155k
                    let consumed = input.len() - start.len();
362
155k
                    let needed = start.len() + 1;
363
155k
                    return AppLayerResult::incomplete(consumed as u32, needed as u32);
364
                }
365
                Err(_) => {
366
456
                    self.set_event(LdapEvent::InvalidData);
367
456
                    return AppLayerResult::err();
368
                }
369
            }
370
        }
371
372
84.3k
        return AppLayerResult::ok();
373
240k
    }
374
375
15.1k
    fn parse_request_udp(
376
15.1k
        &mut self, flow: *const Flow, stream_slice: StreamSlice,
377
15.1k
    ) -> AppLayerResult {
378
15.1k
        let input = stream_slice.as_slice();
379
380
15.1k
        let _pdu = Frame::new(
381
15.1k
            flow,
382
15.1k
            &stream_slice,
383
15.1k
            input,
384
15.1k
            input.len() as i64,
385
15.1k
            LdapFrameType::Pdu as u8,
386
15.1k
            None,
387
        );
388
        SCLogDebug!("ts: pdu {:?}", self.request_frame);
389
390
15.1k
        match ldap_parse_msg(input) {
391
14.8k
            Ok((_, request)) => {
392
14.8k
                let tx = self.new_tx();
393
14.8k
                if tx.is_none() {
394
2
                    return AppLayerResult::err();
395
14.8k
                }
396
14.8k
                let mut tx = tx.unwrap();
397
14.8k
                tx.complete |= tx_is_complete(&request.protocol_op, Direction::ToServer);
398
14.8k
                tx.request = Some(request.to_static());
399
14.8k
                self.transactions.push_back(tx);
400
            }
401
            Err(nom::Err::Incomplete(_)) => {
402
173
                self.set_event(LdapEvent::IncompleteData);
403
173
                return AppLayerResult::err();
404
            }
405
            Err(_) => {
406
126
                self.set_event(LdapEvent::InvalidData);
407
126
                return AppLayerResult::err();
408
            }
409
        }
410
411
14.8k
        return AppLayerResult::ok();
412
15.1k
    }
413
414
14.5k
    fn parse_response_udp(
415
14.5k
        &mut self, flow: *const Flow, stream_slice: StreamSlice,
416
14.5k
    ) -> AppLayerResult {
417
14.5k
        let input = stream_slice.as_slice();
418
14.5k
        if input.is_empty() {
419
0
            return AppLayerResult::ok();
420
14.5k
        }
421
422
14.5k
        let mut start = input;
423
31.5k
        while !start.is_empty() {
424
17.2k
            if self.response_frame.is_none() {
425
17.2k
                self.response_frame = Frame::new(
426
17.2k
                    flow,
427
17.2k
                    &stream_slice,
428
17.2k
                    start,
429
17.2k
                    -1_i64,
430
17.2k
                    LdapFrameType::Pdu as u8,
431
17.2k
                    None,
432
17.2k
                );
433
17.2k
                SCLogDebug!("tc: pdu {:?}", self.response_frame);
434
17.2k
            }
435
17.2k
            match ldap_parse_msg(start) {
436
17.0k
                Ok((rem, response)) => {
437
17.0k
                    if let Some(tx) = self.find_request(response.message_id) {
438
11.9k
                        tx.complete |= tx_is_complete(&response.protocol_op, Direction::ToClient);
439
11.9k
                        let tx_id = tx.id();
440
11.9k
                        if tx.responses.len() < unsafe { LDAP_MAX_RESPONSES } {
441
11.6k
                            tx.responses.push_back(response.to_static());
442
11.6k
                        } else {
443
237
                            tx.set_event(LdapEvent::TooManyResponses);
444
237
                        }
445
11.9k
                        let consumed = start.len() - rem.len();
446
11.9k
                        self.set_frame_tc(flow, tx_id, consumed as i64);
447
5.10k
                    } else if let ProtocolOp::ExtendedResponse(_) = response.protocol_op {
448
                        // this is an unsolicited notification, which means
449
                        // there is no request
450
1.84k
                        let tx = self.new_tx();
451
1.84k
                        if tx.is_none() {
452
1
                            return AppLayerResult::err();
453
1.84k
                        }
454
1.84k
                        let mut tx = tx.unwrap();
455
1.84k
                        tx.complete = true;
456
1.84k
                        let tx_id = tx.id();
457
1.84k
                        tx.responses.push_back(response.to_static());
458
1.84k
                        self.transactions.push_back(tx);
459
1.84k
                        let consumed = start.len() - rem.len();
460
1.84k
                        self.set_frame_tc(flow, tx_id, consumed as i64);
461
                    } else {
462
3.25k
                        let tx = self.new_tx();
463
3.25k
                        if tx.is_none() {
464
2
                            return AppLayerResult::err();
465
3.25k
                        }
466
3.25k
                        let mut tx = tx.unwrap();
467
3.25k
                        tx.complete = true;
468
3.25k
                        let tx_id = tx.id();
469
3.25k
                        tx.responses.push_back(response.to_static());
470
3.25k
                        self.transactions.push_back(tx);
471
3.25k
                        self.set_event(LdapEvent::RequestNotFound);
472
3.25k
                        let consumed = start.len() - rem.len();
473
3.25k
                        self.set_frame_tc(flow, tx_id, consumed as i64);
474
                    };
475
17.0k
                    start = rem;
476
                }
477
                Err(nom::Err::Incomplete(_)) => {
478
121
                    self.set_event(LdapEvent::IncompleteData);
479
121
                    return AppLayerResult::err();
480
                }
481
                Err(_) => {
482
67
                    self.set_event(LdapEvent::InvalidData);
483
67
                    return AppLayerResult::err();
484
                }
485
            }
486
        }
487
488
14.3k
        return AppLayerResult::ok();
489
14.5k
    }
490
491
176k
    fn set_frame_ts(&mut self, flow: *const Flow, tx_id: u64, consumed: i64) {
492
176k
        if let Some(frame) = &self.request_frame {
493
0
            frame.set_len(flow, consumed);
494
0
            frame.set_tx(flow, tx_id);
495
0
            self.request_frame = None;
496
176k
        }
497
176k
    }
498
499
249k
    fn set_frame_tc(&mut self, flow: *const Flow, tx_id: u64, consumed: i64) {
500
249k
        if let Some(frame) = &self.response_frame {
501
0
            frame.set_len(flow, consumed);
502
0
            frame.set_tx(flow, tx_id);
503
0
            self.response_frame = None;
504
249k
        }
505
249k
    }
506
507
0
    fn on_request_gap(&mut self, _size: u32) {
508
0
        self.request_gap = true;
509
0
    }
510
511
0
    fn on_response_gap(&mut self, _size: u32) {
512
0
        self.response_gap = true;
513
0
    }
514
}
515
516
264k
fn tx_is_complete(op: &ProtocolOp, dir: Direction) -> bool {
517
264k
    match dir {
518
191k
        Direction::ToServer => match op {
519
377
            ProtocolOp::UnbindRequest => true,
520
148k
            ProtocolOp::AbandonRequest(_) => true,
521
43.0k
            _ => false,
522
        },
523
73.1k
        Direction::ToClient => match op {
524
            ProtocolOp::SearchResultDone(_)
525
            | ProtocolOp::BindResponse(_)
526
            | ProtocolOp::ModifyResponse(_)
527
            | ProtocolOp::AddResponse(_)
528
            | ProtocolOp::DelResponse(_)
529
            | ProtocolOp::ModDnResponse(_)
530
            | ProtocolOp::CompareResponse(_)
531
3.80k
            | ProtocolOp::ExtendedResponse(_) => true,
532
69.3k
            _ => false,
533
        },
534
    }
535
264k
}
536
537
1.20k
fn probe(input: &[u8], direction: Direction, rdir: *mut u8) -> AppProto {
538
1.20k
    match ldap_parse_msg(input) {
539
140
        Ok((_, ldap_msg)) => {
540
140
            if direction == Direction::ToServer && !ldap_is_request(&ldap_msg) {
541
57
                unsafe {
542
57
                    *rdir = Direction::ToClient.into();
543
57
                }
544
83
            }
545
140
            if direction == Direction::ToClient && !ldap_is_response(&ldap_msg) {
546
19
                unsafe {
547
19
                    *rdir = Direction::ToServer.into();
548
19
                }
549
121
            }
550
140
            return unsafe { ALPROTO_LDAP };
551
        }
552
        Err(nom::Err::Incomplete(_)) => {
553
381
            return ALPROTO_UNKNOWN;
554
        }
555
688
        Err(_e) => {
556
688
            return ALPROTO_FAILED;
557
        }
558
    }
559
1.20k
}
560
561
1.21k
unsafe extern "C" fn ldap_probing_parser(
562
1.21k
    _flow: *const Flow, direction: u8, input: *const u8, input_len: u32, rdir: *mut u8,
563
1.21k
) -> AppProto {
564
1.21k
    if input_len > 1 && !input.is_null() {
565
1.20k
        let slice = build_slice!(input, input_len as usize);
566
1.20k
        return probe(slice, direction.into(), rdir);
567
1
    }
568
1
    return ALPROTO_UNKNOWN;
569
1.21k
}
570
571
4.61k
extern "C" fn ldap_state_new(_orig_state: *mut c_void, _orig_proto: AppProto) -> *mut c_void {
572
4.61k
    let state = LdapState::new();
573
4.61k
    let boxed = Box::new(state);
574
4.61k
    return Box::into_raw(boxed) as *mut c_void;
575
4.61k
}
576
577
4.61k
unsafe extern "C" fn ldap_state_free(state: *mut c_void) {
578
4.61k
    std::mem::drop(Box::from_raw(state as *mut LdapState));
579
4.61k
}
580
581
321k
unsafe extern "C" fn ldap_state_tx_free(state: *mut c_void, tx_id: u64) {
582
321k
    let state = cast_pointer!(state, LdapState);
583
321k
    state.free_tx(tx_id);
584
321k
}
585
586
239k
unsafe extern "C" fn ldap_parse_request(
587
239k
    flow: *mut Flow, state: *mut c_void, pstate: *mut AppLayerParserState,
588
239k
    stream_slice: StreamSlice, _data: *const c_void,
589
239k
) -> AppLayerResult {
590
239k
    if stream_slice.is_empty() {
591
0
        if SCAppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS) > 0 {
592
0
            return AppLayerResult::ok();
593
        } else {
594
0
            return AppLayerResult::err();
595
        }
596
239k
    }
597
239k
    let state = cast_pointer!(state, LdapState);
598
599
239k
    if stream_slice.is_gap() {
600
0
        state.on_request_gap(stream_slice.gap_size());
601
0
    } else {
602
239k
        return state.parse_request(flow, stream_slice);
603
    }
604
0
    AppLayerResult::ok()
605
239k
}
606
607
240k
unsafe extern "C" fn ldap_parse_response(
608
240k
    flow: *mut Flow, state: *mut c_void, pstate: *mut AppLayerParserState,
609
240k
    stream_slice: StreamSlice, _data: *const c_void,
610
240k
) -> AppLayerResult {
611
240k
    if stream_slice.is_empty() {
612
0
        if SCAppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC) > 0 {
613
0
            return AppLayerResult::ok();
614
        } else {
615
0
            return AppLayerResult::err();
616
        }
617
240k
    }
618
240k
    let state = cast_pointer!(state, LdapState);
619
240k
    if stream_slice.is_gap() {
620
0
        state.on_response_gap(stream_slice.gap_size());
621
0
    } else {
622
240k
        return state.parse_response(flow, stream_slice);
623
    }
624
0
    AppLayerResult::ok()
625
240k
}
626
627
15.1k
unsafe extern "C" fn ldap_parse_request_udp(
628
15.1k
    flow: *mut Flow, state: *mut c_void, _pstate: *mut AppLayerParserState,
629
15.1k
    stream_slice: StreamSlice, _data: *const c_void,
630
15.1k
) -> AppLayerResult {
631
15.1k
    let state = cast_pointer!(state, LdapState);
632
15.1k
    state.parse_request_udp(flow, stream_slice)
633
15.1k
}
634
635
14.5k
unsafe extern "C" fn ldap_parse_response_udp(
636
14.5k
    flow: *mut Flow, state: *mut c_void, _pstate: *mut AppLayerParserState,
637
14.5k
    stream_slice: StreamSlice, _data: *const c_void,
638
14.5k
) -> AppLayerResult {
639
14.5k
    let state = cast_pointer!(state, LdapState);
640
14.5k
    state.parse_response_udp(flow, stream_slice)
641
14.5k
}
642
643
0
unsafe extern "C" fn ldap_state_get_tx(state: *mut c_void, tx_id: u64) -> *mut c_void {
644
0
    let state = cast_pointer!(state, LdapState);
645
0
    match state.get_tx(tx_id) {
646
0
        Some(tx) => {
647
0
            return tx as *const _ as *mut _;
648
        }
649
        None => {
650
0
            return std::ptr::null_mut();
651
        }
652
    }
653
0
}
654
655
1.52M
unsafe extern "C" fn ldap_state_get_tx_count(state: *mut c_void) -> u64 {
656
1.52M
    let state = cast_pointer!(state, LdapState);
657
1.52M
    return state.tx_id;
658
1.52M
}
659
660
8.35M
unsafe extern "C" fn ldap_tx_get_alstate_progress(tx: *mut c_void, _direction: u8) -> c_int {
661
8.35M
    let tx = cast_pointer!(tx, LdapTransaction);
662
8.35M
    if tx.complete {
663
643k
        return 1;
664
7.71M
    }
665
7.71M
    return 0;
666
8.35M
}
667
668
export_tx_data_get!(ldap_get_tx_data, LdapTransaction);
669
export_state_data_get!(ldap_get_state_data, LdapState);
670
671
const PARSER_NAME: &[u8] = b"ldap\0";
672
673
#[no_mangle]
674
40
pub unsafe extern "C" fn SCRegisterLdapTcpParser() {
675
40
    let default_port = CString::new("[389, 3268]").unwrap();
676
40
    let parser = RustParser {
677
40
        name: PARSER_NAME.as_ptr() as *const c_char,
678
40
        default_port: default_port.as_ptr(),
679
40
        ipproto: IPPROTO_TCP,
680
40
        probe_ts: Some(ldap_probing_parser),
681
40
        probe_tc: Some(ldap_probing_parser),
682
40
        min_depth: 0,
683
40
        max_depth: 16,
684
40
        state_new: ldap_state_new,
685
40
        state_free: ldap_state_free,
686
40
        tx_free: ldap_state_tx_free,
687
40
        parse_ts: ldap_parse_request,
688
40
        parse_tc: ldap_parse_response,
689
40
        get_tx_count: ldap_state_get_tx_count,
690
40
        get_tx: ldap_state_get_tx,
691
40
        tx_comp_st_ts: 1,
692
40
        tx_comp_st_tc: 1,
693
40
        tx_get_progress: ldap_tx_get_alstate_progress,
694
40
        get_eventinfo: Some(LdapEvent::get_event_info),
695
40
        get_eventinfo_byid: Some(LdapEvent::get_event_info_by_id),
696
40
        localstorage_new: None,
697
40
        localstorage_free: None,
698
40
        get_tx_files: None,
699
40
        get_tx_iterator: Some(applayer::state_get_tx_iterator::<LdapState, LdapTransaction>),
700
40
        get_tx_data: ldap_get_tx_data,
701
40
        get_state_data: ldap_get_state_data,
702
40
        apply_tx_config: None,
703
40
        flags: APP_LAYER_PARSER_OPT_ACCEPT_GAPS,
704
40
        get_frame_id_by_name: Some(LdapFrameType::ffi_id_from_name),
705
40
        get_frame_name_by_id: Some(LdapFrameType::ffi_name_from_id),
706
40
        get_state_id_by_name: None,
707
40
        get_state_name_by_id: None,
708
40
    };
709
710
40
    let ip_proto_str = CString::new("tcp").unwrap();
711
40
    if SCAppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
712
40
        let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
713
40
        ALPROTO_LDAP = alproto;
714
40
        if SCAppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
715
40
            let _ = AppLayerRegisterParser(&parser, alproto);
716
40
        }
717
40
        if let Some(val) = conf_get("app-layer.protocols.ldap.max-tx") {
718
0
            if let Ok(v) = val.parse::<usize>() {
719
0
                if LDAP_MAX_TX == LDAP_MAX_TX_DEFAULT {
720
0
                    LDAP_MAX_TX = v;
721
0
                }
722
            } else {
723
0
                SCLogError!("Invalid value for ldap.max-tx");
724
            }
725
40
        }
726
40
        if let Some(val) = conf_get("app-layer.protocols.ldap.max-responses") {
727
0
            if let Ok(v) = val.parse::<usize>() {
728
0
                LDAP_MAX_RESPONSES = v;
729
0
            } else {
730
0
                SCLogWarning!("Invalid value for ldap.max-responses");
731
            }
732
40
        }
733
40
        SCAppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_LDAP);
734
0
    } else {
735
0
        SCLogDebug!("Protocol detection and parser disabled for LDAP/TCP.");
736
0
    }
737
40
}
738
739
#[no_mangle]
740
40
pub unsafe extern "C" fn SCRegisterLdapUdpParser() {
741
40
    let default_port = CString::new("[389, 3268]").unwrap();
742
40
    let parser = RustParser {
743
40
        name: PARSER_NAME.as_ptr() as *const c_char,
744
40
        default_port: default_port.as_ptr(),
745
40
        ipproto: IPPROTO_UDP,
746
40
        probe_ts: Some(ldap_probing_parser),
747
40
        probe_tc: Some(ldap_probing_parser),
748
40
        min_depth: 0,
749
40
        max_depth: 16,
750
40
        state_new: ldap_state_new,
751
40
        state_free: ldap_state_free,
752
40
        tx_free: ldap_state_tx_free,
753
40
        parse_ts: ldap_parse_request_udp,
754
40
        parse_tc: ldap_parse_response_udp,
755
40
        get_tx_count: ldap_state_get_tx_count,
756
40
        get_tx: ldap_state_get_tx,
757
40
        tx_comp_st_ts: 1,
758
40
        tx_comp_st_tc: 1,
759
40
        tx_get_progress: ldap_tx_get_alstate_progress,
760
40
        get_eventinfo: Some(LdapEvent::get_event_info),
761
40
        get_eventinfo_byid: Some(LdapEvent::get_event_info_by_id),
762
40
        localstorage_new: None,
763
40
        localstorage_free: None,
764
40
        get_tx_files: None,
765
40
        get_tx_iterator: Some(applayer::state_get_tx_iterator::<LdapState, LdapTransaction>),
766
40
        get_tx_data: ldap_get_tx_data,
767
40
        get_state_data: ldap_get_state_data,
768
40
        apply_tx_config: None,
769
40
        flags: 0,
770
40
        get_frame_id_by_name: Some(LdapFrameType::ffi_id_from_name),
771
40
        get_frame_name_by_id: Some(LdapFrameType::ffi_name_from_id),
772
40
        get_state_id_by_name: None,
773
40
        get_state_name_by_id: None,
774
40
    };
775
776
40
    let ip_proto_str = CString::new("udp").unwrap();
777
40
    if SCAppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
778
40
        let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
779
40
        ALPROTO_LDAP = alproto;
780
40
        if SCAppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
781
40
            let _ = AppLayerRegisterParser(&parser, alproto);
782
40
        }
783
40
        if let Some(val) = conf_get("app-layer.protocols.ldap.max-tx") {
784
0
            if let Ok(v) = val.parse::<usize>() {
785
0
                if LDAP_MAX_TX == LDAP_MAX_TX_DEFAULT {
786
0
                    LDAP_MAX_TX = v;
787
0
                }
788
            } else {
789
0
                SCLogError!("Invalid value for ldap.max-tx");
790
            }
791
40
        }
792
40
        if let Some(val) = conf_get("app-layer.protocols.ldap.max-responses") {
793
0
            if let Ok(v) = val.parse::<usize>() {
794
0
                LDAP_MAX_RESPONSES = v;
795
0
            } else {
796
0
                SCLogWarning!("Invalid value for ldap.max-responses");
797
            }
798
40
        }
799
40
        SCAppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_LDAP);
800
0
    } else {
801
0
        SCLogDebug!("Protocol detection and parser disabled for LDAP/UDP.");
802
0
    }
803
40
}