Skip to content

Commit

Permalink
feat(server,net): Add TLS/SSL support serverside
Browse files Browse the repository at this point in the history
Implements the missing enum cases in Http* and adds a new
method to the default Server implementation to take advantage
of the new TLS support

Closes hyperium#1
  • Loading branch information
cactorium authored and Wright, Jack committed Jan 14, 2015
1 parent a85ba99 commit e04edea
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 8 deletions.
39 changes: 31 additions & 8 deletions src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,21 @@ use std::io::net::ip::{SocketAddr, ToSocketAddr, Port};
use std::io::net::tcp::{TcpStream, TcpListener, TcpAcceptor};
use std::mem;
use std::raw::{self, TraitObject};
use std::sync::Arc;

use uany::UnsafeAnyExt;
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::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.
#[allow(missing_copy_implementations)]
Expand Down Expand Up @@ -184,8 +193,8 @@ impl NetworkStream {
pub enum HttpListener {
/// Http variant.
Http,
/// Https variant.
Https,
/// Https variant. The two paths point to the certificate and key PEM files, in that order.
Https(Path, Path),
}

impl NetworkListener for HttpListener {
Expand All @@ -197,7 +206,16 @@ impl NetworkListener for HttpListener {
let addr = try!(tcp.socket_name());
Ok(match *self {
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))
}
})
}
}
Expand All @@ -208,7 +226,7 @@ pub enum HttpAcceptor {
/// Http variant.
Http(TcpAcceptor, SocketAddr),
/// Https variant.
Https(TcpAcceptor, SocketAddr),
Https(TcpAcceptor, SocketAddr, Arc<SslContext>),
}

impl NetworkAcceptor for HttpAcceptor {
Expand All @@ -218,23 +236,28 @@ impl NetworkAcceptor for HttpAcceptor {
fn accept(&mut self) -> IoResult<HttpStream> {
Ok(match *self {
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)
}
})
}

#[inline]
fn close(&mut self) -> IoResult<()> {
match *self {
HttpAcceptor::Http(ref mut tcp, _) => tcp.close_accept(),
HttpAcceptor::Https(ref mut tcp, _) => tcp.close_accept(),
HttpAcceptor::Https(ref mut tcp, _, _) => tcp.close_accept(),
}
}

#[inline]
fn socket_name(&self) -> IoResult<SocketAddr> {
match *self {
HttpAcceptor::Http(_, addr) => Ok(addr),
HttpAcceptor::Https(_, addr) => Ok(addr),
HttpAcceptor::Https(_, addr, _) => Ok(addr),
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ impl Server<HttpListener> {
pub fn http(ip: IpAddr, port: Port) -> Server {
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<
Expand Down

0 comments on commit e04edea

Please sign in to comment.