mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +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
|
@ -11,7 +11,7 @@
|
|||
//! over events from the network and events from the DOM, using async/await to avoid
|
||||
//! the need for a dedicated thread per websocket.
|
||||
|
||||
use crate::connector::{create_tls_config, ALPN_H1};
|
||||
use crate::connector::{create_tls_config, CACertificates, TlsConfig};
|
||||
use crate::cookie::Cookie;
|
||||
use crate::fetch::methods::should_be_blocked_due_to_bad_port;
|
||||
use crate::hosts::replace_host;
|
||||
|
@ -19,7 +19,6 @@ use crate::http_loader::HttpState;
|
|||
use async_tungstenite::tokio::{client_async_tls_with_connector_and_config, ConnectStream};
|
||||
use async_tungstenite::WebSocketStream;
|
||||
use base64::Engine;
|
||||
use embedder_traits::resources::{self, Resource};
|
||||
use futures::future::TryFutureExt;
|
||||
use futures::sink::SinkExt;
|
||||
use futures::stream::StreamExt;
|
||||
|
@ -29,15 +28,14 @@ use ipc_channel::router::ROUTER;
|
|||
use net_traits::request::{RequestBuilder, RequestMode};
|
||||
use net_traits::{CookieSource, MessageData};
|
||||
use net_traits::{WebSocketDomAction, WebSocketNetworkEvent};
|
||||
use openssl::ssl::ConnectConfiguration;
|
||||
use servo_url::ServoUrl;
|
||||
use std::fs;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::runtime::Runtime;
|
||||
use tokio::select;
|
||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
||||
use tokio_rustls::TlsConnector;
|
||||
use tungstenite::error::Result as WebSocketResult;
|
||||
use tungstenite::error::{Error, ProtocolError, UrlError};
|
||||
use tungstenite::handshake::client::{Request, Response};
|
||||
|
@ -302,7 +300,7 @@ async fn start_websocket(
|
|||
resource_event_sender: IpcSender<WebSocketNetworkEvent>,
|
||||
protocols: Vec<String>,
|
||||
client: Request,
|
||||
tls_config: ConnectConfiguration,
|
||||
tls_config: TlsConfig,
|
||||
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
|
||||
) -> Result<(), Error> {
|
||||
trace!("starting WS connection to {}", url);
|
||||
|
@ -330,8 +328,10 @@ async fn start_websocket(
|
|||
|
||||
let try_socket = TcpStream::connect((&*domain.to_string(), port)).await;
|
||||
let socket = try_socket.map_err(Error::Io)?;
|
||||
let connector = TlsConnector::from(Arc::new(tls_config));
|
||||
|
||||
let (stream, response) =
|
||||
client_async_tls_with_connector_and_config(client, socket, Some(tls_config), None).await?;
|
||||
client_async_tls_with_connector_and_config(client, socket, Some(connector), None).await?;
|
||||
|
||||
let protocol_in_use = process_ws_response(&http_state, &response, &url, &protocols)?;
|
||||
|
||||
|
@ -357,7 +357,8 @@ fn connect(
|
|||
resource_event_sender: IpcSender<WebSocketNetworkEvent>,
|
||||
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
|
||||
http_state: Arc<HttpState>,
|
||||
certificate_path: Option<String>,
|
||||
ca_certificates: CACertificates,
|
||||
ignore_certificate_errors: bool,
|
||||
) -> Result<(), String> {
|
||||
let protocols = match req_builder.mode {
|
||||
RequestMode::WebSocket { protocols } => protocols,
|
||||
|
@ -382,11 +383,6 @@ fn connect(
|
|||
return Err("Port blocked".to_string());
|
||||
}
|
||||
|
||||
let certs = match certificate_path {
|
||||
Some(ref path) => fs::read_to_string(path).map_err(|e| e.to_string())?,
|
||||
None => resources::read_string(Resource::SSLCertificates),
|
||||
};
|
||||
|
||||
let client = match create_request(
|
||||
&req_url,
|
||||
&req_builder.origin.ascii_serialization(),
|
||||
|
@ -397,16 +393,12 @@ fn connect(
|
|||
Err(e) => return Err(e.to_string()),
|
||||
};
|
||||
|
||||
let tls_config = create_tls_config(
|
||||
&certs,
|
||||
ALPN_H1,
|
||||
http_state.extra_certs.clone(),
|
||||
http_state.connection_certs.clone(),
|
||||
let mut tls_config = create_tls_config(
|
||||
ca_certificates,
|
||||
ignore_certificate_errors,
|
||||
http_state.override_manager.clone(),
|
||||
);
|
||||
let tls_config = match tls_config.build().configure() {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Err(e.to_string()),
|
||||
};
|
||||
tls_config.alpn_protocols = vec!["h2".to_string().into(), "http/1.1".to_string().into()];
|
||||
|
||||
let resource_event_sender2 = resource_event_sender.clone();
|
||||
match HANDLE.lock().unwrap().as_mut() {
|
||||
|
@ -436,7 +428,8 @@ pub fn init(
|
|||
resource_event_sender: IpcSender<WebSocketNetworkEvent>,
|
||||
dom_action_receiver: IpcReceiver<WebSocketDomAction>,
|
||||
http_state: Arc<HttpState>,
|
||||
certificate_path: Option<String>,
|
||||
ca_certificates: CACertificates,
|
||||
ignore_certificate_errors: bool,
|
||||
) {
|
||||
let resource_event_sender2 = resource_event_sender.clone();
|
||||
if let Err(e) = connect(
|
||||
|
@ -444,7 +437,8 @@ pub fn init(
|
|||
resource_event_sender,
|
||||
dom_action_receiver,
|
||||
http_state,
|
||||
certificate_path,
|
||||
ca_certificates,
|
||||
ignore_certificate_errors,
|
||||
) {
|
||||
warn!("Error starting websocket: {}", e);
|
||||
let _ = resource_event_sender2.send(WebSocketNetworkEvent::Fail);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue