Skip to content

Commit

Permalink
feat: add event.client.tlsJA3MD5
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeChampion committed Jul 7, 2023
1 parent cf93b62 commit 2ecf4af
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 0 deletions.
20 changes: 20 additions & 0 deletions runtime/js-compute-runtime/builtins/client-info.cpp
@@ -1,6 +1,7 @@
#include "builtins/client-info.h"
#include "core/geo_ip.h"
#include "host_interface/host_api.h"
#include "openssl/evp.h"

#include "js/JSON.h"
#include <arpa/inet.h>
Expand Down Expand Up @@ -126,6 +127,24 @@ bool ClientInfo::tls_cipher_openssl_name_get(JSContext *cx, unsigned argc, JS::V
return true;
}

bool ClientInfo::tls_ja3_md5_get(JSContext *cx, unsigned argc, JS::Value *vp) {
METHOD_HEADER(0);

auto res = HttpReq::http_req_downstream_tls_ja3_md5();
if (auto *err = res.to_err()) {
HANDLE_ERROR(cx, *err);
return false;
}

auto ja3 = std::move(res.unwrap());
JS::UniqueChars hex{OPENSSL_buf2hexstr(ja3.ptr.get(), ja3.len)};
std::string ja3hex{hex.get(), std::remove(hex.get(), hex.get() + strlen(hex.get()), ':')};

JS::RootedString s(cx, JS_NewStringCopyN(cx, ja3hex.c_str(), ja3hex.length()));
args.rval().setString(s);
return true;
}

bool ClientInfo::tls_client_hello_get(JSContext *cx, unsigned argc, JS::Value *vp) {
METHOD_HEADER(0);

Expand Down Expand Up @@ -207,6 +226,7 @@ const JSPropertySpec ClientInfo::properties[] = {
JS_PSG("geo", geo_get, JSPROP_ENUMERATE),
JS_PSG("tlsCipherOpensslName", tls_cipher_openssl_name_get, JSPROP_ENUMERATE),
JS_PSG("tlsProtocol", tls_protocol_get, JSPROP_ENUMERATE),
JS_PSG("tlsJA3MD5", tls_ja3_md5_get, JSPROP_ENUMERATE),
JS_PSG("tlsClientCertificate", tls_client_certificate_get, JSPROP_ENUMERATE),
JS_PSG("tlsClientHello", tls_client_hello_get, JSPROP_ENUMERATE),
JS_PS_END,
Expand Down
1 change: 1 addition & 0 deletions runtime/js-compute-runtime/builtins/client-info.h
Expand Up @@ -11,6 +11,7 @@ class ClientInfo final : public BuiltinNoConstructor<ClientInfo> {
static bool tls_cipher_openssl_name_get(JSContext *cx, unsigned argc, JS::Value *vp);
static bool tls_protocol_get(JSContext *cx, unsigned argc, JS::Value *vp);
static bool tls_client_hello_get(JSContext *cx, unsigned argc, JS::Value *vp);
static bool tls_ja3_md5_get(JSContext *cx, unsigned argc, JS::Value *vp);
static bool tls_client_certificate_get(JSContext *cx, unsigned argc, JS::Value *vp);

public:
Expand Down
Expand Up @@ -211,6 +211,12 @@ bool fastly_http_req_downstream_tls_raw_client_certificate(fastly_world_list_u8_
}
return convert_result(status, err);
}

bool fastly_http_req_downstream_tls_ja3_md5(fastly_world_list_u8_t *ret, fastly_error_t *err) {
ret->ptr = static_cast<uint8_t *>(cabi_malloc(16, 1));
return convert_result(
fastly::req_downstream_tls_ja3_md5(reinterpret_cast<char *>(ret->ptr), &ret->len), err);
}
bool fastly_http_req_downstream_tls_client_hello(fastly_world_list_u8_t *ret, fastly_error_t *err) {
auto default_size = 512;
ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));
Expand Down
4 changes: 4 additions & 0 deletions runtime/js-compute-runtime/host_interface/fastly.h
Expand Up @@ -160,6 +160,10 @@ int req_downstream_tls_client_hello(char *ret, size_t ret_len, size_t *nwritten)

WASM_IMPORT("fastly_http_req", "downstream_tls_raw_client_certificate")
int req_downstream_tls_raw_client_certificate(char *ret, size_t ret_len, size_t *nwritten);

WASM_IMPORT("fastly_http_req", "downstream_tls_ja3_md5")
int req_downstream_tls_ja3_md5(char *ret, size_t *nwritten);

WASM_IMPORT("fastly_http_req", "new")
int req_new(fastly_request_handle_t *req_handle_out);

Expand Down
16 changes: 16 additions & 0 deletions runtime/js-compute-runtime/host_interface/host_api.cpp
Expand Up @@ -561,6 +561,22 @@ Result<HostBytes> HttpReq::http_req_downstream_tls_raw_client_certificate() {

return res;
}

// http-req-downstream-tls-ja3-md5: func() -> result<list<u8>, error>
Result<HostBytes> HttpReq::http_req_downstream_tls_ja3_md5() {
Result<HostBytes> res;

fastly_world_list_u8_t ret;
fastly_error_t err;
if (!fastly_http_req_downstream_tls_ja3_md5(&ret, &err)) {
res.emplace_err(err);
} else {
res.emplace(ret);
}

return res;
}

bool HttpReq::is_valid() const { return this->handle != HttpReq::invalid; }

Result<fastly_http_version_t> HttpReq::get_version() const {
Expand Down
2 changes: 2 additions & 0 deletions runtime/js-compute-runtime/host_interface/host_api.h
Expand Up @@ -263,6 +263,8 @@ class HttpReq final : public HttpBase {

static Result<HostBytes> http_req_downstream_tls_raw_client_certificate();

static Result<HostBytes> http_req_downstream_tls_ja3_md5();

/// Send this request synchronously, and wait for the response.
Result<Response> send(HttpBody body, std::string_view backend);

Expand Down

0 comments on commit 2ecf4af

Please sign in to comment.