Skip to content

Commit

Permalink
sdp: add sdp.media.encryption_key sticky buffer
Browse files Browse the repository at this point in the history
This adds a sticky (multi) buffer to match the "Encryption key" subfield
of the "Media description" field in both requests and responses.

Ticket OISF#7291
glongo committed Oct 15, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 3f82820 commit b6fe4e7
Showing 4 changed files with 457 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/userguide/rules/index.rst
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ Suricata Rules
snmp-keywords
base64-keywords
sip-keywords
sdp-keywords
rfb-keywords
mqtt-keywords
ike-keywords
382 changes: 382 additions & 0 deletions doc/userguide/rules/sdp-keywords.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,382 @@
SDP Keywords
============

The SDP keywords are implemented as sticky buffers and can be used to match on fields in SDP messages.

======================================== ==================
Keyword Direction
======================================== ==================
sdp.origin Both
sdp.session_name Both
sdp.session_info Both
sdp.uri Both
sdp.email Both
sdp.connection_data Both
sdp.bandwidth Both
sdp.time Both
sdp.repeat_time Both
sdp.timezone Both
sdp.encryption_key Both
sdp.attribute Both
sdp.media_description.media Both
sdp.media_description.session_info Both
sdp.media_description.connection_data Both
sdp.media_description.encryption_key Both
======================================== ==================

sdp.origin
----------

This keyword matches on the originator found in an SDP request or response.

Syntax
~~~~~~

::

sdp.origin; content:<origin>;

Where <origin> is an originator that follows the SDP Origin (o=) scheme.

Examples
~~~~~~~~

::

sdp.origin; content:"SIPPS 105015165 105015162 IN IP4 192.168.1.2";

sdp.session_name
----------------

This keyword matches on the session name found in an SDP request or response.

Syntax
~~~~~~

::

sdp.session_name; content:<session_name>;

Where <session_name> is a name that follows the SDP Session name (s=) scheme.

Examples
~~~~~~~~

::

sdp.session_name; content:"SIP call";

sdp.session_info
----------------

This keyword matches on the session information found in an SDP request or response.

Syntax
~~~~~~

::

sdp.session_info; content:<session_info>;

Where <session_info> is a description that follows the SDP Session information (i=) scheme.

Examples
~~~~~~~~

::

sdp.session_info; content:"Session Description Protocol";

sdp.uri
-------

This keyword matches on the URI found in an SDP request or response.

Syntax
~~~~~~

::

sdp.uri; content:<uri>;

Where <uri> is a URI (u=) that the follows the SDP scheme.

Examples
~~~~~~~~

::

sdp.uri; content:"https://www.sdp.proto"

sdp.email
---------

This keyword matches on the email found in an SDP request or response.

Syntax
~~~~~~

::

sdp.email; content:<email>

Where <email> is an email address (e=) that follows the SDP scheme.

Examples
~~~~~~~~

::

sdp.email; content:"[email protected] (Jane Doe)";

sdp.phone_number
----------------

This keyword matches on the phone number found in an SDP request or response.

Syntax
~~~~~~

::

sdp.phone_number; content:<phone_number>

Where <phone_number> is a phone number (p=) that follows the SDP scheme.

Examples
~~~~~~~~

::

sdp.phone_number; content:"+1 617 555-6011 (Jane Doe)";

sdp.connection_data
-------------------

This keyword matches on the connection found in an SDP request or response.

Syntax
~~~~~~

::

sdp.connection_data; content:<connection_data>;

Where <connection_data> is a connection (c=) that follows the SDP scheme.

Examples
~~~~~~~~

::

sdp.connection_data; content:"IN IP4 192.168.1.2"

sdp.bandwidth
-------------

This keyword matches on the bandwidths found in an SDP request or response.

Syntax
~~~~~~

::

sdp.bandwidth; content:<bandwidth>

