Switch to rustls and webpki-roots (#30025)

This change replaces OpenSSL with rustls and also the manually curated
CA certs file with webpki-roots (effectively the same thing, but as a
crate).

Generally speaking the design of the network stack is the same. Changes:

- Code around certificate overrides needed to be refactored to work with
  rustls so the various thread-safe list of certificates is refactored
  into `CertificateErrorOverrideManager`
- hyper-rustls takes care of setting ALPN protocols for HTTP requests,
  so for WebSockets this is moved to the WebSocket code.
- The safe set of cypher suites is chosen, which seem to correspond to
  the "Modern" configuration from [1]. This can be adjusted later.
- Instead of passing a string of PEM CA certificates around, an enum is
  used that includes parsed Certificates (or the default which reads
  them from webpki-roots).
- Code for starting up an SSL server for testing is cleaned up a little,
  due to the fact that the certificates need to be overriden explicitly
  now. This is due to the fact that the `webpki` crate is more stringent
  with self-signed certificates than SSL (CA certificates cannot used as
  end-entity certificates). [2]

1. https://wiki.mozilla.org/Security/Server_Side_TLS
2. https://github.com/briansmith/webpki/issues/114

Fixes #7888.
Fixes #13749.
Fixes #26835.
Fixes #29291.
This commit is contained in:
Martin Robinson 2023-08-08 16:00:10 +02:00 committed by GitHub
parent ab0f48f8e8
commit bce7622cde
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 575 additions and 4399 deletions

View file

@ -24,7 +24,6 @@ use hyper::Body;
use hyper::{Request as HyperRequest, Response as HyperResponse};
use mime::{self, Mime};
use msg::constellation_msg::TEST_PIPELINE_ID;
use net::connector::{create_tls_config, ConnectionCerts, ExtraCerts, ALPN_H2_H1};
use net::fetch::cors_cache::CorsCache;
use net::fetch::methods::{self, CancellationListener, FetchContext};
use net::filemanager_thread::FileManager;
@ -756,24 +755,10 @@ fn test_fetch_with_hsts() {
*response.body_mut() = MESSAGE.to_vec().into();
};
let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt")
.canonicalize()
.unwrap();
let key_path = Path::new("../../resources/privatekey_for_testing.key")
.canonicalize()
.unwrap();
let (server, url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
let certs = fs::read_to_string(cert_path).expect("Couldn't find certificate file");
let tls_config = create_tls_config(
&certs,
ALPN_H2_H1,
ExtraCerts::new(),
ConnectionCerts::new(),
);
let (server, url) = make_ssl_server(handler);
let mut context = FetchContext {
state: Arc::new(HttpState::new(tls_config)),
state: Arc::new(HttpState::new()),
user_agent: DEFAULT_USER_AGENT.into(),
devtools_chan: None,
filemanager: Arc::new(Mutex::new(FileManager::new(
@ -787,6 +772,12 @@ fn test_fetch_with_hsts() {
))),
};
// The server certificate is self-signed, so we need to add an override
// so that the connection works properly.
for certificate in server.certificates.as_ref().unwrap().iter() {
context.state.override_manager.add_override(certificate);
}
{
let mut list = context.state.hsts_list.write().unwrap();
list.push(
@ -821,25 +812,12 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() {
));
*response.body_mut() = b"Yay!".to_vec().into();
};
let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt")
.canonicalize()
.unwrap();
let key_path = Path::new("../../resources/privatekey_for_testing.key")
.canonicalize()
.unwrap();
let (server, mut url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
let (server, mut url) = make_ssl_server(handler);
url.as_mut_url().set_scheme("https").unwrap();
let certs = fs::read_to_string(cert_path).expect("Couldn't find certificate file");
let tls_config = create_tls_config(
&certs,
ALPN_H2_H1,
ExtraCerts::new(),
ConnectionCerts::new(),
);
let mut context = FetchContext {
state: Arc::new(HttpState::new(tls_config)),
state: Arc::new(HttpState::new()),
user_agent: DEFAULT_USER_AGENT.into(),
devtools_chan: None,
filemanager: Arc::new(Mutex::new(FileManager::new(
@ -853,6 +831,12 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() {
))),
};
// The server certificate is self-signed, so we need to add an override
// so that the connection works properly.
for certificate in server.certificates.as_ref().unwrap().iter() {
context.state.override_manager.add_override(certificate);
}
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer)
.method(Method::GET)
.body(None)
@ -885,29 +869,12 @@ fn test_fetch_self_signed() {
let handler = move |_: HyperRequest<Body>, response: &mut HyperResponse<Body>| {
*response.body_mut() = b"Yay!".to_vec().into();
};
let client_cert_path = Path::new("../../resources/certs").canonicalize().unwrap();
let cert_path = Path::new("../../resources/self_signed_certificate_for_testing.crt")
.canonicalize()
.unwrap();
let key_path = Path::new("../../resources/privatekey_for_testing.key")
.canonicalize()
.unwrap();
let (_server, mut url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
let (server, mut url) = make_ssl_server(handler);
url.as_mut_url().set_scheme("https").unwrap();
let cert_data = fs::read_to_string(cert_path.clone()).expect("Couldn't find certificate file");
let client_cert_data =
fs::read_to_string(client_cert_path.clone()).expect("Couldn't find certificate file");
let extra_certs = ExtraCerts::new();
let tls_config = create_tls_config(
&client_cert_data,
ALPN_H2_H1,
extra_certs.clone(),
ConnectionCerts::new(),
);
let mut context = FetchContext {
state: Arc::new(HttpState::new(tls_config)),
state: Arc::new(HttpState::new()),
user_agent: DEFAULT_USER_AGENT.into(),
devtools_chan: None,
filemanager: Arc::new(Mutex::new(FileManager::new(
@ -936,16 +903,11 @@ fn test_fetch_self_signed() {
Some(NetworkError::SslValidation(..))
));
extra_certs.add(cert_data.as_bytes().into());
// FIXME: something weird happens inside the SSL server after the first
// connection encounters a verification error, and it no longer
// accepts new connections that should work fine. We are forced
// to start a new server and connect to that to verfiy that
// the self-signed cert is now accepted.
let (server, mut url) = make_ssl_server(handler, cert_path.clone(), key_path.clone());
url.as_mut_url().set_scheme("https").unwrap();
// The server certificate is self-signed, so we need to add an override
// so that the connection works properly.
for certificate in server.certificates.as_ref().unwrap().iter() {
context.state.override_manager.add_override(certificate);
}
let mut request = RequestBuilder::new(url.clone(), Referrer::NoReferrer)
.method(Method::GET)