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)
        }
    }
}