Where <bandwidth> is a bandwidth (b=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.bandwidth; content:"AS:64"

sdp.time
--------

This keyword matches on the time found in an SDP request or response.

Syntax
~~~~~~

::

sdp.time; content:<time>

Where <time> is a time (t=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.time; content:"3034423619 3042462419"

sdp.repeat_time
---------------

This keyword matches on the repeat time found in an SDP request or response.

Syntax
~~~~~~

::

sdp.repeat_time; content:<repeat_time>

Where <repeat_time> is a repeat time (r=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.repeat_time; content:"604800 3600 0 90000"

sdp.timezone
------------

This keyword matches on the timezone found in an SDP request or response.

Syntax
~~~~~~

::

sdp.timezone; content:<timezone>

Where <timezone> is a timezone (z=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.timezone; content:"2882844526 -1h 2898848070 0"

sdp.encryption_key
------------------

This keyword matches on the encryption key found in an SDP request or response.

Syntax
~~~~~~

::

sdp.encryption_key; content:<encryption_key>

Where <encryption_key> is a key (k=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.encryption_key; content:"prompt"

sdp.attribute
----------------

This keyword matches on the attributes found in an SDP request or response.

Syntax
~~~~~~

::

sdp.attribute; content:<attribute>

Where <attribute> is an attribute (a=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.attribute; content:"sendrecv"

sdp.media_description.media
---------------------------

This keyword matches on the Media subfield of a Media description field found in an SDP request or response.

Syntax
~~~~~~

::

sdp.media_description.media; content:<media>

Where <media> is a media (m=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.media_description.media; content:"audio 30000 RTP/AVP 0 8 97 2 3"

sdp.media_description.session_info
----------------------------------

This keyword matches on the Session information subfield of a Media description field found in an SDP request or response.

Syntax
~~~~~~

::

sdp.media_description.session_info; content:<session_info>

Where <session_info> is a description (i=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.media_description.session_info; content:"Session Description Protocol"

sdp.media_description.connection_data
-------------------------------------

This keyword matches on the Connection data subfield of a Media description field found in an SDP request or response.

Syntax
~~~~~~

::

sdp.media_description.connection_data; content:<connection_data>

Where <connection_data> is a connection (c=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.media_description.connection_data; content:"IN IP4 192.168.1.2"

sdp.media_description.encryption_key
------------------------------------

This keyword matches on the Encryption key subfield of a Media description field found in an SDP request or response.

Syntax
~~~~~~

::

sdp.media_description.encryption_key; content:<encryption_key>

Where <encryption_key> is a key (k=) that follows the SDP scheme.

Example
~~~~~~~

::

sdp.media_description.encryption_key; content:"prompt"
1 change: 1 addition & 0 deletions doc/userguide/upgrade.rst
Original file line number Diff line number Diff line change
@@ -79,6 +79,7 @@ Major changes
- sip.content_length
- Napatech support has been moved to a capture plugin. See :doc:`Napatech plugin
<upgrade/8.0-napatech-plugin>`.
- SDP sticky buffers have been introduced.

Removals
~~~~~~~~
73 changes: 73 additions & 0 deletions rust/src/sdp/detect.rs
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ static mut G_SDP_ATTRIBUTE_BUFFER_ID: c_int = 0;
static mut G_SDP_MEDIA_DESC_MEDIA_BUFFER_ID: c_int = 0;
static mut G_SDP_MEDIA_DESC_SESSION_INFO_BUFFER_ID: c_int = 0;
static mut G_SDP_MEDIA_DESC_CONNECTION_DATA_BUFFER_ID: c_int = 0;
static mut G_SDP_MEDIA_DESC_ENCRYPTION_KEY_BUFFER_ID: c_int = 0;

unsafe extern "C" fn sdp_session_name_setup(
de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
@@ -833,6 +834,59 @@ unsafe extern "C" fn sip_media_desc_connection_data_get_data(
false
}

unsafe extern "C" fn sdp_media_desc_encryption_key_setup(
de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
) -> c_int {
if DetectSignatureSetAppProto(s, ALPROTO_SIP) != 0 {
return -1;
}
if DetectBufferSetActiveList(de, s, G_SDP_MEDIA_DESC_ENCRYPTION_KEY_BUFFER_ID) < 0 {
return -1;
}
return 0;
}

unsafe extern "C" fn sdp_media_desc_encryption_key_get(
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,
sip_media_desc_encryption_key_get_data,
);
}

unsafe extern "C" fn sip_media_desc_encryption_key_get_data(
tx: *const c_void, flow_flags: u8, local_id: u32, buffer: *mut *const u8, buffer_len: *mut u32,
) -> bool {
let tx = cast_pointer!(tx, SIPTransaction);
let direction = flow_flags.into();
let sdp_option = match direction {
Direction::ToServer => tx.request.as_ref().and_then(|req| req.body.as_ref()),
Direction::ToClient => tx.response.as_ref().and_then(|resp| resp.body.as_ref()),
};
if let Some(sdp) = sdp_option {
if let Some(ref m) = sdp.media_description {
if (local_id as usize) < m.len() {
if let Some(k) = &m[local_id as usize].encryption_key {
*buffer = k.as_ptr();
*buffer_len = k.len() as u32;
return true;
}
}
}
}
*buffer = ptr::null();
*buffer_len = 0;
false
}

#[no_mangle]
pub unsafe extern "C" fn ScDetectSdpRegister() {
let kw = SCSigTableElmt {
@@ -1134,4 +1188,23 @@ pub unsafe extern "C" fn ScDetectSdpRegister() {
true,
sdp_media_desc_connection_data_get,
);
let kw = SCSigTableElmt {
name: b"sdp.media.encryption_key\0".as_ptr() as *const libc::c_char,
desc: b"sticky buffer to match on the SDP encryption key subfield of the media_description field\0".as_ptr()
as *const libc::c_char,
url: b"/rules/sdp-keywords.html#sdp-media-description-encryption-key\0".as_ptr() as *const libc::c_char,
Setup: sdp_media_desc_encryption_key_setup,
flags: SIGMATCH_NOOPT,
AppLayerTxMatch: None,
Free: None,
};
let _ = DetectHelperKeywordRegister(&kw);
G_SDP_MEDIA_DESC_ENCRYPTION_KEY_BUFFER_ID = DetectHelperMultiBufferMpmRegister(
b"sdp.media.encryption_key\0".as_ptr() as *const libc::c_char,
b"sdp.media.encryption_key\0".as_ptr() as *const libc::c_char,
ALPROTO_SIP,
true,
true,
sdp_media_desc_encryption_key_get,
);
}

0 comments on commit b6fe4e7

Please sign in to comment.