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