diff --git a/doc/userguide/rules/sip-keywords.rst b/doc/userguide/rules/sip-keywords.rst index be3662b1a5b0..64a67c20d144 100644 --- a/doc/userguide/rules/sip-keywords.rst +++ b/doc/userguide/rules/sip-keywords.rst @@ -13,6 +13,12 @@ sip.stat_code Response sip.stat_msg Response sip.response_line Response sip.protocol Both +sip.from Both +sip.to Both +sip.via Both +sip.user_agent Both +sip.content_type Both +sip.content_length Both ============================== ================== sip.method @@ -177,3 +183,129 @@ Example :: sip.protocol; content:"SIP/2.0" + +sip.from +-------- + +This keyword matches on the From field that can be present in SIP headers. + +Syntax +~~~~~~ + +:: + + sip.from; content: + +Where is the value of the From header. + +Example +~~~~~~~ + +:: + + sip.from; content:"user" + +sip.to +------ + +This keyword matches on the To field that can be present in SIP headers. + +Syntax +~~~~~~ + +:: + + sip.to; content: + +Where is the value of the To header. + +Example +~~~~~~~ + +:: + + sip.to; content:"user" + +sip.via +-------- + +This keyword matches on the Via field that can be present in SIP headers. + +Syntax +~~~~~~ + +:: + + sip.via; content: + +Where is the value of the Via header. + +Example +~~~~~~~ + +:: + + sip.via; content:"SIP/2.0/UDP" + +sip.user_agent +-------------- + +This keyword matches on the User-Agent field that can be present in SIP headers. + +Syntax +~~~~~~ + +:: + + sip.user_agent; content: + +Where is the value of the User-Agent header. + +Example +~~~~~~~ + +:: + + sip.user_agent; content:"Asterisk" + +sip.content_type +---------------- + +This keyword matches on the Content-Type field that can be present in SIP headers. + +Syntax +~~~~~~ + +:: + + sip.content_type; content: + +Where is the value of the Content-Type header. + +Example +~~~~~~~ + +:: + + sip.content_type; content:"application/sdp" + +sip.content_length +------------------ + +This keyword matches on the Content-Length field that can be present in SIP headers. + +Syntax +~~~~~~ + +:: + + sip.content_length; content: + +Where is the value of the Content-Length header. + +Example +~~~~~~~ + +:: + + sip.content_length; content:"200" diff --git a/doc/userguide/upgrade.rst b/doc/userguide/upgrade.rst index 4de3971c94c3..e48edfb6d285 100644 --- a/doc/userguide/upgrade.rst +++ b/doc/userguide/upgrade.rst @@ -60,6 +60,12 @@ Major changes - It is possible to see an increase of alerts, for the same rule-sets, if you use many stream/payload rules, due to Suricata triggering TCP stream reassembly earlier. +- The following sticky buffers for matching SIP headers have been implemented: + - sip.via + - sip.from + - sip.to + - sip.content_type + - sip.content_length Upgrading 6.0 to 7.0 -------------------- diff --git a/rust/src/sip/detect.rs b/rust/src/sip/detect.rs index 91df4fb29932..ecca62285414 100644 --- a/rust/src/sip/detect.rs +++ b/rust/src/sip/detect.rs @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Open Information Security Foundation +/* Copyright (C) 2024 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -19,6 +19,7 @@ use crate::core::Direction; use crate::sip::sip::SIPTransaction; +use std::ffi::CStr; use std::ptr; #[no_mangle] @@ -165,3 +166,32 @@ pub unsafe extern "C" fn rs_sip_tx_get_response_line( return 0; } + +#[no_mangle] +pub unsafe extern "C" fn rs_sip_tx_get_header_value( + tx: &mut SIPTransaction, i: u32, direction: u8, strname: *const std::os::raw::c_char, + buffer: *mut *const u8, buffer_len: *mut u32, +) -> u8 { + let hname: &CStr = CStr::from_ptr(strname); + if let Ok(s) = hname.to_str() { + let headers = match direction.into() { + Direction::ToServer => tx.request.as_ref().map(|r| &r.headers), + Direction::ToClient => tx.response.as_ref().map(|r| &r.headers), + }; + if let Some(headers) = headers { + if let Some(header_vals) = headers.get(s) { + if (i as usize) < header_vals.len() { + let value = &header_vals[i as usize]; + *buffer = value.as_ptr(); + *buffer_len = value.len() as u32; + return 1; + } + } + } + } + + *buffer = ptr::null(); + *buffer_len = 0; + + return 0; +} diff --git a/rust/src/sip/parser.rs b/rust/src/sip/parser.rs index a7314f163914..037ecd292ada 100644 --- a/rust/src/sip/parser.rs +++ b/rust/src/sip/parser.rs @@ -21,7 +21,7 @@ use crate::sdp::parser::{sdp_parse_message, SdpMessage}; use nom7::bytes::streaming::{tag, take, take_while, take_while1}; use nom7::character::streaming::{char, crlf}; use nom7::character::{is_alphabetic, is_alphanumeric, is_digit, is_space}; -use nom7::combinator::{map_res, opt}; +use nom7::combinator::{map, map_res, opt}; use nom7::sequence::delimited; use nom7::{Err, IResult, Needed}; use std; @@ -38,7 +38,7 @@ pub struct Request { pub method: String, pub path: String, pub version: String, - pub headers: HashMap, + pub headers: HashMap>, pub request_line_len: u16, pub headers_len: u16, @@ -52,7 +52,7 @@ pub struct Response { pub version: String, pub code: String, pub reason: String, - + pub headers: HashMap>, pub response_line_len: u16, pub headers_len: u16, pub body_offset: u16, @@ -97,6 +97,22 @@ fn is_header_value(b: u8) -> bool { is_alphanumeric(b) || is_token_char(b) || b"\"#$&(),/;:<=>?@[]{}()^|~\\\t\n\r ".contains(&b) } +fn expand_header_name(h: &str) -> &str { + match h { + "i" => "Call-ID", + "m" => "Contact", + "e" => "Content-Encoding", + "l" => "Content-Length", + "c" => "Content-Type", + "f" => "From", + "s" => "Subject", + "k" => "Supported", + "t" => "To", + "v" => "Via", + _ => h, + } +} + pub fn sip_parse_request(oi: &[u8]) -> IResult<&[u8], Request> { let (i, method) = parse_method(oi)?; let (i, _) = char(' ')(i)?; @@ -135,7 +151,7 @@ pub fn sip_parse_response(oi: &[u8]) -> IResult<&[u8], Response> { let (i, reason) = parse_reason(i)?; let (hi, _) = crlf(i)?; let response_line_len = oi.len() - hi.len(); - let (phi, _headers) = parse_headers(hi)?; + let (phi, headers) = parse_headers(hi)?; let headers_len = hi.len() - phi.len(); let (bi, _) = crlf(phi)?; let body_offset = oi.len() - bi.len(); @@ -146,6 +162,7 @@ pub fn sip_parse_response(oi: &[u8]) -> IResult<&[u8], Response> { version, code: code.into(), reason: reason.into(), + headers, response_line_len: response_line_len as u16, headers_len: headers_len as u16, @@ -199,7 +216,7 @@ fn hcolon(i: &[u8]) -> IResult<&[u8], char> { } fn message_header(i: &[u8]) -> IResult<&[u8], Header> { - let (i, n) = header_name(i)?; + let (i, n) = map(header_name, expand_header_name)(i)?; let (i, _) = hcolon(i)?; let (i, v) = header_value(i)?; let (i, _) = crlf(i)?; @@ -217,8 +234,8 @@ pub fn sip_take_line(i: &[u8]) -> IResult<&[u8], Option> { Ok((i, Some(line.into()))) } -pub fn parse_headers(mut input: &[u8]) -> IResult<&[u8], HashMap> { - let mut headers_map: HashMap = HashMap::new(); +pub fn parse_headers(mut input: &[u8]) -> IResult<&[u8], HashMap>> { + let mut headers_map: HashMap> = HashMap::new(); loop { match crlf(input) as IResult<&[u8], _> { Ok((_, _)) => { @@ -229,7 +246,10 @@ pub fn parse_headers(mut input: &[u8]) -> IResult<&[u8], HashMap Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), }; let (rest, header) = message_header(input)?; - headers_map.insert(header.name, header.value); + headers_map + .entry(header.name) + .or_default() + .push(header.value); input = rest; } @@ -292,7 +312,7 @@ mod tests { assert_eq!(req.method, "REGISTER"); assert_eq!(req.path, "sip:sip.cybercity.dk"); assert_eq!(req.version, "SIP/2.0"); - assert_eq!(req.headers["Content-Length"], "0"); + assert_eq!(req.headers["Content-Length"].first().unwrap(), "0"); } #[test] @@ -308,7 +328,7 @@ mod tests { assert_eq!(req.method, "REGISTER"); assert_eq!(req.path, "sip:sip.cybercity.dk"); assert_eq!(req.version, "SIP/2.0"); - assert_eq!(req.headers["Content-Length"], "4"); + assert_eq!(req.headers["Content-Length"].first().unwrap(), "4"); assert_eq!(body, "ABCD".as_bytes()); } diff --git a/src/Makefile.am b/src/Makefile.am index 5b83d60cfd42..b62c92b99377 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -281,13 +281,21 @@ noinst_HEADERS = \ detect-rpc.h \ detect-sameip.h \ detect-sid.h \ + detect-sip-content-length.h \ + detect-sip-content-type.h \ + detect-sip-headers.h \ + detect-sip-headers-stub.h \ + detect-sip-from.h \ detect-sip-method.h \ detect-sip-protocol.h \ detect-sip-request-line.h \ detect-sip-response-line.h \ detect-sip-stat-code.h \ detect-sip-stat-msg.h \ + detect-sip-to.h \ + detect-sip-ua.h \ detect-sip-uri.h \ + detect-sip-via.h \ detect-smb-ntlmssp.h \ detect-smb-share.h \ detect-smb-version.h \ @@ -880,13 +888,20 @@ libsuricata_c_a_SOURCES = \ detect-rpc.c \ detect-sameip.c \ detect-sid.c \ + detect-sip-content-length.c \ + detect-sip-content-type.c \ + detect-sip-headers.c \ + detect-sip-from.c \ detect-sip-method.c \ detect-sip-protocol.c \ detect-sip-request-line.c \ detect-sip-response-line.c \ detect-sip-stat-code.c \ detect-sip-stat-msg.c \ + detect-sip-to.c \ + detect-sip-ua.c \ detect-sip-uri.c \ + detect-sip-via.c \ detect-smb-ntlmssp.c \ detect-smb-share.c \ detect-smb-version.c \ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 5d4438485811..818c7399f32f 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -207,6 +207,7 @@ #include "detect-sip-stat-msg.h" #include "detect-sip-request-line.h" #include "detect-sip-response-line.h" +#include "detect-sip-headers.h" #include "detect-rfb-secresult.h" #include "detect-rfb-sectype.h" #include "detect-rfb-name.h" @@ -686,6 +687,7 @@ void SigTableSetup(void) DetectSipStatMsgRegister(); DetectSipRequestLineRegister(); DetectSipResponseLineRegister(); + DetectSipHeadersRegister(); DetectRfbSecresultRegister(); DetectRfbSectypeRegister(); DetectRfbNameRegister(); diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index 71af4c3a1659..7748f2d86928 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -275,6 +275,12 @@ enum DetectKeywordId { DETECT_AL_SIP_STAT_MSG, DETECT_AL_SIP_REQUEST_LINE, DETECT_AL_SIP_RESPONSE_LINE, + DETECT_AL_SIP_HEADER_FROM, + DETECT_AL_SIP_HEADER_TO, + DETECT_AL_SIP_HEADER_VIA, + DETECT_AL_SIP_HEADER_UA, + DETECT_AL_SIP_HEADER_CONTENT_TYPE, + DETECT_AL_SIP_HEADER_CONTENT_LENGTH, DETECT_AL_RFB_SECRESULT, DETECT_AL_RFB_SECTYPE, DETECT_AL_RFB_NAME, diff --git a/src/detect-sip-content-length.c b/src/detect-sip-content-length.c new file mode 100644 index 000000000000..ebc5657d2fe3 --- /dev/null +++ b/src/detect-sip-content-length.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Giuseppe Longo + * + * Implements the sip.content_length sticky buffer + */ + +#define KEYWORD_NAME "sip.content_length" +#define KEYWORD_DOC "sip-keywords.html#sip-content-length" +#define BUFFER_NAME "sip.content_length" +#define BUFFER_DESC "sip content-length header" +#define HEADER_NAME "Content-Length" +#define KEYWORD_ID DETECT_AL_SIP_HEADER_CONTENT_LENGTH +#define KEYWORD_TOSERVER 1 +#define KEYWORD_TOCLIENT 1 + +#include "detect-sip-headers-stub.h" +#include "detect-sip-content-length.h" + +void RegisterSipHeadersContentLength(void) +{ + DetectSipHeadersRegisterStub(); +} diff --git a/src/detect-sip-content-length.h b/src/detect-sip-content-length.h new file mode 100644 index 000000000000..1674320c49f6 --- /dev/null +++ b/src/detect-sip-content-length.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + */ + +#ifndef SURICATA_DETECT_SIP_CONTENT_LENGTH_H +#define SURICATA_DETECT_SIP_CONTENT_LENGTH_H + +void RegisterSipHeadersContentLength(void); + +#endif /* SURICATA_DETECT_SIP_CONTENT_LENGTH_H */ diff --git a/src/detect-sip-content-type.c b/src/detect-sip-content-type.c new file mode 100644 index 000000000000..2ab720c93f51 --- /dev/null +++ b/src/detect-sip-content-type.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + * Implements the sip.content_type sticky buffer + */ + +#define KEYWORD_NAME "sip.content_type" +#define KEYWORD_DOC "sip-keywords.html#sip-content-type" +#define BUFFER_NAME "sip.content_type" +#define BUFFER_DESC "sip content-type header" +#define HEADER_NAME "Content-Type" +#define KEYWORD_ID DETECT_AL_SIP_HEADER_CONTENT_TYPE +#define KEYWORD_TOSERVER 1 +#define KEYWORD_TOCLIENT 1 + +#include "detect-sip-headers-stub.h" +#include "detect-sip-content-type.h" + +void RegisterSipHeadersContentType(void) +{ + DetectSipHeadersRegisterStub(); +} diff --git a/src/detect-sip-content-type.h b/src/detect-sip-content-type.h new file mode 100644 index 000000000000..28f20191c5a3 --- /dev/null +++ b/src/detect-sip-content-type.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * + * \author Giuseppe Longo + * + */ + +#ifndef SURICATA_DETECT_SIP_CONTENT_TYPE_H +#define SURICATA_DETECT_SIP_CONTENT_TYPE_H + +void RegisterSipHeadersContentType(void); + +#endif /* SURICATA_DETECT_SIP_CONTENT_TYPE_H */ diff --git a/src/detect-sip-from.c b/src/detect-sip-from.c new file mode 100644 index 000000000000..7a22bca9b37f --- /dev/null +++ b/src/detect-sip-from.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + * Implements the sip.from sticky buffer + */ + +#define KEYWORD_NAME "sip.from" +#define KEYWORD_DOC "sip-keywords.html#sip-from" +#define BUFFER_NAME "sip.from" +#define BUFFER_DESC "sip from header" +#define HEADER_NAME "From" +#define KEYWORD_ID DETECT_AL_SIP_HEADER_FROM +#define KEYWORD_TOSERVER 1 +#define KEYWORD_TOCLIENT 1 + +#include "detect-sip-headers-stub.h" +#include "detect-sip-from.h" + +void RegisterSipHeadersFrom(void) +{ + DetectSipHeadersRegisterStub(); +} diff --git a/src/detect-sip-from.h b/src/detect-sip-from.h new file mode 100644 index 000000000000..faa22cb1d1f1 --- /dev/null +++ b/src/detect-sip-from.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2023 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + */ + +#ifndef SURICATA_DETECT_SIP_FROM_H +#define SURICATA_DETECT_SIP_FROM_H + +void RegisterSipHeadersFrom(void); + +#endif /* SURICATA_DETECT_SIP_FROM_H */ diff --git a/src/detect-sip-headers-stub.h b/src/detect-sip-headers-stub.h new file mode 100644 index 000000000000..375724ad5a9a --- /dev/null +++ b/src/detect-sip-headers-stub.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + * Stub for per SIP header detection keyword. + */ + +#include "suricata-common.h" +#include "flow.h" + +#include "detect.h" +#include "detect-parse.h" +#include "detect-engine.h" +#include "detect-engine-mpm.h" +#include "detect-engine-prefilter.h" +#include "detect-engine-content-inspection.h" + +#include "rust.h" + +static int g_buffer_id = 0; + +#ifdef KEYWORD_TOSERVER +static InspectionBuffer *GetRequestData(DetectEngineThreadCtx *det_ctx, + const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv, + const int list_id, uint32_t local_id) +{ + SCEnter(); + + InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id); + if (buffer->inspect == NULL) { + uint32_t b_len = 0; + const uint8_t *b = NULL; + + if (rs_sip_tx_get_header_value(txv, local_id, STREAM_TOSERVER, HEADER_NAME, &b, &b_len) != + 1) { + InspectionBufferSetupMultiEmpty(buffer); + return NULL; + } + if (b == NULL || b_len == 0) { + InspectionBufferSetupMultiEmpty(buffer); + return NULL; + } + + InspectionBufferSetupMulti(buffer, transforms, b, b_len); + buffer->flags = DETECT_CI_FLAGS_SINGLE; + } + + return buffer; +} + +#endif +#ifdef KEYWORD_TOCLIENT +static InspectionBuffer *GetResponseData(DetectEngineThreadCtx *det_ctx, + const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv, + const int list_id, uint32_t local_id) +{ + SCEnter(); + + InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id); + if (buffer->inspect == NULL) { + uint32_t b_len = 0; + const uint8_t *b = NULL; + + if (rs_sip_tx_get_header_value(txv, local_id, STREAM_TOCLIENT, HEADER_NAME, &b, &b_len) != + 1) { + InspectionBufferSetupMultiEmpty(buffer); + return NULL; + } + if (b == NULL || b_len == 0) { + InspectionBufferSetupMultiEmpty(buffer); + return NULL; + } + + InspectionBufferSetupMulti(buffer, transforms, b, b_len); + buffer->flags = DETECT_CI_FLAGS_SINGLE; + } + + return buffer; +} +#endif + +/** + * \brief this function setup the http.header keyword used in the rule + * + * \param de_ctx Pointer to the Detection Engine Context + * \param s Pointer to the Signature to which the current keyword belongs + * \param str Should hold an empty string always + * + * \retval 0 On success + */ +static int DetectSipHeadersSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str) +{ + if (DetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0) + return -1; + + if (DetectSignatureSetAppProto(s, ALPROTO_SIP) < 0) + return -1; + + return 0; +} + +static void DetectSipHeadersRegisterStub(void) +{ + sigmatch_table[KEYWORD_ID].name = KEYWORD_NAME; + sigmatch_table[KEYWORD_ID].desc = KEYWORD_NAME " sticky buffer for the " BUFFER_DESC; + sigmatch_table[KEYWORD_ID].url = "/rules/" KEYWORD_DOC; + sigmatch_table[KEYWORD_ID].Setup = DetectSipHeadersSetupSticky; + sigmatch_table[KEYWORD_ID].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER; + +#ifdef KEYWORD_TOSERVER + DetectAppLayerMultiRegister( + BUFFER_NAME, ALPROTO_SIP, SIG_FLAG_TOSERVER, 0, GetRequestData, 2, 1); +#endif +#ifdef KEYWORD_TOCLIENT + DetectAppLayerMultiRegister( + BUFFER_NAME, ALPROTO_SIP, SIG_FLAG_TOCLIENT, 0, GetResponseData, 2, 1); +#endif + + DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC); + + DetectBufferTypeSupportsMultiInstance(BUFFER_NAME); + + g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME); +} diff --git a/src/detect-sip-headers.c b/src/detect-sip-headers.c new file mode 100644 index 000000000000..ea00fde0cf28 --- /dev/null +++ b/src/detect-sip-headers.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + */ + +#include "detect-sip-headers.h" +#include "detect-sip-from.h" +#include "detect-sip-to.h" +#include "detect-sip-via.h" +#include "detect-sip-ua.h" +#include "detect-sip-content-type.h" +#include "detect-sip-content-length.h" + +void DetectSipHeadersRegister(void) +{ + RegisterSipHeadersFrom(); + RegisterSipHeadersTo(); + RegisterSipHeadersVia(); + RegisterSipHeadersUa(); + RegisterSipHeadersContentType(); + RegisterSipHeadersContentLength(); +} diff --git a/src/detect-sip-headers.h b/src/detect-sip-headers.h new file mode 100644 index 000000000000..37bbd3af1f18 --- /dev/null +++ b/src/detect-sip-headers.h @@ -0,0 +1,23 @@ +/* Copyright (C) 2023 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __DETECT_SIP_HEADERS_H__ +#define __DETECT_SIP_HEADERS_H__ + +void DetectSipHeadersRegister(void); + +#endif /* __DETECT_SIP_HEADERS_H__ */ diff --git a/src/detect-sip-to.c b/src/detect-sip-to.c new file mode 100644 index 000000000000..73fe74ab4757 --- /dev/null +++ b/src/detect-sip-to.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + * Implements the sip.to sticky buffer + */ + +#define KEYWORD_NAME "sip.to" +#define KEYWORD_DOC "sip-keywords.html#sip-to" +#define BUFFER_NAME "sip.to" +#define BUFFER_DESC "sip to header" +#define HEADER_NAME "To" +#define KEYWORD_ID DETECT_AL_SIP_HEADER_TO +#define KEYWORD_TOSERVER 1 +#define KEYWORD_TOCLIENT 1 + +#include "detect-sip-headers-stub.h" +#include "detect-sip-to.h" + +void RegisterSipHeadersTo(void) +{ + DetectSipHeadersRegisterStub(); +} diff --git a/src/detect-sip-to.h b/src/detect-sip-to.h new file mode 100644 index 000000000000..f4eabcaa76ba --- /dev/null +++ b/src/detect-sip-to.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + */ + +#ifndef SURICATA_DETECT_SIP_TO_H +#define SURICATA_DETECT_SIP_TO_H + +void RegisterSipHeadersTo(void); + +#endif /* SURICATA_DETECT_SIP_TO_H */ diff --git a/src/detect-sip-ua.c b/src/detect-sip-ua.c new file mode 100644 index 000000000000..efc21c98db21 --- /dev/null +++ b/src/detect-sip-ua.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + * Implements the sip.user_agent sticky buffer + */ + +#define KEYWORD_NAME "sip.user_agent" +#define KEYWORD_DOC "sip-keywords.html#sip-user-agent" +#define BUFFER_NAME "sip.user_agent" +#define BUFFER_DESC "sip user agent header" +#define HEADER_NAME "User-Agent" +#define KEYWORD_ID DETECT_AL_SIP_HEADER_UA +#define KEYWORD_TOSERVER 1 +#define KEYWORD_TOCLIENT 1 + +#include "detect-sip-headers-stub.h" +#include "detect-sip-ua.h" + +void RegisterSipHeadersUa(void) +{ + DetectSipHeadersRegisterStub(); +} diff --git a/src/detect-sip-ua.h b/src/detect-sip-ua.h new file mode 100644 index 000000000000..9435531590d5 --- /dev/null +++ b/src/detect-sip-ua.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + */ + +#ifndef SURICATA_DETECT_SIP_UA_H +#define SURICATA_DETECT_SIP_UA_H + +void RegisterSipHeadersUa(void); + +#endif /* SURICATA_DETECT_SIP_UA_H */ diff --git a/src/detect-sip-via.c b/src/detect-sip-via.c new file mode 100644 index 000000000000..687c7a20d641 --- /dev/null +++ b/src/detect-sip-via.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + * Implements the sip.via sticky buffer + */ + +#define KEYWORD_NAME "sip.via" +#define KEYWORD_DOC "sip-keywords.html#sip-via" +#define BUFFER_NAME "sip.via" +#define BUFFER_DESC "sip via header" +#define HEADER_NAME "Via" +#define KEYWORD_ID DETECT_AL_SIP_HEADER_VIA +#define KEYWORD_TOSERVER 1 +#define KEYWORD_TOCLIENT 1 + +#include "detect-sip-headers-stub.h" +#include "detect-sip-via.h" + +void RegisterSipHeadersVia(void) +{ + DetectSipHeadersRegisterStub(); +} diff --git a/src/detect-sip-via.h b/src/detect-sip-via.h new file mode 100644 index 000000000000..2e43bfe23435 --- /dev/null +++ b/src/detect-sip-via.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \author Giuseppe Longo + * + */ + +#ifndef SURICATA_DETECT_SIP_VIA_H +#define SURICATA_DETECT_SIP_VIA_H + +void RegisterSipHeadersVia(void); + +#endif /* SURICATA_DETECT_SIP_VIA_H */