xref: /tonic/tonic/src/transport/server/service/tls.rs (revision 77cee9c5)
1 use std::{fmt, sync::Arc};
2 
3 use tokio::io::{AsyncRead, AsyncWrite};
4 use tokio_rustls::{
5     rustls::{server::WebPkiClientVerifier, RootCertStore, ServerConfig},
6     server::TlsStream,
7     TlsAcceptor as RustlsAcceptor,
8 };
9 
10 use crate::transport::{
11     service::tls::{convert_certificate_to_pki_types, convert_identity_to_pki_types, ALPN_H2},
12     Certificate, Identity,
13 };
14 
15 #[derive(Clone)]
16 pub(crate) struct TlsAcceptor {
17     inner: Arc<ServerConfig>,
18 }
19 
20 impl TlsAcceptor {
new( identity: &Identity, client_ca_root: Option<&Certificate>, client_auth_optional: bool, ignore_client_order: bool, use_key_log: bool, ) -> Result<Self, crate::BoxError>21     pub(crate) fn new(
22         identity: &Identity,
23         client_ca_root: Option<&Certificate>,
24         client_auth_optional: bool,
25         ignore_client_order: bool,
26         use_key_log: bool,
27     ) -> Result<Self, crate::BoxError> {
28         let builder = ServerConfig::builder();
29 
30         let builder = match client_ca_root {
31             None => builder.with_no_client_auth(),
32             Some(cert) => {
33                 let mut roots = RootCertStore::empty();
34                 roots.add_parsable_certificates(convert_certificate_to_pki_types(cert)?);
35                 let verifier = if client_auth_optional {
36                     WebPkiClientVerifier::builder(roots.into()).allow_unauthenticated()
37                 } else {
38                     WebPkiClientVerifier::builder(roots.into())
39                 }
40                 .build()?;
41                 builder.with_client_cert_verifier(verifier)
42             }
43         };
44 
45         let (cert, key) = convert_identity_to_pki_types(identity)?;
46         let mut config = builder.with_single_cert(cert, key)?;
47         config.ignore_client_order = ignore_client_order;
48 
49         if use_key_log {
50             config.key_log = Arc::new(tokio_rustls::rustls::KeyLogFile::new());
51         }
52 
53         config.alpn_protocols.push(ALPN_H2.into());
54         Ok(Self {
55             inner: Arc::new(config),
56         })
57     }
58 
accept<IO>(&self, io: IO) -> Result<TlsStream<IO>, crate::BoxError> where IO: AsyncRead + AsyncWrite + Unpin,59     pub(crate) async fn accept<IO>(&self, io: IO) -> Result<TlsStream<IO>, crate::BoxError>
60     where
61         IO: AsyncRead + AsyncWrite + Unpin,
62     {
63         let acceptor = RustlsAcceptor::from(self.inner.clone());
64         acceptor.accept(io).await.map_err(Into::into)
65     }
66 }
67 
68 impl fmt::Debug for TlsAcceptor {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result69     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70         f.debug_struct("TlsAcceptor").finish()
71     }
72 }
73