Merge pull request #249 from Manishearth/sslcontext

Allow more generic SSL verification (fixes #244)
This commit is contained in:
Sean McArthur
2015-01-15 09:07:09 -08:00
2 changed files with 14 additions and 11 deletions

View File

@@ -25,12 +25,10 @@ use std::iter::Extend;
use url::UrlParser; use url::UrlParser;
use url::ParseError as UrlError; use url::ParseError as UrlError;
use openssl::ssl::VerifyCallback;
use header::{Headers, Header, HeaderFormat}; use header::{Headers, Header, HeaderFormat};
use header::common::{ContentLength, Location}; use header::common::{ContentLength, Location};
use method::Method; use method::Method;
use net::{NetworkConnector, HttpConnector}; use net::{NetworkConnector, HttpConnector, ContextVerifier};
use status::StatusClass::Redirection; use status::StatusClass::Redirection;
use {Url, Port, HttpResult}; use {Url, Port, HttpResult};
use HttpError::HttpUriError; use HttpError::HttpUriError;
@@ -49,15 +47,15 @@ pub struct Client<C> {
redirect_policy: RedirectPolicy, redirect_policy: RedirectPolicy,
} }
impl Client<HttpConnector> { impl<'v> Client<HttpConnector<'v>> {
/// Create a new Client. /// Create a new Client.
pub fn new() -> Client<HttpConnector> { pub fn new() -> Client<HttpConnector<'v>> {
Client::with_connector(HttpConnector(None)) Client::with_connector(HttpConnector(None))
} }
/// Set the SSL verifier callback for use with OpenSSL. /// Set the SSL verifier callback for use with OpenSSL.
pub fn set_ssl_verifier(&mut self, verifier: VerifyCallback) { pub fn set_ssl_verifier(&mut self, verifier: ContextVerifier<'v>) {
self.connector = HttpConnector(Some(verifier)); self.connector = HttpConnector(Some(verifier));
} }

View File

@@ -11,8 +11,8 @@ use std::raw::{self, TraitObject};
use std::sync::Arc; use std::sync::Arc;
use uany::UnsafeAnyExt; use uany::UnsafeAnyExt;
use openssl::ssl::{Ssl, SslStream, SslContext, VerifyCallback}; use openssl::ssl::{Ssl, SslStream, SslContext};
use openssl::ssl::SslVerifyMode::{SslVerifyPeer, SslVerifyNone}; use openssl::ssl::SslVerifyMode::SslVerifyNone;
use openssl::ssl::SslMethod::Sslv23; use openssl::ssl::SslMethod::Sslv23;
use openssl::ssl::error::{SslError, StreamError, OpenSslErrors, SslSessionClosed}; use openssl::ssl::error::{SslError, StreamError, OpenSslErrors, SslSessionClosed};
use openssl::x509::X509FileType; use openssl::x509::X509FileType;
@@ -309,9 +309,12 @@ impl NetworkStream for HttpStream {
/// A connector that will produce HttpStreams. /// A connector that will produce HttpStreams.
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
pub struct HttpConnector(pub Option<VerifyCallback>); pub struct HttpConnector<'v>(pub Option<ContextVerifier<'v>>);
impl NetworkConnector for HttpConnector { /// A method that can set verification methods on an SSL context
pub type ContextVerifier<'v> = Box<FnMut(&mut SslContext) -> ()+'v>;
impl<'v> NetworkConnector for HttpConnector<'v> {
type Stream = HttpStream; type Stream = HttpStream;
fn connect(&mut self, host: &str, port: Port, scheme: &str) -> IoResult<HttpStream> { fn connect(&mut self, host: &str, port: Port, scheme: &str) -> IoResult<HttpStream> {
@@ -325,7 +328,9 @@ impl NetworkConnector for HttpConnector {
debug!("https scheme"); debug!("https scheme");
let stream = try!(TcpStream::connect(addr)); let stream = try!(TcpStream::connect(addr));
let mut context = try!(SslContext::new(Sslv23).map_err(lift_ssl_error)); let mut context = try!(SslContext::new(Sslv23).map_err(lift_ssl_error));
self.0.as_ref().map(|cb| context.set_verify(SslVerifyPeer, Some(*cb))); if let Some(ref mut verifier) = self.0 {
verifier(&mut context);
}
let ssl = try!(Ssl::new(&context).map_err(lift_ssl_error)); let ssl = try!(Ssl::new(&context).map_err(lift_ssl_error));
try!(ssl.set_hostname(host).map_err(lift_ssl_error)); try!(ssl.set_hostname(host).map_err(lift_ssl_error));
let stream = try!(SslStream::new(&context, stream).map_err(lift_ssl_error)); let stream = try!(SslStream::new(&context, stream).map_err(lift_ssl_error));