Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
2 changes: 1 addition & 1 deletion rust/rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Rust format configuration file. If empty, then this is a message that
# we expect the default formatting rules to be used.

fn_args_layout = "compressed"
fn_params_layout = "compressed"
64 changes: 28 additions & 36 deletions rust/src/dns/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,44 +156,36 @@ mod test {

#[test]
fn test_match_opcode() {
assert!(
match_opcode(
&DetectDnsOpcode {
negate: false,
opcode: 0,
},
0b0000_0000_0000_0000,
)
);
assert!(match_opcode(
&DetectDnsOpcode {
negate: false,
opcode: 0,
},
0b0000_0000_0000_0000,
));

assert!(
!match_opcode(
&DetectDnsOpcode {
negate: true,
opcode: 0,
},
0b0000_0000_0000_0000,
)
);
assert!(!match_opcode(
&DetectDnsOpcode {
negate: true,
opcode: 0,
},
0b0000_0000_0000_0000,
));

assert!(
match_opcode(
&DetectDnsOpcode {
negate: false,
opcode: 4,
},
0b0010_0000_0000_0000,
)
);
assert!(match_opcode(
&DetectDnsOpcode {
negate: false,
opcode: 4,
},
0b0010_0000_0000_0000,
));

assert!(
!match_opcode(
&DetectDnsOpcode {
negate: true,
opcode: 4,
},
0b0010_0000_0000_0000,
)
);
assert!(!match_opcode(
&DetectDnsOpcode {
negate: true,
opcode: 4,
},
0b0010_0000_0000_0000,
));
}
}
83 changes: 61 additions & 22 deletions rust/src/dns/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,7 @@ pub struct DNSAnswerEntry {
}

#[derive(Debug)]
pub struct DNSRequest {
pub header: DNSHeader,
pub queries: Vec<DNSQueryEntry>,
}

#[derive(Debug)]
pub struct DNSResponse {
pub struct DNSMessage {
pub header: DNSHeader,
pub queries: Vec<DNSQueryEntry>,
pub answers: Vec<DNSAnswerEntry>,
Expand All @@ -237,8 +231,8 @@ pub struct DNSResponse {
#[derive(Debug, Default)]
pub struct DNSTransaction {
pub id: u64,
pub request: Option<DNSRequest>,
pub response: Option<DNSResponse>,
pub request: Option<DNSMessage>,
pub response: Option<DNSMessage>,
pub tx_data: AppLayerTxData,
}

Expand All @@ -250,10 +244,10 @@ impl Transaction for DNSTransaction {

impl DNSTransaction {
pub fn new(direction: Direction) -> Self {
Self {
tx_data: AppLayerTxData::for_direction(direction),
Self {
tx_data: AppLayerTxData::for_direction(direction),
..Default::default()
}
}
}

/// Get the DNS transactions ID (not the internal tracking ID).
Expand Down Expand Up @@ -402,7 +396,7 @@ impl DNSState {
return !is_tcp;
};

match parser::dns_parse_request_body(body, input, header) {
match parser::dns_parse_body(body, input, header) {
Ok((_, request)) => {
if request.header.flags & 0x8000 != 0 {
SCLogDebug!("DNS message is not a request");
Expand Down Expand Up @@ -474,7 +468,7 @@ impl DNSState {
return !is_tcp;
};

match parser::dns_parse_response_body(body, input, header) {
match parser::dns_parse_body(body, input, header) {
Ok((_, response)) => {
SCLogDebug!("Response header flags: {}", response.header.flags);

Expand Down Expand Up @@ -702,14 +696,9 @@ fn probe(input: &[u8], dlen: usize) -> (bool, bool, bool) {
}
}

match parser::dns_parse_request(input) {
Ok((_, request)) => {
return probe_header_validity(&request.header, dlen);
}
Err(Err::Incomplete(_)) => match parser::dns_parse_header(input) {
Ok((_, header)) => {
return probe_header_validity(&header, dlen);
}
match parser::dns_parse_header(input) {
Ok((body, header)) => match parser::dns_parse_body(body, input, header) {
Ok((_, request)) => probe_header_validity(&request.header, dlen),
Err(Err::Incomplete(_)) => (false, false, true),
Err(_) => (false, false, false),
},
Expand Down Expand Up @@ -881,6 +870,56 @@ 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(
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, to_client: bool, i: u32, buf: *mut *const u8, len: *mut u32,
) -> bool {
let answers = if to_client {
tx.response.as_ref().map(|response| &response.answers)
} else {
tx.request.as_ref().map(|request| &request.answers)
};
let index = i as usize;

if let Some(answers) = answers {
if let Some(answer) = answers.get(index) {
if !answer.name.is_empty() {
*buf = answer.name.as_ptr();
*len = answer.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
17 changes: 11 additions & 6 deletions rust/src/dns/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ fn dns_log_json_answer_detail(answer: &DNSAnswerEntry) -> Result<JsonBuilder, Js
}

fn dns_log_json_answer(
js: &mut JsonBuilder, response: &DNSResponse, flags: u64,
js: &mut JsonBuilder, response: &DNSMessage, flags: u64,
) -> Result<(), JsonError> {
let header = &response.header;

Expand Down Expand Up @@ -524,7 +524,8 @@ fn dns_log_json_answer(
match &answer.data {
DNSRData::A(addr) | DNSRData::AAAA(addr) => {
if !answer_types.contains_key(&type_string) {
answer_types.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
answer_types
.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
}
if let Some(a) = answer_types.get_mut(&type_string) {
a.append_string(&dns_print_addr(addr))?;
Expand All @@ -537,31 +538,35 @@ fn dns_log_json_answer(
| DNSRData::NULL(bytes)
| DNSRData::PTR(bytes) => {
if !answer_types.contains_key(&type_string) {
answer_types.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
answer_types
.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
}
if let Some(a) = answer_types.get_mut(&type_string) {
a.append_string_from_bytes(bytes)?;
}
}
DNSRData::SOA(soa) => {
if !answer_types.contains_key(&type_string) {
answer_types.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
answer_types
.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
}
if let Some(a) = answer_types.get_mut(&type_string) {
a.append_object(&dns_log_soa(soa)?)?;
}
}
DNSRData::SSHFP(sshfp) => {
if !answer_types.contains_key(&type_string) {
answer_types.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
answer_types
.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
}
if let Some(a) = answer_types.get_mut(&type_string) {
a.append_object(&dns_log_sshfp(sshfp)?)?;
}
}
DNSRData::SRV(srv) => {
if !answer_types.contains_key(&type_string) {
answer_types.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
answer_types
.insert(type_string.to_string(), JsonBuilder::try_new_array()?);
}
if let Some(a) = answer_types.get_mut(&type_string) {
a.append_object(&dns_log_srv(srv)?)?;
Expand Down
Loading