From d0b769c93c623d308c02cb5d86726f4c9607f5f4 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Jun 2015 15:11:11 -0700 Subject: [PATCH 01/33] Move macro replicas into C shim --- openssl-sys/build.rs | 10 ++-- openssl-sys/src/lib.rs | 46 +++++++------------ .../{old_openssl_shim.c => openssl_shim.c} | 31 +++++++++++++ openssl/src/bio/mod.rs | 2 +- 4 files changed, 53 insertions(+), 36 deletions(-) rename openssl-sys/src/{old_openssl_shim.c => openssl_shim.c} (65%) diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index de43c462..e788af5d 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -15,7 +15,7 @@ fn main() { if lib_dir.is_none() && include_dir.is_none() { if let Ok(info) = pkg_config::find_library("openssl") { - build_old_openssl_shim(&info.include_paths); + build_openssl_shim(&info.include_paths); return; } if let Some(mingw_paths) = get_mingw_in_path() { @@ -58,18 +58,18 @@ fn main() { include_dirs.push(PathBuf::from(&include_dir)); } - build_old_openssl_shim(&include_dirs); + build_openssl_shim(&include_dirs); } -fn build_old_openssl_shim(include_paths: &[PathBuf]) { +fn build_openssl_shim(include_paths: &[PathBuf]) { let mut config = gcc::Config::new(); for path in include_paths { config.include(path); } - config.file("src/old_openssl_shim.c") - .compile("libold_openssl_shim.a"); + config.file("src/openssl_shim.c") + .compile("libopenssl_shim.a"); } fn get_mingw_in_path() -> Option> { diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index d77264be..ce8e6e37 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -9,7 +9,6 @@ extern crate libressl_pnacl_sys; use libc::{c_void, c_int, c_char, c_ulong, c_long, c_uint, c_uchar, size_t}; use std::mem; -use std::ptr; use std::sync::{Mutex, MutexGuard}; use std::sync::{Once, ONCE_INIT}; @@ -263,35 +262,6 @@ pub fn init() { } } -// Functions converted from macros -pub unsafe fn BIO_eof(b: *mut BIO) -> bool { - BIO_ctrl(b, BIO_CTRL_EOF, 0, ptr::null_mut()) == 1 -} - -pub unsafe fn SSL_CTX_set_options(ssl: *mut SSL_CTX, op: c_long) -> c_long { - SSL_CTX_ctrl(ssl, SSL_CTRL_OPTIONS, op, ptr::null_mut()) -} - -pub unsafe fn BIO_set_mem_eof_return(b: *mut BIO, v: c_int) { - BIO_ctrl(b, BIO_C_SET_BUF_MEM_EOF_RETURN, v as c_long, ptr::null_mut()); -} - -pub unsafe fn SSL_CTX_get_options(ssl: *mut SSL_CTX) -> c_long { - SSL_CTX_ctrl(ssl, SSL_CTRL_OPTIONS, 0, ptr::null_mut()) -} - -pub unsafe fn SSL_CTX_clear_options(ssl: *mut SSL_CTX, op: c_long) -> c_long { - SSL_CTX_ctrl(ssl, SSL_CTRL_CLEAR_OPTIONS, (op), ptr::null_mut()) -} - -pub unsafe fn SSL_CTX_add_extra_chain_cert(ssl: *mut SSL_CTX, cert: *mut X509) -> c_long { - SSL_CTX_ctrl(ssl, SSL_CTRL_EXTRA_CHAIN_CERT, 0, cert) -} - -pub unsafe fn SSL_CTX_set_read_ahead(ctx: *mut SSL_CTX, m: c_long) -> c_long { - SSL_CTX_ctrl(ctx, SSL_CTRL_SET_READ_AHEAD, m, ptr::null_mut()) -} - // True functions extern "C" { pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int; @@ -610,6 +580,22 @@ extern "C" { pub fn d2i_RSA_PUBKEY(k: *const *mut RSA, buf: *const *const u8, len: c_uint) -> *mut RSA; pub fn i2d_RSAPrivateKey(k: *mut RSA, buf: *const *mut u8) -> c_int; pub fn d2i_RSAPrivateKey(k: *const *mut RSA, buf: *const *const u8, len: c_uint) -> *mut RSA; + + // These functions are defined in OpenSSL as macros, so we shim them + #[link_name = "BIO_eof_shim"] + pub fn BIO_eof(b: *mut BIO) -> c_int; + #[link_name = "BIO_set_mem_eof_return_shim"] + pub fn BIO_set_mem_eof_return(b: *mut BIO, v: c_int); + #[link_name = "SSL_CTX_set_options_shim"] + pub fn SSL_CTX_set_options(ctx: *mut SSL_CTX, options: c_long) -> c_long; + #[link_name = "SSL_CTX_get_options_shim"] + pub fn SSL_CTX_get_options(ctx: *mut SSL_CTX) -> c_long; + #[link_name = "SSL_CTX_clear_options_shim"] + pub fn SSL_CTX_clear_options(ctx: *mut SSL_CTX, options: c_long) -> c_long; + #[link_name = "SSL_CTX_add_extra_chain_cert_shim"] + pub fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -> c_long; + #[link_name = "SSL_CTX_set_read_ahead_shim"] + pub fn SSL_CTX_set_read_ahead(ctx: *mut SSL_CTX, m: c_long) -> c_long; } pub mod probe; diff --git a/openssl-sys/src/old_openssl_shim.c b/openssl-sys/src/openssl_shim.c similarity index 65% rename from openssl-sys/src/old_openssl_shim.c rename to openssl-sys/src/openssl_shim.c index 19ce74fc..9b4a9fa2 100644 --- a/openssl-sys/src/old_openssl_shim.c +++ b/openssl-sys/src/openssl_shim.c @@ -1,4 +1,5 @@ #include +#include #if OPENSSL_VERSION_NUMBER < 0x1000000L // Copied from openssl crypto/hmac/hmac.c @@ -47,3 +48,33 @@ int HMAC_Final_shim(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) { return HMAC_Final(ctx, md, len); } #endif + +// shims for OpenSSL macros + +int BIO_eof_shim(BIO *b) { + return BIO_eof(b); +} + +void BIO_set_mem_eof_return_shim(BIO *b, int v) { + BIO_set_mem_eof_return(b, v); +} + +long SSL_CTX_set_options_shim(SSL_CTX *ctx, long options) { + return SSL_CTX_set_options(ctx, options); +} + +long SSL_CTX_get_options_shim(SSL_CTX *ctx) { + return SSL_CTX_get_options(ctx); +} + +long SSL_CTX_clear_options_shim(SSL_CTX *ctx, long options) { + return SSL_CTX_clear_options(ctx, options); +} + +long SSL_CTX_add_extra_chain_cert_shim(SSL_CTX *ctx, X509 *x509) { + return SSL_CTX_add_extra_chain_cert(ctx, x509); +} + +long SSL_CTX_set_read_ahead_shim(SSL_CTX *ctx, long m) { + return SSL_CTX_set_read_ahead(ctx, m); +} diff --git a/openssl/src/bio/mod.rs b/openssl/src/bio/mod.rs index e81694a4..e0a7d0c9 100644 --- a/openssl/src/bio/mod.rs +++ b/openssl/src/bio/mod.rs @@ -73,7 +73,7 @@ impl Read for MemBio { if ret <= 0 { let is_eof = unsafe { ffi::BIO_eof(self.bio) }; - if is_eof { + if is_eof != 0 { Ok(0) } else { Err(io::Error::new(io::ErrorKind::Other, From cb7248d8cb1596f48cb916fe36aa3be2d7b91164 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Jun 2015 15:23:19 -0700 Subject: [PATCH 02/33] Import shim'd HMAC stuff with the original name --- openssl-sys/src/lib.rs | 10 ++++++++++ openssl/src/crypto/hmac.rs | 18 +++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index ce8e6e37..20185e5a 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -415,10 +415,20 @@ extern "C" { pub fn HMAC_CTX_copy(dst: *mut HMAC_CTX, src: *const HMAC_CTX) -> c_int; // Pre-1.0 versions of these didn't return anything, so the shims bridge that gap + #[cfg_attr(not(target_os = "nacl"), link_name = "HMAC_Init_ex_shim")] + pub fn HMAC_Init_ex(ctx: *mut HMAC_CTX, key: *const u8, keylen: c_int, md: *const EVP_MD, imple: *const ENGINE) -> c_int; + #[cfg_attr(not(target_os = "nacl"), link_name = "HMAC_Final_shim")] + pub fn HMAC_Final(ctx: *mut HMAC_CTX, output: *mut u8, len: *mut c_uint) -> c_int; + #[cfg_attr(not(target_os = "nacl"), link_name = "HMAC_Update_shim")] + pub fn HMAC_Update(ctx: *mut HMAC_CTX, input: *const u8, len: c_uint) -> c_int; + + /// Deprecated - use the non "_shim" version #[cfg_attr(target_os = "nacl", link_name = "HMAC_Init_ex")] pub fn HMAC_Init_ex_shim(ctx: *mut HMAC_CTX, key: *const u8, keylen: c_int, md: *const EVP_MD, imple: *const ENGINE) -> c_int; + /// Deprecated - use the non "_shim" version #[cfg_attr(target_os = "nacl", link_name = "HMAC_Final")] pub fn HMAC_Final_shim(ctx: *mut HMAC_CTX, output: *mut u8, len: *mut c_uint) -> c_int; + /// Deprecated - use the non "_shim" version #[cfg_attr(target_os = "nacl", link_name = "HMAC_Update")] pub fn HMAC_Update_shim(ctx: *mut HMAC_CTX, input: *const u8, len: c_uint) -> c_int; diff --git a/openssl/src/crypto/hmac.rs b/openssl/src/crypto/hmac.rs index a59cb929..5c9f7576 100644 --- a/openssl/src/crypto/hmac.rs +++ b/openssl/src/crypto/hmac.rs @@ -88,9 +88,9 @@ impl HMAC { #[inline] fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) { unsafe { - let r = ffi::HMAC_Init_ex_shim(&mut self.ctx, - key.as_ptr(), key.len() as c_int, - md, 0 as *const _); + let r = ffi::HMAC_Init_ex(&mut self.ctx, + key.as_ptr(), key.len() as c_int, + md, 0 as *const _); assert_eq!(r, 1); } self.state = Reset; @@ -106,9 +106,9 @@ impl HMAC { // If the key and/or md is not supplied it's reused from the last time // avoiding redundant initializations unsafe { - let r = ffi::HMAC_Init_ex_shim(&mut self.ctx, - 0 as *const _, 0, - 0 as *const _, 0 as *const _); + let r = ffi::HMAC_Init_ex(&mut self.ctx, + 0 as *const _, 0, + 0 as *const _, 0 as *const _); assert_eq!(r, 1); } self.state = Reset; @@ -120,7 +120,7 @@ impl HMAC { self.init(); } unsafe { - let r = ffi::HMAC_Update_shim(&mut self.ctx, data.as_ptr(), data.len() as c_uint); + let r = ffi::HMAC_Update(&mut self.ctx, data.as_ptr(), data.len() as c_uint); assert_eq!(r, 1); } self.state = Updated; @@ -135,7 +135,7 @@ impl HMAC { let mut res: Vec = repeat(0).take(md_len).collect(); unsafe { let mut len = 0; - let r = ffi::HMAC_Final_shim(&mut self.ctx, res.as_mut_ptr(), &mut len); + let r = ffi::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len); self.state = Finalized; assert_eq!(len as usize, md_len); assert_eq!(r, 1); @@ -181,7 +181,7 @@ impl Drop for HMAC { if self.state != Finalized { let mut buf: Vec = repeat(0).take(self.type_.md_len()).collect(); let mut len = 0; - ffi::HMAC_Final_shim(&mut self.ctx, buf.as_mut_ptr(), &mut len); + ffi::HMAC_Final(&mut self.ctx, buf.as_mut_ptr(), &mut len); } ffi::HMAC_CTX_cleanup(&mut self.ctx); } From 645430602d0f4d56c6ab153b68a11c6be6d8b183 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Jun 2015 15:45:48 -0700 Subject: [PATCH 03/33] Don't build a custom openssl on OSX I don't believe the bugfix the required this is needed anymore --- .travis.yml | 4 +--- openssl/test/build.sh | 10 ---------- 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100755 openssl/test/build.sh diff --git a/.travis.yml b/.travis.yml index e8bf79e9..2a8eee47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,8 @@ rust: os: - osx - linux -before_install: -- (test $TRAVIS_OS_NAME == "osx" || ./openssl/test/build.sh) before_script: - ./openssl/test/test.sh script: -- (cd openssl && LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test) +- (cd openssl && cargo test) - (test $TRAVIS_OS_NAME == "osx" || (cd openssl && LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES")) diff --git a/openssl/test/build.sh b/openssl/test/build.sh deleted file mode 100755 index 27def60a..00000000 --- a/openssl/test/build.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -e - -mkdir /tmp/openssl -cd /tmp/openssl -sudo apt-get install gcc make -curl https://openssl.org/source/openssl-1.0.2-latest.tar.gz | tar --strip-components=1 -xzf - -./config --prefix=/usr/ shared -make -sudo make install From cb89b23a157d55eb36910287d3b88ba70b5c4178 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Jun 2015 15:53:40 -0700 Subject: [PATCH 04/33] Strip other LD_LIBRARY_PATH reference --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2a8eee47..4d0379b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,4 @@ before_script: - ./openssl/test/test.sh script: - (cd openssl && cargo test) -- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES")) +- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && cargo test --features "$FEATURES")) From 9d0acfe6155e1f432a80d0bfa99efbbdf0b07100 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Jun 2015 19:37:45 -0700 Subject: [PATCH 05/33] Fix set_hostname It was previously failing to null terminate the hostname string (was anyone actually using this?). Also move the macro expansion to the C shim. --- openssl-sys/src/lib.rs | 2 ++ openssl-sys/src/openssl_shim.c | 4 ++++ openssl/src/ssl/mod.rs | 12 ++---------- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 20185e5a..5204c3bf 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -606,6 +606,8 @@ extern "C" { pub fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -> c_long; #[link_name = "SSL_CTX_set_read_ahead_shim"] pub fn SSL_CTX_set_read_ahead(ctx: *mut SSL_CTX, m: c_long) -> c_long; + #[link_name = "SSL_set_tlsext_host_name_shim"] + pub fn SSL_set_tlsext_host_name(s: *mut SSL, name: *const c_char) -> c_long; } pub mod probe; diff --git a/openssl-sys/src/openssl_shim.c b/openssl-sys/src/openssl_shim.c index 9b4a9fa2..7b4f9c74 100644 --- a/openssl-sys/src/openssl_shim.c +++ b/openssl-sys/src/openssl_shim.c @@ -78,3 +78,7 @@ long SSL_CTX_add_extra_chain_cert_shim(SSL_CTX *ctx, X509 *x509) { long SSL_CTX_set_read_ahead_shim(SSL_CTX *ctx, long m) { return SSL_CTX_set_read_ahead(ctx, m); } + +long SSL_set_tlsext_host_name_shim(SSL *s, char *name) { + return SSL_set_tlsext_host_name(s, name); +} diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index a0f97b17..57635523 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -655,16 +655,8 @@ impl Ssl { /// Set the host name to be used with SNI (Server Name Indication). pub fn set_hostname(&self, hostname: &str) -> Result<(), SslError> { - let ret = unsafe { - // This is defined as a macro: - // #define SSL_set_tlsext_host_name(s,name) \ - // SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name) - - let hostname = CString::new(hostname.as_bytes()).unwrap(); - ffi::SSL_ctrl(self.ssl, ffi::SSL_CTRL_SET_TLSEXT_HOSTNAME, - ffi::TLSEXT_NAMETYPE_host_name, - hostname.as_ptr() as *mut c_void) - }; + let cstr = CString::new(hostname).unwrap(); + let ret = unsafe { ffi::SSL_set_tlsext_host_name(self.ssl, cstr.as_ptr()) }; // For this case, 0 indicates failure. if ret == 0 { From a80a77bbb8b6c969c053cdbd56d83faa6de15e0f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Jun 2015 19:42:13 -0700 Subject: [PATCH 06/33] Initialize stream buffer --- openssl/src/ssl/mod.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 57635523..fbad7dcc 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -5,6 +5,7 @@ use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::io::prelude::*; +use std::iter; use std::mem; use std::net; use std::path::Path; @@ -770,14 +771,7 @@ impl SslStream { stream: stream, ssl: Arc::new(ssl), // Maximum TLS record size is 16k - // We're just using this as a buffer, so there's no reason to pay - // to memset it - buf: { - const CAP: usize = 16 * 1024; - let mut v = Vec::with_capacity(CAP); - unsafe { v.set_len(CAP); } - v - } + buf: iter::repeat(0).take(16 * 1024).collect(), } } From 0cff370f1d4e46145bc9047508a7e63402b10adc Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Jun 2015 21:40:00 -0700 Subject: [PATCH 07/33] Reduce SslStream constructor duplication --- openssl-sys/src/lib.rs | 1 + openssl/src/bio/mod.rs | 6 ++--- openssl/src/ssl/mod.rs | 57 +++++++++++++++++++++++++++------------- openssl/src/ssl/tests.rs | 46 ++++++++++++++++---------------- 4 files changed, 65 insertions(+), 45 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 5204c3bf..b347b949 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -271,6 +271,7 @@ extern "C" { pub fn BIO_ctrl(b: *mut BIO, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long; pub fn BIO_free_all(b: *mut BIO); pub fn BIO_new(type_: *const BIO_METHOD) -> *mut BIO; + pub fn BIO_new_socket(sock: c_int, close_flag: c_int) -> *mut BIO; pub fn BIO_read(b: *mut BIO, buf: *mut c_void, len: c_int) -> c_int; pub fn BIO_write(b: *mut BIO, buf: *const c_void, len: c_int) -> c_int; pub fn BIO_s_mem() -> *const BIO_METHOD; diff --git a/openssl/src/bio/mod.rs b/openssl/src/bio/mod.rs index e0a7d0c9..7eea16d8 100644 --- a/openssl/src/bio/mod.rs +++ b/openssl/src/bio/mod.rs @@ -76,8 +76,7 @@ impl Read for MemBio { if is_eof != 0 { Ok(0) } else { - Err(io::Error::new(io::ErrorKind::Other, - SslError::get())) + Err(io::Error::new(io::ErrorKind::Other, SslError::get())) } } else { Ok(ret as usize) @@ -93,8 +92,7 @@ impl Write for MemBio { }; if ret < 0 { - Err(io::Error::new(io::ErrorKind::Other, - SslError::get())) + Err(io::Error::new(io::ErrorKind::Other, SslError::get())) } else { Ok(ret as usize) } diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index fbad7dcc..0768fead 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -496,7 +496,7 @@ impl SslContext { pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(),SslError> { wrap_ssl_result( unsafe { - let cipher_list = CString::new(cipher_list.as_bytes()).unwrap(); + let cipher_list = CString::new(cipher_list).unwrap(); ffi::SSL_CTX_set_cipher_list(self.ctx, cipher_list.as_ptr()) }) } @@ -766,36 +766,41 @@ impl fmt::Debug for SslStream where S: fmt::Debug { } impl SslStream { - fn new_base(ssl:Ssl, stream: S) -> SslStream { - SslStream { + fn new_base(ssl: T, stream: S) -> Result, SslError> { + let ssl = try!(ssl.into_ssl()); + Ok(SslStream { stream: stream, ssl: Arc::new(ssl), // Maximum TLS record size is 16k buf: iter::repeat(0).take(16 * 1024).collect(), - } + }) } + pub fn new_client(ssl: T, stream: S) -> Result, SslError> { + let mut ssl = try!(SslStream::new_base(ssl, stream)); + try!(ssl.in_retry_wrapper(|ssl| ssl.connect())); + Ok(ssl) + } + + pub fn new_server(ssl: T, stream: S) -> Result, SslError> { + let mut ssl = try!(SslStream::new_base(ssl, stream)); + try!(ssl.in_retry_wrapper(|ssl| ssl.accept())); + Ok(ssl) + } + + /// # Deprecated pub fn new_server_from(ssl: Ssl, stream: S) -> Result, SslError> { - let mut ssl = SslStream::new_base(ssl, stream); - ssl.in_retry_wrapper(|ssl| { ssl.accept() }).and(Ok(ssl)) + SslStream::new_server(ssl, stream) } - /// Attempts to create a new SSL stream from a given `Ssl` instance. + /// # Deprecated pub fn new_from(ssl: Ssl, stream: S) -> Result, SslError> { - let mut ssl = SslStream::new_base(ssl, stream); - ssl.in_retry_wrapper(|ssl| { ssl.connect() }).and(Ok(ssl)) + SslStream::new_client(ssl, stream) } - /// Creates a new SSL stream + /// # Deprecated pub fn new(ctx: &SslContext, stream: S) -> Result, SslError> { - let ssl = try!(Ssl::new(ctx)); - SslStream::new_from(ssl, stream) - } - - /// Creates a new SSL server stream - pub fn new_server(ctx: &SslContext, stream: S) -> Result, SslError> { - let ssl = try!(Ssl::new(ctx)); - SslStream::new_server_from(ssl, stream) + SslStream::new_client(ctx, stream) } #[doc(hidden)] @@ -920,6 +925,22 @@ impl Write for SslStream { } } +pub trait IntoSsl { + fn into_ssl(self) -> Result; +} + +impl IntoSsl for Ssl { + fn into_ssl(self) -> Result { + Ok(self) + } +} + +impl<'a> IntoSsl for &'a SslContext { + fn into_ssl(self) -> Result { + Ssl::new(self) + } +} + /// A utility type to help in cases where the use of SSL is decided at runtime. #[derive(Debug)] pub enum MaybeSslStream where S: Read+Write { diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index dcaee215..a0e4a9d6 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -83,14 +83,14 @@ run_test!(new_ctx, |method, _| { }); run_test!(new_sslstream, |method, stream| { - SslStream::new(&SslContext::new(method).unwrap(), stream).unwrap(); + SslStream::new_client(&SslContext::new(method).unwrap(), stream).unwrap(); }); run_test!(verify_untrusted, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, None); - match SslStream::new(&ctx, stream) { + match SslStream::new_client(&ctx, stream) { Ok(_) => panic!("expected failure"), Err(err) => println!("error {:?}", err) } @@ -104,7 +104,7 @@ run_test!(verify_trusted, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - match SslStream::new(&ctx, stream) { + match SslStream::new_client(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -118,7 +118,7 @@ run_test!(verify_untrusted_callback_override_ok, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - match SslStream::new(&ctx, stream) { + match SslStream::new_client(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -132,7 +132,7 @@ run_test!(verify_untrusted_callback_override_bad, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::new(&ctx, stream).is_err()); + assert!(SslStream::new_client(&ctx, stream).is_err()); }); run_test!(verify_trusted_callback_override_ok, |method, stream| { @@ -147,7 +147,7 @@ run_test!(verify_trusted_callback_override_ok, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - match SslStream::new(&ctx, stream) { + match SslStream::new_client(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -165,7 +165,7 @@ run_test!(verify_trusted_callback_override_bad, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - assert!(SslStream::new(&ctx, stream).is_err()); + assert!(SslStream::new_client(&ctx, stream).is_err()); }); run_test!(verify_callback_load_certs, |method, stream| { @@ -177,7 +177,7 @@ run_test!(verify_callback_load_certs, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::new(&ctx, stream).is_ok()); + assert!(SslStream::new_client(&ctx, stream).is_ok()); }); run_test!(verify_trusted_get_error_ok, |method, stream| { @@ -193,7 +193,7 @@ run_test!(verify_trusted_get_error_ok, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - assert!(SslStream::new(&ctx, stream).is_ok()); + assert!(SslStream::new_client(&ctx, stream).is_ok()); }); run_test!(verify_trusted_get_error_err, |method, stream| { @@ -205,7 +205,7 @@ run_test!(verify_trusted_get_error_err, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::new(&ctx, stream).is_err()); + assert!(SslStream::new_client(&ctx, stream).is_err()); }); run_test!(verify_callback_data, |method, stream| { @@ -230,7 +230,7 @@ run_test!(verify_callback_data, |method, stream| { ctx.set_verify_with_data(SSL_VERIFY_PEER, callback, node_id); ctx.set_verify_depth(1); - match SslStream::new(&ctx, stream) { + match SslStream::new_client(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -245,7 +245,7 @@ fn test_write_hits_stream() { let guard = thread::spawn(move || { let ctx = SslContext::new(Sslv23).unwrap(); let stream = TcpStream::connect(addr).unwrap(); - let mut stream = SslStream::new(&ctx, stream).unwrap(); + let mut stream = SslStream::new_client(&ctx, stream).unwrap(); stream.write_all(b"hello").unwrap(); stream @@ -310,7 +310,7 @@ run_test!(clear_ctx_options, |method, _| { #[test] fn test_write() { let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::new(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let mut stream = SslStream::new_client(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -319,7 +319,7 @@ fn test_write() { run_test!(get_peer_certificate, |method, stream| { //let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); - let stream = SslStream::new(&SslContext::new(method).unwrap(), stream).unwrap(); + let stream = SslStream::new_client(&SslContext::new(method).unwrap(), stream).unwrap(); let cert = stream.get_peer_certificate().unwrap(); let fingerprint = cert.fingerprint(SHA256).unwrap(); let node_hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b"; @@ -333,7 +333,7 @@ fn test_write_dtlsv1() { let sock = UdpSocket::bind("127.0.0.1:0").unwrap(); let stream = sock.connect("127.0.0.1:15410").unwrap(); - let mut stream = SslStream::new(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::new_client(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -343,7 +343,7 @@ fn test_write_dtlsv1() { #[test] fn test_read() { let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::new(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::new_client(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); @@ -353,7 +353,7 @@ fn test_read() { #[test] fn test_pending() { let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::new(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::new_client(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); @@ -386,7 +386,7 @@ fn test_connect_with_unilateral_npn() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - let stream = match SslStream::new(&ctx, stream) { + let stream = match SslStream::new_client(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -410,7 +410,7 @@ fn test_connect_with_npn_successful_multiple_matching() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - let stream = match SslStream::new(&ctx, stream) { + let stream = match SslStream::new_client(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -435,7 +435,7 @@ fn test_connect_with_npn_successful_single_match() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - let stream = match SslStream::new(&ctx, stream) { + let stream = match SslStream::new_client(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -477,7 +477,7 @@ fn test_npn_server_advertise_multiple() { } // Now connect to the socket and make sure the protocol negotiation works... let stream = TcpStream::connect(localhost).unwrap(); - let stream = match SslStream::new(&ctx, stream) { + let stream = match SslStream::new_client(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -514,7 +514,7 @@ fn test_read_dtlsv1() { let server = udp::next_server(); let stream = sock.connect(&server[..]).unwrap(); - let mut stream = SslStream::new(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::new_client(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); let mut buf = [0u8;100]; assert!(stream.read(&mut buf).is_ok()); } @@ -523,5 +523,5 @@ fn test_read_dtlsv1() { #[cfg(feature = "sslv2")] fn test_sslv2_connect_failure() { let tcp = TcpStream::connect("127.0.0.1:15420").unwrap(); - SslStream::new(&SslContext::new(Sslv2).unwrap(), tcp).err().unwrap(); + SslStream::new_client(&SslContext::new(Sslv2).unwrap(), tcp).err().unwrap(); } From c722f889c1e4962dc7793a881d37b07aedc6f02f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Jun 2015 21:40:55 -0700 Subject: [PATCH 08/33] Docs tweak --- openssl/src/ssl/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 0768fead..cb4448b8 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -803,6 +803,7 @@ impl SslStream { SslStream::new_client(ctx, stream) } + /// # Deprecated #[doc(hidden)] pub fn get_inner(&mut self) -> &mut S { self.get_mut() @@ -823,7 +824,7 @@ impl SslStream { /// ## Warning /// /// It is inadvisable to read from or write to the underlying stream as it - /// will most likely desynchronize the SSL session. + /// will most likely corrupt the SSL session. pub fn get_mut(&mut self) -> &mut S { &mut self.stream } From 9b235a7b9121613780810b0bc7b4d1f30dc861c9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Jun 2015 22:37:10 -0700 Subject: [PATCH 09/33] Prepare for direct stream support --- openssl/src/ssl/mod.rs | 263 +++++++++++++++++++++++++++-------------- 1 file changed, 175 insertions(+), 88 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index cb4448b8..18acf7f8 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -5,7 +5,6 @@ use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::io::prelude::*; -use std::iter; use std::mem; use std::net; use std::path::Path; @@ -740,97 +739,57 @@ make_LibSslError! { ErrorWantAccept = SSL_ERROR_WANT_ACCEPT } -/// A stream wrapper which handles SSL encryption for an underlying stream. -#[derive(Clone)] -pub struct SslStream { +struct IndirectStream { stream: S, ssl: Arc, - buf: Vec + // Max TLS record size is 16k + buf: Box<[u8; 16 * 1024]>, } -impl SslStream { - /// Create a new independently owned handle to the underlying socket. - pub fn try_clone(&self) -> io::Result> { - Ok(SslStream { +impl Clone for IndirectStream { + fn clone(&self) -> IndirectStream { + IndirectStream { + stream: self.stream.clone(), + ssl: self.ssl.clone(), + buf: Box::new(*self.buf) + } + } +} + +impl IndirectStream { + fn try_clone(&self) -> io::Result> { + Ok(IndirectStream { stream: try!(self.stream.try_clone()), ssl: self.ssl.clone(), - buf: self.buf.clone(), + buf: Box::new(*self.buf) }) } } -impl fmt::Debug for SslStream where S: fmt::Debug { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "SslStream {{ stream: {:?}, ssl: {:?} }}", self.stream, self.ssl) - } -} - -impl SslStream { - fn new_base(ssl: T, stream: S) -> Result, SslError> { +impl IndirectStream { + fn new_base(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); - Ok(SslStream { + Ok(IndirectStream { stream: stream, ssl: Arc::new(ssl), - // Maximum TLS record size is 16k - buf: iter::repeat(0).take(16 * 1024).collect(), + buf: Box::new([0; 16 * 1024]), }) } - pub fn new_client(ssl: T, stream: S) -> Result, SslError> { - let mut ssl = try!(SslStream::new_base(ssl, stream)); + fn new_client(ssl: T, stream: S) -> Result, SslError> { + let mut ssl = try!(IndirectStream::new_base(ssl, stream)); try!(ssl.in_retry_wrapper(|ssl| ssl.connect())); Ok(ssl) } - pub fn new_server(ssl: T, stream: S) -> Result, SslError> { - let mut ssl = try!(SslStream::new_base(ssl, stream)); + fn new_server(ssl: T, stream: S) -> Result, SslError> { + let mut ssl = try!(IndirectStream::new_base(ssl, stream)); try!(ssl.in_retry_wrapper(|ssl| ssl.accept())); Ok(ssl) } - /// # Deprecated - pub fn new_server_from(ssl: Ssl, stream: S) -> Result, SslError> { - SslStream::new_server(ssl, stream) - } - - /// # Deprecated - pub fn new_from(ssl: Ssl, stream: S) -> Result, SslError> { - SslStream::new_client(ssl, stream) - } - - /// # Deprecated - pub fn new(ctx: &SslContext, stream: S) -> Result, SslError> { - SslStream::new_client(ctx, stream) - } - - /// # Deprecated - #[doc(hidden)] - pub fn get_inner(&mut self) -> &mut S { - self.get_mut() - } - - /// Returns a reference to the underlying stream. - pub fn get_ref(&self) -> &S { - &self.stream - } - - /// Return the certificate of the peer - pub fn get_peer_certificate(&self) -> Option { - self.ssl.get_peer_certificate() - } - - /// Returns a mutable reference to the underlying stream. - /// - /// ## Warning - /// - /// It is inadvisable to read from or write to the underlying stream as it - /// will most likely corrupt the SSL session. - pub fn get_mut(&mut self) -> &mut S { - &mut self.stream - } - - fn in_retry_wrapper(&mut self, mut blk: F) - -> Result where F: FnMut(&Ssl) -> c_int { + fn in_retry_wrapper(&mut self, mut blk: F) -> Result + where F: FnMut(&Ssl) -> c_int { loop { let ret = blk(&self.ssl); if ret > 0 { @@ -860,12 +819,149 @@ impl SslStream { fn write_through(&mut self) -> io::Result<()> { io::copy(&mut *self.ssl.get_wbio(), &mut self.stream).map(|_| ()) } +} + +impl Read for IndirectStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + match self.in_retry_wrapper(|ssl| { ssl.read(buf) }) { + Ok(len) => Ok(len as usize), + Err(SslSessionClosed) => Ok(0), + Err(StreamError(e)) => Err(e), + Err(e @ OpenSslErrors(_)) => { + Err(io::Error::new(io::ErrorKind::Other, e)) + } + } + } +} + +impl Write for IndirectStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + let count = match self.in_retry_wrapper(|ssl| ssl.write(buf)) { + Ok(len) => len as usize, + Err(SslSessionClosed) => 0, + Err(StreamError(e)) => return Err(e), + Err(e @ OpenSslErrors(_)) => return Err(io::Error::new(io::ErrorKind::Other, e)), + }; + try!(self.write_through()); + Ok(count) + } + + fn flush(&mut self) -> io::Result<()> { + try!(self.write_through()); + self.stream.flush() + } +} + +#[derive(Clone)] +enum StreamKind { + Indirect(IndirectStream), +} + +impl StreamKind { + fn stream(&self) -> &S { + match *self { + StreamKind::Indirect(ref s) => &s.stream + } + } + + fn mut_stream(&mut self) -> &mut S { + match *self { + StreamKind::Indirect(ref mut s) => &mut s.stream + } + } + + fn ssl(&self) -> &Ssl { + match *self { + StreamKind::Indirect(ref s) => &s.ssl + } + } +} + +/// A stream wrapper which handles SSL encryption for an underlying stream. +#[derive(Clone)] +pub struct SslStream { + kind: StreamKind, +} + +impl SslStream { + /// Create a new independently owned handle to the underlying socket. + pub fn try_clone(&self) -> io::Result> { + let kind = match self.kind { + StreamKind::Indirect(ref s) => StreamKind::Indirect(try!(s.try_clone())) + }; + Ok(SslStream { + kind: kind + }) + } +} + +impl fmt::Debug for SslStream where S: fmt::Debug { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "SslStream {{ stream: {:?}, ssl: {:?} }}", self.kind.stream(), self.kind.ssl()) + } +} + +impl SslStream { + pub fn new_client(ssl: T, stream: S) -> Result, SslError> { + let stream = try!(IndirectStream::new_client(ssl, stream)); + Ok(SslStream { + kind: StreamKind::Indirect(stream) + }) + } + + pub fn new_server(ssl: T, stream: S) -> Result, SslError> { + let stream = try!(IndirectStream::new_server(ssl, stream)); + Ok(SslStream { + kind: StreamKind::Indirect(stream) + }) + } + + /// # Deprecated + pub fn new_server_from(ssl: Ssl, stream: S) -> Result, SslError> { + SslStream::new_server(ssl, stream) + } + + /// # Deprecated + pub fn new_from(ssl: Ssl, stream: S) -> Result, SslError> { + SslStream::new_client(ssl, stream) + } + + /// # Deprecated + pub fn new(ctx: &SslContext, stream: S) -> Result, SslError> { + SslStream::new_client(ctx, stream) + } + + /// # Deprecated + #[doc(hidden)] + pub fn get_inner(&mut self) -> &mut S { + self.get_mut() + } + + /// Returns a reference to the underlying stream. + pub fn get_ref(&self) -> &S { + self.kind.stream() + } + + /// Return the certificate of the peer + pub fn get_peer_certificate(&self) -> Option { + self.kind.ssl().get_peer_certificate() + } + + /// Returns a mutable reference to the underlying stream. + /// + /// ## Warning + /// + /// It is inadvisable to read from or write to the underlying stream as it + /// will most likely corrupt the SSL session. + pub fn get_mut(&mut self) -> &mut S { + self.kind.mut_stream() + } /// Get the compression currently in use. The result will be /// either None, indicating no compression is in use, or a string /// with the compression name. pub fn get_compression(&self) -> Option { - let ptr = unsafe { ffi::SSL_get_current_compression(self.ssl.ssl) }; + let ptr = unsafe { ffi::SSL_get_current_compression(self.kind.ssl().ssl) }; if ptr == ptr::null() { return None; } @@ -886,43 +982,34 @@ impl SslStream { /// This method needs the `npn` feature. #[cfg(feature = "npn")] pub fn get_selected_npn_protocol(&self) -> Option<&[u8]> { - self.ssl.get_selected_npn_protocol() + self.kind.ssl().get_selected_npn_protocol() } /// pending() takes into account only bytes from the TLS/SSL record that is currently being processed (if any). pub fn pending(&self) -> usize { - self.ssl.pending() + self.kind.ssl().pending() } } impl Read for SslStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { - match self.in_retry_wrapper(|ssl| { ssl.read(buf) }) { - Ok(len) => Ok(len as usize), - Err(SslSessionClosed) => Ok(0), - Err(StreamError(e)) => Err(e), - Err(e @ OpenSslErrors(_)) => { - Err(io::Error::new(io::ErrorKind::Other, e)) - } + match self.kind { + StreamKind::Indirect(ref mut s) => s.read(buf) } } } impl Write for SslStream { fn write(&mut self, buf: &[u8]) -> io::Result { - let count = match self.in_retry_wrapper(|ssl| ssl.write(buf)) { - Ok(len) => len as usize, - Err(SslSessionClosed) => 0, - Err(StreamError(e)) => return Err(e), - Err(e @ OpenSslErrors(_)) => return Err(io::Error::new(io::ErrorKind::Other, e)), - }; - try!(self.write_through()); - Ok(count) + match self.kind { + StreamKind::Indirect(ref mut s) => s.write(buf) + } } fn flush(&mut self) -> io::Result<()> { - try!(self.write_through()); - self.stream.flush() + match self.kind { + StreamKind::Indirect(ref mut s) => s.flush() + } } } From 1373a76ce12d6a856b6caae7457ceb3eb5ad4122 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Jun 2015 00:06:14 -0700 Subject: [PATCH 10/33] Implement direct IO support --- openssl/src/ssl/mod.rs | 181 ++++++++++++++++++++++++++++++++++++--- openssl/src/ssl/tests.rs | 19 +++- 2 files changed, 187 insertions(+), 13 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 18acf7f8..0e1e5b30 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -603,11 +603,6 @@ impl Ssl { return Err(SslError::get()); } let ssl = Ssl { ssl: ssl }; - - let rbio = try!(MemBio::new()); - let wbio = try!(MemBio::new()); - - unsafe { ffi::SSL_set_bio(ssl.ssl, rbio.unwrap(), wbio.unwrap()) } Ok(ssl) } @@ -769,6 +764,12 @@ impl IndirectStream { impl IndirectStream { fn new_base(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); + + let rbio = try!(MemBio::new()); + let wbio = try!(MemBio::new()); + + unsafe { ffi::SSL_set_bio(ssl.ssl, rbio.unwrap(), wbio.unwrap()) } + Ok(IndirectStream { stream: stream, ssl: Arc::new(ssl), @@ -852,27 +853,139 @@ impl Write for IndirectStream { } } +#[derive(Clone)] +struct DirectStream { + stream: S, + ssl: Arc, +} + +impl DirectStream { + fn try_clone(&self) -> io::Result> { + Ok(DirectStream { + stream: try!(self.stream.try_clone()), + ssl: self.ssl.clone(), + }) + } +} + +impl DirectStream { + fn new_base(ssl: Ssl, stream: S, sock: c_int) -> Result, SslError> { + unsafe { + let bio = ffi::BIO_new_socket(sock, 0); + if bio == ptr::null_mut() { + return Err(SslError::get()); + } + ffi::SSL_set_bio(ssl.ssl, bio, bio); + } + + Ok(DirectStream { + stream: stream, + ssl: Arc::new(ssl), + }) + } + + fn new_client(ssl: Ssl, stream: S, sock: c_int) -> Result, SslError> { + let ssl = try!(DirectStream::new_base(ssl, stream, sock)); + let ret = ssl.ssl.connect(); + if ret > 0 { + Ok(ssl) + } else { + Err(ssl.make_error(ret)) + } + } + + fn new_server(ssl: Ssl, stream: S, sock: c_int) -> Result, SslError> { + let ssl = try!(DirectStream::new_base(ssl, stream, sock)); + let ret = ssl.ssl.accept(); + if ret > 0 { + Ok(ssl) + } else { + Err(ssl.make_error(ret)) + } + } + + fn make_error(&self, ret: c_int) -> SslError { + match self.ssl.get_error(ret) { + LibSslError::ErrorSsl => SslError::get(), + LibSslError::ErrorSyscall => { + let err = SslError::get(); + let count = match err { + SslError::OpenSslErrors(ref v) => v.len(), + _ => unreachable!(), + }; + if count == 0 { + if ret == 0 { + SslError::StreamError(io::Error::new(io::ErrorKind::ConnectionAborted, + "unexpected EOF observed")) + } else { + SslError::StreamError(io::Error::last_os_error()) + } + } else { + err + } + } + err => panic!("unexpected error {:?} with ret {}", err, ret), + } + } +} + +impl Read for DirectStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let ret = self.ssl.read(buf); + if ret >= 0 { + return Ok(ret as usize); + } + + match self.make_error(ret) { + SslError::StreamError(e) => Err(e), + e => Err(io::Error::new(io::ErrorKind::Other, e)), + } + } +} + +impl Write for DirectStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + let ret = self.ssl.write(buf); + if ret > 0 { + return Ok(ret as usize); + } + + match self.make_error(ret) { + SslError::StreamError(e) => Err(e), + e => Err(io::Error::new(io::ErrorKind::Other, e)), + } + } + + fn flush(&mut self) -> io::Result<()> { + self.stream.flush() + } +} + #[derive(Clone)] enum StreamKind { Indirect(IndirectStream), + Direct(DirectStream), } impl StreamKind { fn stream(&self) -> &S { match *self { - StreamKind::Indirect(ref s) => &s.stream + StreamKind::Indirect(ref s) => &s.stream, + StreamKind::Direct(ref s) => &s.stream, } } fn mut_stream(&mut self) -> &mut S { match *self { - StreamKind::Indirect(ref mut s) => &mut s.stream + StreamKind::Indirect(ref mut s) => &mut s.stream, + StreamKind::Direct(ref mut s) => &mut s.stream, } } fn ssl(&self) -> &Ssl { match *self { - StreamKind::Indirect(ref s) => &s.ssl + StreamKind::Indirect(ref s) => &s.ssl, + StreamKind::Direct(ref s) => &s.ssl, } } } @@ -887,7 +1000,8 @@ impl SslStream { /// Create a new independently owned handle to the underlying socket. pub fn try_clone(&self) -> io::Result> { let kind = match self.kind { - StreamKind::Indirect(ref s) => StreamKind::Indirect(try!(s.try_clone())) + StreamKind::Indirect(ref s) => StreamKind::Indirect(try!(s.try_clone())), + StreamKind::Direct(ref s) => StreamKind::Direct(try!(s.try_clone())) }; Ok(SslStream { kind: kind @@ -901,6 +1015,46 @@ impl fmt::Debug for SslStream where S: fmt::Debug { } } +#[cfg(unix)] +impl SslStream { + pub fn new_client_direct(ssl: T, stream: S) -> Result, SslError> { + let ssl = try!(ssl.into_ssl()); + let fd = stream.as_raw_fd() as c_int; + let stream = try!(DirectStream::new_client(ssl, stream, fd)); + Ok(SslStream { + kind: StreamKind::Direct(stream) + }) + } + + pub fn new_server_direct(ssl: T, stream: S) -> Result, SslError> { + let ssl = try!(ssl.into_ssl()); + let fd = stream.as_raw_fd() as c_int; + let stream = try!(DirectStream::new_server(ssl, stream, fd)); + Ok(SslStream { + kind: StreamKind::Direct(stream) + }) + } +} + +#[cfg(windows)] +impl SslStream { + pub fn new_client_direct(ssl: T, stream: S) -> Result, SslError> { + let fd = stream.as_raw_socket() as c_int; + let stream = try!(DirectStream::new_client(ssl, stream, fd)); + Ok(SslStream { + kind: StreamKind::Direct(stream) + }) + } + + pub fn new_server_direct(ssl: T, stream: S) -> Result, SslError> { + let fd = stream.as_raw_socket() as c_int; + let stream = try!(DirectStream::new_server(ssl, stream, fd)); + Ok(SslStream { + kind: StreamKind::Direct(stream) + }) + } +} + impl SslStream { pub fn new_client(ssl: T, stream: S) -> Result, SslError> { let stream = try!(IndirectStream::new_client(ssl, stream)); @@ -994,7 +1148,8 @@ impl SslStream { impl Read for SslStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self.kind { - StreamKind::Indirect(ref mut s) => s.read(buf) + StreamKind::Indirect(ref mut s) => s.read(buf), + StreamKind::Direct(ref mut s) => s.read(buf), } } } @@ -1002,13 +1157,15 @@ impl Read for SslStream { impl Write for SslStream { fn write(&mut self, buf: &[u8]) -> io::Result { match self.kind { - StreamKind::Indirect(ref mut s) => s.write(buf) + StreamKind::Indirect(ref mut s) => s.write(buf), + StreamKind::Direct(ref mut s) => s.write(buf), } } fn flush(&mut self) -> io::Result<()> { match self.kind { - StreamKind::Indirect(ref mut s) => s.flush() + StreamKind::Indirect(ref mut s) => s.flush(), + StreamKind::Direct(ref mut s) => s.flush(), } } } diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index a0e4a9d6..2ba940ab 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -317,8 +317,17 @@ fn test_write() { stream.flush().unwrap(); } +#[test] +fn test_write_direct() { + let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); + let mut stream = SslStream::new_client_direct(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + stream.write_all("hello".as_bytes()).unwrap(); + stream.flush().unwrap(); + stream.write_all(" there".as_bytes()).unwrap(); + stream.flush().unwrap(); +} + run_test!(get_peer_certificate, |method, stream| { - //let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); let stream = SslStream::new_client(&SslContext::new(method).unwrap(), stream).unwrap(); let cert = stream.get_peer_certificate().unwrap(); let fingerprint = cert.fingerprint(SHA256).unwrap(); @@ -349,6 +358,14 @@ fn test_read() { io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); } +#[test] +fn test_read_direct() { + let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); + let mut stream = SslStream::new_client_direct(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); + stream.flush().unwrap(); + io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); +} #[test] fn test_pending() { From b1a30ce4ba13cc6e673fb3b71ca9aa7249529c31 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Jun 2015 00:12:47 -0700 Subject: [PATCH 11/33] Rename new_client to connect and new_server to accept --- openssl/src/ssl/mod.rs | 39 ++++++++++++++++------------- openssl/src/ssl/tests.rs | 54 ++++++++++++++++++++-------------------- 2 files changed, 49 insertions(+), 44 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 0e1e5b30..5d770c19 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -777,13 +777,13 @@ impl IndirectStream { }) } - fn new_client(ssl: T, stream: S) -> Result, SslError> { + fn connect(ssl: T, stream: S) -> Result, SslError> { let mut ssl = try!(IndirectStream::new_base(ssl, stream)); try!(ssl.in_retry_wrapper(|ssl| ssl.connect())); Ok(ssl) } - fn new_server(ssl: T, stream: S) -> Result, SslError> { + fn accept(ssl: T, stream: S) -> Result, SslError> { let mut ssl = try!(IndirectStream::new_base(ssl, stream)); try!(ssl.in_retry_wrapper(|ssl| ssl.accept())); Ok(ssl) @@ -884,7 +884,7 @@ impl DirectStream { }) } - fn new_client(ssl: Ssl, stream: S, sock: c_int) -> Result, SslError> { + fn connect(ssl: Ssl, stream: S, sock: c_int) -> Result, SslError> { let ssl = try!(DirectStream::new_base(ssl, stream, sock)); let ret = ssl.ssl.connect(); if ret > 0 { @@ -894,7 +894,7 @@ impl DirectStream { } } - fn new_server(ssl: Ssl, stream: S, sock: c_int) -> Result, SslError> { + fn accept(ssl: Ssl, stream: S, sock: c_int) -> Result, SslError> { let ssl = try!(DirectStream::new_base(ssl, stream, sock)); let ret = ssl.ssl.accept(); if ret > 0 { @@ -1017,19 +1017,19 @@ impl fmt::Debug for SslStream where S: fmt::Debug { #[cfg(unix)] impl SslStream { - pub fn new_client_direct(ssl: T, stream: S) -> Result, SslError> { + pub fn connect_direct(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; - let stream = try!(DirectStream::new_client(ssl, stream, fd)); + let stream = try!(DirectStream::connect(ssl, stream, fd)); Ok(SslStream { kind: StreamKind::Direct(stream) }) } - pub fn new_server_direct(ssl: T, stream: S) -> Result, SslError> { + pub fn accept_direct(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; - let stream = try!(DirectStream::new_server(ssl, stream, fd)); + let stream = try!(DirectStream::accept(ssl, stream, fd)); Ok(SslStream { kind: StreamKind::Direct(stream) }) @@ -1040,7 +1040,7 @@ impl SslStream { impl SslStream { pub fn new_client_direct(ssl: T, stream: S) -> Result, SslError> { let fd = stream.as_raw_socket() as c_int; - let stream = try!(DirectStream::new_client(ssl, stream, fd)); + let stream = try!(DirectStream::connect(ssl, stream, fd)); Ok(SslStream { kind: StreamKind::Direct(stream) }) @@ -1048,7 +1048,7 @@ impl SslStream { pub fn new_server_direct(ssl: T, stream: S) -> Result, SslError> { let fd = stream.as_raw_socket() as c_int; - let stream = try!(DirectStream::new_server(ssl, stream, fd)); + let stream = try!(DirectStream::accept(ssl, stream, fd)); Ok(SslStream { kind: StreamKind::Direct(stream) }) @@ -1056,33 +1056,38 @@ impl SslStream { } impl SslStream { - pub fn new_client(ssl: T, stream: S) -> Result, SslError> { - let stream = try!(IndirectStream::new_client(ssl, stream)); + pub fn connect(ssl: T, stream: S) -> Result, SslError> { + let stream = try!(IndirectStream::connect(ssl, stream)); Ok(SslStream { kind: StreamKind::Indirect(stream) }) } - pub fn new_server(ssl: T, stream: S) -> Result, SslError> { - let stream = try!(IndirectStream::new_server(ssl, stream)); + pub fn accept(ssl: T, stream: S) -> Result, SslError> { + let stream = try!(IndirectStream::accept(ssl, stream)); Ok(SslStream { kind: StreamKind::Indirect(stream) }) } + /// # Deprecated + pub fn new_server(ssl: Ssl, stream: S) -> Result, SslError> { + SslStream::accept(ssl, stream) + } + /// # Deprecated pub fn new_server_from(ssl: Ssl, stream: S) -> Result, SslError> { - SslStream::new_server(ssl, stream) + SslStream::accept(ssl, stream) } /// # Deprecated pub fn new_from(ssl: Ssl, stream: S) -> Result, SslError> { - SslStream::new_client(ssl, stream) + SslStream::connect(ssl, stream) } /// # Deprecated pub fn new(ctx: &SslContext, stream: S) -> Result, SslError> { - SslStream::new_client(ctx, stream) + SslStream::connect(ctx, stream) } /// # Deprecated diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index 2ba940ab..02f962d6 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -83,14 +83,14 @@ run_test!(new_ctx, |method, _| { }); run_test!(new_sslstream, |method, stream| { - SslStream::new_client(&SslContext::new(method).unwrap(), stream).unwrap(); + SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); }); run_test!(verify_untrusted, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, None); - match SslStream::new_client(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => panic!("expected failure"), Err(err) => println!("error {:?}", err) } @@ -104,7 +104,7 @@ run_test!(verify_trusted, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - match SslStream::new_client(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -118,7 +118,7 @@ run_test!(verify_untrusted_callback_override_ok, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - match SslStream::new_client(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -132,7 +132,7 @@ run_test!(verify_untrusted_callback_override_bad, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::new_client(&ctx, stream).is_err()); + assert!(SslStream::connect(&ctx, stream).is_err()); }); run_test!(verify_trusted_callback_override_ok, |method, stream| { @@ -147,7 +147,7 @@ run_test!(verify_trusted_callback_override_ok, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - match SslStream::new_client(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -165,7 +165,7 @@ run_test!(verify_trusted_callback_override_bad, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - assert!(SslStream::new_client(&ctx, stream).is_err()); + assert!(SslStream::connect(&ctx, stream).is_err()); }); run_test!(verify_callback_load_certs, |method, stream| { @@ -177,7 +177,7 @@ run_test!(verify_callback_load_certs, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::new_client(&ctx, stream).is_ok()); + assert!(SslStream::connect(&ctx, stream).is_ok()); }); run_test!(verify_trusted_get_error_ok, |method, stream| { @@ -193,7 +193,7 @@ run_test!(verify_trusted_get_error_ok, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - assert!(SslStream::new_client(&ctx, stream).is_ok()); + assert!(SslStream::connect(&ctx, stream).is_ok()); }); run_test!(verify_trusted_get_error_err, |method, stream| { @@ -205,7 +205,7 @@ run_test!(verify_trusted_get_error_err, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::new_client(&ctx, stream).is_err()); + assert!(SslStream::connect(&ctx, stream).is_err()); }); run_test!(verify_callback_data, |method, stream| { @@ -230,7 +230,7 @@ run_test!(verify_callback_data, |method, stream| { ctx.set_verify_with_data(SSL_VERIFY_PEER, callback, node_id); ctx.set_verify_depth(1); - match SslStream::new_client(&ctx, stream) { + match SslStream::connect(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -245,7 +245,7 @@ fn test_write_hits_stream() { let guard = thread::spawn(move || { let ctx = SslContext::new(Sslv23).unwrap(); let stream = TcpStream::connect(addr).unwrap(); - let mut stream = SslStream::new_client(&ctx, stream).unwrap(); + let mut stream = SslStream::connect(&ctx, stream).unwrap(); stream.write_all(b"hello").unwrap(); stream @@ -256,7 +256,7 @@ fn test_write_hits_stream() { ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM).unwrap(); ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM).unwrap(); let stream = listener.accept().unwrap().0; - let mut stream = SslStream::new_server(&ctx, stream).unwrap(); + let mut stream = SslStream::accept(&ctx, stream).unwrap(); let mut buf = [0; 5]; assert_eq!(5, stream.read(&mut buf).unwrap()); @@ -310,7 +310,7 @@ run_test!(clear_ctx_options, |method, _| { #[test] fn test_write() { let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::new_client(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -320,7 +320,7 @@ fn test_write() { #[test] fn test_write_direct() { let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::new_client_direct(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect_direct(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -328,7 +328,7 @@ fn test_write_direct() { } run_test!(get_peer_certificate, |method, stream| { - let stream = SslStream::new_client(&SslContext::new(method).unwrap(), stream).unwrap(); + let stream = SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); let cert = stream.get_peer_certificate().unwrap(); let fingerprint = cert.fingerprint(SHA256).unwrap(); let node_hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b"; @@ -342,7 +342,7 @@ fn test_write_dtlsv1() { let sock = UdpSocket::bind("127.0.0.1:0").unwrap(); let stream = sock.connect("127.0.0.1:15410").unwrap(); - let mut stream = SslStream::new_client(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -352,7 +352,7 @@ fn test_write_dtlsv1() { #[test] fn test_read() { let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::new_client(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); @@ -361,7 +361,7 @@ fn test_read() { #[test] fn test_read_direct() { let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::new_client_direct(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect_direct(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); @@ -370,7 +370,7 @@ fn test_read_direct() { #[test] fn test_pending() { let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::new_client(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); @@ -403,7 +403,7 @@ fn test_connect_with_unilateral_npn() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - let stream = match SslStream::new_client(&ctx, stream) { + let stream = match SslStream::connect(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -427,7 +427,7 @@ fn test_connect_with_npn_successful_multiple_matching() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - let stream = match SslStream::new_client(&ctx, stream) { + let stream = match SslStream::connect(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -452,7 +452,7 @@ fn test_connect_with_npn_successful_single_match() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - let stream = match SslStream::new_client(&ctx, stream) { + let stream = match SslStream::connect(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -482,7 +482,7 @@ fn test_npn_server_advertise_multiple() { // Have the listener wait on the connection in a different thread. thread::spawn(move || { let (stream, _) = listener.accept().unwrap(); - let _ = SslStream::new_server(&listener_ctx, stream).unwrap(); + let _ = SslStream::accept(&listener_ctx, stream).unwrap(); }); let mut ctx = SslContext::new(Sslv23).unwrap(); @@ -494,7 +494,7 @@ fn test_npn_server_advertise_multiple() { } // Now connect to the socket and make sure the protocol negotiation works... let stream = TcpStream::connect(localhost).unwrap(); - let stream = match SslStream::new_client(&ctx, stream) { + let stream = match SslStream::connect(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -531,7 +531,7 @@ fn test_read_dtlsv1() { let server = udp::next_server(); let stream = sock.connect(&server[..]).unwrap(); - let mut stream = SslStream::new_client(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); let mut buf = [0u8;100]; assert!(stream.read(&mut buf).is_ok()); } @@ -540,5 +540,5 @@ fn test_read_dtlsv1() { #[cfg(feature = "sslv2")] fn test_sslv2_connect_failure() { let tcp = TcpStream::connect("127.0.0.1:15420").unwrap(); - SslStream::new_client(&SslContext::new(Sslv2).unwrap(), tcp).err().unwrap(); + SslStream::connect(&SslContext::new(Sslv2).unwrap(), tcp).err().unwrap(); } From 797488dd091ce74e9b36c1c131406b4a9e9962ad Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Jun 2015 00:21:41 -0700 Subject: [PATCH 12/33] Add docs for accept and connect --- openssl/src/ssl/mod.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 5d770c19..d0f1644b 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1017,6 +1017,11 @@ impl fmt::Debug for SslStream where S: fmt::Debug { #[cfg(unix)] impl SslStream { + /// Creates an SSL/TLS client operating over the provided stream. + /// + /// `connect_direct` creates a more efficient `SslStream` than `connect` + /// does, but requires that the stream implement `AsRawFd` on Unix and + /// `AsRawSocket` on Windows. pub fn connect_direct(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; @@ -1026,6 +1031,11 @@ impl SslStream { }) } + /// Creates an SSL/TLS server operating over the provided stream. + /// + /// `accept_direct` creates a more efficient `SslStream` than `accept` + /// does, but requires that the stream implement `AsRawFd` on Unix and + /// `AsRawSocket` on Windows. pub fn accept_direct(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; @@ -1038,6 +1048,11 @@ impl SslStream { #[cfg(windows)] impl SslStream { + /// Creates an SSL/TLS client operating over the provided stream. + /// + /// `connect_direct` creates a more efficient `SslStream` than `connect` + /// does, but requires that the stream implement `AsRawFd` on Unix and + /// `AsRawSocket` on Windows. pub fn new_client_direct(ssl: T, stream: S) -> Result, SslError> { let fd = stream.as_raw_socket() as c_int; let stream = try!(DirectStream::connect(ssl, stream, fd)); @@ -1046,6 +1061,11 @@ impl SslStream { }) } + /// Creates an SSL/TLS server operating over the provided stream. + /// + /// `accept_direct` creates a more efficient `SslStream` than `accept` + /// does, but requires that the stream implement `AsRawFd` on Unix and + /// `AsRawSocket` on Windows. pub fn new_server_direct(ssl: T, stream: S) -> Result, SslError> { let fd = stream.as_raw_socket() as c_int; let stream = try!(DirectStream::accept(ssl, stream, fd)); @@ -1056,6 +1076,7 @@ impl SslStream { } impl SslStream { + /// Creates an SSL/TLS client operating over the provided stream. pub fn connect(ssl: T, stream: S) -> Result, SslError> { let stream = try!(IndirectStream::connect(ssl, stream)); Ok(SslStream { @@ -1063,6 +1084,7 @@ impl SslStream { }) } + /// Creates an SSL/TLS server operating over the provided stream. pub fn accept(ssl: T, stream: S) -> Result, SslError> { let stream = try!(IndirectStream::accept(ssl, stream)); Ok(SslStream { From 3325e6b4748b76367c06987e1288579b485b3016 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Jun 2015 10:06:42 -0700 Subject: [PATCH 13/33] Make the direct constructors the defaults --- openssl/src/ssl/mod.rs | 20 ++++++++-------- openssl/src/ssl/tests.rs | 50 ++++++++++++++++++++-------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index d0f1644b..500e9aa4 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1022,7 +1022,7 @@ impl SslStream { /// `connect_direct` creates a more efficient `SslStream` than `connect` /// does, but requires that the stream implement `AsRawFd` on Unix and /// `AsRawSocket` on Windows. - pub fn connect_direct(ssl: T, stream: S) -> Result, SslError> { + pub fn connect(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; let stream = try!(DirectStream::connect(ssl, stream, fd)); @@ -1036,7 +1036,7 @@ impl SslStream { /// `accept_direct` creates a more efficient `SslStream` than `accept` /// does, but requires that the stream implement `AsRawFd` on Unix and /// `AsRawSocket` on Windows. - pub fn accept_direct(ssl: T, stream: S) -> Result, SslError> { + pub fn accept(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; let stream = try!(DirectStream::accept(ssl, stream, fd)); @@ -1053,7 +1053,7 @@ impl SslStream { /// `connect_direct` creates a more efficient `SslStream` than `connect` /// does, but requires that the stream implement `AsRawFd` on Unix and /// `AsRawSocket` on Windows. - pub fn new_client_direct(ssl: T, stream: S) -> Result, SslError> { + pub fn connect(ssl: T, stream: S) -> Result, SslError> { let fd = stream.as_raw_socket() as c_int; let stream = try!(DirectStream::connect(ssl, stream, fd)); Ok(SslStream { @@ -1066,7 +1066,7 @@ impl SslStream { /// `accept_direct` creates a more efficient `SslStream` than `accept` /// does, but requires that the stream implement `AsRawFd` on Unix and /// `AsRawSocket` on Windows. - pub fn new_server_direct(ssl: T, stream: S) -> Result, SslError> { + pub fn accept(ssl: T, stream: S) -> Result, SslError> { let fd = stream.as_raw_socket() as c_int; let stream = try!(DirectStream::accept(ssl, stream, fd)); Ok(SslStream { @@ -1077,7 +1077,7 @@ impl SslStream { impl SslStream { /// Creates an SSL/TLS client operating over the provided stream. - pub fn connect(ssl: T, stream: S) -> Result, SslError> { + pub fn connect_generic(ssl: T, stream: S) -> Result, SslError> { let stream = try!(IndirectStream::connect(ssl, stream)); Ok(SslStream { kind: StreamKind::Indirect(stream) @@ -1085,7 +1085,7 @@ impl SslStream { } /// Creates an SSL/TLS server operating over the provided stream. - pub fn accept(ssl: T, stream: S) -> Result, SslError> { + pub fn accept_generic(ssl: T, stream: S) -> Result, SslError> { let stream = try!(IndirectStream::accept(ssl, stream)); Ok(SslStream { kind: StreamKind::Indirect(stream) @@ -1094,22 +1094,22 @@ impl SslStream { /// # Deprecated pub fn new_server(ssl: Ssl, stream: S) -> Result, SslError> { - SslStream::accept(ssl, stream) + SslStream::accept_generic(ssl, stream) } /// # Deprecated pub fn new_server_from(ssl: Ssl, stream: S) -> Result, SslError> { - SslStream::accept(ssl, stream) + SslStream::accept_generic(ssl, stream) } /// # Deprecated pub fn new_from(ssl: Ssl, stream: S) -> Result, SslError> { - SslStream::connect(ssl, stream) + SslStream::connect_generic(ssl, stream) } /// # Deprecated pub fn new(ctx: &SslContext, stream: S) -> Result, SslError> { - SslStream::connect(ctx, stream) + SslStream::connect_generic(ctx, stream) } /// # Deprecated diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index 02f962d6..c4673edc 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -83,14 +83,14 @@ run_test!(new_ctx, |method, _| { }); run_test!(new_sslstream, |method, stream| { - SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); + SslStream::connect_generic(&SslContext::new(method).unwrap(), stream).unwrap(); }); run_test!(verify_untrusted, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, None); - match SslStream::connect(&ctx, stream) { + match SslStream::connect_generic(&ctx, stream) { Ok(_) => panic!("expected failure"), Err(err) => println!("error {:?}", err) } @@ -104,7 +104,7 @@ run_test!(verify_trusted, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - match SslStream::connect(&ctx, stream) { + match SslStream::connect_generic(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -118,7 +118,7 @@ run_test!(verify_untrusted_callback_override_ok, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - match SslStream::connect(&ctx, stream) { + match SslStream::connect_generic(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -132,7 +132,7 @@ run_test!(verify_untrusted_callback_override_bad, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::connect(&ctx, stream).is_err()); + assert!(SslStream::connect_generic(&ctx, stream).is_err()); }); run_test!(verify_trusted_callback_override_ok, |method, stream| { @@ -147,7 +147,7 @@ run_test!(verify_trusted_callback_override_ok, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - match SslStream::connect(&ctx, stream) { + match SslStream::connect_generic(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -165,7 +165,7 @@ run_test!(verify_trusted_callback_override_bad, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - assert!(SslStream::connect(&ctx, stream).is_err()); + assert!(SslStream::connect_generic(&ctx, stream).is_err()); }); run_test!(verify_callback_load_certs, |method, stream| { @@ -177,7 +177,7 @@ run_test!(verify_callback_load_certs, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::connect(&ctx, stream).is_ok()); + assert!(SslStream::connect_generic(&ctx, stream).is_ok()); }); run_test!(verify_trusted_get_error_ok, |method, stream| { @@ -193,7 +193,7 @@ run_test!(verify_trusted_get_error_ok, |method, stream| { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - assert!(SslStream::connect(&ctx, stream).is_ok()); + assert!(SslStream::connect_generic(&ctx, stream).is_ok()); }); run_test!(verify_trusted_get_error_err, |method, stream| { @@ -205,7 +205,7 @@ run_test!(verify_trusted_get_error_err, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback)); - assert!(SslStream::connect(&ctx, stream).is_err()); + assert!(SslStream::connect_generic(&ctx, stream).is_err()); }); run_test!(verify_callback_data, |method, stream| { @@ -230,7 +230,7 @@ run_test!(verify_callback_data, |method, stream| { ctx.set_verify_with_data(SSL_VERIFY_PEER, callback, node_id); ctx.set_verify_depth(1); - match SslStream::connect(&ctx, stream) { + match SslStream::connect_generic(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err) } @@ -245,7 +245,7 @@ fn test_write_hits_stream() { let guard = thread::spawn(move || { let ctx = SslContext::new(Sslv23).unwrap(); let stream = TcpStream::connect(addr).unwrap(); - let mut stream = SslStream::connect(&ctx, stream).unwrap(); + let mut stream = SslStream::connect_generic(&ctx, stream).unwrap(); stream.write_all(b"hello").unwrap(); stream @@ -310,7 +310,7 @@ run_test!(clear_ctx_options, |method, _| { #[test] fn test_write() { let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -320,7 +320,7 @@ fn test_write() { #[test] fn test_write_direct() { let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::connect_direct(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -328,7 +328,7 @@ fn test_write_direct() { } run_test!(get_peer_certificate, |method, stream| { - let stream = SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); + let stream = SslStream::connect_generic(&SslContext::new(method).unwrap(), stream).unwrap(); let cert = stream.get_peer_certificate().unwrap(); let fingerprint = cert.fingerprint(SHA256).unwrap(); let node_hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b"; @@ -342,7 +342,7 @@ fn test_write_dtlsv1() { let sock = UdpSocket::bind("127.0.0.1:0").unwrap(); let stream = sock.connect("127.0.0.1:15410").unwrap(); - let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect_generic(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -352,7 +352,7 @@ fn test_write_dtlsv1() { #[test] fn test_read() { let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); @@ -361,7 +361,7 @@ fn test_read() { #[test] fn test_read_direct() { let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::connect_direct(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); @@ -370,7 +370,7 @@ fn test_read_direct() { #[test] fn test_pending() { let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); @@ -403,7 +403,7 @@ fn test_connect_with_unilateral_npn() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match SslStream::connect_generic(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -427,7 +427,7 @@ fn test_connect_with_npn_successful_multiple_matching() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match SslStream::connect_generic(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -452,7 +452,7 @@ fn test_connect_with_npn_successful_single_match() { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err) } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match SslStream::connect_generic(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -494,7 +494,7 @@ fn test_npn_server_advertise_multiple() { } // Now connect to the socket and make sure the protocol negotiation works... let stream = TcpStream::connect(localhost).unwrap(); - let stream = match SslStream::connect(&ctx, stream) { + let stream = match SslStream::connect_generic(&ctx, stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; @@ -531,7 +531,7 @@ fn test_read_dtlsv1() { let server = udp::next_server(); let stream = sock.connect(&server[..]).unwrap(); - let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect_generic(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); let mut buf = [0u8;100]; assert!(stream.read(&mut buf).is_ok()); } @@ -540,5 +540,5 @@ fn test_read_dtlsv1() { #[cfg(feature = "sslv2")] fn test_sslv2_connect_failure() { let tcp = TcpStream::connect("127.0.0.1:15420").unwrap(); - SslStream::connect(&SslContext::new(Sslv2).unwrap(), tcp).err().unwrap(); + SslStream::connect_generic(&SslContext::new(Sslv2).unwrap(), tcp).err().unwrap(); } From b1dd46ae6a9f873e809ddc5aea8ea01ab7c39349 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Jun 2015 10:15:33 -0700 Subject: [PATCH 14/33] Docs --- openssl/src/ssl/mod.rs | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 500e9aa4..0bbba4c8 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1016,12 +1016,8 @@ impl fmt::Debug for SslStream where S: fmt::Debug { } #[cfg(unix)] -impl SslStream { +impl SslStream { /// Creates an SSL/TLS client operating over the provided stream. - /// - /// `connect_direct` creates a more efficient `SslStream` than `connect` - /// does, but requires that the stream implement `AsRawFd` on Unix and - /// `AsRawSocket` on Windows. pub fn connect(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; @@ -1032,10 +1028,6 @@ impl SslStream { } /// Creates an SSL/TLS server operating over the provided stream. - /// - /// `accept_direct` creates a more efficient `SslStream` than `accept` - /// does, but requires that the stream implement `AsRawFd` on Unix and - /// `AsRawSocket` on Windows. pub fn accept(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; @@ -1047,12 +1039,8 @@ impl SslStream { } #[cfg(windows)] -impl SslStream { +impl SslStream { /// Creates an SSL/TLS client operating over the provided stream. - /// - /// `connect_direct` creates a more efficient `SslStream` than `connect` - /// does, but requires that the stream implement `AsRawFd` on Unix and - /// `AsRawSocket` on Windows. pub fn connect(ssl: T, stream: S) -> Result, SslError> { let fd = stream.as_raw_socket() as c_int; let stream = try!(DirectStream::connect(ssl, stream, fd)); @@ -1062,10 +1050,6 @@ impl SslStream { } /// Creates an SSL/TLS server operating over the provided stream. - /// - /// `accept_direct` creates a more efficient `SslStream` than `accept` - /// does, but requires that the stream implement `AsRawFd` on Unix and - /// `AsRawSocket` on Windows. pub fn accept(ssl: T, stream: S) -> Result, SslError> { let fd = stream.as_raw_socket() as c_int; let stream = try!(DirectStream::accept(ssl, stream, fd)); @@ -1077,6 +1061,10 @@ impl SslStream { impl SslStream { /// Creates an SSL/TLS client operating over the provided stream. + /// + /// `SslStream`s returned by this method will be less efficient than ones + /// returned by `connect`, so this method should only be used for streams + /// that do not implement `AsRawFd` and `AsRawSocket`. pub fn connect_generic(ssl: T, stream: S) -> Result, SslError> { let stream = try!(IndirectStream::connect(ssl, stream)); Ok(SslStream { @@ -1085,6 +1073,10 @@ impl SslStream { } /// Creates an SSL/TLS server operating over the provided stream. + /// + /// `SslStream`s returned by this method will be less efficient than ones + /// returned by `accept`, so this method should only be used for streams + /// that do not implement `AsRawFd` and `AsRawSocket`. pub fn accept_generic(ssl: T, stream: S) -> Result, SslError> { let stream = try!(IndirectStream::accept(ssl, stream)); Ok(SslStream { From 94b0f26c10e6a5862264d578e7cd47c05d252e3d Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Jun 2015 10:21:06 -0700 Subject: [PATCH 15/33] Fix windows build --- openssl/src/ssl/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 0bbba4c8..6d4b1f81 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1042,6 +1042,7 @@ impl SslStream { impl SslStream { /// Creates an SSL/TLS client operating over the provided stream. pub fn connect(ssl: T, stream: S) -> Result, SslError> { + let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_socket() as c_int; let stream = try!(DirectStream::connect(ssl, stream, fd)); Ok(SslStream { @@ -1051,6 +1052,7 @@ impl SslStream { /// Creates an SSL/TLS server operating over the provided stream. pub fn accept(ssl: T, stream: S) -> Result, SslError> { + let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_socket() as c_int; let stream = try!(DirectStream::accept(ssl, stream, fd)); Ok(SslStream { From 8fdd0e2ec1e0457215cb0550714e0e6024ac6192 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Jun 2015 11:30:49 -0700 Subject: [PATCH 16/33] More docs --- openssl/src/ssl/mod.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 6d4b1f81..2163891d 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1018,6 +1018,10 @@ impl fmt::Debug for SslStream where S: fmt::Debug { #[cfg(unix)] impl SslStream { /// Creates an SSL/TLS client operating over the provided stream. + /// + /// Streams passed to this method must implement `AsRawFd` on Unixy + /// platforms and `AsRawSocket` on Windows. Use `connect_generic` for + /// streams that do not. pub fn connect(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; @@ -1028,6 +1032,10 @@ impl SslStream { } /// Creates an SSL/TLS server operating over the provided stream. + /// + /// Streams passed to this method must implement `AsRawFd` on Unixy + /// platforms and `AsRawSocket` on Windows. Use `accept_generic` for + /// streams that do not. pub fn accept(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_fd() as c_int; @@ -1041,6 +1049,10 @@ impl SslStream { #[cfg(windows)] impl SslStream { /// Creates an SSL/TLS client operating over the provided stream. + /// + /// Streams passed to this method must implement `AsRawFd` on Unixy + /// platforms and `AsRawSocket` on Windows. Use `connect_generic` for + /// streams that do not. pub fn connect(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_socket() as c_int; @@ -1051,6 +1063,10 @@ impl SslStream { } /// Creates an SSL/TLS server operating over the provided stream. + /// + /// Streams passed to this method must implement `AsRawFd` on Unixy + /// platforms and `AsRawSocket` on Windows. Use `accept_generic` for + /// streams that do not. pub fn accept(ssl: T, stream: S) -> Result, SslError> { let ssl = try!(ssl.into_ssl()); let fd = stream.as_raw_socket() as c_int; From d465f6c5bb19224205f4ec1da9020cfcbd07d848 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Jun 2015 19:28:28 -0700 Subject: [PATCH 17/33] Don't use pkg-config on windows --- openssl-sys/build.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index e788af5d..8bbb0657 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -14,9 +14,12 @@ fn main() { let include_dir = env::var("OPENSSL_INCLUDE_DIR").ok(); if lib_dir.is_none() && include_dir.is_none() { - if let Ok(info) = pkg_config::find_library("openssl") { - build_openssl_shim(&info.include_paths); - return; + // rustc doesn't seem to work with pkg-config's output in mingw64 + if !target.contains("windows") { + if let Ok(info) = pkg_config::find_library("openssl") { + build_openssl_shim(&info.include_paths); + return; + } } if let Some(mingw_paths) = get_mingw_in_path() { for path in mingw_paths { From 6e43f5c0d45620cc53df790e6e16cfc274e7deb5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Jun 2015 19:41:52 -0700 Subject: [PATCH 18/33] Modernize cargo directives --- openssl-sys/build.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index 8bbb0657..c1f12034 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -23,7 +23,7 @@ fn main() { } if let Some(mingw_paths) = get_mingw_in_path() { for path in mingw_paths { - println!("cargo:rustc-flags=-L native={}", path); + println!("cargo:rustc-link-search=native={}", path); } } } @@ -49,11 +49,12 @@ fn main() { }; if let Some(lib_dir) = lib_dir { - println!("cargo:rustc-flags=-L native={}", lib_dir); + println!("cargo:rustc-link-search=native={}", lib_dir); } - let libs_arg = libs.iter().fold(String::new(), |args, lib| args + &format!(" -l {0}={1}", mode, lib)); - println!("cargo:rustc-flags={0}", libs_arg); + for lib in libs { + println!("cargo:rustc-link-lib={}={}", mode, lib); + } let mut include_dirs = vec![]; From a94ea78d8a4b8beafa539ab817a1f110c8c2ed3e Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Wed, 24 Jun 2015 15:15:17 -0400 Subject: [PATCH 19/33] ssl: use a common helper to generate new ex data indexes, switch NPN to a lazyref Rather than having the verification data idx generation and NPN use there own (similar) impls to generate indexes with destructors, unify them. Make NPNs use of indexes more idomatic by storing the index in a lazyref rather than having a function with static data members. --- openssl/src/ssl/mod.rs | 64 ++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 2163891d..1123b3d0 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -170,49 +170,33 @@ lazy_static! { // Registers a destructor for the data which will be called // when context is freed fn get_verify_data_idx() -> c_int { + *INDEXES.lock().unwrap().entry(TypeId::of::()).or_insert_with(|| { + get_new_idx::() + }) +} + +#[cfg(feature = "npn")] +lazy_static! { + static ref NPN_PROTOS_IDX: c_int = get_new_idx::>(); +} + +/// Determine a new index to use for SSL CTX ex data. +/// Registers a destruct for the data which will be called by openssl when the context is freed. +fn get_new_idx() -> c_int { extern fn free_data_box(_parent: *mut c_void, ptr: *mut c_void, - _ad: *mut ffi::CRYPTO_EX_DATA, _idx: c_int, - _argl: c_long, _argp: *mut c_void) { - if ptr != 0 as *mut _ { + _ad: *mut ffi::CRYPTO_EX_DATA, _idx: c_int, + _argl: c_long, _argp: *mut c_void) { + if !ptr.is_null() { let _: Box = unsafe { mem::transmute(ptr) }; } } - *INDEXES.lock().unwrap().entry(TypeId::of::()).or_insert_with(|| { - unsafe { - let f: ffi::CRYPTO_EX_free = free_data_box::; - let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, Some(f)); - assert!(idx >= 0); - idx - } - }) -} - -/// Creates a static index for the list of NPN protocols. -/// Registers a destructor for the data which will be called -/// when the context is freed. -#[cfg(feature = "npn")] -fn get_npn_protos_idx() -> c_int { - static mut NPN_PROTOS_IDX: c_int = -1; - static mut INIT: Once = ONCE_INIT; - - extern fn free_data_box(_parent: *mut c_void, ptr: *mut c_void, - _ad: *mut ffi::CRYPTO_EX_DATA, _idx: c_int, - _argl: c_long, _argp: *mut c_void) { - if !ptr.is_null() { - let _: Box> = unsafe { mem::transmute(ptr) }; - } - } - unsafe { - INIT.call_once(|| { - let f: ffi::CRYPTO_EX_free = free_data_box; - let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, - None, Some(f)); - assert!(idx >= 0); - NPN_PROTOS_IDX = idx; - }); - NPN_PROTOS_IDX + let f: ffi::CRYPTO_EX_free = free_data_box::; + let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, + None, Some(f)); + assert!(idx >= 0); + idx } } @@ -279,7 +263,7 @@ extern fn raw_next_proto_select_cb(ssl: *mut ffi::SSL, // First, get the list of protocols (that the client should support) saved in the context // extra data. let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_npn_protos_idx()); + let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, *NPN_PROTOS_IDX); let protocols: &Vec = mem::transmute(protocols); // Prepare the client list parameters to be passed to the OpenSSL function... let client = protocols.as_ptr(); @@ -306,7 +290,7 @@ extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, unsafe { // First, get the list of (supported) protocols saved in the context extra data. let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_npn_protos_idx()); + let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, *NPN_PROTOS_IDX); if protocols.is_null() { *out = b"".as_ptr(); *outlen = 0; @@ -543,7 +527,7 @@ impl SslContext { unsafe { // Attach the protocol list to the OpenSSL context structure, // so that we can refer to it within the callback. - ffi::SSL_CTX_set_ex_data(self.ctx, get_npn_protos_idx(), + ffi::SSL_CTX_set_ex_data(self.ctx, *NPN_PROTOS_IDX, mem::transmute(protocols)); // Now register the callback that performs the default protocol // matching based on the client-supported list of protocols that From 539ae2eebf723e935fee2e342f0ce4799d2733fc Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Wed, 24 Jun 2015 15:18:19 -0400 Subject: [PATCH 20/33] ssl/NPN: factor out encoding of the protocol list The intention is to allow the encoding to be reused by the ALPN support code. --- openssl/src/ssl/mod.rs | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 1123b3d0..67ecd302 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -306,6 +306,24 @@ extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, ffi::SSL_TLSEXT_ERR_OK } +/// Convert a set of byte slices into a series of byte strings encoded for SSL. Encoding is a byte +/// containing the length followed by the string. +#[cfg(feature = "npn")] +fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec +{ + let mut enc = Vec::new(); + for string in strings { + let len = string.len() as u8; + if len as usize != string.len() { + // If the item does not fit, discard it + continue; + } + enc.push(len); + enc.extend(string[..len as usize].to_vec()); + } + enc +} + /// The signature of functions that can be used to manually verify certificates pub type VerifyCallback = fn(preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool; @@ -515,14 +533,7 @@ impl SslContext { pub fn set_npn_protocols(&mut self, protocols: &[&[u8]]) { // Firstly, convert the list of protocols to a byte-array that can be passed to OpenSSL // APIs -- a list of length-prefixed strings. - let mut npn_protocols = Vec::new(); - for protocol in protocols { - let len = protocol.len() as u8; - npn_protocols.push(len); - // If the length is greater than the max `u8`, this truncates the protocol name. - npn_protocols.extend(protocol[..len as usize].to_vec()); - } - let protocols: Box> = Box::new(npn_protocols); + let protocols: Box> = Box::new(ssl_encode_byte_strings(protocols)); unsafe { // Attach the protocol list to the OpenSSL context structure, From 01e01e3747dd0dbd46486c4f9406c29488a28c19 Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Wed, 24 Jun 2015 17:17:43 -0400 Subject: [PATCH 21/33] ssl: support ALPN Heavily based on the existing NPN wrapping code. Naming of public functions is identical to the NPN ones with `s/npn/alpn/` applied to prevent devs from needing to remember 2 names (and to let my copy the npn tests and perform the subistution to generate the apln tests). It might make sense to (at some point) use macros or a trait to cut down the duplication. --- openssl-sys/Cargo.toml | 1 + openssl-sys/src/lib.rs | 20 ++++++- openssl/Cargo.toml | 1 + openssl/src/ssl/mod.rs | 115 ++++++++++++++++++++++++++++++++++----- openssl/src/ssl/tests.rs | 113 ++++++++++++++++++++++++++++++++++++++ openssl/test/test.sh | 2 +- 6 files changed, 235 insertions(+), 17 deletions(-) diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index f3fbfc18..bc9e9876 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -19,6 +19,7 @@ dtlsv1_2 = [] sslv2 = [] aes_xts = [] npn = [] +alpn = [] [dependencies] libc = "0.1" diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index b347b949..9f2041a4 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -547,13 +547,31 @@ extern "C" { inlen: c_uint, arg: *mut c_void) -> c_int, arg: *mut c_void); - #[cfg(feature = "npn")] + #[cfg(any(feature = "alpn", feature = "npn"))] pub fn SSL_select_next_proto(out: *mut *mut c_uchar, outlen: *mut c_uchar, inbuf: *const c_uchar, inlen: c_uint, client: *const c_uchar, client_len: c_uint) -> c_int; #[cfg(feature = "npn")] pub fn SSL_get0_next_proto_negotiated(s: *const SSL, data: *mut *const c_uchar, len: *mut c_uint); + #[cfg(feature = "alpn")] + pub fn SSL_CTX_set_alpn_protos(s: *mut SSL_CTX, data: *const c_uchar, len: c_uint) -> c_int; + + #[cfg(feature = "alpn")] + pub fn SSL_set_alpn_protos(s: *mut SSL, data: *const c_uchar, len: c_uint) -> c_int; + + #[cfg(feature = "alpn")] + pub fn SSL_CTX_set_alpn_select_cb(ssl: *mut SSL_CTX, + cb: extern "C" fn(ssl: *mut SSL, + out: *mut *mut c_uchar, + outlen: *mut c_uchar, + inbuf: *const c_uchar, + inlen: c_uint, + arg: *mut c_void) -> c_int, + arg: *mut c_void); + #[cfg(feature = "alpn")] + pub fn SSL_get0_alpn_selected(s: *const SSL, data: *mut *const c_uchar, len: *mut c_uint); + pub fn X509_add_ext(x: *mut X509, ext: *mut X509_EXTENSION, loc: c_int) -> c_int; pub fn X509_digest(x: *mut X509, digest: *const EVP_MD, buf: *mut c_char, len: *mut c_uint) -> c_int; pub fn X509_free(x: *mut X509); diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index c2097774..3e3c34de 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -17,6 +17,7 @@ dtlsv1_2 = ["openssl-sys/dtlsv1_2"] sslv2 = ["openssl-sys/sslv2"] aes_xts = ["openssl-sys/aes_xts"] npn = ["openssl-sys/npn"] +alpn = ["openssl-sys/alpn"] [dependencies.openssl-sys] path = "../openssl-sys" diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 67ecd302..d67dc1a2 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -13,9 +13,9 @@ use std::sync::{Once, ONCE_INIT, Arc, Mutex}; use std::ops::{Deref, DerefMut}; use std::cmp; use std::any::Any; -#[cfg(feature = "npn")] +#[cfg(any(feature = "npn", feature = "alpn"))] use libc::{c_uchar, c_uint}; -#[cfg(feature = "npn")] +#[cfg(any(feature = "npn", feature = "alpn"))] use std::slice; use bio::{MemBio}; @@ -179,6 +179,10 @@ fn get_verify_data_idx() -> c_int { lazy_static! { static ref NPN_PROTOS_IDX: c_int = get_new_idx::>(); } +#[cfg(feature = "alpn")] +lazy_static! { + static ref ALPN_PROTOS_IDX: c_int = get_new_idx::>(); +} /// Determine a new index to use for SSL CTX ex data. /// Registers a destruct for the data which will be called by openssl when the context is freed. @@ -248,6 +252,26 @@ extern fn raw_verify_with_data(preverify_ok: c_int, } } +#[cfg(any(feature = "npn", feature = "alpn"))] +unsafe fn select_proto_using(ssl: *mut ffi::SSL, + out: *mut *mut c_uchar, outlen: *mut c_uchar, + inbuf: *const c_uchar, inlen: c_uint, + ex_data: c_int) -> c_int { + + // First, get the list of protocols (that the client should support) saved in the context + // extra data. + let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); + let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, ex_data); + let protocols: &Vec = mem::transmute(protocols); + // Prepare the client list parameters to be passed to the OpenSSL function... + let client = protocols.as_ptr(); + let client_len = protocols.len() as c_uint; + // Finally, let OpenSSL find a protocol to be used, by matching the given server and + // client lists. + ffi::SSL_select_next_proto(out, outlen, inbuf, inlen, client, client_len); + ffi::SSL_TLSEXT_ERR_OK +} + /// The function is given as the callback to `SSL_CTX_set_next_proto_select_cb`. /// /// It chooses the protocol that the client wishes to use, out of the given list of protocols @@ -260,20 +284,18 @@ extern fn raw_next_proto_select_cb(ssl: *mut ffi::SSL, inbuf: *const c_uchar, inlen: c_uint, _arg: *mut c_void) -> c_int { unsafe { - // First, get the list of protocols (that the client should support) saved in the context - // extra data. - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, *NPN_PROTOS_IDX); - let protocols: &Vec = mem::transmute(protocols); - // Prepare the client list parameters to be passed to the OpenSSL function... - let client = protocols.as_ptr(); - let client_len = protocols.len() as c_uint; - // Finally, let OpenSSL find a protocol to be used, by matching the given server and - // client lists. - ffi::SSL_select_next_proto(out, outlen, inbuf, inlen, client, client_len); + select_proto_using(ssl, out, outlen, inbuf, inlen, *NPN_PROTOS_IDX) } +} - ffi::SSL_TLSEXT_ERR_OK +#[cfg(feature = "alpn")] +extern fn raw_alpn_select_cb(ssl: *mut ffi::SSL, + out: *mut *mut c_uchar, outlen: *mut c_uchar, + inbuf: *const c_uchar, inlen: c_uint, + _arg: *mut c_void) -> c_int { + unsafe { + select_proto_using(ssl, out, outlen, inbuf, inlen, *ALPN_PROTOS_IDX) + } } /// The function is given as the callback to `SSL_CTX_set_next_protos_advertised_cb`. @@ -308,7 +330,7 @@ extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, /// Convert a set of byte slices into a series of byte strings encoded for SSL. Encoding is a byte /// containing the length followed by the string. -#[cfg(feature = "npn")] +#[cfg(any(feature = "npn", feature = "alpn"))] fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec { let mut enc = Vec::new(); @@ -549,6 +571,35 @@ impl SslContext { ffi::SSL_CTX_set_next_protos_advertised_cb(self.ctx, raw_next_protos_advertise_cb, ptr::null_mut()); } } + + /// Set the protocols to be used during ALPN (application layer protocol negotiation). + /// If this is a server, these are the protocols we report to the client. + /// If this is a client, these are the protocols we try to match with those reported by the + /// server. + /// + /// Note that ordering of the protocols controls the priority with which they are chosen. + /// + /// This method needs the `alpn` feature. + #[cfg(feature = "alpn")] + pub fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) { + let protocols: Box> = Box::new(ssl_encode_byte_strings(protocols)); + unsafe { + // Set the context's internal protocol list for use if we are a server + ffi::SSL_CTX_set_alpn_protos(self.ctx, protocols.as_ptr(), protocols.len() as c_uint); + + // Rather than use the argument to the callback to contain our data, store it in the + // ssl ctx's ex_data so that we can configure a function to free it later. In the + // future, it might make sense to pull this into our internal struct Ssl instead of + // leaning on openssl and using function pointers. + ffi::SSL_CTX_set_ex_data(self.ctx, *ALPN_PROTOS_IDX, + mem::transmute(protocols)); + + // Now register the callback that performs the default protocol + // matching based on the client-supported list of protocols that + // has been saved. + ffi::SSL_CTX_set_alpn_select_cb(self.ctx, raw_alpn_select_cb, ptr::null_mut()); + } + } } #[allow(dead_code)] @@ -690,6 +741,29 @@ impl Ssl { } } + /// Returns the protocol selected by performing ALPN, if any. + /// + /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client + /// to interpret it. + /// + /// This method needs the `alpn` feature. + #[cfg(feature = "alpn")] + pub fn get_selected_alpn_protocol(&self) -> Option<&[u8]> { + unsafe { + let mut data: *const c_uchar = ptr::null(); + let mut len: c_uint = 0; + // Get the negotiated protocol from the SSL instance. + // `data` will point at a `c_uchar` array; `len` will contain the length of this array. + ffi::SSL_get0_alpn_selected(self.ssl, &mut data, &mut len); + + if data.is_null() { + None + } else { + Some(slice::from_raw_parts(data, len as usize)) + } + } + } + /// pending() takes into account only bytes from the TLS/SSL record that is currently being processed (if any). pub fn pending(&self) -> usize { unsafe { @@ -1171,6 +1245,17 @@ impl SslStream { self.kind.ssl().get_selected_npn_protocol() } + /// Returns the protocol selected by performing ALPN, if any. + /// + /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client + /// to interpret it. + /// + /// This method needs the `alpn` feature. + #[cfg(feature = "alpn")] + pub fn get_selected_alpn_protocol(&self) -> Option<&[u8]> { + self.ssl.get_selected_alpn_protocol() + } + /// pending() takes into account only bytes from the TLS/SSL record that is currently being processed (if any). pub fn pending(&self) -> usize { self.kind.ssl().pending() diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index c4673edc..b44b9c35 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -390,6 +390,28 @@ fn test_pending() { assert_eq!(pending, len); } +/// Tests that connecting with the client using NPN, but the server not does not +/// break the existing connection behavior. +#[test] +#[cfg(feature = "alpn")] +fn test_connect_with_unilateral_alpn() { + let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); + let mut ctx = SslContext::new(Sslv23).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); + match ctx.set_CA_file(&Path::new("test/cert.pem")) { + Ok(_) => {} + Err(err) => panic!("Unexpected error {:?}", err) + } + let stream = match SslStream::new(&ctx, stream) { + Ok(stream) => stream, + Err(err) => panic!("Expected success, got {:?}", err) + }; + // Since the socket to which we connected is not configured to use NPN, + // there should be no selected protocol... + assert!(stream.get_selected_alpn_protocol().is_none()); +} + /// Tests that connecting with the client using NPN, but the server not does not /// break the existing connection behavior. #[test] @@ -412,6 +434,30 @@ fn test_connect_with_unilateral_npn() { assert!(stream.get_selected_npn_protocol().is_none()); } +/// Tests that when both the client as well as the server use ALPN and their +/// lists of supported protocols have an overlap, the correct protocol is chosen. +#[test] +#[cfg(feature = "alpn")] +fn test_connect_with_alpn_successful_multiple_matching() { + // A different port than the other tests: an `openssl` process that has + // NPN enabled. + let stream = TcpStream::connect("127.0.0.1:15419").unwrap(); + let mut ctx = SslContext::new(Sslv23).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_alpn_protocols(&[b"spdy/3.1", b"http/1.1"]); + match ctx.set_CA_file(&Path::new("test/cert.pem")) { + Ok(_) => {} + Err(err) => panic!("Unexpected error {:?}", err) + } + let stream = match SslStream::new(&ctx, stream) { + Ok(stream) => stream, + Err(err) => panic!("Expected success, got {:?}", err) + }; + // The server prefers "http/1.1", so that is chosen, even though the client + // would prefer "spdy/3.1" + assert_eq!(b"http/1.1", stream.get_selected_alpn_protocol().unwrap()); +} + /// Tests that when both the client as well as the server use NPN and their /// lists of supported protocols have an overlap, the correct protocol is chosen. #[test] @@ -436,6 +482,32 @@ fn test_connect_with_npn_successful_multiple_matching() { assert_eq!(b"http/1.1", stream.get_selected_npn_protocol().unwrap()); } +/// Tests that when both the client as well as the server use ALPN and their +/// lists of supported protocols have an overlap -- with only ONE protocol +/// being valid for both. +#[test] +#[cfg(feature = "alpn")] +fn test_connect_with_alpn_successful_single_match() { + // A different port than the other tests: an `openssl` process that has + // ALPN enabled. + let stream = TcpStream::connect("127.0.0.1:15419").unwrap(); + let mut ctx = SslContext::new(Sslv23).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_alpn_protocols(&[b"spdy/3.1"]); + match ctx.set_CA_file(&Path::new("test/cert.pem")) { + Ok(_) => {} + Err(err) => panic!("Unexpected error {:?}", err) + } + let stream = match SslStream::new(&ctx, stream) { + Ok(stream) => stream, + Err(err) => panic!("Expected success, got {:?}", err) + }; + // The client now only supports one of the server's protocols, so that one + // is used. + assert_eq!(b"spdy/3.1", stream.get_selected_alpn_protocol().unwrap()); +} + + /// Tests that when both the client as well as the server use NPN and their /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. @@ -502,6 +574,47 @@ fn test_npn_server_advertise_multiple() { assert_eq!(b"spdy/3.1", stream.get_selected_npn_protocol().unwrap()); } +/// Tests that when the `SslStream` is created as a server stream, the protocols +/// are correctly advertised to the client. +#[test] +#[cfg(feature = "alpn")] +fn test_alpn_server_advertise_multiple() { + let localhost = "127.0.0.1:15420"; + let listener = TcpListener::bind(localhost).unwrap(); + // We create a different context instance for the server... + let listener_ctx = { + let mut ctx = SslContext::new(Sslv23).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); + assert!(ctx.set_certificate_file( + &Path::new("test/cert.pem"), X509FileType::PEM).is_ok()); + ctx.set_private_key_file( + &Path::new("test/key.pem"), X509FileType::PEM).unwrap(); + ctx + }; + // Have the listener wait on the connection in a different thread. + thread::spawn(move || { + let (stream, _) = listener.accept().unwrap(); + let _ = SslStream::new_server(&listener_ctx, stream).unwrap(); + }); + + let mut ctx = SslContext::new(Sslv23).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_alpn_protocols(&[b"spdy/3.1"]); + match ctx.set_CA_file(&Path::new("test/cert.pem")) { + Ok(_) => {} + Err(err) => panic!("Unexpected error {:?}", err) + } + // Now connect to the socket and make sure the protocol negotiation works... + let stream = TcpStream::connect(localhost).unwrap(); + let stream = match SslStream::new(&ctx, stream) { + Ok(stream) => stream, + Err(err) => panic!("Expected success, got {:?}", err) + }; + // SPDY is selected since that's the only thing the client supports. + assert_eq!(b"spdy/3.1", stream.get_selected_alpn_protocol().unwrap()); +} + #[cfg(feature="dtlsv1")] #[cfg(test)] mod dtlsv1 { diff --git a/openssl/test/test.sh b/openssl/test/test.sh index 975b124e..9beb37c3 100755 --- a/openssl/test/test.sh +++ b/openssl/test/test.sh @@ -4,7 +4,7 @@ cd $(dirname $0) openssl s_server -accept 15418 -www -cert cert.pem -key key.pem >/dev/null 2>&1 & openssl s_server -accept 15419 -www -cert cert.pem -key key.pem \ - -nextprotoneg "http/1.1,spdy/3.1" >/dev/null 2>&1 & + -nextprotoneg "http/1.1,spdy/3.1" -alpn "http/1.1,spdy/3.1" >/dev/null 2>&1 & openssl s_server -no_ssl2 -accept 15420 -www -cert cert.pem -key key.pem >/dev/null 2>&1 & if test "$TRAVIS_OS_NAME" == "osx"; then From 8f408dae65f62c92b8f6b116c85a4b7d4c0c8a7f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 29 Jun 2015 21:55:55 -0700 Subject: [PATCH 22/33] Initialize FEATURES again in travis config --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4d0379b8..d512112c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,9 @@ rust: os: - osx - linux +env: + global: + - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv2 aes_xts npn alpn" before_script: - ./openssl/test/test.sh script: From dfacea1df693e9c3ec3eadafa9c96a0e1ddd3839 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 29 Jun 2015 21:58:54 -0700 Subject: [PATCH 23/33] Fix build with alpn feature --- openssl/src/ssl/mod.rs | 2 +- openssl/src/ssl/tests.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index d67dc1a2..cf885201 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1253,7 +1253,7 @@ impl SslStream { /// This method needs the `alpn` feature. #[cfg(feature = "alpn")] pub fn get_selected_alpn_protocol(&self) -> Option<&[u8]> { - self.ssl.get_selected_alpn_protocol() + self.kind.ssl().get_selected_alpn_protocol() } /// pending() takes into account only bytes from the TLS/SSL record that is currently being processed (if any). diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index b44b9c35..8401836d 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -579,7 +579,7 @@ fn test_npn_server_advertise_multiple() { #[test] #[cfg(feature = "alpn")] fn test_alpn_server_advertise_multiple() { - let localhost = "127.0.0.1:15420"; + let localhost = "127.0.0.1:15421"; let listener = TcpListener::bind(localhost).unwrap(); // We create a different context instance for the server... let listener_ctx = { @@ -595,7 +595,7 @@ fn test_alpn_server_advertise_multiple() { // Have the listener wait on the connection in a different thread. thread::spawn(move || { let (stream, _) = listener.accept().unwrap(); - let _ = SslStream::new_server(&listener_ctx, stream).unwrap(); + let _ = SslStream::accept(&listener_ctx, stream).unwrap(); }); let mut ctx = SslContext::new(Sslv23).unwrap(); From 61e61bbae4a7d25291c48c1bd1d7504310a96c16 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 29 Jun 2015 22:04:31 -0700 Subject: [PATCH 24/33] Fix backcompat method --- openssl/src/ssl/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index cf885201..88ba9af4 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1172,7 +1172,7 @@ impl SslStream { } /// # Deprecated - pub fn new_server(ssl: Ssl, stream: S) -> Result, SslError> { + pub fn new_server(ssl: &SslContext, stream: S) -> Result, SslError> { SslStream::accept_generic(ssl, stream) } From a6ff56209d9558911bd9622d146a2bc1a457f140 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 30 Jun 2015 00:07:38 -0700 Subject: [PATCH 25/33] Revert "Don't build a custom openssl on OSX" This reverts commit 645430602d0f4d56c6ab153b68a11c6be6d8b183. We actually need 1.0.2 for DTLSv1.2 and ALPN --- .travis.yml | 6 ++++-- openssl/test/build.sh | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100755 openssl/test/build.sh diff --git a/.travis.yml b/.travis.yml index d512112c..8d006d87 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,10 @@ os: env: global: - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv2 aes_xts npn alpn" +before_install: +- (test $TRAVIS_OS_NAME == "osx" || ./openssl/test/build.sh) before_script: - ./openssl/test/test.sh script: -- (cd openssl && cargo test) -- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && cargo test --features "$FEATURES")) +- (cd openssl && LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test) +- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES")) diff --git a/openssl/test/build.sh b/openssl/test/build.sh new file mode 100755 index 00000000..27def60a --- /dev/null +++ b/openssl/test/build.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e + +mkdir /tmp/openssl +cd /tmp/openssl +sudo apt-get install gcc make +curl https://openssl.org/source/openssl-1.0.2-latest.tar.gz | tar --strip-components=1 -xzf - +./config --prefix=/usr/ shared +make +sudo make install From d926d0c6e563d52500c09b260f350d4c9bad7f85 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 30 Jun 2015 09:13:51 -0700 Subject: [PATCH 26/33] Manually set lib and include dirs on linux builds --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8d006d87..bbe6e35d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,5 +14,8 @@ before_install: before_script: - ./openssl/test/test.sh script: -- (cd openssl && LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test) -- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES")) +- (test $TRAVIS_OS_NAME != "osx" || cd openssl && cargo test) +- (test $TRAVIS_OS_NAME == "osx" || cd openssl && \ + OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test) +- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && \ + OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES")) From d886fee56b21b0b7d48d0b92feeea6e6508d6de9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 30 Jun 2015 09:22:11 -0700 Subject: [PATCH 27/33] Fix travis? --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index bbe6e35d..1c14bbfb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,5 @@ before_script: - ./openssl/test/test.sh script: - (test $TRAVIS_OS_NAME != "osx" || cd openssl && cargo test) -- (test $TRAVIS_OS_NAME == "osx" || cd openssl && \ - OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test) -- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && \ - OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES")) +- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test) +- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES")) From c640fa8e7143f9e8c42d6ff707fd6c1af4ec4d9e Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 30 Jun 2015 22:55:17 -0700 Subject: [PATCH 28/33] Fix travis file syntax --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1c14bbfb..26124b1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,5 +15,5 @@ before_script: - ./openssl/test/test.sh script: - (test $TRAVIS_OS_NAME != "osx" || cd openssl && cargo test) -- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test) +- (test $TRAVIS_OS_NAME == "osx" || (cd openssl && OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test)) - (test $TRAVIS_OS_NAME == "osx" || (cd openssl && OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES")) From 26bc75cdefff7eb8bd5d5f346719815cee3745e0 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 30 Jun 2015 23:03:01 -0700 Subject: [PATCH 29/33] More syntax fixes --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 26124b1e..7df1431a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,6 @@ before_install: before_script: - ./openssl/test/test.sh script: -- (test $TRAVIS_OS_NAME != "osx" || cd openssl && cargo test) +- (test $TRAVIS_OS_NAME != "osx" || (cd openssl && cargo test)) - (test $TRAVIS_OS_NAME == "osx" || (cd openssl && OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test)) - (test $TRAVIS_OS_NAME == "osx" || (cd openssl && OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH cargo test --features "$FEATURES")) From 1d214bce61e461f7aa57808e9c650eee27971ddb Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 18:45:17 -0700 Subject: [PATCH 30/33] Fix NID definitions to match OpenSSL. The previous numbers were introduced incorrectly in #213 --- openssl/src/nid.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openssl/src/nid.rs b/openssl/src/nid.rs index 08424ae8..c5b9e277 100644 --- a/openssl/src/nid.rs +++ b/openssl/src/nid.rs @@ -37,6 +37,7 @@ pub enum Nid { DES_EDE, DES_EDE3, IDEA_CBC, + IDEA_CFB, IDEA_ECB, RC2_CBC, RC2_ECB, @@ -55,6 +56,7 @@ pub enum Nid { MessageDigest, SigningTime, CounterSignature, + ChallengePassword, UnstructuredAddress, ExtendedCertificateAttributes, Netscape, @@ -93,6 +95,7 @@ pub enum Nid { AuthorityKeyIdentifier, BF_CBC, BF_ECB, + BF_CFB, BF_OFB, MDC2, RSA_MDC2, @@ -117,7 +120,8 @@ pub enum Nid { RSA_SHA1_2, DSA, RIPEMD160, - RSA_RIPEMD160, + /* 118 missing */ + RSA_RIPEMD160=119, RC5_CBC, RC5_ECB, RC5_CFB, @@ -142,7 +146,6 @@ pub enum Nid { CRLReason, InvalidityDate, SXNetID, - Pkcs12, PBE_SHA1_RC4_128, PBE_SHA1_RC4_40, PBE_SHA1_3DES, From 9074af5bdd0d88521979174e287748b0422c12e2 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:51:54 -0700 Subject: [PATCH 31/33] Add a test that checks whether 3 known subject attributes can be retrieved by NID --- openssl/src/x509/tests.rs | 29 +++++++++++++++++++++++++++++ openssl/test/nid_test_cert.pem | 12 ++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 openssl/test/nid_test_cert.pem diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 6d95b966..4e1c4f15 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -69,3 +69,32 @@ fn test_subject_read_cn() { assert_eq!(&cn as &str, "test_cert") } + +#[test] +fn test_nid_values() { + let cert_path = Path::new("test/nid_test_cert.pem"); + let mut file = File::open(&cert_path) + .ok() + .expect("Failed to open `test/nid_test_cert.pem`"); + + let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); + let subject = cert.subject_name(); + + let cn = match subject.text_by_nid(Nid::CN) { + Some(x) => x, + None => panic!("Failed to read CN from cert") + }; + assert_eq!(&cn as &str, "example.com"); + + let email = match subject.text_by_nid(Nid::Email) { + Some(x) => x, + None => panic!("Failed to read subject email address from cert") + }; + assert_eq!(&email as &str, "test@example.com"); + + let friendly = match subject.text_by_nid(Nid::FriendlyName) { + Some(x) => x, + None => panic!("Failed to read subject friendly name from cert") + }; + assert_eq!(&friendly as &str, "Example"); +} diff --git a/openssl/test/nid_test_cert.pem b/openssl/test/nid_test_cert.pem new file mode 100644 index 00000000..6f17e734 --- /dev/null +++ b/openssl/test/nid_test_cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIB1DCCAX6gAwIBAgIJAMzXWZGWHleWMA0GCSqGSIb3DQEBCwUAMFYxHzAdBgkq +hkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20xFDASBgNVBAMMC2V4YW1wbGUuY29t +MR0wGwYJKoZIhvcNAQkUHg4ARQB4AGEAbQBwAGwAZTAeFw0xNTA3MDEwNjQ3NDRa +Fw0xNTA3MzEwNjQ3NDRaMFYxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5j +b20xFDASBgNVBAMMC2V4YW1wbGUuY29tMR0wGwYJKoZIhvcNAQkUHg4ARQB4AGEA +bQBwAGwAZTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCmejzp4+o35FD0hAnx2trL +08h07X5jZca9DgZH35hWXPh7fMucLt/IPXIRnz2zKEa/Mo6D2V/fx03Mqo0epid7 +AgMBAAGjLzAtMB0GA1UdDgQWBBRQa57tXz3rZNRz+fTbo3w3jQJMBTAMBgNVHRME +BTADAQH/MA0GCSqGSIb3DQEBCwUAA0EAm0iY9cr+gvC+vcQIebdofpQ4GcDW8U6W +Bxs8ZXinLl69P0jYLum3+XITNFRiyQqcivaxdxthxDNOX7P+aKwkJA== +-----END CERTIFICATE----- From f4afe615dddf367f4f7eaa18093f17c47c4e3e18 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Mon, 6 Jul 2015 09:49:28 +0200 Subject: [PATCH 32/33] Unpin the bitflags version. This dependency causes Servo to depend on multiple versions of the bitflags crate. --- openssl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 3e3c34de..6cba0100 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -24,7 +24,7 @@ path = "../openssl-sys" version = "0.6.3" [dependencies] -bitflags = "0.2" +bitflags = ">= 0.2, < 0.4" lazy_static = "0.1" libc = "0.1" From cc497b47686d1dd03f96e2c2a99f214b9bc97eb9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 6 Jul 2015 11:09:03 -0700 Subject: [PATCH 33/33] Release v0.6.4 --- README.md | 2 +- openssl-sys/Cargo.toml | 4 ++-- openssl-sys/src/lib.rs | 2 +- openssl/Cargo.toml | 6 +++--- openssl/src/lib.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f0e15d57..aafabaee 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/sfackler/rust-openssl.svg?branch=master)](https://travis-ci.org/sfackler/rust-openssl) -[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.6.3/openssl). +[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.6.4/openssl). ## Building diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index bc9e9876..5ed9d068 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "openssl-sys" -version = "0.6.3" +version = "0.6.4" authors = ["Alex Crichton ", "Steven Fackler "] license = "MIT" description = "FFI bindings to OpenSSL" repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.3/openssl_sys" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.4/openssl_sys" links = "openssl" build = "build.rs" diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 9f2041a4..eb7750f7 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] #![allow(dead_code)] -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.3")] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.4")] extern crate libc; diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 6cba0100..8a6b4ddc 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "openssl" -version = "0.6.3" +version = "0.6.4" authors = ["Steven Fackler "] license = "Apache-2.0" description = "OpenSSL bindings" repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.3/openssl" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.4/openssl" readme = "../README.md" keywords = ["crypto", "tls", "ssl", "dtls"] @@ -21,7 +21,7 @@ alpn = ["openssl-sys/alpn"] [dependencies.openssl-sys] path = "../openssl-sys" -version = "0.6.3" +version = "0.6.4" [dependencies] bitflags = ">= 0.2, < 0.4" diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 06c514a1..62d18dce 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.3")] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.4")] #[macro_use] extern crate bitflags;