Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switched to rustls for certificate verification #15329

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Large diffs are not rendered by default.

@@ -12,8 +12,8 @@ path = "lib.rs"
[dependencies]
devtools_traits = {path = "../devtools_traits"}
encoding = "0.2"
hyper = "0.9.9"
hyper_serde = "0.1.4"
hyper = {version = "0.9.9", default-features = false}
hyper_serde = "0.2"
ipc-channel = "0.5"
log = "0.3.5"
msg = {path = "../msg"}
@@ -13,8 +13,8 @@ path = "lib.rs"
bitflags = "0.7"
heapsize = "0.3.0"
heapsize_derive = "0.1"
hyper = "0.9.9"
hyper_serde = "0.1.4"
hyper = {version = "0.9.9", default-features = false}
hyper_serde = "0.2"
ipc-channel = "0.5"
msg = {path = "../msg"}
serde = "0.8"
@@ -10,13 +10,15 @@ name = "net"
path = "lib.rs"

[dependencies]
bitflags = "0.7"
brotli = "1.0.6"
content-blocker = "0.2.1"
cookie = {version = "0.2.5", features = ["serialize-rustc"]}
cookie = {version = "0.4", features = ["serialize-rustc"]}
devtools_traits = {path = "../devtools_traits"}
flate2 = "0.2.0"
hyper = "0.9.9"
hyper_serde = "0.1.4"
hyper = {version = "0.9.9", default-features = false}
hyper_serde = "0.2"
hyper-openssl = "0.1"
immeta = "0.3.1"
ipc-channel = "0.5"
lazy_static = "0.2"
@@ -26,19 +28,24 @@ mime = "0.2.1"
mime_guess = "1.8.0"
msg = {path = "../msg"}
net_traits = {path = "../net_traits"}
openssl = "0.7.6"
openssl-verify = "0.1"
openssl = "0.9"
plugins = {path = "../plugins"}
profile_traits = {path = "../profile_traits"}
rustc-serialize = "0.3"
serde = "0.8"
serde_derive = "0.8"
servo_config = {path = "../config"}
servo_url = {path = "../url"}
threadpool = "1.0"
time = "0.1.17"
unicase = "1.4.0"
url = {version = "1.2", features = ["heap_size", "rustc-serialize"]}
uuid = {version = "0.3.1", features = ["v4"]}
websocket = "0.17"
websocket = {git = "https://github.com/dten/rust-websocket.git", branch = "openssl_0.9.1" }
webpki = "0.8.0"
antidote = "1.0.0"
untrusted = "0.3.1"
rustls = "0.5"

[dependencies.webrender_traits]
git = "https://github.com/servo/webrender"
@@ -2,11 +2,21 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use antidote::Mutex;
use hyper;
use hyper::Result;
use hyper::client::Pool;
use hyper::net::{HttpStream, HttpsConnector, SslClient};
use hyper_openssl;
use openssl;
use openssl::ssl::{SSL_OP_NO_COMPRESSION, SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3, SSL_VERIFY_PEER};
use openssl::ssl::{Ssl, SslContext, SslMethod, SslStream};
use servo_config::resource_files::resources_dir_path;
use openssl::ssl::{Ssl, SslContext, SslContextBuilder, SslMethod};
use openssl::x509::X509StoreContextRef;
use rustls;
use rustls::RootCertStore;
use servo_config::resource_files::resources_dir_path; //FIXME are we using this or the cert file arg
use std::fs::File;
use std::io::BufReader;
use std::sync::Arc;

pub type Connector = HttpsConnector<ServoSslClient>;
@@ -28,33 +38,102 @@ const DEFAULT_CIPHERS: &'static str = concat!(
);

pub fn create_http_connector(certificate_file: &str) -> Arc<Pool<Connector>> {
let mut context = SslContext::new(SslMethod::Sslv23).unwrap();
context.set_CA_file(&resources_dir_path()
.expect("Need certificate file to make network requests")
.join(certificate_file)).unwrap();
let mut context = SslContextBuilder::new(SslMethod::tls()).unwrap();
context.set_ca_file(certificate_file);
context.set_cipher_list(DEFAULT_CIPHERS).unwrap();
context.set_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3 | SSL_OP_NO_COMPRESSION);

