diff --git a/rust/src/ldap/ldap.rs b/rust/src/ldap/ldap.rs
index 4c9c3947d7a8..f86c8d8499d9 100644
--- a/rust/src/ldap/ldap.rs
+++ b/rust/src/ldap/ldap.rs
@@ -35,6 +35,8 @@ static mut LDAP_MAX_TX: usize = LDAP_MAX_TX_DEFAULT;
static mut ALPROTO_LDAP: AppProto = ALPROTO_UNKNOWN;
+const STARTTLS_OID: &str = "1.3.6.1.4.1.1466.20037";
+
#[derive(AppLayerFrameType)]
pub enum LdapFrameType {
Pdu,
@@ -92,6 +94,8 @@ pub struct LdapState {
response_frame: Option,
request_gap: bool,
response_gap: bool,
+ request_tls: bool,
+ has_starttls: bool,
}
impl State for LdapState {
@@ -115,6 +119,8 @@ impl LdapState {
response_frame: None,
request_gap: false,
response_gap: false,
+ request_tls: false,
+ has_starttls: false,
}
}
@@ -182,6 +188,13 @@ impl LdapState {
return AppLayerResult::ok();
}
+ if self.has_starttls {
+ unsafe {
+ AppLayerRequestProtocolTLSUpgrade(flow);
+ }
+ return AppLayerResult::ok();
+ }
+
if self.request_gap {
match ldap_parse_msg(input) {
Ok((_, msg)) => {
@@ -216,6 +229,12 @@ impl LdapState {
let mut tx = self.new_tx();
let tx_id = tx.id();
let request = LdapMessage::from(msg);
+ // check if STARTTLS was requested
+ if let ProtocolOp::ExtendedRequest(request) = &request.protocol_op {
+ if request.request_name.0 == STARTTLS_OID {
+ self.request_tls = true;
+ }
+ }
tx.complete = tx_is_complete(&request.protocol_op, Direction::ToServer);
tx.request = Some(request);
self.transactions.push_back(tx);
@@ -275,6 +294,17 @@ impl LdapState {
match ldap_parse_msg(start) {
Ok((rem, msg)) => {
let response = LdapMessage::from(msg);
+ // check if STARTTLS was requested
+ if self.request_tls {
+ if let ProtocolOp::ExtendedResponse(response) = &response.protocol_op
+ {
+ if response.result.result_code == ResultCode(0) {
+ SCLogDebug!("LDAP: STARTTLS detected");
+ self.has_starttls = true;
+ }
+ self.request_tls = false;
+ }
+ }
if let Some(tx) = self.find_request(response.message_id) {
tx.complete = tx_is_complete(&response.protocol_op, Direction::ToClient);
let tx_id = tx.id();
@@ -617,7 +647,7 @@ const PARSER_NAME: &[u8] = b"ldap\0";
#[no_mangle]
pub unsafe extern "C" fn SCRegisterLdapTcpParser() {
- let default_port = CString::new("389").unwrap();
+ let default_port = CString::new("[389, 3268]").unwrap();
let parser = RustParser {
name: PARSER_NAME.as_ptr() as *const c_char,
default_port: default_port.as_ptr(),
@@ -674,7 +704,7 @@ pub unsafe extern "C" fn SCRegisterLdapTcpParser() {
#[no_mangle]
pub unsafe extern "C" fn SCRegisterLdapUdpParser() {
- let default_port = CString::new("389").unwrap();
+ let default_port = CString::new("[389, 3268]").unwrap();
let parser = RustParser {
name: PARSER_NAME.as_ptr() as *const c_char,
default_port: default_port.as_ptr(),
diff --git a/suricata.yaml.in b/suricata.yaml.in
index 7dd7cb588675..82a72bad0f3a 100644
--- a/suricata.yaml.in
+++ b/suricata.yaml.in
@@ -1188,11 +1188,11 @@ app-layer:
tcp:
enabled: yes
detection-ports:
- dp: 389
+ dp: 389, 3268
udp:
enabled: yes
detection-ports:
- dp: 389
+ dp: 389, 3268
# Maximum number of live LDAP transactions per flow
# max-tx: 1024