suricata
util-lua-tls.c
Go to the documentation of this file.
1/* Copyright (C) 2014 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 Eric Leblond <eric@regit.org>
23 *
24 */
25
26#include "suricata-common.h"
27#include "detect.h"
28#include "pkt-var.h"
29#include "conf.h"
30
31#include "threads.h"
32#include "threadvars.h"
33#include "tm-threads.h"
34
35#include "util-print.h"
36#include "util-unittest.h"
37
38#include "util-debug.h"
39
40#include "output.h"
41#include "app-layer.h"
42#include "app-layer-parser.h"
43#include "app-layer-ssl.h"
44#include "util-privs.h"
45#include "util-buffer.h"
46#include "util-proto-name.h"
47#include "util-logopenfile.h"
48#include "util-time.h"
49
50#include "lua.h"
51#include "lualib.h"
52#include "lauxlib.h"
53
54#include "util-lua.h"
55#include "util-lua-common.h"
56#include "util-lua-tls.h"
57
58static const char tls_state_mt[] = "suricata:tls";
59
60struct LuaTls {
61 const SSLState *state; // state
62};
63
64static int LuaTlsFlowStateGet(lua_State *luastate)
65{
66 if (!LuaStateNeedProto(luastate, ALPROTO_TLS)) {
67 return LuaCallbackError(luastate, "error: protocol not tls");
68 }
69 Flow *f = LuaStateGetFlow(luastate);
70 if (f == NULL) {
71 LUA_ERROR("failed to get flow");
72 }
73
74 struct LuaTls *s = (struct LuaTls *)lua_newuserdata(luastate, sizeof(*s));
75 if (s == NULL) {
76 LUA_ERROR("failed to allocate userdata");
77 }
78
79 void *state = FlowGetAppState(f);
80 if (state == NULL)
81 return LuaCallbackError(luastate, "error: no app layer state");
82 s->state = (const SSLState *)state;
83 luaL_getmetatable(luastate, tls_state_mt);
84 lua_setmetatable(luastate, -2);
85 return 1;
86}
87
88static int GetCertNotBefore(lua_State *luastate, bool client, const SSLState *ssl_state)
89{
90 const SSLStateConnp *connp;
91
92 if (client) {
93 connp = &ssl_state->client_connp;
94 } else {
95 connp = &ssl_state->server_connp;
96 }
97
98 if (connp->cert0_not_before == 0)
99 return LuaCallbackError(luastate, "error: no certificate NotBefore");
100
101 return LuaPushInteger(luastate, connp->cert0_not_before);
102}
103
104static int LuaTlsGetServerCertNotBefore(lua_State *luastate)
105{
106 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
107 if (s->state == NULL) {
108 LUA_ERROR("failed to get flow");
109 }
110
111 return GetCertNotBefore(luastate, false, s->state);
112}
113
114static int LuaTlsGetClientCertNotBefore(lua_State *luastate)
115{
116 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
117 if (s->state == NULL) {
118 LUA_ERROR("failed to get flow");
119 }
120
121 return GetCertNotBefore(luastate, true, s->state);
122}
123
124static int GetCertNotAfter(lua_State *luastate, bool client, const SSLState *ssl_state)
125{
126 const SSLStateConnp *connp;
127
128 if (client) {
129 connp = &ssl_state->client_connp;
130 } else {
131 connp = &ssl_state->server_connp;
132 }
133
134 if (connp->cert0_not_after == 0)
135 return LuaCallbackError(luastate, "error: no certificate NotAfter");
136
137 return LuaPushInteger(luastate, connp->cert0_not_after);
138}
139
140static int LuaTlsGetServerCertNotAfter(lua_State *luastate)
141{
142 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
143 if (s->state == NULL) {
144 LUA_ERROR("failed to get state");
145 }
146
147 return GetCertNotAfter(luastate, false, s->state);
148}
149static int LuaTlsGetClientCertNotAfter(lua_State *luastate)
150{
151 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
152 if (s->state == NULL) {
153 LUA_ERROR("failed to get state");
154 }
155
156 return GetCertNotAfter(luastate, true, s->state);
157}
158
159static int GetCertInfo(lua_State *luastate, bool client, const SSLState *ssl_state)
160{
161 const SSLStateConnp *connp;
162
163 if (client) {
164 connp = &ssl_state->client_connp;
165 } else {
166 connp = &ssl_state->server_connp;
167 }
168
169 if (connp->cert0_subject == NULL)
170 return LuaCallbackError(luastate, "error: no cert");
171
172 /* tls.version */
173 char ssl_version[SSL_VERSION_MAX_STRLEN];
174 SSLVersionToString(ssl_state->server_connp.version, ssl_version);
175
176 int r = LuaPushStringBuffer(luastate, (uint8_t *)ssl_version, strlen(ssl_version));
177 r += LuaPushStringBuffer(luastate, (uint8_t *)connp->cert0_subject, strlen(connp->cert0_subject));
178 r += LuaPushStringBuffer(luastate, (uint8_t *)connp->cert0_issuerdn, strlen(connp->cert0_issuerdn));
179 r += LuaPushStringBuffer(luastate, (uint8_t *)connp->cert0_fingerprint, strlen(connp->cert0_fingerprint));
180 return r;
181}
182
183static int LuaTlsGetServerCertInfo(lua_State *luastate)
184{
185 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
186 if (s->state == NULL) {
187 LUA_ERROR("failed to get state");
188 }
189
190 return GetCertInfo(luastate, false, s->state);
191}
192
193static int LuaTlsGetClientCertInfo(lua_State *luastate)
194{
195 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
196 if (s->state == NULL) {
197 LUA_ERROR("failed to get state");
198 }
199
200 return GetCertInfo(luastate, true, s->state);
201}
202
203static int GetSNI(lua_State *luastate, const SSLState *ssl_state)
204{
205 if (ssl_state->client_connp.sni == NULL)
206 return LuaCallbackError(luastate, "error: no server name indication");
207
208 return LuaPushStringBuffer(luastate, (uint8_t *)ssl_state->client_connp.sni,
209 strlen(ssl_state->client_connp.sni));
210}
211
212static int LuaTlsGetSNI(lua_State *luastate)
213{
214 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
215 if (s->state == NULL) {
216 LUA_ERROR("failed to get state");
217 }
218
219 if (!(LuaStateNeedProto(luastate, ALPROTO_TLS)))
220 return LuaCallbackError(luastate, "error: protocol not tls");
221
222 return GetSNI(luastate, s->state);
223}
224
225static int GetCertChain(lua_State *luastate, bool client)
226{
227 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
228 if (s->state == NULL) {
229 LUA_ERROR("failed to get state");
230 }
231
232 if (!(LuaStateNeedProto(luastate, ALPROTO_TLS)))
233 return LuaCallbackError(luastate, "error: protocol not tls");
234
235 const SSLStateConnp *connp;
236
237 if (client) {
238 connp = &s->state->client_connp;
239 } else {
240 connp = &s->state->server_connp;
241 }
242
243 uint32_t u = 0;
244 lua_newtable(luastate);
245 SSLCertsChain *cert = NULL;
246
247 TAILQ_FOREACH(cert, &connp->certs, next)
248 {
249 lua_pushinteger(luastate, u++);
250
251 lua_newtable(luastate);
252
253 lua_pushstring(luastate, "length");
254 lua_pushinteger(luastate, cert->cert_len);
255 lua_settable(luastate, -3);
256
257 lua_pushstring(luastate, "data");
258 LuaPushStringBuffer(luastate, cert->cert_data, cert->cert_len);
259
260 lua_settable(luastate, -3);
261 lua_settable(luastate, -3);
262 }
263
264 return 1;
265}
266
267static int LuaTlsGetServerCertChain(lua_State *luastate)
268{
269 return GetCertChain(luastate, false);
270}
271
272static int LuaTlsGetClientCertChain(lua_State *luastate)
273{
274 return GetCertChain(luastate, true);
275}
276
277static int GetCertSerial(lua_State *luastate, bool client)
278{
279 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
280 if (s->state == NULL) {
281 LUA_ERROR("failed to get flow");
282 }
283
284 const SSLStateConnp *connp;
285
286 if (client) {
287 connp = &s->state->client_connp;
288 } else {
289 connp = &s->state->server_connp;
290 }
291 if (connp->cert0_serial == NULL)
292 return LuaCallbackError(luastate, "error: no certificate serial");
293
294 return LuaPushStringBuffer(
295 luastate, (uint8_t *)connp->cert0_serial, strlen(connp->cert0_serial));
296}
297
298static int LuaTlsGetServerCertSerial(lua_State *luastate)
299{
300 return GetCertSerial(luastate, false);
301}
302
303static int LuaTlsGetClientCertSerial(lua_State *luastate)
304{
305 return GetCertSerial(luastate, true);
306}
307
308static int GetAgreedVersion(lua_State *luastate, bool client)
309{
310 struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
311 if (s->state == NULL) {
312 LUA_ERROR("failed to get state");
313 }
314
315 uint16_t version;
316 if (client) {
318 } else {
320 }
321
322 char ssl_version[SSL_VERSION_MAX_STRLEN];
323 SSLVersionToString(version, ssl_version);
324
325 lua_pushstring(luastate, (const char *)&ssl_version);
326 return 1;
327}
328
329static int LuaTlsGetServerVersion(lua_State *luastate)
330{
331 return GetAgreedVersion(luastate, false);
332}
333
334static int LuaTlsGetClientVersion(lua_State *luastate)
335{
336 return GetAgreedVersion(luastate, true);
337}
338
339static const struct luaL_Reg tlslib_meta[] = {
340 // clang-format off
341 { "get_server_cert_not_before", LuaTlsGetServerCertNotBefore },
342 { "get_client_cert_not_before", LuaTlsGetClientCertNotBefore },
343 { "get_server_cert_not_after", LuaTlsGetServerCertNotAfter },
344 { "get_client_cert_not_after", LuaTlsGetClientCertNotAfter },
345 { "get_server_version", LuaTlsGetServerVersion },
346 { "get_client_version", LuaTlsGetClientVersion },
347 { "get_server_serial", LuaTlsGetServerCertSerial },
348 { "get_client_serial", LuaTlsGetClientCertSerial },
349 { "get_server_cert_info", LuaTlsGetServerCertInfo },
350 { "get_client_cert_info", LuaTlsGetClientCertInfo },
351 { "get_client_sni", LuaTlsGetSNI },
352 { "get_client_cert_chain", LuaTlsGetClientCertChain },
353 { "get_server_cert_chain", LuaTlsGetServerCertChain },
354 { NULL, NULL, }
355 // clang-format off
356};
357
358static const struct luaL_Reg tlslib[] = {
359 // clang-format off
360 { "get_tx", LuaTlsFlowStateGet },
361 { NULL, NULL, },
362 // clang-format on
363};
364
366{
367 luaL_newmetatable(L, tls_state_mt);
368 lua_pushvalue(L, -1);
369 lua_setfield(L, -2, "__index");
370 luaL_setfuncs(L, tlslib_meta, 0);
371
372 luaL_newlib(L, tlslib);
373 return 1;
374}
struct HtpBodyChunk_ * next
@ ALPROTO_TLS
uint8_t version
Definition decode-gre.h:1
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:252
Flow data structure.
Definition flow.h:356
const SSLState * state
uint8_t * cert_data
char * cert0_fingerprint
int64_t cert0_not_after
int64_t cert0_not_before
SSLv[2.0|3.[0|1|2|3]] state structure.
SSLStateConnp server_connp
SSLStateConnp client_connp
struct lua_State lua_State
int LuaStateNeedProto(lua_State *luastate, AppProto alproto)
int LuaCallbackError(lua_State *luastate, const char *msg)
#define LUA_ERROR(msg)
int SCLuaLoadTlsLib(lua_State *L)
int LuaPushStringBuffer(lua_State *luastate, const uint8_t *input, size_t input_len)
Definition util-lua.c:319
int LuaPushInteger(lua_State *luastate, lua_Integer n)
Definition util-lua.c:340
Flow * LuaStateGetFlow(lua_State *luastate)
get flow pointer from lua state
Definition util-lua.c:161