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  if (connp->cert0_subject || connp->cert0_issuerdn)
346  return true;
347  return false;
348 }
349 
350 static void JsonTlsLogClientCert(
351  SCJsonBuilder *js, SSLStateConnp *connp, const bool log_cert, const bool log_chain)
352 {
353  if (connp->cert0_subject != NULL) {
354  if (connp->cert0_subject_len == 0) {
355  SCJbSetString(js, "subject", "");
356  } else {
357  SCJbSetStringFromBytes(js, "subject", connp->cert0_subject, connp->cert0_subject_len);
358  }
359  }
360  if (connp->cert0_issuerdn != NULL) {
361  if (connp->cert0_issuerdn_len == 0) {
362  SCJbSetString(js, "issuerdn", "");
363  } else {
364  SCJbSetStringFromBytes(
365  js, "issuerdn", connp->cert0_issuerdn, connp->cert0_issuerdn_len);
366  }
367  }
368  if (connp->cert0_fingerprint) {
369  SCJbSetString(js, "fingerprint", connp->cert0_fingerprint);
370  }
371  if (connp->cert0_serial) {
372  SCJbSetStringFromBytes(js, "serial", connp->cert0_serial, connp->cert0_serial_len);
373  }
374  if (connp->cert0_not_before != 0) {
375  char timebuf[64];
377  CreateUtcIsoTimeString(ts, timebuf, sizeof(timebuf));
378  SCJbSetString(js, "notbefore", timebuf);
379  }
380  if (connp->cert0_not_after != 0) {
381  char timebuf[64];
383  CreateUtcIsoTimeString(ts, timebuf, sizeof(timebuf));
384  SCJbSetString(js, "notafter", timebuf);
385  }
386 
387  if (log_cert) {
388  JsonTlsLogCertificate(js, connp);
389  }
390  if (log_chain) {
391  JsonTlsLogChain(js, connp);
392  }
393 }
394 
395 static void JsonTlsLogClientHandshake(SCJsonBuilder *js, SSLState *ssl_state)
396 {
397  if (ssl_state->client_connp.hs == NULL) {
398  return;
399  }
400 
401  // Don't write an empty handshake
402  if (SCTLSHandshakeIsEmpty(ssl_state->client_connp.hs)) {
403  return;
404  }
405 
406  SCJbOpenObject(js, "client_handshake");
407 
408  SCTLSHandshakeLogVersion(ssl_state->client_connp.hs, js);
409  SCTLSHandshakeLogCiphers(ssl_state->client_connp.hs, js);
410  SCTLSHandshakeLogExtensions(ssl_state->client_connp.hs, js);
411  SCTLSHandshakeLogSigAlgs(ssl_state->client_connp.hs, js);
412 
413  SCJbClose(js);
414 }
415 
416 static void JsonTlsLogServerHandshake(SCJsonBuilder *js, SSLState *ssl_state)
417 {
418  if (ssl_state->server_connp.hs == NULL) {
419  return;
420  }
421 
422  if (SCTLSHandshakeIsEmpty(ssl_state->server_connp.hs)) {
423  return;
424  }
425 
426  SCJbOpenObject(js, "server_handshake");
427 
428  SCTLSHandshakeLogVersion(ssl_state->server_connp.hs, js);
429  SCTLSHandshakeLogFirstCipher(ssl_state->server_connp.hs, js);
430  SCTLSHandshakeLogExtensions(ssl_state->server_connp.hs, js);
431 
432  SCJbClose(js);
433 }
434 
435 static void JsonTlsLogFields(SCJsonBuilder *js, SSLState *ssl_state, uint64_t fields)
436 {
437  /* tls subject */
438  if (fields & LOG_TLS_FIELD_SUBJECT)
439  JsonTlsLogSubject(js, ssl_state);
440 
441  /* tls issuerdn */
442  if (fields & LOG_TLS_FIELD_ISSUER)
443  JsonTlsLogIssuer(js, ssl_state);
444 
445  /* tls subjectaltname */
446  if (fields & LOG_TLS_FIELD_SUBJECTALTNAME)
447  JsonTlsLogSAN(js, ssl_state);
448 
449  /* tls session resumption */
450  if (fields & LOG_TLS_FIELD_SESSION_RESUMED)
451  JsonTlsLogSessionResumed(js, ssl_state);
452 
453  /* tls serial */
454  if (fields & LOG_TLS_FIELD_SERIAL)
455  JsonTlsLogSerial(js, ssl_state);
456 
457  /* tls fingerprint */
458  if (fields & LOG_TLS_FIELD_FINGERPRINT)
459  JsonTlsLogFingerprint(js, ssl_state);
460 
461  /* tls sni */
462  if (fields & LOG_TLS_FIELD_SNI)
463  JsonTlsLogSni(js, ssl_state);
464 
465  /* tls version */
466  if (fields & LOG_TLS_FIELD_VERSION) {
467  JsonTlsLogVersion(js, ssl_state);
468  }
469 
470  /* tls notbefore */
471  if (fields & LOG_TLS_FIELD_NOTBEFORE)
472  JsonTlsLogNotBefore(js, ssl_state);
473 
474  /* tls notafter */
475  if (fields & LOG_TLS_FIELD_NOTAFTER)
476  JsonTlsLogNotAfter(js, ssl_state);
477 
478  /* tls certificate */
479  if (fields & LOG_TLS_FIELD_CERTIFICATE)
480  JsonTlsLogCertificate(js, &ssl_state->server_connp);
481 
482  /* tls chain */
483  if (fields & LOG_TLS_FIELD_CHAIN)
484  JsonTlsLogChain(js, &ssl_state->server_connp);
485 
486  /* tls ja3_hash */
487  if (fields & LOG_TLS_FIELD_JA3)
488  JsonTlsLogJa3(js, ssl_state);
489 
490  /* tls ja3s */
491  if (fields & LOG_TLS_FIELD_JA3S)
492  JsonTlsLogJa3S(js, ssl_state);
493 
494  /* tls ja4 */
495  if (fields & LOG_TLS_FIELD_JA4)
496  JsonTlsLogSCJA4(js, ssl_state);
497 
498  if (fields & LOG_TLS_FIELD_CLIENT_ALPNS) {
499  JsonTlsLogAlpns(js, &ssl_state->client_connp, "client_alpns");
500  }
501 
502  if (fields & LOG_TLS_FIELD_SERVER_ALPNS) {
503  JsonTlsLogAlpns(js, &ssl_state->server_connp, "server_alpns");
504  }
505 
506  /* tls client handshake parameters */
507  if (fields & LOG_TLS_FIELD_CLIENT_HANDSHAKE)
508  JsonTlsLogClientHandshake(js, ssl_state);
509 
510  /* tls server handshake parameters */
511  if (fields & LOG_TLS_FIELD_SERVER_HANDSHAKE)
512  JsonTlsLogServerHandshake(js, ssl_state);
513 
514  if (fields & LOG_TLS_FIELD_CLIENT) {
515  const bool log_cert = (fields & LOG_TLS_FIELD_CLIENT_CERT) != 0;
516  const bool log_chain = (fields & LOG_TLS_FIELD_CLIENT_CHAIN) != 0;
517  if (HasClientCert(&ssl_state->client_connp)) {
518  SCJbOpenObject(js, "client");
519  JsonTlsLogClientCert(js, &ssl_state->client_connp, log_cert, log_chain);
520  SCJbClose(js);
521  }
522  }
523 }
524 
525 bool JsonTlsLogJSONExtended(void *vtx, SCJsonBuilder *tjs)
526 {
527  SSLState *state = (SSLState *)vtx;
528  SCJbOpenObject(tjs, "tls");
529  JsonTlsLogFields(tjs, state, EXTENDED_FIELDS);
530  return SCJbClose(tjs);
531 }
532 
533 static int JsonTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p,
534  Flow *f, void *state, void *txptr, uint64_t tx_id)
535 {
536  JsonTlsLogThread *aft = (JsonTlsLogThread *)thread_data;
537  OutputTlsCtx *tls_ctx = aft->tlslog_ctx;
538 
539  SSLState *ssl_state = (SSLState *)state;
540  if (unlikely(ssl_state == NULL)) {
541  return 0;
542  }
543 
544  if ((ssl_state->server_connp.cert0_issuerdn == NULL ||
545  ssl_state->server_connp.cert0_subject == NULL) &&
546  ((ssl_state->flags & SSL_AL_FLAG_SESSION_RESUMED) == 0 ||
547  (!tls_ctx->session_resumed)) &&
548  ((ssl_state->flags & SSL_AL_FLAG_LOG_WITHOUT_CERT) == 0)) {
549  return 0;
550  }
551 
552  SCJsonBuilder *js = CreateEveHeader(p, LOG_DIR_FLOW, "tls", NULL, aft->tlslog_ctx->eve_ctx);
553  if (unlikely(js == NULL)) {
554  return 0;
555  }
556 
557  SCJbOpenObject(js, "tls");
558 
559  JsonTlsLogFields(js, ssl_state, tls_ctx->fields);
560 
561  /* print original application level protocol when it have been changed
562  because of STARTTLS, HTTP CONNECT, or similar. */
563  if (f->alproto_orig != ALPROTO_UNKNOWN) {
564  SCJbSetString(js, "from_proto", AppLayerGetProtoName(f->alproto_orig));
565  }
566 
567  /* Close the tls object. */
568  SCJbClose(js);
569 
570  OutputJsonBuilderBuffer(tv, p, p->flow, js, aft->ctx);
571  SCJbFree(js);
572 
573  return 0;
574 }
575 
576 static TmEcode JsonTlsLogThreadInit(ThreadVars *t, const void *initdata, void **data)
577 {
578  JsonTlsLogThread *aft = SCCalloc(1, sizeof(JsonTlsLogThread));
579  if (unlikely(aft == NULL)) {
580  return TM_ECODE_FAILED;
581  }
582 
583  if (initdata == NULL) {
584  SCLogDebug("Error getting context for eve-log tls 'initdata' argument NULL");
585  goto error_exit;
586  }
587 
588  /* use the Output Context (file pointer and mutex) */
589  aft->tlslog_ctx = ((OutputCtx *)initdata)->data;
590 
591  aft->ctx = CreateEveThreadCtx(t, aft->tlslog_ctx->eve_ctx);
592  if (!aft->ctx) {
593  goto error_exit;
594  }
595  *data = (void *)aft;
596  return TM_ECODE_OK;
597 
598 error_exit:
599  SCFree(aft);
600  return TM_ECODE_FAILED;
601 }
602 
603 static TmEcode JsonTlsLogThreadDeinit(ThreadVars *t, void *data)
604 {
605  JsonTlsLogThread *aft = (JsonTlsLogThread *)data;
606  if (aft == NULL) {
607  return TM_ECODE_OK;
608  }
609 
610  FreeEveThreadCtx(aft->ctx);
611 
612  /* clear memory */
613  memset(aft, 0, sizeof(JsonTlsLogThread));
614 
615  SCFree(aft);
616  return TM_ECODE_OK;
617 }
618 
619 static OutputTlsCtx *OutputTlsInitCtx(SCConfNode *conf)
620 {
621  OutputTlsCtx *tls_ctx = SCCalloc(1, sizeof(OutputTlsCtx));
622  if (unlikely(tls_ctx == NULL))
623  return NULL;
624 
625  tls_ctx->fields = BASIC_FIELDS;
626  tls_ctx->session_resumed = false;
627 
628  if (conf == NULL)
629  return tls_ctx;
630 
631  const char *extended = SCConfNodeLookupChildValue(conf, "extended");
632  if (extended) {
633  if (SCConfValIsTrue(extended)) {
634  tls_ctx->fields = EXTENDED_FIELDS;
635  }
636  }
637 
638  SCConfNode *custom = SCConfNodeLookupChild(conf, "custom");
639  if (custom) {
640  tls_ctx->fields = 0;
641  SCConfNode *field;
642  TAILQ_FOREACH(field, &custom->head, next)
643  {
644  bool valid = false;
645  TlsFields *valid_fields = tls_fields;
646  for ( ; valid_fields->name != NULL; valid_fields++) {
647  if (strcasecmp(field->val, valid_fields->name) == 0) {
648  tls_ctx->fields |= valid_fields->flag;
649  SCLogDebug("enabled %s", field->val);
650  valid = true;
651  break;
652  }
653  }
654  if (!valid) {
655  SCLogWarning("eve.tls: unknown 'custom' field '%s'", field->val);
656  }
657  }
658  }
659 
660  const char *session_resumption = SCConfNodeLookupChildValue(conf, "session-resumption");
661  if (session_resumption == NULL || SCConfValIsTrue(session_resumption)) {
663  tls_ctx->session_resumed = true;
664  }
665 
666  if ((tls_ctx->fields & LOG_TLS_FIELD_CERTIFICATE) &&
667  (tls_ctx->fields & LOG_TLS_FIELD_CHAIN)) {
668  SCLogWarning("Both 'certificate' and 'chain' contains the top "
669  "certificate, so only one of them should be enabled "
670  "at a time");
671  }
672  if ((tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CERT) &&
673  (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CHAIN)) {
674  SCLogWarning("Both 'client_certificate' and 'client_chain' contains the top "
675  "certificate, so only one of them should be enabled "
676  "at a time");
677  }
678 
679  if ((tls_ctx->fields & LOG_TLS_FIELD_CLIENT) == 0) {
680  if (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CERT) {
681  SCLogConfig("enabling \"client\" as a dependency of \"client_certificate\"");
682  tls_ctx->fields |= LOG_TLS_FIELD_CLIENT;
683  }
684  if (tls_ctx->fields & LOG_TLS_FIELD_CLIENT_CHAIN) {
685  SCLogConfig("enabling \"client\" as a dependency of \"client_chain\"");
686  tls_ctx->fields |= LOG_TLS_FIELD_CLIENT;
687  }
688  }
689 
690  return tls_ctx;
691 }
692 
693 static void OutputTlsLogDeinitSub(OutputCtx *output_ctx)
694 {
695  OutputTlsCtx *tls_ctx = output_ctx->data;
696  SCFree(tls_ctx);
697  SCFree(output_ctx);
698 }
699 
700 static OutputInitResult OutputTlsLogInitSub(SCConfNode *conf, OutputCtx *parent_ctx)
701 {
702  OutputInitResult result = { NULL, false };
703  OutputJsonCtx *ojc = parent_ctx->data;
704 
705  OutputTlsCtx *tls_ctx = OutputTlsInitCtx(conf);
706  if (unlikely(tls_ctx == NULL))
707  return result;
708 
709  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
710  if (unlikely(output_ctx == NULL)) {
711  SCFree(tls_ctx);
712  return result;
713  }
714 
715  tls_ctx->eve_ctx = ojc;
716 
717  if ((tls_ctx->fields & LOG_TLS_FIELD_CERTIFICATE) &&
718  (tls_ctx->fields & LOG_TLS_FIELD_CHAIN)) {
719  SCLogWarning("Both 'certificate' and 'chain' contains the top "
720  "certificate, so only one of them should be enabled "
721  "at a time");
722  }
723 
724  output_ctx->data = tls_ctx;
725  output_ctx->DeInit = OutputTlsLogDeinitSub;
726 
728 
729  result.ctx = output_ctx;
730  result.ok = true;
731  return result;
732 }
733 
735 {
736  /* register as child of eve-log */
737  OutputRegisterTxSubModuleWithProgress(LOGGER_JSON_TX, "eve-log", "JsonTlsLog", "eve-log.tls",
738  OutputTlsLogInitSub, ALPROTO_TLS, JsonTlsLogger, TLS_STATE_SERVER_HANDSHAKE_DONE,
739  TLS_STATE_CLIENT_HANDSHAKE_DONE, JsonTlsLogThreadInit, JsonTlsLogThreadDeinit);
740 }
SSLState_
SSLv[2.0|3.[0|1|2|3]] state structure.
Definition: app-layer-ssl.h:236
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:169
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:163
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:525
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:380
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:257
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:258
SSLStateConnp_::cert0_not_before
int64_t cert0_not_before
Definition: app-layer-ssl.h:198
SSL_AL_FLAG_SESSION_RESUMED
#define SSL_AL_FLAG_SESSION_RESUMED
Definition: app-layer-ssl.h:121
FreeEveThreadCtx
void FreeEveThreadCtx(OutputJsonThreadCtx *ctx)
Definition: output-json-common.c:58
SSLStateConnp_
Definition: app-layer-ssl.h:172
SSLStateConnp_::ja3_hash
char * ja3_hash
Definition: app-layer-ssl.h:218
CreateEveHeader
SCJsonBuilder * CreateEveHeader(const Packet *p, enum SCOutputJsonLogDirection dir, const char *event_type, JsonAddrInfo *addr, OutputJsonCtx *eve_ctx)
Definition: output-json.c:834
OutputJsonCtx_
Definition: output-json.h:75
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:110
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:447
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:1000
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:855
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:734
TlsFields::flag
uint64_t flag
Definition: output-json-tls.c:65
SSLSubjectAltName_::san
uint8_t * san
Definition: app-layer-ssl.h:168
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:83
SSLStateConnp_::cert0_not_after
int64_t cert0_not_after
Definition: app-layer-ssl.h:199
SSLStateConnp_::cert0_sans
SSLSubjectAltName * cert0_sans
Definition: app-layer-ssl.h:202
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:81
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:477
output-json.h
SSLCertsChain_
Definition: app-layer-ssl.h:161
SSLStateConnp_::cert0_serial_len
uint32_t cert0_serial_len
Definition: app-layer-ssl.h:197
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:196
LOG_DIR_FLOW
@ LOG_DIR_FLOW
Definition: output-eve-bindgen.h:33
app-layer-parser.h
LOG_TLS_FIELD_SERIAL
#define LOG_TLS_FIELD_SERIAL
Definition: output-json-tls.c:43
Packet_
Definition: decode.h:501
conf.h
SSLStateConnp_::cert0_issuerdn
uint8_t * cert0_issuerdn
Definition: app-layer-ssl.h:194
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:205
SSLCertsChain_::cert_data
uint8_t * cert_data
Definition: app-layer-ssl.h:162
SSLStateConnp_::cert0_sans_num
uint16_t cert0_sans_num
Definition: app-layer-ssl.h:203
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:827
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:546
SSLStateConnp_::cert0_subject_len
uint32_t cert0_subject_len
Definition: app-layer-ssl.h:193
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:220
SSLStateConnp_::cert0_issuerdn_len
uint32_t cert0_issuerdn_len
Definition: app-layer-ssl.h:195
EXTENDED_FIELDS
#define EXTENDED_FIELDS
Definition: output-json-tls.c:105
SSLStateConnp_::cert0_fingerprint
char * cert0_fingerprint
Definition: app-layer-ssl.h:200
SSLStateConnp_::sni_len
uint16_t sni_len
Definition: app-layer-ssl.h:206
SSLStateConnp_::ja3_str
JA3Buffer * ja3_str
Definition: app-layer-ssl.h:217
TLS_STATE_SERVER_HANDSHAKE_DONE
@ TLS_STATE_SERVER_HANDSHAKE_DONE
Definition: app-layer-ssl.h:90
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:128
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:192
SSLState_::flags
uint32_t flags
Definition: app-layer-ssl.h:243
SSLStateConnp_::version
uint16_t version
Definition: app-layer-ssl.h:181