diff --git a/rust/src/http2/detect.rs b/rust/src/http2/detect.rs index f2ff45ebbb..8778a44abb 100644 --- a/rust/src/http2/detect.rs +++ b/rust/src/http2/detect.rs @@ -15,9 +15,12 @@ * 02110-1301, USA. */ -use super::http2::{HTTP2FrameTypeData, HTTP2Transaction}; +use super::http2::{ + 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; @@ -544,3 +547,61 @@ pub unsafe extern "C" fn rs_http2_tx_get_header( return 0; } + +fn http2_tx_set_header(state: &mut HTTP2State, name: &[u8], input: &[u8]) { + let head = parser::HTTP2FrameHeader { + length: 0, + ftype: parser::HTTP2FrameType::HEADERS as u8, + flags: 0, + reserved: 0, + stream_id: 1, + }; + let mut blocks = Vec::new(); + let b = parser::HTTP2FrameHeaderBlock { + name: name.to_vec(), + value: input.to_vec(), + error: parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSuccess, + sizeupdate: 0, + }; + blocks.push(b); + let hs = parser::HTTP2FrameHeaders { + padlength: None, + priority: None, + blocks: blocks, + }; + let txdata = HTTP2FrameTypeData::HEADERS(hs); + let tx = state.find_or_create_tx(&head, &txdata, STREAM_TOSERVER); + tx.frames_ts.push(HTTP2Frame { + header: head, + data: txdata, + }); + //we do not expect more data from client + tx.state = HTTP2TransactionState::HTTP2StateHalfClosedClient; +} + +#[no_mangle] +pub extern "C" fn rs_http2_tx_set_method( + state: &mut HTTP2State, buffer: *const u8, buffer_len: u32, +) { + let slice = build_slice!(buffer, buffer_len as usize); + http2_tx_set_header(state, ":method".as_bytes(), slice) +} + +#[no_mangle] +pub extern "C" fn rs_http2_tx_set_uri(state: &mut HTTP2State, buffer: *const u8, buffer_len: u32) { + let slice = build_slice!(buffer, buffer_len as usize); + http2_tx_set_header(state, ":path".as_bytes(), slice) +} + +#[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"); + } else { + http2_tx_set_header(state, slice_name, slice_value) + } +} diff --git a/rust/src/http2/http2.rs b/rust/src/http2/http2.rs index e2dd984dba..3ee0e29973 100644 --- a/rust/src/http2/http2.rs +++ b/rust/src/http2/http2.rs @@ -117,7 +117,7 @@ pub struct HTTP2Frame { pub struct HTTP2Transaction { tx_id: u64, pub stream_id: u32, - state: HTTP2TransactionState, + pub state: HTTP2TransactionState, child_stream_id: u32, pub frames_tc: Vec, @@ -373,7 +373,7 @@ impl HTTP2State { return self.transactions.last_mut().unwrap(); } - fn find_or_create_tx( + pub fn find_or_create_tx( &mut self, header: &parser::HTTP2FrameHeader, data: &HTTP2FrameTypeData, dir: u8, ) -> &mut HTTP2Transaction { if header.stream_id == 0 { @@ -876,11 +876,27 @@ pub extern "C" fn rs_http2_probing_parser_tc( return ALPROTO_UNKNOWN; } +/// Extern functions operating on HTTP2. +extern "C" { + pub fn HTTP2MimicHttp1Request( + orig_state: *mut std::os::raw::c_void, new_state: *mut std::os::raw::c_void, + ); +} + #[no_mangle] -pub extern "C" fn rs_http2_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void { +pub extern "C" fn rs_http2_state_new( + orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto, +) -> *mut std::os::raw::c_void { let state = HTTP2State::new(); let boxed = Box::new(state); - return unsafe { transmute(boxed) }; + let r = unsafe { transmute(boxed) }; + if orig_state != std::ptr::null_mut() { + //we could check ALPROTO_HTTP == orig_proto + unsafe { + HTTP2MimicHttp1Request(orig_state, r); + } + } + return r; } #[no_mangle] diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index 2c2a49f4e7..08df37d654 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -968,13 +968,6 @@ static AppLayerResult HTPHandleResponseData(Flow *f, void *htp_state, } consumed = htp_connp_res_data_consumed(hstate->connp); AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_HTTP2); - // close connection to log HTTP1 request in tunnel mode - if (!(hstate->flags & HTP_FLAG_STATE_CLOSED_TC)) { - htp_connp_close(hstate->connp, &ts); - hstate->flags |= HTP_FLAG_STATE_CLOSED_TC; - } - // TODO mimic HTTP1 request into HTTP2 - // During HTTP2 upgrade, we may consume the HTTP1 part of the data // and we need to parser the remaining part with HTTP2 if (consumed > 0 && consumed < input_len) { @@ -2958,6 +2951,19 @@ static void *HTPStateGetTx(void *alstate, uint64_t tx_id) return NULL; } +void *HtpGetTxForH2(void *alstate) +{ + // gets last transaction + HtpState *http_state = (HtpState *)alstate; + if (http_state != NULL && http_state->conn != NULL) { + size_t txid = htp_list_array_size(http_state->conn->transactions); + if (txid > 0) { + return htp_list_get(http_state->conn->transactions, txid - 1); + } + } + return NULL; +} + static int HTPStateGetAlstateProgressCompletionStatus(uint8_t direction) { return (direction & STREAM_TOSERVER) ? HTP_REQUEST_COMPLETE : HTP_RESPONSE_COMPLETE; diff --git a/src/app-layer-htp.h b/src/app-layer-htp.h index 72acc41d3a..dee49f5c19 100644 --- a/src/app-layer-htp.h +++ b/src/app-layer-htp.h @@ -288,6 +288,8 @@ void HTPConfigure(void); void HtpConfigCreateBackup(void); void HtpConfigRestoreBackup(void); +void *HtpGetTxForH2(void *); + #endif /* __APP_LAYER_HTP_H__ */ /** diff --git a/src/app-layer-http2.c b/src/app-layer-http2.c index c937c5a539..8576697780 100644 --- a/src/app-layer-http2.c +++ b/src/app-layer-http2.c @@ -32,6 +32,7 @@ #include "app-layer-detect-proto.h" #include "app-layer-parser.h" +#include "app-layer-htp.h" #include "app-layer-http2.h" #include "rust.h" @@ -69,3 +70,22 @@ void RegisterHTTP2Parsers(void) //TODOask HTTP2ParserRegisterTests(); #endif } + +void HTTP2MimicHttp1Request(void *alstate_orig, void *h2s) +{ + htp_tx_t *h1tx = HtpGetTxForH2(alstate_orig); + if (h2s == NULL || h1tx == NULL) { + return; + } + + rs_http2_tx_set_method(h2s, bstr_ptr(h1tx->request_method), bstr_len(h1tx->request_method)); + rs_http2_tx_set_uri(h2s, bstr_ptr(h1tx->request_uri), bstr_len(h1tx->request_uri)); + size_t nbheaders = htp_table_size(h1tx->request_headers); + for (size_t i = 0; i < nbheaders; i++) { + htp_header_t *h = htp_table_get_index(h1tx->request_headers, i, NULL); + if (h != NULL) { + rs_http2_tx_add_header(h2s, bstr_ptr(h->name), bstr_len(h->name), bstr_ptr(h->value), + bstr_len(h->value)); + } + } +} diff --git a/src/app-layer-http2.h b/src/app-layer-http2.h index 043cf7b30c..b3c52c1d70 100644 --- a/src/app-layer-http2.h +++ b/src/app-layer-http2.h @@ -26,4 +26,6 @@ void RegisterHTTP2Parsers(void); +void HTTP2MimicHttp1Request(void *, void *); + #endif /* __APP_LAYER_HTTP2_H__ */