Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 8 additions & 1 deletion doc/userguide/upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Upgrading to 7.0.8
- Unknown requirements in the ``requires`` keyword will now be treated
as unsatisfied requirements, causing the rule to not be loaded. See
:ref:`keyword_requires`. To opt out of this change and to ignore
uknown requirements, effectively treating them as satified the
unknown requirements, effectively treating them as satisfied the
``ignore-unknown-requirements`` configuration option can be used.

Command line example::
Expand All @@ -66,6 +66,13 @@ Upgrading to 7.0.8
the engine will NOT log any transaction metadata if there is more than one
live transaction, to reduce the chances of logging unrelated data.** This may
lead to what looks like a regression in behavior, but it is a considered choice.
- The configuration setting controlling stream checksum checks no longer affects
checksum keyword validation. In previous Suricata versions, when ``stream.checksum-validation``
was set to ``no``, the checksum keywords (e.g., ``ipv4-csum``, ``tcpv4-csum``, etc)
will always consider it valid; e.g., ``tcpv4-csum: invalid`` will never match. Now,
``stream.checksum-validation`` no longer affects the checksum rule keywords.
E.g., ``ipv4-csum: valid`` will only match if the check sum is valid, even when engine
checksum validations are disabled.

Upgrading 6.0 to 7.0
--------------------
Expand Down
29 changes: 7 additions & 22 deletions rust/src/sip/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ use std::ptr;

