Skip to content

Commit

Permalink
Update Hyper and OpenSSL
Browse files Browse the repository at this point in the history
  • Loading branch information
avadacatavra authored and nox committed Mar 31, 2017
1 parent f66cae3 commit e527c9a
Show file tree
Hide file tree
Showing 32 changed files with 296 additions and 394 deletions.
202 changes: 76 additions & 126 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions components/devtools/Cargo.toml
Expand Up @@ -12,8 +12,8 @@ path = "lib.rs"
[dependencies]
devtools_traits = {path = "../devtools_traits"}
encoding = "0.2"
hyper = "0.9.9"
hyper_serde = "0.5"
hyper = "0.10"
hyper_serde = "0.6"
ipc-channel = "0.7"
log = "0.3.5"
msg = {path = "../msg"}
Expand Down
4 changes: 2 additions & 2 deletions components/devtools_traits/Cargo.toml
Expand Up @@ -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.5"
hyper = "0.10"
hyper_serde = "0.6"
ipc-channel = "0.7"
msg = {path = "../msg"}
serde = "0.9"
Expand Down
12 changes: 6 additions & 6 deletions components/net/Cargo.toml
Expand Up @@ -12,11 +12,12 @@ path = "lib.rs"
[dependencies]
base64 = "0.4.1"
brotli = "1.0.6"
cookie = "0.2.5"
cookie = "0.6"
devtools_traits = {path = "../devtools_traits"}
flate2 = "0.2.0"
hyper = "0.9.9"
hyper_serde = "0.5"
hyper = "0.10"
hyper_serde = "0.6"
hyper-openssl = "0.2.2"
immeta = "0.3.1"
ipc-channel = "0.7"
log = "0.3.5"
Expand All @@ -25,15 +26,14 @@ 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"
profile_traits = {path = "../profile_traits"}
serde = "0.9"
serde_derive = "0.9"
serde_json = "0.9"
servo_config = {path = "../config"}
servo_url = {path = "../url"}
servo-websocket = "0.18"
servo-websocket = "0.19"
threadpool = "1.0"
time = "0.1.17"
unicase = "1.4.0"
Expand Down
52 changes: 20 additions & 32 deletions components/net/connector.rs
Expand Up @@ -2,14 +2,15 @@
* 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 hyper;
use hyper::client::Pool;
use hyper::net::{HttpStream, HttpsConnector, SslClient};
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 hyper_openssl;
use openssl::ssl::{SSL_OP_NO_COMPRESSION, SSL_OP_NO_SSLV2, SSL_OP_NO_SSLV3};
use openssl::ssl::{SslConnectorBuilder, SslMethod};
use servo_config::resource_files::resources_dir_path;
use std::sync::Arc;

pub type Connector = HttpsConnector<ServoSslClient>;
pub type Connector = hyper::net::HttpsConnector<hyper_openssl::OpensslClient>;

// The basic logic here is to prefer ciphers with ECDSA certificates, Forward
// Secrecy, AES GCM ciphers, AES ciphers, and finally 3DES ciphers.
Expand All @@ -28,33 +29,20 @@ 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();
context.set_cipher_list(DEFAULT_CIPHERS).unwrap();
context.set_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3 | SSL_OP_NO_COMPRESSION);
let connector = HttpsConnector::new(ServoSslClient {
context: Arc::new(context)
});

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

pub struct ServoSslClient {
context: Arc<SslContext>,
}

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

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)
});
SslStream::connect(ssl, stream).map_err(From::from)
let ca_file = &resources_dir_path()
.expect("Need certificate file to make network requests")
.join(certificate_file);

let mut ssl_connector_builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
{
let context = ssl_connector_builder.builder_mut();
context.set_ca_file(ca_file).expect("could not set CA file");
context.set_cipher_list(DEFAULT_CIPHERS).expect("could not set ciphers");
context.set_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3 | SSL_OP_NO_COMPRESSION);
}
let ssl_connector = ssl_connector_builder.build();
let ssl_client = hyper_openssl::OpensslClient::from(ssl_connector);
let https_connector = hyper::net::HttpsConnector::new(ssl_client);

Arc::new(Pool::with_connector(Default::default(), https_connector))
}
51 changes: 30 additions & 21 deletions components/net/cookie.rs
Expand Up @@ -21,7 +21,7 @@ use time::{Tm, now, at, Duration};
pub struct Cookie {
#[serde(deserialize_with = "hyper_serde::deserialize",
serialize_with = "hyper_serde::serialize")]
pub cookie: cookie_rs::Cookie,
pub cookie: cookie_rs::Cookie<'static>,
pub host_only: bool,
pub persistent: bool,
#[serde(deserialize_with = "hyper_serde::deserialize",
Expand All @@ -34,27 +34,35 @@ pub struct Cookie {
}

impl Cookie {
pub fn from_cookie_string(cookie_str: String, request: &ServoUrl,
source: CookieSource) -> Option<Cookie> {
cookie_rs::Cookie::parse(cookie_str)
.ok()
.map(|cookie| Cookie::new_wrapped(cookie, request, source))
.unwrap_or(None)
}

/// http://tools.ietf.org/html/rfc6265#section-5.3
pub fn new_wrapped(mut cookie: cookie_rs::Cookie, request: &ServoUrl, source: CookieSource)
pub fn new_wrapped(mut cookie: cookie_rs::Cookie<'static>, request: &ServoUrl, source: CookieSource)
-> Option<Cookie> {
// Step 3
let (persistent, expiry_time) = match (&cookie.max_age, &cookie.expires) {
(&Some(max_age), _) => {
(true, Some(at(now().to_timespec() + Duration::seconds(max_age as i64))))
let (persistent, expiry_time) = match (cookie.max_age(), cookie.expires()) {
(Some(max_age), _) => {
(true, Some(at(now().to_timespec() + Duration::seconds(max_age.num_seconds()))))
}
(_, &Some(expires)) => (true, Some(expires)),
(_, Some(expires)) => (true, Some(expires)),
_ => (false, None)
};

let url_host = request.host_str().unwrap_or("").to_owned();

// Step 4
let mut domain = cookie.domain.clone().unwrap_or("".to_owned());
let mut domain = cookie.domain().unwrap_or("").to_owned();

// Step 5
if is_pub_domain(&domain) {
if domain == url_host {
domain = "".to_owned();
domain = "".to_string();
} else {
return None
}
Expand All @@ -65,24 +73,24 @@ impl Cookie {
if !Cookie::domain_match(&url_host, &domain) {
return None;
} else {
cookie.domain = Some(domain);
cookie.set_domain(domain);
false
}
} else {
cookie.domain = Some(url_host);
cookie.set_domain(url_host);
true
};

// Step 7
let mut path = cookie.path.unwrap_or("".to_owned());
let mut path = cookie.path().unwrap_or("").to_owned();
if path.chars().next() != Some('/') {
path = Cookie::default_path(request.path()).to_owned();
path = Cookie::default_path(&request.path().to_owned()).to_string();
}
cookie.path = Some(path);
cookie.set_path(path);


// Step 10
if cookie.httponly && source == CookieSource::NonHTTP {
if cookie.http_only() && source == CookieSource::NonHTTP {
return None;
}

Expand Down Expand Up @@ -139,8 +147,9 @@ impl Cookie {

// http://tools.ietf.org/html/rfc6265#section-5.1.3
pub fn domain_match(string: &str, domain_string: &str) -> bool {
debug_assert!(string.to_lowercase() == string);
debug_assert!(domain_string.to_lowercase() == domain_string);
let string = &string.to_lowercase();
let domain_string = &domain_string.to_lowercase();

string == domain_string ||
(string.ends_with(domain_string) &&
string.as_bytes()[string.len()-domain_string.len()-1] == b'.' &&
Expand All @@ -152,27 +161,27 @@ impl Cookie {
pub fn appropriate_for_url(&self, url: &ServoUrl, source: CookieSource) -> bool {
let domain = url.host_str();
if self.host_only {
if self.cookie.domain.as_ref().map(String::as_str) != domain {
if self.cookie.domain() != domain {
return false;
}
} else {
if let (Some(domain), &Some(ref cookie_domain)) = (domain, &self.cookie.domain) {
if let (Some(domain), &Some(ref cookie_domain)) = (domain, &self.cookie.domain()) {
if !Cookie::domain_match(domain, cookie_domain) {
return false;
}
}
}

if let Some(ref cookie_path) = self.cookie.path {
if let Some(ref cookie_path) = self.cookie.path() {
if !Cookie::path_match(url.path(), cookie_path) {
return false;
}
}

if self.cookie.secure && !url.is_secure_scheme() {
if self.cookie.secure() && !url.is_secure_scheme() {
return false;
}
if self.cookie.httponly && source == CookieSource::NonHTTP {
if self.cookie.http_only() && source == CookieSource::NonHTTP {
return false;
}

Expand Down
50 changes: 25 additions & 25 deletions components/net/cookie_storage.rs
Expand Up @@ -34,20 +34,20 @@ impl CookieStorage {

// http://tools.ietf.org/html/rfc6265#section-5.3
pub fn remove(&mut self, cookie: &Cookie, url: &ServoUrl, source: CookieSource) -> Result<Option<Cookie>, ()> {
let domain = reg_host(cookie.cookie.domain.as_ref().unwrap_or(&"".to_string()));
let domain = reg_host(cookie.cookie.domain().as_ref().unwrap_or(&""));
let cookies = self.cookies_map.entry(domain).or_insert(vec![]);

// https://www.ietf.org/id/draft-ietf-httpbis-cookie-alone-01.txt Step 2
if !cookie.cookie.secure && !url.is_secure_scheme() {
let new_domain = cookie.cookie.domain.as_ref().unwrap();
let new_path = cookie.cookie.path.as_ref().unwrap();
if !cookie.cookie.secure() && !url.is_secure_scheme() {
let new_domain = cookie.cookie.domain().as_ref().unwrap().to_owned();
let new_path = cookie.cookie.path().as_ref().unwrap().to_owned();

let any_overlapping = cookies.iter().any(|c| {
let existing_domain = c.cookie.domain.as_ref().unwrap();
let existing_path = c.cookie.path.as_ref().unwrap();
let existing_domain = c.cookie.domain().as_ref().unwrap().to_owned();
let existing_path = c.cookie.path().as_ref().unwrap().to_owned();

c.cookie.name == cookie.cookie.name &&
c.cookie.secure &&
c.cookie.name() == cookie.cookie.name() &&
c.cookie.secure() &&
(Cookie::domain_match(new_domain, existing_domain) ||
Cookie::domain_match(existing_domain, new_domain)) &&
Cookie::path_match(new_path, existing_path)
Expand All @@ -60,17 +60,17 @@ impl CookieStorage {

// Step 11.1
let position = cookies.iter().position(|c| {
c.cookie.domain == cookie.cookie.domain &&
c.cookie.path == cookie.cookie.path &&
c.cookie.name == cookie.cookie.name
c.cookie.domain() == cookie.cookie.domain() &&
c.cookie.path() == cookie.cookie.path() &&
c.cookie.name() == cookie.cookie.name()
});

if let Some(ind) = position {
// Step 11.4
let c = cookies.remove(ind);

// http://tools.ietf.org/html/rfc6265#section-5.3 step 11.2
if c.cookie.httponly && source == CookieSource::NonHTTP {
if c.cookie.http_only() && source == CookieSource::NonHTTP {
// Undo the removal.
cookies.push(c);
Err(())
Expand All @@ -85,7 +85,7 @@ impl CookieStorage {
// http://tools.ietf.org/html/rfc6265#section-5.3
pub fn push(&mut self, mut cookie: Cookie, url: &ServoUrl, source: CookieSource) {
// https://www.ietf.org/id/draft-ietf-httpbis-cookie-alone-01.txt Step 1
if cookie.cookie.secure && !url.is_secure_scheme() {
if cookie.cookie.secure() && !url.is_secure_scheme() {
return;
}

Expand All @@ -102,7 +102,7 @@ impl CookieStorage {
}

// Step 12
let domain = reg_host(&cookie.cookie.domain.as_ref().unwrap_or(&"".to_string()));
let domain = reg_host(&cookie.cookie.domain().as_ref().unwrap_or(&""));
let mut cookies = self.cookies_map.entry(domain).or_insert(vec![]);

if cookies.len() == self.max_per_host {
Expand All @@ -111,16 +111,16 @@ impl CookieStorage {
let new_len = cookies.len();

// https://www.ietf.org/id/draft-ietf-httpbis-cookie-alone-01.txt
if new_len == old_len && !evict_one_cookie(cookie.cookie.secure, cookies) {
if new_len == old_len && !evict_one_cookie(cookie.cookie.secure(), cookies) {
return;
}
}
cookies.push(cookie);
}

pub fn cookie_comparator(a: &Cookie, b: &Cookie) -> Ordering {
let a_path_len = a.cookie.path.as_ref().map_or(0, |p| p.len());
let b_path_len = b.cookie.path.as_ref().map_or(0, |p| p.len());
let a_path_len = a.cookie.path().as_ref().map_or(0, |p| p.len());
let b_path_len = b.cookie.path().as_ref().map_or(0, |p| p.len());
match a_path_len.cmp(&b_path_len) {
Ordering::Equal => {
let a_creation_time = a.creation_time.to_timespec();
Expand All @@ -137,10 +137,10 @@ impl CookieStorage {
pub fn cookies_for_url(&mut self, url: &ServoUrl, source: CookieSource) -> Option<String> {
let filterer = |c: &&mut Cookie| -> bool {
info!(" === SENT COOKIE : {} {} {:?} {:?}",
c.cookie.name,
c.cookie.value,
c.cookie.domain,
c.cookie.path);
c.cookie.name(),
c.cookie.value(),
c.cookie.domain(),
c.cookie.path());
info!(" === SENT COOKIE RESULT {}",
c.appropriate_for_url(url, source));
// Step 1
Expand All @@ -161,7 +161,7 @@ impl CookieStorage {
(match acc.len() {
0 => acc,
_ => acc + "; ",
}) + &c.cookie.name + "=" + &c.cookie.value
}) + &c.cookie.name() + "=" + &c.cookie.value()
};
let result = url_cookies.iter_mut().fold("".to_owned(), reducer);

Expand All @@ -175,7 +175,7 @@ impl CookieStorage {
pub fn cookies_data_for_url<'a>(&'a mut self,
url: &'a ServoUrl,
source: CookieSource)
-> Box<Iterator<Item = cookie_rs::Cookie> + 'a> {
-> Box<Iterator<Item = cookie_rs::Cookie<'static>> + 'a> {
let domain = reg_host(url.host_str().unwrap_or(""));
let cookies = self.cookies_map.entry(domain).or_insert(vec![]);

Expand All @@ -187,7 +187,7 @@ impl CookieStorage {
}

fn reg_host<'a>(url: &'a str) -> String {
reg_suffix(url).to_string()
reg_suffix(url).to_lowercase()
}

fn is_cookie_expired(cookie: &Cookie) -> bool {
Expand Down Expand Up @@ -219,7 +219,7 @@ fn evict_one_cookie(is_secure_cookie: bool, cookies: &mut Vec<Cookie>) -> bool {
fn get_oldest_accessed(is_secure_cookie: bool, cookies: &mut Vec<Cookie>) -> Option<(usize, Tm)> {
let mut oldest_accessed: Option<(usize, Tm)> = None;
for (i, c) in cookies.iter().enumerate() {
if (c.cookie.secure == is_secure_cookie) &&
if (c.cookie.secure() == is_secure_cookie) &&
oldest_accessed.as_ref().map_or(true, |a| c.last_access < a.1) {
oldest_accessed = Some((i, c.last_access));
}
Expand Down

0 comments on commit e527c9a

Please sign in to comment.