From 9add4e1001ce08d78c17e4a3d994fd805f872d2a Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Mon, 31 Aug 2015 16:28:14 +0200 Subject: [PATCH 01/19] Add support for set_tmp_dh() and RFC5114 DH parameters for forward secrecy. rust-openssl didn't support forward secrecy at all. This adds support for DHE, by exposing set_tmp_dh() as well as the RFC5114 parameters, which are conveniently exposed since OpenSSL 1.0.2. With OpenSSL >= 1.0.2, and the rfc5114 feature gate, enabling DHE is as simple as (here for 2048-bit MODP group with 256-bit prime order subgroup): use openssl::dh::DH; let dh = DH::get_2048_256().unwrap(); ctx.set_tmp_dh(dh).unwrap(); With OpenSSL < 1.0.2, DH::from_params() can be used to manually specify the DH parameters (here for 2048-bit MODP group with 256-bit prime order subgroup): use openssl::bn::BigNum; use openssl::dh::DH; let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597").unwrap(); let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659").unwrap(); let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3").unwrap(); let dh = DH::from_params(p, g, q).unwrap(); ctx.set_tmp_dh(dh).unwrap(); --- openssl-sys/Cargo.toml | 1 + openssl-sys/src/lib.rs | 14 +++++ openssl-sys/src/openssl_shim.c | 18 +++++++ openssl/Cargo.toml | 1 + openssl/src/bn/mod.rs | 4 +- openssl/src/dh/mod.rs | 97 ++++++++++++++++++++++++++++++++++ openssl/src/lib.rs | 1 + openssl/src/ssl/mod.rs | 7 +++ 8 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 openssl/src/dh/mod.rs diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 85a6aeb5..e710388a 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -21,6 +21,7 @@ aes_xts = [] aes_ctr = [] npn = [] alpn = [] +rfc5114 = [] [dependencies] libc = "0.1" diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index b3025be1..c2dafb5d 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -20,6 +20,7 @@ pub type BIO_METHOD = c_void; pub type BN_CTX = c_void; pub type COMP_METHOD = c_void; pub type CRYPTO_EX_DATA = c_void; +pub type DH = c_void; pub type ENGINE = c_void; pub type EVP_CIPHER = c_void; pub type EVP_CIPHER_CTX = c_void; @@ -380,6 +381,17 @@ extern "C" { pub fn CRYPTO_memcmp(a: *const c_void, b: *const c_void, len: size_t) -> c_int; + pub fn DH_free(dh: *mut DH); + + #[cfg(feature = "rfc5114")] + pub fn DH_get_1024_160() -> *mut DH; + #[cfg(feature = "rfc5114")] + pub fn DH_get_2048_224() -> *mut DH; + #[cfg(feature = "rfc5114")] + pub fn DH_get_2048_256() -> *mut DH; + + pub fn DH_new_from_params(p: *mut BIGNUM, g: *mut BIGNUM, q: *mut BIGNUM) -> *mut DH; + pub fn ERR_get_error() -> c_ulong; pub fn ERR_lib_error_string(err: c_ulong) -> *const c_char; @@ -664,6 +676,8 @@ extern "C" { 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; + #[link_name = "SSL_CTX_set_tmp_dh_shim"] + pub fn SSL_CTX_set_tmp_dh(s: *mut SSL, dh: *const DH) -> c_long; #[link_name = "X509_get_extensions_shim"] pub fn X509_get_extensions(x: *mut X509) -> *mut stack_st_X509_EXTENSION; } diff --git a/openssl-sys/src/openssl_shim.c b/openssl-sys/src/openssl_shim.c index f0622d2d..ce0ee692 100644 --- a/openssl-sys/src/openssl_shim.c +++ b/openssl-sys/src/openssl_shim.c @@ -1,5 +1,7 @@ #include #include +#include +#include #if OPENSSL_VERSION_NUMBER < 0x1000000L // Copied from openssl crypto/hmac/hmac.c @@ -79,6 +81,22 @@ long SSL_CTX_set_read_ahead_shim(SSL_CTX *ctx, long m) { return SSL_CTX_set_read_ahead(ctx, m); } +long SSL_CTX_set_tmp_dh_shim(SSL_CTX *ctx, DH *dh) { + return SSL_CTX_set_tmp_dh(ctx, dh); +} + +DH *DH_new_from_params(BIGNUM *p, BIGNUM *g, BIGNUM *q) { + DH *dh; + + if ((dh = DH_new()) == NULL) { + return NULL; + } + dh->p = p; + dh->g = g; + dh->q = q; + return dh; +} + long SSL_set_tlsext_host_name_shim(SSL *s, char *name) { return SSL_set_tlsext_host_name(s, name); } diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index c230aa04..660c24d5 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -19,6 +19,7 @@ aes_xts = ["openssl-sys/aes_xts"] aes_ctr = ["openssl-sys/aes_ctr"] npn = ["openssl-sys/npn"] alpn = ["openssl-sys/alpn"] +rfc5114 = ["openssl-sys/rfc5114"] [dependencies.openssl-sys] path = "../openssl-sys" diff --git a/openssl/src/bn/mod.rs b/openssl/src/bn/mod.rs index ccf28337..3c973438 100644 --- a/openssl/src/bn/mod.rs +++ b/openssl/src/bn/mod.rs @@ -397,12 +397,12 @@ impl BigNum { (self.num_bits() + 7) / 8 } - unsafe fn raw(&self) -> *mut ffi::BIGNUM { + pub unsafe fn raw(&self) -> *mut ffi::BIGNUM { let BigNum(n) = *self; n } - unsafe fn raw_ptr(&self) -> *const *mut ffi::BIGNUM { + pub unsafe fn raw_ptr(&self) -> *const *mut ffi::BIGNUM { let BigNum(ref n) = *self; n } diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs new file mode 100644 index 00000000..cbf9d3ab --- /dev/null +++ b/openssl/src/dh/mod.rs @@ -0,0 +1,97 @@ +use ffi; +use ssl::error::SslError; +use bn::BigNum; +use std::mem; +use std::ptr; + +pub struct DH(*mut ffi::DH); + +impl DH { + pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result { + let dh = unsafe { ffi::DH_new_from_params(p.raw(), g.raw(), q.raw()) }; + if dh == ptr::null_mut() { + return Err(SslError::get()); + } + mem::forget(p); + mem::forget(g); + mem::forget(q); + Ok(DH(dh)) + } + + #[cfg(feature = "rfc5114")] + pub fn get_1024_160() -> Result { + let dh = unsafe { ffi::DH_get_1024_160() }; + if dh == ptr::null_mut() { + return Err(SslError::get()); + } + Ok(DH(dh)) + } + + #[cfg(feature = "rfc5114")] + pub fn get_2048_224() -> Result { + let dh = unsafe { ffi::DH_get_2048_224() }; + if dh == ptr::null_mut() { + return Err(SslError::get()); + } + Ok(DH(dh)) + } + + #[cfg(feature = "rfc5114")] + pub fn get_2048_256() -> Result { + let dh = unsafe { ffi::DH_get_2048_256() }; + if dh == ptr::null_mut() { + return Err(SslError::get()); + } + Ok(DH(dh)) + } + + pub unsafe fn raw(&self) -> *mut ffi::DH { + let DH(n) = *self; + n + } + + pub unsafe fn raw_ptr(&self) -> *const *mut ffi::DH { + let DH(ref n) = *self; + n + } +} + +impl Drop for DH { + fn drop(&mut self) { + unsafe { + if !self.raw().is_null() { + ffi::DH_free(self.raw()) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::DH; + use bn::BigNum; + use ssl::SslContext; + use ssl::SslMethod::Sslv23; + + #[test] + #[cfg(feature = "rfc5114")] + fn test_dh_rfc5114() { + let ctx = SslContext::new(Sslv23).unwrap(); + let dh1 = DH::get_1024_160().unwrap(); + ctx.set_tmp_dh(dh1).unwrap(); + let dh2 = DH::get_2048_224().unwrap(); + ctx.set_tmp_dh(dh2).unwrap(); + let dh3 = DH::get_2048_256().unwrap(); + ctx.set_tmp_dh(dh3).unwrap(); + } + + #[test] + fn test_dh() { + let ctx = SslContext::new(Sslv23).unwrap(); + let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597").unwrap(); + let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659").unwrap(); + let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3").unwrap(); + let dh = DH::from_params(p, g, q).unwrap(); + ctx.set_tmp_dh(dh).unwrap(); + } +} diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 62d18dce..f57dcdac 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -20,6 +20,7 @@ pub mod asn1; pub mod bn; pub mod bio; pub mod crypto; +pub mod dh; pub mod ssl; pub mod x509; pub mod nid; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 35180d3a..ee2e1f9f 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -21,6 +21,7 @@ use std::slice; use bio::{MemBio}; use ffi; +use dh::DH; use ssl::error::{SslError, SslSessionClosed, StreamError, OpenSslErrors}; use x509::{X509StoreContext, X509FileType, X509}; use crypto::pkey::PKey; @@ -492,6 +493,12 @@ impl SslContext { } } + pub fn set_tmp_dh(&self, dh: DH) -> Result<(),SslError> { + wrap_ssl_result(unsafe { + ffi::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 + }) + } + #[allow(non_snake_case)] /// Specifies the file that contains trusted CA certificates. pub fn set_CA_file>(&mut self, file: P) -> Result<(),SslError> { From bf16c19f315c83fe4b329730f03e568cbf4c47f9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 1 Sep 2015 11:12:22 -0700 Subject: [PATCH 02/19] Swap order of linking ssl/crypto GNU linkers will sometimes aggressively try to strip objects and archives from a linker command line in a left-to-right fashion. When a linker hits an object file that doesn't satisfy any unresolved symbols, it will discard the object and not re-visit it. This means that currently if symbols are depended upon in libssl then some of the dependencies of libssl (in libcrypto) may have already been stripped, causing a link error. By swapping the order of what's linked it reflects the natural flow of dependencies and the linker should figure everything out for us. --- openssl-sys/build.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index b4a00566..5f934888 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -36,12 +36,12 @@ fn main() { Some(ref v) => v.split(":").collect(), None => if target.contains("windows") { if get_mingw_in_path().is_some() && lib_dir.is_none() && include_dir.is_none() { - vec!("eay32", "ssleay32") + vec!["ssleay32", "eay32"] } else { - vec!("eay32", "ssl32") + vec!["ssl32", "eay32"] } } else { - vec!("crypto", "ssl") + vec!["ssl", "crypto"] } }; From 164f3f08738a15307c8a6e9874a21fe40a9584c5 Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Wed, 1 Jul 2015 15:36:46 -0400 Subject: [PATCH 03/19] openssl/ssl: fix some of the comment text where I missed replacing NPN with ALPN --- openssl/src/ssl/tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index 9198a642..40755977 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -403,7 +403,7 @@ fn test_state() { assert_eq!(stream.get_state_string_long(), "SSL negotiation finished successfully"); } -/// Tests that connecting with the client using NPN, but the server not does not +/// Tests that connecting with the client using ALPN, but the server not does not /// break the existing connection behavior. #[test] #[cfg(feature = "alpn")] @@ -420,7 +420,7 @@ fn test_connect_with_unilateral_alpn() { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err) }; - // Since the socket to which we connected is not configured to use NPN, + // Since the socket to which we connected is not configured to use ALPN, // there should be no selected protocol... assert!(stream.get_selected_alpn_protocol().is_none()); } @@ -453,7 +453,7 @@ fn test_connect_with_unilateral_npn() { #[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. + // 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); From 50c5042c705a399ebc178b204a1e6148a26966e1 Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Tue, 1 Sep 2015 17:09:19 -0400 Subject: [PATCH 04/19] ssl/npn+alpn: adjust protocol selection to fail if no protocols match The current behavior causes a server written using rust-openssl to (if it cannot negotiate a protocol) fallback to the first protocol it has avaliable. This makes it impossible to detect protocol mismatches. This updates our selection to be more similar to how openssl's s_server behaves: non-matching protocols are not supplied with a fallback. Note that some setups may actually want a fallback protocol supplied via ALPN. To support those cases, we should consider adding a generic callback that allows protocol selection to be entirely controlled by the programmer. For the purposes of having a sane default, however, not supplying a default (and mimicing s_server's behavior) is the best choice. --- openssl-sys/src/lib.rs | 6 +++--- openssl/src/ssl/mod.rs | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 9b5fd744..91b090e2 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -167,11 +167,11 @@ macro_rules! import_options { include!("ssl_options.rs"); -#[cfg(feature = "npn")] +#[cfg(any(feature = "npn", feature = "alpn"))] pub const OPENSSL_NPN_UNSUPPORTED: c_int = 0; -#[cfg(feature = "npn")] +#[cfg(any(feature = "npn", feature = "alpn"))] pub const OPENSSL_NPN_NEGOTIATED: c_int = 1; -#[cfg(feature = "npn")] +#[cfg(any(feature = "npn", feature = "alpn"))] pub const OPENSSL_NPN_NO_OVERLAP: c_int = 2; pub const V_ASN1_GENERALIZEDTIME: c_int = 24; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index ee2e1f9f..1f198643 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -308,8 +308,11 @@ unsafe fn select_proto_using(ssl: *mut ffi::SSL, 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 + if ffi::SSL_select_next_proto(out, outlen, inbuf, inlen, client, client_len) != ffi::OPENSSL_NPN_NEGOTIATED { + ffi::SSL_TLSEXT_ERR_NOACK + } else { + ffi::SSL_TLSEXT_ERR_OK + } } /// The function is given as the callback to `SSL_CTX_set_next_proto_select_cb`. From 4781a3304a43d71d32df076eb05d0d056e7881e7 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Sep 2015 19:58:45 -0400 Subject: [PATCH 05/19] Make the docs say that load_pub/save_pub methods take DER bytes --- openssl/src/crypto/pkey.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 48308381..010ffd8f 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -138,14 +138,14 @@ impl PKey { } /** - * Returns a serialized form of the public key, suitable for load_pub(). + * Returns a DER serialized form of the public key, suitable for load_pub(). */ pub fn save_pub(&self) -> Vec { self._tostr(ffi::i2d_RSA_PUBKEY) } /** - * Loads a serialized form of the public key, as produced by save_pub(). + * Loads a DER serialized form of the public key, as produced by save_pub(). */ pub fn load_pub(&mut self, s: &[u8]) { self._fromstr(s, ffi::d2i_RSA_PUBKEY); From 02b109bf0417026fe7825ef5abd3e7bf4595241f Mon Sep 17 00:00:00 2001 From: Mathijs van de Nes Date: Thu, 10 Sep 2015 12:47:26 +0200 Subject: [PATCH 06/19] Check _fromstr function for success --- openssl/src/crypto/pkey.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 48308381..5d4bd7f1 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -110,11 +110,16 @@ impl PKey { } } - fn _fromstr(&mut self, s: &[u8], f: unsafe extern "C" fn(*const *mut ffi::RSA, *const *const u8, c_uint) -> *mut ffi::RSA) { + fn _fromstr(&mut self, s: &[u8], f: unsafe extern "C" fn(*const *mut ffi::RSA, *const *const u8, c_uint) -> *mut ffi::RSA) -> bool { unsafe { let rsa = ptr::null_mut(); f(&rsa, &s.as_ptr(), s.len() as c_uint); - ffi::EVP_PKEY_set1_RSA(self.evp, rsa); + if !rsa.is_null() { + ffi::EVP_PKEY_set1_RSA(self.evp, rsa) == 1 + } + else { + false + } } } @@ -148,8 +153,9 @@ impl PKey { * Loads a serialized form of the public key, as produced by save_pub(). */ pub fn load_pub(&mut self, s: &[u8]) { - self._fromstr(s, ffi::d2i_RSA_PUBKEY); - self.parts = Parts::Public; + if self._fromstr(s, ffi::d2i_RSA_PUBKEY) { + self.parts = Parts::Public; + } } /** @@ -164,8 +170,9 @@ impl PKey { * save_priv(). */ pub fn load_priv(&mut self, s: &[u8]) { - self._fromstr(s, ffi::d2i_RSAPrivateKey); - self.parts = Parts::Both; + if self._fromstr(s, ffi::d2i_RSAPrivateKey) { + self.parts = Parts::Both; + } } /// Stores private key as a PEM From 0eb2f0ecfacf25f1055312ec9a715f25398d527d Mon Sep 17 00:00:00 2001 From: Mathijs van de Nes Date: Thu, 10 Sep 2015 12:58:52 +0200 Subject: [PATCH 07/19] Check rsa.is_null() before passing it to RSA_size RSA_size will cause an segmentation fault if it is null --- openssl/src/crypto/pkey.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 5d4bd7f1..980e8216 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -205,7 +205,13 @@ impl PKey { */ pub fn size(&self) -> usize { unsafe { - ffi::RSA_size(ffi::EVP_PKEY_get1_RSA(self.evp)) as usize + let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); + if rsa.is_null() { + 0 + } + else { + ffi::RSA_size(rsa) as usize + } } } @@ -244,6 +250,9 @@ impl PKey { pub fn max_data(&self) -> usize { unsafe { let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); + if rsa.is_null() { + return 0; + } let len = ffi::RSA_size(rsa); // 41 comes from RSA_public_encrypt(3) for OAEP @@ -254,6 +263,9 @@ impl PKey { pub fn encrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec { unsafe { let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); + if rsa.is_null() { + panic!("Could not get RSA key for encryption"); + } let len = ffi::RSA_size(rsa); assert!(s.len() < self.max_data()); @@ -279,6 +291,9 @@ impl PKey { pub fn decrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec { unsafe { let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); + if rsa.is_null() { + panic!("Could not get RSA key for decryption"); + } let len = ffi::RSA_size(rsa); assert_eq!(s.len() as c_int, ffi::RSA_size(rsa)); @@ -337,6 +352,9 @@ impl PKey { unsafe { let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); let len = ffi::RSA_size(rsa); + if rsa.is_null() { + panic!("Could not get RSA key for signing"); + } let mut r = repeat(0u8).take(len as usize + 1).collect::>(); let mut len = 0; @@ -360,6 +378,9 @@ impl PKey { pub fn verify_with_hash(&self, h: &[u8], s: &[u8], hash: hash::Type) -> bool { unsafe { let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); + if rsa.is_null() { + panic!("Could not get RSA key for verification"); + } let rv = ffi::RSA_verify( openssl_hash_nid(hash), From 3be32528e5b36ff80d5df9c569027bb8c8bcffe5 Mon Sep 17 00:00:00 2001 From: Mathijs van de Nes Date: Fri, 11 Sep 2015 09:23:51 +0200 Subject: [PATCH 08/19] Add tests to ensure a panic occurs instead of segv --- openssl/src/crypto/pkey.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 980e8216..d59a9cfb 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -560,4 +560,36 @@ mod tests { assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY")); assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY")); } + + #[test] + #[should_panic(expected = "Could not get RSA key for encryption")] + fn test_nokey_encrypt() { + let mut pkey = super::PKey::new(); + pkey.load_pub(&[]); + pkey.encrypt(&[]); + } + + #[test] + #[should_panic(expected = "Could not get RSA key for decryption")] + fn test_nokey_decrypt() { + let mut pkey = super::PKey::new(); + pkey.load_priv(&[]); + pkey.decrypt(&[]); + } + + #[test] + #[should_panic(expected = "Could not get RSA key for signing")] + fn test_nokey_sign() { + let mut pkey = super::PKey::new(); + pkey.load_priv(&[]); + pkey.sign(&[]); + } + + #[test] + #[should_panic(expected = "Could not get RSA key for verification")] + fn test_nokey_verify() { + let mut pkey = super::PKey::new(); + pkey.load_pub(&[]); + pkey.verify(&[], &[]); + } } From 87d5c0e4291051676d8e88513310e9eaa81aca0b Mon Sep 17 00:00:00 2001 From: Mathijs van de Nes Date: Fri, 11 Sep 2015 09:24:24 +0200 Subject: [PATCH 09/19] Fix one call to RSA_size found by tests --- openssl/src/crypto/pkey.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index d59a9cfb..5bf0e81e 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -351,10 +351,10 @@ impl PKey { pub fn sign_with_hash(&self, s: &[u8], hash: hash::Type) -> Vec { unsafe { let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); - let len = ffi::RSA_size(rsa); if rsa.is_null() { panic!("Could not get RSA key for signing"); } + let len = ffi::RSA_size(rsa); let mut r = repeat(0u8).take(len as usize + 1).collect::>(); let mut len = 0; From 6666a1818ac1d3e126bf632132f941e2aeb0e351 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 1 Sep 2015 10:04:05 +0200 Subject: [PATCH 10/19] Add DH::from_pem() to load DH parameters from a file --- openssl-sys/src/lib.rs | 3 ++- openssl/src/dh/mod.rs | 28 +++++++++++++++++++++++++++- openssl/test/dhparams.pem | 8 ++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 openssl/test/dhparams.pem diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 9b5fd744..c2c6157c 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -477,7 +477,8 @@ extern "C" { #[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; - + pub fn PEM_read_bio_DHparams(bio: *mut BIO, out: *mut *mut DH, callback: Option, + user_data: *mut c_void) -> *mut DH; pub fn PEM_read_bio_X509(bio: *mut BIO, out: *mut *mut X509, callback: Option, user_data: *mut c_void) -> *mut X509; pub fn PEM_read_bio_X509_REQ(bio: *mut BIO, out: *mut *mut X509_REQ, callback: Option, diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index cbf9d3ab..7be5dd04 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -1,5 +1,8 @@ use ffi; -use ssl::error::SslError; +use std::io; +use std::io::prelude::*; +use ssl::error::{SslError, StreamError}; +use bio::MemBio; use bn::BigNum; use std::mem; use std::ptr; @@ -18,6 +21,16 @@ impl DH { Ok(DH(dh)) } + pub fn from_pem(reader: &mut R) -> Result where R: Read { + let mut mem_bio = try!(MemBio::new()); + try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); + let dh = unsafe { + ffi::PEM_read_bio_DHparams(mem_bio.get_handle(), ptr::null_mut(), None, ptr::null_mut()) + }; + try_ssl_null!(dh); + Ok(DH(dh)) + } + #[cfg(feature = "rfc5114")] pub fn get_1024_160() -> Result { let dh = unsafe { ffi::DH_get_1024_160() }; @@ -68,6 +81,8 @@ impl Drop for DH { #[cfg(test)] mod tests { + use std::fs::File; + use std::path::Path; use super::DH; use bn::BigNum; use ssl::SslContext; @@ -94,4 +109,15 @@ mod tests { let dh = DH::from_params(p, g, q).unwrap(); ctx.set_tmp_dh(dh).unwrap(); } + + #[test] + fn test_dh_from_pem() { + let ctx = SslContext::new(Sslv23).unwrap(); + let pem_path = Path::new("test/dhparams.pem"); + let mut file = File::open(&pem_path) + .ok() + .expect("Failed to open `test/dhparams.pem`"); + let dh = DH::from_pem(&mut file).ok().expect("Failed to load PEM"); + ctx.set_tmp_dh(dh).unwrap(); + } } diff --git a/openssl/test/dhparams.pem b/openssl/test/dhparams.pem new file mode 100644 index 00000000..6e4d4c68 --- /dev/null +++ b/openssl/test/dhparams.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAh3Betv+hf5jNsOmGXU8oxuABD2B8r0yU8FVgjnCZBSVo61qJ0A2d +J6r8rYKbjtolnrZN/V4IPSzYvxurHbu8nbiFVyhOySPchI2Fu+YT/HsSe/0MH9bW +gJTNzmutWoy9VxtWLCmXnOSZHep3MZ1ZNimno6Kh2qQ7VJr0+KF8GbxUKOPv4SqK +NBwouIQXFc0pE9kGhcGKbr7TnHhyJFCRLNP1OVDQZbcoKjk1Vh+5sy7vM2VUTQmM +yOToT2LEZVAUJXNumcYMki9MIwfYCwYZbNt0ZEolyHzUEesuyHfU1eJd6+sKEjUz +5GteQIR7AehxZIS+cytu7BXO7B0owLJ2awIBAg== +-----END DH PARAMETERS----- From 6a2b4402e9f2e93008bd47470d88e12337edcfae Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 1 Sep 2015 09:25:41 +0200 Subject: [PATCH 11/19] Use try_ssl_null!() when relevant --- openssl/src/dh/mod.rs | 20 ++++---------------- openssl/src/ssl/mod.rs | 15 +++------------ 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs index cbf9d3ab..64429fd8 100644 --- a/openssl/src/dh/mod.rs +++ b/openssl/src/dh/mod.rs @@ -8,10 +8,7 @@ pub struct DH(*mut ffi::DH); impl DH { pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result { - let dh = unsafe { ffi::DH_new_from_params(p.raw(), g.raw(), q.raw()) }; - if dh == ptr::null_mut() { - return Err(SslError::get()); - } + let dh = try_ssl_null!(unsafe { ffi::DH_new_from_params(p.raw(), g.raw(), q.raw()) }); mem::forget(p); mem::forget(g); mem::forget(q); @@ -20,28 +17,19 @@ impl DH { #[cfg(feature = "rfc5114")] pub fn get_1024_160() -> Result { - let dh = unsafe { ffi::DH_get_1024_160() }; - if dh == ptr::null_mut() { - return Err(SslError::get()); - } + let dh = try_ssl_null!(unsafe { ffi::DH_get_1024_160() }); Ok(DH(dh)) } #[cfg(feature = "rfc5114")] pub fn get_2048_224() -> Result { - let dh = unsafe { ffi::DH_get_2048_224() }; - if dh == ptr::null_mut() { - return Err(SslError::get()); - } + let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_224() }); Ok(DH(dh)) } #[cfg(feature = "rfc5114")] pub fn get_2048_256() -> Result { - let dh = unsafe { ffi::DH_get_2048_256() }; - if dh == ptr::null_mut() { - return Err(SslError::get()); - } + let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_256() }); Ok(DH(dh)) } diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index ee2e1f9f..20c9234c 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -432,10 +432,7 @@ impl SslContext { pub fn new(method: SslMethod) -> Result { init(); - let ctx = unsafe { ffi::SSL_CTX_new(method.to_raw()) }; - if ctx == ptr::null_mut() { - return Err(SslError::get()); - } + let ctx = try_ssl_null!(unsafe { ffi::SSL_CTX_new(method.to_raw()) }); let ctx = SslContext { ctx: ctx }; @@ -690,10 +687,7 @@ impl Drop for Ssl { impl Ssl { pub fn new(ctx: &SslContext) -> Result { - let ssl = unsafe { ffi::SSL_new(ctx.ctx) }; - if ssl == ptr::null_mut() { - return Err(SslError::get()); - } + let ssl = try_ssl_null!(unsafe { ffi::SSL_new(ctx.ctx) }); let ssl = Ssl { ssl: ssl }; Ok(ssl) } @@ -1019,10 +1013,7 @@ impl DirectStream { 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()); - } + let bio = try_ssl_null!(ffi::BIO_new_socket(sock, 0)); ffi::SSL_set_bio(ssl.ssl, bio, bio); } From 4c28eb706e06463f1e00e143d2d52d8e23827c1b Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Wed, 16 Sep 2015 13:23:34 -0400 Subject: [PATCH 12/19] ssl/alpn: test mismatch between protocols resulting in None --- openssl/src/ssl/tests.rs | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index 40755977..344bcfe8 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -628,6 +628,49 @@ fn test_alpn_server_advertise_multiple() { assert_eq!(b"spdy/3.1", stream.get_selected_alpn_protocol().unwrap()); } +/// Test that Servers supporting ALPN don't report a protocol when none of their protocols match +/// the client's reported protocol. +#[test] +#[cfg(feature = "alpn")] +fn test_alpn_server_select_none() { + let localhost = "127.0.0.1:15422"; + 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::accept(&listener_ctx, stream).unwrap(); + }); + + let mut ctx = SslContext::new(Sslv23).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER, None); + ctx.set_alpn_protocols(&[b"http/2"]); + 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) + }; + + // Since the protocols from the server and client don't overlap at all, no protocol is selected + assert_eq!(None, stream.get_selected_alpn_protocol()); +} + + #[cfg(feature="dtlsv1")] #[cfg(test)] mod dtlsv1 { From a91b6bf3bd216c13f0dafdbbf9ef33f15dd103bf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 22 Sep 2015 11:29:47 -0700 Subject: [PATCH 13/19] Enable testing on Windows via AppVeyor This abolishes the test.sh script which spawns a bunch of `openssl` instances to instead run/manage the binary in-process (providing more isolation to boot). The tests have been updated accordingly and the `connected_socket` dependency was also dropped in favor of `net2` as it the former doesn't work on Windows. --- .travis.yml | 2 - README.md | 14 --- appveyor.yml | 25 +++++ openssl/Cargo.toml | 4 +- openssl/src/lib.rs | 3 +- openssl/src/ssl/tests.rs | 224 +++++++++++++++++++++++++++++---------- openssl/test/test.sh | 21 ---- 7 files changed, 193 insertions(+), 100 deletions(-) create mode 100644 appveyor.yml delete mode 100755 openssl/test/test.sh diff --git a/.travis.yml b/.travis.yml index 2b056d10..8ee8c929 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,6 @@ env: - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv2 aes_xts npn alpn aes_ctr" before_install: - (test $TRAVIS_OS_NAME == "osx" || ./openssl/test/build.sh) -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)) diff --git a/README.md b/README.md index 06b9b7f8..82dd2e4f 100644 --- a/README.md +++ b/README.md @@ -64,18 +64,4 @@ The build script can be configured via environment variables: If either `OPENSSL_LIB_DIR` or `OPENSSL_INCLUDE_DIR` are specified, then the build script will skip the pkg-config step. -## Testing -Several tests expect a local test server to be running to bounce requests off -of. It's easy to do this. Open a separate terminal window and `cd` to the -rust-openssl directory. Then run one of the following command: - -```bash -./openssl/test/test.sh -``` - -This will boot a bunch of `openssl s_server` processes that the tests connect -to. Then in the original terminal, run `cargo test`. If everything is set up -correctly, all tests should pass. You can stop the servers with `killall -openssl`. - [1]: http://slproweb.com/products/Win32OpenSSL.html diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..31c41ee1 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,25 @@ +environment: + OPENSSL_INCLUDE_DIR: C:\OpenSSL\include + OPENSSL_LIB_DIR: C:\OpenSSL\lib + OPENSSL_LIBS: ssleay32:libeay32 + matrix: + - TARGET: i686-pc-windows-gnu + BITS: 32 + - TARGET: x86_64-pc-windows-msvc + BITS: 64 +install: + - ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2d.exe" + - Win%BITS%OpenSSL-1_0_2d.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL" + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" + - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin + - SET PATH=%PATH%;C:\MinGW\bin + - rustc -V + - cargo -V + +build: false + +# Don't run doctests due to rust-lang/cargo#1592 +test_script: + - cargo test --lib --manifest-path openssl/Cargo.toml + diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 9d16ccd6..8ade8101 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -32,6 +32,4 @@ libc = "0.1" [dev-dependencies] rustc-serialize = "0.3" - -[dev-dependencies.connected_socket] -connected_socket = "0.0.1" +net2 = "0.2.13" diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index cc74726f..49a7fd4a 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -11,8 +11,7 @@ extern crate openssl_sys as ffi; extern crate rustc_serialize as serialize; #[cfg(test)] -#[cfg(any(feature="dtlsv1", feature="dtlsv1_2"))] -extern crate connected_socket; +extern crate net2; mod macros; diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index 344bcfe8..033a3b86 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -1,12 +1,13 @@ #![allow(unused_imports)] -use std::net::TcpStream; -use std::io; -use std::io::prelude::*; -use std::path::Path; -use std::net::TcpListener; -use std::thread; use std::fs::File; +use std::io::prelude::*; +use std::io::{self, BufReader}; +use std::iter; +use std::net::{TcpStream, TcpListener, SocketAddr}; +use std::path::Path; +use std::process::{Command, Child, Stdio, ChildStdin}; +use std::thread; use crypto::hash::Type::{SHA256}; use ssl; @@ -26,20 +27,140 @@ use ssl::SslMethod::Dtlsv1; #[cfg(feature="sslv2")] use ssl::SslMethod::Sslv2; #[cfg(feature="dtlsv1")] -use connected_socket::Connect; +use net2::UdpSocketExt; + +fn next_addr() -> SocketAddr { + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + static PORT: AtomicUsize = ATOMIC_USIZE_INIT; + let port = 15411 + PORT.fetch_add(1, Ordering::SeqCst); + + format!("127.0.0.1:{}", port).parse().unwrap() +} + +struct Server { + p: Child, +} + +impl Server { + fn spawn(args: &[&str], input: Option>) + -> (Server, SocketAddr) { + let addr = next_addr(); + let mut child = Command::new("openssl").arg("s_server") + .arg("-accept").arg(addr.port().to_string()) + .args(args) + .arg("-cert").arg("cert.pem") + .arg("-key").arg("key.pem") + .arg("-no_dhe") + .current_dir("test") + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .stdin(Stdio::piped()) + .spawn().unwrap(); + let stdin = child.stdin.take().unwrap(); + if let Some(mut input) = input { + thread::spawn(move || input(stdin)); + } + (Server { p: child }, addr) + } + + fn new_tcp(args: &[&str]) -> (Server, TcpStream) { + let (server, addr) = Server::spawn(args, None); + loop { + match TcpStream::connect(&addr) { + Ok(s) => return (server, s), + Err(ref e) if e.kind() == io::ErrorKind::ConnectionRefused => { + thread::sleep_ms(100); + } + Err(e) => panic!("wut: {}", e), + } + } + } + + fn new() -> (Server, TcpStream) { + Server::new_tcp(&["-www"]) + } + + #[cfg(any(feature = "alpn", feature = "npn"))] + fn new_alpn() -> (Server, TcpStream) { + Server::new_tcp(&["-www", "-nextprotoneg", "http/1.1,spdy/3.1", + "-alpn", "http/1.1,spdy/3.1"]) + } + + #[cfg(feature = "dtlsv1")] + fn new_dtlsv1(input: I) -> (Server, UdpConnected) + where I: IntoIterator, + I::IntoIter: Send + 'static + { + let mut input = input.into_iter(); + let (s, addr) = Server::spawn(&["-dtls1"], Some(Box::new(move |mut io| { + for s in input.by_ref() { + if io.write_all(s.as_bytes()).is_err() { + break + } + } + }))); + // Need to wait for the UDP socket to get bound in our child process, + // but don't currently have a great way to do that so just wait for a + // bit. + thread::sleep_ms(100); + let socket = UdpSocket::bind(next_addr()).unwrap(); + socket.connect(&addr).unwrap(); + (s, UdpConnected(socket)) + } +} + +impl Drop for Server { + fn drop(&mut self) { + let _ = self.p.kill(); + let _ = self.p.wait(); + } +} #[cfg(feature = "dtlsv1")] -mod udp { - use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; +struct UdpConnected(UdpSocket); - static UDP_PORT: AtomicUsize = ATOMIC_USIZE_INIT; - - pub fn next_server<'a>() -> String { - let diff = UDP_PORT.fetch_add(1, Ordering::SeqCst); - format!("127.0.0.1:{}", 15411 + diff) +#[cfg(feature = "dtlsv1")] +impl Read for UdpConnected { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.recv_from(buf).map(|(s, _)| s) } } +#[cfg(feature = "dtlsv1")] +impl Write for UdpConnected { + #[cfg(unix)] + fn write(&mut self, buf: &[u8]) -> io::Result { + use std::os::unix::prelude::*; + use libc; + let n = unsafe { + libc::send(self.0.as_raw_fd(), buf.as_ptr() as *const _, + buf.len() as libc::size_t, 0) + }; + if n < 0 { + Err(io::Error::last_os_error()) + } else { + Ok(n as usize) + } + } + + #[cfg(windows)] + fn write(&mut self, buf: &[u8]) -> io::Result { + use std::os::windows::prelude::*; + use libc; + let n = unsafe { + libc::send(self.0.as_raw_socket(), buf.as_ptr() as *const _, + buf.len() as libc::c_int, 0) + }; + if n < 0 { + Err(io::Error::last_os_error()) + } else { + Ok(n as usize) + } + } + + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + macro_rules! run_test( ($module:ident, $blk:expr) => ( #[cfg(test)] @@ -56,22 +177,18 @@ macro_rules! run_test( use crypto::hash::Type::SHA256; use x509::X509StoreContext; use serialize::hex::FromHex; + use super::Server; #[test] fn sslv23() { - let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); + let (_s, stream) = Server::new(); $blk(SslMethod::Sslv23, stream); } #[test] #[cfg(feature="dtlsv1")] fn dtlsv1() { - use connected_socket::Connect; - - let sock = UdpSocket::bind("127.0.0.1:0").unwrap(); - let server = super::udp::next_server(); - let stream = sock.connect(&server[..]).unwrap(); - + let (_s, stream) = Server::new_dtlsv1(Some("hello")); $blk(SslMethod::Dtlsv1, stream); } } @@ -244,7 +361,7 @@ run_test!(verify_callback_data, |method, stream| { // Make sure every write call translates to a write call to the underlying socket. #[test] fn test_write_hits_stream() { - let listener = TcpListener::bind("localhost:0").unwrap(); + let listener = TcpListener::bind(next_addr()).unwrap(); let addr = listener.local_addr().unwrap(); let guard = thread::spawn(move || { @@ -314,7 +431,7 @@ run_test!(clear_ctx_options, |method, _| { #[test] fn test_write() { - let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); + let (_s, stream) = Server::new(); let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); @@ -324,7 +441,7 @@ fn test_write() { #[test] fn test_write_direct() { - let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); + let (_s, stream) = Server::new(); let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); @@ -333,7 +450,8 @@ fn test_write_direct() { } run_test!(get_peer_certificate, |method, stream| { - let stream = SslStream::connect_generic(&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"; @@ -344,19 +462,19 @@ run_test!(get_peer_certificate, |method, stream| { #[test] #[cfg(feature = "dtlsv1")] 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 (_s, stream) = Server::new_dtlsv1(iter::repeat("y\n")); - let mut stream = SslStream::connect_generic(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); - stream.write_all("hello".as_bytes()).unwrap(); + let mut stream = SslStream::connect_generic(&SslContext::new(Dtlsv1).unwrap(), + stream).unwrap(); + stream.write_all(b"hello").unwrap(); stream.flush().unwrap(); - stream.write_all(" there".as_bytes()).unwrap(); + stream.write_all(b" there").unwrap(); stream.flush().unwrap(); } #[test] fn test_read() { - let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); + let (_s, tcp) = Server::new(); 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(); @@ -365,7 +483,7 @@ fn test_read() { #[test] fn test_read_direct() { - let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); + let (_s, tcp) = Server::new(); 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(); @@ -374,7 +492,7 @@ fn test_read_direct() { #[test] fn test_pending() { - let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); + let (_s, tcp) = Server::new(); 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(); @@ -397,7 +515,7 @@ fn test_pending() { #[test] fn test_state() { - let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); + let (_s, tcp) = Server::new(); let stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); assert_eq!(stream.get_state_string(), "SSLOK "); assert_eq!(stream.get_state_string_long(), "SSL negotiation finished successfully"); @@ -408,7 +526,7 @@ fn test_state() { #[test] #[cfg(feature = "alpn")] fn test_connect_with_unilateral_alpn() { - let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); + let (_s, stream) = Server::new(); 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"]); @@ -430,7 +548,7 @@ fn test_connect_with_unilateral_alpn() { #[test] #[cfg(feature = "npn")] fn test_connect_with_unilateral_npn() { - let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); + let (_s, stream) = Server::new(); let mut ctx = SslContext::new(Sslv23).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, None); ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]); @@ -452,9 +570,7 @@ fn test_connect_with_unilateral_npn() { #[test] #[cfg(feature = "alpn")] fn test_connect_with_alpn_successful_multiple_matching() { - // 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 (_s, stream) = Server::new_alpn(); 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"]); @@ -476,9 +592,7 @@ fn test_connect_with_alpn_successful_multiple_matching() { #[test] #[cfg(feature = "npn")] fn test_connect_with_npn_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 (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Sslv23).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, None); ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]); @@ -501,9 +615,7 @@ fn test_connect_with_npn_successful_multiple_matching() { #[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 (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Sslv23).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, None); ctx.set_alpn_protocols(&[b"spdy/3.1"]); @@ -527,9 +639,7 @@ fn test_connect_with_alpn_successful_single_match() { #[test] #[cfg(feature = "npn")] fn test_connect_with_npn_successful_single_match() { - // 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 (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Sslv23).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, None); ctx.set_npn_protocols(&[b"spdy/3.1"]); @@ -551,8 +661,8 @@ fn test_connect_with_npn_successful_single_match() { #[test] #[cfg(feature = "npn")] fn test_npn_server_advertise_multiple() { - let localhost = "127.0.0.1:15450"; - let listener = TcpListener::bind(localhost).unwrap(); + let listener = TcpListener::bind(next_addr()).unwrap(); + let localhost = listener.local_addr().unwrap(); // We create a different context instance for the server... let listener_ctx = { let mut ctx = SslContext::new(Sslv23).unwrap(); @@ -592,8 +702,8 @@ fn test_npn_server_advertise_multiple() { #[test] #[cfg(feature = "alpn")] fn test_alpn_server_advertise_multiple() { - let localhost = "127.0.0.1:15421"; - let listener = TcpListener::bind(localhost).unwrap(); + let listener = TcpListener::bind(next_addr()).unwrap(); + let localhost = listener.local_addr().unwrap(); // We create a different context instance for the server... let listener_ctx = { let mut ctx = SslContext::new(Sslv23).unwrap(); @@ -633,8 +743,8 @@ fn test_alpn_server_advertise_multiple() { #[test] #[cfg(feature = "alpn")] fn test_alpn_server_select_none() { - let localhost = "127.0.0.1:15422"; - let listener = TcpListener::bind(localhost).unwrap(); + let listener = TcpListener::bind(next_addr()).unwrap(); + let localhost = listener.local_addr().unwrap(); // We create a different context instance for the server... let listener_ctx = { let mut ctx = SslContext::new(Sslv23).unwrap(); @@ -696,9 +806,7 @@ mod dtlsv1 { #[test] #[cfg(feature = "dtlsv1")] fn test_read_dtlsv1() { - let sock = UdpSocket::bind("127.0.0.1:0").unwrap(); - let server = udp::next_server(); - let stream = sock.connect(&server[..]).unwrap(); + let (_s, stream) = Server::new_dtlsv1(Some("hello")); let mut stream = SslStream::connect_generic(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); let mut buf = [0u8;100]; @@ -708,6 +816,6 @@ fn test_read_dtlsv1() { #[test] #[cfg(feature = "sslv2")] fn test_sslv2_connect_failure() { - let tcp = TcpStream::connect("127.0.0.1:15420").unwrap(); + let (_s, tcp) = Server::new_tcp(&["-no_ssl2", "-www"]); SslStream::connect_generic(&SslContext::new(Sslv2).unwrap(), tcp).err().unwrap(); } diff --git a/openssl/test/test.sh b/openssl/test/test.sh deleted file mode 100755 index 9beb37c3..00000000 --- a/openssl/test/test.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -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" -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 - return -fi - -for port in `seq 15411 15430`; do - echo hello | openssl s_server -accept $port -dtls1 -cert cert.pem \ - -key key.pem 2>&1 >/dev/null & -done - -# the server for the test ssl::tests::test_write_dtlsv1 must wait to receive -# data from the client -yes | openssl s_server -accept 15410 -dtls1 -cert cert.pem -key key.pem 2>&1 >/dev/null & From 28320a65a734b2b38301ef149746a44cb23cd366 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 1 Sep 2015 10:56:33 +0200 Subject: [PATCH 14/19] Add SSL::set_ecdh_auto() This sets automatic curve selection and enables ECDH support. Requires LibreSSL or OpenSSL >= 1.0.2, so behind a feature gate. --- openssl-sys/Cargo.toml | 1 + openssl-sys/src/lib.rs | 3 +++ openssl-sys/src/openssl_shim.c | 6 ++++++ openssl/Cargo.toml | 1 + openssl/src/ssl/mod.rs | 8 ++++++++ 5 files changed, 19 insertions(+) diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 0e78b0ea..5a01318c 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -22,6 +22,7 @@ aes_ctr = [] npn = [] alpn = [] rfc5114 = [] +ecdh_auto = [] [dependencies] libc = "0.1" diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 3f5f7623..45d03ac8 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -675,6 +675,9 @@ 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; + #[cfg(feature = "ecdh_auto")] + #[link_name = "SSL_CTX_set_ecdh_auto_shim"] + pub fn SSL_CTX_set_ecdh_auto(ssl: *mut SSL_CTX, onoff: c_int) -> c_int; #[link_name = "SSL_set_tlsext_host_name_shim"] pub fn SSL_set_tlsext_host_name(s: *mut SSL, name: *const c_char) -> c_long; #[link_name = "SSL_CTX_set_tmp_dh_shim"] diff --git a/openssl-sys/src/openssl_shim.c b/openssl-sys/src/openssl_shim.c index ce0ee692..7fabe06e 100644 --- a/openssl-sys/src/openssl_shim.c +++ b/openssl-sys/src/openssl_shim.c @@ -85,6 +85,12 @@ long SSL_CTX_set_tmp_dh_shim(SSL_CTX *ctx, DH *dh) { return SSL_CTX_set_tmp_dh(ctx, dh); } +#if OPENSSL_VERSION_NUMBER >= 0x1000200L +int SSL_CTX_set_ecdh_auto_shim(SSL_CTX *ctx, int onoff) { + return SSL_CTX_set_ecdh_auto(ctx, onoff); +} +#endif + DH *DH_new_from_params(BIGNUM *p, BIGNUM *g, BIGNUM *q) { DH *dh; diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 8ade8101..c70c3ad3 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -20,6 +20,7 @@ aes_ctr = ["openssl-sys/aes_ctr"] npn = ["openssl-sys/npn"] alpn = ["openssl-sys/alpn"] rfc5114 = ["openssl-sys/rfc5114"] +ecdh_auto = ["openssl-sys/ecdh_auto"] [dependencies.openssl-sys] path = "../openssl-sys" diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 3adf89e6..40e06e93 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -570,6 +570,14 @@ impl SslContext { }) } + #[cfg(feature = "ecdh_auto")] + pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(),SslError> { + wrap_ssl_result( + unsafe { + ffi::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_int) + }) + } + pub fn set_options(&mut self, option: SslContextOptions) -> SslContextOptions { let raw_bits = option.bits(); let ret = unsafe { From ccc6d07da3b01fef78d9bc109aab8edd9ec4ccf1 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Fri, 25 Sep 2015 15:23:52 +0200 Subject: [PATCH 15/19] Add an ecdh_auto description --- openssl/src/ssl/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 40e06e93..a0553b44 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -570,6 +570,10 @@ impl SslContext { }) } + /// If `onoff` is set to `true`, enable ECDHE for key exchange with compatible + /// clients, and automatically select an appropriate elliptic curve. + /// + /// This method requires OpenSSL >= 1.2.0 or LibreSSL and the `ecdh_auto` feature. #[cfg(feature = "ecdh_auto")] pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(),SslError> { wrap_ssl_result( From df93e5e90bfb4f39c9583ac2e2e83a832afaf1c1 Mon Sep 17 00:00:00 2001 From: John Downey Date: Fri, 2 Oct 2015 16:13:22 -0500 Subject: [PATCH 16/19] Update documentation about SSLv23 In OpenSSL world, the SSLv23 option is a poorly name method that will negotiate what version of TLS or SSL to use. It starts with the best version the library supports and then precedes to keep trying all the way down to SSL 2.0. --- 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 a0553b44..360f3f3e 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -106,7 +106,8 @@ pub enum SslMethod { #[cfg(feature = "sslv2")] /// Only support the SSLv2 protocol, requires the `sslv2` feature. Sslv2, - /// Support the SSLv2, SSLv3 and TLSv1 protocols. + /// Support the SSLv2, SSLv3, TLSv1, TLSv1.1, and TLSv1.2 protocols depending on what the + /// linked OpenSSL library supports. Sslv23, /// Only support the SSLv3 protocol. Sslv3, From 6c810e7f9ce21a8a518aa5ce71372bb96c2efada Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 5 Oct 2015 21:43:49 +0530 Subject: [PATCH 17/19] Set threadid_func on linux/osx (fixes #281) --- openssl-sys/src/lib.rs | 2 ++ openssl-sys/src/openssl_shim.c | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 45d03ac8..e5dfdc82 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -270,6 +270,7 @@ pub fn init() { GUARDS = mem::transmute(guards); CRYPTO_set_locking_callback(locking_function); + unsafe{ rust_openssl_set_id_callback(); } }) } } @@ -290,6 +291,7 @@ pub unsafe fn SSL_CTX_clear_options(ssl: *mut SSL_CTX, op: u64) -> u64 { extern "C" { fn rust_openssl_ssl_ctx_options_rust_to_c(rustval: u64) -> c_long; fn rust_openssl_ssl_ctx_options_c_to_rust(cval: c_long) -> u64; + fn rust_openssl_set_id_callback(); pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int; pub fn ASN1_STRING_type_new(ty: c_int) -> *mut ASN1_STRING; diff --git a/openssl-sys/src/openssl_shim.c b/openssl-sys/src/openssl_shim.c index 7fabe06e..abfa3918 100644 --- a/openssl-sys/src/openssl_shim.c +++ b/openssl-sys/src/openssl_shim.c @@ -3,6 +3,33 @@ #include #include +#if defined(__APPLE__) || defined(__linux) + +#include +#include + +unsigned long thread_id() +{ + unsigned long ret = (unsigned long)pthread_self(); + return ret; +} + +void rust_openssl_set_id_callback() { + CRYPTO_set_id_callback((unsigned long (*)())thread_id); +} + +#else +// Openssl already handles Windows directly, so we don't +// need to explicitly set it + +void rust_openssl_set_id_callback() { + // We don't know how to set the callback for arbitrary OSes + // Let openssl use its defaults and hope they work. +} + +#endif + + #if OPENSSL_VERSION_NUMBER < 0x1000000L // Copied from openssl crypto/hmac/hmac.c int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) From 0ca71a98fff158d35f5a80b10917bd93f48581b0 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 5 Oct 2015 22:05:58 +0100 Subject: [PATCH 18/19] Clean up init stuff --- openssl-sys/src/lib.rs | 12 ++++++------ openssl-sys/src/openssl_shim.c | 5 ++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index e5dfdc82..d40d299d 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -252,10 +252,10 @@ extern fn locking_function(mode: c_int, n: c_int, _file: *const c_char, } pub fn init() { - static mut INIT: Once = ONCE_INIT; + static INIT: Once = ONCE_INIT; - unsafe { - INIT.call_once(|| { + INIT.call_once(|| { + unsafe { SSL_library_init(); SSL_load_error_strings(); @@ -270,9 +270,9 @@ pub fn init() { GUARDS = mem::transmute(guards); CRYPTO_set_locking_callback(locking_function); - unsafe{ rust_openssl_set_id_callback(); } - }) - } + rust_openssl_set_id_callback(); + } + }) } pub unsafe fn SSL_CTX_set_options(ssl: *mut SSL_CTX, op: u64) -> u64 { diff --git a/openssl-sys/src/openssl_shim.c b/openssl-sys/src/openssl_shim.c index abfa3918..f0f55b27 100644 --- a/openssl-sys/src/openssl_shim.c +++ b/openssl-sys/src/openssl_shim.c @@ -10,12 +10,11 @@ unsigned long thread_id() { - unsigned long ret = (unsigned long)pthread_self(); - return ret; + return (unsigned long) pthread_self(); } void rust_openssl_set_id_callback() { - CRYPTO_set_id_callback((unsigned long (*)())thread_id); + CRYPTO_set_id_callback(thread_id); } #else From 677ed6ad1b7a84b0ae96e722bd0a084c67bcff40 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 5 Oct 2015 22:34:32 +0100 Subject: [PATCH 19/19] Release v0.6.6 --- 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 82dd2e4f..a6a5e8b6 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.5/openssl). +[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.6.6/openssl). ## Building diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 5a01318c..b13fc80a 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "openssl-sys" -version = "0.6.5" +version = "0.6.6" 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.5/openssl_sys" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.6/openssl_sys" links = "openssl" build = "build.rs" diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index d40d299d..3bc9e59a 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.5")] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.6")] extern crate libc; diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index c70c3ad3..ac0a5cc7 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "openssl" -version = "0.6.5" +version = "0.6.6" 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.5/openssl" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.6/openssl" readme = "../README.md" keywords = ["crypto", "tls", "ssl", "dtls"] @@ -24,7 +24,7 @@ ecdh_auto = ["openssl-sys/ecdh_auto"] [dependencies.openssl-sys] path = "../openssl-sys" -version = "0.6.4" +version = "0.6.6" [dependencies] bitflags = ">= 0.2, < 0.4" diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 49a7fd4a..5a3b215f 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.5")] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.6")] #[macro_use] extern crate bitflags;