diff options
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/fetch/lib.rs | 7 | ||||
-rw-r--r-- | extensions/net/lib.rs | 10 | ||||
-rw-r--r-- | extensions/net/ops_tls.rs | 17 | ||||
-rw-r--r-- | extensions/tls/Cargo.toml | 2 | ||||
-rw-r--r-- | extensions/tls/lib.rs | 59 | ||||
-rw-r--r-- | extensions/websocket/lib.rs | 21 |
6 files changed, 109 insertions, 7 deletions
diff --git a/extensions/fetch/lib.rs b/extensions/fetch/lib.rs index 0ac853cbc..cc5954b74 100644 --- a/extensions/fetch/lib.rs +++ b/extensions/fetch/lib.rs @@ -60,6 +60,7 @@ pub fn init<P: FetchPermissions + 'static>( root_cert_store: Option<RootCertStore>, proxy: Option<Proxy>, request_builder_hook: Option<fn(RequestBuilder) -> RequestBuilder>, + unsafely_treat_insecure_origin_as_secure: Option<Vec<String>>, ) -> Extension { Extension::builder() .js(include_js_files!( @@ -87,6 +88,7 @@ pub fn init<P: FetchPermissions + 'static>( root_cert_store.clone(), None, proxy.clone(), + unsafely_treat_insecure_origin_as_secure.clone(), ) .unwrap() }); @@ -95,6 +97,8 @@ pub fn init<P: FetchPermissions + 'static>( root_cert_store: root_cert_store.clone(), proxy: proxy.clone(), request_builder_hook, + unsafely_treat_insecure_origin_as_secure: + unsafely_treat_insecure_origin_as_secure.clone(), }); Ok(()) }) @@ -106,6 +110,7 @@ pub struct HttpClientDefaults { pub root_cert_store: Option<RootCertStore>, pub proxy: Option<Proxy>, pub request_builder_hook: Option<fn(RequestBuilder) -> RequestBuilder>, + pub unsafely_treat_insecure_origin_as_secure: Option<Vec<String>>, } pub trait FetchPermissions { @@ -532,11 +537,13 @@ where let defaults = state.borrow::<HttpClientDefaults>(); let cert_data = get_cert_data(args.ca_file.as_deref(), args.ca_data.as_deref())?; + let client = create_http_client( defaults.user_agent.clone(), defaults.root_cert_store.clone(), cert_data, args.proxy, + defaults.unsafely_treat_insecure_origin_as_secure.clone(), ) .unwrap(); diff --git a/extensions/net/lib.rs b/extensions/net/lib.rs index 6b0b728b1..f68034517 100644 --- a/extensions/net/lib.rs +++ b/extensions/net/lib.rs @@ -94,9 +94,16 @@ pub struct DefaultTlsOptions { pub root_cert_store: Option<RootCertStore>, } +/// `UnsafelyTreatInsecureOriginAsSecure` is a wrapper struct so it can be placed inside `GothamState`; +/// using type alias for a `Option<Vec<String>>` could work, but there's a high chance +/// that there might be another type alias pointing to a `Option<Vec<String>>`, which +/// would override previously used alias. +pub struct UnsafelyTreatInsecureOriginAsSecure(Option<Vec<String>>); + pub fn init<P: NetPermissions + 'static>( root_cert_store: Option<RootCertStore>, unstable: bool, + unsafely_treat_insecure_origin_as_secure: Option<Vec<String>>, ) -> Extension { let mut ops_to_register = vec![]; ops_to_register.extend(io::init()); @@ -115,6 +122,9 @@ pub fn init<P: NetPermissions + 'static>( root_cert_store: root_cert_store.clone(), }); state.put(UnstableChecker { unstable }); + state.put(UnsafelyTreatInsecureOriginAsSecure( + unsafely_treat_insecure_origin_as_secure.clone(), + )); Ok(()) }) .build() diff --git a/extensions/net/ops_tls.rs b/extensions/net/ops_tls.rs index 7c4563390..6c26ed748 100644 --- a/extensions/net/ops_tls.rs +++ b/extensions/net/ops_tls.rs @@ -9,6 +9,7 @@ use crate::resolve_addr::resolve_addr; use crate::resolve_addr::resolve_addr_sync; use crate::DefaultTlsOptions; use crate::NetPermissions; +use crate::UnsafelyTreatInsecureOriginAsSecure; use deno_core::error::bad_resource; use deno_core::error::bad_resource_id; use deno_core::error::custom_error; @@ -720,8 +721,8 @@ where let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; - let tls_config = Arc::new(create_client_config(root_cert_store, ca_data)?); - + let tls_config = + Arc::new(create_client_config(root_cert_store, ca_data, None)?); let tls_stream = TlsStream::new_client_side(tcp_stream, &tls_config, hostname_dns); @@ -760,6 +761,11 @@ where }; let port = args.port; let cert_file = args.cert_file.as_deref(); + let unsafely_treat_insecure_origin_as_secure = state + .borrow() + .borrow::<UnsafelyTreatInsecureOriginAsSecure>() + .0 + .clone(); if args.cert_chain.is_some() { super::check_unstable2(&state, "ConnectTlsOptions.certChain"); @@ -801,8 +807,11 @@ where let tcp_stream = TcpStream::connect(connect_addr).await?; let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; - - let mut tls_config = create_client_config(root_cert_store, ca_data)?; + let mut tls_config = create_client_config( + root_cert_store, + ca_data, + unsafely_treat_insecure_origin_as_secure, + )?; if args.cert_chain.is_some() || args.private_key.is_some() { let cert_chain = args diff --git a/extensions/tls/Cargo.toml b/extensions/tls/Cargo.toml index ee7be04dc..e75d0bbfe 100644 --- a/extensions/tls/Cargo.toml +++ b/extensions/tls/Cargo.toml @@ -17,7 +17,7 @@ path = "lib.rs" deno_core = { version = "0.95.0", path = "../../core" } lazy_static = "1.4.0" reqwest = { version = "0.11.4", default-features = false, features = ["rustls-tls", "stream", "gzip", "brotli"] } -rustls = "0.19.0" +rustls = { version = "0.19.1", features = ["dangerous_configuration"] } rustls-native-certs = "0.5.0" serde = { version = "1.0.126", features = ["derive"] } webpki = "0.21.4" diff --git a/extensions/tls/lib.rs b/extensions/tls/lib.rs index f91249792..2a15b4e75 100644 --- a/extensions/tls/lib.rs +++ b/extensions/tls/lib.rs @@ -16,20 +16,65 @@ use reqwest::header::HeaderMap; use reqwest::header::USER_AGENT; use reqwest::redirect::Policy; use reqwest::Client; +use rustls::internal::msgs::handshake::DigitallySignedStruct; +use rustls::Certificate; use rustls::ClientConfig; +use rustls::HandshakeSignatureValid; use rustls::RootCertStore; +use rustls::ServerCertVerified; +use rustls::ServerCertVerifier; use rustls::StoresClientSessions; +use rustls::TLSError; use serde::Deserialize; use std::collections::HashMap; use std::io::BufReader; use std::io::Cursor; use std::sync::Arc; +use webpki::DNSNameRef; /// This extension has no runtime apis, it only exports some shared native functions. pub fn init() -> Extension { Extension::builder().build() } +pub struct NoCertificateVerification(pub Vec<String>); + +impl ServerCertVerifier for NoCertificateVerification { + fn verify_server_cert( + &self, + _roots: &RootCertStore, + _presented_certs: &[Certificate], + dns_name: DNSNameRef<'_>, + _ocsp: &[u8], + ) -> Result<ServerCertVerified, TLSError> { + let dns_name: &str = dns_name.into(); + let dns_name: String = dns_name.to_owned(); + if self.0.is_empty() || self.0.contains(&dns_name) { + Ok(ServerCertVerified::assertion()) + } else { + Err(TLSError::General(dns_name)) + } + } + + fn verify_tls12_signature( + &self, + _message: &[u8], + _cert: &Certificate, + _dss: &DigitallySignedStruct, + ) -> Result<HandshakeSignatureValid, TLSError> { + Ok(HandshakeSignatureValid::assertion()) + } + + fn verify_tls13_signature( + &self, + _message: &[u8], + _cert: &Certificate, + _dss: &DigitallySignedStruct, + ) -> Result<HandshakeSignatureValid, TLSError> { + Ok(HandshakeSignatureValid::assertion()) + } +} + #[derive(Deserialize, Default, Debug, Clone)] #[serde(rename_all = "camelCase")] #[serde(default)] @@ -80,6 +125,7 @@ pub fn create_default_root_cert_store() -> RootCertStore { pub fn create_client_config( root_cert_store: Option<RootCertStore>, ca_data: Option<Vec<u8>>, + unsafely_treat_insecure_origin_as_secure: Option<Vec<String>>, ) -> Result<ClientConfig, AnyError> { let mut tls_config = ClientConfig::new(); tls_config.set_persistence(CLIENT_SESSION_MEMORY_CACHE.clone()); @@ -95,6 +141,12 @@ pub fn create_client_config( } } + if let Some(ic_allowlist) = unsafely_treat_insecure_origin_as_secure { + tls_config.dangerous().set_certificate_verifier(Arc::new( + NoCertificateVerification(ic_allowlist), + )); + } + Ok(tls_config) } @@ -105,8 +157,13 @@ pub fn create_http_client( root_cert_store: Option<RootCertStore>, ca_data: Option<Vec<u8>>, proxy: Option<Proxy>, + unsafely_treat_insecure_origin_as_secure: Option<Vec<String>>, ) -> Result<Client, AnyError> { - let tls_config = create_client_config(root_cert_store, ca_data)?; + let tls_config = create_client_config( + root_cert_store, + ca_data, + unsafely_treat_insecure_origin_as_secure, + )?; let mut headers = HeaderMap::new(); headers.insert(USER_AGENT, user_agent.parse().unwrap()); let mut builder = Client::builder() diff --git a/extensions/websocket/lib.rs b/extensions/websocket/lib.rs index 01f0a523d..896a5f2e2 100644 --- a/extensions/websocket/lib.rs +++ b/extensions/websocket/lib.rs @@ -54,6 +54,12 @@ pub trait WebSocketPermissions { fn check_net_url(&mut self, _url: &url::Url) -> Result<(), AnyError>; } +/// `UnsafelyTreatInsecureOriginAsSecure` is a wrapper struct so it can be placed inside `GothamState`; +/// using type alias for a `Option<Vec<String>>` could work, but there's a high chance +/// that there might be another type alias pointing to a `Option<Vec<String>>`, which +/// would override previously used alias. +pub struct UnsafelyTreatInsecureOriginAsSecure(Option<Vec<String>>); + /// For use with `op_websocket_*` when the user does not want permissions. pub struct NoWebSocketPermissions; @@ -197,6 +203,11 @@ where ); } + let unsafely_treat_insecure_origin_as_secure = state + .borrow() + .borrow::<UnsafelyTreatInsecureOriginAsSecure>() + .0 + .clone(); let root_cert_store = state.borrow().borrow::<WsRootStore>().0.clone(); let user_agent = state.borrow().borrow::<WsUserAgent>().0.clone(); let uri: Uri = args.url.parse()?; @@ -221,7 +232,11 @@ where let socket: MaybeTlsStream<TcpStream> = match uri.scheme_str() { Some("ws") => MaybeTlsStream::Plain(tcp_socket), Some("wss") => { - let tls_config = create_client_config(root_cert_store, None)?; + let tls_config = create_client_config( + root_cert_store, + None, + unsafely_treat_insecure_origin_as_secure, + )?; let tls_connector = TlsConnector::from(Arc::new(tls_config)); let dnsname = DNSNameRef::try_from_ascii_str(domain) .map_err(|_| invalid_hostname(domain))?; @@ -377,6 +392,7 @@ pub async fn op_ws_next_event( pub fn init<P: WebSocketPermissions + 'static>( user_agent: String, root_cert_store: Option<RootCertStore>, + unsafely_treat_insecure_origin_as_secure: Option<Vec<String>>, ) -> Extension { Extension::builder() .js(include_js_files!( @@ -395,6 +411,9 @@ pub fn init<P: WebSocketPermissions + 'static>( ]) .state(move |state| { state.put::<WsUserAgent>(WsUserAgent(user_agent.clone())); + state.put(UnsafelyTreatInsecureOriginAsSecure( + unsafely_treat_insecure_origin_as_secure.clone(), + )); state.put::<WsRootStore>(WsRootStore(root_cert_store.clone())); Ok(()) }) |