* 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;
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)
+ }
+}
pub struct HTTP2Transaction {
tx_id: u64,
pub stream_id: u32,
- state: HTTP2TransactionState,
+ pub state: HTTP2TransactionState,
child_stream_id: u32,
pub frames_tc: Vec<HTTP2Frame>,
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 {
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]
}
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) {
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;
void HtpConfigCreateBackup(void);
void HtpConfigRestoreBackup(void);
+void *HtpGetTxForH2(void *);
+
#endif /* __APP_LAYER_HTP_H__ */
/**
#include "app-layer-detect-proto.h"
#include "app-layer-parser.h"
+#include "app-layer-htp.h"
#include "app-layer-http2.h"
#include "rust.h"
//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));
+ }
+ }
+}
void RegisterHTTP2Parsers(void);
+void HTTP2MimicHttp1Request(void *, void *);
+
#endif /* __APP_LAYER_HTTP2_H__ */