Merge pull request #240 from cactorium/ssltry3

Added TLS/SSL support serverside
This commit is contained in:
Sean McArthur
2015-01-12 09:04:23 -08:00
2 changed files with 35 additions and 8 deletions

View File

@@ -8,12 +8,21 @@ use std::io::net::ip::{SocketAddr, ToSocketAddr, Port};
use std::io::net::tcp::{TcpStream, TcpListener, TcpAcceptor}; use std::io::net::tcp::{TcpStream, TcpListener, TcpAcceptor};
use std::mem; use std::mem;
use std::raw::{self, TraitObject}; use std::raw::{self, TraitObject};
use std::sync::Arc;
use uany::UnsafeAnyExt; use uany::UnsafeAnyExt;
use openssl::ssl::{Ssl, SslStream, SslContext, VerifyCallback}; use openssl::ssl::{Ssl, SslStream, SslContext, VerifyCallback};
use openssl::ssl::SslVerifyMode::SslVerifyPeer; use openssl::ssl::SslVerifyMode::{SslVerifyPeer, 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;
macro_rules! try_some {
($expr:expr) => (match $expr {
Some(val) => { return Err(val); },
_ => {}
})
}
/// The write-status indicating headers have not been written. /// The write-status indicating headers have not been written.
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
@@ -184,8 +193,8 @@ impl NetworkStream {
pub enum HttpListener { pub enum HttpListener {
/// Http variant. /// Http variant.
Http, Http,
/// Https variant. /// Https variant. The two paths point to the certificate and key PEM files, in that order.
Https, Https(Path, Path),
} }
impl NetworkListener for HttpListener { impl NetworkListener for HttpListener {
@@ -197,7 +206,16 @@ impl NetworkListener for HttpListener {
let addr = try!(tcp.socket_name()); let addr = try!(tcp.socket_name());
Ok(match *self { Ok(match *self {
HttpListener::Http => HttpAcceptor::Http(try!(tcp.listen()), addr), HttpListener::Http => HttpAcceptor::Http(try!(tcp.listen()), addr),
HttpListener::Https => unimplemented!(), HttpListener::Https(ref cert, ref key) => {
let mut ssl_context = try!(SslContext::new(Sslv23).map_err(lift_ssl_error));
try_some!(ssl_context.set_cipher_list("DEFAULT").map(lift_ssl_error));
try_some!(ssl_context.set_certificate_file(
cert, X509FileType::PEM).map(lift_ssl_error));
try_some!(ssl_context.set_private_key_file(
key, X509FileType::PEM).map(lift_ssl_error));
ssl_context.set_verify(SslVerifyNone, None);
HttpAcceptor::Https(try!(tcp.listen()), addr, Arc::new(ssl_context))
}
}) })
} }
} }
@@ -208,7 +226,7 @@ pub enum HttpAcceptor {
/// Http variant. /// Http variant.
Http(TcpAcceptor, SocketAddr), Http(TcpAcceptor, SocketAddr),
/// Https variant. /// Https variant.
Https(TcpAcceptor, SocketAddr), Https(TcpAcceptor, SocketAddr, Arc<SslContext>),
} }
impl NetworkAcceptor for HttpAcceptor { impl NetworkAcceptor for HttpAcceptor {
@@ -218,7 +236,12 @@ impl NetworkAcceptor for HttpAcceptor {
fn accept(&mut self) -> IoResult<HttpStream> { fn accept(&mut self) -> IoResult<HttpStream> {
Ok(match *self { Ok(match *self {
HttpAcceptor::Http(ref mut tcp, _) => HttpStream::Http(try!(tcp.accept())), HttpAcceptor::Http(ref mut tcp, _) => HttpStream::Http(try!(tcp.accept())),
HttpAcceptor::Https(ref mut _tcp, _) => unimplemented!(), HttpAcceptor::Https(ref mut tcp, _, ref ssl_context) => {
let stream = try!(tcp.accept());
let ssl_stream = try!(SslStream::<TcpStream>::new_server(&**ssl_context, stream).
map_err(lift_ssl_error));
HttpStream::Https(ssl_stream)
}
}) })
} }
@@ -226,7 +249,7 @@ impl NetworkAcceptor for HttpAcceptor {
fn close(&mut self) -> IoResult<()> { fn close(&mut self) -> IoResult<()> {
match *self { match *self {
HttpAcceptor::Http(ref mut tcp, _) => tcp.close_accept(), HttpAcceptor::Http(ref mut tcp, _) => tcp.close_accept(),
HttpAcceptor::Https(ref mut tcp, _) => tcp.close_accept(), HttpAcceptor::Https(ref mut tcp, _, _) => tcp.close_accept(),
} }
} }
@@ -234,7 +257,7 @@ impl NetworkAcceptor for HttpAcceptor {
fn socket_name(&self) -> IoResult<SocketAddr> { fn socket_name(&self) -> IoResult<SocketAddr> {
match *self { match *self {
HttpAcceptor::Http(_, addr) => Ok(addr), HttpAcceptor::Http(_, addr) => Ok(addr),
HttpAcceptor::Https(_, addr) => Ok(addr), HttpAcceptor::Https(_, addr, _) => Ok(addr),
} }
} }
} }

View File

@@ -46,6 +46,10 @@ impl Server<HttpListener> {
pub fn http(ip: IpAddr, port: Port) -> Server { pub fn http(ip: IpAddr, port: Port) -> Server {
Server::with_listener(ip, port, HttpListener::Http) Server::with_listener(ip, port, HttpListener::Http)
} }
/// Creates a new server that will handler `HttpStreams`s using a TLS connection.
pub fn https(ip: IpAddr, port: Port, cert: Path, key: Path) -> Server {
Server::with_listener(ip, port, HttpListener::Https(cert, key))
}
} }
impl< impl<