mirror of
https://github.com/servo/servo.git
synced 2025-07-22 14:53:49 +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
|
@ -9,7 +9,7 @@ use crate::filemanager_thread::{FileManager, FILE_CHUNK_SIZE};
|
|||
use crate::http_loader::{determine_requests_referrer, http_fetch, HttpState};
|
||||
use crate::http_loader::{set_default_accept, set_default_accept_language};
|
||||
use crate::subresource_integrity::is_response_integrity_valid;
|
||||
use base64::Engine;
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use content_security_policy as csp;
|
||||
use crossbeam_channel::Sender;
|
||||
use devtools_traits::DevtoolsControlMsg;
|
||||
|
@ -31,11 +31,12 @@ use net_traits::request::{
|
|||
use net_traits::response::{Response, ResponseBody, ResponseType};
|
||||
use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy, ResourceFetchTiming};
|
||||
use net_traits::{ResourceAttribute, ResourceTimeValue, ResourceTimingType};
|
||||
use rustls::Certificate;
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use servo_url::ServoUrl;
|
||||
use std::borrow::Cow;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Seek, SeekFrom};
|
||||
use std::io::{self, BufReader, Seek, SeekFrom};
|
||||
use std::mem;
|
||||
use std::ops::Bound;
|
||||
use std::str;
|
||||
|
@ -627,6 +628,48 @@ fn create_blank_reply(url: ServoUrl, timing_type: ResourceTimingType) -> Respons
|
|||
response
|
||||
}
|
||||
|
||||
/// Handle a request from the user interface to ignore validation errors for a certificate.
|
||||
fn handle_allowcert_request(request: &mut Request, context: &FetchContext) -> io::Result<()> {
|
||||
let error = |string| Err(io::Error::new(io::ErrorKind::Other, string));
|
||||
|
||||
let body = match request.body.as_mut() {
|
||||
Some(body) => body,
|
||||
None => return error("No body found"),
|
||||
};
|
||||
|
||||
let stream = body.take_stream();
|
||||
let stream = stream.lock().unwrap();
|
||||
let (body_chan, body_port) = ipc::channel().unwrap();
|
||||
let _ = stream.send(BodyChunkRequest::Connect(body_chan));
|
||||
let _ = stream.send(BodyChunkRequest::Chunk);
|
||||
let body_bytes = match body_port.recv().ok() {
|
||||
Some(BodyChunkResponse::Chunk(bytes)) => bytes,
|
||||
_ => return error("Certificate not sent in a single chunk"),
|
||||
};
|
||||
|
||||
let split_idx = match body_bytes.iter().position(|b| *b == b'&') {
|
||||
Some(split_idx) => split_idx,
|
||||
None => return error("Could not find ampersand in data"),
|
||||
};
|
||||
let (secret, cert_base64) = body_bytes.split_at(split_idx);
|
||||
|
||||
let secret = str::from_utf8(secret).ok().and_then(|s| s.parse().ok());
|
||||
if secret != Some(*net_traits::PRIVILEGED_SECRET) {
|
||||
return error("Invalid secret sent. Ignoring request");
|
||||
}
|
||||
|
||||
let cert_bytes = match general_purpose::STANDARD_NO_PAD.decode(&cert_base64[1..]) {
|
||||
Ok(bytes) => bytes,
|
||||
Err(_) => return error("Could not decode certificate base64"),
|
||||
};
|
||||
|
||||
context
|
||||
.state
|
||||
.override_manager
|
||||
.add_override(&Certificate(cert_bytes));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// [Scheme fetch](https://fetch.spec.whatwg.org#scheme-fetch)
|
||||
async fn scheme_fetch(
|
||||
request: &mut Request,
|
||||
|
@ -641,32 +684,9 @@ async fn scheme_fetch(
|
|||
"about" if url.path() == "blank" => create_blank_reply(url, request.timing_type()),
|
||||
|
||||
"chrome" if url.path() == "allowcert" => {
|
||||
let data = request.body.as_mut().and_then(|body| {
|
||||
let stream = body.take_stream();
|
||||
let stream = stream.lock().unwrap();
|
||||
let (body_chan, body_port) = ipc::channel().unwrap();
|
||||
let _ = stream.send(BodyChunkRequest::Connect(body_chan));
|
||||
let _ = stream.send(BodyChunkRequest::Chunk);
|
||||
match body_port.recv().ok() {
|
||||
Some(BodyChunkResponse::Chunk(bytes)) => Some(bytes),
|
||||
_ => panic!("cert should be sent in a single chunk."),
|
||||
}
|
||||
});
|
||||
let data = data.as_ref().and_then(|b| {
|
||||
let idx = b.iter().position(|b| *b == b'&')?;
|
||||
Some(b.split_at(idx))
|
||||
});
|
||||
|
||||
if let Some((secret, bytes)) = data {
|
||||
let secret = str::from_utf8(secret).ok().and_then(|s| s.parse().ok());
|
||||
if secret == Some(*net_traits::PRIVILEGED_SECRET) {
|
||||
if let Ok(bytes) = base64::engine::general_purpose::STANDARD.decode(&bytes[1..])
|
||||
{
|
||||
context.state.extra_certs.add(bytes);
|
||||
}
|
||||
}
|
||||
if let Err(error) = handle_allowcert_request(request, context) {
|
||||
warn!("Could not handle allowcert request: {error}");
|
||||
}
|
||||
|
||||
create_blank_reply(url, request.timing_type())
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue