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