.. container:: example-rule
alert ldap any any -> any any (msg:"Test attribute type and operation"; :example-rule-emphasis:`ldap.request.operation:add_request; ldap.request.attribute_type; content:"objectClass";` sid:1;)
+
+ldap.responses.attribute_type
+-----------------------------
+
+Matches on LDAP attribute type from response operations.
+
+Comparison is case-sensitive.
+
+Syntax::
+
+ ldap.responses.attribute_type; content:"<content to match against>";
+
+``ldap.responses.attribute_type`` is a 'sticky buffer' and can be used as a ``fast_pattern``.
+
+``ldap.responses.attribute_type`` supports multiple buffer matching, see :doc:`multi-buffer-matching`.
+
+This keyword maps to the EVE field ``ldap.responses[].search_result_entry.attributes[].type``
+
+Example
+^^^^^^^
+
+Example of a signature that would alert if a packet has the LDAP attribute type ``dc``:
+
+.. container:: example-rule
+
+ alert ldap any any -> any any (msg:"Test responses attribute type"; :example-rule-emphasis:`ldap.responses.attribute_type; content:"dc";` sid:1;)
+
+It is possible to use the keyword ``ldap.responses.operation`` in the same rule to
+specify the operation to match.
+
+Here is an example of a signature that would alert if a packet has an LDAP
+search result entry operation at index 1 on the responses array,
+and contains the LDAP attribute type ``dc``.
+
+.. container:: example-rule
+
+ alert ldap any any -> any any (msg:"Test attribute type and operation"; :example-rule-emphasis:`ldap.responses.operation:search_result_entry,1; ldap.responses.attribute_type; content:"dc";` sid:1;)
static mut G_LDAP_RESPONSES_RESULT_CODE_BUFFER_ID: c_int = 0;
static mut G_LDAP_RESPONSES_MSG_BUFFER_ID: c_int = 0;
static mut G_LDAP_REQUEST_ATTRIBUTE_TYPE_BUFFER_ID: c_int = 0;
+static mut G_LDAP_RESPONSES_ATTRIBUTE_TYPE_BUFFER_ID: c_int = 0;
unsafe extern "C" fn ldap_parse_protocol_req_op(
ustr: *const std::os::raw::c_char,
return false;
}
+unsafe extern "C" fn ldap_detect_responses_attibute_type_setup(
+ de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+ if DetectSignatureSetAppProto(s, ALPROTO_LDAP) != 0 {
+ return -1;
+ }
+ if DetectBufferSetActiveList(de, s, G_LDAP_RESPONSES_ATTRIBUTE_TYPE_BUFFER_ID) < 0 {
+ return -1;
+ }
+ return 0;
+}
+
+unsafe extern "C" fn ldap_detect_responses_attribute_type_get_data(
+ de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+ tx: *const c_void, list_id: c_int, local_id: u32,
+) -> *mut c_void {
+ return DetectHelperGetMultiData(
+ de,
+ transforms,
+ flow,
+ flow_flags,
+ tx,
+ list_id,
+ local_id,
+ ldap_tx_get_resp_attribute_type,
+ );
+}
+
+unsafe extern "C" fn ldap_tx_get_resp_attribute_type(
+ tx: *const c_void, _flags: u8, local_id: u32, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+ let tx = cast_pointer!(tx, LdapTransaction);
+
+ let mut pos = 0_u32;
+ for i in 0..tx.responses.len() {
+ let response = &tx.responses[i];
+ match &response.protocol_op {
+ ProtocolOp::SearchResultEntry(resp) => {
+ if local_id < pos + resp.attributes.len() as u32 {
+ let value = &resp.attributes[(local_id - pos) as usize].attr_type.0;
+ *buffer = value.as_ptr(); //unsafe
+ *buffer_len = value.len() as u32;
+ return true;
+ } else {
+ pos += resp.attributes.len() as u32;
+ }
+ }
+ _ => continue,
+ }
+ }
+ return false;
+}
+
#[no_mangle]
pub unsafe extern "C" fn SCDetectLdapRegister() {
let kw = SCSigTableElmt {
true, //to server
ldap_detect_request_attribute_type_get_data,
);
+ let kw = SCSigTableElmt {
+ name: b"ldap.responses.attribute_type\0".as_ptr() as *const libc::c_char,
+ desc: b"match LDAP responses attribute type\0".as_ptr() as *const libc::c_char,
+ url: b"/rules/ldap-keywords.html#ldap.responses.attribute_type\0".as_ptr()
+ as *const libc::c_char,
+ Setup: ldap_detect_responses_attibute_type_setup,
+ flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER,
+ AppLayerTxMatch: None,
+ Free: None,
+ };
+ let _g_ldap_responses_attribute_type_kw_id = DetectHelperKeywordRegister(&kw);
+ G_LDAP_RESPONSES_ATTRIBUTE_TYPE_BUFFER_ID = DetectHelperMultiBufferMpmRegister(
+ b"ldap.responses.attribute_type\0".as_ptr() as *const libc::c_char,
+ b"LDAP RESPONSES ATTRIBUTE TYPE\0".as_ptr() as *const libc::c_char,
+ ALPROTO_LDAP,
+ true, //to client
+ false, //to server
+ ldap_detect_responses_attribute_type_get_data,
+ );
}