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