diff --git a/src/imp/openssl.rs b/src/imp/openssl.rs index ef254a3e..841f3bab 100644 --- a/src/imp/openssl.rs +++ b/src/imp/openssl.rs @@ -11,6 +11,7 @@ use self::openssl::ssl::{ SslVerifyMode, }; use self::openssl::x509::{store::X509StoreBuilder, X509VerifyResult, X509}; +use self::openssl::x509::verify::X509VerifyFlags; use std::error; use std::fmt; use std::io; @@ -246,6 +247,7 @@ impl From for HandshakeError { pub struct TlsConnector { connector: SslConnector, use_sni: bool, + allow_partial: bool, accept_invalid_hostnames: bool, accept_invalid_certs: bool, } @@ -300,6 +302,7 @@ impl TlsConnector { Ok(TlsConnector { connector: connector.build(), use_sni: builder.use_sni, + allow_partial: builder.allow_partial, accept_invalid_hostnames: builder.accept_invalid_hostnames, accept_invalid_certs: builder.accept_invalid_certs, }) @@ -318,6 +321,11 @@ impl TlsConnector { ssl.set_verify(SslVerifyMode::NONE); } + if self.allow_partial { + let params = ssl.param_mut(); + params.set_flags(X509VerifyFlags::PARTIAL_CHAIN)?; + } + let s = ssl.connect(domain, stream)?; Ok(TlsStream(s)) } @@ -328,6 +336,7 @@ impl fmt::Debug for TlsConnector { fmt.debug_struct("TlsConnector") // n.b. SslConnector is a newtype on SslContext which implements a noop Debug so it's omitted .field("use_sni", &self.use_sni) + .field("allow_partial", &self.allow_partial) .field("accept_invalid_hostnames", &self.accept_invalid_hostnames) .field("accept_invalid_certs", &self.accept_invalid_certs) .finish() diff --git a/src/lib.rs b/src/lib.rs index 171e8c7e..9de1a28a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -325,6 +325,7 @@ pub struct TlsConnectorBuilder { accept_invalid_certs: bool, accept_invalid_hostnames: bool, use_sni: bool, + allow_partial: bool, disable_built_in_roots: bool, #[cfg(feature = "alpn")] alpn: Vec, @@ -411,6 +412,16 @@ impl TlsConnectorBuilder { self } + /// Controls whether to accept "partial" certificate chains. Setting this to true means that you + /// can use an intermediate cert to verify the server cert, and don't need the full chain to the + /// root. This only applies to the Openssl backend. + /// + /// Defaults to `true`. + pub fn allow_partial(&mut self, allow_partial: bool) -> &mut TlsConnectorBuilder { + self.allow_partial = allow_partial; + self + } + /// Controls the use of hostname verification. /// /// Defaults to `false`. @@ -471,6 +482,7 @@ impl TlsConnector { max_protocol: None, root_certificates: vec![], use_sni: true, + allow_partial: true, accept_invalid_certs: false, accept_invalid_hostnames: false, disable_built_in_roots: false,