feat(tls): upgrade to tokio-rustls 0.23 (rustls 0.20) (#859)
This commit is contained in:
+5
-4
@@ -27,7 +27,7 @@ codegen = ["async-trait"]
|
|||||||
compression = ["flate2"]
|
compression = ["flate2"]
|
||||||
default = ["transport", "codegen", "prost"]
|
default = ["transport", "codegen", "prost"]
|
||||||
prost = ["prost1", "prost-derive"]
|
prost = ["prost1", "prost-derive"]
|
||||||
tls = ["transport", "tokio-rustls"]
|
tls = ["rustls-pemfile", "transport", "tokio-rustls"]
|
||||||
tls-roots = ["tls-roots-common", "rustls-native-certs"]
|
tls-roots = ["tls-roots-common", "rustls-native-certs"]
|
||||||
tls-roots-common = ["tls"]
|
tls-roots-common = ["tls"]
|
||||||
tls-webpki-roots = ["tls-roots-common", "webpki-roots"]
|
tls-webpki-roots = ["tls-roots-common", "webpki-roots"]
|
||||||
@@ -79,9 +79,10 @@ tower = {version = "0.4.7", features = ["balance", "buffer", "discover", "limit"
|
|||||||
tracing-futures = {version = "0.2", optional = true}
|
tracing-futures = {version = "0.2", optional = true}
|
||||||
|
|
||||||
# rustls
|
# rustls
|
||||||
rustls-native-certs = {version = "0.5", optional = true}
|
rustls-pemfile = { version = "0.2.1", optional = true }
|
||||||
tokio-rustls = {version = "0.22", optional = true}
|
rustls-native-certs = { version = "0.6.1", optional = true }
|
||||||
webpki-roots = {version = "0.21.1", optional = true}
|
tokio-rustls = { version = "0.23.1", optional = true }
|
||||||
|
webpki-roots = { version = "0.22.1", optional = true }
|
||||||
|
|
||||||
# compression
|
# compression
|
||||||
flate2 = {version = "1.0", optional = true}
|
flate2 = {version = "1.0", optional = true}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ pub struct ClientTlsConfig {
|
|||||||
domain: Option<String>,
|
domain: Option<String>,
|
||||||
cert: Option<Certificate>,
|
cert: Option<Certificate>,
|
||||||
identity: Option<Identity>,
|
identity: Option<Identity>,
|
||||||
rustls_raw: Option<tokio_rustls::rustls::ClientConfig>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
@@ -36,7 +35,6 @@ impl ClientTlsConfig {
|
|||||||
domain: None,
|
domain: None,
|
||||||
cert: None,
|
cert: None,
|
||||||
identity: None,
|
identity: None,
|
||||||
rustls_raw: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +47,6 @@ impl ClientTlsConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the CA Certificate against which to verify the server's TLS certificate.
|
/// Sets the CA Certificate against which to verify the server's TLS certificate.
|
||||||
///
|
|
||||||
/// This has no effect if `rustls_client_config` is used to configure Rustls.
|
|
||||||
pub fn ca_certificate(self, ca_certificate: Certificate) -> Self {
|
pub fn ca_certificate(self, ca_certificate: Certificate) -> Self {
|
||||||
ClientTlsConfig {
|
ClientTlsConfig {
|
||||||
cert: Some(ca_certificate),
|
cert: Some(ca_certificate),
|
||||||
@@ -59,8 +55,6 @@ impl ClientTlsConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the client identity to present to the server.
|
/// Sets the client identity to present to the server.
|
||||||
///
|
|
||||||
/// This has no effect if `rustls_client_config` is used to configure Rustls.
|
|
||||||
pub fn identity(self, identity: Identity) -> Self {
|
pub fn identity(self, identity: Identity) -> Self {
|
||||||
ClientTlsConfig {
|
ClientTlsConfig {
|
||||||
identity: Some(identity),
|
identity: Some(identity),
|
||||||
@@ -68,26 +62,11 @@ impl ClientTlsConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use options specified by the given `ClientConfig` to configure TLS.
|
|
||||||
///
|
|
||||||
/// This overrides all other TLS options set via other means.
|
|
||||||
pub fn rustls_client_config(self, config: tokio_rustls::rustls::ClientConfig) -> Self {
|
|
||||||
ClientTlsConfig {
|
|
||||||
rustls_raw: Some(config),
|
|
||||||
..self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn tls_connector(&self, uri: Uri) -> Result<TlsConnector, crate::Error> {
|
pub(crate) fn tls_connector(&self, uri: Uri) -> Result<TlsConnector, crate::Error> {
|
||||||
let domain = match &self.domain {
|
let domain = match &self.domain {
|
||||||
None => uri.host().ok_or_else(Error::new_invalid_uri)?.to_string(),
|
None => uri.host().ok_or_else(Error::new_invalid_uri)?.to_string(),
|
||||||
Some(domain) => domain.clone(),
|
Some(domain) => domain.clone(),
|
||||||
};
|
};
|
||||||
match &self.rustls_raw {
|
TlsConnector::new(self.cert.clone(), self.identity.clone(), domain)
|
||||||
None => {
|
|
||||||
TlsConnector::new_with_rustls_cert(self.cert.clone(), self.identity.clone(), domain)
|
|
||||||
}
|
|
||||||
Some(c) => TlsConnector::new_with_rustls_raw(c.clone(), domain),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::transport::Certificate;
|
|||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
use tokio_rustls::{rustls::Session, server::TlsStream};
|
use tokio_rustls::server::TlsStream;
|
||||||
|
|
||||||
/// Trait that connected IO resources implement and use to produce info about the connection.
|
/// Trait that connected IO resources implement and use to produce info about the connection.
|
||||||
///
|
///
|
||||||
@@ -115,10 +115,10 @@ where
|
|||||||
let (inner, session) = self.get_ref();
|
let (inner, session) = self.get_ref();
|
||||||
let inner = inner.connect_info();
|
let inner = inner.connect_info();
|
||||||
|
|
||||||
let certs = if let Some(certs) = session.get_peer_certificates() {
|
let certs = if let Some(certs) = session.peer_certificates() {
|
||||||
let certs = certs
|
let certs = certs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|c| Certificate::from_pem(c.0))
|
.map(|c| Certificate::from_pem(c))
|
||||||
.collect();
|
.collect();
|
||||||
Some(Arc::new(certs))
|
Some(Arc::new(certs))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ use std::fmt;
|
|||||||
pub struct ServerTlsConfig {
|
pub struct ServerTlsConfig {
|
||||||
identity: Option<Identity>,
|
identity: Option<Identity>,
|
||||||
client_ca_root: Option<Certificate>,
|
client_ca_root: Option<Certificate>,
|
||||||
rustls_raw: Option<tokio_rustls::rustls::ServerConfig>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
@@ -28,7 +27,6 @@ impl ServerTlsConfig {
|
|||||||
ServerTlsConfig {
|
ServerTlsConfig {
|
||||||
identity: None,
|
identity: None,
|
||||||
client_ca_root: None,
|
client_ca_root: None,
|
||||||
rustls_raw: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,24 +46,7 @@ impl ServerTlsConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use options specified by the given `ServerConfig` to configure TLS.
|
|
||||||
///
|
|
||||||
/// This overrides all other TLS options set via other means.
|
|
||||||
pub fn rustls_server_config(
|
|
||||||
&mut self,
|
|
||||||
config: tokio_rustls::rustls::ServerConfig,
|
|
||||||
) -> &mut Self {
|
|
||||||
self.rustls_raw = Some(config);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn tls_acceptor(&self) -> Result<TlsAcceptor, crate::Error> {
|
pub(crate) fn tls_acceptor(&self) -> Result<TlsAcceptor, crate::Error> {
|
||||||
match &self.rustls_raw {
|
TlsAcceptor::new(self.identity.clone().unwrap(), self.client_ca_root.clone())
|
||||||
None => TlsAcceptor::new_with_rustls_identity(
|
|
||||||
self.identity.clone().unwrap(),
|
|
||||||
self.client_ca_root.clone(),
|
|
||||||
),
|
|
||||||
Some(config) => TlsAcceptor::new_with_rustls_raw(config.clone()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ use super::io::BoxedIo;
|
|||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
use super::tls::TlsConnector;
|
use super::tls::TlsConnector;
|
||||||
use http::Uri;
|
use http::Uri;
|
||||||
|
#[cfg(feature = "tls-roots-common")]
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use tower::make::MakeConnection;
|
use tower::make::MakeConnection;
|
||||||
use tower_service::Service;
|
use tower_service::Service;
|
||||||
@@ -39,22 +41,18 @@ impl<C> Connector<C> {
|
|||||||
|
|
||||||
#[cfg(feature = "tls-roots-common")]
|
#[cfg(feature = "tls-roots-common")]
|
||||||
fn tls_or_default(&self, scheme: Option<&str>, host: Option<&str>) -> Option<TlsConnector> {
|
fn tls_or_default(&self, scheme: Option<&str>, host: Option<&str>) -> Option<TlsConnector> {
|
||||||
use tokio_rustls::webpki::DNSNameRef;
|
|
||||||
|
|
||||||
if self.tls.is_some() {
|
if self.tls.is_some() {
|
||||||
return self.tls.clone();
|
return self.tls.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
match (scheme, host) {
|
let host = match (scheme, host) {
|
||||||
(Some("https"), Some(host)) => {
|
(Some("https"), Some(host)) => host,
|
||||||
if DNSNameRef::try_from_ascii(host.as_bytes()).is_ok() {
|
_ => return None,
|
||||||
TlsConnector::new_with_rustls_cert(None, None, host.to_owned()).ok()
|
};
|
||||||
} else {
|
|
||||||
None
|
host.try_into()
|
||||||
}
|
.ok()
|
||||||
}
|
.and_then(|dns| TlsConnector::new(None, None, dns).ok())
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ use crate::transport::{
|
|||||||
};
|
};
|
||||||
#[cfg(feature = "tls-roots")]
|
#[cfg(feature = "tls-roots")]
|
||||||
use rustls_native_certs;
|
use rustls_native_certs;
|
||||||
|
#[cfg(feature = "tls")]
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::{fmt, sync::Arc};
|
use std::{fmt, sync::Arc};
|
||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
use tokio::io::{AsyncRead, AsyncWrite};
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
use tokio_rustls::{
|
use tokio_rustls::{
|
||||||
rustls::{ClientConfig, NoClientAuth, ServerConfig, Session},
|
rustls::{ClientConfig, RootCertStore, ServerConfig, ServerName},
|
||||||
webpki::DNSNameRef,
|
|
||||||
TlsAcceptor as RustlsAcceptor, TlsConnector as RustlsConnector,
|
TlsAcceptor as RustlsAcceptor, TlsConnector as RustlsConnector,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -31,58 +32,59 @@ enum TlsError {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct TlsConnector {
|
pub(crate) struct TlsConnector {
|
||||||
config: Arc<ClientConfig>,
|
config: Arc<ClientConfig>,
|
||||||
domain: Arc<String>,
|
domain: Arc<ServerName>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TlsConnector {
|
impl TlsConnector {
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
pub(crate) fn new_with_rustls_cert(
|
pub(crate) fn new(
|
||||||
ca_cert: Option<Certificate>,
|
ca_cert: Option<Certificate>,
|
||||||
identity: Option<Identity>,
|
identity: Option<Identity>,
|
||||||
domain: String,
|
domain: String,
|
||||||
) -> Result<Self, crate::Error> {
|
) -> Result<Self, crate::Error> {
|
||||||
let mut config = ClientConfig::new();
|
let builder = ClientConfig::builder().with_safe_defaults();
|
||||||
config.set_protocols(&[Vec::from(ALPN_H2)]);
|
let mut roots = RootCertStore::empty();
|
||||||
|
|
||||||
if let Some(identity) = identity {
|
|
||||||
let (client_cert, client_key) = rustls_keys::load_identity(identity)?;
|
|
||||||
config.set_single_client_cert(client_cert, client_key)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "tls-roots")]
|
#[cfg(feature = "tls-roots")]
|
||||||
{
|
{
|
||||||
config.root_store = match rustls_native_certs::load_native_certs() {
|
match rustls_native_certs::load_native_certs() {
|
||||||
Ok(store) | Err((Some(store), _)) => store,
|
Ok(certs) => roots.add_parsable_certificates(
|
||||||
Err((None, error)) => return Err(error.into()),
|
&certs.into_iter().map(|cert| cert.0).collect::<Vec<_>>(),
|
||||||
|
),
|
||||||
|
Err(error) => return Err(error.into()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "tls-webpki-roots")]
|
#[cfg(feature = "tls-webpki-roots")]
|
||||||
{
|
{
|
||||||
config
|
use tokio_rustls::rustls::OwnedTrustAnchor;
|
||||||
.root_store
|
|
||||||
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
|
roots.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
|
||||||
|
OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
|
ta.subject,
|
||||||
|
ta.spki,
|
||||||
|
ta.name_constraints,
|
||||||
|
)
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cert) = ca_cert {
|
if let Some(cert) = ca_cert {
|
||||||
let mut buf = std::io::Cursor::new(&cert.pem[..]);
|
rustls_keys::add_certs_from_pem(std::io::Cursor::new(&cert.pem[..]), &mut roots)?;
|
||||||
config.root_store.add_pem_file(&mut buf).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
let builder = builder.with_root_certificates(roots);
|
||||||
config: Arc::new(config),
|
let mut config = match identity {
|
||||||
domain: Arc::new(domain),
|
Some(identity) => {
|
||||||
})
|
let (client_cert, client_key) = rustls_keys::load_identity(identity)?;
|
||||||
}
|
builder.with_single_cert(client_cert, client_key)?
|
||||||
|
}
|
||||||
|
None => builder.with_no_client_auth(),
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
config.alpn_protocols.push(ALPN_H2.as_bytes().to_vec());
|
||||||
pub(crate) fn new_with_rustls_raw(
|
|
||||||
config: tokio_rustls::rustls::ClientConfig,
|
|
||||||
domain: String,
|
|
||||||
) -> Result<Self, crate::Error> {
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
config: Arc::new(config),
|
config: Arc::new(config),
|
||||||
domain: Arc::new(domain),
|
domain: Arc::new(domain.as_str().try_into()?),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,15 +93,13 @@ impl TlsConnector {
|
|||||||
I: AsyncRead + AsyncWrite + Send + Unpin + 'static,
|
I: AsyncRead + AsyncWrite + Send + Unpin + 'static,
|
||||||
{
|
{
|
||||||
let tls_io = {
|
let tls_io = {
|
||||||
let dns = DNSNameRef::try_from_ascii_str(self.domain.as_str())?.to_owned();
|
|
||||||
|
|
||||||
let io = RustlsConnector::from(self.config.clone())
|
let io = RustlsConnector::from(self.config.clone())
|
||||||
.connect(dns.as_ref(), io)
|
.connect(self.domain.as_ref().to_owned(), io)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let (_, session) = io.get_ref();
|
let (_, session) = io.get_ref();
|
||||||
|
|
||||||
match session.get_alpn_protocol() {
|
match session.alpn_protocol() {
|
||||||
Some(b) if b == b"h2" => (),
|
Some(b) if b == b"h2" => (),
|
||||||
_ => return Err(TlsError::H2NotNegotiated.into()),
|
_ => return Err(TlsError::H2NotNegotiated.into()),
|
||||||
};
|
};
|
||||||
@@ -124,39 +124,26 @@ pub(crate) struct TlsAcceptor {
|
|||||||
|
|
||||||
impl TlsAcceptor {
|
impl TlsAcceptor {
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
pub(crate) fn new_with_rustls_identity(
|
pub(crate) fn new(
|
||||||
identity: Identity,
|
identity: Identity,
|
||||||
client_ca_root: Option<Certificate>,
|
client_ca_root: Option<Certificate>,
|
||||||
) -> Result<Self, crate::Error> {
|
) -> Result<Self, crate::Error> {
|
||||||
let (cert, key) = rustls_keys::load_identity(identity)?;
|
let builder = ServerConfig::builder().with_safe_defaults();
|
||||||
|
|
||||||
let mut config = match client_ca_root {
|
let builder = match client_ca_root {
|
||||||
None => ServerConfig::new(NoClientAuth::new()),
|
None => builder.with_no_client_auth(),
|
||||||
Some(cert) => {
|
Some(cert) => {
|
||||||
let mut cert = std::io::Cursor::new(&cert.pem[..]);
|
use tokio_rustls::rustls::server::AllowAnyAuthenticatedClient;
|
||||||
|
let mut roots = RootCertStore::empty();
|
||||||
let mut client_root_cert_store = tokio_rustls::rustls::RootCertStore::empty();
|
rustls_keys::add_certs_from_pem(std::io::Cursor::new(&cert.pem[..]), &mut roots)?;
|
||||||
if client_root_cert_store.add_pem_file(&mut cert).is_err() {
|
builder.with_client_cert_verifier(AllowAnyAuthenticatedClient::new(roots))
|
||||||
return Err(Box::new(TlsError::CertificateParseError));
|
|
||||||
}
|
|
||||||
|
|
||||||
let client_auth =
|
|
||||||
tokio_rustls::rustls::AllowAnyAuthenticatedClient::new(client_root_cert_store);
|
|
||||||
ServerConfig::new(client_auth)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
config.set_single_cert(cert, key)?;
|
|
||||||
config.set_protocols(&[Vec::from(ALPN_H2)]);
|
|
||||||
|
|
||||||
Ok(Self {
|
let (cert, key) = rustls_keys::load_identity(identity)?;
|
||||||
inner: Arc::new(config),
|
let mut config = builder.with_single_cert(cert, key)?;
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
config.alpn_protocols.push(ALPN_H2.as_bytes().to_vec());
|
||||||
pub(crate) fn new_with_rustls_raw(
|
|
||||||
config: tokio_rustls::rustls::ServerConfig,
|
|
||||||
) -> Result<Self, crate::Error> {
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: Arc::new(config),
|
inner: Arc::new(config),
|
||||||
})
|
})
|
||||||
@@ -194,7 +181,9 @@ impl std::error::Error for TlsError {}
|
|||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
mod rustls_keys {
|
mod rustls_keys {
|
||||||
use tokio_rustls::rustls::{internal::pemfile, Certificate, PrivateKey};
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
use tokio_rustls::rustls::{Certificate, PrivateKey, RootCertStore};
|
||||||
|
|
||||||
use crate::transport::service::tls::TlsError;
|
use crate::transport::service::tls::TlsError;
|
||||||
use crate::transport::Identity;
|
use crate::transport::Identity;
|
||||||
@@ -203,17 +192,17 @@ mod rustls_keys {
|
|||||||
mut cursor: std::io::Cursor<&[u8]>,
|
mut cursor: std::io::Cursor<&[u8]>,
|
||||||
) -> Result<PrivateKey, crate::Error> {
|
) -> Result<PrivateKey, crate::Error> {
|
||||||
// First attempt to load the private key assuming it is PKCS8-encoded
|
// First attempt to load the private key assuming it is PKCS8-encoded
|
||||||
if let Ok(mut keys) = pemfile::pkcs8_private_keys(&mut cursor) {
|
if let Ok(mut keys) = rustls_pemfile::pkcs8_private_keys(&mut cursor) {
|
||||||
if !keys.is_empty() {
|
if let Some(key) = keys.pop() {
|
||||||
return Ok(keys.remove(0));
|
return Ok(PrivateKey(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it not, try loading the private key as an RSA key
|
// If it not, try loading the private key as an RSA key
|
||||||
cursor.set_position(0);
|
cursor.set_position(0);
|
||||||
if let Ok(mut keys) = pemfile::rsa_private_keys(&mut cursor) {
|
if let Ok(mut keys) = rustls_pemfile::rsa_private_keys(&mut cursor) {
|
||||||
if !keys.is_empty() {
|
if let Some(key) = keys.pop() {
|
||||||
return Ok(keys.remove(0));
|
return Ok(PrivateKey(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,8 +215,8 @@ mod rustls_keys {
|
|||||||
) -> Result<(Vec<Certificate>, PrivateKey), crate::Error> {
|
) -> Result<(Vec<Certificate>, PrivateKey), crate::Error> {
|
||||||
let cert = {
|
let cert = {
|
||||||
let mut cert = std::io::Cursor::new(&identity.cert.pem[..]);
|
let mut cert = std::io::Cursor::new(&identity.cert.pem[..]);
|
||||||
match pemfile::certs(&mut cert) {
|
match rustls_pemfile::certs(&mut cert) {
|
||||||
Ok(certs) => certs,
|
Ok(certs) => certs.into_iter().map(Certificate).collect(),
|
||||||
Err(_) => return Err(Box::new(TlsError::CertificateParseError)),
|
Err(_) => return Err(Box::new(TlsError::CertificateParseError)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -244,4 +233,15 @@ mod rustls_keys {
|
|||||||
|
|
||||||
Ok((cert, key))
|
Ok((cert, key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_certs_from_pem(
|
||||||
|
mut certs: Cursor<&[u8]>,
|
||||||
|
roots: &mut RootCertStore,
|
||||||
|
) -> Result<(), crate::Error> {
|
||||||
|
let (_, ignored) = roots.add_parsable_certificates(&rustls_pemfile::certs(&mut certs)?);
|
||||||
|
match ignored == 0 {
|
||||||
|
true => Ok(()),
|
||||||
|
false => Err(Box::new(TlsError::CertificateParseError)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user