suricata
output-json-tls.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2024 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  * \file
20  *
21  * \author Tom DeCanio <td@npulsetech.com>
22  *
23  * Implements TLS JSON logging portion of the engine.
24  */
25 
26 #include "suricata-common.h"
27 
28 #include "app-layer-parser.h"
29 #include "app-layer-ssl.h"
30 #include "app-layer.h"
31 #include "conf.h"
32 #include "output-json-tls.h"
33 #include "output-json.h"
34 #include "output.h"
35 #include "threadvars.h"
36 #include "util-debug.h"
37 #include "util-ja3.h"
38 #include "util-time.h"
39 
40 #define LOG_TLS_FIELD_VERSION BIT_U64(0)
41 #define LOG_TLS_FIELD_SUBJECT BIT_U64(1)
42 #define LOG_TLS_FIELD_ISSUER BIT_U64(2)
43 #define LOG_TLS_FIELD_SERIAL BIT_U64(3)
44 #define LOG_TLS_FIELD_FINGERPRINT BIT_U64(4)
45 #define LOG_TLS_FIELD_NOTBEFORE BIT_U64(5)
46 #define LOG_TLS_FIELD_NOTAFTER BIT_U64(6)
47 #define LOG_TLS_FIELD_SNI BIT_U64(7)
48 #define LOG_TLS_FIELD_CERTIFICATE BIT_U64(8)
49 #define LOG_TLS_FIELD_CHAIN BIT_U64(9)
50 #define LOG_TLS_FIELD_SESSION_RESUMED BIT_U64(10)
51 #define LOG_TLS_FIELD_JA3 BIT_U64(11)
52 #define LOG_TLS_FIELD_JA3S BIT_U64(12)
53 #define LOG_TLS_FIELD_CLIENT BIT_U64(13) /**< client fields (issuer, subject, etc) */
54 #define LOG_TLS_FIELD_CLIENT_CERT BIT_U64(14)
55 #define LOG_TLS_FIELD_CLIENT_CHAIN BIT_U64(15)
56 #define LOG_TLS_FIELD_JA4 BIT_U64(16)
57 #define LOG_TLS_FIELD_SUBJECTALTNAME BIT_U64(17)
58 #define LOG_TLS_FIELD_CLIENT_ALPNS BIT_U64(18)
59 #define LOG_TLS_FIELD_SERVER_ALPNS BIT_U64(19)
60 #define LOG_TLS_FIELD_CLIENT_HANDSHAKE BIT_U64(20)
61 #define LOG_TLS_FIELD_SERVER_HANDSHAKE BIT_U64(21)
62 
63 typedef struct {
64  const char *name;
65  uint64_t flag;
66 } TlsFields;
67 
69  // clang-format off
70  { "version", LOG_TLS_FIELD_VERSION },
71  { "subject", LOG_TLS_FIELD_SUBJECT },
72  { "issuer", LOG_TLS_FIELD_ISSUER },
73  { "serial", LOG_TLS_FIELD_SERIAL },
74  { "fingerprint", LOG_TLS_FIELD_FINGERPRINT },
75  { "not_before", LOG_TLS_FIELD_NOTBEFORE },
76  { "not_after", LOG_TLS_FIELD_NOTAFTER },
77  { "sni", LOG_TLS_FIELD_SNI },
78  { "certificate", LOG_TLS_FIELD_CERTIFICATE },
79  { "chain", LOG_TLS_FIELD_CHAIN },
80  { "session_resumed", LOG_TLS_FIELD_SESSION_RESUMED },
81  { "ja3", LOG_TLS_FIELD_JA3 },
82  { "ja3s", LOG_TLS_FIELD_JA3S },
83  { "client", LOG_TLS_FIELD_CLIENT },
84  { "client_certificate", LOG_TLS_FIELD_CLIENT_CERT },
85  { "client_chain", LOG_TLS_FIELD_CLIENT_CHAIN },
86  // accept if as nop if we do not HAVE_JA4
87  { "ja4", LOG_TLS_FIELD_JA4 },
88  { "subjectaltname", LOG_TLS_FIELD_SUBJECTALTNAME },
89  { "client_alpns", LOG_TLS_FIELD_CLIENT_ALPNS },
90  { "server_alpns", LOG_TLS_FIELD_SERVER_ALPNS },
91  { "client_handshake", LOG_TLS_FIELD_CLIENT_HANDSHAKE },
92  { "server_handshake", LOG_TLS_FIELD_SERVER_HANDSHAKE },
93  { NULL, -1 },
94  // clang-format on
95 };
96 
97 // clang-format off
98 #define BASIC_FIELDS \
99  (LOG_TLS_FIELD_SUBJECT | \
100  LOG_TLS_FIELD_ISSUER | \
101  LOG_TLS_FIELD_SUBJECTALTNAME)
102 // clang-format on
103 
104 // clang-format off
105 #define EXTENDED_FIELDS \
106  (BASIC_FIELDS | \
107  LOG_TLS_FIELD_VERSION | \
108  LOG_TLS_FIELD_SERIAL | \
109  LOG_TLS_FIELD_FINGERPRINT | \
110  LOG_TLS_FIELD_NOTBEFORE | \
111  LOG_TLS_FIELD_NOTAFTER | \
112  LOG_TLS_FIELD_JA3 | \
113  LOG_TLS_FIELD_JA3S | \
114  LOG_TLS_FIELD_JA4 | \
115  LOG_TLS_FIELD_CLIENT | \
116  LOG_TLS_FIELD_CLIENT_ALPNS | \
117  LOG_TLS_FIELD_SERVER_ALPNS | \
118  LOG_TLS_FIELD_SNI)
119 // clang-format on
120 
121 typedef struct OutputTlsCtx_ {
122  uint64_t fields; /** Store fields */
126 
127 typedef struct JsonTlsLogThread_ {
131 
132 static void JsonTlsLogSubject(SCJsonBuilder *js, SSLState *ssl_state)
133 {
134  if (ssl_state->server_connp.cert0_subject) {
135  if (ssl_state->server_connp.cert0_subject_len == 0) {
136  SCJbSetString(js, "subject", "");
137  } else {
138  SCJbSetStringFromBytes(js, "subject", ssl_state->server_connp.cert0_subject,
139  ssl_state->server_connp.cert0_subject_len);
140  }
141  }
142 }
143 
144 static void JsonTlsLogIssuer(SCJsonBuilder *js, SSLState *ssl_state)
145 {
146  if (ssl_state->server_connp.cert0_issuerdn) {
147  if (ssl_state->server_connp.cert0_issuerdn_len == 0) {
148  SCJbSetString(js, "issuerdn", "");
149  } else {
150  SCJbSetStringFromBytes(js, "issuerdn", ssl_state->server_connp.cert0_issuerdn,
151  ssl_state->server_connp.cert0_issuerdn_len);
152  }
153  }
154 }
155 
156 static void JsonTlsLogSAN(SCJsonBuilder *js, SSLState *ssl_state)
157 {
158  if (ssl_state->server_connp.cert0_sans_num > 0) {
159  SCJbOpenArray(js, "subjectaltname");
160  for (uint16_t i = 0; i < ssl_state->server_connp.cert0_sans_num; i++) {
161  SCJbAppendStringFromBytes(js, ssl_state->server_connp.cert0_sans[i].san,
162  ssl_state->server_connp.cert0_sans[i].san_len);
163  }
164  SCJbClose(js);
165  }
166 }
167 
168 static void JsonTlsLogSessionResumed(SCJsonBuilder *js, SSLState *ssl_state)
169 {
170  if (ssl_state->flags & SSL_AL_FLAG_SESSION_RESUMED) {
171  /* Only log a session as 'resumed' if a certificate has not
172  been seen, and the session is not TLSv1.3 or later. */
173  if ((ssl_state->server_connp.cert0_issuerdn == NULL &&
174  ssl_state->server_connp.cert0_subject == NULL) &&
175  (ssl_state->flags & SSL_AL_FLAG_STATE_SERVER_HELLO) &&
176  ((ssl_state->flags & SSL_AL_FLAG_LOG_WITHOUT_CERT) == 0)) {
177  SCJbSetBool(js, "session_resumed", true);
178  }
179  }
180 }
181 
182 static void JsonTlsLogFingerprint(SCJsonBuilder *js, SSLState *ssl_state)
183 {
184  if (ssl_state->server_connp.cert0_fingerprint) {
185  SCJbSetString(js, "fingerprint", ssl_state->server_connp.cert0_fingerprint);
186  }
187 }
188 
189 static void JsonTlsLogSni(SCJsonBuilder *js, SSLState *ssl_state)
190 {
191  if (ssl_state->client_connp.sni) {
192  SCJbSetStringFromBytes(
193  js, "sni", ssl_state->client_connp.sni, ssl_state->client_connp.sni_len);
194  }
195 }
196 
197 static void JsonTlsLogSerial(SCJsonBuilder *js, SSLState *ssl_state)
198 {
199  if (ssl_state->server_connp.cert0_serial) {
200  SCJbSetStringFromBytes(js, "serial", ssl_state->server_connp.cert0_serial,
201  ssl_state->server_connp.cert0_serial_len);
202  }
203 }
204 
205 static void JsonTlsLogVersion(SCJsonBuilder *js, SSLState *ssl_state)
206 {
207  char ssl_version[SSL_VERSION_MAX_STRLEN];
208  /* log server version, but fall back to client if we don't have it yet */
209  if (ssl_state->server_connp.version != 0) {
210  SSLVersionToString(ssl_state->server_connp.version, ssl_version);
211  } else {
212  SSLVersionToString(ssl_state->client_connp.version, ssl_version);
213  }
214  SCJbSetString(js, "version", ssl_version);
215 }
216 
217 static void JsonTlsLogNotBefore(SCJsonBuilder *js, SSLState *ssl_state)
218 {
219  if (ssl_state->server_connp.cert0_not_before != 0) {
220  sc_x509_log_timestamp(js, "notbefore", ssl_state->server_connp.cert0_not_before);
221  }
222 }
223 
224 static void JsonTlsLogNotAfter(SCJsonBuilder *js, SSLState *ssl_state)
225 {
226  if (ssl_state->server_connp.cert0_not_after != 0) {
227  sc_x509_log_timestamp(js, "notafter", ssl_state->server_connp.cert0_not_after);
228  }
229 }
230 
231 static void JsonTlsLogJa3Hash(SCJsonBuilder *js, SSLState *ssl_state)
232 {
233  if (ssl_state->client_connp.ja3_hash != NULL) {
234  SCJbSetString(js, "hash", ssl_state->client_connp.ja3_hash);
235  }
236 }
237 
238 static void JsonTlsLogJa3String(SCJsonBuilder *js, SSLState *ssl_state)
239 {
240  if ((ssl_state->client_connp.ja3_str != NULL) &&
241  ssl_state->client_connp.ja3_str->data != NULL) {
242  SCJbSetString(js, "string", ssl_state->client_connp.ja3_str->data);
243  }
244 }
245 
246 static void JsonTlsLogJa3(SCJsonBuilder *js, SSLState *ssl_state)
247 {
248  if ((ssl_state->client_connp.ja3_hash != NULL) ||
249  ((ssl_state->client_connp.ja3_str != NULL) &&
250  ssl_state->client_connp.ja3_str->data != NULL)) {
251  SCJbOpenObject(js, "ja3");
252 
253  JsonTlsLogJa3Hash(js, ssl_state);
254  JsonTlsLogJa3String(js, ssl_state);
255 
256  SCJbClose(js);
257  }
258 }
259 
260 static void JsonTlsLogSCJA4(SCJsonBuilder *js, SSLState *ssl_state)
261 {
262 #ifdef HAVE_JA4
263  if (ssl_state->client_connp.hs != NULL) {
264  uint8_t buffer[JA4_HEX_LEN];
265  /* JA4 hash has 36 characters */
266  SCJA4GetHash(ssl_state->client_connp.hs, (uint8_t(*)[JA4_HEX_LEN])buffer);
267  SCJbSetStringFromBytes(js, "ja4", buffer, JA4_HEX_LEN);
268  }
269 #endif
270 }
271 
272 static void JsonTlsLogJa3SHash(SCJsonBuilder *js, SSLState *ssl_state)
273 {
274  if (ssl_state->server_connp.ja3_hash != NULL) {
275  SCJbSetString(js, "hash", ssl_state->server_connp.ja3_hash);
276  }
277 }
278 
279 static void JsonTlsLogJa3SString(SCJsonBuilder *js, SSLState *ssl_state)
280 {
281  if ((ssl_state->server_connp.ja3_str != NULL) &&
282  ssl_state->server_connp.ja3_str->data != NULL) {
283  SCJbSetString(js, "string", ssl_state->server_connp.ja3_str->data);
284  }
285 }
286 
287 static void JsonTlsLogJa3S(SCJsonBuilder *js, SSLState *ssl_state)
288 {
289  if ((ssl_state->server_connp.ja3_hash != NULL) ||
290  ((ssl_state->server_connp.ja3_str != NULL) &&
291  ssl_state->server_connp.ja3_str->data != NULL)) {
292  SCJbOpenObject(js, "ja3s");
293 
294  JsonTlsLogJa3SHash(js, ssl_state);
295  JsonTlsLogJa3SString(js, ssl_state);
296 
297  SCJbClose(js);
298  }
299 }
300 
301 static void JsonTlsLogAlpns(SCJsonBuilder *js, SSLStateConnp *connp, const char *object)
302 {
303  if (connp->hs == NULL) {
304  return;
305  }
306 
307  if (SCTLSHandshakeIsEmpty(connp->hs)) {
308  return;
309  }
310  SCTLSHandshakeLogALPNs(connp->hs, js, object);
311 }
312 
313 static void JsonTlsLogCertificate(SCJsonBuilder *js, SSLStateConnp *connp)
314 {
315  if (TAILQ_EMPTY(&connp->certs)) {
316  return;
317  }
318 
319  SSLCertsChain *cert = TAILQ_FIRST(&connp->certs);
320  if (cert == NULL) {
321  return;
322  }
323 
324  SCJbSetBase64(js, "certificate", cert->cert_data, cert->cert_len);
325 }
326 
327 static void JsonTlsLogChain(SCJsonBuilder *js, SSLStateConnp *connp)
328 {
329  if (TAILQ_EMPTY(&connp->certs)) {
330  return;
331  }
332 
333  SCJbOpenArray(js, "chain");
334 
335  SSLCertsChain *cert;
336  TAILQ_FOREACH (cert, &connp->certs, next) {
337  SCJbAppendBase64(js, cert->cert_data, cert->cert_len);
338  }
339 
340  SCJbClose(js);
341 }
342 
343 static bool HasClientCert(SSLStateConnp *connp)
344 {
345  return connp->cert0_subject || connp->cert0_issuerdn;
346 }
347 
348 static void JsonTlsLogClientCert(
349  SCJsonBuilder *js, SSLStateConnp *connp, const bool log_cert, const bool log_chain)
350 {
351  if (connp->cert0_subject != NULL) {
352  if (connp->cert0_subject_len == 0) {
353  SCJbSetString(js, "subject", "");
354  } else {
355  SCJbSetStringFromBytes(js, "subject", connp->cert0_subject, connp->cert0_subject_len);
356  }
357  }
358  if (connp->cert0_issuerdn != NULL) {
359  if (connp->cert0_issuerdn_len == 0) {
360  SCJbSetString(js, "issuerdn", "");
361  } else {
362  SCJbSetStringFromBytes(
363  js, "issuerdn", connp->cert0_issuerdn, connp->cert0_issuerdn_len);
364  }
365  }
366  if (connp->cert0_fingerprint) {
367  SCJbSetString(js, "fingerprint", connp->cert0_fingerprint);
368  }
369  if (connp->cert0_serial) {
370  SCJbSetStringFromBytes(js, "serial", connp->cert0_serial, connp->cert0_serial_len);
371  }
372  if (connp->cert0_not_before != 0) {
373  char timebuf[64];
375  CreateUtcIsoTimeString(ts, timebuf, sizeof(timebuf));
376  SCJbSetString(js, "notbefore", timebuf);
377  }
378  if (connp->cert0_not_after != 0) {
379  char timebuf[64];
381  CreateUtcIsoTimeString(ts, timebuf, sizeof(timebuf));
382  SCJbSetString(js, "notafter", timebuf);
383  }
384 
385  if (log_cert) {
386  JsonTlsLogCertificate(js, connp);
387  }
388  if (log_chain) {
389  JsonTlsLogChain(js, connp);
390  }
391 }
392 
393 static void JsonTlsLogClientHandshake(SCJsonBuilder *js, SSLState *ssl_state)
394 {
395  if (ssl_state->client_connp.hs == NULL) {
396  return;
397  }
398 
399  // Don't write an empty handshake
400  if (SCTLSHandshakeIsEmpty(ssl_state->client_connp.hs)) {
401  return;
402  }
403 
404  SCJbOpenObject(js, "client_handshake");
405 
406  SCTLSHandshakeLogVersion(ssl_state->client_connp.hs, js);
407  SCTLSHandshakeLogCiphers(ssl_state->client_connp.hs, js);
408  SCTLSHandshakeLogExtensions(ssl_state->client_connp.hs, js);
409  SCTLSHandshakeLogSigAlgs(ssl_state->client_connp.hs, js);
410 
411  SCJbClose(js);
412 }
413 
414 static void JsonTlsLogServerHandshake(SCJsonBuilder *js, SSLState *ssl_state)
415 {
416  if (ssl_state->server_connp.hs == NULL) {
417  return;
418  }
419 
420  if (SCTLSHandshakeIsEmpty(ssl_state->server_connp.hs)) {
421  return;
422  }
423 
424  SCJbOpenObject(js, "server_handshake");
425 
426  SCTLSHandshakeLogVersion(ssl_state->server_connp.hs, js);
427  SCTLSHandshakeLogFirstCipher(ssl_state->server_connp.hs, js);
428  SCTLSHandshakeLogExtensions(ssl_state->server_connp.hs, js);
429 
430  SCJbClose(js);
431 }
432 
433 static void JsonTlsLogFields(SCJsonBuilder *js, SSLState *ssl_state, uint64_t fields)
434 {
435  /* tls subject */
436  if (fields & LOG_TLS_FIELD_SUBJECT)
437  JsonTlsLogSubject(js, ssl_state);
438 
439  /* tls issuerdn */
440  if (fields & LOG_TLS_FIELD_ISSUER)
441  JsonTlsLogIssuer(js, ssl_state);
442 
443  /* tls subjectaltname */
444  if (fields & LOG_TLS_FIELD_SUBJECTALTNAME)
445  JsonTlsLogSAN(js, ssl_state);
446 
447  /* tls session resumption */
448  if (fields & LOG_TLS_FIELD_SESSION_RESUMED)
449  JsonTlsLogSessionResumed(js, ssl_state);
450 
451  /* tls serial */
452  if (fields & LOG_TLS_FIELD_SERIAL)
453  JsonTlsLogSerial(js, ssl_state);
454 
455  /* tls fingerprint */
456  if (fields & LOG_TLS_FIELD_FINGERPRINT)
457  JsonTlsLogFingerprint(js, ssl_state);
458 
459  /* tls sni */
460  if (fields & LOG_TLS_FIELD_SNI)
461  JsonTlsLogSni(js, ssl_state);
462 
463  /* tls version */
464  if (fields & LOG_TLS_FIELD_VERSION) {
465  JsonTlsLogVersion(js, ssl_state);
466  }
467 
468  /* tls notbefore */
469  if (fields & LOG_TLS_FIELD_NOTBEFORE)
470  JsonTlsLogNotBefore(js, ssl_state);
471 
472  /* tls notafter */
473  if (fields & LOG_TLS_FIELD_NOTAFTER)
474  JsonTlsLogNotAfter(js, ssl_state);
475 
476  /* tls certificate */
477  if (fields & LOG_TLS_FIELD_CERTIFICATE)
478  JsonTlsLogCertificate(js, &ssl_state->server_connp);
479 
480  /* tls chain */
481  if (fields & LOG_TLS_FIELD_CHAIN)
482  JsonTlsLogChain(js, &ssl_state->server_connp);
483 
484  /* tls ja3_hash */
485  if (fields & LOG_TLS_FIELD_JA3)
486  JsonTlsLogJa3(js, ssl_state);
487 
488  /* tls ja3s */
489  if (fields & LOG_TLS_FIELD_JA3S)
490  JsonTlsLogJa3S(js, ssl_state);
491 
492  /* tls ja4 */
493  if (fields & LOG_TLS_FIELD_JA4)
494  JsonTlsLogSCJA4(js, ssl_state);
495 
496  if (fields & LOG_TLS_FIELD_CLIENT_ALPNS) {
497  JsonTlsLogAlpns(js, &ssl_state->client_connp, "client_alpns");
498  }
499 
500  if (fields & LOG_TLS_FIELD_SERVER_ALPNS) {
501  JsonTlsLogAlpns(js, &ssl_state->server_connp, "server_alpns");
502  }
503 
504  /* tls client handshake parameters */
505  if (fields & LOG_TLS_FIELD_CLIENT_HANDSHAKE)
506  JsonTlsLogClientHandshake(js, ssl_state);
507 
508  /* tls server handshake parameters */
509  if (fields & LOG_TLS_FIELD_SERVER_HANDSHAKE)
510  JsonTlsLogServerHandshake(js, ssl_state);
511 
512  if (fields & LOG_TLS_FIELD_CLIENT) {
513  const bool log_cert = (fields & LOG_TLS_FIELD_CLIENT_CERT) != 0;
514  const bool log_chain = (fields & LOG_TLS_FIELD_CLIENT_CHAIN) != 0;
515  if (HasClientCert(&ssl_state->client_connp)) {
516  SCJbOpenObject(js, "client");
517  JsonTlsLogClientCert(js, &ssl_state->client_connp, log_cert, log_chain);
518  SCJbClose(js);
519  }
520  }
521 }
522 
523 bool JsonTlsLogJSONExtended(void *vtx, SCJsonBuilder *tjs)
524 {
525  SSLState *state = (SSLState *)vtx;
526  SCJbOpenObject(tjs, "tls");
527  JsonTlsLogFields(tjs, state, EXTENDED_FIELDS);
528  return SCJbClose(tjs);
529 }
530 
531 static int JsonTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p,
532  Flow *f, void *state, void *txptr, uint64_t tx_id)
533 {
534  JsonTlsLogThread *aft = (JsonTlsLogThread *)thread_data;
535  OutputTlsCtx *tls_ctx = aft->tlslog_ctx;
536 
537  SSLState *ssl_state = (SSLState *)state;
538  if (unlikely(ssl_state == NULL)) {
539  return 0;
540  }
541 
542  if ((ssl_state->server_connp.cert0_issuerdn == NULL ||
543  ssl_state->server_connp.cert0_subject == NULL) &&
544  ((ssl_state->flags & SSL_AL_FLAG_SESSION_RESUMED) == 0 ||
545  (!tls_ctx->session_resumed)) &&
546  ((ssl_state->flags & SSL_AL_FLAG_LOG_WITHOUT_CERT) == 0)) {
547  return 0;
548  }
549 
550  SCJsonBuilder *js = CreateEveHeader(p, LOG_DIR_FLOW, "tls", NULL, aft->tlslog_ctx->eve_ctx);
551  if (unlikely(js == NULL)) {
552  return 0;
553  }
554 
555  SCJbOpenObject(js, "tls");
556 
557  JsonTlsLogFields(js, ssl_state, tls_ctx->fields);
558 
559  /* print original application level protocol when it have been changed
560  because of STARTTLS, HTTP CONNECT, or similar. */
561  if (f->alproto_orig != ALPROTO_UNKNOWN) {
562  SCJbSetString(js, "from_proto", AppLayerGetProtoName(f->alproto_orig));
563  }
564 
565  /* Close the tls object. */
566  SCJbClose(js);
567 
568  OutputJsonBuilderBuffer(tv, p, p->flow, js, aft->ctx);
569  SCJbFree(js);
570 
571  return 0;
572 }
573 
574 static TmEcode JsonTlsLogThreadInit(ThreadVars *t, const void *initdata, void **data)
575 {
576  JsonTlsLogThread *aft = SCCalloc(1, sizeof(JsonTlsLogThread));
577  if (unlikely(aft == NULL)) {
578  return TM_ECODE_FAILED;
579  }
580 
581  if (initdata == NULL) {
582  SCLogDebug("Error getting context for eve-log tls 'initdata' argument NULL");
583  goto error_exit;
584  }
585 
586  /* use the Output Context (file pointer and mutex) */
587  aft->tlslog_ctx = ((OutputCtx *)initdata)->data;
588 
589  aft->ctx = CreateEveThreadCtx(t, aft->tlslog_ctx->eve_ctx);
590  if (!aft->ctx) {
591  goto error_exit;
592  }
593  *data = (void *)aft;
594  return TM_ECODE_OK;
595 
596 error_exit:
597  SCFree(aft);
598  return TM_ECODE_FAILED;
599 }
600 
601 static TmEcode JsonTlsLogThreadDeinit(ThreadVars *t, void *data)
602 {
603  JsonTlsLogThread *aft = (JsonTlsLogThread *)data;
604  if (aft == NULL) {
605  return TM_ECODE_OK;
606  }
607 
608  FreeEveThreadCtx(aft->ctx);
609 
610  /* clear memory */
611  memset(aft, 0, sizeof(JsonTlsLogThread));
612 
613  SCFree(aft);
614  return TM_ECODE_OK;
615 }
616 
617 static OutputTlsCtx *OutputTlsInitCtx(SCConfNode *conf)
618 {
619  OutputTlsCtx *tls_ctx = SCCalloc(1, sizeof(OutputTlsCtx));
620  if (unlikely(tls_ctx == NULL))
621  return NULL;
622 
623  tls_ctx->fields = BASIC_FIELDS;
624  tls_ctx->session_resumed = false;
625 
626  if (conf == NULL)
627  return tls_ctx;
628 
629  const char *extended = SCConfNodeLookupChildValue(conf, "extended");
630  if (extended) {
631  if (SCConfValIsTrue(extended)) {
632  tls_ctx->fields = EXTENDED_FIELDS;
633  }
634  }
635 
636  SCConfNode *custom = SCConfNodeLookupChild(conf, "custom");
637  if (custom) {
638  tls_ctx->fields = 0;
639  SCConfNode *field;
640  TAILQ_FOREACH(field, &custom->head, next)
641  {
642  bool valid = false;
643  TlsFields *valid_fields = tls_fields;
644  for ( ; valid_fields->name != NULL; valid_fields++) {
645  if (strcasecmp(field->val, valid_fields->name) == 0) {
646  tls_ctx->fields |= valid_fields->flag;
647  SCLogDebug("enabled %s", field->val);
648  valid = true;
649  break;
650  }
651  }
652  if (!valid) {
653  SCLogWarning("eve.tls: unknown 'custom' field '%s'", field->val);
654  }
655  }
656  }
657 
658  const char *session_resumption = SCConfNodeLookupChildValue(conf, "session-resumption");
659  if (session_resumption == NULL || SCConfValIsTrue(session_resumption)) {
661  tls_ctx->session_resumed = true;
662  }
663 
664  if ((tls_ctx->fields & LOG_TLS_FIELD_CERTIFICATE) &&
665  (tls_ctx->fields & LOG_TLS_FIELD_CHAIN)) {
666  SCLogWarning("Both 'certificate' and 'chain' contains the top "
667  "certificate, so only one of them should be enabled "
668  "at a time");
669  }
670  if ((tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CERT) &&
671  (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CHAIN)) {
672  SCLogWarning("Both 'client_certificate' and 'client_chain' contains the top "
673  "certificate, so only one of them should be enabled "
674  "at a time");
675  }
676 
677  if ((tls_ctx->fields & LOG_TLS_FIELD_CLIENT) == 0) {
678  if (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CERT) {
679  SCLogConfig("enabling \"client\" as a dependency of \"client_certificate\"");
680  tls_ctx->fields |= LOG_TLS_FIELD_CLIENT;
681  }
682  if (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CHAIN) {
683  SCLogConfig("enabling \"client\" as a dependency of \"client_chain\"");
684  tls_ctx->fields |= LOG_TLS_FIELD_CLIENT;
685  }
686  }
687 
688  return tls_ctx;
689 }
690 
691 static void OutputTlsLogDeinitSub(OutputCtx *output_ctx)
692 {
693  OutputTlsCtx *tls_ctx = output_ctx->data;
694  SCFree(tls_ctx);
695  SCFree(output_ctx);
696 }
697 
698 static OutputInitResult OutputTlsLogInitSub(SCConfNode *conf, OutputCtx *parent_ctx)
699 {
700  OutputInitResult result = { NULL, false };
701  OutputJsonCtx *ojc = parent_ctx->data;
702 
703  OutputTlsCtx *tls_ctx = OutputTlsInitCtx(conf);
704  if (unlikely(tls_ctx == NULL))
705  return result;
706 
707  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
708  if (unlikely(output_ctx == NULL)) {
709  SCFree(tls_ctx);
710  return result;
711  }
712 
713  tls_ctx->eve_ctx = ojc;
714 
715  if ((tls_ctx->fields & LOG_TLS_FIELD_CERTIFICATE) &&
716  (tls_ctx->fields & LOG_TLS_FIELD_CHAIN)) {
717  SCLogWarning("Both 'certificate' and 'chain' contains the top "
718  "certificate, so only one of them should be enabled "
719  "at a time");
720  }
721 
722  output_ctx->data = tls_ctx;
723  output_ctx->DeInit = OutputTlsLogDeinitSub;
724 
726 
727  result.ctx = output_ctx;
728  result.ok = true;
729  return result;
730 }
731 
733 {
734  /* register as child of eve-log */
735  OutputRegisterTxSubModuleWithProgress(LOGGER_JSON_TX, "eve-log", "JsonTlsLog", "eve-log.tls",
736  OutputTlsLogInitSub, ALPROTO_TLS, JsonTlsLogger, TLS_STATE_SERVER_HANDSHAKE_DONE,
737  TLS_STATE_CLIENT_HANDSHAKE_DONE, JsonTlsLogThreadInit, JsonTlsLogThreadDeinit);
738 }
SSLState_
SSLv[2.0|3.[0|1|2|3]] state structure.
Definition: app-layer-ssl.h:237
ts
uint64_t ts
Definition: source-erf-file.c:55
LOG_TLS_FIELD_NOTBEFORE
#define LOG_TLS_FIELD_NOTBEFORE
Definition: output-json-tls.c:45
SSLSubjectAltName_::san_len
uint32_t san_len
Definition: app-layer-ssl.h:170
SCConfValIsTrue
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:552
SSLCertsChain_::cert_len
uint32_t cert_len
Definition: app-layer-ssl.h:164
LOG_TLS_FIELD_SERVER_ALPNS
#define LOG_TLS_FIELD_SERVER_ALPNS
Definition: output-json-tls.c:59
JsonTlsLogJSONExtended
bool JsonTlsLogJSONExtended(void *vtx, SCJsonBuilder *tjs)
Definition: output-json-tls.c:523
OutputRegisterTxSubModuleWithProgress
void OutputRegisterTxSubModuleWithProgress(LoggerId id, const char *parent_name, const char *name, const char *conf_name, OutputInitSubFunc InitFunc, AppProto alproto, TxLogger TxLogFunc, int tc_log_progress, int ts_log_progress, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit)
Definition: output.c:377
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
LOG_TLS_FIELD_JA3
#define LOG_TLS_FIELD_JA3
Definition: output-json-tls.c:51
SSLState_::client_connp
SSLStateConnp client_connp
Definition: app-layer-ssl.h:258
ALPROTO_TLS
@ ALPROTO_TLS
Definition: app-layer-protos.h:39
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
SSLState_::server_connp
SSLStateConnp server_connp
Definition: app-layer-ssl.h:259
SSLStateConnp_::cert0_not_before
int64_t cert0_not_before
Definition: app-layer-ssl.h:199
SSL_AL_FLAG_SESSION_RESUMED
#define SSL_AL_FLAG_SESSION_RESUMED
Definition: app-layer-ssl.h:122
FreeEveThreadCtx
void FreeEveThreadCtx(OutputJsonThreadCtx *ctx)
Definition: output-json-common.c:58
SSLStateConnp_
Definition: app-layer-ssl.h:173
SSLStateConnp_::ja3_hash
char * ja3_hash
Definition: app-layer-ssl.h:219
CreateEveHeader
SCJsonBuilder * CreateEveHeader(const Packet *p, enum SCOutputJsonLogDirection dir, const char *event_type, JsonAddrInfo *addr, OutputJsonCtx *eve_ctx)
Definition: output-json.c:819
OutputJsonCtx_
Definition: output-json.h:77
Flow_
Flow data structure.
Definition: flow.h:347
SSL_AL_FLAG_STATE_SERVER_HELLO
#define SSL_AL_FLAG_STATE_SERVER_HELLO
Definition: app-layer-ssl.h:111
TlsFields
Definition: output-json-tls.c:63
LOG_TLS_FIELD_SERVER_HANDSHAKE
#define LOG_TLS_FIELD_SERVER_HANDSHAKE
Definition: output-json-tls.c:61
LOG_TLS_FIELD_NOTAFTER
#define LOG_TLS_FIELD_NOTAFTER
Definition: output-json-tls.c:46
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:248
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
Flow_::alproto_orig
AppProto alproto_orig
Definition: flow.h:449
output-json-tls.h
CreateEveThreadCtx
OutputJsonThreadCtx * CreateEveThreadCtx(ThreadVars *t, OutputJsonCtx *ctx)
Definition: output-json-common.c:29
LOG_TLS_FIELD_CLIENT_ALPNS
#define LOG_TLS_FIELD_CLIENT_ALPNS
Definition: output-json-tls.c:58
LOG_TLS_FIELD_SUBJECTALTNAME
#define LOG_TLS_FIELD_SUBJECTALTNAME
Definition: output-json-tls.c:57
JA3Buffer_::data
char * data
Definition: util-ja3.h:32
util-ja3.h
OutputJsonBuilderBuffer
void OutputJsonBuilderBuffer(ThreadVars *tv, const Packet *p, Flow *f, SCJsonBuilder *js, OutputJsonThreadCtx *ctx)
Definition: output-json.c:994
LOG_TLS_FIELD_SUBJECT
#define LOG_TLS_FIELD_SUBJECT
Definition: output-json-tls.c:41
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:852
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
JsonTlsLogThread
struct JsonTlsLogThread_ JsonTlsLogThread
LOG_TLS_FIELD_FINGERPRINT
#define LOG_TLS_FIELD_FINGERPRINT
Definition: output-json-tls.c:44
JsonTlsLogRegister
void JsonTlsLogRegister(void)
Definition: output-json-tls.c:732
TlsFields::flag
uint64_t flag
Definition: output-json-tls.c:65
SSLSubjectAltName_::san
uint8_t * san
Definition: app-layer-ssl.h:169
JsonTlsLogThread_::ctx
OutputJsonThreadCtx * ctx
Definition: output-json-tls.c:129
OutputCtx_::data
void * data
Definition: tm-modules.h:91
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
OutputCtx_
Definition: tm-modules.h:88
OutputJsonThreadCtx_
Definition: output-json.h:85
SSLStateConnp_::cert0_not_after
int64_t cert0_not_after
Definition: app-layer-ssl.h:200
SSLStateConnp_::cert0_sans
SSLSubjectAltName * cert0_sans
Definition: app-layer-ssl.h:203
SCTIME_FROM_SECS
#define SCTIME_FROM_SECS(s)
Definition: util-time.h:69
BASIC_FIELDS
#define BASIC_FIELDS
Definition: output-json-tls.c:98
OutputTlsCtx_::eve_ctx
OutputJsonCtx * eve_ctx
Definition: output-json-tls.c:124
util-debug.h
TlsFields::name
const char * name
Definition: output-json-tls.c:64
TLS_STATE_CLIENT_HANDSHAKE_DONE
@ TLS_STATE_CLIENT_HANDSHAKE_DONE
Definition: app-layer-ssl.h:82
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:250
LOG_TLS_FIELD_JA3S
#define LOG_TLS_FIELD_JA3S
Definition: output-json-tls.c:52
LOG_TLS_FIELD_JA4
#define LOG_TLS_FIELD_JA4
Definition: output-json-tls.c:56
OutputInitResult_::ctx
OutputCtx * ctx
Definition: output.h:47
SCAppLayerParserRegisterLogger
void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
Definition: app-layer-parser.c:495
output-json.h
SSLCertsChain_
Definition: app-layer-ssl.h:162
SSLStateConnp_::cert0_serial_len
uint32_t cert0_serial_len
Definition: app-layer-ssl.h:198
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
LOG_TLS_FIELD_CLIENT_CERT
#define LOG_TLS_FIELD_CLIENT_CERT
Definition: output-json-tls.c:54
util-time.h
OutputInitResult_::ok
bool ok
Definition: output.h:48
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
SSLStateConnp_::cert0_serial
uint8_t * cert0_serial
Definition: app-layer-ssl.h:197
LOG_DIR_FLOW
@ LOG_DIR_FLOW
Definition: output-eve-bindgen.h:35
app-layer-parser.h
LOG_TLS_FIELD_SERIAL
#define LOG_TLS_FIELD_SERIAL
Definition: output-json-tls.c:43
Packet_
Definition: decode.h:505
conf.h
SSLStateConnp_::cert0_issuerdn
uint8_t * cert0_issuerdn
Definition: app-layer-ssl.h:195
OutputTlsCtx
struct OutputTlsCtx_ OutputTlsCtx
SCTime_t
Definition: util-time.h:40
TmEcode
TmEcode
Definition: tm-threads-common.h:80
SSLStateConnp_::sni
uint8_t * sni
Definition: app-layer-ssl.h:206
SSLCertsChain_::cert_data
uint8_t * cert_data
Definition: app-layer-ssl.h:163
SSLStateConnp_::cert0_sans_num
uint16_t cert0_sans_num
Definition: app-layer-ssl.h:204
LOG_TLS_FIELD_ISSUER
#define LOG_TLS_FIELD_ISSUER
Definition: output-json-tls.c:42
OutputTlsCtx_::session_resumed
bool session_resumed
Definition: output-json-tls.c:123
SCConfNodeLookupChild
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:824
OutputInitResult_
Definition: output.h:46
CreateUtcIsoTimeString
void CreateUtcIsoTimeString(const SCTime_t ts, char *str, size_t size)
Definition: util-time.c:230
Packet_::flow
struct Flow_ * flow
Definition: decode.h:553
SSLStateConnp_::cert0_subject_len
uint32_t cert0_subject_len
Definition: app-layer-ssl.h:194
suricata-common.h
OutputCtx_::DeInit
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:94
tls_fields
TlsFields tls_fields[]
Definition: output-json-tls.c:68
LOG_TLS_FIELD_CERTIFICATE
#define LOG_TLS_FIELD_CERTIFICATE
Definition: output-json-tls.c:48
OutputTlsCtx_
Definition: output-json-tls.c:121
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:33
threadvars.h
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
LOGGER_JSON_TX
@ LOGGER_JSON_TX
Definition: suricata-common.h:485
SCFree
#define SCFree(p)
Definition: util-mem.h:61
AppLayerGetProtoName
const char * AppLayerGetProtoName(AppProto alproto)
Given the internal protocol id, returns a string representation of the protocol.
Definition: app-layer.c:1014
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
OutputTlsCtx_::fields
uint64_t fields
Definition: output-json-tls.c:122
LOG_TLS_FIELD_SNI
#define LOG_TLS_FIELD_SNI
Definition: output-json-tls.c:47
SSLStateConnp_::hs
HandshakeParams * hs
Definition: app-layer-ssl.h:221
SSLStateConnp_::cert0_issuerdn_len
uint32_t cert0_issuerdn_len
Definition: app-layer-ssl.h:196
EXTENDED_FIELDS
#define EXTENDED_FIELDS
Definition: output-json-tls.c:105
SSLStateConnp_::cert0_fingerprint
char * cert0_fingerprint
Definition: app-layer-ssl.h:201
SSLStateConnp_::sni_len
uint16_t sni_len
Definition: app-layer-ssl.h:207
SSLStateConnp_::ja3_str
JA3Buffer * ja3_str
Definition: app-layer-ssl.h:218
TLS_STATE_SERVER_HANDSHAKE_DONE
@ TLS_STATE_SERVER_HANDSHAKE_DONE
Definition: app-layer-ssl.h:91
JsonTlsLogThread_::tlslog_ctx
OutputTlsCtx * tlslog_ctx
Definition: output-json-tls.c:128
LOG_TLS_FIELD_SESSION_RESUMED
#define LOG_TLS_FIELD_SESSION_RESUMED
Definition: output-json-tls.c:50
LOG_TLS_FIELD_CLIENT_CHAIN
#define LOG_TLS_FIELD_CLIENT_CHAIN
Definition: output-json-tls.c:55
LOG_TLS_FIELD_CLIENT
#define LOG_TLS_FIELD_CLIENT
Definition: output-json-tls.c:53
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
LOG_TLS_FIELD_CHAIN
#define LOG_TLS_FIELD_CHAIN
Definition: output-json-tls.c:49
SCConfNode_
Definition: conf.h:37
SCConfNode_::val
char * val
Definition: conf.h:39
LOG_TLS_FIELD_VERSION
#define LOG_TLS_FIELD_VERSION
Definition: output-json-tls.c:40
JsonTlsLogThread_
Definition: output-json-tls.c:127
app-layer-ssl.h
SSL_AL_FLAG_LOG_WITHOUT_CERT
#define SSL_AL_FLAG_LOG_WITHOUT_CERT
Definition: app-layer-ssl.h:129
LOG_TLS_FIELD_CLIENT_HANDSHAKE
#define LOG_TLS_FIELD_CLIENT_HANDSHAKE
Definition: output-json-tls.c:60
output.h
app-layer.h
SSLStateConnp_::cert0_subject
uint8_t * cert0_subject
Definition: app-layer-ssl.h:193
SSLState_::flags
uint32_t flags
Definition: app-layer-ssl.h:244
SSLStateConnp_::version
uint16_t version
Definition: app-layer-ssl.h:182