|
|
|
|
@ -31,16 +31,13 @@
|
|
|
|
|
static const char htp_tx[] = "suricata:http:tx";
|
|
|
|
|
|
|
|
|
|
struct LuaTx {
|
|
|
|
|
htp_tx_t *tx;
|
|
|
|
|
void *tx;
|
|
|
|
|
AppProto alproto;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int LuaHttpGetTx(lua_State *luastate)
|
|
|
|
|
static int LuaHttpGetTxProtoChecked(Flow *flow, lua_State *luastate)
|
|
|
|
|
{
|
|
|
|
|
if (!LuaStateNeedProto(luastate, ALPROTO_HTTP1)) {
|
|
|
|
|
return LuaCallbackError(luastate, "error: protocol not http");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
htp_tx_t *tx = LuaStateGetTX(luastate);
|
|
|
|
|
void *tx = LuaStateGetTX(luastate);
|
|
|
|
|
if (tx == NULL) {
|
|
|
|
|
return LuaCallbackError(luastate, "error: no tx available");
|
|
|
|
|
}
|
|
|
|
|
@ -50,6 +47,7 @@ static int LuaHttpGetTx(lua_State *luastate)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ltx->tx = tx;
|
|
|
|
|
ltx->alproto = flow->alproto;
|
|
|
|
|
|
|
|
|
|
luaL_getmetatable(luastate, htp_tx);
|
|
|
|
|
lua_setmetatable(luastate, -2);
|
|
|
|
|
@ -57,6 +55,46 @@ static int LuaHttpGetTx(lua_State *luastate)
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int LuaHttpGetTx(lua_State *luastate)
|
|
|
|
|
{
|
|
|
|
|
Flow *flow = LuaStateGetFlow(luastate);
|
|
|
|
|
if (flow == NULL)
|
|
|
|
|
return LuaCallbackError(luastate, "internal error: no flow");
|
|
|
|
|
|
|
|
|
|
if (flow->alproto != ALPROTO_HTTP1 && flow->alproto != ALPROTO_HTTP2 &&
|
|
|
|
|
flow->alproto != ALPROTO_DOH2) {
|
|
|
|
|
return LuaCallbackError(luastate, "error: protocol not http");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LuaHttpGetTxProtoChecked(flow, luastate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int LuaHttpGetHttp1Tx(lua_State *luastate)
|
|
|
|
|
{
|
|
|
|
|
Flow *flow = LuaStateGetFlow(luastate);
|
|
|
|
|
if (flow == NULL)
|
|
|
|
|
return LuaCallbackError(luastate, "internal error: no flow");
|
|
|
|
|
|
|
|
|
|
if (flow->alproto != ALPROTO_HTTP1) {
|
|
|
|
|
return LuaCallbackError(luastate, "error: protocol not http");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LuaHttpGetTxProtoChecked(flow, luastate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int LuaHttpGetHttp2Tx(lua_State *luastate)
|
|
|
|
|
{
|
|
|
|
|
Flow *flow = LuaStateGetFlow(luastate);
|
|
|
|
|
if (flow == NULL)
|
|
|
|
|
return LuaCallbackError(luastate, "internal error: no flow");
|
|
|
|
|
|
|
|
|
|
if (flow->alproto != ALPROTO_HTTP2 && flow->alproto != ALPROTO_DOH2) {
|
|
|
|
|
return LuaCallbackError(luastate, "error: protocol not http");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LuaHttpGetTxProtoChecked(flow, luastate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int LuaHttpGetRequestHost(lua_State *luastate)
|
|
|
|
|
{
|
|
|
|
|
struct LuaTx *tx = luaL_testudata(luastate, 1, htp_tx);
|
|
|
|
|
@ -64,6 +102,10 @@ static int LuaHttpGetRequestHost(lua_State *luastate)
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (tx->alproto != ALPROTO_HTTP1) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
const struct bstr *host = htp_tx_request_hostname(tx->tx);
|
|
|
|
|
if (host == NULL) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
@ -80,6 +122,16 @@ static int LuaHttpGetRequestUriRaw(lua_State *luastate)
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (tx->alproto == ALPROTO_HTTP2 || tx->alproto == ALPROTO_DOH2) {
|
|
|
|
|
uint32_t b_len = 0;
|
|
|
|
|
const uint8_t *b = NULL;
|
|
|
|
|
|
|
|
|
|
if (SCHttp2TxGetUri(tx->tx, &b, &b_len) != 1) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return LuaPushStringBuffer(luastate, b, b_len);
|
|
|
|
|
} // else ALPROTO_HTTP1
|
|
|
|
|
const struct bstr *uri = htp_tx_request_uri(tx->tx);
|
|
|
|
|
if (uri == NULL) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
@ -96,6 +148,17 @@ static int LuaHttpGetRequestUriNormalized(lua_State *luastate)
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (tx->alproto == ALPROTO_HTTP2 || tx->alproto == ALPROTO_DOH2) {
|
|
|
|
|
uint32_t b_len = 0;
|
|
|
|
|
const uint8_t *b = NULL;
|
|
|
|
|
|
|
|
|
|
if (SCHttp2TxGetUri(tx->tx, &b, &b_len) != 1) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return LuaPushStringBuffer(luastate, b, b_len);
|
|
|
|
|
} // else ALPROTO_HTTP1
|
|
|
|
|
|
|
|
|
|
bstr *request_uri_normalized = (bstr *)htp_tx_normalized_uri(tx->tx);
|
|
|
|
|
|
|
|
|
|
if (request_uri_normalized == NULL || bstr_ptr(request_uri_normalized) == NULL ||
|
|
|
|
|
@ -113,6 +176,16 @@ static int LuaHttpGetRequestLine(lua_State *luastate)
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (tx->alproto == ALPROTO_HTTP2 || tx->alproto == ALPROTO_DOH2) {
|
|
|
|
|
uint32_t b_len = 0;
|
|
|
|
|
const uint8_t *b = NULL;
|
|
|
|
|
|
|
|
|
|
if (SCHttp2TxGetRequestLine(tx->tx, &b, &b_len) != 1) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return LuaPushStringBuffer(luastate, b, b_len);
|
|
|
|
|
} // else ALPROTO_HTTP1
|
|
|
|
|
|
|
|
|
|
const struct bstr *line = htp_tx_request_line(tx->tx);
|
|
|
|
|
if (line == NULL) {
|
|
|
|
|
@ -130,6 +203,10 @@ static int LuaHttpGetResponseLine(lua_State *luastate)
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (tx->alproto != ALPROTO_HTTP1) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const struct bstr *line = htp_tx_response_line(tx->tx);
|
|
|
|
|
if (line == NULL) {
|
|
|
|
|
@ -147,6 +224,10 @@ static int LuaHttpGetHeader(lua_State *luastate, int dir)
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (tx->alproto != ALPROTO_HTTP1) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* since arg was added at last, it must be on top of the stack */
|
|
|
|
|
const char *name = LuaGetStringArgument(luastate, lua_gettop(luastate));
|
|
|
|
|
@ -185,6 +266,10 @@ static int LuaHttpGetRawHeaders(lua_State *luastate, int dir)
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (tx->alproto != ALPROTO_HTTP1) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx->tx);
|
|
|
|
|
|
|
|
|
|
uint8_t *raw = htud->request_headers_raw;
|
|
|
|
|
@ -217,6 +302,10 @@ static int LuaHttpGetHeaders(lua_State *luastate, int dir)
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (tx->alproto != ALPROTO_HTTP1) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const htp_headers_t *table = htp_tx_request_headers(tx->tx);
|
|
|
|
|
if (dir == 1)
|
|
|
|
|
@ -258,6 +347,10 @@ static int LuaHttpGetBody(lua_State *luastate, int dir)
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (tx->alproto != ALPROTO_HTTP1) {
|
|
|
|
|
lua_pushnil(luastate);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx->tx);
|
|
|
|
|
|
|
|
|
|
@ -329,6 +422,8 @@ static const struct luaL_Reg txlib[] = {
|
|
|
|
|
static const struct luaL_Reg htplib[] = {
|
|
|
|
|
// clang-format off
|
|
|
|
|
{"get_tx", LuaHttpGetTx },
|
|
|
|
|
{"get_http1_tx", LuaHttpGetHttp1Tx },
|
|
|
|
|
{"get_http2_tx", LuaHttpGetHttp2Tx },
|
|
|
|
|
{NULL, NULL,},
|
|
|
|
|
// clang-format on
|
|
|
|
|
};
|
|
|
|
|
|