• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 22618661228

02 Mar 2026 09:33PM UTC coverage: 42.258% (-34.4%) from 76.611%
22618661228

push

github

victorjulien
github-actions: bump actions/download-artifact from 7.0.0 to 8.0.0

Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7.0.0 to 8.0.0.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/37930b1c2...70fc10c6e)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

91511 of 216553 relevant lines covered (42.26%)

3416852.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

28.24
/rust/src/websocket/detect.rs
1
/* Copyright (C) 2023 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17

18
use super::websocket::{WebSocketTransaction, ALPROTO_WEBSOCKET};
19
use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER};
20
use crate::detect::uint::{
21
    detect_parse_uint_bitflags, detect_parse_uint_enum, DetectBitflagModifier, DetectUintData,
22
    SCDetectU32Free, SCDetectU32Match, SCDetectU32Parse, SCDetectU8Free, SCDetectU8Match,
23
};
24
use crate::detect::{
25
    helper_keyword_register_sticky_buffer, SigTableElmtStickyBuffer, SIGMATCH_INFO_BITFLAGS_UINT,
26
    SIGMATCH_INFO_ENUM_UINT, SIGMATCH_INFO_UINT32, SIGMATCH_INFO_UINT8,
27
};
28
use crate::websocket::parser::WebSocketOpcode;
29
use suricata_sys::sys::{
30
    DetectEngineCtx, DetectEngineThreadCtx, Flow, SCDetectBufferSetActiveList,
31
    SCDetectHelperBufferMpmRegister, SCDetectHelperBufferRegister, SCDetectHelperKeywordRegister,
32
    SCDetectSignatureSetAppProto, SCSigMatchAppendSMToList, SCSigTableAppLiteElmt, SigMatchCtx,
33
    Signature,
34
};
35

36
use std::ffi::CStr;
37
use std::os::raw::{c_int, c_void};
38

39
unsafe extern "C" fn websocket_parse_opcode(
×
40
    ustr: *const std::os::raw::c_char,
×
41
) -> *mut DetectUintData<u8> {
×
42
    let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
×
43
    if let Ok(s) = ft_name.to_str() {
×
44
        if let Some(ctx) = detect_parse_uint_enum::<u8, WebSocketOpcode>(s) {
×
45
            let boxed = Box::new(ctx);
×
46
            return Box::into_raw(boxed) as *mut _;
×
47
        }
×
48
    }
×
49
    return std::ptr::null_mut();
×
50
}
×
51

52
#[repr(u8)]
53
#[derive(EnumStringU8)]
54
pub enum WebSocketFlag {
55
    Fin = 0x80,
56
    Comp = 0x40,
57
}
58

59
unsafe extern "C" fn websocket_parse_flags(
×
60
    ustr: *const std::os::raw::c_char,
×
61
) -> *mut DetectUintData<u8> {
×
62
    let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
×
63
    if let Ok(s) = ft_name.to_str() {
×
64
        if let Some(ctx) =
×
65
            detect_parse_uint_bitflags::<u8, WebSocketFlag>(s, DetectBitflagModifier::Plus, false)
×
66
        {
67
            let boxed = Box::new(ctx);
×
68
            return Box::into_raw(boxed) as *mut _;
×
69
        }
×
70
    }
×
71
    return std::ptr::null_mut();
×
72
}
×
73

74
static mut G_WEBSOCKET_OPCODE_KW_ID: u16 = 0;
75
static mut G_WEBSOCKET_OPCODE_BUFFER_ID: c_int = 0;
76
static mut G_WEBSOCKET_MASK_KW_ID: u16 = 0;
77
static mut G_WEBSOCKET_MASK_BUFFER_ID: c_int = 0;
78
static mut G_WEBSOCKET_FLAGS_KW_ID: u16 = 0;
79
static mut G_WEBSOCKET_FLAGS_BUFFER_ID: c_int = 0;
80
static mut G_WEBSOCKET_PAYLOAD_BUFFER_ID: c_int = 0;
81

82
unsafe extern "C" fn websocket_detect_opcode_setup(
×
83
    de: *mut DetectEngineCtx, s: *mut Signature, raw: *const libc::c_char,
×
84
) -> c_int {
×
85
    if SCDetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) != 0 {
×
86
        return -1;
×
87
    }
×
88
    let ctx = websocket_parse_opcode(raw) as *mut c_void;
×
89
    if ctx.is_null() {
×
90
        return -1;
×
91
    }
×
92
    if SCSigMatchAppendSMToList(
×
93
        de,
×
94
        s,
×
95
        G_WEBSOCKET_OPCODE_KW_ID,
×
96
        ctx as *mut SigMatchCtx,
×
97
        G_WEBSOCKET_OPCODE_BUFFER_ID,
×
98
    )
×
99
    .is_null()
×
100
    {
101
        websocket_detect_opcode_free(std::ptr::null_mut(), ctx);
×
102
        return -1;
×
103
    }
×
104
    return 0;
×
105
}
×
106

107
unsafe extern "C" fn websocket_detect_opcode_match(
×
108
    _de: *mut DetectEngineThreadCtx, _f: *mut Flow, _flags: u8, _state: *mut c_void,
×
109
    tx: *mut c_void, _sig: *const Signature, ctx: *const SigMatchCtx,
×
110
) -> c_int {
×
111
    let tx = cast_pointer!(tx, WebSocketTransaction);
×
112
    let ctx = cast_pointer!(ctx, DetectUintData<u8>);
×
113
    return SCDetectU8Match(tx.pdu.opcode, ctx);
×
114
}
×
115

116
unsafe extern "C" fn websocket_detect_opcode_free(_de: *mut DetectEngineCtx, ctx: *mut c_void) {
×
117
    // Just unbox...
×
118
    let ctx = cast_pointer!(ctx, DetectUintData<u8>);
×
119
    SCDetectU8Free(ctx);
×
120
}
×
121

122
unsafe extern "C" fn websocket_detect_mask_setup(
×
123
    de: *mut DetectEngineCtx, s: *mut Signature, raw: *const libc::c_char,
×
124
) -> c_int {
×
125
    if SCDetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) != 0 {
×
126
        return -1;
×
127
    }
×
128
    let ctx = SCDetectU32Parse(raw) as *mut c_void;
×
129
    if ctx.is_null() {
×
130
        return -1;
×
131
    }
×
132
    if SCSigMatchAppendSMToList(
×
133
        de,
×
134
        s,
×
135
        G_WEBSOCKET_MASK_KW_ID,
×
136
        ctx as *mut SigMatchCtx,
×
137
        G_WEBSOCKET_MASK_BUFFER_ID,
×
138
    )
×
139
    .is_null()
×
140
    {
141
        websocket_detect_mask_free(std::ptr::null_mut(), ctx);
×
142
        return -1;
×
143
    }
×
144
    return 0;
×
145
}
×
146

147
unsafe extern "C" fn websocket_detect_mask_match(
×
148
    _de: *mut DetectEngineThreadCtx, _f: *mut Flow, _flags: u8, _state: *mut c_void,
×
149
    tx: *mut c_void, _sig: *const Signature, ctx: *const SigMatchCtx,
×
150
) -> c_int {
×
151
    let tx = cast_pointer!(tx, WebSocketTransaction);
×
152
    let ctx = cast_pointer!(ctx, DetectUintData<u32>);
×
153
    if let Some(xorkey) = tx.pdu.mask {
×
154
        return SCDetectU32Match(xorkey, ctx);
×
155
    }
×
156
    return 0;
×
157
}
×
158

159
unsafe extern "C" fn websocket_detect_mask_free(_de: *mut DetectEngineCtx, ctx: *mut c_void) {
×
160
    // Just unbox...
×
161
    let ctx = cast_pointer!(ctx, DetectUintData<u32>);
×
162
    SCDetectU32Free(ctx);
×
163
}
×
164

165
unsafe extern "C" fn websocket_detect_flags_setup(
×
166
    de: *mut DetectEngineCtx, s: *mut Signature, raw: *const libc::c_char,
×
167
) -> c_int {
×
168
    if SCDetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) != 0 {
×
169
        return -1;
×
170
    }
×
171
    let ctx = websocket_parse_flags(raw) as *mut c_void;
×
172
    if ctx.is_null() {
×
173
        return -1;
×
174
    }
×
175
    if SCSigMatchAppendSMToList(
×
176
        de,
×
177
        s,
×
178
        G_WEBSOCKET_FLAGS_KW_ID,
×
179
        ctx as *mut SigMatchCtx,
×
180
        G_WEBSOCKET_FLAGS_BUFFER_ID,
×
181
    )
×
182
    .is_null()
×
183
    {
184
        websocket_detect_flags_free(std::ptr::null_mut(), ctx);
×
185
        return -1;
×
186
    }
×
187
    return 0;
×
188
}
×
189

190
unsafe extern "C" fn websocket_detect_flags_match(
×
191
    _de: *mut DetectEngineThreadCtx, _f: *mut Flow, _flags: u8, _state: *mut c_void,
×
192
    tx: *mut c_void, _sig: *const Signature, ctx: *const SigMatchCtx,
×
193
) -> c_int {
×
194
    let tx = cast_pointer!(tx, WebSocketTransaction);
×
195
    let ctx = cast_pointer!(ctx, DetectUintData<u8>);
×
196
    return SCDetectU8Match(tx.pdu.flags, ctx);
×
197
}
×
198

199
unsafe extern "C" fn websocket_detect_flags_free(_de: *mut DetectEngineCtx, ctx: *mut c_void) {
×
200
    // Just unbox...
×
201
    let ctx = cast_pointer!(ctx, DetectUintData<u8>);
×
202
    SCDetectU8Free(ctx);
×
203
}
×
204

205
pub unsafe extern "C" fn websocket_detect_payload_setup(
×
206
    de: *mut DetectEngineCtx, s: *mut Signature, _raw: *const std::os::raw::c_char,
×
207
) -> c_int {
×
208
    if SCDetectSignatureSetAppProto(s, ALPROTO_WEBSOCKET) != 0 {
×
209
        return -1;
×
210
    }
×
211
    if SCDetectBufferSetActiveList(de, s, G_WEBSOCKET_PAYLOAD_BUFFER_ID) < 0 {
×
212
        return -1;
×
213
    }
×
214
    return 0;
×
215
}
×
216

217
pub unsafe extern "C" fn websocket_detect_payload_get_data(
×
218
    tx: *const c_void, _flow_flags: u8, buffer: *mut *const u8, buffer_len: *mut u32,
×
219
) -> bool {
×
220
    let tx = cast_pointer!(tx, WebSocketTransaction);
×
221
    *buffer = tx.pdu.payload.as_ptr();
×
222
    *buffer_len = tx.pdu.payload.len() as u32;
×
223
    return true;
×
224
}
×
225

226
#[no_mangle]
227
pub unsafe extern "C" fn SCDetectWebsocketRegister() {
7✔
228
    let kw = SCSigTableAppLiteElmt {
7✔
229
        name: b"websocket.opcode\0".as_ptr() as *const libc::c_char,
7✔
230
        desc: b"match WebSocket opcode\0".as_ptr() as *const libc::c_char,
7✔
231
        url: b"/rules/websocket-keywords.html#websocket-opcode\0".as_ptr() as *const libc::c_char,
7✔
232
        AppLayerTxMatch: Some(websocket_detect_opcode_match),
7✔
233
        Setup: Some(websocket_detect_opcode_setup),
7✔
234
        Free: Some(websocket_detect_opcode_free),
7✔
235
        flags: SIGMATCH_INFO_UINT8 | SIGMATCH_INFO_ENUM_UINT,
7✔
236
    };
7✔
237
    G_WEBSOCKET_OPCODE_KW_ID = SCDetectHelperKeywordRegister(&kw);
7✔
238
    G_WEBSOCKET_OPCODE_BUFFER_ID = SCDetectHelperBufferRegister(
7✔
239
        b"websocket.opcode\0".as_ptr() as *const libc::c_char,
7✔
240
        ALPROTO_WEBSOCKET,
7✔
241
        STREAM_TOSERVER | STREAM_TOCLIENT,
7✔
242
    );
7✔
243
    let kw = SCSigTableAppLiteElmt {
7✔
244
        name: b"websocket.mask\0".as_ptr() as *const libc::c_char,
7✔
245
        desc: b"match WebSocket mask\0".as_ptr() as *const libc::c_char,
7✔
246
        url: b"/rules/websocket-keywords.html#websocket-mask\0".as_ptr() as *const libc::c_char,
7✔
247
        AppLayerTxMatch: Some(websocket_detect_mask_match),
7✔
248
        Setup: Some(websocket_detect_mask_setup),
7✔
249
        Free: Some(websocket_detect_mask_free),
7✔
250
        flags: SIGMATCH_INFO_UINT32,
7✔
251
    };
7✔
252
    G_WEBSOCKET_MASK_KW_ID = SCDetectHelperKeywordRegister(&kw);
7✔
253
    G_WEBSOCKET_MASK_BUFFER_ID = SCDetectHelperBufferRegister(
7✔
254
        b"websocket.mask\0".as_ptr() as *const libc::c_char,
7✔
255
        ALPROTO_WEBSOCKET,
7✔
256
        STREAM_TOSERVER | STREAM_TOCLIENT,
7✔
257
    );
7✔
258
    let kw = SCSigTableAppLiteElmt {
7✔
259
        name: b"websocket.flags\0".as_ptr() as *const libc::c_char,
7✔
260
        desc: b"match WebSocket flags\0".as_ptr() as *const libc::c_char,
7✔
261
        url: b"/rules/websocket-keywords.html#websocket-flags\0".as_ptr() as *const libc::c_char,
7✔
262
        AppLayerTxMatch: Some(websocket_detect_flags_match),
7✔
263
        Setup: Some(websocket_detect_flags_setup),
7✔
264
        Free: Some(websocket_detect_flags_free),
7✔
265
        flags: SIGMATCH_INFO_UINT8 | SIGMATCH_INFO_BITFLAGS_UINT,
7✔
266
    };
7✔
267
    G_WEBSOCKET_FLAGS_KW_ID = SCDetectHelperKeywordRegister(&kw);
7✔
268
    G_WEBSOCKET_FLAGS_BUFFER_ID = SCDetectHelperBufferRegister(
7✔
269
        b"websocket.flags\0".as_ptr() as *const libc::c_char,
7✔
270
        ALPROTO_WEBSOCKET,
7✔
271
        STREAM_TOSERVER | STREAM_TOCLIENT,
7✔
272
    );
7✔
273
    let kw = SigTableElmtStickyBuffer {
7✔
274
        name: String::from("websocket.payload"),
7✔
275
        desc: String::from("match WebSocket payload"),
7✔
276
        url: String::from("/rules/websocket-keywords.html#websocket-payload"),
7✔
277
        setup: websocket_detect_payload_setup,
7✔
278
    };
7✔
279
    let _g_ws_payload_kw_id = helper_keyword_register_sticky_buffer(&kw);
7✔
280
    G_WEBSOCKET_PAYLOAD_BUFFER_ID = SCDetectHelperBufferMpmRegister(
7✔
281
        b"websocket.payload\0".as_ptr() as *const libc::c_char,
7✔
282
        b"WebSocket payload\0".as_ptr() as *const libc::c_char,
7✔
283
        ALPROTO_WEBSOCKET,
7✔
284
        STREAM_TOSERVER | STREAM_TOCLIENT,
7✔
285
        Some(websocket_detect_payload_get_data),
7✔
286
    );
7✔
287
}
7✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc