#[cfg(any(feature = "boring", feature = "rustls-tls"))]
use bytes::Bytes;
use tokio::net::TcpStream;
#[cfg(unix)]
use tokio::net::UnixStream;
#[cfg(feature = "boring")]
use tokio_boring::SslStream;
#[cfg(feature = "rustls-tls")]
use tokio_rustls::client::TlsStream;
use crate::tls::{TlsInfo, conn::MaybeHttpsStream};
pub trait TlsInfoFactory {
fn tls_info(&self) -> Option<TlsInfo>;
}
#[cfg(feature = "boring")]
fn extract_tls_info<S>(ssl_stream: &SslStream<S>) -> TlsInfo {
let ssl = ssl_stream.ssl();
TlsInfo {
peer_certificate: ssl
.peer_certificate()
.and_then(|cert| cert.to_der().ok())
.map(Bytes::from),
peer_certificate_chain: ssl.peer_cert_chain().map(|chain| {
chain
.iter()
.filter_map(|cert| cert.to_der().ok())
.map(Bytes::from)
.collect()
}),
}
}
impl TlsInfoFactory for TcpStream {
fn tls_info(&self) -> Option<TlsInfo> {
None
}
}
#[cfg(feature = "boring")]
impl TlsInfoFactory for SslStream<TcpStream> {
#[inline]
fn tls_info(&self) -> Option<TlsInfo> {
Some(extract_tls_info(self))
}
}
#[cfg(feature = "rustls-tls")]
impl TlsInfoFactory for TlsStream<TcpStream> {
#[inline]
fn tls_info(&self) -> Option<TlsInfo> {
self.get_ref().1.peer_certificates().map(|certs| TlsInfo {
peer_certificate: certs.first().map(|c| Bytes::from(c.to_vec())),
peer_certificate_chain: Some(certs.iter().map(|c| Bytes::from(c.to_vec())).collect()),
})
}
}
impl TlsInfoFactory for MaybeHttpsStream<TcpStream> {
fn tls_info(&self) -> Option<TlsInfo> {
match self {
MaybeHttpsStream::Https(tls) => tls.tls_info(),
MaybeHttpsStream::Http(_) => None,
}
}
}
#[cfg(feature = "boring")]
impl TlsInfoFactory for SslStream<MaybeHttpsStream<TcpStream>> {
#[inline]
fn tls_info(&self) -> Option<TlsInfo> {
Some(extract_tls_info(self))
}
}
#[cfg(feature = "rustls-tls")]
impl TlsInfoFactory for TlsStream<MaybeHttpsStream<TcpStream>> {
#[inline]
fn tls_info(&self) -> Option<TlsInfo> {
self.get_ref().1.peer_certificates().map(|certs| TlsInfo {
peer_certificate: certs.first().map(|c| Bytes::from(c.to_vec())),
peer_certificate_chain: Some(certs.iter().map(|c| Bytes::from(c.to_vec())).collect()),
})
}
}
#[cfg(unix)]
impl TlsInfoFactory for UnixStream {
fn tls_info(&self) -> Option<TlsInfo> {
None
}
}
#[cfg(all(unix, feature = "boring"))]
impl TlsInfoFactory for SslStream<UnixStream> {
#[inline]
fn tls_info(&self) -> Option<TlsInfo> {
Some(extract_tls_info(self))
}
}
#[cfg(all(unix, feature = "rustls-tls"))]
impl TlsInfoFactory for TlsStream<UnixStream> {
#[inline]
fn tls_info(&self) -> Option<TlsInfo> {
self.get_ref().1.peer_certificates().map(|certs| TlsInfo {
peer_certificate: certs.first().map(|c| Bytes::from(c.to_vec())),
peer_certificate_chain: Some(certs.iter().map(|c| Bytes::from(c.to_vec())).collect()),
})
}
}
#[cfg(unix)]
impl TlsInfoFactory for MaybeHttpsStream<UnixStream> {
fn tls_info(&self) -> Option<TlsInfo> {
match self {
MaybeHttpsStream::Https(tls) => tls.tls_info(),
MaybeHttpsStream::Http(_) => None,
}
}
}
#[cfg(all(unix, feature = "boring"))]
impl TlsInfoFactory for SslStream<MaybeHttpsStream<UnixStream>> {
#[inline]
fn tls_info(&self) -> Option<TlsInfo> {
Some(extract_tls_info(self))
}
}
#[cfg(all(unix, feature = "rustls-tls"))]
impl TlsInfoFactory for TlsStream<MaybeHttpsStream<UnixStream>> {
#[inline]
fn tls_info(&self) -> Option<TlsInfo> {
self.get_ref().1.peer_certificates().map(|certs| TlsInfo {
peer_certificate: certs.first().map(|c| Bytes::from(c.to_vec())),
peer_certificate_chain: Some(certs.iter().map(|c| Bytes::from(c.to_vec())).collect()),
})
}
}