suricata
util-lua-ja3.c
Go to the documentation of this file.
1/* Copyright (C) 2017 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18
19/**
20 * \file
21 *
22 * \author Mats Klepsland <mats.klepsland@gmail.com>
23 *
24 */
25
26#include "suricata-common.h"
27#include "util-lua-ja3.h"
28#include "util-lua.h"
29#include "util-lua-common.h"
30#include "app-layer-ssl.h"
31#include "rust.h"
32
33static const char ja3_tx[] = "suricata:ja3:tx";
34
35struct LuaTx {
36 void *tx; // Quic or TLS Transaction
38};
39
40static int LuaJa3GetTx(lua_State *L)
41{
42 AppProto alproto = ALPROTO_QUIC;
44 alproto = ALPROTO_TLS;
45 } else if (!(LuaStateNeedProto(L, ALPROTO_QUIC))) {
46 return LuaCallbackError(L, "error: protocol nor tls neither quic");
47 }
48 void *tx = LuaStateGetTX(L);
49 if (tx == NULL) {
50 return LuaCallbackError(L, "error: no tx available");
51 }
52 struct LuaTx *ltx = (struct LuaTx *)lua_newuserdata(L, sizeof(*ltx));
53 if (ltx == NULL) {
54 return LuaCallbackError(L, "error: fail to allocate user data");
55 }
56 ltx->tx = tx;
57 ltx->alproto = alproto;
58
59 luaL_getmetatable(L, ja3_tx);
60 lua_setmetatable(L, -2);
61
62 return 1;
63}
64
65static int LuaJa3TxGetHash(lua_State *L)
66{
67 struct LuaTx *ltx = luaL_testudata(L, 1, ja3_tx);
68 if (ltx == NULL) {
69 lua_pushnil(L);
70 return 1;
71 }
72 if (ltx->alproto == ALPROTO_TLS) {
73 SSLState *ssl_state = (SSLState *)ltx->tx;
74 if (ssl_state->client_connp.ja3_hash == NULL) {
75 lua_pushnil(L);
76 return 1;
77 }
78 return LuaPushStringBuffer(L, (uint8_t *)ssl_state->client_connp.ja3_hash,
79 strlen(ssl_state->client_connp.ja3_hash));
80 } // else QUIC {
81 const uint8_t *buf = NULL;
82 uint32_t b_len = 0;
83 if (!SCQuicTxGetJa3(ltx->tx, STREAM_TOSERVER, &buf, &b_len)) {
84 lua_pushnil(L);
85 return 1;
86 }
87 uint8_t ja3_hash[SC_MD5_HEX_LEN + 1];
88 // this adds a final zero
89 SCMd5HashBufferToHex(buf, b_len, (char *)ja3_hash, SC_MD5_HEX_LEN + 1);
90 return LuaPushStringBuffer(L, ja3_hash, SC_MD5_HEX_LEN);
91}
92
93static int LuaJa3TxGetString(lua_State *L)
94{
95 struct LuaTx *ltx = luaL_testudata(L, 1, ja3_tx);
96 if (ltx == NULL) {
97 lua_pushnil(L);
98 return 1;
99 }
100 if (ltx->alproto == ALPROTO_TLS) {
101 SSLState *ssl_state = (SSLState *)ltx->tx;
102 if (ssl_state->client_connp.ja3_str == NULL ||
103 ssl_state->client_connp.ja3_str->data == NULL) {
104 lua_pushnil(L);
105 return 1;
106 }
107 return LuaPushStringBuffer(L, (uint8_t *)ssl_state->client_connp.ja3_str->data,
108 ssl_state->client_connp.ja3_str->used);
109 } // else QUIC {
110 const uint8_t *buf = NULL;
111 uint32_t b_len = 0;
112 if (!SCQuicTxGetJa3(ltx->tx, STREAM_TOSERVER, &buf, &b_len)) {
113 lua_pushnil(L);
114 return 1;
115 }
116 return LuaPushStringBuffer(L, buf, b_len);
117}
118
119static int LuaJa3TxGetServerHash(lua_State *L)
120{
121 struct LuaTx *ltx = luaL_testudata(L, 1, ja3_tx);
122 if (ltx == NULL) {
123 lua_pushnil(L);
124 return 1;
125 }
126 if (ltx->alproto == ALPROTO_TLS) {
127 SSLState *ssl_state = (SSLState *)ltx->tx;
128 if (ssl_state->server_connp.ja3_hash == NULL) {
129 lua_pushnil(L);
130 return 1;
131 }
132 return LuaPushStringBuffer(L, (uint8_t *)ssl_state->server_connp.ja3_hash,
133 strlen(ssl_state->server_connp.ja3_hash));
134 } // else QUIC {
135 const uint8_t *buf = NULL;
136 uint32_t b_len = 0;
137 if (!SCQuicTxGetJa3(ltx->tx, STREAM_TOCLIENT, &buf, &b_len)) {
138 lua_pushnil(L);
139 return 1;
140 }
141 uint8_t ja3_hash[SC_MD5_HEX_LEN + 1];
142 // this adds a final zero
143 SCMd5HashBufferToHex(buf, b_len, (char *)ja3_hash, SC_MD5_HEX_LEN + 1);
144 return LuaPushStringBuffer(L, ja3_hash, SC_MD5_HEX_LEN);
145}
146
147static int LuaJa3TxGetServerString(lua_State *L)
148{
149 struct LuaTx *ltx = luaL_testudata(L, 1, ja3_tx);
150 if (ltx == NULL) {
151 lua_pushnil(L);
152 return 1;
153 }
154 if (ltx->alproto == ALPROTO_TLS) {
155 SSLState *ssl_state = (SSLState *)ltx->tx;
156 if (ssl_state->server_connp.ja3_str == NULL ||
157 ssl_state->server_connp.ja3_str->data == NULL) {
158 lua_pushnil(L);
159 return 1;
160 }
161 return LuaPushStringBuffer(L, (uint8_t *)ssl_state->server_connp.ja3_str->data,
162 ssl_state->server_connp.ja3_str->used);
163 } // else QUIC {
164 const uint8_t *buf = NULL;
165 uint32_t b_len = 0;
166 if (!SCQuicTxGetJa3(ltx->tx, STREAM_TOCLIENT, &buf, &b_len)) {
167 lua_pushnil(L);
168 return 1;
169 }
170 return LuaPushStringBuffer(L, buf, b_len);
171}
172
173static const struct luaL_Reg txlib[] = {
174 // clang-format off
175 { "ja3_get_hash", LuaJa3TxGetHash },
176 { "ja3_get_string", LuaJa3TxGetString },
177 { "ja3s_get_hash", LuaJa3TxGetServerHash },
178 { "ja3s_get_string", LuaJa3TxGetServerString },
179 { NULL, NULL, }
180 // clang-format on
181};
182
183static int LuaJa3Enable(lua_State *L)
184{
185 SSLEnableJA3();
186 return 1;
187}
188
189static const struct luaL_Reg ja3lib[] = {
190 // clang-format off
191 { "get_tx", LuaJa3GetTx },
192 { "enable_ja3", LuaJa3Enable },
193 { NULL, NULL,},
194 // clang-format on
195};
196
198{
199 luaL_newmetatable(L, ja3_tx);
200 lua_pushvalue(L, -1);
201 lua_setfield(L, -2, "__index");
202 luaL_setfuncs(L, txlib, 0);
203
204 luaL_newlib(L, ja3lib);
205 return 1;
206}
uint16_t AppProto
@ ALPROTO_TLS
@ ALPROTO_QUIC
void SSLEnableJA3(void)
if not explicitly disabled in config, enable ja3 support
AppProto alproto
void * tx
DNSTransaction * tx
SSLv[2.0|3.[0|1|2|3]] state structure.
struct lua_State lua_State
int LuaStateNeedProto(lua_State *luastate, AppProto alproto)
int LuaCallbackError(lua_State *luastate, const char *msg)
int SCLuaLoadJa3Lib(lua_State *L)
int LuaPushStringBuffer(lua_State *luastate, const uint8_t *input, size_t input_len)
Definition util-lua.c:319
void * LuaStateGetTX(lua_State *luastate)
get tx pointer from the lua state
Definition util-lua.c:134