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::huffman;
19 use crate::http2::http2::{HTTP2DynTable, HTTP2_MAX_TABLESIZE};
20 use nom::character::complete::digit1;
21 use nom::combinator::rest;
22 use nom::error::ErrorKind;
23 use nom::number::streaming::{be_u16, be_u32, be_u8};
24 use nom::Err;
25 use nom::IResult;
26 use std::fmt;
27 use std::str::FromStr;
28 
29 #[repr(u8)]
30 #[derive(Clone, Copy, PartialEq, FromPrimitive, Debug)]
31 pub enum HTTP2FrameType {
32     DATA = 0,
33     HEADERS = 1,
34     PRIORITY = 2,
35     RSTSTREAM = 3,
36     SETTINGS = 4,
37     PUSHPROMISE = 5,
38     PING = 6,
39     GOAWAY = 7,
40     WINDOWUPDATE = 8,
41     CONTINUATION = 9,
42 }
43 
44 impl fmt::Display for HTTP2FrameType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result45     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46         write!(f, "{:?}", self)
47     }
48 }
49 
50 impl std::str::FromStr for HTTP2FrameType {
51     type Err = String;
52 
from_str(s: &str) -> Result<Self, Self::Err>53     fn from_str(s: &str) -> Result<Self, Self::Err> {
54         let su = s.to_uppercase();
55         let su_slice: &str = &*su;
56         match su_slice {
57             "DATA" => Ok(HTTP2FrameType::DATA),
58             "HEADERS" => Ok(HTTP2FrameType::HEADERS),
59             "PRIORITY" => Ok(HTTP2FrameType::PRIORITY),
60             "RSTSTREAM" => Ok(HTTP2FrameType::RSTSTREAM),
61             "SETTINGS" => Ok(HTTP2FrameType::SETTINGS),
62             "PUSHPROMISE" => Ok(HTTP2FrameType::PUSHPROMISE),
63             "PING" => Ok(HTTP2FrameType::PING),
64             "GOAWAY" => Ok(HTTP2FrameType::GOAWAY),
65             "WINDOWUPDATE" => Ok(HTTP2FrameType::WINDOWUPDATE),
66             "CONTINUATION" => Ok(HTTP2FrameType::CONTINUATION),
67             _ => Err(format!("'{}' is not a valid value for HTTP2FrameType", s)),
68         }
69     }
70 }
71 
72 #[derive(PartialEq, Debug)]
73 pub struct HTTP2FrameHeader {
74     //we could add detection on (GOAWAY) additional data
75     pub length: u32,
76     pub ftype: u8,
77     pub flags: u8,
78     pub reserved: u8,
79     pub stream_id: u32,
80 }
81 
82 named!(pub http2_parse_frame_header<HTTP2FrameHeader>,
83     do_parse!(
84         length: bits!( take_bits!(24u32) ) >>
85         ftype: be_u8 >>
86         flags: be_u8 >>
87         stream_id: bits!( tuple!( take_bits!(1u8),
88                                   take_bits!(31u32) ) ) >>
89         (HTTP2FrameHeader{length, ftype, flags,
90                           reserved:stream_id.0,
91                           stream_id:stream_id.1})
92     )
93 );
94 
95 #[repr(u32)]
96 #[derive(Clone, Copy, PartialEq, FromPrimitive, Debug)]
97 pub enum HTTP2ErrorCode {
98     NOERROR = 0,
99     PROTOCOLERROR = 1,
100     INTERNALERROR = 2,
101     FLOWCONTROLERROR = 3,
102     SETTINGSTIMEOUT = 4,
103     STREAMCLOSED = 5,
104     FRAMESIZEERROR = 6,
105     REFUSEDSTREAM = 7,
106     CANCEL = 8,
107     COMPRESSIONERROR = 9,
108     CONNECTERROR = 10,
109     ENHANCEYOURCALM = 11,
110     INADEQUATESECURITY = 12,
111     HTTP11REQUIRED = 13,
112 }
113 
114 impl fmt::Display for HTTP2ErrorCode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result115     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116         write!(f, "{:?}", self)
117     }
118 }
119 
120 impl std::str::FromStr for HTTP2ErrorCode {
121     type Err = String;
122 
from_str(s: &str) -> Result<Self, Self::Err>123     fn from_str(s: &str) -> Result<Self, Self::Err> {
124         let su = s.to_uppercase();
125         let su_slice: &str = &*su;
126         match su_slice {
127             "NO_ERROR" => Ok(HTTP2ErrorCode::NOERROR),
128             "PROTOCOL_ERROR" => Ok(HTTP2ErrorCode::PROTOCOLERROR),
129             "FLOW_CONTROL_ERROR" => Ok(HTTP2ErrorCode::FLOWCONTROLERROR),
130             "SETTINGS_TIMEOUT" => Ok(HTTP2ErrorCode::SETTINGSTIMEOUT),
131             "STREAM_CLOSED" => Ok(HTTP2ErrorCode::STREAMCLOSED),
132             "FRAME_SIZE_ERROR" => Ok(HTTP2ErrorCode::FRAMESIZEERROR),
133             "REFUSED_STREAM" => Ok(HTTP2ErrorCode::REFUSEDSTREAM),
134             "CANCEL" => Ok(HTTP2ErrorCode::CANCEL),
135             "COMPRESSION_ERROR" => Ok(HTTP2ErrorCode::COMPRESSIONERROR),
136             "CONNECT_ERROR" => Ok(HTTP2ErrorCode::CONNECTERROR),
137             "ENHANCE_YOUR_CALM" => Ok(HTTP2ErrorCode::ENHANCEYOURCALM),
138             "INADEQUATE_SECURITY" => Ok(HTTP2ErrorCode::INADEQUATESECURITY),
139             "HTTP_1_1_REQUIRED" => Ok(HTTP2ErrorCode::HTTP11REQUIRED),
140             _ => Err(format!("'{}' is not a valid value for HTTP2ErrorCode", s)),
141         }
142     }
143 }
144 
145 #[derive(Clone, Copy, Debug)]
146 pub struct HTTP2FrameGoAway {
147     pub errorcode: u32, //HTTP2ErrorCode
148 }
149 
150 named!(pub http2_parse_frame_goaway<HTTP2FrameGoAway>,
151     do_parse!(
152         errorcode: be_u32 >>
153         (HTTP2FrameGoAway{errorcode})
154     )
155 );
156 
157 #[derive(Clone, Copy, Debug)]
158 pub struct HTTP2FrameRstStream {
159     pub errorcode: u32, ////HTTP2ErrorCode
160 }
161 
162 named!(pub http2_parse_frame_rststream<HTTP2FrameRstStream>,
163     do_parse!(
164         errorcode: be_u32 >>
165         (HTTP2FrameRstStream{errorcode})
166     )
167 );
168 
169 #[derive(Clone, Copy, Debug)]
170 pub struct HTTP2FramePriority {
171     pub exclusive: u8,
172     pub dependency: u32,
173     pub weight: u8,
174 }
175 
176 named!(pub http2_parse_frame_priority<HTTP2FramePriority>,
177     do_parse!(
178         sid: bits!( tuple!( take_bits!(1u8),
179                             take_bits!(31u32) ) ) >>
180         weight: be_u8 >>
181         (HTTP2FramePriority{exclusive:sid.0, dependency:sid.1, weight})
182     )
183 );
184 
185 #[derive(Clone, Copy, Debug)]
186 pub struct HTTP2FrameWindowUpdate {
187     pub reserved: u8,
188     pub sizeinc: u32,
189 }
190 
191 named!(pub http2_parse_frame_windowupdate<HTTP2FrameWindowUpdate>,
192     do_parse!(
193         sizeinc: bits!( tuple!( take_bits!(1u8),
194                                 take_bits!(31u32) ) ) >>
195         (HTTP2FrameWindowUpdate{reserved:sizeinc.0, sizeinc:sizeinc.1})
196     )
197 );
198 
199 #[derive(Clone, Copy, Debug)]
200 pub struct HTTP2FrameHeadersPriority {
201     pub exclusive: u8,
202     pub dependency: u32,
203     pub weight: u8,
204 }
205 
206 named!(pub http2_parse_headers_priority<HTTP2FrameHeadersPriority>,
207     do_parse!(
208         sid: bits!( tuple!( take_bits!(1u8),
209                                 take_bits!(31u32) ) ) >>
210         weight: be_u8 >>
211         (HTTP2FrameHeadersPriority{exclusive:sid.0, dependency:sid.1, weight})
212     )
213 );
214 
215 pub const HTTP2_STATIC_HEADERS_NUMBER: usize = 61;
216 
http2_frame_header_static(n: u64, dyn_headers: &HTTP2DynTable) -> Option<HTTP2FrameHeaderBlock>217 fn http2_frame_header_static(n: u64, dyn_headers: &HTTP2DynTable) -> Option<HTTP2FrameHeaderBlock> {
218     let (name, value) = match n {
219         1 => (":authority", ""),
220         2 => (":method", "GET"),
221         3 => (":method", "POST"),
222         4 => (":path", "/"),
223         5 => (":path", "/index.html"),
224         6 => (":scheme", "http"),
225         7 => (":scheme", "https"),
226         8 => (":status", "200"),
227         9 => (":status", "204"),
228         10 => (":status", "206"),
229         11 => (":status", "304"),
230         12 => (":status", "400"),
231         13 => (":status", "404"),
232         14 => (":status", "500"),
233         15 => ("accept-charset", ""),
234         16 => ("accept-encoding", "gzip, deflate"),
235         17 => ("accept-language", ""),
236         18 => ("accept-ranges", ""),
237         19 => ("accept", ""),
238         20 => ("access-control-allow-origin", ""),
239         21 => ("age", ""),
240         22 => ("allow", ""),
241         23 => ("authorization", ""),
242         24 => ("cache-control", ""),
243         25 => ("content-disposition", ""),
244         26 => ("content-encoding", ""),
245         27 => ("content-language", ""),
246         28 => ("content-length", ""),
247         29 => ("content-location", ""),
248         30 => ("content-range", ""),
249         31 => ("content-type", ""),
250         32 => ("cookie", ""),
251         33 => ("date", ""),
252         34 => ("etag", ""),
253         35 => ("expect", ""),
254         36 => ("expires", ""),
255         37 => ("from", ""),
256         38 => ("host", ""),
257         39 => ("if-match", ""),
258         40 => ("if-modified-since", ""),
259         41 => ("if-none-match", ""),
260         42 => ("if-range", ""),
261         43 => ("if-unmodified-since", ""),
262         44 => ("last-modified", ""),
263         45 => ("link", ""),
264         46 => ("location", ""),
265         47 => ("max-forwards", ""),
266         48 => ("proxy-authenticate", ""),
267         49 => ("proxy-authorization", ""),
268         50 => ("range", ""),
269         51 => ("referer", ""),
270         52 => ("refresh", ""),
271         53 => ("retry-after", ""),
272         54 => ("server", ""),
273         55 => ("set-cookie", ""),
274         56 => ("strict-transport-security", ""),
275         57 => ("transfer-encoding", ""),
276         58 => ("user-agent", ""),
277         59 => ("vary", ""),
278         60 => ("via", ""),
279         61 => ("www-authenticate", ""),
280         _ => ("", ""),
281     };
282     if name.len() > 0 {
283         return Some(HTTP2FrameHeaderBlock {
284             name: name.as_bytes().to_vec(),
285             value: value.as_bytes().to_vec(),
286             error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess,
287             sizeupdate: 0,
288         });
289     } else {
290         //use dynamic table
291         if n == 0 {
292             return Some(HTTP2FrameHeaderBlock {
293                 name: Vec::new(),
294                 value: Vec::new(),
295                 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIndex0,
296                 sizeupdate: 0,
297             });
298         } else if dyn_headers.table.len() + HTTP2_STATIC_HEADERS_NUMBER < n as usize {
299             return Some(HTTP2FrameHeaderBlock {
300                 name: Vec::new(),
301                 value: Vec::new(),
302                 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeNotIndexed,
303                 sizeupdate: 0,
304             });
305         } else {
306             let indyn = dyn_headers.table.len() - (n as usize - HTTP2_STATIC_HEADERS_NUMBER);
307             let headcopy = HTTP2FrameHeaderBlock {
308                 name: dyn_headers.table[indyn].name.to_vec(),
309                 value: dyn_headers.table[indyn].value.to_vec(),
310                 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess,
311                 sizeupdate: 0,
312             };
313             return Some(headcopy);
314         }
315     }
316 }
317 
318 #[repr(u8)]
319 #[derive(Copy, Clone, PartialOrd, PartialEq, Debug)]
320 pub enum HTTP2HeaderDecodeStatus {
321     HTTP2HeaderDecodeSuccess = 0,
322     HTTP2HeaderDecodeSizeUpdate = 1,
323     HTTP2HeaderDecodeError = 0x80,
324     HTTP2HeaderDecodeNotIndexed = 0x81,
325     HTTP2HeaderDecodeIntegerOverflow = 0x82,
326     HTTP2HeaderDecodeIndex0 = 0x83,
327 }
328 
329 impl fmt::Display for HTTP2HeaderDecodeStatus {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result330     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
331         write!(f, "{:?}", self)
332     }
333 }
334 
335 #[derive(Clone, Debug)]
336 pub struct HTTP2FrameHeaderBlock {
337     pub name: Vec<u8>,
338     pub value: Vec<u8>,
339     pub error: HTTP2HeaderDecodeStatus,
340     pub sizeupdate: u64,
341 }
342 
http2_parse_headers_block_indexed<'a>( input: &'a [u8], dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>343 fn http2_parse_headers_block_indexed<'a>(
344     input: &'a [u8], dyn_headers: &HTTP2DynTable,
345 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
346     fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
347         bits!(
348             input,
349             complete!(tuple!(
350                 verify!(take_bits!(1u8), |&x| x == 1),
351                 take_bits!(7u8)
352             ))
353         )
354     }
355     let (i2, indexed) = parser(input)?;
356     let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0x7F)?;
357     if indexreal == 0 && indexed.1 == 0x7F {
358         return Err(Err::Error((i3, ErrorKind::LengthValue)));
359     }
360     match http2_frame_header_static(indexreal, dyn_headers) {
361         Some(h) => Ok((i3, h)),
362         _ => Err(Err::Error((i3, ErrorKind::MapOpt))),
363     }
364 }
365 
http2_parse_headers_block_string(input: &[u8]) -> IResult<&[u8], Vec<u8>>366 fn http2_parse_headers_block_string(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
367     fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
368         bits!(input, tuple!(take_bits!(1u8), take_bits!(7u8)))
369     }
370     let (i1, huffslen) = parser(input)?;
371     let (i2, stringlen) = http2_parse_var_uint(i1, huffslen.1 as u64, 0x7F)?;
372     if stringlen == 0 && huffslen.1 == 0x7F {
373         return Err(Err::Error((i2, ErrorKind::LengthValue)));
374     }
375     let (i3, data) = take!(i2, stringlen as usize)?;
376     if huffslen.0 == 0 {
377         return Ok((i3, data.to_vec()));
378     } else {
379         let (_, val) = bits!(data, many0!(huffman::http2_decode_huffman))?;
380         return Ok((i3, val));
381     }
382 }
383 
http2_parse_headers_block_literal_common<'a>( input: &'a [u8], index: u64, dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>384 fn http2_parse_headers_block_literal_common<'a>(
385     input: &'a [u8], index: u64, dyn_headers: &HTTP2DynTable,
386 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
387     let (i3, name, error) = if index == 0 {
388         match http2_parse_headers_block_string(input) {
389             Ok((r, n)) => Ok((r, n, HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess)),
390             Err(e) => Err(e),
391         }
392     } else {
393         match http2_frame_header_static(index, dyn_headers) {
394             Some(x) => Ok((
395                 input,
396                 x.name,
397                 HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess,
398             )),
399             None => Ok((
400                 input,
401                 Vec::new(),
402                 HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeNotIndexed,
403             )),
404         }
405     }?;
406     let (i4, value) = http2_parse_headers_block_string(i3)?;
407     return Ok((
408         i4,
409         HTTP2FrameHeaderBlock {
410             name,
411             value,
412             error,
413             sizeupdate: 0,
414         },
415     ));
416 }
417 
http2_parse_headers_block_literal_incindex<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>418 fn http2_parse_headers_block_literal_incindex<'a>(
419     input: &'a [u8], dyn_headers: &mut HTTP2DynTable,
420 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
421     fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
422         bits!(
423             input,
424             complete!(tuple!(
425                 verify!(take_bits!(2u8), |&x| x == 1),
426                 take_bits!(6u8)
427             ))
428         )
429     }
430     let (i2, indexed) = parser(input)?;
431     let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0x3F)?;
432     if indexreal == 0 && indexed.1 == 0x3F {
433         return Err(Err::Error((i3, ErrorKind::LengthValue)));
434     }
435     let r = http2_parse_headers_block_literal_common(i3, indexreal, dyn_headers);
436     match r {
437         Ok((r, head)) => {
438             let headcopy = HTTP2FrameHeaderBlock {
439                 name: head.name.to_vec(),
440                 value: head.value.to_vec(),
441                 error: head.error,
442                 sizeupdate: 0,
443             };
444             if head.error == HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess {
445                 dyn_headers.current_size += 32 + headcopy.name.len() + headcopy.value.len();
446                 //in case of overflow, best effort is to keep first headers
447                 if dyn_headers.overflow > 0 {
448                     if dyn_headers.overflow == 1 {
449                         if dyn_headers.current_size <= (HTTP2_MAX_TABLESIZE as usize) {
450                             //overflow had not yet happened
451                             dyn_headers.table.push(headcopy);
452                         } else if dyn_headers.current_size > dyn_headers.max_size {
453                             //overflow happens, we cannot replace evicted headers
454                             dyn_headers.overflow = 2;
455                         }
456                     }
457                 } else {
458                     dyn_headers.table.push(headcopy);
459                 }
460                 while dyn_headers.current_size > dyn_headers.max_size && dyn_headers.table.len() > 0
461                 {
462                     dyn_headers.current_size -=
463                         32 + dyn_headers.table[0].name.len() + dyn_headers.table[0].value.len();
464                     dyn_headers.table.remove(0);
465                 }
466             }
467             return Ok((r, head));
468         }
469         Err(e) => {
470             return Err(e);
471         }
472     }
473 }
474 
http2_parse_headers_block_literal_noindex<'a>( input: &'a [u8], dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>475 fn http2_parse_headers_block_literal_noindex<'a>(
476     input: &'a [u8], dyn_headers: &HTTP2DynTable,
477 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
478     fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
479         bits!(
480             input,
481             complete!(tuple!(
482                 verify!(take_bits!(4u8), |&x| x == 0),
483                 take_bits!(4u8)
484             ))
485         )
486     }
487     let (i2, indexed) = parser(input)?;
488     let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0xF)?;
489     if indexreal == 0 && indexed.1 == 0xF {
490         return Err(Err::Error((i3, ErrorKind::LengthValue)));
491     }
492     let r = http2_parse_headers_block_literal_common(i3, indexreal, dyn_headers);
493     return r;
494 }
495 
http2_parse_headers_block_literal_neverindex<'a>( input: &'a [u8], dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>496 fn http2_parse_headers_block_literal_neverindex<'a>(
497     input: &'a [u8], dyn_headers: &HTTP2DynTable,
498 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
499     fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
500         bits!(
501             input,
502             complete!(tuple!(
503                 verify!(take_bits!(4u8), |&x| x == 1),
504                 take_bits!(4u8)
505             ))
506         )
507     }
508     let (i2, indexed) = parser(input)?;
509     let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0xF)?;
510     if indexreal == 0 && indexed.1 == 0xF {
511         return Err(Err::Error((i3, ErrorKind::LengthValue)));
512     }
513     let r = http2_parse_headers_block_literal_common(i3, indexreal, dyn_headers);
514     return r;
515 }
516 
http2_parse_var_uint(input: &[u8], value: u64, max: u64) -> IResult<&[u8], u64>517 fn http2_parse_var_uint(input: &[u8], value: u64, max: u64) -> IResult<&[u8], u64> {
518     if value < max {
519         return Ok((input, value));
520     }
521     let (i2, varia) = take_while!(input, |ch| (ch & 0x80) != 0)?;
522     let (i3, finalv) = be_u8(i2)?;
523     if varia.len() > 9 || (varia.len() == 9 && finalv > 1) {
524         // this will overflow u64
525         return Ok((i3, 0));
526     }
527     let mut varval = max;
528     for i in 0..varia.len() {
529         varval += ((varia[i] & 0x7F) as u64) << (7 * i);
530     }
531     varval += (finalv as u64) << (7 * varia.len());
532     if varval < max {
533         // this has overflown u64
534         return Ok((i3, 0));
535     }
536     return Ok((i3, varval));
537 }
538 
http2_parse_headers_block_dynamic_size<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>539 fn http2_parse_headers_block_dynamic_size<'a>(
540     input: &'a [u8], dyn_headers: &mut HTTP2DynTable,
541 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
542     fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
543         bits!(
544             input,
545             complete!(tuple!(
546                 verify!(take_bits!(3u8), |&x| x == 1),
547                 take_bits!(5u8)
548             ))
549         )
550     }
551     let (i2, maxsize) = parser(input)?;
552     let (i3, maxsize2) = http2_parse_var_uint(i2, maxsize.1 as u64, 0x1F)?;
553     if maxsize2 == 0 && maxsize.1 == 0x1F {
554         return Ok((
555             i3,
556             HTTP2FrameHeaderBlock {
557                 name: Vec::new(),
558                 value: Vec::new(),
559                 error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIntegerOverflow,
560                 sizeupdate: 0,
561             },
562         ));
563     }
564     if (maxsize2 as usize) < dyn_headers.max_size {
565         //dyn_headers.max_size is updated later with all headers
566         //may evict entries
567         while dyn_headers.current_size > (maxsize2 as usize) && dyn_headers.table.len() > 0 {
568             // we check dyn_headers.table as we may be in best effort
569             // because the previous maxsize was too big for us to retain all the headers
570             dyn_headers.current_size -=
571                 32 + dyn_headers.table[0].name.len() + dyn_headers.table[0].value.len();
572             dyn_headers.table.remove(0);
573         }
574     }
575     return Ok((
576         i3,
577         HTTP2FrameHeaderBlock {
578             name: Vec::new(),
579             value: Vec::new(),
580             error: HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate,
581             sizeupdate: maxsize2,
582         },
583     ));
584 }
585 
http2_parse_headers_block<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock>586 fn http2_parse_headers_block<'a>(
587     input: &'a [u8], dyn_headers: &mut HTTP2DynTable,
588 ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> {
589     //caller garantees o have at least one byte
590     if input[0] & 0x80 != 0 {
591         return http2_parse_headers_block_indexed(input, dyn_headers);
592     } else if input[0] & 0x40 != 0 {
593         return http2_parse_headers_block_literal_incindex(input, dyn_headers);
594     } else if input[0] & 0x20 != 0 {
595         return http2_parse_headers_block_dynamic_size(input, dyn_headers);
596     } else if input[0] & 0x10 != 0 {
597         return http2_parse_headers_block_literal_neverindex(input, dyn_headers);
598     } else {
599         return http2_parse_headers_block_literal_noindex(input, dyn_headers);
600     }
601 }
602 
603 #[derive(Clone, Debug)]
604 pub struct HTTP2FrameHeaders {
605     pub padlength: Option<u8>,
606     pub priority: Option<HTTP2FrameHeadersPriority>,
607     pub blocks: Vec<HTTP2FrameHeaderBlock>,
608 }
609 
610 //end stream
611 pub const HTTP2_FLAG_HEADER_EOS: u8 = 0x1;
612 pub const HTTP2_FLAG_HEADER_END_HEADERS: u8 = 0x4;
613 const HTTP2_FLAG_HEADER_PADDED: u8 = 0x8;
614 const HTTP2_FLAG_HEADER_PRIORITY: u8 = 0x20;
615 
http2_parse_frame_headers<'a>( input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaders>616 pub fn http2_parse_frame_headers<'a>(
617     input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable,
618 ) -> IResult<&'a [u8], HTTP2FrameHeaders> {
619     let (i2, padlength) = cond!(input, flags & HTTP2_FLAG_HEADER_PADDED != 0, be_u8)?;
620     let (mut i3, priority) = cond!(
621         i2,
622         flags & HTTP2_FLAG_HEADER_PRIORITY != 0,
623         http2_parse_headers_priority
624     )?;
625     let mut blocks = Vec::new();
626     while i3.len() > 0 {
627         match http2_parse_headers_block(i3, dyn_headers) {
628             Ok((rem, b)) => {
629                 blocks.push(b);
630                 debug_validate_bug_on!(i3.len() == rem.len());
631                 if i3.len() == rem.len() {
632                     //infinite loop
633                     return Err(Err::Error((input, ErrorKind::Eof)));
634                 }
635                 i3 = rem;
636             }
637             Err(x) => {
638                 return Err(x);
639             }
640         }
641     }
642     return Ok((
643         i3,
644         HTTP2FrameHeaders {
645             padlength,
646             priority,
647             blocks,
648         },
649     ));
650 }
651 
652 #[derive(Clone, Debug)]
653 pub struct HTTP2FramePushPromise {
654     pub padlength: Option<u8>,
655     pub reserved: u8,
656     pub stream_id: u32,
657     pub blocks: Vec<HTTP2FrameHeaderBlock>,
658 }
659 
http2_parse_frame_push_promise<'a>( input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FramePushPromise>660 pub fn http2_parse_frame_push_promise<'a>(
661     input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable,
662 ) -> IResult<&'a [u8], HTTP2FramePushPromise> {
663     let (i2, padlength) = cond!(input, flags & HTTP2_FLAG_HEADER_PADDED != 0, be_u8)?;
664     let (mut i3, stream_id) = bits!(i2, tuple!(take_bits!(1u8), take_bits!(31u32)))?;
665     let mut blocks = Vec::new();
666     while i3.len() > 0 {
667         match http2_parse_headers_block(i3, dyn_headers) {
668             Ok((rem, b)) => {
669                 blocks.push(b);
670                 debug_validate_bug_on!(i3.len() == rem.len());
671                 if i3.len() == rem.len() {
672                     //infinite loop
673                     return Err(Err::Error((input, ErrorKind::Eof)));
674                 }
675                 i3 = rem;
676             }
677             Err(x) => {
678                 return Err(x);
679             }
680         }
681     }
682     return Ok((
683         i3,
684         HTTP2FramePushPromise {
685             padlength,
686             reserved: stream_id.0,
687             stream_id: stream_id.1,
688             blocks,
689         },
690     ));
691 }
692 
693 #[derive(Clone, Debug)]
694 pub struct HTTP2FrameContinuation {
695     pub blocks: Vec<HTTP2FrameHeaderBlock>,
696 }
697 
http2_parse_frame_continuation<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameContinuation>698 pub fn http2_parse_frame_continuation<'a>(
699     input: &'a [u8], dyn_headers: &mut HTTP2DynTable,
700 ) -> IResult<&'a [u8], HTTP2FrameContinuation> {
701     let mut i3 = input;
702     let mut blocks = Vec::new();
703     while i3.len() > 0 {
704         match http2_parse_headers_block(i3, dyn_headers) {
705             Ok((rem, b)) => {
706                 blocks.push(b);
707                 debug_validate_bug_on!(i3.len() == rem.len());
708                 if i3.len() == rem.len() {
709                     //infinite loop
710                     return Err(Err::Error((input, ErrorKind::Eof)));
711                 }
712                 i3 = rem;
713             }
714             Err(x) => {
715                 return Err(x);
716             }
717         }
718     }
719     return Ok((i3, HTTP2FrameContinuation { blocks }));
720 }
721 
722 #[repr(u16)]
723 #[derive(Clone, Copy, PartialEq, FromPrimitive, Debug)]
724 pub enum HTTP2SettingsId {
725     SETTINGSHEADERTABLESIZE = 1,
726     SETTINGSENABLEPUSH = 2,
727     SETTINGSMAXCONCURRENTSTREAMS = 3,
728     SETTINGSINITIALWINDOWSIZE = 4,
729     SETTINGSMAXFRAMESIZE = 5,
730     SETTINGSMAXHEADERLISTSIZE = 6,
731 }
732 
733 impl fmt::Display for HTTP2SettingsId {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result734     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
735         write!(f, "{:?}", self)
736     }
737 }
738 
739 impl std::str::FromStr for HTTP2SettingsId {
740     type Err = String;
741 
from_str(s: &str) -> Result<Self, Self::Err>742     fn from_str(s: &str) -> Result<Self, Self::Err> {
743         let su = s.to_uppercase();
744         let su_slice: &str = &*su;
745         match su_slice {
746             "SETTINGS_HEADER_TABLE_SIZE" => Ok(HTTP2SettingsId::SETTINGSHEADERTABLESIZE),
747             "SETTINGS_ENABLE_PUSH" => Ok(HTTP2SettingsId::SETTINGSENABLEPUSH),
748             "SETTINGS_MAX_CONCURRENT_STREAMS" => Ok(HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS),
749             "SETTINGS_INITIAL_WINDOW_SIZE" => Ok(HTTP2SettingsId::SETTINGSINITIALWINDOWSIZE),
750             "SETTINGS_MAX_FRAME_SIZE" => Ok(HTTP2SettingsId::SETTINGSMAXFRAMESIZE),
751             "SETTINGS_MAX_HEADER_LIST_SIZE" => Ok(HTTP2SettingsId::SETTINGSMAXHEADERLISTSIZE),
752             _ => Err(format!("'{}' is not a valid value for HTTP2SettingsId", s)),
753         }
754     }
755 }
756 
757 //TODOask move elsewhere generic with DetectU64Data and such
758 #[derive(PartialEq, Debug)]
759 pub enum DetectUintMode {
760     DetectUintModeEqual,
761     DetectUintModeLt,
762     DetectUintModeGt,
763     DetectUintModeRange,
764 }
765 
766 pub struct DetectU32Data {
767     pub value: u32,
768     pub valrange: u32,
769     pub mode: DetectUintMode,
770 }
771 
772 pub struct DetectHTTP2settingsSigCtx {
773     pub id: HTTP2SettingsId,          //identifier
774     pub value: Option<DetectU32Data>, //optional value
775 }
776 
777 named!(detect_parse_u32_start_equal<&str,DetectU32Data>,
778     do_parse!(
779         opt!( is_a!( " " ) ) >>
780         opt! (tag!("=") ) >>
781         opt!( is_a!( " " ) ) >>
782         value : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
783         (DetectU32Data{value, valrange:0, mode:DetectUintMode::DetectUintModeEqual})
784     )
785 );
786 
787 named!(detect_parse_u32_start_interval<&str,DetectU32Data>,
788     do_parse!(
789         opt!( is_a!( " " ) ) >>
790         value : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
791         opt!( is_a!( " " ) ) >>
792         tag!("-") >>
793         opt!( is_a!( " " ) ) >>
794         valrange : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
795         (DetectU32Data{value, valrange, mode:DetectUintMode::DetectUintModeRange})
796     )
797 );
798 
799 named!(detect_parse_u32_start_lesser<&str,DetectU32Data>,
800     do_parse!(
801         opt!( is_a!( " " ) ) >>
802         tag!("<") >>
803         opt!( is_a!( " " ) ) >>
804         value : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
805         (DetectU32Data{value, valrange:0, mode:DetectUintMode::DetectUintModeLt})
806     )
807 );
808 
809 named!(detect_parse_u32_start_greater<&str,DetectU32Data>,
810     do_parse!(
811         opt!( is_a!( " " ) ) >>
812         tag!(">") >>
813         opt!( is_a!( " " ) ) >>
814         value : map_opt!(digit1, |s: &str| s.parse::<u32>().ok()) >>
815         (DetectU32Data{value, valrange:0, mode:DetectUintMode::DetectUintModeGt})
816     )
817 );
818 
819 named!(detect_parse_u32<&str,DetectU32Data>,
820     do_parse!(
821         u32 : alt! (
822             detect_parse_u32_start_lesser |
823             detect_parse_u32_start_greater |
824             complete!( detect_parse_u32_start_interval ) |
825             detect_parse_u32_start_equal
826         ) >>
827         (u32)
828     )
829 );
830 
831 named!(pub http2_parse_settingsctx<&str,DetectHTTP2settingsSigCtx>,
832     do_parse!(
833         opt!( is_a!( " " ) ) >>
834         id: map_opt!( alt! ( complete!( is_not!( " <>=" ) ) | rest ),
835             |s: &str| HTTP2SettingsId::from_str(s).ok() ) >>
836         value: opt!( complete!( detect_parse_u32 ) ) >>
837         (DetectHTTP2settingsSigCtx{id, value})
838     )
839 );
840 
841 pub struct DetectU64Data {
842     pub value: u64,
843     pub valrange: u64,
844     pub mode: DetectUintMode,
845 }
846 
847 named!(detect_parse_u64_start_equal<&str,DetectU64Data>,
848     do_parse!(
849         opt!( is_a!( " " ) ) >>
850         opt! (tag!("=") ) >>
851         opt!( is_a!( " " ) ) >>
852         value : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
853         (DetectU64Data{value, valrange:0, mode:DetectUintMode::DetectUintModeEqual})
854     )
855 );
856 
857 named!(detect_parse_u64_start_interval<&str,DetectU64Data>,
858     do_parse!(
859         opt!( is_a!( " " ) ) >>
860         value : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
861         opt!( is_a!( " " ) ) >>
862         tag!("-") >>
863         opt!( is_a!( " " ) ) >>
864         valrange : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
865         (DetectU64Data{value, valrange, mode:DetectUintMode::DetectUintModeRange})
866     )
867 );
868 
869 named!(detect_parse_u64_start_lesser<&str,DetectU64Data>,
870     do_parse!(
871         opt!( is_a!( " " ) ) >>
872         tag!("<") >>
873         opt!( is_a!( " " ) ) >>
874         value : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
875         (DetectU64Data{value, valrange:0, mode:DetectUintMode::DetectUintModeLt})
876     )
877 );
878 
879 named!(detect_parse_u64_start_greater<&str,DetectU64Data>,
880     do_parse!(
881         opt!( is_a!( " " ) ) >>
882         tag!(">") >>
883         opt!( is_a!( " " ) ) >>
884         value : map_opt!(digit1, |s: &str| s.parse::<u64>().ok()) >>
885         (DetectU64Data{value, valrange:0, mode:DetectUintMode::DetectUintModeGt})
886     )
887 );
888 
889 named!(pub detect_parse_u64<&str,DetectU64Data>,
890     do_parse!(
891         u64 : alt! (
892             detect_parse_u64_start_lesser |
893             detect_parse_u64_start_greater |
894             complete!( detect_parse_u64_start_interval ) |
895             detect_parse_u64_start_equal
896         ) >>
897         (u64)
898     )
899 );
900 
901 #[derive(Clone, Copy, Debug)]
902 pub struct HTTP2FrameSettings {
903     pub id: HTTP2SettingsId,
904     pub value: u32,
905 }
906 
907 named!(
908     http2_parse_frame_setting<HTTP2FrameSettings>,
909     do_parse!(
910         id: map_opt!(be_u16, num::FromPrimitive::from_u16)
911             >> value: be_u32
912             >> (HTTP2FrameSettings { id, value })
913     )
914 );
915 
916 named!(pub http2_parse_frame_settings<Vec<HTTP2FrameSettings>>,
917     many0!( complete!(http2_parse_frame_setting) )
918 );
919 
920 #[cfg(test)]
921 mod tests {
922 
923     use super::*;
924 
925     #[test]
test_http2_parse_header()926     fn test_http2_parse_header() {
927         let buf0: &[u8] = &[0x82];
928         let mut dynh = HTTP2DynTable::new();
929         let r0 = http2_parse_headers_block(buf0, &mut dynh);
930         match r0 {
931             Ok((remainder, hd)) => {
932                 // Check the first message.
933                 assert_eq!(hd.name, ":method".as_bytes().to_vec());
934                 assert_eq!(hd.value, "GET".as_bytes().to_vec());
935                 // And we should have no bytes left.
936                 assert_eq!(remainder.len(), 0);
937             }
938             Err(Err::Incomplete(_)) => {
939                 panic!("Result should not have been incomplete.");
940             }
941             Err(Err::Error(err)) | Err(Err::Failure(err)) => {
942                 panic!("Result should not be an error: {:?}.", err);
943             }
944         }
945         let buf1: &[u8] = &[0x53, 0x03, 0x2A, 0x2F, 0x2A];
946         let r1 = http2_parse_headers_block(buf1, &mut dynh);
947         match r1 {
948             Ok((remainder, hd)) => {
949                 // Check the first message.
950                 assert_eq!(hd.name, "accept".as_bytes().to_vec());
951                 assert_eq!(hd.value, "*/*".as_bytes().to_vec());
952                 // And we should have no bytes left.
953                 assert_eq!(remainder.len(), 0);
954                 assert_eq!(dynh.table.len(), 1);
955             }
956             Err(Err::Incomplete(_)) => {
957                 panic!("Result should not have been incomplete.");
958             }
959             Err(Err::Error(err)) | Err(Err::Failure(err)) => {
960                 panic!("Result should not be an error: {:?}.", err);
961             }
962         }
963         let buf: &[u8] = &[
964             0x41, 0x8a, 0xa0, 0xe4, 0x1d, 0x13, 0x9d, 0x09, 0xb8, 0xc8, 0x00, 0x0f,
965         ];
966         let result = http2_parse_headers_block(buf, &mut dynh);
967         match result {
968             Ok((remainder, hd)) => {
969                 // Check the first message.
970                 assert_eq!(hd.name, ":authority".as_bytes().to_vec());
971                 assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec());
972                 // And we should have no bytes left.
973                 assert_eq!(remainder.len(), 0);
974                 assert_eq!(dynh.table.len(), 2);
975             }
976             Err(Err::Incomplete(_)) => {
977                 panic!("Result should not have been incomplete.");
978             }
979             Err(Err::Error(err)) | Err(Err::Failure(err)) => {
980                 panic!("Result should not be an error: {:?}.", err);
981             }
982         }
983         let buf3: &[u8] = &[0xbe];
984         let r3 = http2_parse_headers_block(buf3, &mut dynh);
985         match r3 {
986             Ok((remainder, hd)) => {
987                 // same as before
988                 assert_eq!(hd.name, ":authority".as_bytes().to_vec());
989                 assert_eq!(hd.value, "localhost:3000".as_bytes().to_vec());
990                 // And we should have no bytes left.
991                 assert_eq!(remainder.len(), 0);
992                 assert_eq!(dynh.table.len(), 2);
993             }
994             Err(Err::Incomplete(_)) => {
995                 panic!("Result should not have been incomplete.");
996             }
997             Err(Err::Error(err)) | Err(Err::Failure(err)) => {
998                 panic!("Result should not be an error: {:?}.", err);
999             }
1000         }
1001         let buf4: &[u8] = &[0x80];
1002         let r4 = http2_parse_headers_block(buf4, &mut dynh);
1003         match r4 {
1004             Ok((remainder, hd)) => {
1005                 assert_eq!(hd.error, HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeIndex0);
1006                 assert_eq!(remainder.len(), 0);
1007                 assert_eq!(dynh.table.len(), 2);
1008             }
1009             Err(Err::Incomplete(_)) => {
1010                 panic!("Result should not have been incomplete.");
1011             }
1012             Err(Err::Error(err)) | Err(Err::Failure(err)) => {
1013                 panic!("Result should not be an error: {:?}.", err);
1014             }
1015         }
1016         let buf2: &[u8] = &[
1017             0x04, 0x94, 0x62, 0x43, 0x91, 0x8a, 0x47, 0x55, 0xa3, 0xa1, 0x89, 0xd3, 0x4d, 0x0c,
1018             0x1a, 0xa9, 0x0b, 0xe5, 0x79, 0xd3, 0x4d, 0x1f,
1019         ];
1020         let r2 = http2_parse_headers_block(buf2, &mut dynh);
1021         match r2 {
1022             Ok((remainder, hd)) => {
1023                 // Check the first message.
1024                 assert_eq!(hd.name, ":path".as_bytes().to_vec());
1025                 assert_eq!(hd.value, "/doc/manual/html/index.html".as_bytes().to_vec());
1026                 // And we should have no bytes left.
1027                 assert_eq!(remainder.len(), 0);
1028                 assert_eq!(dynh.table.len(), 2);
1029             }
1030             Err(Err::Incomplete(_)) => {
1031                 panic!("Result should not have been incomplete.");
1032             }
1033             Err(Err::Error(err)) | Err(Err::Failure(err)) => {
1034                 panic!("Result should not be an error: {:?}.", err);
1035             }
1036         }
1037     }
1038 
1039     /// Simple test of some valid data.
1040     #[test]
test_http2_parse_settingsctx()1041     fn test_http2_parse_settingsctx() {
1042         let s = "SETTINGS_ENABLE_PUSH";
1043         let r = http2_parse_settingsctx(s);
1044         match r {
1045             Ok((rem, ctx)) => {
1046                 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSENABLEPUSH);
1047                 match ctx.value {
1048                     Some(_) => {
1049                         panic!("Unexpected value");
1050                     }
1051                     None => {}
1052                 }
1053                 assert_eq!(rem.len(), 0);
1054             }
1055             Err(e) => {
1056                 panic!("Result should not be an error {:?}.", e);
1057             }
1058         }
1059 
1060         //spaces in the end
1061         let s1 = "SETTINGS_ENABLE_PUSH ";
1062         let r1 = http2_parse_settingsctx(s1);
1063         match r1 {
1064             Ok((rem, ctx)) => {
1065                 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSENABLEPUSH);
1066                 match ctx.value {
1067                     Some(_) => {
1068                         panic!("Unexpected value");
1069                     }
1070                     None => {}
1071                 }
1072                 assert_eq!(rem.len(), 1);
1073             }
1074             Err(e) => {
1075                 panic!("Result should not be an error {:?}.", e);
1076             }
1077         }
1078 
1079         let s2 = "SETTINGS_MAX_CONCURRENT_STREAMS  42";
1080         let r2 = http2_parse_settingsctx(s2);
1081         match r2 {
1082             Ok((rem, ctx)) => {
1083                 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
1084                 match ctx.value {
1085                     Some(ctxval) => {
1086                         assert_eq!(ctxval.value, 42);
1087                     }
1088                     None => {
1089                         panic!("No value");
1090                     }
1091                 }
1092                 assert_eq!(rem.len(), 0);
1093             }
1094             Err(e) => {
1095                 panic!("Result should not be an error {:?}.", e);
1096             }
1097         }
1098 
1099         let s3 = "SETTINGS_MAX_CONCURRENT_STREAMS 42-68";
1100         let r3 = http2_parse_settingsctx(s3);
1101         match r3 {
1102             Ok((rem, ctx)) => {
1103                 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
1104                 match ctx.value {
1105                     Some(ctxval) => {
1106                         assert_eq!(ctxval.value, 42);
1107                         assert_eq!(ctxval.mode, DetectUintMode::DetectUintModeRange);
1108                         assert_eq!(ctxval.valrange, 68);
1109                     }
1110                     None => {
1111                         panic!("No value");
1112                     }
1113                 }
1114                 assert_eq!(rem.len(), 0);
1115             }
1116             Err(e) => {
1117                 panic!("Result should not be an error {:?}.", e);
1118             }
1119         }
1120 
1121         let s4 = "SETTINGS_MAX_CONCURRENT_STREAMS<54";
1122         let r4 = http2_parse_settingsctx(s4);
1123         match r4 {
1124             Ok((rem, ctx)) => {
1125                 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
1126                 match ctx.value {
1127                     Some(ctxval) => {
1128                         assert_eq!(ctxval.value, 54);
1129                         assert_eq!(ctxval.mode, DetectUintMode::DetectUintModeLt);
1130                     }
1131                     None => {
1132                         panic!("No value");
1133                     }
1134                 }
1135                 assert_eq!(rem.len(), 0);
1136             }
1137             Err(e) => {
1138                 panic!("Result should not be an error {:?}.", e);
1139             }
1140         }
1141 
1142         let s5 = "SETTINGS_MAX_CONCURRENT_STREAMS > 76";
1143         let r5 = http2_parse_settingsctx(s5);
1144         match r5 {
1145             Ok((rem, ctx)) => {
1146                 assert_eq!(ctx.id, HTTP2SettingsId::SETTINGSMAXCONCURRENTSTREAMS);
1147                 match ctx.value {
1148                     Some(ctxval) => {
1149                         assert_eq!(ctxval.value, 76);
1150                         assert_eq!(ctxval.mode, DetectUintMode::DetectUintModeGt);
1151                     }
1152                     None => {
1153                         panic!("No value");
1154                     }
1155                 }
1156                 assert_eq!(rem.len(), 0);
1157             }
1158             Err(e) => {
1159                 panic!("Result should not be an error {:?}.", e);
1160             }
1161         }
1162     }
1163 
1164     #[test]
test_http2_parse_headers_block_string()1165     fn test_http2_parse_headers_block_string() {
1166         let buf: &[u8] = &[0x01, 0xFF];
1167         let r = http2_parse_headers_block_string(buf);
1168         match r {
1169             Ok((remainder, _)) => {
1170                 assert_eq!(remainder.len(), 0);
1171             }
1172             Err(Err::Error(err)) | Err(Err::Failure(err)) => {
1173                 panic!("Result should not be an error: {:?}.", err);
1174             }
1175             _ => {
1176                 panic!("Result should have been ok");
1177             }
1178         }
1179         let buf2: &[u8] = &[0x83, 0xFF, 0xFF, 0xEA];
1180         let r2 = http2_parse_headers_block_string(buf2);
1181         match r2 {
1182             Ok((remainder, _)) => {
1183                 assert_eq!(remainder.len(), 0);
1184             }
1185             _ => {
1186                 panic!("Result should have been ok");
1187             }
1188         }
1189     }
1190 
1191     #[test]
test_http2_parse_frame_header()1192     fn test_http2_parse_frame_header() {
1193         let buf: &[u8] = &[
1194             0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1195             0x64,
1196         ];
1197         let result = http2_parse_frame_header(buf);
1198         match result {
1199             Ok((remainder, frame)) => {
1200                 // Check the first message.
1201                 assert_eq!(frame.length, 6);
1202                 assert_eq!(frame.ftype, HTTP2FrameType::SETTINGS as u8);
1203                 assert_eq!(frame.flags, 0);
1204                 assert_eq!(frame.reserved, 0);
1205                 assert_eq!(frame.stream_id, 0);
1206 
1207                 // And we should have 6 bytes left.
1208                 assert_eq!(remainder.len(), 6);
1209             }
1210             Err(Err::Incomplete(_)) => {
1211                 panic!("Result should not have been incomplete.");
1212             }
1213             Err(Err::Error(err)) | Err(Err::Failure(err)) => {
1214                 panic!("Result should not be an error: {:?}.", err);
1215             }
1216         }
1217     }
1218 }
1219