]> git.ipfire.org Git - people/ms/suricata.git/commitdiff
http2: generic http2_header_blocks
authorPhilippe Antoine <contact@catenacyber.fr>
Mon, 31 May 2021 09:40:42 +0000 (11:40 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 3 Sep 2021 08:37:00 +0000 (10:37 +0200)
so as not to forget continuation and push promise
when iterating over headers

rust/src/http2/detect.rs

index 979c8c08a4c470c11f6eaa824461f5f3083d2156..05ea3f8b9421bb22e78c8d78426a264d3b45b710 100644 (file)
@@ -341,38 +341,38 @@ pub unsafe extern "C" fn rs_detect_u64_free(ctx: *mut std::os::raw::c_void) {
 }
 
 fn http2_detect_sizeupdate_match(
-    hd: &parser::HTTP2FrameHeaders, ctx: &parser::DetectU64Data,
+    blocks: &Vec<parser::HTTP2FrameHeaderBlock>, ctx: &parser::DetectU64Data,
 ) -> std::os::raw::c_int {
-    for i in 0..hd.blocks.len() {
+    for i in 0..blocks.len() {
         match ctx.mode {
             parser::DetectUintMode::DetectUintModeEqual => {
-                if hd.blocks[i].sizeupdate == ctx.value
-                    && hd.blocks[i].error
+                if blocks[i].sizeupdate == ctx.value
+                    && blocks[i].error
                         == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
                 {
                     return 1;
                 }
             }
             parser::DetectUintMode::DetectUintModeLt => {
-                if hd.blocks[i].sizeupdate <= ctx.value
-                    && hd.blocks[i].error
+                if blocks[i].sizeupdate <= ctx.value
+                    && blocks[i].error
                         == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
                 {
                     return 1;
                 }
             }
             parser::DetectUintMode::DetectUintModeGt => {
-                if hd.blocks[i].sizeupdate >= ctx.value
-                    && hd.blocks[i].error
+                if blocks[i].sizeupdate >= ctx.value
+                    && blocks[i].error
                         == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
                 {
                     return 1;
                 }
             }
             parser::DetectUintMode::DetectUintModeRange => {
-                if hd.blocks[i].sizeupdate <= ctx.value
-                    && hd.blocks[i].sizeupdate >= ctx.valrange
-                    && hd.blocks[i].error
+                if blocks[i].sizeupdate <= ctx.value
+                    && blocks[i].sizeupdate >= ctx.valrange
+                    && blocks[i].error
                         == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
                 {
                     return 1;
@@ -383,29 +383,39 @@ fn http2_detect_sizeupdate_match(
     return 0;
 }
 
+fn http2_header_blocks(frame: &HTTP2Frame) -> Option<&Vec<parser::HTTP2FrameHeaderBlock>> {
+    match &frame.data {
+        HTTP2FrameTypeData::HEADERS(hd) => {
+            return Some(&hd.blocks);
+        }
+        HTTP2FrameTypeData::CONTINUATION(hd) => {
+            return Some(&hd.blocks);
+        }
+        HTTP2FrameTypeData::PUSHPROMISE(hd) => {
+            return Some(&hd.blocks);
+        }
+        _ => {}
+    }
+    return None;
+}
+
 fn http2_detect_sizeupdatectx_match(
     ctx: &mut parser::DetectU64Data, tx: &mut HTTP2Transaction, direction: u8,
 ) -> std::os::raw::c_int {
     if direction & STREAM_TOSERVER != 0 {
         for i in 0..tx.frames_ts.len() {
-            match &tx.frames_ts[i].data {
-                HTTP2FrameTypeData::HEADERS(hd) => {
-                    if http2_detect_sizeupdate_match(hd, ctx) != 0 {
-                        return 1;
-                    }
+            if let Some(blocks) = http2_header_blocks(&tx.frames_ts[i]) {
+                if http2_detect_sizeupdate_match(blocks, ctx) != 0 {
+                    return 1;
                 }
-                _ => {}
             }
         }
     } else {
         for i in 0..tx.frames_tc.len() {
-            match &tx.frames_tc[i].data {
-                HTTP2FrameTypeData::HEADERS(hd) => {
-                    if http2_detect_sizeupdate_match(hd, ctx) != 0 {
-                        return 1;
-                    }
+            if let Some(blocks) = http2_header_blocks(&tx.frames_tc[i]) {
+                if http2_detect_sizeupdate_match(blocks, ctx) != 0 {
+                    return 1;
                 }
-                _ => {}
             }
         }
     }
@@ -430,34 +440,28 @@ pub unsafe extern "C" fn rs_http2_tx_get_header_name(
     let mut pos = 0 as u32;
     if direction & STREAM_TOSERVER != 0 {
         for i in 0..tx.frames_ts.len() {
-            match &tx.frames_ts[i].data {
-                HTTP2FrameTypeData::HEADERS(hd) => {
-                    if nb < pos + hd.blocks.len() as u32 {
-                        let value = &hd.blocks[(nb - pos) as usize].name;
-                        *buffer = value.as_ptr(); //unsafe
-                        *buffer_len = value.len() as u32;
-                        return 1;
-                    } else {
-                        pos = pos + hd.blocks.len() as u32;
-                    }
+            if let Some(blocks) = http2_header_blocks(&tx.frames_ts[i]) {
+                if nb < pos + blocks.len() as u32 {
+                    let value = &blocks[(nb - pos) as usize].name;
+                    *buffer = value.as_ptr(); //unsafe
+                    *buffer_len = value.len() as u32;
+                    return 1;
+                } else {
+                    pos = pos + blocks.len() as u32;
                 }
-                _ => {}
             }
         }
     } else {
         for i in 0..tx.frames_tc.len() {
-            match &tx.frames_tc[i].data {
-                HTTP2FrameTypeData::HEADERS(hd) => {
-                    if nb < pos + hd.blocks.len() as u32 {
-                        let value = &hd.blocks[(nb - pos) as usize].name;
-                        *buffer = value.as_ptr(); //unsafe
-                        *buffer_len = value.len() as u32;
-                        return 1;
-                    } else {
-                        pos = pos + hd.blocks.len() as u32;
-                    }
+            if let Some(blocks) = http2_header_blocks(&tx.frames_tc[i]) {
+                if nb < pos + blocks.len() as u32 {
+                    let value = &blocks[(nb - pos) as usize].name;
+                    *buffer = value.as_ptr(); //unsafe
+                    *buffer_len = value.len() as u32;
+                    return 1;
+                } else {
+                    pos = pos + blocks.len() as u32;
                 }
-                _ => {}
             }
         }
     }
@@ -479,23 +483,10 @@ fn http2_frames_get_header_value<'a>(
     frames: &'a Vec<HTTP2Frame>, name: &str,
 ) -> Result<&'a [u8], ()> {
     for i in 0..frames.len() {
-        match &frames[i].data {
-            HTTP2FrameTypeData::HEADERS(hd) => {
-                if let Ok(value) = http2_blocks_get_header_value(&hd.blocks, name) {
-                    return Ok(value);
-                }
+        if let Some(blocks) = http2_header_blocks(&frames[i]) {
+            if let Ok(value) = http2_blocks_get_header_value(&blocks, name) {
+                return Ok(value);
             }
-            HTTP2FrameTypeData::PUSHPROMISE(hd) => {
-                if let Ok(value) = http2_blocks_get_header_value(&hd.blocks, name) {
-                    return Ok(value);
-                }
-            }
-            HTTP2FrameTypeData::CONTINUATION(hd) => {
-                if let Ok(value) = http2_blocks_get_header_value(&hd.blocks, name) {
-                    return Ok(value);
-                }
-            }
-            _ => {}
         }
     }
 
@@ -657,21 +648,21 @@ pub unsafe extern "C" fn rs_http2_tx_get_header_value(
     return 0;
 }
 
-fn http2_escape_header(hd: &parser::HTTP2FrameHeaders, i: u32) -> Vec<u8> {
+fn http2_escape_header(blocks: &Vec<parser::HTTP2FrameHeaderBlock>, i: u32) -> Vec<u8> {
     //minimum size + 2 for escapes
-    let normalsize = hd.blocks[i as usize].value.len() + 2 + hd.blocks[i as usize].name.len() + 2;
+    let normalsize = blocks[i as usize].value.len() + 2 + blocks[i as usize].name.len() + 2;
     let mut vec = Vec::with_capacity(normalsize);
-    for j in 0..hd.blocks[i as usize].name.len() {
-        vec.push(hd.blocks[i as usize].name[j]);
-        if hd.blocks[i as usize].name[j] == ':' as u8 {
+    for j in 0..blocks[i as usize].name.len() {
+        vec.push(blocks[i as usize].name[j]);
+        if blocks[i as usize].name[j] == ':' as u8 {
             vec.push(':' as u8);
         }
     }
     vec.push(':' as u8);
     vec.push(' ' as u8);
-    for j in 0..hd.blocks[i as usize].value.len() {
-        vec.push(hd.blocks[i as usize].value[j]);
-        if hd.blocks[i as usize].value[j] == ':' as u8 {
+    for j in 0..blocks[i as usize].value.len() {
+        vec.push(blocks[i as usize].value[j]);
+        if blocks[i as usize].value[j] == ':' as u8 {
             vec.push(':' as u8);
         }
     }
@@ -691,16 +682,13 @@ pub unsafe extern "C" fn rs_http2_tx_get_header_names(
         &tx.frames_tc
     };
     for i in 0..frames.len() {
-        match &frames[i].data {
-            HTTP2FrameTypeData::HEADERS(hd) => {
-                for j in 0..hd.blocks.len() {
-                    // we do not escape linefeeds in headers names
-                    vec.extend_from_slice(&hd.blocks[j].name);
-                    vec.push('\r' as u8);
-                    vec.push('\n' as u8);
-                }
+        if let Some(blocks) = http2_header_blocks(&frames[i]) {
+            for j in 0..blocks.len() {
+                // we do not escape linefeeds in headers names
+                vec.extend_from_slice(&blocks[j].name);
+                vec.push('\r' as u8);
+                vec.push('\n' as u8);
             }
-            _ => {}
         }
     }
     if vec.len() > 2 {
@@ -762,21 +750,18 @@ pub unsafe extern "C" fn rs_http2_tx_get_headers(
         &tx.frames_tc
     };
     for i in 0..frames.len() {
-        match &frames[i].data {
-            HTTP2FrameTypeData::HEADERS(hd) => {
-                for j in 0..hd.blocks.len() {
-                    if !http2_header_iscookie(direction, &hd.blocks[j].name) {
-                        // we do not escape linefeeds nor : in headers names
-                        vec.extend_from_slice(&hd.blocks[j].name);
-                        vec.push(':' as u8);
-                        vec.push(' ' as u8);
-                        vec.extend_from_slice(http2_header_trimspaces(&hd.blocks[j].value));
-                        vec.push('\r' as u8);
-                        vec.push('\n' as u8);
-                    }
+        if let Some(blocks) = http2_header_blocks(&frames[i]) {
+            for j in 0..blocks.len() {
+                if !http2_header_iscookie(direction, &blocks[j].name) {
+                    // we do not escape linefeeds nor : in headers names
+                    vec.extend_from_slice(&blocks[j].name);
+                    vec.push(':' as u8);
+                    vec.push(' ' as u8);
+                    vec.extend_from_slice(http2_header_trimspaces(&blocks[j].value));
+                    vec.push('\r' as u8);
+                    vec.push('\n' as u8);
                 }
             }
-            _ => {}
         }
     }
     if vec.len() > 0 {
@@ -801,19 +786,16 @@ pub unsafe extern "C" fn rs_http2_tx_get_headers_raw(
         &tx.frames_tc
     };
     for i in 0..frames.len() {
-        match &frames[i].data {
-            HTTP2FrameTypeData::HEADERS(hd) => {
-                for j in 0..hd.blocks.len() {
-                    // we do not escape linefeeds nor : in headers names
-                    vec.extend_from_slice(&hd.blocks[j].name);
-                    vec.push(':' as u8);
-                    vec.push(' ' as u8);
-                    vec.extend_from_slice(&hd.blocks[j].value);
-                    vec.push('\r' as u8);
-                    vec.push('\n' as u8);
-                }
+        if let Some(blocks) = http2_header_blocks(&frames[i]) {
+            for j in 0..blocks.len() {
+                // we do not escape linefeeds nor : in headers names
+                vec.extend_from_slice(&blocks[j].name);
+                vec.push(':' as u8);
+                vec.push(' ' as u8);
+                vec.extend_from_slice(&blocks[j].value);
+                vec.push('\r' as u8);
+                vec.push('\n' as u8);
             }
-            _ => {}
         }
     }
     if vec.len() > 0 {
@@ -834,40 +816,34 @@ pub unsafe extern "C" fn rs_http2_tx_get_header(
     let mut pos = 0 as u32;
     if direction & STREAM_TOSERVER != 0 {
         for i in 0..tx.frames_ts.len() {
-            match &tx.frames_ts[i].data {
-                HTTP2FrameTypeData::HEADERS(hd) => {
-                    if nb < pos + hd.blocks.len() as u32 {
-                        let ehdr = http2_escape_header(hd, nb - pos);
-                        tx.escaped.push(ehdr);
-                        let idx = tx.escaped.len() - 1;
-                        let value = &tx.escaped[idx];
-                        *buffer = value.as_ptr(); //unsafe
-                        *buffer_len = value.len() as u32;
-                        return 1;
-                    } else {
-                        pos = pos + hd.blocks.len() as u32;
-                    }
+            if let Some(blocks) = http2_header_blocks(&tx.frames_ts[i]) {
+                if nb < pos + blocks.len() as u32 {
+                    let ehdr = http2_escape_header(&blocks, nb - pos);
+                    tx.escaped.push(ehdr);
+                    let idx = tx.escaped.len() - 1;
+                    let value = &tx.escaped[idx];
+                    *buffer = value.as_ptr(); //unsafe
+                    *buffer_len = value.len() as u32;
+                    return 1;
+                } else {
+                    pos = pos + blocks.len() as u32;
                 }
-                _ => {}
             }
         }
     } else {
         for i in 0..tx.frames_tc.len() {
-            match &tx.frames_tc[i].data {
-                HTTP2FrameTypeData::HEADERS(hd) => {
-                    if nb < pos + hd.blocks.len() as u32 {
-                        let ehdr = http2_escape_header(hd, nb - pos);
-                        tx.escaped.push(ehdr);
-                        let idx = tx.escaped.len() - 1;
-                        let value = &tx.escaped[idx];
-                        *buffer = value.as_ptr(); //unsafe
-                        *buffer_len = value.len() as u32;
-                        return 1;
-                    } else {
-                        pos = pos + hd.blocks.len() as u32;
-                    }
+            if let Some(blocks) = http2_header_blocks(&tx.frames_tc[i]) {
+                if nb < pos + blocks.len() as u32 {
+                    let ehdr = http2_escape_header(&blocks, nb - pos);
+                    tx.escaped.push(ehdr);
+                    let idx = tx.escaped.len() - 1;
+                    let value = &tx.escaped[idx];
+                    *buffer = value.as_ptr(); //unsafe
+                    *buffer_len = value.len() as u32;
+                    return 1;
+                } else {
+                    pos = pos + blocks.len() as u32;
                 }
-                _ => {}
             }
         }
     }