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