From 13c81e9a746fe44f0598a016c6211afbdbc35084 Mon Sep 17 00:00:00 2001 From: Joshua Steffensky Date: Mon, 1 Aug 2016 18:17:33 +0200 Subject: [PATCH 1/5] option for expertmode --- src/tcp.rs | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/tcp.rs b/src/tcp.rs index 6829efb..07bf963 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -3,7 +3,7 @@ use std::io::{self, Read, Write}; use std::net::{SocketAddr, ToSocketAddrs, TcpListener, TcpStream, Shutdown}; use std::time::Duration; -use openssl::ssl::{self, SslContext, SslMethod, Ssl, SslStream}; +use openssl::ssl::{self, SslContext, SslMethod, Ssl, SslStream, SslContextOptions}; use openssl::dh::DH; use openssl::x509::X509FileType; @@ -32,9 +32,14 @@ impl TlsTcpListener { /// Behaves exactly like `TcpStream::bind`. It expects paths to key and certificate files in /// PEM format. pub fn bind(addr: A, key: &str, cert: &str) -> Result { + TlsTcpListener::bind_expert(addr, key, cert, None, None, None) + } + + //new expert bind methode => gives additional options to define sslmethode, ssloptions, and list of ciphers to use + pub fn bind_expert(addr: A, key: &str, cert: &str, method: Option, opts: Option, cipher_list: Option) -> Result { // create listener let listener = try!(TcpListener::bind(addr)); - let ctx = try!(new_ssl_context(&key, &cert)); + let ctx = try!(new_ssl_context(&key, &cert, method, opts, cipher_list)); Ok(TlsTcpListener { listener: listener, ctx: ctx, @@ -113,15 +118,31 @@ impl<'a> Write for &'a TlsTcpStream { } } -fn new_ssl_context(key: &str, cert: &str) -> Result { - let mut ctx = try!(ssl::SslContext::new(SslMethod::Tlsv1_2)); - // use recommended settings - let opts = ssl::SSL_OP_CIPHER_SERVER_PREFERENCE | ssl::SSL_OP_NO_COMPRESSION | - ssl::SSL_OP_NO_TICKET | ssl::SSL_OP_NO_SSLV2 | - ssl::SSL_OP_NO_SSLV3 | ssl::SSL_OP_NO_TLSV1 | ssl::SSL_OP_NO_TLSV1_1; +fn new_ssl_context(key: &str, cert: &str, method: Option, opts: Option, cipher_list: Option) -> Result { + let mut ctx = try!(ssl::SslContext::new( + match method{ + Some(x) => x, + None => SslMethod::Tlsv1_2, //default option + })); + + + let opts = match opts{ + Some(x) => x, + + // use recommended settings => default + None => ssl::SSL_OP_CIPHER_SERVER_PREFERENCE | ssl::SSL_OP_NO_COMPRESSION | + ssl::SSL_OP_NO_TICKET | ssl::SSL_OP_NO_SSLV2 | + ssl::SSL_OP_NO_SSLV3 | ssl::SSL_OP_NO_TLSV1 | ssl::SSL_OP_NO_TLSV1_1, + }; + ctx.set_options(opts); - // set strong cipher suites - try!(ctx.set_cipher_list("ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\ + + + let ciphers = match cipher_list { + Some(x) => x, + + // set strong cipher suites + None => String::from("ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\ ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\ DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:\ @@ -133,7 +154,10 @@ fn new_ssl_context(key: &str, cert: &str) -> Result { ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:\ EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:\ AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:\ - !DSS")); + !DSS"), + }; + + try!(ctx.set_cipher_list(ciphers.as_str())); // enable forward secrecy let dh = try!(DH::get_2048_256()); try!(ctx.set_tmp_dh(dh)); From 5df5c61053e656230413f2df92f378a427f570f2 Mon Sep 17 00:00:00 2001 From: Joshua Steffensky Date: Mon, 1 Aug 2016 18:18:34 +0200 Subject: [PATCH 2/5] add me as author --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a81614a..b05f408 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,8 @@ readme = "README.md" keywords = ["tls", "ssl", "tcp", "crypto"] license = "MIT" -version = "0.2.0" -authors = ["Arturo Vergara "] +version = "0.2.1" +authors = ["Arturo Vergara ", Joshua Steffensky "steffensky@fox4c.com"] [dependencies] openssl = "0.7.6" From aadde0447e03060e9ca409f4fee6975ec6a336bc Mon Sep 17 00:00:00 2001 From: Joshua Steffensky Date: Mon, 1 Aug 2016 18:32:19 +0200 Subject: [PATCH 3/5] fix toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b05f408..927fe40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["tls", "ssl", "tcp", "crypto"] license = "MIT" version = "0.2.1" -authors = ["Arturo Vergara ", Joshua Steffensky "steffensky@fox4c.com"] +authors = ["Arturo Vergara ", "Joshua Steffensky "] [dependencies] openssl = "0.7.6" From 990c7eb1ed719575c630c04088d0f7c47b0a3aff Mon Sep 17 00:00:00 2001 From: Joshua Steffensky Date: Thu, 18 Aug 2016 11:50:59 +0200 Subject: [PATCH 4/5] Init FoxTLS (TODO: docu), moved to MIO instead of std::net --- .gitignore | 2 ++ Cargo.toml | 17 +++++++++-------- LICENSE | 2 +- README.md | 39 +++++++++------------------------------ src/lib.rs | 3 ++- src/tcp.rs | 44 ++++++++++++++++++++++++++++++++------------ src/types.rs | 32 ++++++++++++++++---------------- 7 files changed, 71 insertions(+), 68 deletions(-) diff --git a/.gitignore b/.gitignore index 8ca775c..764202e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ target Cargo.lock *.bk build.sh + +.DS_Store/ diff --git a/Cargo.toml b/Cargo.toml index 927fe40..486b12b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,17 +1,18 @@ [package] -name = "caesar" -description = "A drop-in replacement for the Rust standard library TCP listener with TLSv1.2 enabled." -documentation = "https://arturovm.me/rustdoc/caesar/index.html" -repository = "https://github.com/Postage/caesar" +name = "FoxTLS" +description = "A lightweight non-blocking TLS wrapper for the Rust standard library TCP listener." +documentation = "https://fox4c.github.io/FoxTLS/" +repository = "https://github.com/Fox4c/FoxTLS" readme = "README.md" -keywords = ["tls", "ssl", "tcp", "crypto"] +keywords = ["tls", "ssl", "tcp", "crypto", "mio", "non-blocking"] license = "MIT" -version = "0.2.1" -authors = ["Arturo Vergara ", "Joshua Steffensky "] +version = "0.0.1" +authors = ["Joshua Steffensky "] [dependencies] -openssl = "0.7.6" +openssl = "^0.7.6" +mio = "^0.5.1" [features] default = ["tlsv1_2", "rfc5114"] diff --git a/LICENSE b/LICENSE index 0867607..57e8b51 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Arturo Vergara +Copyright (c) 2015 Fox4c GbR Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 524ae33..bf395bb 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,28 @@ -# Caesar +# FoxTLS -A drop-in replacement for the Rust standard library TCP listener with TLSv1.2 enabled. +FoxTLS is a lightweight non-blocking TLS wrapper for the Rust standard library TCP listener. +It is based on the [Postage/caesar](https://github.com/Postage/caesar). -- [Documentation](https://arturovm.me/rustdoc/caesar/index.html) -- [Crate](https://crates.io/crates/caesar) +- [Documentation](https://fox4c.github.io/FoxTLS/) +- [Crate](https://crates.io/crates/FoxTLS) _Note: This library hasn't been tested._ ## Introduction -This library abstracts over a regular TCP listener from the Rust standard library, and provides a drop-in* interface replacement that layers TLSv1.2 with a set of strong cipher suites on top of the connection. +This library abstracts over a regular TCP listener from the Rust standard library, and provides a drop-in* interface replacement that layers TLS with a set of strong cipher suites on top of the connection. -It uses the [OpenSSL library Rust bindings](https://github.com/sfackler/rust-openssl) by Steven Fackler for the underlying TLS functionality. If you don't trust OpenSSL (I don't), you can compile this crate against LibreSSL (instructions provided below). +It uses the [OpenSSL library Rust bindings](https://github.com/sfackler/rust-openssl) by Steven Fackler for the underlying TLS functionality. _* It's only necessary to prepend `Tls` to the regular types (e.g. `TlsTcpListener`), and write error handling code for the new error types._ -## Compiling -### Prerequisites - -- OpenSSL/LibreSSL headers - -How and where you install these headers depends on your platform. A quick Google search should do the trick. - -### Building - -As described in the [README](https://github.com/sfackler/rust-openssl) for the Rust OpenSSL bindings, there are various ways of compiling this crate, depending on your platform. However, the most universal route, is to configure your build manually with environment variables (and this is required anyway for compiling against LibreSSL). There are only three: - -- `OPENSSL_LIB_DIR`: Use this to specify the path to the _lib_ dir of your SSL library of choice -- `OPENSSL_INCLUDE_DIR`: Use this to specify the path to the _include_ dir of your SSL library of choice -- `OPENSSL_STATIC`: [optional] This is a boolean variable specifying whether to statically link against your SSL library - -The complete command might look something like this: - -```bash -$ env OPENSSL_LIB_DIR="/usr/local/opt/libressl/lib" \ - OPENSSL_INCLUDE_DIR="/usr/local/opt/libressl/include" \ - OPENSSL_STATIC=true cargo build -``` ## Usage -Caesar provides a `CaesarError` enum type, with a variant for I/O errors and another one for SSL errors. You can find the specifics in the library [docs](https://arturovm.me/rustdoc/caesar/index.html). +FoxTLS provides a `FoxTLSError` enum type, with a variant for I/O errors and another one for SSL errors. You can find the specifics in the library [docs](https://fox4c.github.io/FoxTLS/FoxTLS/index.html). ```rust -extern crate caesar; +extern crate FoxTlS; use caesar::{TlsTcpListener, TlsTcpStream}; use std::thread; diff --git a/src/lib.rs b/src/lib.rs index cd1080a..c164067 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,10 +52,11 @@ //! drop(listener); //! ``` +extern crate mio; extern crate openssl; mod types; mod tcp; -pub use types::{Result, CaesarError}; +pub use types::{Result, FoxTLSError}; pub use tcp::*; diff --git a/src/tcp.rs b/src/tcp.rs index 07bf963..eb679e9 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -1,7 +1,8 @@ use std::cell::RefCell; use std::io::{self, Read, Write}; -use std::net::{SocketAddr, ToSocketAddrs, TcpListener, TcpStream, Shutdown}; -use std::time::Duration; +use std::net::{SocketAddr, ToSocketAddrs, Shutdown}; +use mio::tcp::{TcpListener, TcpStream}; +//use std::time::Duration; use openssl::ssl::{self, SslContext, SslMethod, Ssl, SslStream, SslContextOptions}; use openssl::dh::DH; @@ -9,7 +10,7 @@ use openssl::x509::X509FileType; use super::types::Result; -/// Abstracts over a `TcpListener`, and layers TLSv1.2 on top. +/// Abstracts over a `TcpListener`, and layers TLS on top. #[derive(Debug)] pub struct TlsTcpListener { listener: TcpListener, @@ -37,8 +38,9 @@ impl TlsTcpListener { //new expert bind methode => gives additional options to define sslmethode, ssloptions, and list of ciphers to use pub fn bind_expert(addr: A, key: &str, cert: &str, method: Option, opts: Option, cipher_list: Option) -> Result { + let sockaddr = try!(addr.to_socket_addrs()).next().unwrap(); // create listener - let listener = try!(TcpListener::bind(addr)); + let listener = try!(TcpListener::bind(&sockaddr)); let ctx = try!(new_ssl_context(&key, &cert, method, opts, cipher_list)); Ok(TlsTcpListener { listener: listener, @@ -46,14 +48,18 @@ impl TlsTcpListener { }) } - pub fn accept(&self) -> Result<(TlsTcpStream, SocketAddr)> { + pub fn accept(&self) -> Result> { // acept from bare TCP stream - let (stream, addr) = try!(self.listener.accept()); + let acceptoption = try!(self.listener.accept()); + let (stream, addr) = match acceptoption{ + Some((s,a)) => (s,a), + None => return Ok(None), + }; // create SSL object with stored context let ssl = try!(Ssl::new(&self.ctx)); // accept from encrypted stream let tls_stream = try!(SslStream::accept(ssl, stream)); - Ok((TlsTcpStream(RefCell::new(tls_stream)), addr)) + Ok(Some((TlsTcpStream(RefCell::new(tls_stream)), addr))) } pub fn incoming(&self) -> Incoming { @@ -64,7 +70,24 @@ impl TlsTcpListener { impl<'a> Iterator for Incoming<'a> { type Item = Result; fn next(&mut self) -> Option> { - Some(self.listener.accept().map(|p| p.0)) + let mut tmp: Option<(TlsTcpStream, SocketAddr)> = match self.listener.accept() { + Err(x) => return Some(Err(x)), + Ok(x) => x, + }; + + loop{ + match tmp{ + None => tmp = match self.listener.accept(){ + Err(x) => return Some(Err(x)), + Ok(x) => x, + }, + Some(_) => break, + } + } + + let (stream, _) = tmp.unwrap(); + + Some(Ok(stream)) } } @@ -80,10 +103,7 @@ impl TlsTcpStream { pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.borrow().get_ref().shutdown(how) } - - pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { - self.0.borrow().get_ref().set_read_timeout(dur) - } + } impl Read for TlsTcpStream { diff --git a/src/types.rs b/src/types.rs index 19efcbf..4058714 100644 --- a/src/types.rs +++ b/src/types.rs @@ -4,46 +4,46 @@ use std::convert::From; use openssl::ssl::error::SslError; #[derive(Debug)] -pub enum CaesarError { +pub enum FoxTLSError { Ssl(SslError), Io(io::Error), } -pub type Result = result::Result; +pub type Result = result::Result; -impl fmt::Display for CaesarError { +impl fmt::Display for FoxTLSError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - CaesarError::Ssl(ref e) => write!(f, "SSL error: {}", e), - CaesarError::Io(ref e) => write!(f, "IO error: {}", e), + FoxTLSError::Ssl(ref e) => write!(f, "SSL error: {}", e), + FoxTLSError::Io(ref e) => write!(f, "IO error: {}", e), } } } -impl error::Error for CaesarError { +impl error::Error for FoxTLSError { fn description(&self) -> &str { match *self { - CaesarError::Ssl(ref e) => e.description(), - CaesarError::Io(ref e) => e.description(), + FoxTLSError::Ssl(ref e) => e.description(), + FoxTLSError::Io(ref e) => e.description(), } } fn cause(&self) -> Option<&error::Error> { match *self { - CaesarError::Ssl(ref e) => Some(e), - CaesarError::Io(ref e) => Some(e), + FoxTLSError::Ssl(ref e) => Some(e), + FoxTLSError::Io(ref e) => Some(e), } } } -impl From for CaesarError { - fn from(err: SslError) -> CaesarError { - CaesarError::Ssl(err) +impl From for FoxTLSError { + fn from(err: SslError) -> FoxTLSError { + FoxTLSError::Ssl(err) } } -impl From for CaesarError { - fn from(err: io::Error) -> CaesarError { - CaesarError::Io(err) +impl From for FoxTLSError { + fn from(err: io::Error) -> FoxTLSError { + FoxTLSError::Io(err) } } From 739c1719ded4dbe4ac092edc27f820e6c5c54b68 Mon Sep 17 00:00:00 2001 From: Joshua Steffensky Date: Thu, 18 Aug 2016 11:56:10 +0200 Subject: [PATCH 5/5] packagename lower case --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 486b12b..9a57ef6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "FoxTLS" +name = "foxtls" description = "A lightweight non-blocking TLS wrapper for the Rust standard library TCP listener." documentation = "https://fox4c.github.io/FoxTLS/" repository = "https://github.com/Fox4c/FoxTLS"