*/
use super::http2::{
- HTTP2Frame, HTTP2FrameTypeData, HTTP2State, HTTP2Transaction, HTTP2TransactionState,
+ HTTP2Event, HTTP2Frame, HTTP2FrameTypeData, HTTP2State, HTTP2Transaction, HTTP2TransactionState,
};
use super::parser;
use crate::core::STREAM_TOSERVER;
-use crate::log::*;
use std::ffi::CStr;
use std::mem::transmute;
use std::str::FromStr;
http2_tx_set_header(state, ":path".as_bytes(), slice)
}
+#[derive(Debug, PartialEq)]
+pub enum Http2Base64Error {
+ InvalidBase64,
+}
+
+impl std::error::Error for Http2Base64Error {}
+
+impl std::fmt::Display for Http2Base64Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "invalid base64")
+ }
+}
+
+fn http2_base64_map(input: u8) -> Result<u8, Http2Base64Error> {
+ match input {
+ 43 => Ok(62), // +
+ 47 => Ok(63), // /
+ 48 => Ok(52), // 0
+ 49 => Ok(53), // 1
+ 50 => Ok(54), // 2
+ 51 => Ok(55), // 3
+ 52 => Ok(56), // 4
+ 53 => Ok(57), // 5
+ 54 => Ok(58), // 6
+ 55 => Ok(59), // 7
+ 56 => Ok(60), // 8
+ 57 => Ok(61), // 9
+ 65 => Ok(0), // A
+ 66 => Ok(1), // B
+ 67 => Ok(2), // C
+ 68 => Ok(3), // D
+ 69 => Ok(4), // E
+ 70 => Ok(5), // F
+ 71 => Ok(6), // G
+ 72 => Ok(7), // H
+ 73 => Ok(8), // I
+ 74 => Ok(9), // J
+ 75 => Ok(10), // K
+ 76 => Ok(11), // L
+ 77 => Ok(12), // M
+ 78 => Ok(13), // N
+ 79 => Ok(14), // O
+ 80 => Ok(15), // P
+ 81 => Ok(16), // Q
+ 82 => Ok(17), // R
+ 83 => Ok(18), // S
+ 84 => Ok(19), // T
+ 85 => Ok(20), // U
+ 86 => Ok(21), // V
+ 87 => Ok(22), // W
+ 88 => Ok(23), // X
+ 89 => Ok(24), // Y
+ 90 => Ok(25), // Z
+ 97 => Ok(26), // a
+ 98 => Ok(27), // b
+ 99 => Ok(28), // c
+ 100 => Ok(29), // d
+ 101 => Ok(30), // e
+ 102 => Ok(31), // f
+ 103 => Ok(32), // g
+ 104 => Ok(33), // h
+ 105 => Ok(34), // i
+ 106 => Ok(35), // j
+ 107 => Ok(36), // k
+ 108 => Ok(37), // l
+ 109 => Ok(38), // m
+ 110 => Ok(39), // n
+ 111 => Ok(40), // o
+ 112 => Ok(41), // p
+ 113 => Ok(42), // q
+ 114 => Ok(43), // r
+ 115 => Ok(44), // s
+ 116 => Ok(45), // t
+ 117 => Ok(46), // u
+ 118 => Ok(47), // v
+ 119 => Ok(48), // w
+ 120 => Ok(49), // x
+ 121 => Ok(50), // y
+ 122 => Ok(51), // z
+ _ => Err(Http2Base64Error::InvalidBase64),
+ }
+}
+
+fn http2_decode_base64(input: &[u8]) -> Result<Vec<u8>, Http2Base64Error> {
+ if input.len() % 4 != 0 {
+ return Err(Http2Base64Error::InvalidBase64);
+ }
+ let mut r = vec![0; (input.len() * 3) / 4];
+ for i in 0..input.len() / 4 {
+ let i1 = http2_base64_map(input[4 * i])?;
+ let i2 = http2_base64_map(input[4 * i + 1])?;
+ let i3 = http2_base64_map(input[4 * i + 2])?;
+ let i4 = http2_base64_map(input[4 * i + 3])?;
+ r[3 * i] = (i1 << 2) | (i2 >> 4);
+ r[3 * i + 1] = (i2 << 4) | (i3 >> 2);
+ r[3 * i + 2] = (i3 << 6) | i4;
+ }
+ return Ok(r);
+}
+
+fn http2_tx_set_settings(state: &mut HTTP2State, input: &[u8]) {
+ match http2_decode_base64(input) {
+ Ok(dec) => {
+ if dec.len() % 6 != 0 {
+ state.set_event(HTTP2Event::InvalidHTTP1Settings);
+ }
+
+ let head = parser::HTTP2FrameHeader {
+ length: dec.len() as u32,
+ ftype: parser::HTTP2FrameType::SETTINGS as u8,
+ flags: 0,
+ reserved: 0,
+ stream_id: 0,
+ };
+
+ match parser::http2_parse_frame_settings(&dec) {
+ Ok((_, set)) => {
+ let txdata = HTTP2FrameTypeData::SETTINGS(set);
+ let tx = state.find_or_create_tx(&head, &txdata, STREAM_TOSERVER);
+ tx.frames_ts.push(HTTP2Frame {
+ header: head,
+ data: txdata,
+ });
+ }
+ Err(_) => {
+ state.set_event(HTTP2Event::InvalidHTTP1Settings);
+ }
+ }
+ }
+ Err(_) => {
+ state.set_event(HTTP2Event::InvalidHTTP1Settings);
+ }
+ }
+}
+
#[no_mangle]
pub extern "C" fn rs_http2_tx_add_header(
state: &mut HTTP2State, name: *const u8, name_len: u32, value: *const u8, value_len: u32,
let slice_name = build_slice!(name, name_len as usize);
let slice_value = build_slice!(value, value_len as usize);
if slice_name == "HTTP2-Settings".as_bytes() {
- SCLogNotice!("lol seetings TODO");
+ http2_tx_set_settings(state, slice_value)
} else {
http2_tx_set_header(state, slice_name, slice_value)
}
ExtraHeaderData,
LongFrameData,
StreamIdReuse,
+ InvalidHTTP1Settings,
}
impl HTTP2Event {
5 => Some(HTTP2Event::ExtraHeaderData),
6 => Some(HTTP2Event::LongFrameData),
7 => Some(HTTP2Event::StreamIdReuse),
+ 8 => Some(HTTP2Event::InvalidHTTP1Settings),
_ => None,
}
}
self.files.free();
}
- fn set_event(&mut self, event: HTTP2Event) {
+ pub fn set_event(&mut self, event: HTTP2Event) {
let len = self.transactions.len();
if len == 0 {
return;
"extra_header_data" => HTTP2Event::ExtraHeaderData as i32,
"long_frame_data" => HTTP2Event::LongFrameData as i32,
"stream_id_reuse" => HTTP2Event::StreamIdReuse as i32,
+ "invalid_http1_settings" => HTTP2Event::InvalidHTTP1Settings as i32,
_ => -1, // unknown event
}
}
HTTP2Event::ExtraHeaderData => "extra_header_data\0",
HTTP2Event::LongFrameData => "long_frame_data\0",
HTTP2Event::StreamIdReuse => "stream_id_reuse\0",
+ HTTP2Event::InvalidHTTP1Settings => "invalid_http1_settings\0",
};
unsafe {
*event_name = estr.as_ptr() as *const std::os::raw::c_char;