rama_net/tls/client/
mod.rs1mod hello;
12#[doc(inline)]
13pub use hello::{ClientHello, ClientHelloExtension, ECHClientHello};
14
15mod parser;
16pub use parser::parse_client_hello;
17
18mod config;
19#[doc(inline)]
20pub use config::{
21 ClientAuth, ClientAuthData, ClientConfig, ClientConfigChain, ProxyClientConfig,
22 ServerVerifyMode, append_all_client_configs_to_ctx, append_client_config_to_ctx,
23 extract_client_config_from_ctx,
24};
25
26use super::{ApplicationProtocol, DataEncoding, ProtocolVersion};
27
28#[derive(Debug, Clone)]
29pub struct NegotiatedTlsParameters {
32 pub protocol_version: ProtocolVersion,
36 pub application_layer_protocol: Option<ApplicationProtocol>,
42 pub peer_certificate_chain: Option<DataEncoding>,
44}
45
46pub fn merge_client_hello_lists(
49 a: impl AsRef<[ClientHelloExtension]>,
50 b: impl AsRef<[ClientHelloExtension]>,
51) -> Vec<ClientHelloExtension> {
52 let a = a.as_ref();
53 let b = b.as_ref();
54
55 let mut output = Vec::with_capacity(a.len() + b.len());
56
57 output.extend(a.iter().cloned());
58
59 for ext in b.iter().cloned() {
60 match output.iter_mut().find(|e| e.id() == ext.id()) {
61 Some(old) => {
62 *old = ext;
63 }
64 None => output.push(ext),
65 }
66 }
67
68 output
69}
70
71#[cfg(test)]
72mod tests {
73 use crate::address::{Domain, Host};
74
75 use super::*;
76
77 #[test]
78 fn test_merge_client_hello_lists_empty() {
79 assert!(merge_client_hello_lists(vec![], vec![]).is_empty());
80 }
81
82 #[test]
83 fn test_merge_client_hello_lists_zero_one() {
84 let output = merge_client_hello_lists(&[], [ClientHelloExtension::ServerName(None)]);
85 assert_eq!(1, output.len());
86 assert!(matches!(output[0], ClientHelloExtension::ServerName(_)))
87 }
88
89 #[test]
90 fn test_merge_client_hello_lists_one_zero() {
91 let output = merge_client_hello_lists(vec![ClientHelloExtension::ServerName(None)], &[]);
92 assert_eq!(1, output.len());
93 assert!(matches!(output[0], ClientHelloExtension::ServerName(_)))
94 }
95
96 #[test]
97 fn test_merge_client_hello_lists_one_one() {
98 let output = merge_client_hello_lists(
99 vec![ClientHelloExtension::ServerName(None)],
100 &[ClientHelloExtension::SupportedVersions(vec![])],
101 );
102 assert_eq!(2, output.len());
103 assert!(matches!(output[0], ClientHelloExtension::ServerName(_)));
104 assert!(matches!(
105 output[1],
106 ClientHelloExtension::SupportedVersions(_)
107 ));
108 }
109
110 #[test]
111 fn test_merge_client_hello_lists_two_two_with_one_conflict() {
112 let output = merge_client_hello_lists(
113 vec![
114 ClientHelloExtension::ServerName(None),
115 ClientHelloExtension::SupportedVersions(vec![]),
116 ],
117 &[
118 ClientHelloExtension::ServerName(Some(Host::Name(Domain::from_static(
119 "example.com",
120 )))),
121 ClientHelloExtension::ApplicationLayerProtocolNegotiation(vec![]),
122 ],
123 );
124 assert_eq!(3, output.len());
125 assert!(matches!(output[0], ClientHelloExtension::ServerName(_)));
126 assert!(matches!(
127 output[1],
128 ClientHelloExtension::SupportedVersions(_)
129 ));
130 assert!(matches!(
131 output[2],
132 ClientHelloExtension::ApplicationLayerProtocolNegotiation(_)
133 ));
134 }
135}