Skip to content

Commit 2ecf4af

Browse files
Jake ChampionJakeChampion
authored andcommitted
feat: add event.client.tlsJA3MD5
1 parent cf93b62 commit 2ecf4af

File tree

6 files changed

+49
-0
lines changed

6 files changed

+49
-0
lines changed

runtime/js-compute-runtime/builtins/client-info.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "builtins/client-info.h"
22
#include "core/geo_ip.h"
33
#include "host_interface/host_api.h"
4+
#include "openssl/evp.h"
45

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

130+
bool ClientInfo::tls_ja3_md5_get(JSContext *cx, unsigned argc, JS::Value *vp) {
131+
METHOD_HEADER(0);
132+
133+
auto res = HttpReq::http_req_downstream_tls_ja3_md5();
134+
if (auto *err = res.to_err()) {
135+
HANDLE_ERROR(cx, *err);
136+
return false;
137+
}
138+
139+
auto ja3 = std::move(res.unwrap());
140+
JS::UniqueChars hex{OPENSSL_buf2hexstr(ja3.ptr.get(), ja3.len)};
141+
std::string ja3hex{hex.get(), std::remove(hex.get(), hex.get() + strlen(hex.get()), ':')};
142+
143+
JS::RootedString s(cx, JS_NewStringCopyN(cx, ja3hex.c_str(), ja3hex.length()));
144+
args.rval().setString(s);
145+
return true;
146+
}
147+
129148
bool ClientInfo::tls_client_hello_get(JSContext *cx, unsigned argc, JS::Value *vp) {
130149
METHOD_HEADER(0);
131150

@@ -207,6 +226,7 @@ const JSPropertySpec ClientInfo::properties[] = {
207226
JS_PSG("geo", geo_get, JSPROP_ENUMERATE),
208227
JS_PSG("tlsCipherOpensslName", tls_cipher_openssl_name_get, JSPROP_ENUMERATE),
209228
JS_PSG("tlsProtocol", tls_protocol_get, JSPROP_ENUMERATE),
229+
JS_PSG("tlsJA3MD5", tls_ja3_md5_get, JSPROP_ENUMERATE),
210230
JS_PSG("tlsClientCertificate", tls_client_certificate_get, JSPROP_ENUMERATE),
211231
JS_PSG("tlsClientHello", tls_client_hello_get, JSPROP_ENUMERATE),
212232
JS_PS_END,

runtime/js-compute-runtime/builtins/client-info.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class ClientInfo final : public BuiltinNoConstructor<ClientInfo> {
1111
static bool tls_cipher_openssl_name_get(JSContext *cx, unsigned argc, JS::Value *vp);
1212
static bool tls_protocol_get(JSContext *cx, unsigned argc, JS::Value *vp);
1313
static bool tls_client_hello_get(JSContext *cx, unsigned argc, JS::Value *vp);
14+
static bool tls_ja3_md5_get(JSContext *cx, unsigned argc, JS::Value *vp);
1415
static bool tls_client_certificate_get(JSContext *cx, unsigned argc, JS::Value *vp);
1516

1617
public:

runtime/js-compute-runtime/fastly-world/fastly_world_adapter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,12 @@ bool fastly_http_req_downstream_tls_raw_client_certificate(fastly_world_list_u8_
211211
}
212212
return convert_result(status, err);
213213
}
214+
215+
bool fastly_http_req_downstream_tls_ja3_md5(fastly_world_list_u8_t *ret, fastly_error_t *err) {
216+
ret->ptr = static_cast<uint8_t *>(cabi_malloc(16, 1));
217+
return convert_result(
218+
fastly::req_downstream_tls_ja3_md5(reinterpret_cast<char *>(ret->ptr), &ret->len), err);
219+
}
214220
bool fastly_http_req_downstream_tls_client_hello(fastly_world_list_u8_t *ret, fastly_error_t *err) {
215221
auto default_size = 512;
216222
ret->ptr = static_cast<uint8_t *>(cabi_malloc(default_size, 4));

runtime/js-compute-runtime/host_interface/fastly.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ int req_downstream_tls_client_hello(char *ret, size_t ret_len, size_t *nwritten)
160160

161161
WASM_IMPORT("fastly_http_req", "downstream_tls_raw_client_certificate")
162162
int req_downstream_tls_raw_client_certificate(char *ret, size_t ret_len, size_t *nwritten);
163+
164+
WASM_IMPORT("fastly_http_req", "downstream_tls_ja3_md5")
165+
int req_downstream_tls_ja3_md5(char *ret, size_t *nwritten);
166+
163167
WASM_IMPORT("fastly_http_req", "new")
164168
int req_new(fastly_request_handle_t *req_handle_out);
165169

runtime/js-compute-runtime/host_interface/host_api.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,22 @@ Result<HostBytes> HttpReq::http_req_downstream_tls_raw_client_certificate() {
561561

562562
return res;
563563
}
564+
565+
// http-req-downstream-tls-ja3-md5: func() -> result<list<u8>, error>
566+
Result<HostBytes> HttpReq::http_req_downstream_tls_ja3_md5() {
567+
Result<HostBytes> res;
568+
569+
fastly_world_list_u8_t ret;
570+
fastly_error_t err;
571+
if (!fastly_http_req_downstream_tls_ja3_md5(&ret, &err)) {
572+
res.emplace_err(err);
573+
} else {
574+
res.emplace(ret);
575+
}
576+
577+
return res;
578+
}
579+
564580
bool HttpReq::is_valid() const { return this->handle != HttpReq::invalid; }
565581

566582
Result<fastly_http_version_t> HttpReq::get_version() const {

runtime/js-compute-runtime/host_interface/host_api.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ class HttpReq final : public HttpBase {
263263

264264
static Result<HostBytes> http_req_downstream_tls_raw_client_certificate();
265265

266+
static Result<HostBytes> http_req_downstream_tls_ja3_md5();
267+
266268
/// Send this request synchronously, and wait for the response.
267269
Result<Response> send(HttpBody body, std::string_view backend);
268270

0 commit comments

Comments
 (0)