1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
use std::io;
use std::borrow::Cow;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio_util::either::Either;
use super::Endpoint;
/// A collection of raw certificate data.
#[derive(Clone)]
pub struct Certificates<'r>(Cow<'r, [der::CertificateDer<'r>]>);
pub trait Connection: AsyncRead + AsyncWrite + Send + Unpin {
fn endpoint(&self) -> io::Result<Endpoint>;
/// DER-encoded X.509 certificate chain presented by the client, if any.
///
/// The certificate order must be as it appears in the TLS protocol: the
/// first certificate relates to the peer, the second certifies the first,
/// the third certifies the second, and so on.
///
/// Defaults to an empty vector to indicate that no certificates were
/// presented.
fn certificates(&self) -> Option<Certificates<'_>> { None }
}
impl<A: Connection, B: Connection> Connection for Either<A, B> {
fn endpoint(&self) -> io::Result<Endpoint> {
match self {
Either::Left(c) => c.endpoint(),
Either::Right(c) => c.endpoint(),
}
}
fn certificates(&self) -> Option<Certificates<'_>> {
match self {
Either::Left(c) => c.certificates(),
Either::Right(c) => c.certificates(),
}
}
}
impl Certificates<'_> {
pub fn into_owned(self) -> Certificates<'static> {
let cow = self.0.iter()
.map(|der| der.clone().into_owned())
.collect::<Vec<_>>()
.into();
Certificates(cow)
}
}
#[cfg(feature = "mtls")]
#[cfg_attr(nightly, doc(cfg(feature = "mtls")))]
mod der {
use super::*;
pub use crate::mtls::CertificateDer;
impl<'r> Certificates<'r> {
pub(crate) fn inner(&self) -> &[CertificateDer<'r>] {
&self.0
}
}
impl<'r> From<&'r [CertificateDer<'r>]> for Certificates<'r> {
fn from(value: &'r [CertificateDer<'r>]) -> Self {
Certificates(value.into())
}
}
impl From<Vec<CertificateDer<'static>>> for Certificates<'static> {
fn from(value: Vec<CertificateDer<'static>>) -> Self {
Certificates(value.into())
}
}
}
#[cfg(not(feature = "mtls"))]
mod der {
use std::marker::PhantomData;
/// A thin wrapper over raw, DER-encoded X.509 client certificate data.
#[derive(Clone)]
pub struct CertificateDer<'r>(PhantomData<&'r [u8]>);
impl CertificateDer<'_> {
pub fn into_owned(self) -> CertificateDer<'static> {
CertificateDer(PhantomData)
}
}
}