/* Copyright (C) 2021 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free * Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * version 2 along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ 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 { 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_template(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 !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.into())?; 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 rs_quic_to_json( tx: *mut std::os::raw::c_void, js: &mut JsonBuilder, ) -> bool { let tx = cast_pointer!(tx, QuicTransaction); log_template(tx, js).is_ok() }