mod hello;
#[doc(inline)]
pub use hello::{ClientHello, ClientHelloExtension, ECHClientHello};
mod parser;
pub use parser::{
extract_sni_from_client_hello_handshake, extract_sni_from_client_hello_record,
parse_client_hello, parse_client_hello_handshake,
};
mod config;
#[doc(inline)]
pub use config::{
ClientAuth, ClientAuthData, ServerVerifyMode, TlsClientAuth, TlsClientConfig, TlsServerName,
TlsServerVerify, TlsStoreServerCertChain,
};
use rama_crypto::pki_types::CertificateDer;
use super::{ApplicationProtocol, ProtocolVersion};
use rama_core::extensions::Extension;
#[derive(Debug, Clone, Extension)]
#[extension(tags(tls))]
pub struct NegotiatedTlsParameters {
pub protocol_version: ProtocolVersion,
pub application_layer_protocol: Option<ApplicationProtocol>,
pub peer_certificate_chain: Option<Vec<CertificateDer<'static>>>,
}
pub fn merge_client_hello_lists(
a: impl AsRef<[ClientHelloExtension]>,
b: impl AsRef<[ClientHelloExtension]>,
) -> Vec<ClientHelloExtension> {
let a = a.as_ref();
let b = b.as_ref();
let mut output = Vec::with_capacity(a.len() + b.len());
output.extend(a.iter().cloned());
for ext in b.iter().cloned() {
match output.iter_mut().find(|e| e.id() == ext.id()) {
Some(old) => {
*old = ext;
}
None => output.push(ext),
}
}
output
}
#[cfg(test)]
mod tests {
use rama_net::address::Domain;
use super::*;
#[test]
fn test_merge_client_hello_lists_empty() {
assert!(merge_client_hello_lists(vec![], vec![]).is_empty());
}
#[test]
fn test_merge_client_hello_lists_zero_one() {
let output = merge_client_hello_lists(&[], [ClientHelloExtension::ServerName(None)]);
assert_eq!(1, output.len());
assert!(matches!(output[0], ClientHelloExtension::ServerName(_)))
}
#[test]
fn test_merge_client_hello_lists_one_zero() {
let output = merge_client_hello_lists(vec![ClientHelloExtension::ServerName(None)], &[]);
assert_eq!(1, output.len());
assert!(matches!(output[0], ClientHelloExtension::ServerName(_)))
}
#[test]
fn test_merge_client_hello_lists_one_one() {
let output = merge_client_hello_lists(
vec![ClientHelloExtension::ServerName(None)],
&[ClientHelloExtension::SupportedVersions(vec![])],
);
assert_eq!(2, output.len());
assert!(matches!(output[0], ClientHelloExtension::ServerName(_)));
assert!(matches!(
output[1],
ClientHelloExtension::SupportedVersions(_)
));
}
#[test]
fn test_merge_client_hello_lists_two_two_with_one_conflict() {
let output = merge_client_hello_lists(
vec![
ClientHelloExtension::ServerName(None),
ClientHelloExtension::SupportedVersions(vec![]),
],
&[
ClientHelloExtension::ServerName(Some(Domain::from_static("example.com"))),
ClientHelloExtension::ApplicationLayerProtocolNegotiation(vec![]),
],
);
assert_eq!(3, output.len());
assert!(matches!(output[0], ClientHelloExtension::ServerName(_)));
assert!(matches!(
output[1],
ClientHelloExtension::SupportedVersions(_)
));
assert!(matches!(
output[2],
ClientHelloExtension::ApplicationLayerProtocolNegotiation(_)
));
}
}