//create the rustls root cert store
let ca_pem = File::open(certificate_file).unwrap();
let mut ca_pem = BufReader::new(ca_pem);
let mut root_store = RootCertStore::empty();
root_store.add_pem_file(&mut ca_pem).unwrap().0;

let servo_connector = ServoSslConnector {
context: Arc::new(context.build()),
roots: Arc::new(root_store),
};

let connector = HttpsConnector::new(ServoSslClient {
context: Arc::new(context)
connector: Arc::new(servo_connector),
});

Arc::new(Pool::with_connector(Default::default(), connector))
}

#[derive(Clone)]
pub struct ServoSslClient {
context: Arc<SslContext>,
connector: Arc<ServoSslConnector>,
}

impl SslClient for ServoSslClient {
type Stream = SslStream<HttpStream>;
type Stream = hyper_openssl::SslStream<HttpStream>;

fn wrap_client(&self, stream: HttpStream, host: &str) -> Result<Self::Stream> {
match self.connector.connect(host, stream) {
Ok(stream) => Ok(hyper_openssl::SslStream(Arc::new(Mutex::new(stream)))),
Err(err) => Err(err),
}
}
}

#[derive(Clone)]
pub struct ServoSslConnector {
context: Arc<SslContext>,
roots: Arc<RootCertStore>,
}

impl ServoSslConnector {
pub fn connect(&self, domain: &str, stream: HttpStream) -> Result<openssl::ssl::SslStream<HttpStream>>
{
let mut ssl = Ssl::new(&self.context).unwrap();
ssl.set_hostname(domain).unwrap();
let domain = domain.to_owned();
let roots = self.roots.clone();

fn wrap_client(&self, stream: HttpStream, host: &str) -> Result<Self::Stream, ::hyper::Error> {
let mut ssl = try!(Ssl::new(&self.context));
try!(ssl.set_hostname(host));
let host = host.to_owned();
ssl.set_verify_callback(SSL_VERIFY_PEER, move |p, x| {
::openssl_verify::verify_callback(&host, p, x)
rustls_verify(&domain, &roots, p, x)
});
SslStream::connect(ssl, stream).map_err(From::from)


match ssl.connect(stream) {
Ok(stream) => Ok(stream),
Err(err) => Err(hyper::Error::Ssl(Box::new(err))),
}
}
}

fn rustls_verify(domain: &str,
roots: &RootCertStore,
preverify_ok: bool,
x509_ctx: &X509StoreContextRef) -> bool {
if !preverify_ok || x509_ctx.error_depth() != 0 {
return preverify_ok;
}

// create presented certs
let mut presented_certs = vec!();
match x509_ctx.chain() {
Some(chain) => {
for cert in chain {
presented_certs.push(rustls::Certificate(cert.to_der().unwrap()));
}
},
None => (),
};

// verify certificate
match rustls::parallel_verify_server_cert(&roots, &presented_certs, &domain) {
Ok(_) => true,
Err(error) => { error!("Verification error: {:?}", error);
false },
}

//TODO when to use serial
/*match rustls::verify_server_cert(&roots, &presented_certs, &domain) {
Ok(_) => true,
Err(error) => { error!("Verification error: {:?}", error);
false },
}*/
}

@@ -6,6 +6,7 @@
//! http://tools.ietf.org/html/rfc6265

use cookie_rs;
use hyper;
use net_traits::CookieSource;
use net_traits::pub_domains::is_pub_domain;
use servo_url::ServoUrl;
@@ -89,6 +90,22 @@ impl Cookie {
})
}

pub fn new_wrapped_hyper(cookie: hyper::header::CookiePair, request: &ServoUrl,
source: CookieSource) -> Option<Cookie> {
let cookie = cookie_rs::Cookie {
name: cookie.name,
value: cookie.value,
expires: cookie.expires,
max_age: cookie.max_age,
domain: cookie.domain,
path: cookie.path,
secure: cookie.secure,
httponly: cookie.httponly,
custom: cookie.custom,
};
Cookie::new_wrapped(cookie, request, source)
}

pub fn touch(&mut self) {
self.last_access = now();
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.