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