diff --git a/Cargo.lock b/Cargo.lock index 2403a7d4dbb..25b2495c070 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,11 +226,11 @@ dependencies = [ "futures-io", "futures-util", "log", - "openssl", "pin-project-lite", "tokio", - "tokio-openssl", + "tokio-rustls", "tungstenite", + "webpki-roots", ] [[package]] @@ -1639,7 +1639,7 @@ dependencies = [ "futures-sink", "nanorand", "pin-project", - "spin", + "spin 0.9.8", ] [[package]] @@ -2715,21 +2715,19 @@ dependencies = [ ] [[package]] -name = "hyper-openssl" -version = "0.9.2" +name = "hyper-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ee5d7a8f718585d1c3c61dfde28ef5b0bb14734b4db13f5ada856cdc6c612b" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ + "futures-util", "http", "hyper", - "linked_hash_set", - "once_cell", - "openssl", - "openssl-sys", - "parking_lot 0.12.0", + "log", + "rustls", "tokio", - "tokio-openssl", - "tower-layer", + "tokio-rustls", + "webpki-roots", ] [[package]] @@ -3342,21 +3340,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "linked_hash_set" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -3849,7 +3832,7 @@ dependencies = [ "headers", "http", "hyper", - "hyper-openssl", + "hyper-rustls", "hyper_serde", "immeta", "ipc-channel", @@ -3862,12 +3845,12 @@ dependencies = [ "mime_guess", "msg", "net_traits", - "openssl", - "openssl-sys", "percent-encoding", "pixels", "profile_traits", "rayon", + "rustls", + "rustls-pemfile", "serde", "serde_json", "servo_allocator", @@ -3878,12 +3861,13 @@ dependencies = [ "std_test_override", "time 0.1.45", "tokio", - "tokio-openssl", + "tokio-rustls", "tokio-stream", "tokio-test", "tungstenite", "url", "uuid 1.3.4", + "webpki-roots", "webrender_api", ] @@ -3920,6 +3904,7 @@ dependencies = [ "num-traits", "percent-encoding", "pixels", + "rustls", "serde", "servo_arc", "servo_rand", @@ -4202,44 +4187,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -[[package]] -name = "openssl" -version = "0.10.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1" -dependencies = [ - "bitflags 1.3.2", - "cfg-if 1.0.0", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-sys" -version = "0.9.85" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d3d193fb1488ad46ffe3aaabc912cc931d02ee8518fe2959aea8ef52718b0c0" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "orbclient" version = "0.3.42" @@ -4881,6 +4828,21 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "rle-decode-fast" version = "1.0.3" @@ -4945,14 +4907,46 @@ dependencies = [ ] [[package]] -name = "rustls-pemfile" -version = "1.0.2" +name = "rustls" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.2", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ "base64 0.21.2", ] +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513722fd73ad80a71f72b61009ea1b584bcfa1483ca93949c8f290298837fa59" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -5180,6 +5174,16 @@ dependencies = [ "webxr-api", ] +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sctk-adwaita" version = "0.5.3" @@ -5821,6 +5825,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b72d540d5c565dbe1f891d7e21ceb21d2649508306782f1066989fccb0b363d3" +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.8" @@ -6355,14 +6365,12 @@ dependencies = [ ] [[package]] -name = "tokio-openssl" -version = "0.6.3" +name = "tokio-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08f9ffb7809f1b20c1b398d92acf4cc719874b3b2b2d9ea2f09b4a80350878a" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "futures-util", - "openssl", - "openssl-sys", + "rustls", "tokio", ] @@ -6413,12 +6421,6 @@ dependencies = [ "serde", ] -[[package]] -name = "tower-layer" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" - [[package]] name = "tower-service" version = "0.3.1" @@ -6486,10 +6488,12 @@ dependencies = [ "httparse", "log", "rand 0.8.5", + "rustls", "sha1", "thiserror", "url", "utf-8", + "webpki", ] [[package]] @@ -6589,6 +6593,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "unwind-sys" version = "0.1.3" @@ -6957,6 +6967,25 @@ dependencies = [ "wgpu-types", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +dependencies = [ + "rustls-webpki 0.100.1", +] + [[package]] name = "webrender" version = "0.61.0" diff --git a/Cargo.toml b/Cargo.toml index 1d58f0656ab..ef6983cdb9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ exclude = [".cargo"] [workspace.dependencies] accountable-refcell = "0.2.0" app_units = "0.7" +async-tungstenite = { version = "0.22", features = ["tokio-rustls-webpki-roots"] } atomic_refcell = "0.1.6" arrayvec = "0.7" backtrace = "0.3" @@ -35,6 +36,7 @@ headers = "0.3" html5ever = "0.26" http = "0.2" hyper = "0.14" +hyper-rustls = { version = "0.24", default-features = false, features = ["webpki-tokio", "http1", "http2", "tls12", "logging", "acceptor"] } hyper_serde = "0.13" image = "0.24" indexmap = { version = "1.0.2", features = ["std"] } @@ -57,6 +59,8 @@ quote = "1" rand = "0.7" rayon = "1" regex = "1.1" +rustls = { version = "0.21.5", features = ["dangerous_configuration"] } +rustls-pemfile = "1.0.3" serde = "1.0.60" serde_bytes = "0.11" serde_json = "1.0" @@ -73,11 +77,15 @@ surfman-chains-api = "0.2" thin-slice = "0.1.0" time = "0.1.41" tokio = "1" +tokio-rustls = "0.24" +tungstenite = "0.19" unicode-bidi = "0.3.4" unicode-script = "0.5" url = "2.0" uuid = { version = "1.3.4", features = ["v4"] } webdriver = "0.48.0" +webpki-roots = "0.23" +webpki = "0.22" webrender = { git = "https://github.com/servo/webrender", features = ["capture"] } webrender_api = { git = "https://github.com/servo/webrender" } winapi = "0.3" diff --git a/components/config/opts.rs b/components/config/opts.rs index 94a97ad07b7..721f86af5c1 100644 --- a/components/config/opts.rs +++ b/components/config/opts.rs @@ -113,9 +113,14 @@ pub struct Opts { /// Print the version and exit. pub is_printing_version: bool, - /// Path to SSL certificates. + /// Path to PEM encoded SSL CA certificate store. pub certificate_path: Option, + /// Whether or not to completely ignore SSL certificate validation errors. + /// TODO: We should see if we can eliminate the need for this by fixing + /// https://github.com/servo/servo/issues/30080. + pub ignore_certificate_errors: bool, + /// Unminify Javascript. pub unminify_js: bool, @@ -408,6 +413,7 @@ pub fn default_opts() -> Opts { is_printing_version: false, shaders_dir: None, certificate_path: None, + ignore_certificate_errors: false, unminify_js: false, local_script_source: None, print_pwm: false, @@ -524,6 +530,11 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR "Path to find SSL certificates", "/home/servo/resources/certs", ); + opts.optflag( + "", + "ignore-certificate-errors", + "Whether or not to completely ignore certificate errors", + ); opts.optopt( "", "content-process", @@ -767,6 +778,7 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR is_printing_version, shaders_dir: opt_match.opt_str("shaders").map(Into::into), certificate_path: opt_match.opt_str("certificate-path"), + ignore_certificate_errors: opt_match.opt_present("ignore-certificate-errors"), unminify_js: opt_match.opt_present("unminify-js"), local_script_source: opt_match.opt_str("local-script-source"), print_pwm: opt_match.opt_present("print-pwm"), diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index f54ffe4d7be..929000b9c94 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -6,7 +6,6 @@ license = "MPL-2.0" edition = "2018" publish = false autotests = false # Inhibit lookup for tests/*.rs without [[test]] sections -build = "build.rs" [lib] name = "net" @@ -16,7 +15,7 @@ doctest = false [dependencies] async-recursion = "0.3.2" -async-tungstenite = { version = "0.22", features = ["tokio-openssl"] } +async-tungstenite = { workspace = true } base64 = { workspace = true } brotli = "3" bytes = "1" @@ -33,7 +32,7 @@ generic-array = "0.14" headers = { workspace = true } http = { workspace = true } hyper = { workspace = true, features = ["client", "http1", "http2", "tcp", "stream"] } -hyper-openssl = "0.9.1" +hyper-rustls = { workspace = true } hyper_serde = { workspace = true } immeta = "0.4" ipc-channel = { workspace = true } @@ -46,12 +45,12 @@ mime = { workspace = true } mime_guess = { workspace = true } msg = { path = "../msg" } net_traits = { path = "../net_traits" } -openssl = "0.10" -openssl-sys = "0.9" percent-encoding = { workspace = true } pixels = { path = "../pixels" } profile_traits = { path = "../profile_traits" } rayon = { workspace = true } +rustls = { workspace = true } +rustls-pemfile = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } servo_allocator = { path = "../allocator" } @@ -61,16 +60,17 @@ servo_url = { path = "../url" } sha2 = "0.10" time = { workspace = true } tokio = { workspace = true, features = ["sync", "macros", "rt-multi-thread"] } +tokio-rustls = { workspace = true } tokio-stream = "0.1" -tungstenite = "0.19" +tungstenite = { workspace = true } url = { workspace = true } uuid = { workspace = true } webrender_api = { workspace = true } +webpki-roots = { workspace = true } [dev-dependencies] futures = {version = "0.3", features = ["compat"]} std_test_override = { path = "../std_test_override" } -tokio-openssl = "0.6" tokio-test = "0.4" tokio-stream = { version = "0.1", features = ["net"] } hyper = { workspace = true, features = ["full"] } diff --git a/components/net/build.rs b/components/net/build.rs deleted file mode 100644 index 4a75c1b4bbb..00000000000 --- a/components/net/build.rs +++ /dev/null @@ -1,16 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -fn main() { - let version = - std::env::var("DEP_OPENSSL_VERSION_NUMBER").expect("missing DEP_OPENSSL_VERSION_NUMBER"); - let actual = u64::from_str_radix(&version, 16).unwrap(); - let minimum = 0x10101000; - if actual < minimum { - panic!( - "Your OpenSSL version is older than 1.1.1 ({:x}), you have: {:x}", - minimum, actual - ); - } -} diff --git a/components/net/connector.rs b/components/net/connector.rs index cd24d8697f5..65981f25d16 100644 --- a/components/net/connector.rs +++ b/components/net/connector.rs @@ -9,80 +9,30 @@ use http::uri::{Authority, Uri as Destination}; use hyper::client::HttpConnector as HyperHttpConnector; use hyper::rt::Executor; use hyper::{service::Service, Body, Client}; -use hyper_openssl::HttpsConnector; -use openssl::ex_data::Index; -use openssl::ssl::{ - Ssl, SslConnector, SslConnectorBuilder, SslContext, SslMethod, SslOptions, SslVerifyMode, -}; -use openssl::x509::{self, X509StoreContext}; -use std::collections::hash_map::{Entry, HashMap}; +use hyper_rustls::HttpsConnector as HyperRustlsHttpsConnector; +use rustls::client::WebPkiVerifier; +use rustls::{Certificate, ClientConfig, OwnedTrustAnchor, RootCertStore, ServerName}; +use std::collections::hash_map::HashMap; +use std::convert::TryFrom; use std::sync::{Arc, Mutex}; pub const BUF_SIZE: usize = 32768; -pub const ALPN_H2_H1: &'static [u8] = b"\x02h2\x08http/1.1"; -pub const ALPN_H1: &'static [u8] = b"\x08http/1.1"; - -// See https://wiki.mozilla.org/Security/Server_Side_TLS for orientation. -const TLS1_2_CIPHERSUITES: &'static str = concat!( - "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:", - "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:", - "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:", - "ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA@SECLEVEL=2" -); -const SIGNATURE_ALGORITHMS: &'static str = concat!( - "ed448:ed25519:", - "ECDSA+SHA384:ECDSA+SHA256:", - "RSA-PSS+SHA512:RSA-PSS+SHA384:RSA-PSS+SHA256:", - "RSA+SHA512:RSA+SHA384:RSA+SHA256" -); #[derive(Clone)] -pub struct ConnectionCerts { - certs: Arc, u32)>>>, -} - -impl ConnectionCerts { - pub fn new() -> Self { - Self { - certs: Arc::new(Mutex::new(HashMap::new())), - } - } - - fn store(&self, host: String, cert_bytes: Vec) { - let mut certs = self.certs.lock().unwrap(); - let entry = certs.entry(host).or_insert((cert_bytes, 0)); - entry.1 += 1; - } - - pub(crate) fn remove(&self, host: String) -> Option> { - match self.certs.lock().unwrap().entry(host) { - Entry::Vacant(_) => return None, - Entry::Occupied(mut e) => { - e.get_mut().1 -= 1; - if e.get().1 == 0 { - return Some((e.remove_entry().1).0); - } - Some(e.get().0.clone()) - }, - } - } -} - -#[derive(Clone)] -pub struct HttpConnector { +pub struct ServoHttpConnector { inner: HyperHttpConnector, } -impl HttpConnector { - fn new() -> HttpConnector { +impl ServoHttpConnector { + fn new() -> ServoHttpConnector { let mut inner = HyperHttpConnector::new(); inner.enforce_http(false); inner.set_happy_eyeballs_timeout(None); - HttpConnector { inner } + ServoHttpConnector { inner } } } -impl Service for HttpConnector { +impl Service for ServoHttpConnector { type Response = >::Response; type Error = >::Error; type Future = >::Future; @@ -118,119 +68,85 @@ impl Service for HttpConnector { } } -pub type Connector = HttpsConnector; -pub type TlsConfig = SslConnectorBuilder; +pub type Connector = HyperRustlsHttpsConnector; +pub type TlsConfig = ClientConfig; -#[derive(Clone)] -pub struct ExtraCerts(Arc>>>); +#[derive(Clone, Debug, Default)] +struct CertificateErrorOverrideManagerInternal { + /// A mapping of certificates and their hosts, which have seen certificate errors. + /// This is used to later create an override in this [CertificateErrorOverrideManager]. + certificates_failing_to_verify: HashMap, + /// A list of certificates that should be accepted despite encountering verification + /// errors. + overrides: Vec, +} -impl ExtraCerts { +/// This data structure is used to track certificate verification errors and overrides. +/// It tracks: +/// - A list of [Certificate]s with verification errors mapped by their [ServerName] +/// - A list of [Certificate]s for which to ignore verification errors. +#[derive(Clone, Debug, Default)] +pub struct CertificateErrorOverrideManager(Arc>); + +impl CertificateErrorOverrideManager { pub fn new() -> Self { - Self(Arc::new(Mutex::new(vec![]))) + Self(Default::default()) } - pub fn add(&self, bytes: Vec) { - self.0.lock().unwrap().push(bytes); + /// Add a certificate to this manager's list of certificates for which to ignore + /// validation errors. + pub fn add_override(&self, certificate: &Certificate) { + self.0.lock().unwrap().overrides.push(certificate.clone()); + } + + /// Given the a string representation of a sever host name, remove information about + /// a [Certificate] with verification errors. If a certificate with + /// verification errors was found, return it, otherwise None. + pub(crate) fn remove_certificate_failing_verification( + &self, + host: &str, + ) -> Option { + let server_name = match ServerName::try_from(host) { + Ok(name) => name, + Err(error) => { + warn!("Could not convert host string into RustTLS ServerName: {error:?}"); + return None; + }, + }; + self.0 + .lock() + .unwrap() + .certificates_failing_to_verify + .remove(&server_name) } } -struct Host(String); - -lazy_static! { - static ref EXTRA_INDEX: Index = SslContext::new_ex_index().unwrap(); - static ref CONNECTION_INDEX: Index = - SslContext::new_ex_index().unwrap(); - static ref HOST_INDEX: Index = Ssl::new_ex_index().unwrap(); +#[derive(Clone, Debug)] +pub enum CACertificates { + Default, + Override(RootCertStore), } +/// Create a [TlsConfig] to use for managing a HTTP connection. This currently creates +/// a rustls [ClientConfig]. +/// +/// FIXME: The `ignore_certificate_errors` argument ignores all certificate errors. This +/// is used when running the WPT tests, because rustls currently rejects the WPT certificiate. +/// See https://github.com/servo/servo/issues/30080 pub fn create_tls_config( - certs: &str, - alpn: &[u8], - extra_certs: ExtraCerts, - connection_certs: ConnectionCerts, + ca_certificates: CACertificates, + ignore_certificate_errors: bool, + override_manager: CertificateErrorOverrideManager, ) -> TlsConfig { - // certs include multiple certificates. We could add all of them at once, - // but if any of them were already added, openssl would fail to insert all - // of them. - let mut certs = certs; - let mut cfg = SslConnector::builder(SslMethod::tls()).unwrap(); - loop { - let token = "-----END CERTIFICATE-----"; - if let Some(index) = certs.find(token) { - let (cert, rest) = certs.split_at(index + token.len()); - certs = rest; - let cert = x509::X509::from_pem(cert.as_bytes()).unwrap(); - cfg.cert_store_mut() - .add_cert(cert) - .or_else(|e| { - let v: Option> = e.errors().iter().nth(0).map(|e| e.reason()); - if v == Some(Some("cert already in hash table")) { - warn!("Cert already in hash table. Ignoring."); - // Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the - // certificate is already in the store. - Ok(()) - } else { - Err(e) - } - }) - .expect("could not set CA file"); - } else { - break; - } - } - cfg.set_alpn_protos(alpn) - .expect("could not set alpn protocols"); - cfg.set_cipher_list(TLS1_2_CIPHERSUITES) - .expect("could not set TLS 1.2 ciphersuites"); - cfg.set_sigalgs_list(SIGNATURE_ALGORITHMS) - .expect("could not set signature algorithms"); - cfg.set_options( - SslOptions::NO_SSLV2 | - SslOptions::NO_SSLV3 | - SslOptions::NO_TLSV1 | - SslOptions::NO_TLSV1_1 | - SslOptions::NO_COMPRESSION, + let verifier = CertificateVerificationOverrideVerifier::new( + ca_certificates, + ignore_certificate_errors, + override_manager, ); - - cfg.set_ex_data(*EXTRA_INDEX, extra_certs); - cfg.set_ex_data(*CONNECTION_INDEX, connection_certs); - cfg.set_verify_callback(SslVerifyMode::PEER, |verified, x509_store_context| { - if verified { - return true; - } - - let ssl_idx = X509StoreContext::ssl_idx().unwrap(); - let ssl = x509_store_context.ex_data(ssl_idx).unwrap(); - - // Obtain the cert bytes for this connection. - let cert = match x509_store_context.current_cert() { - Some(cert) => cert, - None => return false, - }; - let pem = match cert.to_pem() { - Ok(pem) => pem, - Err(_) => return false, - }; - - let ssl_context = ssl.ssl_context(); - - // Ensure there's an entry stored in the set of known connection certs for this connection. - if let Some(host) = ssl.ex_data(*HOST_INDEX) { - let connection_certs = ssl_context.ex_data(*CONNECTION_INDEX).unwrap(); - connection_certs.store((*host).0.clone(), pem.clone()); - } - - // Fall back to the dynamic set of allowed certs. - let extra_certs = ssl_context.ex_data(*EXTRA_INDEX).unwrap(); - for cert in &*extra_certs.0.lock().unwrap() { - if pem == *cert { - return true; - } - } - false - }); - - cfg + rustls::ClientConfig::builder() + .with_safe_defaults() + .with_custom_certificate_verifier(Arc::new(verifier)) + .with_no_client_auth() } struct TokioExecutor {} @@ -244,14 +160,95 @@ where } } -pub fn create_http_client(tls_config: TlsConfig) -> Client { - let mut connector = HttpsConnector::with_connector(HttpConnector::new(), tls_config).unwrap(); - connector.set_callback(|configuration, destination| { - if let Some(host) = destination.host() { - configuration.set_ex_data(*HOST_INDEX, Host(host.to_owned())); +struct CertificateVerificationOverrideVerifier { + webpki_verifier: WebPkiVerifier, + ignore_certificate_errors: bool, + override_manager: CertificateErrorOverrideManager, +} + +impl CertificateVerificationOverrideVerifier { + fn new( + ca_certficates: CACertificates, + ignore_certificate_errors: bool, + override_manager: CertificateErrorOverrideManager, + ) -> Self { + let root_cert_store = match ca_certficates { + CACertificates::Default => { + let mut root_cert_store = rustls::RootCertStore::empty(); + root_cert_store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map( + |trust_anchor| { + OwnedTrustAnchor::from_subject_spki_name_constraints( + trust_anchor.subject, + trust_anchor.spki, + trust_anchor.name_constraints, + ) + }, + )); + root_cert_store + }, + CACertificates::Override(root_cert_store) => root_cert_store, + }; + + Self { + // See https://github.com/rustls/rustls/blame/v/0.21.6/rustls/src/client/builder.rs#L141 + // This is the default verifier for Rustls that we are wrapping. + webpki_verifier: WebPkiVerifier::new(root_cert_store, None), + ignore_certificate_errors, + override_manager, } - Ok(()) - }); + } +} + +impl rustls::client::ServerCertVerifier for CertificateVerificationOverrideVerifier { + fn verify_server_cert( + &self, + end_entity: &Certificate, + intermediates: &[Certificate], + server_name: &ServerName, + scts: &mut dyn Iterator, + ocsp_response: &[u8], + now: std::time::SystemTime, + ) -> Result { + let error = match self.webpki_verifier.verify_server_cert( + end_entity, + intermediates, + server_name, + scts, + ocsp_response, + now, + ) { + Ok(result) => return Ok(result), + Err(error) => error, + }; + + if self.ignore_certificate_errors { + warn!("Ignoring certficate error: {error:?}"); + return Ok(rustls::client::ServerCertVerified::assertion()); + } + + // If there's an override for this certificate, just accept it. + for cert_with_exception in &*self.override_manager.0.lock().unwrap().overrides { + if *end_entity == *cert_with_exception { + return Ok(rustls::client::ServerCertVerified::assertion()); + } + } + self.override_manager + .0 + .lock() + .unwrap() + .certificates_failing_to_verify + .insert(server_name.clone(), end_entity.clone()); + Err(error) + } +} + +pub fn create_http_client(tls_config: TlsConfig) -> Client { + let connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_tls_config(tls_config) + .https_or_http() + .enable_http1() + .enable_http2() + .wrap_connector(ServoHttpConnector::new()); Client::builder() .http1_title_case_headers(true) diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index fb40d40ac19..f11a203b3bc 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -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()) }, diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 6a12100f3d1..d1decdb70da 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -2,7 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::connector::{create_http_client, ConnectionCerts, Connector, ExtraCerts, TlsConfig}; +use crate::connector::{ + create_http_client, create_tls_config, CACertificates, CertificateErrorOverrideManager, + Connector, +}; use crate::cookie; use crate::cookie_storage::CookieStorage; use crate::decoder::Decoder; @@ -98,12 +101,12 @@ pub struct HttpState { pub auth_cache: RwLock, pub history_states: RwLock>>, pub client: Client, - pub extra_certs: ExtraCerts, - pub connection_certs: ConnectionCerts, + pub override_manager: CertificateErrorOverrideManager, } impl HttpState { - pub fn new(tls_config: TlsConfig) -> HttpState { + pub fn new() -> HttpState { + let override_manager = CertificateErrorOverrideManager::new(); HttpState { hsts_list: RwLock::new(HstsList::new()), cookie_jar: RwLock::new(CookieStorage::new(150)), @@ -111,9 +114,12 @@ impl HttpState { history_states: RwLock::new(HashMap::new()), http_cache: RwLock::new(HttpCache::new()), http_cache_state: Mutex::new(HashMap::new()), - client: create_http_client(tls_config), - extra_certs: ExtraCerts::new(), - connection_certs: ConnectionCerts::new(), + client: create_http_client(create_tls_config( + CACertificates::Default, + false, /* ignore_certificate_errors */ + override_manager.clone(), + )), + override_manager, } } } @@ -652,18 +658,12 @@ async fn obtain_response( let send_start = precise_time_ms(); let host = request.uri().host().unwrap_or("").to_owned(); - let host_clone = request.uri().host().unwrap_or("").to_owned(); - let connection_certs = context.state.connection_certs.clone(); - let connection_certs_clone = context.state.connection_certs.clone(); - + let override_manager = context.state.override_manager.clone(); let headers = headers.clone(); client .request(request) .and_then(move |res| { - // We no longer need to track the cert for this connection. - connection_certs.remove(host); - let send_end = precise_time_ms(); // TODO(#21271) response_start: immediately after receiving first byte of response @@ -696,8 +696,11 @@ async fn obtain_response( }; future::ready(Ok((Decoder::detect(res), msg))) }) - .map_err(move |e| { - NetworkError::from_hyper_error(&e, connection_certs_clone.remove(host_clone)) + .map_err(move |error| { + NetworkError::from_hyper_error( + &error, + override_manager.remove_certificate_failing_verification(host.as_str()), + ) }) .await } diff --git a/components/net/lib.rs b/components/net/lib.rs index 1c9c987a691..2c19e895bc5 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -46,6 +46,3 @@ pub mod test { pub use crate::hosts::{parse_hostsfile, replace_host_table}; pub use crate::http_loader::HttpState; } - -// This dependency gives `build.rs` access to the `DEP_OPENSSL_VERSION_NUMBER` env variable. -use openssl_sys as _; diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index 3d656428f6b..a4314fbe8df 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -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 { + 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, certificate_path: Option, + 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 = StorageThreadFactory::new(config_dir); ( @@ -86,7 +109,8 @@ pub fn new_core_resource_thread( mem_profiler_chan: MemProfilerChan, embedder_proxy: EmbedderProxy, config_dir: Option, - certificate_path: Option, + 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, - certificate_path: Option, + ca_certificates: CACertificates, + ignore_certificate_errors: bool, } fn create_http_states( config_dir: Option<&Path>, - certificate_path: Option, + ca_certificates: CACertificates, + ignore_certificate_errors: bool, ) -> (Arc, Arc) { 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>, filemanager: FileManager, thread_pool: Arc, - certificate_path: Option, + 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>, _profiler_chan: ProfilerChan, embedder_proxy: EmbedderProxy, - certificate_path: Option, + 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, ); } } diff --git a/components/net/tests/fetch.rs b/components/net/tests/fetch.rs index 3b0f18f1950..b5c34a91f3b 100644 --- a/components/net/tests/fetch.rs +++ b/components/net/tests/fetch.rs @@ -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, response: &mut HyperResponse| { *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) diff --git a/components/net/tests/main.rs b/components/net/tests/main.rs index 46f3eb1bb05..7a0f4955cd5 100644 --- a/components/net/tests/main.rs +++ b/components/net/tests/main.rs @@ -22,10 +22,8 @@ mod resource_thread; mod subresource_integrity; use core::convert::Infallible; -use core::pin::Pin; use crossbeam_channel::{unbounded, Sender}; use devtools_traits::DevtoolsControlMsg; -use embedder_traits::resources::{self, Resource}; use embedder_traits::{EmbedderProxy, EventLoopWaker}; use futures::future::ready; use futures::StreamExt; @@ -33,7 +31,6 @@ use hyper::server::conn::Http; use hyper::server::Server as HyperServer; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request as HyperRequest, Response as HyperResponse}; -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; @@ -43,16 +40,19 @@ use net_traits::filemanager_thread::FileTokenCheck; use net_traits::request::Request; use net_traits::response::Response; use net_traits::{FetchTaskTarget, ResourceFetchTiming, ResourceTimingType}; -use openssl::ssl::{Ssl, SslAcceptor, SslFiletype, SslMethod}; +use rustls::{self, Certificate, PrivateKey}; +use rustls_pemfile::{certs, pkcs8_private_keys}; use servo_arc::Arc as ServoArc; use servo_url::ServoUrl; +use std::fs::File; +use std::io::{self, BufReader}; use std::net::TcpListener as StdTcpListener; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex, Weak}; use tokio::net::TcpListener; use tokio::net::TcpStream; use tokio::runtime::{Builder, Runtime}; -use tokio_openssl::SslStream; +use tokio_rustls::{self, TlsAcceptor}; use tokio_stream::wrappers::TcpListenerStream; use tokio_test::block_on; @@ -102,17 +102,10 @@ fn new_fetch_context( fc: Option, pool_handle: Option>, ) -> FetchContext { - let certs = resources::read_string(Resource::SSLCertificates); - let tls_config = create_tls_config( - &certs, - ALPN_H2_H1, - ExtraCerts::new(), - ConnectionCerts::new(), - ); let sender = fc.unwrap_or_else(|| create_embedder_proxy()); FetchContext { - state: Arc::new(HttpState::new(tls_config)), + state: Arc::new(HttpState::new()), user_agent: DEFAULT_USER_AGENT.into(), devtools_chan: dc.map(|dc| Arc::new(Mutex::new(dc))), filemanager: Arc::new(Mutex::new(FileManager::new( @@ -167,6 +160,7 @@ fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache) -> Respon pub(crate) struct Server { pub close_channel: tokio::sync::oneshot::Sender<()>, + pub certificates: Option>, } impl Server { @@ -205,11 +199,39 @@ where }; HANDLE.lock().unwrap().spawn(server); - let server = Server { close_channel: tx }; - (server, url) + ( + Server { + close_channel: tx, + certificates: None, + }, + url, + ) } -fn make_ssl_server(handler: H, cert_path: PathBuf, key_path: PathBuf) -> (Server, ServoUrl) +/// Given a path to a file containing PEM certificates, load and parse them into +/// a vector of RusTLS [Certificate]s. +fn load_certificates_from_pem(path: &PathBuf) -> std::io::Result> { + let file = File::open(path)?; + let mut reader = BufReader::new(file); + let certs = certs(&mut reader)?; + Ok(certs.into_iter().map(Certificate).collect()) +} + +/// Given a path to a file containing PEM keys, load and parse them into +/// a vector of RusTLS [PrivateKey]s. +fn load_private_key_from_file(path: &PathBuf) -> Result> { + let file = File::open(&path)?; + let mut reader = BufReader::new(file); + let mut keys = pkcs8_private_keys(&mut reader)?; + + match keys.len() { + 0 => Err(format!("No PKCS8-encoded private key found in {path:?}").into()), + 1 => Ok(PrivateKey(keys.remove(0))), + _ => Err(format!("More than one PKCS8-encoded private key found in {path:?}").into()), + } +} + +fn make_ssl_server(handler: H) -> (Server, ServoUrl) where H: Fn(HyperRequest, &mut HyperResponse) + Send + Sync + 'static, { @@ -219,13 +241,28 @@ where .lock() .unwrap() .block_on(async move { TcpListener::from_std(listener).unwrap() }); - let url_string = format!("http://localhost:{}", listener.local_addr().unwrap().port()); - let mut listener = TcpListenerStream::new(listener); - let url = ServoUrl::parse(&url_string).unwrap(); - let (tx, mut rx) = tokio::sync::oneshot::channel::<()>(); + 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 certificates = load_certificates_from_pem(&cert_path).expect("Invalid certificate"); + let key = load_private_key_from_file(&key_path).expect("Invalid key"); + + let config = rustls::ServerConfig::builder() + .with_safe_defaults() + .with_no_client_auth() + .with_single_cert(certificates.clone(), key) + .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err)) + .expect("Could not create rustls ServerConfig"); + let acceptor = TlsAcceptor::from(Arc::new(config)); + + let mut listener = TcpListenerStream::new(listener); + let (tx, mut rx) = tokio::sync::oneshot::channel::<()>(); let server = async move { loop { let stream = tokio::select! { @@ -244,22 +281,16 @@ where .unwrap(); let stream = TcpStream::from_std(stream).unwrap(); - let mut tls_server_config = - SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap(); - tls_server_config - .set_certificate_file(&cert_path, SslFiletype::PEM) - .unwrap(); - tls_server_config - .set_private_key_file(&key_path, SslFiletype::PEM) - .unwrap(); - - let tls_server_config = tls_server_config.build(); - let ssl = Ssl::new(tls_server_config.context()).unwrap(); - let mut stream = SslStream::new(ssl, stream).unwrap(); - - let _ = Pin::new(&mut stream).accept().await; - let handler = handler.clone(); + let acceptor = acceptor.clone(); + + let stream = match acceptor.accept(stream).await { + Ok(stream) => stream, + Err(_) => { + eprintln!("Error handling TLS stream."); + continue; + }, + }; let _ = Http::new() .serve_connection( @@ -276,6 +307,11 @@ where HANDLE.lock().unwrap().spawn(server); - let server = Server { close_channel: tx }; - (server, url) + ( + Server { + close_channel: tx, + certificates: Some(certificates), + }, + url, + ) } diff --git a/components/net/tests/resource_thread.rs b/components/net/tests/resource_thread.rs index 7951e7e10da..11aac7efc49 100644 --- a/components/net/tests/resource_thread.rs +++ b/components/net/tests/resource_thread.rs @@ -4,6 +4,7 @@ use crate::create_embedder_proxy; use ipc_channel::ipc; +use net::connector::CACertificates; use net::resource_thread::new_core_resource_thread; use net::test::parse_hostsfile; use net_traits::CoreResourceMsg; @@ -27,7 +28,8 @@ fn test_exit() { MemProfilerChan(mtx), create_embedder_proxy(), None, - None, + CACertificates::Default, + false, /* ignore_certificate_errors */ ); resource_thread.send(CoreResourceMsg::Exit(sender)).unwrap(); receiver.recv().unwrap(); diff --git a/components/net/websocket_loader.rs b/components/net/websocket_loader.rs index 1bdb8faec10..140a57f4a30 100644 --- a/components/net/websocket_loader.rs +++ b/components/net/websocket_loader.rs @@ -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, protocols: Vec, client: Request, - tls_config: ConnectConfiguration, + tls_config: TlsConfig, dom_action_receiver: IpcReceiver, ) -> 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, dom_action_receiver: IpcReceiver, http_state: Arc, - certificate_path: Option, + 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, dom_action_receiver: IpcReceiver, http_state: Arc, - certificate_path: Option, + 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); diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml index a31a23759c5..92e82dd0704 100644 --- a/components/net_traits/Cargo.toml +++ b/components/net_traits/Cargo.toml @@ -31,6 +31,7 @@ msg = { path = "../msg" } num-traits = { workspace = true } percent-encoding = { workspace = true } pixels = { path = "../pixels" } +rustls = { workspace = true } serde = { workspace = true } servo_arc = { path = "../servo_arc" } servo_rand = { path = "../rand" } diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 323fc9a59cb..1df0e5e0374 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -30,6 +30,7 @@ use ipc_channel::router::ROUTER; use ipc_channel::Error as IpcError; use mime::Mime; use msg::constellation_msg::HistoryStateId; +use rustls::Certificate; use servo_rand::RngCore; use servo_url::{ImmutableOrigin, ServoUrl}; use time::precise_time_ns; @@ -762,12 +763,11 @@ pub enum NetworkError { } impl NetworkError { - pub fn from_hyper_error(error: &HyperError, cert_bytes: Option>) -> Self { - let s = error.to_string(); - if s.to_lowercase().contains("ssl") { - NetworkError::SslValidation(s, cert_bytes.unwrap_or_default()) - } else { - NetworkError::Internal(s) + pub fn from_hyper_error(error: &HyperError, certificate: Option) -> Self { + let error_string = error.to_string(); + match certificate { + Some(certificate) => NetworkError::SslValidation(error_string, certificate.0), + _ => NetworkError::Internal(error_string), } } diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index 44d0c3de1df..943a680d4ef 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -36,6 +36,7 @@ use crate::dom::virtualmethods::vtable_for; use crate::network_listener::PreInvoke; use crate::realms::enter_realm; use crate::script_thread::ScriptThread; +use base64::{engine::general_purpose, Engine as _}; use content_security_policy::{self as csp, CspList}; use dom_struct::dom_struct; use embedder_traits::resources::{self, Resource}; @@ -880,8 +881,8 @@ impl FetchResponseListener for ParserContext { self.is_synthesized_document = true; let page = resources::read_string(Resource::BadCertHTML); let page = page.replace("${reason}", &reason); - let page = - page.replace("${bytes}", std::str::from_utf8(&bytes).unwrap_or_default()); + let encoded_bytes = general_purpose::STANDARD_NO_PAD.encode(&bytes); + let page = page.replace("${bytes}", encoded_bytes.as_str()); let page = page.replace("${secret}", &net_traits::PRIVILEGED_SECRET.to_string()); parser.push_string_input_chunk(page); diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 0738452b162..ff84c4bf4ab 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -857,6 +857,7 @@ fn create_constellation( embedder_proxy.clone(), config_dir, opts.certificate_path.clone(), + opts.ignore_certificate_errors, ); let font_cache_thread = FontCacheThread::new( diff --git a/etc/cert_generator.js b/etc/cert_generator.js deleted file mode 100644 index a7b6d4c4c32..00000000000 --- a/etc/cert_generator.js +++ /dev/null @@ -1,75 +0,0 @@ -// XPCShell script for generating a single file containing all certificates in PEM -// format. You may run this in the browser toolbox's console -// (Firefox -> devtools -> settings -> enable remote/chrome debugging, -// followed by settings -> devtools menu -> browser toolbox) or the -// xpcshell runner that comes with a built Firefox (./run-mozilla.sh ./xpcshell). -// The variable `certstring` contains the final pem file. You can use `save(path)` to -// save it to a file. `certlist` contains an array with the PEM certs as well as their names if you -// want to filter them. - - -// http://mxr.mozilla.org/mozilla-central/source/security/manager/pki/resources/content/pippki.js -function getDERString(cert) -{ - var length = {}; - var derArray = cert.getRawDER(length); - var derString = ''; - for (var i = 0; i < derArray.length; i++) { - derString += String.fromCharCode(derArray[i]); - } - return derString; -} - -// http://mxr.mozilla.org/mozilla-central/source/security/manager/pki/resources/content/pippki.js -function getPEMString(cert) -{ - var derb64 = btoa(getDERString(cert)); - // Wrap the Base64 string into lines of 64 characters, - // with CRLF line breaks (as specified in RFC 1421). - var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n"); - return "-----BEGIN CERTIFICATE-----\r\n" - + wrapped - + "\r\n-----END CERTIFICATE-----\r\n"; -} - -let certdb = Components.classes["@mozilla.org/security/x509certdb;1"].createInstance(Ci.nsIX509CertDB); -let enumerator = certdb.getCerts().getEnumerator(); -let certlist = []; -let certstring=""; -while(enumerator.hasMoreElements()){ - let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert); - let pem = getPEMString(cert); - let trusted = certdb.isCertTrusted(cert, Ci.nsIX509Cert.CA_CERT, Ci.nsIX509CertDB.TRUSTED_SSL); - certlist.push({name: cert.commonName, pem: pem, trusted: trusted}); - if (trusted) { - certstring+=pem; - } -} - -function save(path) { - // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O - Components.utils.import("resource://gre/modules/FileUtils.jsm"); - var file = new FileUtils.File(path); - Components.utils.import("resource://gre/modules/NetUtil.jsm"); - - // file is nsIFile, data is a string - - // You can also optionally pass a flags parameter here. It defaults to - // FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE; - var ostream = FileUtils.openSafeFileOutputStream(file); - - var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]. - createInstance(Components.interfaces.nsIScriptableUnicodeConverter); - converter.charset = "UTF-8"; - var istream = converter.convertToInputStream(certstring); - - // The last argument (the callback) is optional. - NetUtil.asyncCopy(istream, ostream, function(status) { - if (!Components.isSuccessCode(status)) { - // Handle error! - return; - } - - // Data has been written to the file. - }); -} diff --git a/etc/cert_generator.sh b/etc/cert_generator.sh deleted file mode 100755 index a14a48c3d83..00000000000 --- a/etc/cert_generator.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at https://mozilla.org/MPL/2.0/. - -set -o errexit -set -o nounset -set -o pipefail - -# https://wiki.mozilla.org/CA/Included_Certificates -# 1. Mozilla's official CA database CSV file is downloaded with curl -# and processed with awk. -# 2. Rows end with `"\n`. -# 3. Each row is split by ^" and "," into columns. -# 4. Single and double quotes are removed from column 32. -# 5. If column 13 (12 in the csv file) contains `Websites` -# (some are Email-only), column 32 is printed, the raw certificate. -# 6. All CA certs trusted for Websites are stored into the `certs` file. - -url="https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReportPEMCSV" -curl "${url}" -sSf | gawk -v RS="\"\n" -F'","|^"' \ -'{gsub("\047","",$(32));gsub("\"","",$(32));if($(13)~/Websites/)print $(32)}' \ -> ../resources/certs diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py index 4497e16e849..212b17f5c9d 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -188,15 +188,10 @@ class MachCommands(CommandBase): ) assert os.path.exists(servo_exe_dir) - # on msvc, we need to copy in some DLLs in to the servo.exe dir and the directory for unit tests. - for ssl_lib in ["libssl.dll", "libcrypto.dll"]: - ssl_path = path.join(env['OPENSSL_LIB_DIR'], "../bin", ssl_lib) - shutil.copy(ssl_path, servo_exe_dir) - shutil.copy(ssl_path, path.join(servo_exe_dir, "deps")) - build_path = path.join(servo_exe_dir, "build") assert os.path.exists(build_path) + # on msvc, we need to copy in some DLLs in to the servo.exe dir and the directory for unit tests. def package_generated_shared_libraries(libs, build_path, servo_exe_dir): for root, dirs, files in os.walk(build_path): remaining_libs = list(libs) @@ -265,16 +260,6 @@ class MachCommands(CommandBase): if not self.is_android_build: return - openssl_dir = os.path.join(self.target_path, "native", "openssl") - if not os.path.exists(openssl_dir): - os.makedirs(openssl_dir) - shutil.copy(os.path.join(self.android_support_dir(), "openssl.makefile"), openssl_dir) - shutil.copy(os.path.join(self.android_support_dir(), "openssl.sh"), openssl_dir) - - status = call(["make", "-f", "openssl.makefile"], env=env, cwd=openssl_dir) - if status: - return status - # Build the name of the package containing all GStreamer dependencies # according to the build target. android_lib = self.config["android"]["lib"] diff --git a/python/servo/command_base.py b/python/servo/command_base.py index 43d2e97d89c..8542abe55b7 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -500,19 +500,6 @@ class CommandBase(object): env.setdefault("CC", "clang-cl.exe") env.setdefault("CXX", "clang-cl.exe") - arch = effective_target.split('-')[0] - vcpkg_arch = { - "x86_64": "x64-windows", - "i686": "x86-windows", - "aarch64": "arm64-windows", - } - target_arch = vcpkg_arch[arch] - openssl_base_dir = path.join(self.msvc_package_dir("openssl"), target_arch) - - # Link openssl - env["OPENSSL_INCLUDE_DIR"] = path.join(openssl_base_dir, "include") - env["OPENSSL_LIB_DIR"] = path.join(openssl_base_dir, "lib") - env["OPENSSL_LIBS"] = "libssl:libcrypto" # Link moztools, used for building SpiderMonkey moztools_paths = [ path.join(self.msvc_package_dir("moztools"), "bin"), @@ -625,9 +612,6 @@ class CommandBase(object): android_lib = self.config["android"]["lib"] android_arch = self.config["android"]["arch"] - # Build OpenSSL for android - env["OPENSSL_VERSION"] = "1.1.1d" - # Check if the NDK version is 15 if not os.path.isfile(path.join(env["ANDROID_NDK"], 'source.properties')): print("ANDROID_NDK should have file `source.properties`.") @@ -639,11 +623,6 @@ class CommandBase(object): print("Currently only support NDK 15. Please re-run `./mach bootstrap-android`.") sys.exit(1) - openssl_dir = path.join( - self.target_path, "native", "openssl", "openssl-{}".format(env["OPENSSL_VERSION"])) - env['OPENSSL_LIB_DIR'] = openssl_dir - env['OPENSSL_INCLUDE_DIR'] = path.join(openssl_dir, "include") - env['OPENSSL_STATIC'] = 'TRUE' # Android builds also require having the gcc bits on the PATH and various INCLUDE # path munging if you do not want to install a standalone NDK. See: # https://dxr.mozilla.org/mozilla-central/source/build/autoconf/android.m4#139-161 diff --git a/python/servo/platform/linux.py b/python/servo/platform/linux.py index 516b7448686..e49154d8ff2 100644 --- a/python/servo/platform/linux.py +++ b/python/servo/platform/linux.py @@ -19,8 +19,7 @@ from .base import Base # Please keep these in sync with the packages in README.md APT_PKGS = ['git', 'curl', 'autoconf', 'libx11-dev', 'libfreetype6-dev', 'libgl1-mesa-dri', 'libglib2.0-dev', 'xorg-dev', 'gperf', 'g++', - 'build-essential', 'cmake', 'libssl-dev', - 'liblzma-dev', 'libxmu6', 'libxmu-dev', + 'build-essential', 'cmake', 'liblzma-dev', 'libxmu6', 'libxmu-dev', "libxcb-render0-dev", "libxcb-shape0-dev", "libxcb-xfixes0-dev", 'libgles2-mesa-dev', 'libegl1-mesa-dev', 'libdbus-1-dev', 'libharfbuzz-dev', 'ccache', 'clang', 'libunwind-dev', @@ -31,8 +30,7 @@ DNF_PKGS = ['libtool', 'gcc-c++', 'libXi-devel', 'freetype-devel', 'libunwind-devel', 'mesa-libGL-devel', 'mesa-libEGL-devel', 'glib2-devel', 'libX11-devel', 'libXrandr-devel', 'gperf', 'fontconfig-devel', 'cabextract', 'ttmkfdir', 'expat-devel', - 'rpm-build', 'openssl-devel', 'cmake', - 'libXcursor-devel', 'libXmu-devel', + 'rpm-build', 'cmake', 'libXcursor-devel', 'libXmu-devel', 'dbus-devel', 'ncurses-devel', 'harfbuzz-devel', 'ccache', 'clang', 'clang-libs', 'llvm', 'autoconf213', 'python3-devel', 'gstreamer1-devel', 'gstreamer1-plugins-base-devel', diff --git a/python/servo/platform/windows.py b/python/servo/platform/windows.py index ddd283db72d..02d013bafc6 100644 --- a/python/servo/platform/windows.py +++ b/python/servo/platform/windows.py @@ -21,7 +21,6 @@ DEPS_URL = "https://github.com/servo/servo-build-deps/releases/download/msvc-dep DEPENDENCIES = { "llvm": "15.0.5", "moztools": "3.2", - "openssl": "111.3.0+1.1.1c-vs2017-2019-09-18", } URL_BASE = "https://gstreamer.freedesktop.org/data/pkg/windows/1.16.0/" diff --git a/resources/badcert.html b/resources/badcert.html index 4548686afc5..4933f5af0cb 100644 --- a/resources/badcert.html +++ b/resources/badcert.html @@ -6,7 +6,7 @@

${reason}

-
${bytes}
+
${bytes}