Skip to content
10 changes: 5 additions & 5 deletions doc/userguide/devguide/extending/app-layer/transactions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Rule Matching

Transaction progress is also used for certain keywords to know what is the minimum state before we can expect a match: until that, Suricata won't even try to look for the patterns.

As seen in ``DetectAppLayerMpmRegister2`` that has ``int progress`` as parameter, and ``DetectAppLayerInspectEngineRegister2``, which expects ``int tx_min_progress``, for instance. In the code snippet,
As seen in ``DetectAppLayerMpmRegister`` that has ``int progress`` as parameter, and ``DetectAppLayerInspectEngineRegister``, which expects ``int tx_min_progress``, for instance. In the code snippet,
``HTTP2StateDataClient``, ``HTTP2StateDataServer`` and ``0`` are the values passed to the functions - in the last
example, for ``FTPDATA``,
the existence of a transaction implies that a file is being transferred. Hence the ``0`` value.
Expand All @@ -80,18 +80,18 @@ the existence of a transaction implies that a file is being transferred. Hence t
{
.
.
DetectAppLayerMpmRegister2("file_data", SIG_FLAG_TOSERVER, 2,
DetectAppLayerMpmRegister("file_data", SIG_FLAG_TOSERVER, 2,
PrefilterMpmFiledataRegister, NULL,
ALPROTO_HTTP2, HTTP2StateDataClient);
DetectAppLayerMpmRegister2("file_data", SIG_FLAG_TOCLIENT, 2,
DetectAppLayerMpmRegister("file_data", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmFiledataRegister, NULL,
ALPROTO_HTTP2, HTTP2StateDataServer);
.
.
DetectAppLayerInspectEngineRegister2("file_data",
DetectAppLayerInspectEngineRegister("file_data",
ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, HTTP2StateDataServer,
DetectEngineInspectFiledata, NULL);
DetectAppLayerInspectEngineRegister2(
DetectAppLayerInspectEngineRegister(
"file_data", ALPROTO_FTPDATA, SIG_FLAG_TOSERVER, 0, DetectEngineInspectFiledata, NULL);
.
.
Expand Down
54 changes: 46 additions & 8 deletions doc/userguide/rules/dns-keywords.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
DNS Keywords
============

There are some more content modifiers (If you are unfamiliar with
content modifiers, please visit the page :doc:`payload-keywords` These
ones make sure the signature checks a specific part of the
network-traffic.
Suricata supports sticky buffers as well as keywords for efficiently
matching on specific fields in DNS messages.

Note that sticky buffers are expected to be followed by one or more
:doc:`payload-keywords`.

dns.answer.name
---------------

``dns.answer.name`` is a sticky buffer that is used to look at the
name field in DNS answer resource records.

``dns.answer.name`` will look at both requests and responses, so
``flow`` is recommended to confine to a specific direction.

.. note:: At this time ``dns.answer.name`` is only supported for
responses, but supporting it in requests is planned.

The buffer being matched on contains the complete re-assembled
resource name, for example "www.suricata.io".

``dns.answer.name`` supports :doc:`multi-buffer-matching`.

dns.opcode
----------
Expand Down Expand Up @@ -32,9 +50,10 @@ Match on DNS requests where the **opcode** is NOT 0::
dns.query
---------

With **dns.query** the DNS request queries are inspected. The dns.query
keyword works a bit different from the normal content modifiers. When
used in a rule all contents following it are affected by it. Example:
With **dns.query** the DNS request query names are inspected. The
dns.query keyword works a bit different from the normal content
Copy link
Member

@victorjulien victorjulien Nov 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"this works a bit different"-bit could be removed. It's just about sticky buffer vs content modifier

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given we're at 8 maybe we should clean this up. Just refer to it as a sticky buffer and not much more?

modifiers. When used in a rule all contents following it are affected
by it. Example:

alert dns any any -> any any (msg:"Test dns.query option";
dns.query; content:"google"; nocase; sid:1;)
Expand All @@ -46,6 +65,10 @@ is used or it reaches the end of the rule.

.. note:: **dns.query** is equivalent to the older **dns_query**.

.. note:: **dns.query** will only match on DNS request messages, to
also match on DNS response message, see
`dns.query.name`_.

Normalized Buffer
~~~~~~~~~~~~~~~~~

Expand All @@ -71,4 +94,19 @@ DNS query on the wire (snippet)::
Multiple Buffer Matching
~~~~~~~~~~~~~~~~~~~~~~~~

``dns.query`` supports multiple buffer matching, see :doc:`multi-buffer-matching`.
``dns.query`` supports multiple buffer matching, see :doc:`multi-buffer-matching`.

dns.query.name
---------------

``dns.query.name`` is a sticky buffer that is used to look at the name
field in DNS query (question) resource records. It is nearly identical
to ``dns.query`` but supports both DNS requests and responses.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guess this makes things clear enough.


``dns.query.name`` will look at both requests and responses, so
``flow`` is recommended to confine to a specific direction.

The buffer being matched on contains the complete re-assembled
resource name, for example "www.suricata.io".

``dns.query.name`` supports :doc:`multi-buffer-matching`.
43 changes: 43 additions & 0 deletions rust/src/dns/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,49 @@ pub unsafe extern "C" fn rs_dns_tx_get_query_name(
return 0;
}

/// Get the DNS query name at index i.
#[no_mangle]
pub unsafe extern "C" fn SCDnsTxGetQueryName(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we break the rust style here (and previously below)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the off by one on the indent? Not sure how that happened, I rust formatted the new code, but didn't take in some new formatting.

tx: &mut DNSTransaction, to_client: bool, i: u32, buf: *mut *const u8, len: *mut u32,
) -> bool {
let queries = if to_client {
tx.response.as_ref().map(|response| &response.queries)
} else {
tx.request.as_ref().map(|request| &request.queries)
};
let index = i as usize;

if let Some(queries) = queries {
if let Some(query) = queries.get(index) {
if !query.name.is_empty() {
*buf = query.name.as_ptr();
*len = query.name.len() as u32;
return true;
}
}
}

false
}

/// Get the DNS response answer name and index i.
#[no_mangle]
pub unsafe extern "C" fn SCDnsTxGetAnswerName(
tx: &mut DNSTransaction, i: u32, buf: *mut *const u8, len: *mut u32,
) -> bool {
let index = i as usize;
if let Some(response) = &tx.response {
if let Some(name) = response.answers.get(index).map(|answer| &answer.name) {
if !name.is_empty() {
*buf = name.as_ptr();
*len = name.len() as u32;
return true;
}
}
}
false
}

/// Get the DNS transaction ID of a transaction.
//
/// extern uint16_t rs_dns_tx_get_tx_id(RSDNSTransaction *);
Expand Down
4 changes: 4 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ noinst_HEADERS = \
detect-detection-filter.h \
detect-distance.h \
detect-dnp3.h \
detect-dns-answer-name.h \
detect-dns-opcode.h \
detect-dns-query.h \
detect-dns-query-name.h \
detect-dsize.h \
detect-engine-address.h \
detect-engine-address-ipv4.h \
Expand Down Expand Up @@ -732,8 +734,10 @@ libsuricata_c_a_SOURCES = \
detect-detection-filter.c \
detect-distance.c \
detect-dnp3.c \
detect-dns-answer-name.c \
detect-dns-opcode.c \
detect-dns-query.c \
detect-dns-query-name.c \
detect-dsize.c \
detect-engine-address.c \
detect-engine-address-ipv4.c \
Expand Down
4 changes: 2 additions & 2 deletions src/detect-app-layer-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ void DetectAppLayerEventRegister(void)
sigmatch_table[DETECT_AL_APP_LAYER_EVENT].Setup = DetectAppLayerEventSetup;
sigmatch_table[DETECT_AL_APP_LAYER_EVENT].Free = DetectAppLayerEventFree;

DetectAppLayerInspectEngineRegister2("app-layer-events", ALPROTO_UNKNOWN, SIG_FLAG_TOSERVER, 0,
DetectAppLayerInspectEngineRegister("app-layer-events", ALPROTO_UNKNOWN, SIG_FLAG_TOSERVER, 0,
DetectEngineAptEventInspect, NULL);
DetectAppLayerInspectEngineRegister2("app-layer-events", ALPROTO_UNKNOWN, SIG_FLAG_TOCLIENT, 0,
DetectAppLayerInspectEngineRegister("app-layer-events", ALPROTO_UNKNOWN, SIG_FLAG_TOCLIENT, 0,
DetectEngineAptEventInspect, NULL);

g_applayer_events_list_id = DetectBufferTypeGetByName("app-layer-events");
Expand Down
8 changes: 4 additions & 4 deletions src/detect-cipservice.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ void DetectCipServiceRegister(void)
sigmatch_table[DETECT_CIPSERVICE].RegisterTests
= DetectCipServiceRegisterTests;
#endif
DetectAppLayerInspectEngineRegister2(
DetectAppLayerInspectEngineRegister(
"cip", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, DetectEngineInspectCIP, NULL);
DetectAppLayerInspectEngineRegister2(
DetectAppLayerInspectEngineRegister(
"cip", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectCIP, NULL);

g_cip_buffer_id = DetectBufferTypeGetByName("cip");
Expand Down Expand Up @@ -316,9 +316,9 @@ void DetectEnipCommandRegister(void)
sigmatch_table[DETECT_ENIPCOMMAND].RegisterTests
= DetectEnipCommandRegisterTests;
#endif
DetectAppLayerInspectEngineRegister2(
DetectAppLayerInspectEngineRegister(
"enip", ALPROTO_ENIP, SIG_FLAG_TOSERVER, 0, DetectEngineInspectENIP, NULL);
DetectAppLayerInspectEngineRegister2(
DetectAppLayerInspectEngineRegister(
"enip", ALPROTO_ENIP, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectENIP, NULL);

g_enip_buffer_id = DetectBufferTypeGetByName("enip");
Expand Down
8 changes: 4 additions & 4 deletions src/detect-dce-iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ void DetectDceIfaceRegister(void)

g_dce_generic_list_id = DetectBufferTypeRegister("dce_generic");

DetectAppLayerInspectEngineRegister2("dce_generic", ALPROTO_DCERPC, SIG_FLAG_TOSERVER, 0,
DetectAppLayerInspectEngineRegister("dce_generic", ALPROTO_DCERPC, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister2(
DetectAppLayerInspectEngineRegister(
"dce_generic", ALPROTO_SMB, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL);

DetectAppLayerInspectEngineRegister2("dce_generic", ALPROTO_DCERPC, SIG_FLAG_TOCLIENT, 0,
DetectAppLayerInspectEngineRegister("dce_generic", ALPROTO_DCERPC, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister2(
DetectAppLayerInspectEngineRegister(
"dce_generic", ALPROTO_SMB, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL);
}

Expand Down
46 changes: 17 additions & 29 deletions src/detect-dce-stub-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,35 +125,23 @@ void DetectDceStubDataRegister(void)
#endif
sigmatch_table[DETECT_DCE_STUB_DATA].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER;

DetectAppLayerInspectEngineRegister2(BUFFER_NAME,
ALPROTO_SMB, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric,
GetSMBData);
DetectAppLayerMpmRegister2(BUFFER_NAME, SIG_FLAG_TOSERVER, 2,
PrefilterGenericMpmRegister, GetSMBData,
ALPROTO_SMB, 0);
DetectAppLayerInspectEngineRegister2(BUFFER_NAME,
ALPROTO_SMB, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric,
GetSMBData);
DetectAppLayerMpmRegister2(BUFFER_NAME, SIG_FLAG_TOCLIENT, 2,
PrefilterGenericMpmRegister, GetSMBData,
ALPROTO_SMB, 0);

DetectAppLayerInspectEngineRegister2(BUFFER_NAME,
ALPROTO_DCERPC, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric,
GetDCEData);
DetectAppLayerMpmRegister2(BUFFER_NAME, SIG_FLAG_TOSERVER, 2,
PrefilterGenericMpmRegister, GetDCEData,
ALPROTO_DCERPC, 0);
DetectAppLayerInspectEngineRegister2(BUFFER_NAME,
ALPROTO_DCERPC, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric,
GetDCEData);
DetectAppLayerMpmRegister2(BUFFER_NAME, SIG_FLAG_TOCLIENT, 2,
PrefilterGenericMpmRegister, GetDCEData,
ALPROTO_DCERPC, 0);
DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_SMB, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric, GetSMBData);
DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetSMBData, ALPROTO_SMB, 0);
DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_SMB, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric, GetSMBData);
DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
GetSMBData, ALPROTO_SMB, 0);

DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_DCERPC, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric, GetDCEData);
DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetDCEData, ALPROTO_DCERPC, 0);
DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_DCERPC, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric, GetDCEData);
DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
GetDCEData, ALPROTO_DCERPC, 0);

g_dce_stub_data_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
}
Expand Down
4 changes: 2 additions & 2 deletions src/detect-dhcp-leasetime.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ void DetectDHCPLeaseTimeRegister(void)
sigmatch_table[DETECT_AL_DHCP_LEASETIME].Setup = DetectDHCPLeaseTimeSetup;
sigmatch_table[DETECT_AL_DHCP_LEASETIME].Free = DetectDHCPLeaseTimeFree;

DetectAppLayerInspectEngineRegister2("dhcp.leasetime", ALPROTO_DHCP, SIG_FLAG_TOSERVER, 0,
DetectAppLayerInspectEngineRegister("dhcp.leasetime", ALPROTO_DHCP, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectGenericList, NULL);

DetectAppLayerInspectEngineRegister2("dhcp.leasetime", ALPROTO_DHCP, SIG_FLAG_TOCLIENT, 0,
DetectAppLayerInspectEngineRegister("dhcp.leasetime", ALPROTO_DHCP, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectGenericList, NULL);

g_buffer_id = DetectBufferTypeGetByName("dhcp.leasetime");
Expand Down
4 changes: 2 additions & 2 deletions src/detect-dhcp-rebinding-time.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@ void DetectDHCPRebindingTimeRegister(void)
sigmatch_table[DETECT_AL_DHCP_REBINDING_TIME].Setup = DetectDHCPRebindingTimeSetup;
sigmatch_table[DETECT_AL_DHCP_REBINDING_TIME].Free = DetectDHCPRebindingTimeFree;

DetectAppLayerInspectEngineRegister2("dhcp.rebinding-time", ALPROTO_DHCP, SIG_FLAG_TOSERVER, 0,
DetectAppLayerInspectEngineRegister("dhcp.rebinding-time", ALPROTO_DHCP, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectGenericList, NULL);

DetectAppLayerInspectEngineRegister2("dhcp.rebinding-time", ALPROTO_DHCP, SIG_FLAG_TOCLIENT, 0,
DetectAppLayerInspectEngineRegister("dhcp.rebinding-time", ALPROTO_DHCP, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectGenericList, NULL);

g_buffer_id = DetectBufferTypeGetByName("dhcp.rebinding-time");
Expand Down
4 changes: 2 additions & 2 deletions src/detect-dhcp-renewal-time.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ void DetectDHCPRenewalTimeRegister(void)
sigmatch_table[DETECT_AL_DHCP_RENEWAL_TIME].Setup = DetectDHCPRenewalTimeSetup;
sigmatch_table[DETECT_AL_DHCP_RENEWAL_TIME].Free = DetectDHCPRenewalTimeFree;

DetectAppLayerInspectEngineRegister2("dhcp.renewal-time", ALPROTO_DHCP, SIG_FLAG_TOSERVER, 0,
DetectAppLayerInspectEngineRegister("dhcp.renewal-time", ALPROTO_DHCP, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectGenericList, NULL);

DetectAppLayerInspectEngineRegister2("dhcp.renewal-time", ALPROTO_DHCP, SIG_FLAG_TOCLIENT, 0,
DetectAppLayerInspectEngineRegister("dhcp.renewal-time", ALPROTO_DHCP, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectGenericList, NULL);

g_buffer_id = DetectBufferTypeGetByName("dhcp.renewal-time");
Expand Down
28 changes: 11 additions & 17 deletions src/detect-dnp3.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,21 +551,15 @@ static void DetectDNP3DataRegister(void)
sigmatch_table[DETECT_AL_DNP3DATA].Setup = DetectDNP3DataSetup;
sigmatch_table[DETECT_AL_DNP3DATA].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER;

DetectAppLayerInspectEngineRegister2("dnp3_data",
ALPROTO_DNP3, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric,
GetDNP3Data);
DetectAppLayerMpmRegister2("dnp3_data", SIG_FLAG_TOSERVER, 2,
PrefilterGenericMpmRegister, GetDNP3Data,
ALPROTO_DNP3, 0);

DetectAppLayerInspectEngineRegister2("dnp3_data",
ALPROTO_DNP3, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric,
GetDNP3Data);
DetectAppLayerMpmRegister2("dnp3_data", SIG_FLAG_TOCLIENT, 2,
PrefilterGenericMpmRegister, GetDNP3Data,
ALPROTO_DNP3, 0);
DetectAppLayerInspectEngineRegister("dnp3_data", ALPROTO_DNP3, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric, GetDNP3Data);
DetectAppLayerMpmRegister("dnp3_data", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetDNP3Data, ALPROTO_DNP3, 0);

DetectAppLayerInspectEngineRegister("dnp3_data", ALPROTO_DNP3, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric, GetDNP3Data);
DetectAppLayerMpmRegister("dnp3_data", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
GetDNP3Data, ALPROTO_DNP3, 0);

g_dnp3_data_buffer_id = DetectBufferTypeGetByName("dnp3_data");
SCReturn;
Expand All @@ -580,9 +574,9 @@ void DetectDNP3Register(void)
DetectDNP3ObjRegister();

/* Register the list of func, ind and obj. */
DetectAppLayerInspectEngineRegister2(
DetectAppLayerInspectEngineRegister(
"dnp3", ALPROTO_DNP3, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister2(
DetectAppLayerInspectEngineRegister(
"dnp3", ALPROTO_DNP3, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL);

g_dnp3_match_buffer_id = DetectBufferTypeRegister("dnp3");
Expand Down
Loading