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
use futures_lite::io::{AsyncRead, AsyncWrite};
use openssl::ssl;
use std::fmt;
use std::path::Path;
use std::sync::Arc;

use super::async_to_sync_wrapper::AsyncToSyncWrapper;
use super::certificate::{Certificate, PrivateKey};
use super::error::Result;
use super::handshake::HandshakeFuture;
use super::stream::TlsStream;

#[derive(Clone)]
pub struct TlsAcceptor(pub Arc<ssl::SslAcceptor>);

impl TlsAcceptor {
    pub fn builder() -> Result<TlsAcceptorBuilder> {
        let inner =
            openssl::ssl::SslAcceptor::mozilla_intermediate_v5(openssl::ssl::SslMethod::tls())?;

        Ok(TlsAcceptorBuilder { inner })
    }

    pub async fn accept<S>(&self, stream: S) -> Result<TlsStream<S>>
    where
        S: AsyncRead + AsyncWrite + Unpin + fmt::Debug + Send + Sync + 'static,
    {
        HandshakeFuture::Initial(
            move |stream| self.0.accept(stream),
            AsyncToSyncWrapper::new(stream),
        )
        .await
    }
}

pub struct TlsAcceptorBuilder {
    pub inner: ssl::SslAcceptorBuilder,
}

impl TlsAcceptorBuilder {
    pub fn with_certifiate_and_key_from_pem_files<P: AsRef<Path>>(
        mut self,
        cert_file: P,
        key_file: P,
    ) -> Result<TlsAcceptorBuilder> {
        self.inner
            .set_certificate_file(cert_file, ssl::SslFiletype::PEM)?;
        self.inner
            .set_private_key_file(key_file, ssl::SslFiletype::PEM)?;
        Ok(self)
    }

    pub fn with_certifiate_and_key(
        mut self,
        cert: Certificate,
        key: PrivateKey,
    ) -> Result<TlsAcceptorBuilder> {
        self.inner.set_certificate(&cert.0)?;
        self.inner.set_private_key(&key.0)?;
        Ok(self)
    }

    pub fn with_chain(mut self, chain: Vec<Certificate>) -> Result<TlsAcceptorBuilder> {
        for cert in chain {
            self.inner.add_extra_chain_cert(cert.0)?;
        }
        Ok(self)
    }

    pub fn with_ca_from_pem_file<P: AsRef<Path>>(
        mut self,
        ca_file: P,
    ) -> Result<TlsAcceptorBuilder> {
        self.inner.set_ca_file(ca_file)?;
        Ok(self)
    }

    pub fn with_ssl_verify_mode(mut self, mode: ssl::SslVerifyMode) -> TlsAcceptorBuilder {
        self.inner.set_verify(mode);
        self
    }

    pub fn build(self) -> TlsAcceptor {
        TlsAcceptor(Arc::new(self.inner.build()))
    }
}