]> git.ipfire.org Git - people/ms/suricata.git/blob - rust/src/http2/http2.rs
http2: files inspection API fixes
[people/ms/suricata.git] / rust / src / http2 / http2.rs
1 /* Copyright (C) 2020 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::files::*;
19 use super::parser;
20 use crate::applayer::{self, *};
21 use crate::core::{
22 self, AppProto, Flow, SuricataFileContext, ALPROTO_FAILED, ALPROTO_UNKNOWN, IPPROTO_TCP,
23 STREAM_TOCLIENT, STREAM_TOSERVER,
24 };
25 use crate::filecontainer::*;
26 use crate::filetracker::*;
27 use nom;
28 use std;
29 use std::ffi::{CStr, CString};
30 use std::fmt;
31 use std::mem::transmute;
32
33 static mut ALPROTO_HTTP2: AppProto = ALPROTO_UNKNOWN;
34
35 const HTTP2_DEFAULT_MAX_FRAME_SIZE: u32 = 16384;
36 const HTTP2_MAX_HANDLED_FRAME_SIZE: usize = 65536;
37 const HTTP2_MIN_HANDLED_FRAME_SIZE: usize = 256;
38
39 pub static mut SURICATA_HTTP2_FILE_CONFIG: Option<&'static SuricataFileContext> = None;
40
41 #[no_mangle]
42 pub extern "C" fn rs_http2_init(context: &'static mut SuricataFileContext) {
43 unsafe {
44 SURICATA_HTTP2_FILE_CONFIG = Some(context);
45 }
46 }
47
48 #[repr(u8)]
49 #[derive(Copy, Clone, PartialOrd, PartialEq)]
50 pub enum HTTP2ConnectionState {
51 Http2StateInit = 0,
52 Http2StateMagicDone = 1,
53 }
54
55 const HTTP2_FRAME_HEADER_LEN: usize = 9;
56 const HTTP2_MAGIC_LEN: usize = 24;
57 const HTTP2_FRAME_GOAWAY_LEN: usize = 4;
58 const HTTP2_FRAME_RSTSTREAM_LEN: usize = 4;
59 const HTTP2_FRAME_PRIORITY_LEN: usize = 5;
60 const HTTP2_FRAME_WINDOWUPDATE_LEN: usize = 4;
61 //TODO make this configurable
62 pub const HTTP2_MAX_TABLESIZE: u32 = 0x10000; // 65536
63
64 #[repr(u8)]
65 #[derive(Copy, Clone, PartialOrd, PartialEq, Debug)]
66 pub enum HTTP2FrameUnhandledReason {
67 UnknownType = 0,
68 TooLong = 1,
69 ParsingError = 2,
70 Incomplete = 3,
71 }
72
73 impl fmt::Display for HTTP2FrameUnhandledReason {
74 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75 write!(f, "{:?}", self)
76 }
77 }
78
79 #[derive(Debug)]
80 pub struct HTTP2FrameUnhandled {
81 pub reason: HTTP2FrameUnhandledReason,
82 }
83
84 pub enum HTTP2FrameTypeData {
85 PRIORITY(parser::HTTP2FramePriority),
86 GOAWAY(parser::HTTP2FrameGoAway),
87 RSTSTREAM(parser::HTTP2FrameRstStream),
88 SETTINGS(Vec<parser::HTTP2FrameSettings>),
89 WINDOWUPDATE(parser::HTTP2FrameWindowUpdate),
90 HEADERS(parser::HTTP2FrameHeaders),
91 PUSHPROMISE(parser::HTTP2FramePushPromise),
92 CONTINUATION(parser::HTTP2FrameContinuation),
93 PING,
94 DATA,
95 //not a defined frame
96 UNHANDLED(HTTP2FrameUnhandled),
97 }
98
99 #[repr(u8)]
100 #[derive(Copy, Clone, PartialOrd, PartialEq, Debug)]
101 pub enum HTTP2TransactionState {
102 HTTP2StateIdle = 0,
103 HTTP2StateOpen = 1,
104 HTTP2StateReserved = 2,
105 HTTP2StateDataClient = 3,
106 HTTP2StateHalfClosedClient = 4,
107 HTTP2StateDataServer = 5,
108 HTTP2StateHalfClosedServer = 6,
109 HTTP2StateClosed = 7,
110 //not a RFC-defined state, used for stream 0 frames appyling to the global connection
111 HTTP2StateGlobal = 8,
112 }
113
114 pub struct HTTP2Frame {
115 pub header: parser::HTTP2FrameHeader,
116 pub data: HTTP2FrameTypeData,
117 }
118
119 pub struct HTTP2Transaction {
120 tx_id: u64,
121 pub stream_id: u32,
122 pub state: HTTP2TransactionState,
123 child_stream_id: u32,
124
125 pub frames_tc: Vec<HTTP2Frame>,
126 pub frames_ts: Vec<HTTP2Frame>,
127
128 de_state: Option<*mut core::DetectEngineState>,
129 events: *mut core::AppLayerDecoderEvents,
130 tx_data: AppLayerTxData,
131 ft: FileTransferTracker,
132
133 //temporary escaped header for detection
134 //must be attached to transaction for memory management (be freed at the right time)
135 pub escaped: Vec<Vec<u8>>,
136 }
137
138 impl HTTP2Transaction {
139 pub fn new() -> HTTP2Transaction {
140 HTTP2Transaction {
141 tx_id: 0,
142 stream_id: 0,
143 child_stream_id: 0,
144 state: HTTP2TransactionState::HTTP2StateIdle,
145 frames_tc: Vec::new(),
146 frames_ts: Vec::new(),
147 de_state: None,
148 events: std::ptr::null_mut(),
149 tx_data: AppLayerTxData::new(),
150 ft: FileTransferTracker::new(),
151 escaped: Vec::with_capacity(16),
152 }
153 }
154
155 pub fn free(&mut self) {
156 if self.events != std::ptr::null_mut() {
157 core::sc_app_layer_decoder_events_free_events(&mut self.events);
158 }
159 if let Some(state) = self.de_state {
160 core::sc_detect_engine_state_free(state);
161 }
162 }
163
164 fn handle_frame(
165 &mut self, header: &parser::HTTP2FrameHeader, data: &HTTP2FrameTypeData, dir: u8,
166 ) {
167 //handle child_stream_id changes
168 match data {
169 HTTP2FrameTypeData::PUSHPROMISE(hs) => {
170 if dir == STREAM_TOCLIENT {
171 //we could set an event if self.child_stream_id != 0
172 if header.flags & parser::HTTP2_FLAG_HEADER_END_HEADERS == 0 {
173 self.child_stream_id = hs.stream_id;
174 }
175 self.state = HTTP2TransactionState::HTTP2StateReserved;
176 }
177 }
178 HTTP2FrameTypeData::CONTINUATION(_) => {
179 if dir == STREAM_TOCLIENT
180 && header.flags & parser::HTTP2_FLAG_HEADER_END_HEADERS != 0
181 {
182 self.child_stream_id = 0;
183 }
184 }
185 HTTP2FrameTypeData::HEADERS(_) => {
186 if dir == STREAM_TOCLIENT {
187 self.child_stream_id = 0;
188 }
189 }
190 HTTP2FrameTypeData::RSTSTREAM(_) => {
191 self.child_stream_id = 0;
192 }
193 _ => {}
194 }
195 //handle closing state changes
196 match data {
197 HTTP2FrameTypeData::HEADERS(_) | HTTP2FrameTypeData::DATA => {
198 if header.flags & parser::HTTP2_FLAG_HEADER_EOS != 0 {
199 match self.state {
200 HTTP2TransactionState::HTTP2StateHalfClosedClient
201 | HTTP2TransactionState::HTTP2StateDataServer => {
202 if dir == STREAM_TOCLIENT {
203 self.state = HTTP2TransactionState::HTTP2StateClosed;
204 }
205 }
206 HTTP2TransactionState::HTTP2StateHalfClosedServer => {
207 if dir == STREAM_TOSERVER {
208 self.state = HTTP2TransactionState::HTTP2StateClosed;
209 }
210 }
211 // do not revert back to a half closed state
212 HTTP2TransactionState::HTTP2StateClosed => {}
213 HTTP2TransactionState::HTTP2StateGlobal => {}
214 _ => {
215 if dir == STREAM_TOCLIENT {
216 self.state = HTTP2TransactionState::HTTP2StateHalfClosedServer;
217 } else {
218 self.state = HTTP2TransactionState::HTTP2StateHalfClosedClient;
219 }
220 }
221 }
222 } else if header.ftype == parser::HTTP2FrameType::DATA as u8 {
223 //not end of stream
224 if dir == STREAM_TOSERVER {
225 if self.state < HTTP2TransactionState::HTTP2StateDataClient {
226 self.state = HTTP2TransactionState::HTTP2StateDataClient;
227 }
228 } else {
229 if self.state < HTTP2TransactionState::HTTP2StateDataServer {
230 self.state = HTTP2TransactionState::HTTP2StateDataServer;
231 }
232 }
233 }
234 }
235 _ => {}
236 }
237 }
238 }
239
240 impl Drop for HTTP2Transaction {
241 fn drop(&mut self) {
242 self.free();
243 }
244 }
245
246 #[repr(u32)]
247 pub enum HTTP2Event {
248 InvalidFrameHeader = 0,
249 InvalidClientMagic,
250 InvalidFrameData,
251 InvalidHeader,
252 InvalidFrameLength,
253 ExtraHeaderData,
254 LongFrameData,
255 StreamIdReuse,
256 InvalidHTTP1Settings,
257 }
258
259 impl HTTP2Event {
260 fn from_i32(value: i32) -> Option<HTTP2Event> {
261 match value {
262 0 => Some(HTTP2Event::InvalidFrameHeader),
263 1 => Some(HTTP2Event::InvalidClientMagic),
264 2 => Some(HTTP2Event::InvalidFrameData),
265 3 => Some(HTTP2Event::InvalidHeader),
266 4 => Some(HTTP2Event::InvalidFrameLength),
267 5 => Some(HTTP2Event::ExtraHeaderData),
268 6 => Some(HTTP2Event::LongFrameData),
269 7 => Some(HTTP2Event::StreamIdReuse),
270 8 => Some(HTTP2Event::InvalidHTTP1Settings),
271 _ => None,
272 }
273 }
274 }
275
276 pub struct HTTP2DynTable {
277 pub table: Vec<parser::HTTP2FrameHeaderBlock>,
278 pub current_size: usize,
279 pub max_size: usize,
280 pub overflow: u8,
281 }
282
283 impl HTTP2DynTable {
284 pub fn new() -> Self {
285 Self {
286 table: Vec::with_capacity(64),
287 current_size: 0,
288 max_size: 4096, //default value
289 overflow: 0,
290 }
291 }
292 }
293
294 pub struct HTTP2State {
295 tx_id: u64,
296 request_frame_size: u32,
297 response_frame_size: u32,
298 dynamic_headers_ts: HTTP2DynTable,
299 dynamic_headers_tc: HTTP2DynTable,
300 transactions: Vec<HTTP2Transaction>,
301 progress: HTTP2ConnectionState,
302 pub files: HTTP2Files,
303 }
304
305 impl HTTP2State {
306 pub fn new() -> Self {
307 Self {
308 tx_id: 0,
309 request_frame_size: 0,
310 response_frame_size: 0,
311 // the headers are encoded on one byte
312 // with a fixed number of static headers, and
313 // a variable number of dynamic headers
314 dynamic_headers_ts: HTTP2DynTable::new(),
315 dynamic_headers_tc: HTTP2DynTable::new(),
316 transactions: Vec::new(),
317 progress: HTTP2ConnectionState::Http2StateInit,
318 files: HTTP2Files::new(),
319 }
320 }
321
322 pub fn free(&mut self) {
323 self.transactions.clear();
324 self.files.free();
325 }
326
327 pub fn set_event(&mut self, event: HTTP2Event) {
328 let len = self.transactions.len();
329 if len == 0 {
330 return;
331 }
332 let tx = &mut self.transactions[len - 1];
333 let ev = event as u8;
334 core::sc_app_layer_decoder_events_set_event_raw(&mut tx.events, ev);
335 }
336
337 // Free a transaction by ID.
338 fn free_tx(&mut self, tx_id: u64) {
339 let len = self.transactions.len();
340 let mut found = false;
341 let mut index = 0;
342 for i in 0..len {
343 let tx = &self.transactions[i];
344 if tx.tx_id == tx_id + 1 {
345 found = true;
346 index = i;
347 break;
348 }
349 }
350 if found {
351 self.transactions.remove(index);
352 }
353 }
354
355 pub fn get_tx(&mut self, tx_id: u64) -> Option<&HTTP2Transaction> {
356 for tx in &mut self.transactions {
357 if tx.tx_id == tx_id + 1 {
358 return Some(tx);
359 }
360 }
361 return None;
362 }
363
364 fn find_tx_index(&mut self, sid: u32) -> usize {
365 for i in 0..self.transactions.len() {
366 //reverse order should be faster
367 let idx = self.transactions.len() - 1 - i;
368 if sid == self.transactions[idx].stream_id {
369 return idx + 1;
370 }
371 }
372 return 0;
373 }
374
375 fn find_child_stream_id(&mut self, sid: u32) -> u32 {
376 for i in 0..self.transactions.len() {
377 //reverse order should be faster
378 if sid == self.transactions[self.transactions.len() - 1 - i].stream_id {
379 if self.transactions[self.transactions.len() - 1 - i].child_stream_id > 0 {
380 return self.transactions[self.transactions.len() - 1 - i].child_stream_id;
381 }
382 return sid;
383 }
384 }
385 return sid;
386 }
387
388 fn create_global_tx(&mut self) -> &mut HTTP2Transaction {
389 //special transaction with only one frame
390 //as it affects the global connection, there is no end to it
391 let mut tx = HTTP2Transaction::new();
392 self.tx_id += 1;
393 tx.tx_id = self.tx_id;
394 tx.state = HTTP2TransactionState::HTTP2StateGlobal;
395 self.transactions.push(tx);
396 return self.transactions.last_mut().unwrap();
397 }
398
399 pub fn find_or_create_tx(
400 &mut self, header: &parser::HTTP2FrameHeader, data: &HTTP2FrameTypeData, dir: u8,
401 ) -> &mut HTTP2Transaction {
402 if header.stream_id == 0 {
403 return self.create_global_tx();
404 }
405 let sid = match data {
406 //yes, the right stream_id for Suricata is not the header one
407 HTTP2FrameTypeData::PUSHPROMISE(hs) => hs.stream_id,
408 HTTP2FrameTypeData::CONTINUATION(_) => {
409 if dir == STREAM_TOCLIENT {
410 //continuation of a push promise
411 self.find_child_stream_id(header.stream_id)
412 } else {
413 header.stream_id
414 }
415 }
416 _ => header.stream_id,
417 };
418 let index = self.find_tx_index(sid);
419 if index > 0 {
420 if self.transactions[index - 1].state == HTTP2TransactionState::HTTP2StateClosed {
421 //these frames can be received in this state for a short period
422 if header.ftype != parser::HTTP2FrameType::RSTSTREAM as u8
423 && header.ftype != parser::HTTP2FrameType::WINDOWUPDATE as u8
424 && header.ftype != parser::HTTP2FrameType::PRIORITY as u8
425 {
426 self.set_event(HTTP2Event::StreamIdReuse);
427 }
428 }
429 return &mut self.transactions[index - 1];
430 } else {
431 let mut tx = HTTP2Transaction::new();
432 self.tx_id += 1;
433 tx.tx_id = self.tx_id;
434 tx.stream_id = sid;
435 tx.state = HTTP2TransactionState::HTTP2StateOpen;
436 self.transactions.push(tx);
437 return self.transactions.last_mut().unwrap();
438 }
439 }
440
441 fn process_headers(&mut self, blocks: &Vec<parser::HTTP2FrameHeaderBlock>, dir: u8) {
442 let (mut update, mut sizeup) = (false, 0);
443 for i in 0..blocks.len() {
444 if blocks[i].error >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError {
445 self.set_event(HTTP2Event::InvalidHeader);
446 } else if blocks[i].error
447 == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
448 {
449 update = true;
450 if blocks[i].sizeupdate > sizeup {
451 sizeup = blocks[i].sizeupdate;
452 }
453 }
454 }
455 if update {
456 //borrow checker forbids to pass directly dyn_headers
457 let dyn_headers = if dir == STREAM_TOCLIENT {
458 &mut self.dynamic_headers_tc
459 } else {
460 &mut self.dynamic_headers_ts
461 };
462 dyn_headers.max_size = sizeup as usize;
463 }
464 }
465
466 fn parse_frame_data(
467 &mut self, ftype: u8, input: &[u8], complete: bool, hflags: u8, dir: u8,
468 ) -> HTTP2FrameTypeData {
469 match num::FromPrimitive::from_u8(ftype) {
470 Some(parser::HTTP2FrameType::GOAWAY) => {
471 if input.len() < HTTP2_FRAME_GOAWAY_LEN {
472 self.set_event(HTTP2Event::InvalidFrameLength);
473 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
474 reason: HTTP2FrameUnhandledReason::Incomplete,
475 });
476 }
477 match parser::http2_parse_frame_goaway(input) {
478 Ok((_, goaway)) => {
479 return HTTP2FrameTypeData::GOAWAY(goaway);
480 }
481 Err(_) => {
482 self.set_event(HTTP2Event::InvalidFrameData);
483 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
484 reason: HTTP2FrameUnhandledReason::ParsingError,
485 });
486 }
487 }
488 }
489 Some(parser::HTTP2FrameType::SETTINGS) => {
490 match parser::http2_parse_frame_settings(input) {
491 Ok((_, set)) => {
492 for i in 0..set.len() {
493 if set[i].id == parser::HTTP2SettingsId::SETTINGSHEADERTABLESIZE {
494 //reverse order as this is what we accept from the other endpoint
495 let dyn_headers = if dir == STREAM_TOCLIENT {
496 &mut self.dynamic_headers_ts
497 } else {
498 &mut self.dynamic_headers_tc
499 };
500 dyn_headers.max_size = set[i].value as usize;
501 if set[i].value > HTTP2_MAX_TABLESIZE {
502 //mark potential overflow
503 dyn_headers.overflow = 1;
504 } else {
505 //reset in case peer set a lower value, to be tested
506 dyn_headers.overflow = 0;
507 }
508 }
509 }
510 //we could set an event on remaining data
511 return HTTP2FrameTypeData::SETTINGS(set);
512 }
513 Err(nom::Err::Incomplete(_)) => {
514 if complete {
515 self.set_event(HTTP2Event::InvalidFrameData);
516 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
517 reason: HTTP2FrameUnhandledReason::ParsingError,
518 });
519 } else {
520 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
521 reason: HTTP2FrameUnhandledReason::TooLong,
522 });
523 }
524 }
525 Err(_) => {
526 self.set_event(HTTP2Event::InvalidFrameData);
527 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
528 reason: HTTP2FrameUnhandledReason::ParsingError,
529 });
530 }
531 }
532 }
533 Some(parser::HTTP2FrameType::RSTSTREAM) => {
534 if input.len() != HTTP2_FRAME_RSTSTREAM_LEN {
535 self.set_event(HTTP2Event::InvalidFrameLength);
536 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
537 reason: HTTP2FrameUnhandledReason::Incomplete,
538 });
539 } else {
540 match parser::http2_parse_frame_rststream(input) {
541 Ok((_, rst)) => {
542 return HTTP2FrameTypeData::RSTSTREAM(rst);
543 }
544 Err(_) => {
545 self.set_event(HTTP2Event::InvalidFrameData);
546 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
547 reason: HTTP2FrameUnhandledReason::ParsingError,
548 });
549 }
550 }
551 }
552 }
553 Some(parser::HTTP2FrameType::PRIORITY) => {
554 if input.len() != HTTP2_FRAME_PRIORITY_LEN {
555 self.set_event(HTTP2Event::InvalidFrameLength);
556 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
557 reason: HTTP2FrameUnhandledReason::Incomplete,
558 });
559 } else {
560 match parser::http2_parse_frame_priority(input) {
561 Ok((_, priority)) => {
562 return HTTP2FrameTypeData::PRIORITY(priority);
563 }
564 Err(_) => {
565 self.set_event(HTTP2Event::InvalidFrameData);
566 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
567 reason: HTTP2FrameUnhandledReason::ParsingError,
568 });
569 }
570 }
571 }
572 }
573 Some(parser::HTTP2FrameType::WINDOWUPDATE) => {
574 if input.len() != HTTP2_FRAME_WINDOWUPDATE_LEN {
575 self.set_event(HTTP2Event::InvalidFrameLength);
576 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
577 reason: HTTP2FrameUnhandledReason::Incomplete,
578 });
579 } else {
580 match parser::http2_parse_frame_windowupdate(input) {
581 Ok((_, wu)) => {
582 return HTTP2FrameTypeData::WINDOWUPDATE(wu);
583 }
584 Err(_) => {
585 self.set_event(HTTP2Event::InvalidFrameData);
586 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
587 reason: HTTP2FrameUnhandledReason::ParsingError,
588 });
589 }
590 }
591 }
592 }
593 Some(parser::HTTP2FrameType::PUSHPROMISE) => {
594 let dyn_headers = if dir == STREAM_TOCLIENT {
595 &mut self.dynamic_headers_tc
596 } else {
597 &mut self.dynamic_headers_ts
598 };
599 match parser::http2_parse_frame_push_promise(input, hflags, dyn_headers) {
600 Ok((_, hs)) => {
601 self.process_headers(&hs.blocks, dir);
602 return HTTP2FrameTypeData::PUSHPROMISE(hs);
603 }
604 Err(nom::Err::Incomplete(_)) => {
605 if complete {
606 self.set_event(HTTP2Event::InvalidFrameData);
607 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
608 reason: HTTP2FrameUnhandledReason::ParsingError,
609 });
610 } else {
611 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
612 reason: HTTP2FrameUnhandledReason::TooLong,
613 });
614 }
615 }
616 Err(_) => {
617 self.set_event(HTTP2Event::InvalidFrameData);
618 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
619 reason: HTTP2FrameUnhandledReason::ParsingError,
620 });
621 }
622 }
623 }
624 Some(parser::HTTP2FrameType::DATA) => {
625 return HTTP2FrameTypeData::DATA;
626 }
627 Some(parser::HTTP2FrameType::CONTINUATION) => {
628 let dyn_headers = if dir == STREAM_TOCLIENT {
629 &mut self.dynamic_headers_tc
630 } else {
631 &mut self.dynamic_headers_ts
632 };
633 match parser::http2_parse_frame_continuation(input, dyn_headers) {
634 Ok((_, hs)) => {
635 self.process_headers(&hs.blocks, dir);
636 return HTTP2FrameTypeData::CONTINUATION(hs);
637 }
638 Err(nom::Err::Incomplete(_)) => {
639 if complete {
640 self.set_event(HTTP2Event::InvalidFrameData);
641 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
642 reason: HTTP2FrameUnhandledReason::ParsingError,
643 });
644 } else {
645 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
646 reason: HTTP2FrameUnhandledReason::TooLong,
647 });
648 }
649 }
650 Err(_) => {
651 self.set_event(HTTP2Event::InvalidFrameData);
652 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
653 reason: HTTP2FrameUnhandledReason::ParsingError,
654 });
655 }
656 }
657 }
658 Some(parser::HTTP2FrameType::HEADERS) => {
659 let dyn_headers = if dir == STREAM_TOCLIENT {
660 &mut self.dynamic_headers_tc
661 } else {
662 &mut self.dynamic_headers_ts
663 };
664 match parser::http2_parse_frame_headers(input, hflags, dyn_headers) {
665 Ok((hrem, hs)) => {
666 self.process_headers(&hs.blocks, dir);
667 if hrem.len() > 0 {
668 SCLogDebug!("Remaining data for HTTP2 headers");
669 self.set_event(HTTP2Event::ExtraHeaderData);
670 }
671 return HTTP2FrameTypeData::HEADERS(hs);
672 }
673 Err(nom::Err::Incomplete(_)) => {
674 if complete {
675 self.set_event(HTTP2Event::InvalidFrameData);
676 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
677 reason: HTTP2FrameUnhandledReason::ParsingError,
678 });
679 } else {
680 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
681 reason: HTTP2FrameUnhandledReason::TooLong,
682 });
683 }
684 }
685 Err(_) => {
686 self.set_event(HTTP2Event::InvalidFrameData);
687 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
688 reason: HTTP2FrameUnhandledReason::ParsingError,
689 });
690 }
691 }
692 }
693 Some(parser::HTTP2FrameType::PING) => {
694 return HTTP2FrameTypeData::PING;
695 }
696 _ => {
697 return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled {
698 reason: HTTP2FrameUnhandledReason::UnknownType,
699 });
700 }
701 }
702 }
703
704 fn parse_frames(&mut self, mut input: &[u8], il: usize, dir: u8) -> AppLayerResult {
705 while input.len() > 0 {
706 match parser::http2_parse_frame_header(input) {
707 Ok((rem, head)) => {
708 let hl = head.length as usize;
709
710 //we check for completeness first
711 if rem.len() < hl {
712 //but limit ourselves so as not to exhaust memory
713 if hl < HTTP2_MAX_HANDLED_FRAME_SIZE {
714 return AppLayerResult::incomplete(
715 (il - input.len()) as u32,
716 (HTTP2_FRAME_HEADER_LEN + hl) as u32,
717 );
718 } else if rem.len() < HTTP2_MIN_HANDLED_FRAME_SIZE {
719 return AppLayerResult::incomplete(
720 (il - input.len()) as u32,
721 (HTTP2_FRAME_HEADER_LEN + HTTP2_MIN_HANDLED_FRAME_SIZE) as u32,
722 );
723 } else {
724 self.set_event(HTTP2Event::LongFrameData);
725 self.request_frame_size = head.length - (rem.len() as u32);
726 }
727 }
728
729 //get a safe length for the buffer
730 let (hlsafe, complete) = if rem.len() < hl {
731 (rem.len(), false)
732 } else {
733 (hl, true)
734 };
735
736 if head.length == 0 && head.ftype == parser::HTTP2FrameType::SETTINGS as u8 {
737 input = &rem[hlsafe..];
738 continue;
739 }
740 let txdata = self.parse_frame_data(
741 head.ftype,
742 &rem[..hlsafe],
743 complete,
744 head.flags,
745 dir,
746 );
747
748 let tx = self.find_or_create_tx(&head, &txdata, dir);
749 tx.handle_frame(&head, &txdata, dir);
750 let over = head.flags & parser::HTTP2_FLAG_HEADER_EOS != 0;
751 let ftype = head.ftype;
752 let sid = head.stream_id;
753 if dir == STREAM_TOSERVER {
754 tx.frames_ts.push(HTTP2Frame {
755 header: head,
756 data: txdata,
757 });
758 } else {
759 tx.frames_tc.push(HTTP2Frame {
760 header: head,
761 data: txdata,
762 });
763 }
764 if ftype == parser::HTTP2FrameType::DATA as u8 {
765 match unsafe { SURICATA_HTTP2_FILE_CONFIG } {
766 Some(sfcm) => {
767 //borrow checker forbids to reuse directly tx
768 let index = self.find_tx_index(sid);
769 if index > 0 {
770 let mut tx_same = &mut self.transactions[index - 1];
771 let xid: u32 = tx_same.tx_id as u32;
772 tx_same.ft.tx_id = tx_same.tx_id - 1;
773 let (files, flags) = self.files.get(dir);
774 tx_same.ft.new_chunk(
775 sfcm,
776 files,
777 flags,
778 b"",
779 &rem[..hlsafe],
780 tx_same.ft.tracked, //offset = append
781 hlsafe as u32,
782 0,
783 over,
784 &xid,
785 );
786 }
787 }
788 None => panic!("BUG"),
789 }
790 }
791 input = &rem[hlsafe..];
792 }
793 Err(nom::Err::Incomplete(_)) => {
794 //we may have consumed data from previous records
795 return AppLayerResult::incomplete(
796 (il - input.len()) as u32,
797 HTTP2_FRAME_HEADER_LEN as u32,
798 );
799 }
800 Err(_) => {
801 self.set_event(HTTP2Event::InvalidFrameHeader);
802 return AppLayerResult::err();
803 }
804 }
805 }
806 return AppLayerResult::ok();
807 }
808
809 fn parse_ts(&mut self, mut input: &[u8]) -> AppLayerResult {
810 //very first : skip magic
811 let mut magic_consumed = 0;
812 if self.progress < HTTP2ConnectionState::Http2StateMagicDone {
813 //skip magic
814 if input.len() >= HTTP2_MAGIC_LEN {
815 //skip magic
816 match std::str::from_utf8(&input[..HTTP2_MAGIC_LEN]) {
817 Ok("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n") => {
818 input = &input[HTTP2_MAGIC_LEN..];
819 magic_consumed = HTTP2_MAGIC_LEN;
820 }
821 Ok(&_) => {
822 self.set_event(HTTP2Event::InvalidClientMagic);
823 }
824 Err(_) => {
825 return AppLayerResult::err();
826 }
827 }
828 self.progress = HTTP2ConnectionState::Http2StateMagicDone;
829 } else {
830 //still more buffer
831 return AppLayerResult::incomplete(0 as u32, HTTP2_MAGIC_LEN as u32);
832 }
833 }
834 //first consume frame bytes
835 let il = input.len();
836 if self.request_frame_size > 0 {
837 let ilen = input.len() as u32;
838 if self.request_frame_size >= ilen {
839 self.request_frame_size -= ilen;
840 return AppLayerResult::ok();
841 } else {
842 let start = self.request_frame_size as usize;
843 input = &input[start..];
844 self.request_frame_size = 0;
845 }
846 }
847
848 //then parse all we can
849 let r = self.parse_frames(input, il, STREAM_TOSERVER);
850 if r.status == 1 {
851 //adds bytes consumed by banner to incomplete result
852 return AppLayerResult::incomplete(r.consumed + magic_consumed as u32, r.needed);
853 } else {
854 return r;
855 }
856 }
857
858 fn parse_tc(&mut self, mut input: &[u8]) -> AppLayerResult {
859 //first consume frame bytes
860 let il = input.len();
861 if self.response_frame_size > 0 {
862 let ilen = input.len() as u32;
863 if self.response_frame_size >= ilen {
864 self.response_frame_size -= ilen;
865 return AppLayerResult::ok();
866 } else {
867 let start = self.response_frame_size as usize;
868 input = &input[start..];
869 self.response_frame_size = 0;
870 }
871 }
872 //then parse all we can
873 return self.parse_frames(input, il, STREAM_TOCLIENT);
874 }
875
876 fn tx_iterator(
877 &mut self, min_tx_id: u64, state: &mut u64,
878 ) -> Option<(&HTTP2Transaction, u64, bool)> {
879 let mut index = *state as usize;
880 let len = self.transactions.len();
881
882 while index < len {
883 let tx = &self.transactions[index];
884 if tx.tx_id < min_tx_id + 1 {
885 index += 1;
886 continue;
887 }
888 *state = index as u64;
889 return Some((tx, tx.tx_id - 1, (len - index) > 1));
890 }
891
892 return None;
893 }
894 }
895
896 // C exports.
897
898 export_tx_get_detect_state!(rs_http2_tx_get_detect_state, HTTP2Transaction);
899 export_tx_set_detect_state!(rs_http2_tx_set_detect_state, HTTP2Transaction);
900
901 export_tx_data_get!(rs_http2_get_tx_data, HTTP2Transaction);
902
903 /// C entry point for a probing parser.
904 #[no_mangle]
905 pub extern "C" fn rs_http2_probing_parser_tc(
906 _flow: *const Flow, _direction: u8, input: *const u8, input_len: u32, _rdir: *mut u8,
907 ) -> AppProto {
908 if input != std::ptr::null_mut() {
909 let slice = build_slice!(input, input_len as usize);
910 match parser::http2_parse_frame_header(slice) {
911 Ok((_, header)) => {
912 if header.reserved != 0
913 || header.length > HTTP2_DEFAULT_MAX_FRAME_SIZE
914 || header.flags & 0xFE != 0
915 || header.ftype != parser::HTTP2FrameType::SETTINGS as u8
916 {
917 return unsafe { ALPROTO_FAILED };
918 }
919 return unsafe { ALPROTO_HTTP2 };
920 }
921 Err(nom::Err::Incomplete(_)) => {
922 return ALPROTO_UNKNOWN;
923 }
924 Err(_) => {
925 return unsafe { ALPROTO_FAILED };
926 }
927 }
928 }
929 return ALPROTO_UNKNOWN;
930 }
931
932 /// Extern functions operating on HTTP2.
933 extern "C" {
934 pub fn HTTP2MimicHttp1Request(
935 orig_state: *mut std::os::raw::c_void, new_state: *mut std::os::raw::c_void,
936 );
937 }
938
939 #[no_mangle]
940 pub extern "C" fn rs_http2_state_new(
941 orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto,
942 ) -> *mut std::os::raw::c_void {
943 let state = HTTP2State::new();
944 let boxed = Box::new(state);
945 let r = unsafe { transmute(boxed) };
946 if orig_state != std::ptr::null_mut() {
947 //we could check ALPROTO_HTTP == orig_proto
948 unsafe {
949 HTTP2MimicHttp1Request(orig_state, r);
950 }
951 }
952 return r;
953 }
954
955 #[no_mangle]
956 pub extern "C" fn rs_http2_state_free(state: *mut std::os::raw::c_void) {
957 // Just unbox...
958 let mut state: Box<HTTP2State> = unsafe { transmute(state) };
959 state.free();
960 }
961
962 #[no_mangle]
963 pub extern "C" fn rs_http2_state_tx_free(state: *mut std::os::raw::c_void, tx_id: u64) {
964 let state = cast_pointer!(state, HTTP2State);
965 state.free_tx(tx_id);
966 }
967
968 #[no_mangle]
969 pub extern "C" fn rs_http2_parse_ts(
970 flow: *const Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
971 input: *const u8, input_len: u32, _data: *const std::os::raw::c_void, _flags: u8,
972 ) -> AppLayerResult {
973 let state = cast_pointer!(state, HTTP2State);
974 let buf = build_slice!(input, input_len as usize);
975
976 state.files.flags_ts = unsafe { FileFlowToFlags(flow, STREAM_TOSERVER) };
977 state.files.flags_ts = state.files.flags_ts | FILE_USE_DETECT;
978 return state.parse_ts(buf);
979 }
980
981 #[no_mangle]
982 pub extern "C" fn rs_http2_parse_tc(
983 flow: *const Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
984 input: *const u8, input_len: u32, _data: *const std::os::raw::c_void, _flags: u8,
985 ) -> AppLayerResult {
986 let state = cast_pointer!(state, HTTP2State);
987 let buf = build_slice!(input, input_len as usize);
988 state.files.flags_tc = unsafe { FileFlowToFlags(flow, STREAM_TOCLIENT) };
989 state.files.flags_tc = state.files.flags_tc | FILE_USE_DETECT;
990 return state.parse_tc(buf);
991 }
992
993 #[no_mangle]
994 pub extern "C" fn rs_http2_state_get_tx(
995 state: *mut std::os::raw::c_void, tx_id: u64,
996 ) -> *mut std::os::raw::c_void {
997 let state = cast_pointer!(state, HTTP2State);
998 match state.get_tx(tx_id) {
999 Some(tx) => {
1000 return unsafe { transmute(tx) };
1001 }
1002 None => {
1003 return std::ptr::null_mut();
1004 }
1005 }
1006 }
1007
1008 #[no_mangle]
1009 pub extern "C" fn rs_http2_state_get_tx_count(state: *mut std::os::raw::c_void) -> u64 {
1010 let state = cast_pointer!(state, HTTP2State);
1011 return state.tx_id;
1012 }
1013
1014 #[no_mangle]
1015 pub extern "C" fn rs_http2_state_progress_completion_status(_direction: u8) -> std::os::raw::c_int {
1016 return HTTP2TransactionState::HTTP2StateClosed as i32;
1017 }
1018
1019 #[no_mangle]
1020 pub extern "C" fn rs_http2_tx_get_state(tx: *mut std::os::raw::c_void) -> HTTP2TransactionState {
1021 let tx = cast_pointer!(tx, HTTP2Transaction);
1022 return tx.state;
1023 }
1024
1025 #[no_mangle]
1026 pub extern "C" fn rs_http2_tx_get_alstate_progress(
1027 tx: *mut std::os::raw::c_void, _direction: u8,
1028 ) -> std::os::raw::c_int {
1029 return rs_http2_tx_get_state(tx) as i32;
1030 }
1031
1032 #[no_mangle]
1033 pub extern "C" fn rs_http2_state_get_events(
1034 tx: *mut std::os::raw::c_void,
1035 ) -> *mut core::AppLayerDecoderEvents {
1036 let tx = cast_pointer!(tx, HTTP2Transaction);
1037 return tx.events;
1038 }
1039
1040 #[no_mangle]
1041 pub extern "C" fn rs_http2_state_get_event_info(
1042 event_name: *const std::os::raw::c_char, event_id: *mut std::os::raw::c_int,
1043 event_type: *mut core::AppLayerEventType,
1044 ) -> std::os::raw::c_int {
1045 if event_name == std::ptr::null() {
1046 return -1;
1047 }
1048 let c_event_name: &CStr = unsafe { CStr::from_ptr(event_name) };
1049 let event = match c_event_name.to_str() {
1050 Ok(s) => {
1051 match s {
1052 "invalid_frame_header" => HTTP2Event::InvalidFrameHeader as i32,
1053 "invalid_client_magic" => HTTP2Event::InvalidClientMagic as i32,
1054 "invalid_frame_data" => HTTP2Event::InvalidFrameData as i32,
1055 "invalid_header" => HTTP2Event::InvalidHeader as i32,
1056 "invalid_frame_length" => HTTP2Event::InvalidFrameLength as i32,
1057 "extra_header_data" => HTTP2Event::ExtraHeaderData as i32,
1058 "long_frame_data" => HTTP2Event::LongFrameData as i32,
1059 "stream_id_reuse" => HTTP2Event::StreamIdReuse as i32,
1060 "invalid_http1_settings" => HTTP2Event::InvalidHTTP1Settings as i32,
1061 _ => -1, // unknown event
1062 }
1063 }
1064 Err(_) => -1, // UTF-8 conversion failed
1065 };
1066 unsafe {
1067 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
1068 *event_id = event as std::os::raw::c_int;
1069 };
1070 0
1071 }
1072
1073 #[no_mangle]
1074 pub extern "C" fn rs_http2_state_get_event_info_by_id(
1075 event_id: std::os::raw::c_int, event_name: *mut *const std::os::raw::c_char,
1076 event_type: *mut core::AppLayerEventType,
1077 ) -> i8 {
1078 if let Some(e) = HTTP2Event::from_i32(event_id as i32) {
1079 let estr = match e {
1080 HTTP2Event::InvalidFrameHeader => "invalid_frame_header\0",
1081 HTTP2Event::InvalidClientMagic => "invalid_client_magic\0",
1082 HTTP2Event::InvalidFrameData => "invalid_frame_data\0",
1083 HTTP2Event::InvalidHeader => "invalid_header\0",
1084 HTTP2Event::InvalidFrameLength => "invalid_frame_length\0",
1085 HTTP2Event::ExtraHeaderData => "extra_header_data\0",
1086 HTTP2Event::LongFrameData => "long_frame_data\0",
1087 HTTP2Event::StreamIdReuse => "stream_id_reuse\0",
1088 HTTP2Event::InvalidHTTP1Settings => "invalid_http1_settings\0",
1089 };
1090 unsafe {
1091 *event_name = estr.as_ptr() as *const std::os::raw::c_char;
1092 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
1093 };
1094 0
1095 } else {
1096 -1
1097 }
1098 }
1099 #[no_mangle]
1100 pub extern "C" fn rs_http2_state_get_tx_iterator(
1101 _ipproto: u8, _alproto: AppProto, state: *mut std::os::raw::c_void, min_tx_id: u64,
1102 _max_tx_id: u64, istate: &mut u64,
1103 ) -> applayer::AppLayerGetTxIterTuple {
1104 let state = cast_pointer!(state, HTTP2State);
1105 match state.tx_iterator(min_tx_id, istate) {
1106 Some((tx, out_tx_id, has_next)) => {
1107 let c_tx = unsafe { transmute(tx) };
1108 let ires = applayer::AppLayerGetTxIterTuple::with_values(c_tx, out_tx_id, has_next);
1109 return ires;
1110 }
1111 None => {
1112 return applayer::AppLayerGetTxIterTuple::not_found();
1113 }
1114 }
1115 }
1116
1117 #[no_mangle]
1118 pub extern "C" fn rs_http2_getfiles(
1119 state: *mut std::os::raw::c_void, direction: u8,
1120 ) -> *mut FileContainer {
1121 let state = cast_pointer!(state, HTTP2State);
1122 if direction == STREAM_TOCLIENT {
1123 &mut state.files.files_tc as *mut FileContainer
1124 } else {
1125 &mut state.files.files_ts as *mut FileContainer
1126 }
1127 }
1128
1129 // Parser name as a C style string.
1130 const PARSER_NAME: &'static [u8] = b"http2\0";
1131
1132 #[no_mangle]
1133 pub unsafe extern "C" fn rs_http2_register_parser() {
1134 let default_port = CString::new("[80]").unwrap();
1135 let parser = RustParser {
1136 name: PARSER_NAME.as_ptr() as *const std::os::raw::c_char,
1137 default_port: default_port.as_ptr(),
1138 ipproto: IPPROTO_TCP,
1139 probe_ts: None, // big magic string should be enough
1140 probe_tc: Some(rs_http2_probing_parser_tc),
1141 min_depth: HTTP2_FRAME_HEADER_LEN as u16,
1142 max_depth: HTTP2_MAGIC_LEN as u16,
1143 state_new: rs_http2_state_new,
1144 state_free: rs_http2_state_free,
1145 tx_free: rs_http2_state_tx_free,
1146 parse_ts: rs_http2_parse_ts,
1147 parse_tc: rs_http2_parse_tc,
1148 get_tx_count: rs_http2_state_get_tx_count,
1149 get_tx: rs_http2_state_get_tx,
1150 tx_get_comp_st: rs_http2_state_progress_completion_status,
1151 tx_get_progress: rs_http2_tx_get_alstate_progress,
1152 get_de_state: rs_http2_tx_get_detect_state,
1153 set_de_state: rs_http2_tx_set_detect_state,
1154 get_events: Some(rs_http2_state_get_events),
1155 get_eventinfo: Some(rs_http2_state_get_event_info),
1156 get_eventinfo_byid: Some(rs_http2_state_get_event_info_by_id),
1157 localstorage_new: None,
1158 localstorage_free: None,
1159 get_files: Some(rs_http2_getfiles),
1160 get_tx_iterator: Some(rs_http2_state_get_tx_iterator),
1161 get_tx_data: rs_http2_get_tx_data,
1162 apply_tx_config: None,
1163 flags: 0,
1164 truncate: None,
1165 };
1166
1167 let ip_proto_str = CString::new("tcp").unwrap();
1168
1169 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1170 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1171 ALPROTO_HTTP2 = alproto;
1172 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1173 let _ = AppLayerRegisterParser(&parser, alproto);
1174 }
1175 SCLogDebug!("Rust http2 parser registered.");
1176 } else {
1177 SCLogNotice!("Protocol detector and parser disabled for HTTP2.");
1178 }
1179 }