diff --git a/components/config/prefs.rs b/components/config/prefs.rs index f5766c45fdd..d40850eac8d 100644 --- a/components/config/prefs.rs +++ b/components/config/prefs.rs @@ -250,8 +250,10 @@ pub struct Preferences { pub network_http_proxy_uri: String, pub network_local_directory_listing_enabled: bool, pub network_mime_sniff: bool, - /// Use the webpki roots if no root store path is given. - pub network_webpki_roots: bool, + /// Force the use of `rust-webpki` verification for CA roots. If this is false (the + /// default), then `rustls-platform-verifier` will be used, except on Android where + /// `rust-webpki` is always used. + pub network_use_webpki_roots: bool, pub session_history_max_length: i64, /// The background color of shell's viewport. This will be used by OpenGL's `glClearColor`. pub shell_background_color_rgba: [f64; 4], @@ -436,7 +438,7 @@ impl Preferences { network_http_proxy_uri: String::new(), network_local_directory_listing_enabled: true, network_mime_sniff: false, - network_webpki_roots: false, + network_use_webpki_roots: false, session_history_max_length: 20, shell_background_color_rgba: [1.0, 1.0, 1.0, 1.0], threadpools_async_runtime_workers_max: 6, diff --git a/components/fonts/lib.rs b/components/fonts/lib.rs index 7ca5e577e67..2a7f44079a2 100644 --- a/components/fonts/lib.rs +++ b/components/fonts/lib.rs @@ -45,7 +45,7 @@ pub(crate) enum EmojiPresentationPreference { pub struct FallbackFontSelectionOptions { pub(crate) character: char, pub(crate) presentation_preference: EmojiPresentationPreference, - #[cfg_attr(target_os = "windows", allow(dead_code))] + #[cfg_attr(any(target_os = "android", target_os = "windows"), allow(dead_code))] pub(crate) lang: Option, } diff --git a/components/fonts/platform/freetype/android/xml.rs b/components/fonts/platform/freetype/android/xml.rs index ea69784f9cd..155be2fa8b9 100644 --- a/components/fonts/platform/freetype/android/xml.rs +++ b/components/fonts/platform/freetype/android/xml.rs @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ pub(super) use xml::attribute::OwnedAttribute as Attribute; -use xml::reader::XmlEvent::*; +use xml::reader::XmlEvent; pub(super) enum Node { Element { @@ -19,13 +19,13 @@ pub(super) fn parse(bytes: &[u8]) -> xml::reader::Result> { let mut nodes = Vec::new(); for result in xml::EventReader::new(bytes) { match result? { - StartElement { + XmlEvent::StartElement { name, attributes, .. } => { stack.push((name, attributes, nodes)); nodes = Vec::new(); }, - EndElement { .. } => { + XmlEvent::EndElement { .. } => { let (name, attributes, mut parent_nodes) = stack.pop().unwrap(); parent_nodes.push(Node::Element { name, @@ -34,15 +34,18 @@ pub(super) fn parse(bytes: &[u8]) -> xml::reader::Result> { }); nodes = parent_nodes; }, - CData(s) | Characters(s) | Whitespace(s) => { + XmlEvent::CData(s) | XmlEvent::Characters(s) | XmlEvent::Whitespace(s) => { if let Some(Node::Text(text)) = nodes.last_mut() { text.push_str(&s) } else { nodes.push(Node::Text(s)) } }, - StartDocument { .. } | EndDocument | ProcessingInstruction { .. } | Comment(..) => {}, - Doctype => {}, + XmlEvent::Comment(..) | + XmlEvent::Doctype { .. } | + XmlEvent::EndDocument | + XmlEvent::ProcessingInstruction { .. } | + XmlEvent::StartDocument { .. } => {}, } } assert!(stack.is_empty()); diff --git a/components/net/connector.rs b/components/net/connector.rs index 8b240e825df..1c09401f8cf 100644 --- a/components/net/connector.rs +++ b/components/net/connector.rs @@ -24,9 +24,10 @@ use log::warn; use parking_lot::Mutex; use rustls::client::danger::ServerCertVerifier; use rustls::client::{ClientConnection, EchStatus}; -use rustls::crypto::aws_lc_rs; +use rustls::crypto::{CryptoProvider, aws_lc_rs}; use rustls::{ClientConfig, ProtocolVersion}; use rustls_pki_types::{CertificateDer, ServerName, UnixTime}; +use servo_config::pref; use tokio::net::TcpStream; use tower::Service; @@ -361,11 +362,10 @@ impl CertificateErrorOverrideManager { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub enum CACertificates<'de> { - #[cfg(not(target_os = "android"))] - PlatformVerifier, - WebPKI, + #[default] + Default, Override(Vec>), } @@ -416,49 +416,52 @@ impl CertificateVerificationOverrideVerifier { ignore_certificate_errors: bool, override_manager: CertificateErrorOverrideManager, ) -> Self { - let crypto_provider = rustls::crypto::CryptoProvider::get_default() - .unwrap_or(&Arc::new(aws_lc_rs::default_provider())) - .clone(); - let main_verifier = match ca_certficates { - #[cfg(not(target_os = "android"))] - CACertificates::PlatformVerifier => Arc::new( - rustls_platform_verifier::Verifier::new(crypto_provider) - .expect("Could not initialize platform certificate verifier."), - ), - CACertificates::WebPKI => { - let root_store = Arc::new(rustls::RootCertStore::from_iter( - webpki_roots::TLS_SERVER_ROOTS.iter().cloned(), - )); - - rustls::client::WebPkiServerVerifier::builder(root_store) - .build() - .expect("Could not initialize platform certificate verifier.") - as Arc - }, - #[cfg(not(target_os = "android"))] - CACertificates::Override(root_cert_store) => Arc::new( - rustls_platform_verifier::Verifier::new_with_extra_roots( - root_cert_store, - crypto_provider, - ) - .expect("Could not build platform verifier with additional certs."), - ), - #[cfg(target_os = "android")] - CACertificates::Override(root_cert_store) => { - // Android does not support rustls_platform_verifier::Verifier::new_with_extra_roots. - let mut main_store = rustls::RootCertStore::from_iter( - webpki_roots::TLS_SERVER_ROOTS.iter().cloned(), - ); - for i in root_cert_store { - if main_store.add(i).is_err() { - log::error!("Could not add an override certificate."); + // From : + // > Some manual setup is required, outside of cargo, to use this crate on + // > Android. In order to use Android's certificate verifier, the crate needs to + // > call into the JVM. A small Kotlin component must be included in your app's + // > build to support rustls-platform-verifier. + // + // Since we cannot count on embedders to do this setup, just stick with webpki roots + // on Android. + let use_webpki_roots = cfg!(target_os = "android") || pref!(network_use_webpki_roots); + let main_verifier = if !use_webpki_roots { + let crypto_provider = CryptoProvider::get_default() + .unwrap_or(&Arc::new(aws_lc_rs::default_provider())) + .clone(); + let verifier = match ca_certficates { + CACertificates::Default => rustls_platform_verifier::Verifier::new(crypto_provider), + // Android doesn't support `Verifier::new_with_extra_roots`, but currently Android + // never uses the platform verifier at all. + CACertificates::Override(_certificates) => { + #[cfg(target_os = "android")] + unreachable!("Android should always use the WebPKI verifier."); + #[cfg(not(target_os = "android"))] + rustls_platform_verifier::Verifier::new_with_extra_roots( + _certificates, + crypto_provider, + ) + }, + } + .expect("Could not initialize platform certificate verifier"); + Arc::new(verifier) as Arc + } else { + let mut root_store = + rustls::RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); + match ca_certficates { + CACertificates::Default => {}, + CACertificates::Override(certificates) => { + for certificate in certificates { + if root_store.add(certificate).is_err() { + log::error!("Could not add an override certificate."); + } } - } - rustls::client::WebPkiServerVerifier::builder(main_store.into()) - .build() - .expect("Could not initialize platform certificate verifier.") - as Arc - }, + }, + } + rustls::client::WebPkiServerVerifier::builder(root_store.into()) + .build() + .expect("Could not initialize platform certificate verifier.") + as Arc }; Self { diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index 82f000a2eaa..65db2bb3bdd 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -44,7 +44,6 @@ use rustls_pki_types::CertificateDer; use rustls_pki_types::pem::PemObject; use serde::{Deserialize, Serialize}; use servo_arc::Arc as ServoArc; -use servo_config::pref; use servo_url::{ImmutableOrigin, ServoUrl}; use crate::async_runtime::{init_async_runtime, spawn_task}; @@ -92,27 +91,13 @@ pub fn new_resource_threads( // Initialize the async runtime, and get a handle to it for use in clean shutdown. let async_runtime = init_async_runtime(); - #[cfg(target_os = "android")] - let default_verifier = CACertificates::WebPKI; - #[cfg(not(target_os = "android"))] - let default_verifier = CACertificates::PlatformVerifier; - - 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:?}"); - default_verifier - }, - }, - None => { - if pref!(network_webpki_roots) { - CACertificates::WebPKI - } else { - default_verifier - } - }, - }; + let ca_certificates = certificate_path + .and_then(|path| { + Some(CACertificates::Override( + load_root_cert_store_from_file(path).ok()?, + )) + }) + .unwrap_or_default(); let (public_core, private_core) = new_core_resource_thread( devtools_sender, diff --git a/components/net/tests/fetch.rs b/components/net/tests/fetch.rs index 45d6e12c3af..3ac802a6b29 100644 --- a/components/net/tests/fetch.rs +++ b/components/net/tests/fetch.rs @@ -768,7 +768,7 @@ fn test_fetch_with_hsts() { ))), protocols: Arc::new(ProtocolRegistry::default()), websocket_chan: None, - ca_certificates: CACertificates::PlatformVerifier, + ca_certificates: CACertificates::Default, ignore_certificate_errors: false, }; @@ -832,7 +832,7 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() { ))), protocols: Arc::new(ProtocolRegistry::default()), websocket_chan: None, - ca_certificates: CACertificates::PlatformVerifier, + ca_certificates: CACertificates::Default, ignore_certificate_errors: false, }; @@ -901,7 +901,7 @@ fn test_fetch_self_signed() { ))), protocols: Arc::new(ProtocolRegistry::default()), websocket_chan: None, - ca_certificates: CACertificates::PlatformVerifier, + ca_certificates: CACertificates::Default, ignore_certificate_errors: false, }; @@ -1552,7 +1552,7 @@ fn test_fetch_request_intercepted() { ))), protocols: Arc::new(ProtocolRegistry::default()), websocket_chan: None, - ca_certificates: CACertificates::PlatformVerifier, + ca_certificates: CACertificates::Default, ignore_certificate_errors: false, }; diff --git a/components/net/tests/main.rs b/components/net/tests/main.rs index 55879c9ba4b..e7ca7c2930c 100644 --- a/components/net/tests/main.rs +++ b/components/net/tests/main.rs @@ -107,7 +107,7 @@ fn create_http_state(fc: Option) -> HttpState { http_cache: RwLock::new(net::http_cache::HttpCache::default()), http_cache_state: Mutex::new(HashMap::new()), client: create_http_client(create_tls_config( - net::connector::CACertificates::PlatformVerifier, + net::connector::CACertificates::Default, false, /* ignore_certificate_errors */ override_manager.clone(), )), @@ -139,7 +139,7 @@ fn new_fetch_context( ))), protocols: Arc::new(ProtocolRegistry::with_internal_protocols()), websocket_chan: None, - ca_certificates: CACertificates::PlatformVerifier, + ca_certificates: CACertificates::Default, ignore_certificate_errors: false, } } diff --git a/components/net/tests/resource_thread.rs b/components/net/tests/resource_thread.rs index 36cf46b212f..eaaba5649f1 100644 --- a/components/net/tests/resource_thread.rs +++ b/components/net/tests/resource_thread.rs @@ -30,7 +30,7 @@ fn test_exit() { MemProfilerChan(mtx), create_embedder_proxy(), None, - CACertificates::PlatformVerifier, + CACertificates::Default, false, /* ignore_certificate_errors */ std::sync::Arc::new(ProtocolRegistry::default()), ); diff --git a/components/script/dom/console.rs b/components/script/dom/console.rs index 727f2c21e62..f7d2c8a40ca 100644 --- a/components/script/dom/console.rs +++ b/components/script/dom/console.rs @@ -350,20 +350,21 @@ fn stringify_handle_values(messages: &[HandleValue]) -> DOMString { )) } +#[cfg(not(any(target_os = "android", target_env = "ohos")))] +fn console_message_to_stdout(global: &GlobalScope, message: &DOMString) { + let prefix = global.current_group_label().unwrap_or_default(); + let formatted_message = format!("{}{}", prefix, message); + with_stderr_lock(move || { + println!("{}", formatted_message); + }); +} + /// On OHOS/ Android, stdout and stderr will be redirected to go /// to the logger. As `Console::method` and `Console::send_string_message` /// already forwards all messages to the logger with appropriate level /// this does not need to do anything for these targets. -fn console_message_to_stdout(global: &GlobalScope, message: &DOMString) { - #[cfg(not(any(target_os = "android", target_env = "ohos")))] - { - let prefix = global.current_group_label().unwrap_or_default(); - let formatted_message = format!("{}{}", prefix, message); - with_stderr_lock(move || { - println!("{}", formatted_message); - }); - } -} +#[cfg(any(target_os = "android", target_env = "ohos"))] +fn console_message_to_stdout(_: &GlobalScope, _: &DOMString) {} #[derive(Debug, Eq, PartialEq)] enum IncludeStackTrace {