diff --git a/.travis.yml b/.travis.yml index 2b056d108903140620355744be70826ab26148a0..8ee8c92910b3027a8e0cfc40ad0bd28f41202acc 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 06b9b7f87e4a806bc12cb51ab003ce662f94c58b..a6a5e8b65075361391696d9d5138c98d83c9a65c 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 @@ -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 0000000000000000000000000000000000000000..31c41ee1e95bf26fd65a5adcec0eaed136494d31 --- /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-sys/Cargo.toml b/openssl-sys/Cargo.toml index 437f7fb624511816e9943c2cf49038558af59158..b13fc80a16d03fa7096db509118b05f7baf8ed7a 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" @@ -21,6 +21,8 @@ aes_xts = [] aes_ctr = [] npn = [] alpn = [] +rfc5114 = [] +ecdh_auto = [] [dependencies] libc = "0.1" diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index b4a0056662a309a36979953f814638599b1a5597..5f9348889b5456d5dde0265ffe555e06ab1184bb 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"] } }; diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 0e0ef8a5b04235a895c19722a7e828f940c0f944..3bc9e59a8f16066071e5dcc6d61fd0ab9605b500 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; @@ -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; @@ -166,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; @@ -251,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(); @@ -269,8 +270,9 @@ pub fn init() { GUARDS = mem::transmute(guards); CRYPTO_set_locking_callback(locking_function); - }) - } + rust_openssl_set_id_callback(); + } + }) } pub unsafe fn SSL_CTX_set_options(ssl: *mut SSL_CTX, op: u64) -> u64 { @@ -289,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; @@ -380,6 +383,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; @@ -465,7 +479,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, @@ -662,8 +677,13 @@ 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"] + 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 f0622d2db34d1410b9535d6479d8c368029ad485..f0f55b27be59864ca19e7f470557ed2427f948b6 100644 --- a/openssl-sys/src/openssl_shim.c +++ b/openssl-sys/src/openssl_shim.c @@ -1,5 +1,33 @@ #include #include +#include +#include + +#if defined(__APPLE__) || defined(__linux) + +#include +#include + +unsigned long thread_id() +{ + return (unsigned long) pthread_self(); +} + +void rust_openssl_set_id_callback() { + CRYPTO_set_id_callback(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 @@ -79,6 +107,28 @@ 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); +} + +#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; + + 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 b8bc357db48fe882fdd28452bd880ec29e95c8f7..ac0a5cc78a1888bece0b59cc97a7ee5a2934e78f 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"] @@ -19,10 +19,12 @@ aes_xts = ["openssl-sys/aes_xts"] 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" -version = "0.6.4" +version = "0.6.6" [dependencies] bitflags = ">= 0.2, < 0.4" @@ -31,6 +33,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/bn/mod.rs b/openssl/src/bn/mod.rs index ccf2833796ddeb356c987817d7f9cc2a692b3f7f..3c973438a2742e531b5788af172388add218e8e7 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/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 4830838174235f462f9a268d2e2448072680634a..5a528b1b49e9cc7d62802769a73684309dcdd565 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 + } } } @@ -138,18 +143,19 @@ 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); - 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 @@ -198,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 + } } } @@ -237,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 @@ -247,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()); @@ -272,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)); @@ -329,6 +351,9 @@ impl PKey { pub fn sign_with_hash(&self, s: &[u8], hash: hash::Type) -> Vec { unsafe { let rsa = ffi::EVP_PKEY_get1_RSA(self.evp); + 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::>(); @@ -353,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), @@ -532,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(&[], &[]); + } } diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..e774abd1935349f32272c4a4fb4e8ccc806c6d2f --- /dev/null +++ b/openssl/src/dh/mod.rs @@ -0,0 +1,111 @@ +use ffi; +use std::io; +use std::io::prelude::*; +use ssl::error::{SslError, StreamError}; +use bio::MemBio; +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 = try_ssl_null!(unsafe { ffi::DH_new_from_params(p.raw(), g.raw(), q.raw()) }); + mem::forget(p); + mem::forget(g); + mem::forget(q); + 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 = try_ssl_null!(unsafe { ffi::DH_get_1024_160() }); + Ok(DH(dh)) + } + + #[cfg(feature = "rfc5114")] + pub fn get_2048_224() -> Result { + 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 = try_ssl_null!(unsafe { ffi::DH_get_2048_256() }); + 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 std::fs::File; + use std::path::Path; + 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(); + } + + #[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/src/lib.rs b/openssl/src/lib.rs index 17e625b931574a59f5ce579917019a4d50e5586e..5a3b215fcbe3993c54aef004a6fe4eea246fc858 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; @@ -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; @@ -20,6 +19,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 35180d3a191456ed2a2f8df704d09a029d7bcc7f..360f3f3ef3faeecab68d51135ef32bfc68cf677f 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; @@ -105,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, @@ -307,8 +309,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`. @@ -431,10 +436,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 }; @@ -492,6 +494,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> { @@ -563,6 +571,18 @@ 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( + 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 { @@ -683,10 +703,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) } @@ -1012,10 +1029,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); } diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index 9198a642a4003568c7acb0775268c644c46442ec..033a3b8648722ee33c6128384704f8408f1d3f4b 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::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::net::TcpListener; +use std::process::{Command, Child, Stdio, ChildStdin}; use std::thread; -use std::fs::File; 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; -#[cfg(feature = "dtlsv1")] -mod udp { +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) + } - static UDP_PORT: AtomicUsize = ATOMIC_USIZE_INIT; + 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"]) + } - pub fn next_server<'a>() -> String { - let diff = UDP_PORT.fetch_add(1, Ordering::SeqCst); - format!("127.0.0.1:{}", 15411 + diff) + #[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")] +struct UdpConnected(UdpSocket); + +#[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,18 +515,18 @@ 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"); } -/// 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")] 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"]); @@ -420,7 +538,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()); } @@ -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 - // 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_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(); @@ -628,6 +738,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 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(); + 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 { @@ -653,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]; @@ -665,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/dhparams.pem b/openssl/test/dhparams.pem new file mode 100644 index 0000000000000000000000000000000000000000..6e4d4c68cb283d2a851be0a2cd117f2002e316f9 --- /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----- diff --git a/openssl/test/test.sh b/openssl/test/test.sh deleted file mode 100755 index 9beb37c38b8653e710ff7a3bb7141ff0c0209648..0000000000000000000000000000000000000000 --- 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 &