fix certificate tampered

This commit is contained in:
Toshit Chawda 2024-09-07 13:34:30 -07:00
parent 5aeea21d29
commit 7c02aecc27
No known key found for this signature in database
GPG key ID: 91480ED99E2B3D9D
3 changed files with 106 additions and 31 deletions

View file

@ -201,6 +201,7 @@ cfg_if! {
pub user_agent: String,
#[wasm_bindgen(getter_with_clone)]
pub pem_files: Vec<String>,
pub disable_certificate_validation: bool,
}
} else {
#[wasm_bindgen]
@ -212,6 +213,7 @@ cfg_if! {
pub redirect_limit: usize,
#[wasm_bindgen(getter_with_clone)]
pub user_agent: String,
pub disable_certificate_validation: bool,
}
}
}
@ -234,6 +236,7 @@ impl Default for EpoxyClientOptions {
user_agent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36".to_string(),
#[cfg(feature = "full")]
pem_files: Vec::new(),
disable_certificate_validation: false,
}
}
}
@ -366,9 +369,9 @@ impl EpoxyClient {
redirect_limit: options.redirect_limit,
user_agent: options.user_agent,
#[cfg(feature = "full")]
certs_tampered: !options.pem_files.is_empty(),
certs_tampered: options.disable_certificate_validation || !options.pem_files.is_empty(),
#[cfg(not(feature = "full"))]
certs_tampered: false,
certs_tampered: options.disable_certificate_validation,
})
}
@ -605,10 +608,9 @@ impl EpoxyClient {
.await?;
if self.certs_tampered {
response.headers_mut().insert(
HeaderName::from_static("X-Epoxy-CertsTampered"),
HeaderValue::from_static("true"),
);
response
.headers_mut()
.insert("X-Epoxy-CertsTampered", HeaderValue::from_static("true"));
}
let response_headers: Array = response
@ -688,11 +690,11 @@ impl EpoxyClient {
if jv.is_array() {
let arr = Array::from(&jv);
arr.push(&v);
object_set(&raw_headers, &k, arr.into());
object_set(&raw_headers, k, arr.into());
} else if jv.is_truthy() {
object_set(&raw_headers, &k, Array::of2(&jv, &v).into());
object_set(&raw_headers, k, Array::of2(&jv, &v).into());
} else {
object_set(&raw_headers, &k, v);
object_set(&raw_headers, k, v);
}
}
utils::define_property(&resp, "rawHeaders", raw_headers.into());

View file

@ -2,7 +2,7 @@ use std::{io::ErrorKind, pin::Pin, sync::Arc, task::Poll};
use cfg_if::cfg_if;
use futures_rustls::{
rustls::{ClientConfig, RootCertStore},
rustls::{crypto::ring::default_provider, ClientConfig, RootCertStore},
TlsConnector,
};
use futures_util::{
@ -20,7 +20,11 @@ use wisp_mux::{
ClientMux, MuxStreamAsyncRW, MuxStreamIo, StreamType,
};
use crate::{console_log, utils::IgnoreCloseNotify, EpoxyClientOptions, EpoxyError};
use crate::{
console_log,
utils::{IgnoreCloseNotify, NoCertificateVerification},
EpoxyClientOptions, EpoxyError,
};
pub type ProviderUnencryptedStream = MuxStreamIo;
pub type ProviderUnencryptedAsyncRW = MuxStreamAsyncRW;
@ -60,27 +64,33 @@ impl StreamProvider {
wisp_generator: ProviderWispTransportGenerator,
options: &EpoxyClientOptions,
) -> Result<Self, EpoxyError> {
cfg_if! {
if #[cfg(feature = "full")] {
let pems: Result<Result<Vec<_>, webpki::Error>, std::io::Error> = options
.pem_files
.iter()
.flat_map(|x| {
rustls_pemfile::certs(&mut std::io::BufReader::new(x.as_bytes()))
.map(|x| x.map(|x| webpki::anchor_from_trusted_cert(&x).map(|x| x.to_owned())))
.collect::<Vec<_>>()
})
.collect();
let pems = pems.map_err(EpoxyError::Pemfile)??;
let certstore = RootCertStore::from_iter(pems.into_iter().chain(TLS_SERVER_ROOTS.iter().cloned()));
} else {
let certstore = RootCertStore::from_iter(TLS_SERVER_ROOTS.iter().cloned());
let client_config = if options.disable_certificate_validation {
ClientConfig::builder()
.dangerous()
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification::new(
default_provider(),
)))
} else {
cfg_if! {
if #[cfg(feature = "full")] {
let pems: Result<Result<Vec<_>, webpki::Error>, std::io::Error> = options
.pem_files
.iter()
.flat_map(|x| {
rustls_pemfile::certs(&mut std::io::BufReader::new(x.as_bytes()))
.map(|x| x.map(|x| webpki::anchor_from_trusted_cert(&x).map(|x| x.to_owned())))
.collect::<Vec<_>>()
})
.collect();
let pems = pems.map_err(EpoxyError::Pemfile)??;
let certstore = RootCertStore::from_iter(pems.into_iter().chain(TLS_SERVER_ROOTS.iter().cloned()));
} else {
let certstore = RootCertStore::from_iter(TLS_SERVER_ROOTS.iter().cloned());
}
}
ClientConfig::builder().with_root_certificates(certstore)
}
let client_config = ClientConfig::builder()
.with_root_certificates(certstore)
.with_no_client_auth();
.with_no_client_auth();
let client_config = Arc::new(client_config);
Ok(Self {

View file

@ -6,12 +6,21 @@ use std::{
use async_trait::async_trait;
use bytes::{buf::UninitSlice, BufMut, Bytes, BytesMut};
use futures_rustls::TlsStream;
use futures_rustls::{
rustls::{
self,
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
crypto::{verify_tls12_signature, verify_tls13_signature, CryptoProvider},
DigitallySignedStruct, SignatureScheme,
},
TlsStream,
};
use futures_util::{ready, AsyncRead, AsyncWrite, Future, Stream, StreamExt, TryStreamExt};
use http::{HeaderValue, Uri};
use hyper::{body::Body, rt::Executor};
use js_sys::{Array, ArrayBuffer, JsString, Object, Uint8Array};
use pin_project_lite::pin_project;
use rustls_pki_types::{CertificateDer, ServerName, UnixTime};
use send_wrapper::SendWrapper;
use wasm_bindgen::{prelude::*, JsCast, JsValue};
use wasm_bindgen_futures::JsFuture;
@ -300,6 +309,60 @@ impl AsyncWrite for IgnoreCloseNotify {
}
}
#[derive(Debug)]
pub struct NoCertificateVerification(CryptoProvider);
impl NoCertificateVerification {
pub fn new(provider: CryptoProvider) -> Self {
Self(provider)
}
}
impl ServerCertVerifier for NoCertificateVerification {
fn verify_server_cert(
&self,
_end_entity: &CertificateDer<'_>,
_intermediates: &[CertificateDer<'_>],
_server_name: &ServerName<'_>,
_ocsp: &[u8],
_now: UnixTime,
) -> Result<ServerCertVerified, rustls::Error> {
Ok(ServerCertVerified::assertion())
}
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
verify_tls12_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
}
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
verify_tls13_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
self.0.signature_verification_algorithms.supported_schemes()
}
}
pub fn is_redirect(code: u16) -> bool {
[301, 302, 303, 307, 308].contains(&code)
}