/src/suricata7/rust/src/quic/logger.rs
Line | Count | Source |
1 | | /* Copyright (C) 2021 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | use super::parser::QuicType; |
19 | | use super::quic::QuicTransaction; |
20 | | use crate::jsonbuilder::{JsonBuilder, JsonError}; |
21 | | use digest::Digest; |
22 | | use digest::Update; |
23 | | use md5::Md5; |
24 | | |
25 | 88 | fn quic_tls_extension_name(e: u16) -> Option<String> { |
26 | 88 | match e { |
27 | 2 | 0 => Some("server_name".to_string()), |
28 | 0 | 1 => Some("max_fragment_length".to_string()), |
29 | 0 | 2 => Some("client_certificate_url".to_string()), |
30 | 0 | 3 => Some("trusted_ca_keys".to_string()), |
31 | 0 | 4 => Some("truncated_hmac".to_string()), |
32 | 6 | 5 => Some("status_request".to_string()), |
33 | 0 | 6 => Some("user_mapping".to_string()), |
34 | 0 | 7 => Some("client_authz".to_string()), |
35 | 0 | 8 => Some("server_authz".to_string()), |
36 | 0 | 9 => Some("cert_type".to_string()), |
37 | 8 | 10 => Some("supported_groups".to_string()), |
38 | 6 | 11 => Some("ec_point_formats".to_string()), |
39 | 0 | 12 => Some("srp".to_string()), |
40 | 8 | 13 => Some("signature_algorithms".to_string()), |
41 | 0 | 14 => Some("use_srtp".to_string()), |
42 | 0 | 15 => Some("heartbeat".to_string()), |
43 | 8 | 16 => Some("alpn".to_string()), |
44 | 0 | 17 => Some("status_request_v2".to_string()), |
45 | 6 | 18 => Some("signed_certificate_timestamp".to_string()), |
46 | 0 | 19 => Some("client_certificate_type".to_string()), |
47 | 0 | 20 => Some("server_certificate_type".to_string()), |
48 | 0 | 21 => Some("padding".to_string()), |
49 | 0 | 22 => Some("encrypt_then_mac".to_string()), |
50 | 6 | 23 => Some("extended_master_secret".to_string()), |
51 | 0 | 24 => Some("token_binding".to_string()), |
52 | 0 | 25 => Some("cached_info".to_string()), |
53 | 0 | 26 => Some("tls_lts".to_string()), |
54 | 0 | 27 => Some("compress_certificate".to_string()), |
55 | 0 | 28 => Some("record_size_limit".to_string()), |
56 | 0 | 29 => Some("pwd_protect".to_string()), |
57 | 0 | 30 => Some("pwd_clear".to_string()), |
58 | 0 | 31 => Some("password_salt".to_string()), |
59 | 0 | 32 => Some("ticket_pinning".to_string()), |
60 | 0 | 33 => Some("tls_cert_with_extern_psk".to_string()), |
61 | 0 | 34 => Some("delegated_credentials".to_string()), |
62 | 0 | 35 => Some("session_ticket".to_string()), |
63 | 0 | 36 => Some("tlmsp".to_string()), |
64 | 0 | 37 => Some("tlmsp_proxying".to_string()), |
65 | 0 | 38 => Some("tlmsp_delegate".to_string()), |
66 | 0 | 39 => Some("supported_ekt_ciphers".to_string()), |
67 | 2 | 41 => Some("pre_shared_key".to_string()), |
68 | 0 | 42 => Some("early_data".to_string()), |
69 | 10 | 43 => Some("supported_versions".to_string()), |
70 | 0 | 44 => Some("cookie".to_string()), |
71 | 2 | 45 => Some("psk_key_exchange_modes".to_string()), |
72 | 0 | 47 => Some("certificate_authorities".to_string()), |
73 | 0 | 48 => Some("oid_filters".to_string()), |
74 | 0 | 49 => Some("post_handshake_auth".to_string()), |
75 | 0 | 50 => Some("signature_algorithms_cert".to_string()), |
76 | 10 | 51 => Some("key_share".to_string()), |
77 | 0 | 52 => Some("transparency_info".to_string()), |
78 | 0 | 53 => Some("connection_id_deprecated".to_string()), |
79 | 0 | 54 => Some("connection_id".to_string()), |
80 | 0 | 55 => Some("external_id_hash".to_string()), |
81 | 0 | 56 => Some("external_session_id".to_string()), |
82 | 8 | 57 => Some("quic_transport_parameters".to_string()), |
83 | 0 | 58 => Some("ticket_request".to_string()), |
84 | 0 | 59 => Some("dnssec_chain".to_string()), |
85 | 0 | 13172 => Some("next_protocol_negotiation".to_string()), |
86 | 6 | 65281 => Some("renegotiation_info".to_string()), |
87 | 0 | _ => None, |
88 | | } |
89 | 88 | } |
90 | | |
91 | 1.52k | fn log_template(tx: &QuicTransaction, log_ja4: bool, js: &mut JsonBuilder) -> Result<(), JsonError> { |
92 | 1.52k | js.open_object("quic")?; |
93 | 1.52k | if tx.header.ty != QuicType::Short { |
94 | 1.52k | js.set_string("version", String::from(tx.header.version).as_str())?; |
95 | | |
96 | 1.52k | if let Some(sni) = &tx.sni { |
97 | 197 | js.set_string("sni", &String::from_utf8_lossy(sni))?; |
98 | 1.32k | } |
99 | 1.52k | if let Some(ua) = &tx.ua { |
100 | 195 | js.set_string("ua", &String::from_utf8_lossy(ua))?; |
101 | 1.33k | } |
102 | 0 | } |
103 | 1.52k | if !tx.cyu.is_empty() { |
104 | 195 | js.open_array("cyu")?; |
105 | 390 | for cyu in &tx.cyu { |
106 | 195 | js.start_object()?; |
107 | 195 | js.set_string("hash", &cyu.hash)?; |
108 | 195 | js.set_string("string", &cyu.string)?; |
109 | 195 | js.close()?; |
110 | | } |
111 | 195 | js.close()?; |
112 | 1.33k | } |
113 | | |
114 | 1.52k | if let Some(ja3) = &tx.ja3 { |
115 | 10 | if tx.client { |
116 | 8 | js.open_object("ja3")?; |
117 | | } else { |
118 | 2 | js.open_object("ja3s")?; |
119 | | } |
120 | 10 | let hash = format!("{:x}", Md5::new().chain(ja3).finalize()); |
121 | 10 | js.set_string("hash", &hash)?; |
122 | 10 | js.set_string("string", ja3)?; |
123 | 10 | js.close()?; |
124 | 1.51k | } |
125 | | |
126 | 1.52k | if log_ja4 { |
127 | 0 | if let Some(ref ja4) = &tx.ja4 { |
128 | 0 | js.set_string("ja4", ja4)?; |
129 | 0 | } |
130 | 1.52k | } |
131 | | |
132 | 1.52k | if !tx.extv.is_empty() { |
133 | 10 | js.open_array("extensions")?; |
134 | 98 | for e in &tx.extv { |
135 | 88 | js.start_object()?; |
136 | 88 | let etype = u16::from(e.etype); |
137 | 88 | if let Some(s) = quic_tls_extension_name(etype) { |
138 | 88 | js.set_string("name", &s)?; |
139 | 0 | } |
140 | 88 | js.set_uint("type", etype.into())?; |
141 | | |
142 | 88 | if !e.values.is_empty() { |
143 | 28 | js.open_array("values")?; |
144 | 106 | for i in 0..e.values.len() { |
145 | 106 | js.append_string(&String::from_utf8_lossy(&e.values[i]))?; |
146 | | } |
147 | 28 | js.close()?; |
148 | 60 | } |
149 | 88 | js.close()?; |
150 | | } |
151 | 10 | js.close()?; |
152 | 1.51k | } |
153 | | |
154 | 1.52k | js.close()?; |
155 | 1.52k | Ok(()) |
156 | 1.52k | } |
157 | | |
158 | | #[no_mangle] |
159 | 1.52k | pub unsafe extern "C" fn rs_quic_to_json( |
160 | 1.52k | tx: *mut std::os::raw::c_void, log_ja4: bool, js: &mut JsonBuilder, |
161 | 1.52k | ) -> bool { |
162 | 1.52k | let tx = cast_pointer!(tx, QuicTransaction); |
163 | 1.52k | log_template(tx, log_ja4, js).is_ok() |
164 | 1.52k | } |