feat(server,net): Add TLS/SSL support serverside
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 #1
This commit is contained in:
		
							
								
								
									
										39
									
								
								src/net.rs
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/net.rs
									
									
									
									
									
								
							| @@ -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)] | ||||
| @@ -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 { | ||||
| @@ -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)) | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| @@ -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 { | ||||
| @@ -218,7 +236,12 @@ 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) | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
|  | ||||
| @@ -226,7 +249,7 @@ impl NetworkAcceptor for HttpAcceptor { | ||||
|     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(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -234,7 +257,7 @@ impl NetworkAcceptor for HttpAcceptor { | ||||
|     fn socket_name(&self) -> IoResult<SocketAddr> { | ||||
|         match *self { | ||||
|             HttpAcceptor::Http(_, addr) => Ok(addr), | ||||
|             HttpAcceptor::Https(_, addr) => Ok(addr), | ||||
|             HttpAcceptor::Https(_, addr, _) => Ok(addr), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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< | ||||
|   | ||||
		Reference in New Issue
	
	Block a user