#[no_mangle]
pub unsafe extern "C" fn rs_sip_tx_get_method(
tx: &mut SIPTransaction,
buffer: *mut *const u8,
buffer_len: *mut u32,
tx: &mut SIPTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
) -> u8 {
if let Some(ref r) = tx.request {
let m = &r.method;
Expand All @@ -44,9 +42,7 @@ pub unsafe extern "C" fn rs_sip_tx_get_method(

#[no_mangle]
pub unsafe extern "C" fn rs_sip_tx_get_uri(
tx: &mut SIPTransaction,
buffer: *mut *const u8,
buffer_len: *mut u32,
tx: &mut SIPTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
) -> u8 {
if let Some(ref r) = tx.request {
let p = &r.path;
Expand All @@ -65,10 +61,7 @@ pub unsafe extern "C" fn rs_sip_tx_get_uri(

#[no_mangle]
pub unsafe extern "C" fn rs_sip_tx_get_protocol(
tx: &mut SIPTransaction,
buffer: *mut *const u8,
buffer_len: *mut u32,
direction: u8,
tx: &mut SIPTransaction, buffer: *mut *const u8, buffer_len: *mut u32, direction: u8,
) -> u8 {
match direction.into() {
Direction::ToServer => {
Expand Down Expand Up @@ -101,9 +94,7 @@ pub unsafe extern "C" fn rs_sip_tx_get_protocol(

#[no_mangle]
pub unsafe extern "C" fn rs_sip_tx_get_stat_code(
tx: &mut SIPTransaction,
buffer: *mut *const u8,
buffer_len: *mut u32,
tx: &mut SIPTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
) -> u8 {
if let Some(ref r) = tx.response {
let c = &r.code;
Expand All @@ -122,9 +113,7 @@ pub unsafe extern "C" fn rs_sip_tx_get_stat_code(

#[no_mangle]
pub unsafe extern "C" fn rs_sip_tx_get_stat_msg(
tx: &mut SIPTransaction,
buffer: *mut *const u8,
buffer_len: *mut u32,
tx: &mut SIPTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
) -> u8 {
if let Some(ref r) = tx.response {
let re = &r.reason;
Expand All @@ -143,9 +132,7 @@ pub unsafe extern "C" fn rs_sip_tx_get_stat_msg(

#[no_mangle]
pub unsafe extern "C" fn rs_sip_tx_get_request_line(
tx: &mut SIPTransaction,
buffer: *mut *const u8,
buffer_len: *mut u32,
tx: &mut SIPTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
) -> u8 {
if let Some(ref r) = tx.request_line {
if !r.is_empty() {
Expand All @@ -163,9 +150,7 @@ pub unsafe extern "C" fn rs_sip_tx_get_request_line(

#[no_mangle]
pub unsafe extern "C" fn rs_sip_tx_get_response_line(
tx: &mut SIPTransaction,
buffer: *mut *const u8,
buffer_len: *mut u32,
tx: &mut SIPTransaction, buffer: *mut *const u8, buffer_len: *mut u32,
) -> u8 {
if let Some(ref r) = tx.response_line {
if !r.is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion rust/src/sip/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ fn log(tx: &SIPTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> {
#[no_mangle]
pub extern "C" fn rs_sip_log_json(tx: &mut SIPTransaction, js: &mut JsonBuilder) -> bool {
log(tx, js).is_ok()
}
}
42 changes: 32 additions & 10 deletions rust/src/sip/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
* 02110-1301, USA.
*/

// written by Giuseppe Longo <giuseppe@glono.it>
// written by Giuseppe Longo <giuseppe@glongo.it>

use nom7::bytes::streaming::{take, take_while, take_while1};
use nom7::bytes::streaming::{tag, take, take_while, take_while1};
use nom7::character::streaming::{char, crlf};
use nom7::character::{is_alphabetic, is_alphanumeric, is_space};
use nom7::character::{is_alphabetic, is_alphanumeric, is_digit, is_space};
use nom7::combinator::map_res;
use nom7::sequence::delimited;
use nom7::{Err, IResult, Needed};
Expand Down Expand Up @@ -57,9 +57,13 @@ pub struct Response {
pub body_len: u16,
}

/**
* Valid tokens and chars are defined in RFC3261:
* https://www.rfc-editor.org/rfc/rfc3261#section-25.1
*/
#[inline]
fn is_token_char(b: u8) -> bool {
is_alphanumeric(b) || b"!%'*+-._`".contains(&b)
is_alphanumeric(b) || b"!%'*+-._`~".contains(&b)
}

#[inline]
Expand All @@ -69,12 +73,12 @@ fn is_method_char(b: u8) -> bool {

#[inline]
fn is_request_uri_char(b: u8) -> bool {
is_alphanumeric(b) || is_token_char(b) || b"~#@:".contains(&b)
is_alphanumeric(b) || is_token_char(b) || b"~#@:;=?+&$,/".contains(&b)
}

#[inline]
fn is_version_char(b: u8) -> bool {
is_alphanumeric(b) || b"./".contains(&b)
is_digit(b) || b".".contains(&b)
}

#[inline]
Expand Down Expand Up @@ -107,7 +111,7 @@ pub fn sip_parse_request(oi: &[u8]) -> IResult<&[u8], Request> {
Request {
method: method.into(),
path: path.into(),
version: version.into(),
version,
headers,

request_line_len: request_line_len as u16,
Expand All @@ -133,7 +137,7 @@ pub fn sip_parse_response(oi: &[u8]) -> IResult<&[u8], Response> {
Ok((
bi,
Response {
version: version.into(),
version,
code: code.into(),
reason: reason.into(),

Expand All @@ -156,8 +160,10 @@ fn parse_request_uri(i: &[u8]) -> IResult<&[u8], &str> {
}

#[inline]
fn parse_version(i: &[u8]) -> IResult<&[u8], &str> {
map_res(take_while1(is_version_char), std::str::from_utf8)(i)
fn parse_version(i: &[u8]) -> IResult<&[u8], String> {
let (i, prefix) = map_res(tag("SIP/"), std::str::from_utf8)(i)?;
let (i, version) = map_res(take_while1(is_version_char), std::str::from_utf8)(i)?;
Ok((i, format!("{}{}", prefix, version)))
}

#[inline]
Expand Down Expand Up @@ -322,4 +328,20 @@ mod tests {
}
}
}

#[test]
fn test_parse_invalid_version() {
let buf: &[u8] = "HTTP/1.1\r\n".as_bytes();

// This test must fail if 'HTTP/1.1' is accepted
assert!(parse_version(buf).is_err());
}

#[test]
fn test_parse_valid_version() {
let buf: &[u8] = "SIP/2.0\r\n".as_bytes();

let (_rem, result) = parse_version(buf).unwrap();
assert_eq!(result, "SIP/2.0");
}
}
79 changes: 43 additions & 36 deletions rust/src/sip/sip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

// written by Giuseppe Longo <giuseppe@glongo.it>

use crate::frames::*;
use crate::applayer::{self, *};
use crate::core;
use crate::core::{AppProto, Flow, ALPROTO_UNKNOWN};
use crate::frames::*;
use crate::sip::parser::*;
use nom7::Err;
use std;
Expand Down Expand Up @@ -96,10 +96,7 @@ impl SIPState {
}

fn free_tx(&mut self, tx_id: u64) {
let tx = self
.transactions
.iter()
.position(|tx| tx.id == tx_id + 1);
let tx = self.transactions.iter().position(|tx| tx.id == tx_id + 1);
debug_assert!(tx.is_some());
if let Some(idx) = tx {
let _ = self.transactions.remove(idx);
Expand Down Expand Up @@ -149,7 +146,13 @@ impl SIPState {

fn parse_response(&mut self, flow: *const core::Flow, stream_slice: StreamSlice) -> bool {
let input = stream_slice.as_slice();
let _pdu = Frame::new(flow, &stream_slice, input, input.len() as i64, SIPFrameType::Pdu as u8);
let _pdu = Frame::new(
flow,
&stream_slice,
input,
input.len() as i64,
SIPFrameType::Pdu as u8,
);
SCLogDebug!("tc: pdu {:?}", _pdu);

match sip_parse_response(input) {
Expand Down Expand Up @@ -224,20 +227,40 @@ fn sip_frames_ts(flow: *const core::Flow, stream_slice: &StreamSlice, r: &Reques

fn sip_frames_tc(flow: *const core::Flow, stream_slice: &StreamSlice, r: &Response) {
let oi = stream_slice.as_slice();
let _f = Frame::new(flow, stream_slice, oi, r.response_line_len as i64, SIPFrameType::ResponseLine as u8);
let hi = &oi[r.response_line_len as usize ..];
let _f = Frame::new(
flow,
stream_slice,
oi,
r.response_line_len as i64,
SIPFrameType::ResponseLine as u8,
);
let hi = &oi[r.response_line_len as usize..];
SCLogDebug!("tc: response_line {:?}", _f);
let _f = Frame::new(flow, stream_slice, hi, r.headers_len as i64, SIPFrameType::ResponseHeaders as u8);
let _f = Frame::new(
flow,
stream_slice,
hi,
r.headers_len as i64,
SIPFrameType::ResponseHeaders as u8,
);
SCLogDebug!("tc: response_headers {:?}", _f);
if r.body_len > 0 {
let bi = &oi[r.body_offset as usize ..];
let _f = Frame::new(flow, stream_slice, bi, r.body_len as i64, SIPFrameType::ResponseBody as u8);
let bi = &oi[r.body_offset as usize..];
let _f = Frame::new(
flow,
stream_slice,
bi,
r.body_len as i64,
SIPFrameType::ResponseBody as u8,
);
SCLogDebug!("tc: response_body {:?}", _f);
}
}

#[no_mangle]
pub extern "C" fn rs_sip_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void {
pub extern "C" fn rs_sip_state_new(
_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto,
) -> *mut std::os::raw::c_void {
let state = SIPState::new();
let boxed = Box::new(state);
return Box::into_raw(boxed) as *mut _;
Expand All @@ -251,8 +274,7 @@ pub extern "C" fn rs_sip_state_free(state: *mut std::os::raw::c_void) {

#[no_mangle]
pub unsafe extern "C" fn rs_sip_state_get_tx(
state: *mut std::os::raw::c_void,
tx_id: u64,
state: *mut std::os::raw::c_void, tx_id: u64,
) -> *mut std::os::raw::c_void {
let state = cast_pointer!(state, SIPState);
match state.get_tx_by_id(tx_id) {
Expand All @@ -275,8 +297,7 @@ pub unsafe extern "C" fn rs_sip_state_tx_free(state: *mut std::os::raw::c_void,

#[no_mangle]
pub extern "C" fn rs_sip_tx_get_alstate_progress(
_tx: *mut std::os::raw::c_void,
_direction: u8,
_tx: *mut std::os::raw::c_void, _direction: u8,
) -> std::os::raw::c_int {
1
}
Expand All @@ -285,11 +306,7 @@ static mut ALPROTO_SIP: AppProto = ALPROTO_UNKNOWN;

#[no_mangle]
pub unsafe extern "C" fn rs_sip_probing_parser_ts(
_flow: *const Flow,
_direction: u8,
input: *const u8,
input_len: u32,
_rdir: *mut u8,
_flow: *const Flow, _direction: u8, input: *const u8, input_len: u32, _rdir: *mut u8,
) -> AppProto {
let buf = build_slice!(input, input_len as usize);
if sip_parse_request(buf).is_ok() {
Expand All @@ -300,11 +317,7 @@ pub unsafe extern "C" fn rs_sip_probing_parser_ts(

#[no_mangle]
pub unsafe extern "C" fn rs_sip_probing_parser_tc(
_flow: *const Flow,
_direction: u8,
input: *const u8,
input_len: u32,
_rdir: *mut u8,
_flow: *const Flow, _direction: u8, input: *const u8, input_len: u32, _rdir: *mut u8,
) -> AppProto {
let buf = build_slice!(input, input_len as usize);
if sip_parse_response(buf).is_ok() {
Expand All @@ -315,23 +328,17 @@ pub unsafe extern "C" fn rs_sip_probing_parser_tc(

#[no_mangle]
pub unsafe extern "C" fn rs_sip_parse_request(
flow: *const core::Flow,
state: *mut std::os::raw::c_void,
_pstate: *mut std::os::raw::c_void,
stream_slice: StreamSlice,
_data: *const std::os::raw::c_void,
flow: *const core::Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
) -> AppLayerResult {
let state = cast_pointer!(state, SIPState);
state.parse_request(flow, stream_slice).into()
}

#[no_mangle]
pub unsafe extern "C" fn rs_sip_parse_response(
flow: *const core::Flow,
state: *mut std::os::raw::c_void,
_pstate: *mut std::os::raw::c_void,
stream_slice: StreamSlice,
_data: *const std::os::raw::c_void,
flow: *const core::Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
) -> AppLayerResult {
let state = cast_pointer!(state, SIPState);
state.parse_response(flow, stream_slice).into()
Expand Down
2 changes: 1 addition & 1 deletion src/app-layer-detect-proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ static AppProto AppLayerProtoDetectPPGetProto(Flow *f, const uint8_t *buf, uint3
else if (pp_port_sp)
mask = pp_port_sp->alproto_mask;

if (alproto_masks[0] == mask) {
if ((alproto_masks[0] & mask) == mask) {
FLOW_SET_PP_DONE(f, dir);
SCLogDebug("%s, mask is now %08x, needed %08x, so done",
(dir == STREAM_TOSERVER) ? "toserver":"toclient",
Expand Down
4 changes: 0 additions & 4 deletions src/stream-tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5815,11 +5815,7 @@ TmEcode StreamTcp (ThreadVars *tv, Packet *p, void *data, PacketQueueNoLock *pq)
StatsIncr(tv, stt->counter_tcp_invalid_checksum);
return TM_ECODE_OK;
}
} else {
p->flags |= PKT_IGNORE_CHECKSUM;
}
} else {
p->flags |= PKT_IGNORE_CHECKSUM; //TODO check that this is set at creation
}
AppLayerProfilingReset(stt->ra_ctx->app_tctx);

Expand Down
Loading