mirror of
https://github.com/servo/servo.git
synced 2025-07-22 14:53:49 +01:00
net: Add an SSL verification callback to support checking a dynamic list of certs.
This commit is contained in:
parent
b7a640b517
commit
1cdaf40eb2
3 changed files with 60 additions and 11 deletions
|
@ -8,8 +8,12 @@ use hyper::client::HttpConnector as HyperHttpConnector;
|
|||
use hyper::rt::Future;
|
||||
use hyper::{Body, Client};
|
||||
use hyper_openssl::HttpsConnector;
|
||||
use openssl::ssl::{SslConnector, SslConnectorBuilder, SslMethod, SslOptions};
|
||||
use openssl::x509;
|
||||
use openssl::ex_data::Index;
|
||||
use openssl::ssl::{
|
||||
SslConnector, SslConnectorBuilder, SslContext, SslMethod, SslOptions, SslVerifyMode,
|
||||
};
|
||||
use openssl::x509::{self, X509StoreContext};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tokio::prelude::future::Executor;
|
||||
|
||||
pub const BUF_SIZE: usize = 32768;
|
||||
|
@ -60,7 +64,20 @@ impl Connect for HttpConnector {
|
|||
pub type Connector = HttpsConnector<HttpConnector>;
|
||||
pub type TlsConfig = SslConnectorBuilder;
|
||||
|
||||
pub fn create_tls_config(certs: &str, alpn: &[u8]) -> TlsConfig {
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ExtraCerts(pub Arc<Mutex<Vec<Vec<u8>>>>);
|
||||
|
||||
impl ExtraCerts {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self(Arc::new(Mutex::new(vec![])))
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref INDEX: Index<SslContext, ExtraCerts> = SslContext::new_ex_index().unwrap();
|
||||
}
|
||||
|
||||
pub(crate) fn create_tls_config(certs: &str, alpn: &[u8], extra_certs: ExtraCerts) -> 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.
|
||||
|
@ -104,6 +121,32 @@ pub fn create_tls_config(certs: &str, alpn: &[u8]) -> TlsConfig {
|
|||
SslOptions::NO_COMPRESSION,
|
||||
);
|
||||
|
||||
cfg.set_ex_data(*INDEX, extra_certs);
|
||||
cfg.set_verify_callback(SslVerifyMode::PEER, |verified, x509_store_context| {
|
||||
if verified {
|
||||
return true;
|
||||
}
|
||||
if let Some(cert) = x509_store_context.current_cert() {
|
||||
match cert.to_pem() {
|
||||
Ok(pem) => {
|
||||
let ssl_idx = X509StoreContext::ssl_idx().unwrap();
|
||||
let ssl = x509_store_context.ex_data(ssl_idx).unwrap();
|
||||
let ssl_context = ssl.ssl_context();
|
||||
let extra_certs = ssl_context.ex_data(*INDEX).unwrap();
|
||||
for cert in &*extra_certs.0.lock().unwrap() {
|
||||
if pem == *cert {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
},
|
||||
Err(_) => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
cfg
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
//! A thread that takes a URL and streams back the binary data.
|
||||
|
||||
use crate::connector::{create_http_client, create_tls_config, ALPN_H2_H1};
|
||||
use crate::connector::{create_http_client, create_tls_config, ExtraCerts, ALPN_H2_H1};
|
||||
use crate::cookie;
|
||||
use crate::cookie_storage::CookieStorage;
|
||||
use crate::fetch::cors_cache::CorsCache;
|
||||
|
@ -127,7 +127,7 @@ struct ResourceChannelManager {
|
|||
fn create_http_states(
|
||||
config_dir: Option<&Path>,
|
||||
certificate_path: Option<String>,
|
||||
) -> (Arc<HttpState>, Arc<HttpState>) {
|
||||
) -> (Arc<HttpState>, Arc<HttpState>, ExtraCerts) {
|
||||
let mut hsts_list = HstsList::from_servo_preload();
|
||||
let mut auth_cache = AuthCache::new();
|
||||
let http_cache = HttpCache::new();
|
||||
|
@ -143,6 +143,8 @@ fn create_http_states(
|
|||
None => resources::read_string(Resource::SSLCertificates),
|
||||
};
|
||||
|
||||
let extra_certs = ExtraCerts::new();
|
||||
|
||||
let http_state = HttpState {
|
||||
hsts_list: RwLock::new(hsts_list),
|
||||
cookie_jar: RwLock::new(cookie_jar),
|
||||
|
@ -151,7 +153,7 @@ 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),
|
||||
create_tls_config(&certs, ALPN_H2_H1, extra_certs.clone()),
|
||||
HANDLE.lock().unwrap().as_ref().unwrap().executor(),
|
||||
),
|
||||
};
|
||||
|
@ -164,12 +166,16 @@ 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),
|
||||
create_tls_config(&certs, ALPN_H2_H1, extra_certs.clone()),
|
||||
HANDLE.lock().unwrap().as_ref().unwrap().executor(),
|
||||
),
|
||||
};
|
||||
|
||||
(Arc::new(http_state), Arc::new(private_http_state))
|
||||
(
|
||||
Arc::new(http_state),
|
||||
Arc::new(private_http_state),
|
||||
extra_certs,
|
||||
)
|
||||
}
|
||||
|
||||
impl ResourceChannelManager {
|
||||
|
@ -180,7 +186,7 @@ impl ResourceChannelManager {
|
|||
private_receiver: IpcReceiver<CoreResourceMsg>,
|
||||
memory_reporter: IpcReceiver<ReportsChan>,
|
||||
) {
|
||||
let (public_http_state, private_http_state) = create_http_states(
|
||||
let (public_http_state, private_http_state, extra_certs) = create_http_states(
|
||||
self.config_dir.as_ref().map(Deref::deref),
|
||||
self.certificate_path.clone(),
|
||||
);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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_tls_config, ALPN_H1};
|
||||
use crate::connector::{create_tls_config, ExtraCerts, ALPN_H1};
|
||||
use crate::cookie::Cookie;
|
||||
use crate::fetch::methods::should_be_blocked_due_to_bad_port;
|
||||
use crate::hosts::replace_host;
|
||||
|
@ -167,7 +167,7 @@ impl<'a> Handler for Client<'a> {
|
|||
WebSocketErrorKind::Protocol,
|
||||
format!("Unable to parse domain from {}. Needed for SSL.", url),
|
||||
))?;
|
||||
let tls_config = create_tls_config(&certs, ALPN_H1);
|
||||
let tls_config = create_tls_config(&certs, ALPN_H1, ExtraCerts::new());
|
||||
tls_config
|
||||
.build()
|
||||
.connect(domain, stream)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue