From f37315b2708e092eaf5177a6960df9f7bf11eb5c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 16 Apr 2016 12:46:25 -0700 Subject: [PATCH] feat(net): Add Ssl impls for security-framework Cloese #755 --- Cargo.toml | 4 ++ src/lib.rs | 2 + src/net.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 86ad78683d..8364187334 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,10 @@ default-features = false version = "0.7" optional = true +[dependencies.security-framework] +version = "0.1.4" +optional = true + [dependencies.solicit] version = "0.4" default-features = false diff --git a/src/lib.rs b/src/lib.rs index 60fde80c11..7f8704c697 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,6 +133,8 @@ extern crate time; extern crate url; #[cfg(feature = "openssl")] extern crate openssl; +#[cfg(feature = "security-framework")] +extern crate security_framework; #[cfg(feature = "serde-serialization")] extern crate serde; extern crate cookie; diff --git a/src/net.rs b/src/net.rs index 6495964c3d..6b4fadd43c 100644 --- a/src/net.rs +++ b/src/net.rs @@ -593,7 +593,7 @@ impl NetworkConnector for HttpsConnector { } -#[cfg(not(feature = "openssl"))] +#[cfg(all(not(feature = "openssl"), not(feature = "security-framework")))] #[doc(hidden)] pub type DefaultConnector = HttpConnector; @@ -601,6 +601,9 @@ pub type DefaultConnector = HttpConnector; #[doc(hidden)] pub type DefaultConnector = HttpsConnector; +#[cfg(all(feature = "security-framework", not(feature = "openssl")))] +pub type DefaultConnector = HttpsConnector; + #[cfg(feature = "openssl")] mod openssl { use std::io; @@ -702,6 +705,116 @@ mod openssl { } } +#[cfg(feature = "security-framework")] +pub mod security_framework { + use std::io; + use std::fmt; + use std::sync::{Arc, Mutex}; + use std::net::{Shutdown, SocketAddr}; + use std::time::Duration; + use security_framework::secure_transport::{SslStream, ClientBuilder, ServerBuilder}; + + use error::Error; + use net::{SslClient, SslServer, HttpStream, NetworkStream}; + + #[derive(Default)] + pub struct ClientWrapper(ClientBuilder); + + impl ClientWrapper { + pub fn new(builder: ClientBuilder) -> ClientWrapper { + ClientWrapper(builder) + } + } + + impl SslClient for ClientWrapper { + type Stream = Stream; + + fn wrap_client(&self, stream: HttpStream, host: &str) -> ::Result { + match self.0.handshake(host, stream) { + Ok(s) => Ok(Stream(Arc::new(Mutex::new(s)))), + Err(e) => Err(Error::Ssl(e.into())), + } + } + } + + #[derive(Clone)] + pub struct ServerWrapper(Arc); + + impl ServerWrapper { + pub fn new(builder: ServerBuilder) -> ServerWrapper { + ServerWrapper(Arc::new(builder)) + } + } + + impl SslServer for ServerWrapper { + type Stream = Stream; + + fn wrap_server(&self, stream: HttpStream) -> ::Result { + match self.0.handshake(stream) { + Ok(s) => Ok(Stream(Arc::new(Mutex::new(s)))), + Err(e) => Err(Error::Ssl(e.into())), + } + } + } + + #[derive(Clone)] + pub struct Stream(Arc>>); + + impl io::Read for Stream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.lock().unwrap_or_else(|e| e.into_inner()).read(buf) + } + + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.0.lock().unwrap_or_else(|e| e.into_inner()).read_to_end(buf) + } + + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + self.0.lock().unwrap_or_else(|e| e.into_inner()).read_to_string(buf) + } + + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + self.0.lock().unwrap_or_else(|e| e.into_inner()).read_exact(buf) + } + } + + impl io::Write for Stream { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.lock().unwrap_or_else(|e| e.into_inner()).write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.0.lock().unwrap_or_else(|e| e.into_inner()).flush() + } + + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.0.lock().unwrap_or_else(|e| e.into_inner()).write_all(buf) + } + + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + self.0.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(fmt) + } + } + + impl NetworkStream for Stream { + fn peer_addr(&mut self) -> io::Result { + self.0.lock().unwrap_or_else(|e| e.into_inner()).get_mut().peer_addr() + } + + fn set_read_timeout(&self, dur: Option) -> io::Result<()> { + self.0.lock().unwrap_or_else(|e| e.into_inner()).get_mut().set_read_timeout(dur) + } + + fn set_write_timeout(&self, dur: Option) -> io::Result<()> { + self.0.lock().unwrap_or_else(|e| e.into_inner()).get_mut().set_write_timeout(dur) + } + + fn close(&mut self, how: Shutdown) -> io::Result<()> { + self.0.lock().unwrap_or_else(|e| e.into_inner()).get_mut().close(how) + } + } +} + #[cfg(test)] mod tests { use mock::MockStream;