• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/util-lua-tls.c
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

58
static const char tls_state_mt[] = "suricata:tls";
59

60
struct LuaTls {
61
    const SSLState *state; // state
62
};
63

64
static int LuaTlsFlowStateGet(lua_State *luastate)
UNCOV
65
{
×
UNCOV
66
    if (!LuaStateNeedProto(luastate, ALPROTO_TLS)) {
×
67
        return LuaCallbackError(luastate, "error: protocol not tls");
×
68
    }
×
UNCOV
69
    Flow *f = LuaStateGetFlow(luastate);
×
UNCOV
70
    if (f == NULL) {
×
71
        LUA_ERROR("failed to get flow");
×
72
    }
×
73

UNCOV
74
    struct LuaTls *s = (struct LuaTls *)lua_newuserdata(luastate, sizeof(*s));
×
UNCOV
75
    if (s == NULL) {
×
76
        LUA_ERROR("failed to allocate userdata");
×
77
    }
×
78

UNCOV
79
    void *state = FlowGetAppState(f);
×
UNCOV
80
    if (state == NULL)
×
81
        return LuaCallbackError(luastate, "error: no app layer state");
×
UNCOV
82
    s->state = (const SSLState *)state;
×
UNCOV
83
    luaL_getmetatable(luastate, tls_state_mt);
×
UNCOV
84
    lua_setmetatable(luastate, -2);
×
UNCOV
85
    return 1;
×
UNCOV
86
}
×
87

88
static 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

104
static 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

114
static 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

124
static 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

140
static 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
}
×
149
static 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

159
static 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, connp->cert0_subject, connp->cert0_subject_len);
×
178
    r += LuaPushStringBuffer(luastate, connp->cert0_issuerdn, connp->cert0_issuerdn_len);
×
179
    r += LuaPushStringBuffer(luastate, (uint8_t *)connp->cert0_fingerprint, strlen(connp->cert0_fingerprint));
×
180
    return r;
×
181
}
×
182

183
static 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

193
static 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

203
static 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(
×
209
            luastate, ssl_state->client_connp.sni, ssl_state->client_connp.sni_len);
×
210
}
×
211

212
static 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

225
static 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

267
static int LuaTlsGetServerCertChain(lua_State *luastate)
268
{
×
269
    return GetCertChain(luastate, false);
×
270
}
×
271

272
static int LuaTlsGetClientCertChain(lua_State *luastate)
273
{
×
274
    return GetCertChain(luastate, true);
×
275
}
×
276

277
static int GetCertSerial(lua_State *luastate, bool client)
UNCOV
278
{
×
UNCOV
279
    struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
×
UNCOV
280
    if (s->state == NULL) {
×
281
        LUA_ERROR("failed to get flow");
×
282
    }
×
283

UNCOV
284
    const SSLStateConnp *connp;
×
285

UNCOV
286
    if (client) {
×
287
        connp = &s->state->client_connp;
×
UNCOV
288
    } else {
×
UNCOV
289
        connp = &s->state->server_connp;
×
UNCOV
290
    }
×
UNCOV
291
    if (connp->cert0_serial == NULL)
×
UNCOV
292
        return LuaCallbackError(luastate, "error: no certificate serial");
×
293

UNCOV
294
    return LuaPushStringBuffer(luastate, connp->cert0_serial, connp->cert0_serial_len);
×
UNCOV
295
}
×
296

297
static int LuaTlsGetServerCertSerial(lua_State *luastate)
UNCOV
298
{
×
UNCOV
299
    return GetCertSerial(luastate, false);
×
UNCOV
300
}
×
301

302
static int LuaTlsGetClientCertSerial(lua_State *luastate)
303
{
×
304
    return GetCertSerial(luastate, true);
×
305
}
×
306

307
static int GetAgreedVersion(lua_State *luastate, bool client)
UNCOV
308
{
×
UNCOV
309
    struct LuaTls *s = (struct LuaTls *)luaL_checkudata(luastate, 1, tls_state_mt);
×
UNCOV
310
    if (s->state == NULL) {
×
311
        LUA_ERROR("failed to get state");
×
312
    }
×
313

UNCOV
314
    uint16_t version;
×
UNCOV
315
    if (client) {
×
UNCOV
316
        version = s->state->client_connp.version;
×
UNCOV
317
    } else {
×
UNCOV
318
        version = s->state->server_connp.version;
×
UNCOV
319
    }
×
320

UNCOV
321
    char ssl_version[SSL_VERSION_MAX_STRLEN];
×
UNCOV
322
    SSLVersionToString(version, ssl_version);
×
323

UNCOV
324
    lua_pushstring(luastate, (const char *)&ssl_version);
×
UNCOV
325
    return 1;
×
UNCOV
326
}
×
327

328
static int LuaTlsGetServerVersion(lua_State *luastate)
UNCOV
329
{
×
UNCOV
330
    return GetAgreedVersion(luastate, false);
×
UNCOV
331
}
×
332

333
static int LuaTlsGetClientVersion(lua_State *luastate)
UNCOV
334
{
×
UNCOV
335
    return GetAgreedVersion(luastate, true);
×
UNCOV
336
}
×
337

338
static const struct luaL_Reg tlslib_meta[] = {
339
    // clang-format off
340
    { "get_server_cert_not_before", LuaTlsGetServerCertNotBefore },
341
    { "get_client_cert_not_before", LuaTlsGetClientCertNotBefore },
342
    { "get_server_cert_not_after", LuaTlsGetServerCertNotAfter },
343
    { "get_client_cert_not_after", LuaTlsGetClientCertNotAfter },
344
    { "get_server_version", LuaTlsGetServerVersion },
345
    { "get_client_version", LuaTlsGetClientVersion },
346
    { "get_server_serial", LuaTlsGetServerCertSerial },
347
    { "get_client_serial", LuaTlsGetClientCertSerial },
348
    { "get_server_cert_info", LuaTlsGetServerCertInfo },
349
    { "get_client_cert_info", LuaTlsGetClientCertInfo },
350
    { "get_client_sni", LuaTlsGetSNI },
351
    { "get_client_cert_chain", LuaTlsGetClientCertChain },
352
    { "get_server_cert_chain", LuaTlsGetServerCertChain },
353
    { NULL, NULL, }
354
    // clang-format off
355
};
356

357
static const struct luaL_Reg tlslib[] = {
358
    // clang-format off
359
    { "get_tx", LuaTlsFlowStateGet },
360
    { NULL, NULL, },
361
    // clang-format on
362
};
363

364
int SCLuaLoadTlsLib(lua_State *L)
UNCOV
365
{
×
UNCOV
366
    luaL_newmetatable(L, tls_state_mt);
×
UNCOV
367
    lua_pushvalue(L, -1);
×
UNCOV
368
    lua_setfield(L, -2, "__index");
×
UNCOV
369
    luaL_setfuncs(L, tlslib_meta, 0);
×
370

UNCOV
371
    luaL_newlib(L, tlslib);
×
UNCOV
372
    return 1;
×
UNCOV
373
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc