use super::parser::QuicType;
use super::quic::QuicTransaction;
use crate::jsonbuilder::{JsonBuilder, JsonError};
use digest::Digest;
use digest::Update;
use md5::Md5;
fn quic_tls_extension_name(e: u16) -> Option<String> {
match e {
0 => Some("server_name".to_string()),
1 => Some("max_fragment_length".to_string()),
2 => Some("client_certificate_url".to_string()),
3 => Some("trusted_ca_keys".to_string()),
4 => Some("truncated_hmac".to_string()),
5 => Some("status_request".to_string()),
6 => Some("user_mapping".to_string()),
7 => Some("client_authz".to_string()),
8 => Some("server_authz".to_string()),
9 => Some("cert_type".to_string()),
10 => Some("supported_groups".to_string()),
11 => Some("ec_point_formats".to_string()),
12 => Some("srp".to_string()),
13 => Some("signature_algorithms".to_string()),
14 => Some("use_srtp".to_string()),
15 => Some("heartbeat".to_string()),
16 => Some("alpn".to_string()),
17 => Some("status_request_v2".to_string()),
18 => Some("signed_certificate_timestamp".to_string()),
19 => Some("client_certificate_type".to_string()),
20 => Some("server_certificate_type".to_string()),
21 => Some("padding".to_string()),
22 => Some("encrypt_then_mac".to_string()),
23 => Some("extended_master_secret".to_string()),
24 => Some("token_binding".to_string()),
25 => Some("cached_info".to_string()),
26 => Some("tls_lts".to_string()),
27 => Some("compress_certificate".to_string()),
28 => Some("record_size_limit".to_string()),
29 => Some("pwd_protect".to_string()),
30 => Some("pwd_clear".to_string()),
31 => Some("password_salt".to_string()),
32 => Some("ticket_pinning".to_string()),
33 => Some("tls_cert_with_extern_psk".to_string()),
34 => Some("delegated_credentials".to_string()),
35 => Some("session_ticket".to_string()),
36 => Some("tlmsp".to_string()),
37 => Some("tlmsp_proxying".to_string()),
38 => Some("tlmsp_delegate".to_string()),
39 => Some("supported_ekt_ciphers".to_string()),
41 => Some("pre_shared_key".to_string()),
42 => Some("early_data".to_string()),
43 => Some("supported_versions".to_string()),
44 => Some("cookie".to_string()),
45 => Some("psk_key_exchange_modes".to_string()),
47 => Some("certificate_authorities".to_string()),
48 => Some("oid_filters".to_string()),
49 => Some("post_handshake_auth".to_string()),
50 => Some("signature_algorithms_cert".to_string()),
51 => Some("key_share".to_string()),
52 => Some("transparency_info".to_string()),
53 => Some("connection_id_deprecated".to_string()),
54 => Some("connection_id".to_string()),
55 => Some("external_id_hash".to_string()),
56 => Some("external_session_id".to_string()),
57 => Some("quic_transport_parameters".to_string()),
58 => Some("ticket_request".to_string()),
59 => Some("dnssec_chain".to_string()),
13172 => Some("next_protocol_negotiation".to_string()),
65281 => Some("renegotiation_info".to_string()),
_ => None,
}
}
fn log_quic(tx: &QuicTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> {
js.open_object("quic")?;
if tx.header.ty != QuicType::Short {
js.set_string("version", String::from(tx.header.version).as_str())?;
if let Some(sni) = &tx.sni {
js.set_string("sni", &String::from_utf8_lossy(sni))?;
}
if let Some(ua) = &tx.ua {
js.set_string("ua", &String::from_utf8_lossy(ua))?;
}
}
if !tx.cyu.is_empty() {
js.open_array("cyu")?;
for cyu in &tx.cyu {
js.start_object()?;
js.set_string("hash", &cyu.hash)?;
js.set_string("string", &cyu.string)?;
js.close()?;
}
js.close()?;
}
if let Some(ja3) = &tx.ja3 {
if tx.client {
js.open_object("ja3")?;
} else {
js.open_object("ja3s")?;
}
let hash = format!("{:x}", Md5::new().chain(ja3).finalize());
js.set_string("hash", &hash)?;
js.set_string("string", ja3)?;
js.close()?;
}
if let Some(ref ja4) = &tx.ja4 {
js.set_string("ja4", ja4.as_ref())?;
}
if !tx.extv.is_empty() {
js.open_array("extensions")?;
for e in &tx.extv {
js.start_object()?;
let etype = u16::from(e.etype);
if let Some(s) = quic_tls_extension_name(etype) {
js.set_string("name", &s)?;
}
js.set_uint("type", etype)?;
if !e.values.is_empty() {
js.open_array("values")?;
for i in 0..e.values.len() {
js.append_string(&String::from_utf8_lossy(&e.values[i]))?;
}
js.close()?;
}
js.close()?;
}
js.close()?;
}
js.close()?;
Ok(())
}
#[no_mangle]
pub unsafe extern "C" fn SCQuicLogJson(
tx: *mut std::os::raw::c_void, js: &mut JsonBuilder,
) -> bool {
let tx = cast_pointer!(tx, QuicTransaction);
log_quic(tx, js).is_ok()
}