fi
fi
+ AC_ARG_ENABLE(ja3,
+ AS_HELP_STRING([--disable-ja3], [Disable JA3 support]),
+ [enable_ja3="$enableval"],
+ [enable_ja3=yes])
+ if test "$enable_ja3" = "yes"; then
+ AC_DEFINE([HAVE_JA3],[1],[JA3 enabled])
+ enable_ja3="yes"
+ fi
+ AM_CONDITIONAL([HAVE_JA3], [test "x$enable_ja3" != "xno"])
+
# Check for lz4
enable_liblz4="yes"
AC_CHECK_LIB(lz4, LZ4F_createCompressionContext, , enable_liblz4="no")
LUA support: ${enable_lua}
libluajit: ${enable_luajit}
GeoIP2 support: ${enable_geoip}
+ JA3 support: ${enable_ja3}
Non-bundled htp: ${enable_non_bundled_htp}
Hyperscan support: ${enable_hyperscan}
Libnet support: ${enable_libnet}
strict = []
debug = []
debug-validate = []
+ja3 = []
[dependencies]
nom7 = { version="7.0", package="nom" }
RUST_FEATURES += lua $(LUA_INT8)
endif
+if HAVE_JA3
+RUST_FEATURES += ja3
+endif
+
if DEBUG
RUST_FEATURES += debug
endif
// We remap the Vec<TlsExtension> from tls_parser::parse_tls_extensions because of
// the lifetime of TlsExtension due to references to the slice used for parsing
pub extv: Vec<QuicTlsExtension>,
- pub ja3: String,
+ pub ja3: Option<String>,
}
#[derive(Debug, PartialEq)]
ja3.push(',');
let ciphers = ch.ciphers;
let extv = quic_get_tls_extensions(ch.ext, &mut ja3, true);
- return Some(Frame::Crypto(Crypto { ciphers, extv, ja3 }));
+ return Some(Frame::Crypto(Crypto {
+ ciphers,
+ extv,
+ ja3: if cfg!(feature = "ja3") {
+ Some(ja3)
+ } else {
+ None
+ },
+ }));
}
ServerHello(sh) => {
let mut ja3 = String::with_capacity(256);
ja3.push(',');
let ciphers = vec![sh.cipher];
let extv = quic_get_tls_extensions(sh.ext, &mut ja3, false);
- return Some(Frame::Crypto(Crypto { ciphers, extv, ja3 }));
+ return Some(Frame::Crypto(Crypto {
+ ciphers,
+ extv,
+ ja3: if cfg!(feature = "ja3") {
+ Some(ja3)
+ } else {
+ None
+ },
+ }));
}
_ => {}
}
}
}
Frame::Crypto(c) => {
- ja3 = Some(c.ja3.clone());
+ if let Some(ja3str) = &c.ja3 {
+ ja3 = Some(ja3str.clone());
+ }
for e in &c.extv {
if e.etype == TlsExtensionType::ServerName && !e.values.is_empty() {
sni = Some(e.values[0].to_vec());
#include "decode-events.h"
#include "conf.h"
+#include "feature.h"
+
#include "util-spm.h"
#include "util-unittest.h"
#include "util-debug.h"
return 0;
}
+#ifdef HAVE_JA3
+static void CheckJA3Enabled(void)
+{
+ const char *strval = NULL;
+ /* Check if we should generate JA3 fingerprints */
+ int enable_ja3 = SSL_CONFIG_DEFAULT_JA3;
+ if (ConfGet("app-layer.protocols.tls.ja3-fingerprints", &strval) != 1) {
+ enable_ja3 = SSL_CONFIG_DEFAULT_JA3;
+ } else if (strcmp(strval, "auto") == 0) {
+ enable_ja3 = SSL_CONFIG_DEFAULT_JA3;
+ } else if (ConfValIsFalse(strval)) {
+ enable_ja3 = 0;
+ ssl_config.disable_ja3 = true;
+ } else if (ConfValIsTrue(strval)) {
+ enable_ja3 = true;
+ }
+ SC_ATOMIC_SET(ssl_config.enable_ja3, enable_ja3);
+ if (!ssl_config.disable_ja3 && !g_disable_hashing) {
+ /* The feature is available, i.e. _could_ be activated by a rule or
+ even is enabled in the configuration. */
+ ProvidesFeature(FEATURE_JA3);
+ }
+}
+#endif /* HAVE_JA3 */
+
/**
* \brief Function to register the SSL protocol parser and other functions
*/
}
SCLogDebug("ssl_config.encrypt_mode %u", ssl_config.encrypt_mode);
- /* Check if we should generate JA3 fingerprints */
- int enable_ja3 = SSL_CONFIG_DEFAULT_JA3;
- const char *strval = NULL;
- if (ConfGet("app-layer.protocols.tls.ja3-fingerprints", &strval) != 1) {
- enable_ja3 = SSL_CONFIG_DEFAULT_JA3;
- } else if (strcmp(strval, "auto") == 0) {
- enable_ja3 = SSL_CONFIG_DEFAULT_JA3;
- } else if (ConfValIsFalse(strval)) {
- enable_ja3 = 0;
- ssl_config.disable_ja3 = true;
- } else if (ConfValIsTrue(strval)) {
- enable_ja3 = true;
- }
- SC_ATOMIC_SET(ssl_config.enable_ja3, enable_ja3);
+#ifdef HAVE_JA3
+ CheckJA3Enabled();
+#endif /* HAVE_JA3 */
if (g_disable_hashing) {
if (SC_ATOMIC_GET(ssl_config.enable_ja3)) {
}
} else {
if (RunmodeIsUnittests()) {
+#ifdef HAVE_JA3
SC_ATOMIC_SET(ssl_config.enable_ja3, 1);
+#endif /* HAVE_JA3 */
}
}
} else {
#include "util-unittest.h"
#include "util-unittest-helper.h"
+#ifndef HAVE_JA3
+static int DetectJA3SetupNoSupport(DetectEngineCtx *a, Signature *b, const char *c)
+{
+ SCLogError("no JA3 support built in");
+ return -1;
+}
+#endif
+
static int DetectTlsJa3HashSetup(DetectEngineCtx *, Signature *, const char *);
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms,
sigmatch_table[DETECT_AL_TLS_JA3_HASH].alias = "ja3_hash";
sigmatch_table[DETECT_AL_TLS_JA3_HASH].desc = "sticky buffer to match the JA3 hash buffer";
sigmatch_table[DETECT_AL_TLS_JA3_HASH].url = "/rules/ja3-keywords.html#ja3-hash";
+#ifdef HAVE_JA3
sigmatch_table[DETECT_AL_TLS_JA3_HASH].Setup = DetectTlsJa3HashSetup;
+#else /* HAVE_JA3 */
+ sigmatch_table[DETECT_AL_TLS_JA3_HASH].Setup = DetectJA3SetupNoSupport;
+#endif /* HAVE_JA3 */
sigmatch_table[DETECT_AL_TLS_JA3_HASH].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_TLS_JA3_HASH].flags |= SIGMATCH_INFO_STICKY_BUFFER;
+#ifdef HAVE_JA3
DetectAppLayerInspectEngineRegister("ja3.hash", ALPROTO_TLS, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric, GetData);
DetectTlsJa3HashValidateCallback);
g_tls_ja3_hash_buffer_id = DetectBufferTypeGetByName("ja3.hash");
+#endif /* HAVE_JA3 */
}
/**
#include "util-unittest.h"
#include "util-unittest-helper.h"
+#ifndef HAVE_JA3
+static int DetectJA3SetupNoSupport(DetectEngineCtx *a, Signature *b, const char *c)
+{
+ SCLogError("no JA3 support built in");
+ return -1;
+}
+#endif /* HAVE_JA3 */
+
static int DetectTlsJa3StringSetup(DetectEngineCtx *, Signature *, const char *);
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms,
sigmatch_table[DETECT_AL_TLS_JA3_STRING].alias = "ja3_string";
sigmatch_table[DETECT_AL_TLS_JA3_STRING].desc = "sticky buffer to match the JA3 string buffer";
sigmatch_table[DETECT_AL_TLS_JA3_STRING].url = "/rules/ja3-keywords.html#ja3-string";
+#ifdef HAVE_JA3
sigmatch_table[DETECT_AL_TLS_JA3_STRING].Setup = DetectTlsJa3StringSetup;
+#else /* HAVE_JA3 */
+ sigmatch_table[DETECT_AL_TLS_JA3_STRING].Setup = DetectJA3SetupNoSupport;
+#endif /* HAVE_JA3 */
sigmatch_table[DETECT_AL_TLS_JA3_STRING].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_TLS_JA3_STRING].flags |= SIGMATCH_INFO_STICKY_BUFFER;
+#ifdef HAVE_JA3
DetectAppLayerInspectEngineRegister("ja3.string", ALPROTO_TLS, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectBufferGeneric, GetData);
DetectBufferTypeSetDescriptionByName("ja3.string", "TLS JA3 string");
g_tls_ja3_str_buffer_id = DetectBufferTypeGetByName("ja3.string");
+#endif /* HAVE_JA3 */
}
/**
#include "util-unittest.h"
#include "util-unittest-helper.h"
+#ifndef HAVE_JA3
+static int DetectJA3SetupNoSupport(DetectEngineCtx *a, Signature *b, const char *c)
+{
+ SCLogError("no JA3 support built in");
+ return -1;
+}
+#endif /* HAVE_JA3 */
+
static int DetectTlsJa3SHashSetup(DetectEngineCtx *, Signature *, const char *);
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms,
sigmatch_table[DETECT_AL_TLS_JA3S_HASH].name = "ja3s.hash";
sigmatch_table[DETECT_AL_TLS_JA3S_HASH].desc = "sticky buffer to match the JA3S hash buffer";
sigmatch_table[DETECT_AL_TLS_JA3S_HASH].url = "/rules/ja3-keywords.html#ja3s-hash";
+#ifdef HAVE_JA3
sigmatch_table[DETECT_AL_TLS_JA3S_HASH].Setup = DetectTlsJa3SHashSetup;
+#else /* HAVE_JA3 */
+ sigmatch_table[DETECT_AL_TLS_JA3S_HASH].Setup = DetectJA3SetupNoSupport;
+#endif /* HAVE_JA3 */
sigmatch_table[DETECT_AL_TLS_JA3S_HASH].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_TLS_JA3S_HASH].flags |= SIGMATCH_INFO_STICKY_BUFFER;
+#ifdef HAVE_JA3
DetectAppLayerInspectEngineRegister("ja3s.hash", ALPROTO_TLS, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric, GetData);
DetectTlsJa3SHashValidateCallback);
g_tls_ja3s_hash_buffer_id = DetectBufferTypeGetByName("ja3s.hash");
+#endif /* HAVE_JA3 */
}
/**
#include "util-unittest.h"
#include "util-unittest-helper.h"
+#ifndef HAVE_JA3
+static int DetectJA3SetupNoSupport(DetectEngineCtx *a, Signature *b, const char *c)
+{
+ SCLogError("no JA3 support built in");
+ return -1;
+}
+#endif /* HAVE_JA3 */
+
static int DetectTlsJa3SStringSetup(DetectEngineCtx *, Signature *, const char *);
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms,
sigmatch_table[DETECT_AL_TLS_JA3S_STRING].desc =
"sticky buffer to match the JA3S string buffer";
sigmatch_table[DETECT_AL_TLS_JA3S_STRING].url = "/rules/ja3-keywords.html#ja3s-string";
+#ifdef HAVE_JA3
sigmatch_table[DETECT_AL_TLS_JA3S_STRING].Setup = DetectTlsJa3SStringSetup;
+#else /* HAVE_JA3 */
+ sigmatch_table[DETECT_AL_TLS_JA3S_STRING].Setup = DetectJA3SetupNoSupport;
+#endif /* HAVE_JA3 */
sigmatch_table[DETECT_AL_TLS_JA3S_STRING].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_TLS_JA3S_STRING].flags |= SIGMATCH_INFO_STICKY_BUFFER;
+#ifdef HAVE_JA3
DetectAppLayerInspectEngineRegister("ja3s.string", ALPROTO_TLS, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectBufferGeneric, GetData);
DetectBufferTypeSetDescriptionByName("ja3s.string", "TLS JA3S string");
g_tls_ja3s_str_buffer_id = DetectBufferTypeGetByName("ja3s.string");
+#endif /* HAVE_JA3 */
}
/**
/* Provided feature names */
#define FEATURE_OUTPUT_FILESTORE "output::file-store"
+#define FEATURE_JA3 "ja3"
void ProvidesFeature(const char *);
bool RequiresFeature(const char *);
#ifdef HAVE_LUA
strlcat(features, "HAVE_LUA ", sizeof(features));
#endif
+#ifdef HAVE_JA3
+ strlcat(features, "HAVE_JA3 ", sizeof(features));
+#endif
#ifdef HAVE_LUAJIT
strlcat(features, "HAVE_LUAJIT ", sizeof(features));
#endif
*buffer = NULL;
}
+#ifdef HAVE_JA3
+
/**
* \internal
* \brief Resize buffer if it is full.
}
return buffer;
}
+
+#else /* HAVE_JA3 */
+
+/* Stubs for when JA3 is disabled */
+
+int Ja3BufferAppendBuffer(JA3Buffer **buffer1, JA3Buffer **buffer2)
+{
+ return 0;
+}
+
+int Ja3BufferAddValue(JA3Buffer **buffer, uint32_t value)
+{
+ return 0;
+}
+
+char *Ja3GenerateHash(JA3Buffer *buffer)
+{
+ return NULL;
+}
+
+int Ja3IsDisabled(const char *type)
+{
+ return true;
+}
+
+#endif /* HAVE_JA3 */
char *Ja3GenerateHash(JA3Buffer *);
int Ja3IsDisabled(const char *);
+#ifdef HAVE_JA3
InspectionBuffer *Ja3DetectGetHash(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv,
const int list_id);
InspectionBuffer *Ja3DetectGetString(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv,
const int list_id);
-
+#endif /* HAVE_JA3 */
#endif /* SURICATA_UTIL_JA3_H */