mirror of https://github.com/OISF/suricata
imap: implement sticky buffers
This implements the following sticky buffers for IMAP protocol: - imap.request - imap.response Both match on the request/response lines as sent on the wire and support firewall rules. Ticket #8276pull/16515/head
parent
c3d583349b
commit
295e96a4df
@ -0,0 +1,153 @@
|
||||
/* Copyright (C) 2026 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 <glongo@oisf.net>
|
||||
|
||||
use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER};
|
||||
use crate::detect::{
|
||||
SIGMATCH_INFO_MULTI_BUFFER, SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT,
|
||||
SIGMATCH_SUPPORT_FIREWALL,
|
||||
};
|
||||
use crate::imap::imap::{ImapTransaction, ALPROTO_IMAP};
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::{c_int, c_void};
|
||||
use suricata_sys::sys::{
|
||||
DetectEngineCtx, DetectEngineThreadCtx, SCDetectBufferSetActiveList,
|
||||
SCDetectHelperKeywordRegister, SCDetectHelperKeywordSetCleanCString,
|
||||
SCDetectHelperMultiBufferProgressMpmRegister, SCDetectSignatureSetAppProto,
|
||||
SCSigTableAppLiteElmt, Signature,
|
||||
};
|
||||
|
||||
static mut G_IMAP_REQUEST_BUFFER_ID: c_int = 0;
|
||||
static mut G_IMAP_RESPONSE_BUFFER_ID: c_int = 0;
|
||||
|
||||
unsafe extern "C" fn imap_detect_request_setup(
|
||||
de: *mut DetectEngineCtx, s: *mut Signature, _raw: *const std::os::raw::c_char,
|
||||
) -> c_int {
|
||||
if SCDetectSignatureSetAppProto(s, ALPROTO_IMAP) != 0 {
|
||||
return -1;
|
||||
}
|
||||
if SCDetectBufferSetActiveList(de, s, G_IMAP_REQUEST_BUFFER_ID) < 0 {
|
||||
return -1;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
unsafe extern "C" fn imap_tx_get_request(
|
||||
_de: *mut DetectEngineThreadCtx, tx: *const c_void, _flags: u8, local_id: u32,
|
||||
buffer: *mut *const u8, buffer_len: *mut u32,
|
||||
) -> bool {
|
||||
let tx = cast_pointer!(tx, ImapTransaction);
|
||||
|
||||
let Some(request) = tx.requests.get(local_id as usize) else {
|
||||
return false;
|
||||
};
|
||||
*buffer = request.raw_line.as_ptr();
|
||||
*buffer_len = request.raw_line.len() as u32;
|
||||
true
|
||||
}
|
||||
|
||||
unsafe extern "C" fn imap_detect_response_setup(
|
||||
de: *mut DetectEngineCtx, s: *mut Signature, _raw: *const std::os::raw::c_char,
|
||||
) -> c_int {
|
||||
if SCDetectSignatureSetAppProto(s, ALPROTO_IMAP) != 0 {
|
||||
return -1;
|
||||
}
|
||||
if SCDetectBufferSetActiveList(de, s, G_IMAP_RESPONSE_BUFFER_ID) < 0 {
|
||||
return -1;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
unsafe extern "C" fn imap_tx_get_response(
|
||||
_de: *mut DetectEngineThreadCtx, tx: *const c_void, _flags: u8, local_id: u32,
|
||||
buffer: *mut *const u8, buffer_len: *mut u32,
|
||||
) -> bool {
|
||||
let tx = cast_pointer!(tx, ImapTransaction);
|
||||
|
||||
let Some(line) = tx.response_lines.get(local_id as usize) else {
|
||||
return false;
|
||||
};
|
||||
*buffer = line.as_ptr();
|
||||
*buffer_len = line.len() as u32;
|
||||
true
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn SCDetectImapRegister() {
|
||||
let name = CString::new("imap.request").unwrap().into_raw();
|
||||
let desc = CString::new("match on IMAP request line")
|
||||
.unwrap()
|
||||
.into_raw();
|
||||
let url = CString::new("/rules/imap-keywords.html#imap-request")
|
||||
.unwrap()
|
||||
.into_raw();
|
||||
let kw = SCSigTableAppLiteElmt {
|
||||
name,
|
||||
desc,
|
||||
url,
|
||||
Setup: Some(imap_detect_request_setup),
|
||||
flags: SIGMATCH_NOOPT
|
||||
| SIGMATCH_INFO_STICKY_BUFFER
|
||||
| SIGMATCH_INFO_MULTI_BUFFER
|
||||
| SIGMATCH_SUPPORT_FIREWALL,
|
||||
AppLayerTxMatch: None,
|
||||
Free: None,
|
||||
};
|
||||
let r = SCDetectHelperKeywordRegister(&kw);
|
||||
SCDetectHelperKeywordSetCleanCString(r);
|
||||
|
||||
G_IMAP_REQUEST_BUFFER_ID = SCDetectHelperMultiBufferProgressMpmRegister(
|
||||
b"imap.request\0".as_ptr() as *const libc::c_char,
|
||||
b"IMAP REQUEST LINE\0".as_ptr() as *const libc::c_char,
|
||||
ALPROTO_IMAP,
|
||||
STREAM_TOSERVER,
|
||||
Some(imap_tx_get_request),
|
||||
0,
|
||||
);
|
||||
|
||||
let name = CString::new("imap.response").unwrap().into_raw();
|
||||
let desc = CString::new("match on IMAP response line")
|
||||
.unwrap()
|
||||
.into_raw();
|
||||
let url = CString::new("/rules/imap-keywords.html#imap-response")
|
||||
.unwrap()
|
||||
.into_raw();
|
||||
let kw = SCSigTableAppLiteElmt {
|
||||
name,
|
||||
desc,
|
||||
url,
|
||||
Setup: Some(imap_detect_response_setup),
|
||||
flags: SIGMATCH_NOOPT
|
||||
| SIGMATCH_INFO_STICKY_BUFFER
|
||||
| SIGMATCH_INFO_MULTI_BUFFER
|
||||
| SIGMATCH_SUPPORT_FIREWALL,
|
||||
AppLayerTxMatch: None,
|
||||
Free: None,
|
||||
};
|
||||
let r = SCDetectHelperKeywordRegister(&kw);
|
||||
SCDetectHelperKeywordSetCleanCString(r);
|
||||
|
||||
G_IMAP_RESPONSE_BUFFER_ID = SCDetectHelperMultiBufferProgressMpmRegister(
|
||||
b"imap.response\0".as_ptr() as *const libc::c_char,
|
||||
b"IMAP RESPONSE LINE\0".as_ptr() as *const libc::c_char,
|
||||
ALPROTO_IMAP,
|
||||
STREAM_TOCLIENT,
|
||||
Some(imap_tx_get_response),
|
||||
1,
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue