mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
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:
parent
ab0f48f8e8
commit
bce7622cde
31 changed files with 575 additions and 4399 deletions
|
@ -5,7 +5,7 @@
|
|||
//! A thread that takes a URL and streams back the binary data.
|
||||
|
||||
use crate::connector::{
|
||||
create_http_client, create_tls_config, ConnectionCerts, ExtraCerts, ALPN_H2_H1,
|
||||
create_http_client, create_tls_config, CACertificates, CertificateErrorOverrideManager,
|
||||
};
|
||||
use crate::cookie;
|
||||
use crate::cookie_storage::CookieStorage;
|
||||
|
@ -19,7 +19,6 @@ use crate::storage_thread::StorageThreadFactory;
|
|||
use crate::websocket_loader;
|
||||
use crossbeam_channel::Sender;
|
||||
use devtools_traits::DevtoolsControlMsg;
|
||||
use embedder_traits::resources::{self, Resource};
|
||||
use embedder_traits::EmbedderProxy;
|
||||
use hyper_serde::Serde;
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcReceiverSet, IpcSender};
|
||||
|
@ -39,19 +38,30 @@ use net_traits::{ResourceThreads, WebSocketDomAction};
|
|||
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||
use profile_traits::mem::{Report, ReportKind, ReportsChan};
|
||||
use profile_traits::time::ProfilerChan;
|
||||
use rustls::RootCertStore;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||
use std::borrow::{Cow, ToOwned};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{self, File};
|
||||
use std::io::prelude::*;
|
||||
use std::fs::File;
|
||||
use std::io::{self, prelude::*, BufReader};
|
||||
use std::ops::Deref;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
/// Load a file with CA certificate and produce a RootCertStore with the results.
|
||||
fn load_root_cert_store_from_file(file_path: String) -> io::Result<RootCertStore> {
|
||||
let mut root_cert_store = RootCertStore::empty();
|
||||
|
||||
let mut pem = BufReader::new(File::open(file_path)?);
|
||||
let certs = rustls_pemfile::certs(&mut pem)?;
|
||||
root_cert_store.add_parsable_certificates(&certs);
|
||||
Ok(root_cert_store)
|
||||
}
|
||||
|
||||
/// Returns a tuple of (public, private) senders to the new threads.
|
||||
pub fn new_resource_threads(
|
||||
user_agent: Cow<'static, str>,
|
||||
|
@ -61,7 +71,19 @@ pub fn new_resource_threads(
|
|||
embedder_proxy: EmbedderProxy,
|
||||
config_dir: Option<PathBuf>,
|
||||
certificate_path: Option<String>,
|
||||
ignore_certificate_errors: bool,
|
||||
) -> (ResourceThreads, ResourceThreads) {
|
||||
let ca_certificates = match certificate_path {
|
||||
Some(path) => match load_root_cert_store_from_file(path) {
|
||||
Ok(root_cert_store) => CACertificates::Override(root_cert_store),
|
||||
Err(error) => {
|
||||
warn!("Could not load CA file. Falling back to defaults. {error:?}");
|
||||
CACertificates::Default
|
||||
},
|
||||
},
|
||||
None => CACertificates::Default,
|
||||
};
|
||||
|
||||
let (public_core, private_core) = new_core_resource_thread(
|
||||
user_agent,
|
||||
devtools_sender,
|
||||
|
@ -69,7 +91,8 @@ pub fn new_resource_threads(
|
|||
mem_profiler_chan,
|
||||
embedder_proxy,
|
||||
config_dir.clone(),
|
||||
certificate_path,
|
||||
ca_certificates,
|
||||
ignore_certificate_errors,
|
||||
);
|
||||
let storage: IpcSender<StorageThreadMsg> = StorageThreadFactory::new(config_dir);
|
||||
(
|
||||
|
@ -86,7 +109,8 @@ pub fn new_core_resource_thread(
|
|||
mem_profiler_chan: MemProfilerChan,
|
||||
embedder_proxy: EmbedderProxy,
|
||||
config_dir: Option<PathBuf>,
|
||||
certificate_path: Option<String>,
|
||||
ca_certificates: CACertificates,
|
||||
ignore_certificate_errors: bool,
|
||||
) -> (CoreResourceThread, CoreResourceThread) {
|
||||
let (public_setup_chan, public_setup_port) = ipc::channel().unwrap();
|
||||
let (private_setup_chan, private_setup_port) = ipc::channel().unwrap();
|
||||
|
@ -100,13 +124,15 @@ pub fn new_core_resource_thread(
|
|||
devtools_sender,
|
||||
time_profiler_chan,
|
||||
embedder_proxy,
|
||||
certificate_path.clone(),
|
||||
ca_certificates.clone(),
|
||||
ignore_certificate_errors,
|
||||
);
|
||||
|
||||
let mut channel_manager = ResourceChannelManager {
|
||||
resource_manager,
|
||||
config_dir,
|
||||
certificate_path,
|
||||
ca_certificates,
|
||||
ignore_certificate_errors,
|
||||
};
|
||||
|
||||
mem_profiler_chan.run_with_memory_reporting(
|
||||
|
@ -123,12 +149,14 @@ pub fn new_core_resource_thread(
|
|||
struct ResourceChannelManager {
|
||||
resource_manager: CoreResourceManager,
|
||||
config_dir: Option<PathBuf>,
|
||||
certificate_path: Option<String>,
|
||||
ca_certificates: CACertificates,
|
||||
ignore_certificate_errors: bool,
|
||||
}
|
||||
|
||||
fn create_http_states(
|
||||
config_dir: Option<&Path>,
|
||||
certificate_path: Option<String>,
|
||||
ca_certificates: CACertificates,
|
||||
ignore_certificate_errors: bool,
|
||||
) -> (Arc<HttpState>, Arc<HttpState>) {
|
||||
let mut hsts_list = HstsList::from_servo_preload();
|
||||
let mut auth_cache = AuthCache::new();
|
||||
|
@ -140,14 +168,7 @@ fn create_http_states(
|
|||
read_json_from_file(&mut cookie_jar, config_dir, "cookie_jar.json");
|
||||
}
|
||||
|
||||
let certs = match certificate_path {
|
||||
Some(ref path) => fs::read_to_string(path).expect("Couldn't not find certificate file"),
|
||||
None => resources::read_string(Resource::SSLCertificates),
|
||||
};
|
||||
|
||||
let extra_certs = ExtraCerts::new();
|
||||
let connection_certs = ConnectionCerts::new();
|
||||
|
||||
let override_manager = CertificateErrorOverrideManager::new();
|
||||
let http_state = HttpState {
|
||||
hsts_list: RwLock::new(hsts_list),
|
||||
cookie_jar: RwLock::new(cookie_jar),
|
||||
|
@ -156,18 +177,14 @@ fn create_http_states(
|
|||
http_cache: RwLock::new(http_cache),
|
||||
http_cache_state: Mutex::new(HashMap::new()),
|
||||
client: create_http_client(create_tls_config(
|
||||
&certs,
|
||||
ALPN_H2_H1,
|
||||
extra_certs.clone(),
|
||||
connection_certs.clone(),
|
||||
ca_certificates.clone(),
|
||||
ignore_certificate_errors,
|
||||
override_manager.clone(),
|
||||
)),
|
||||
extra_certs,
|
||||
connection_certs,
|
||||
override_manager,
|
||||
};
|
||||
|
||||
let extra_certs = ExtraCerts::new();
|
||||
let connection_certs = ConnectionCerts::new();
|
||||
|
||||
let override_manager = CertificateErrorOverrideManager::new();
|
||||
let private_http_state = HttpState {
|
||||
hsts_list: RwLock::new(HstsList::from_servo_preload()),
|
||||
cookie_jar: RwLock::new(CookieStorage::new(150)),
|
||||
|
@ -176,13 +193,11 @@ fn create_http_states(
|
|||
http_cache: RwLock::new(HttpCache::new()),
|
||||
http_cache_state: Mutex::new(HashMap::new()),
|
||||
client: create_http_client(create_tls_config(
|
||||
&certs,
|
||||
ALPN_H2_H1,
|
||||
extra_certs.clone(),
|
||||
connection_certs.clone(),
|
||||
ca_certificates,
|
||||
ignore_certificate_errors,
|
||||
override_manager.clone(),
|
||||
)),
|
||||
extra_certs,
|
||||
connection_certs,
|
||||
override_manager,
|
||||
};
|
||||
|
||||
(Arc::new(http_state), Arc::new(private_http_state))
|
||||
|
@ -198,7 +213,8 @@ impl ResourceChannelManager {
|
|||
) {
|
||||
let (public_http_state, private_http_state) = create_http_states(
|
||||
self.config_dir.as_ref().map(Deref::deref),
|
||||
self.certificate_path.clone(),
|
||||
self.ca_certificates.clone(),
|
||||
self.ignore_certificate_errors,
|
||||
);
|
||||
|
||||
let mut rx_set = IpcReceiverSet::new().unwrap();
|
||||
|
@ -455,7 +471,8 @@ pub struct CoreResourceManager {
|
|||
sw_managers: HashMap<ImmutableOrigin, IpcSender<CustomResponseMediator>>,
|
||||
filemanager: FileManager,
|
||||
thread_pool: Arc<CoreResourceThreadPool>,
|
||||
certificate_path: Option<String>,
|
||||
ca_certificates: CACertificates,
|
||||
ignore_certificate_errors: bool,
|
||||
}
|
||||
|
||||
/// The state of the thread-pool used by CoreResource.
|
||||
|
@ -589,7 +606,8 @@ impl CoreResourceManager {
|
|||
devtools_sender: Option<Sender<DevtoolsControlMsg>>,
|
||||
_profiler_chan: ProfilerChan,
|
||||
embedder_proxy: EmbedderProxy,
|
||||
certificate_path: Option<String>,
|
||||
ca_certificates: CACertificates,
|
||||
ignore_certificate_errors: bool,
|
||||
) -> CoreResourceManager {
|
||||
let pool = CoreResourceThreadPool::new(16);
|
||||
let pool_handle = Arc::new(pool);
|
||||
|
@ -599,7 +617,8 @@ impl CoreResourceManager {
|
|||
sw_managers: Default::default(),
|
||||
filemanager: FileManager::new(embedder_proxy, Arc::downgrade(&pool_handle)),
|
||||
thread_pool: pool_handle,
|
||||
certificate_path,
|
||||
ca_certificates,
|
||||
ignore_certificate_errors,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -725,7 +744,8 @@ impl CoreResourceManager {
|
|||
event_sender,
|
||||
action_receiver,
|
||||
http_state.clone(),
|
||||
self.certificate_path.clone(),
|
||||
self.ca_certificates.clone(),
|
||||
self.ignore_certificate_errors,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue