diff options
| author | Steven Fackler <[email protected]> | 2016-11-05 20:06:50 -0700 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2016-11-05 20:06:50 -0700 |
| commit | a0b56c437803a08413755928040a0970a93a7b83 (patch) | |
| tree | 0f21848301b62d6078eafaee10e513df4163087b /openssl/src/ssl/tests | |
| parent | Merge branch 'release-v0.8.3' into release (diff) | |
| parent | Release v0.9.0 (diff) | |
| download | rust-openssl-0.9.0.tar.xz rust-openssl-0.9.0.zip | |
Merge branch 'release-v0.9.0' into releasev0.9.0
Diffstat (limited to 'openssl/src/ssl/tests')
| -rw-r--r-- | openssl/src/ssl/tests/mod.rs | 690 |
1 files changed, 396 insertions, 294 deletions
diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 3bbbed03..a84f6b25 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -1,5 +1,6 @@ #![allow(unused_imports)] +use std::env; use std::fs::File; use std::io::prelude::*; use std::io::{self, BufReader}; @@ -11,31 +12,26 @@ use std::process::{Command, Child, Stdio, ChildStdin}; use std::thread; use std::time::Duration; -use net2::TcpStreamExt; +use tempdir::TempDir; -use crypto::hash::Type::SHA256; +use hash::MessageDigest; use ssl; use ssl::SSL_VERIFY_PEER; -use ssl::SslMethod::Sslv23; use ssl::{SslMethod, HandshakeError}; -use ssl::error::Error; -use ssl::{SslContext, SslStream}; -use x509::X509StoreContext; -use x509::X509FileType; -use x509::X509; -use crypto::pkey::PKey; - -#[cfg(feature="dtlsv1")] +use ssl::{SslContext, SslStream, Ssl, ShutdownResult, SslConnectorBuilder, SslAcceptorBuilder, + Error}; +use x509::{X509StoreContext, X509, X509_FILETYPE_PEM}; +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] +use x509::verify::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; +use pkey::PKey; + use std::net::UdpSocket; -#[cfg(feature="dtlsv1")] -use ssl::SslMethod::Dtlsv1; -#[cfg(feature="sslv2")] -use ssl::SslMethod::Sslv2; -#[cfg(feature="dtlsv1")] -use net2::UdpSocketExt; mod select; +static CERT: &'static [u8] = include_bytes!("../../../test/cert.pem"); +static KEY: &'static [u8] = include_bytes!("../../../test/key.pem"); + fn next_addr() -> SocketAddr { use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; static PORT: AtomicUsize = ATOMIC_USIZE_INIT; @@ -46,32 +42,42 @@ fn next_addr() -> SocketAddr { struct Server { p: Child, + _temp: TempDir, } impl Server { fn spawn(args: &[&str], input: Option<Box<FnMut(ChildStdin) + Send>>) -> (Server, SocketAddr) { + let td = TempDir::new("openssl").unwrap(); + let cert = td.path().join("cert.pem"); + let key = td.path().join("key.pem"); + File::create(&cert).unwrap().write_all(CERT).unwrap(); + File::create(&key).unwrap().write_all(KEY).unwrap(); + 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(); + .arg("s_server") + .arg("-accept") + .arg(addr.port().to_string()) + .args(args) + .arg("-cert") + .arg(&cert) + .arg("-key") + .arg(&key) + .arg("-no_dhe") + .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) + (Server { + p: child, + _temp: td, + }, + addr) } fn new_tcp(args: &[&str]) -> (Server, TcpStream) { @@ -92,7 +98,6 @@ impl Server { Server::new_tcp(&["-www"]) } - #[cfg(any(feature = "alpn", feature = "npn"))] fn new_alpn() -> (Server, TcpStream) { Server::new_tcp(&["-www", "-nextprotoneg", @@ -101,7 +106,6 @@ impl Server { "http/1.1,spdy/3.1"]) } - #[cfg(feature = "dtlsv1")] fn new_dtlsv1<I>(input: I) -> (Server, UdpConnected) where I: IntoIterator<Item = &'static str>, I::IntoIter: Send + 'static @@ -109,17 +113,17 @@ impl Server { 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; - } - } - }))); + 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(Duration::from_millis(100)); - let socket = UdpSocket::bind(next_addr()).unwrap(); + let socket = UdpSocket::bind("127.0.0.1:0").unwrap(); socket.connect(&addr).unwrap(); (s, UdpConnected(socket)) } @@ -132,51 +136,18 @@ impl Drop for Server { } } -#[cfg(feature = "dtlsv1")] #[derive(Debug)] struct UdpConnected(UdpSocket); -#[cfg(feature = "dtlsv1")] impl Read for UdpConnected { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - self.0.recv_from(buf).map(|(s, _)| s) + self.0.recv(buf) } } -#[cfg(feature = "dtlsv1")] impl Write for UdpConnected { - #[cfg(unix)] - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - 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<usize> { - 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) - } + self.0.send(buf) } fn flush(&mut self) -> io::Result<()> { @@ -197,147 +168,139 @@ macro_rules! run_test( use ssl::SslMethod; use ssl::{SslContext, Ssl, SslStream}; use ssl::SSL_VERIFY_PEER; - use crypto::hash::Type::{SHA1, SHA256}; + use hash::MessageDigest; use x509::X509StoreContext; use serialize::hex::FromHex; + use types::OpenSslTypeRef; use super::Server; #[test] fn sslv23() { let (_s, stream) = Server::new(); - $blk(SslMethod::Sslv23, stream); + $blk(SslMethod::tls(), stream); } #[test] - #[cfg(feature="dtlsv1")] + #[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn dtlsv1() { let (_s, stream) = Server::new_dtlsv1(Some("hello")); - $blk(SslMethod::Dtlsv1, stream); + $blk(SslMethod::dtls(), stream); } } ); ); run_test!(new_ctx, |method, _| { - SslContext::new(method).unwrap(); -}); - -run_test!(new_sslstream, |method, stream| { - SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); -}); - -run_test!(get_ssl_method, |method, _| { - let ssl = Ssl::new(&SslContext::new(method).unwrap()).unwrap(); - assert_eq!(ssl.ssl_method(), method); + SslContext::builder(method).unwrap(); }); run_test!(verify_untrusted, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => panic!("expected failure"), Err(err) => println!("error {:?}", err), } }); run_test!(verify_trusted, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } }); run_test!(verify_untrusted_callback_override_ok, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| true); - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } }); run_test!(verify_untrusted_callback_override_bad, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| false); - assert!(SslStream::connect(&ctx, stream).is_err()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_err()); }); run_test!(verify_trusted_callback_override_ok, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| true); - match ctx.set_CA_file(&Path::new("test/cert.pem")) { + match ctx.set_ca_file(&Path::new("test/cert.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } }); run_test!(verify_trusted_callback_override_bad, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| false); - match ctx.set_CA_file(&Path::new("test/cert.pem")) { + match ctx.set_ca_file(&Path::new("test/cert.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - assert!(SslStream::connect(&ctx, stream).is_err()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_err()); }); run_test!(verify_callback_load_certs, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { assert!(x509_ctx.current_cert().is_some()); true }); - assert!(SslStream::connect(&ctx, stream).is_ok()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_ok()); }); run_test!(verify_trusted_get_error_ok, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { assert!(x509_ctx.error().is_none()); true }); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - assert!(SslStream::connect(&ctx, stream).is_ok()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_ok()); }); run_test!(verify_trusted_get_error_err, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { assert!(x509_ctx.error().is_some()); false }); - assert!(SslStream::connect(&ctx, stream).is_err()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_err()); }); run_test!(verify_callback_data, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); - // Node id was generated as SHA256 hash of certificate "test/cert.pem" - // in DER format. - // Command: openssl x509 -in test/cert.pem -outform DER | openssl dgst -sha256 - // Please update if "test/cert.pem" will ever change +// Node id was generated as SHA256 hash of certificate "test/cert.pem" +// in DER format. +// Command: openssl x509 -in test/cert.pem -outform DER | openssl dgst -sha256 +// Please update if "test/cert.pem" will ever change let node_hash_str = "59172d9313e84459bcff27f967e79e6e9217e584"; let node_id = node_hash_str.from_hex().unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, move |_preverify_ok, x509_ctx| { @@ -345,14 +308,14 @@ run_test!(verify_callback_data, |method, stream| { match cert { None => false, Some(cert) => { - let fingerprint = cert.fingerprint(SHA1).unwrap(); + let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); fingerprint == node_id } } }); ctx.set_verify_depth(1); - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } @@ -360,12 +323,11 @@ run_test!(verify_callback_data, |method, stream| { run_test!(ssl_verify_callback, |method, stream| { use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - use ssl::IntoSsl; static CHECKED: AtomicUsize = ATOMIC_USIZE_INIT; - let ctx = SslContext::new(method).unwrap(); - let mut ssl = ctx.into_ssl().unwrap(); + let ctx = SslContext::builder(method).unwrap(); + let mut ssl = Ssl::new(&ctx.build()).unwrap(); let node_hash_str = "59172d9313e84459bcff27f967e79e6e9217e584"; let node_id = node_hash_str.from_hex().unwrap(); @@ -374,13 +336,13 @@ run_test!(ssl_verify_callback, |method, stream| { match x509.current_cert() { None => false, Some(cert) => { - let fingerprint = cert.fingerprint(SHA1).unwrap(); + let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); fingerprint == node_id } } }); - match SslStream::connect(ssl, stream) { + match ssl.connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } @@ -391,24 +353,24 @@ run_test!(ssl_verify_callback, |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(next_addr()).unwrap(); + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let guard = thread::spawn(move || { - let ctx = SslContext::new(Sslv23).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); let stream = TcpStream::connect(addr).unwrap(); - let mut stream = SslStream::connect(&ctx, stream).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); stream.write_all(b"hello").unwrap(); stream }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM).unwrap(); - ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM).unwrap(); + ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); let stream = listener.accept().unwrap().0; - let mut stream = SslStream::accept(&ctx, stream).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().accept(stream).unwrap(); let mut buf = [0; 5]; assert_eq!(5, stream.read(&mut buf).unwrap()); @@ -423,7 +385,7 @@ fn test_set_certificate_and_private_key() { let cert = include_bytes!("../../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_private_key(&key).unwrap(); ctx.set_certificate(&cert).unwrap(); @@ -431,18 +393,18 @@ fn test_set_certificate_and_private_key() { } run_test!(get_ctx_options, |method, _| { - let ctx = SslContext::new(method).unwrap(); + let ctx = SslContext::builder(method).unwrap(); ctx.options(); }); run_test!(set_ctx_options, |method, _| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); let opts = ctx.set_options(ssl::SSL_OP_NO_TICKET); assert!(opts.contains(ssl::SSL_OP_NO_TICKET)); }); run_test!(clear_ctx_options, |method, _| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_options(ssl::SSL_OP_ALL); let opts = ctx.clear_options(ssl::SSL_OP_ALL); assert!(!opts.contains(ssl::SSL_OP_ALL)); @@ -451,17 +413,8 @@ run_test!(clear_ctx_options, |method, _| { #[test] fn test_write() { 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(); - stream.write_all(" there".as_bytes()).unwrap(); - stream.flush().unwrap(); -} - -#[test] -fn test_write_direct() { - let (_s, stream) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -469,20 +422,21 @@ fn test_write_direct() { } run_test!(get_peer_certificate, |method, stream| { - let stream = SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); + let ctx = SslContext::builder(method).unwrap(); + let stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); let cert = stream.ssl().peer_certificate().unwrap(); - let fingerprint = cert.fingerprint(SHA1).unwrap(); + let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); let node_hash_str = "59172d9313e84459bcff27f967e79e6e9217e584"; let node_id = node_hash_str.from_hex().unwrap(); assert_eq!(node_id, fingerprint) }); #[test] -#[cfg(feature = "dtlsv1")] +#[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_write_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(iter::repeat("y\n")); - - let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let ctx = SslContext::builder(SslMethod::dtls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); stream.write_all(b"hello").unwrap(); stream.flush().unwrap(); stream.write_all(b" there").unwrap(); @@ -492,16 +446,8 @@ fn test_write_dtlsv1() { #[test] fn test_read() { 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(); - io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); -} - -#[test] -fn test_read_direct() { - let (_s, tcp) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); @@ -510,7 +456,8 @@ fn test_read_direct() { #[test] fn test_pending() { let (_s, tcp) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); @@ -533,7 +480,8 @@ fn test_pending() { #[test] fn test_state() { let (_s, tcp) = Server::new(); - let stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let stream = Ssl::new(&ctx.build()).unwrap().connect(tcp).unwrap(); assert_eq!(stream.ssl().state_string(), "SSLOK "); assert_eq!(stream.ssl().state_string_long(), "SSL negotiation finished successfully"); @@ -542,17 +490,17 @@ fn test_state() { /// Tests that connecting with the client using ALPN, but the server not does not /// break the existing connection behavior. #[test] -#[cfg(feature = "alpn")] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] fn test_connect_with_unilateral_alpn() { let (_s, stream) = Server::new(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -564,17 +512,16 @@ fn test_connect_with_unilateral_alpn() { /// Tests that connecting with the client using NPN, but the server not does not /// break the existing connection behavior. #[test] -#[cfg(feature = "npn")] fn test_connect_with_unilateral_npn() { let (_s, stream) = Server::new(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -586,17 +533,17 @@ fn test_connect_with_unilateral_npn() { /// Tests that when both the client as well as the server use ALPN and their /// lists of supported protocols have an overlap, the correct protocol is chosen. #[test] -#[cfg(feature = "alpn")] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] fn test_connect_with_alpn_successful_multiple_matching() { let (_s, stream) = Server::new_alpn(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_alpn_protocols(&[b"spdy/3.1", b"http/1.1"]); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + ctx.set_alpn_protocols(&[b"spdy/3.1", b"http/1.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -608,17 +555,17 @@ fn test_connect_with_alpn_successful_multiple_matching() { /// Tests that when both the client as well as the server use NPN and their /// lists of supported protocols have an overlap, the correct protocol is chosen. #[test] -#[cfg(feature = "npn")] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] fn test_connect_with_npn_successful_multiple_matching() { let (_s, stream) = Server::new_alpn(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -631,17 +578,17 @@ fn test_connect_with_npn_successful_multiple_matching() { /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. #[test] -#[cfg(feature = "alpn")] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] fn test_connect_with_alpn_successful_single_match() { let (_s, stream) = Server::new_alpn(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_alpn_protocols(&[b"spdy/3.1"]); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + ctx.set_alpn_protocols(&[b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -655,17 +602,17 @@ fn test_connect_with_alpn_successful_single_match() { /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. #[test] -#[cfg(feature = "npn")] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] fn test_connect_with_npn_successful_single_match() { let (_s, stream) = Server::new_alpn(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_npn_protocols(&[b"spdy/3.1"]); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + ctx.set_npn_protocols(&[b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -677,37 +624,36 @@ fn test_connect_with_npn_successful_single_match() { /// Tests that when the `SslStream` is created as a server stream, the protocols /// are correctly advertised to the client. #[test] -#[cfg(feature = "npn")] fn test_npn_server_advertise_multiple() { - let listener = TcpListener::bind(next_addr()).unwrap(); + let listener = TcpListener::bind("127.0.0.1:0").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(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]); - assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM) + ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) .is_ok()); - ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM) - .unwrap(); - ctx + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) + .unwrap(); + ctx.build() }; // 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(); + Ssl::new(&listener_ctx).unwrap().accept(stream).unwrap(); }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_npn_protocols(&[b"spdy/3.1"]); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + ctx.set_npn_protocols(&[b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.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::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -718,37 +664,37 @@ fn test_npn_server_advertise_multiple() { /// Tests that when the `SslStream` is created as a server stream, the protocols /// are correctly advertised to the client. #[test] -#[cfg(feature = "alpn")] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] fn test_alpn_server_advertise_multiple() { - let listener = TcpListener::bind(next_addr()).unwrap(); + let listener = TcpListener::bind("127.0.0.1:0").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(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); - assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM) + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) .is_ok()); - ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM) - .unwrap(); - ctx + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) + .unwrap(); + ctx.build() }; // 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(); + Ssl::new(&listener_ctx).unwrap().accept(stream).unwrap(); }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_alpn_protocols(&[b"spdy/3.1"]); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + ctx.set_alpn_protocols(&[b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.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::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -759,87 +705,82 @@ fn test_alpn_server_advertise_multiple() { /// 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")] +#[cfg(all(feature = "v102", ossl102))] fn test_alpn_server_select_none() { - let listener = TcpListener::bind(next_addr()).unwrap(); + let listener = TcpListener::bind("127.0.0.1:0").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(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); - assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM) + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) .is_ok()); - ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM) - .unwrap(); - ctx + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) + .unwrap(); + ctx.build() }; // 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(); + Ssl::new(&listener_ctx).unwrap().accept(stream).unwrap(); }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - ctx.set_alpn_protocols(&[b"http/2"]); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { - Ok(_) => {} - Err(err) => panic!("Unexpected error {:?}", err), - } + ctx.set_alpn_protocols(&[b"http/2"]).unwrap(); + ctx.set_ca_file(&Path::new("test/root-ca.pem")).unwrap(); // Now connect to the socket and make sure the protocol negotiation works... let stream = TcpStream::connect(localhost).unwrap(); - let stream = match SslStream::connect(&ctx, stream) { - Ok(stream) => stream, - Err(err) => panic!("Expected success, got {:?}", err), - }; + let stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); // Since the protocols from the server and client don't overlap at all, no protocol is selected assert_eq!(None, stream.ssl().selected_alpn_protocol()); } +// In 1.1.0, ALPN negotiation failure is a fatal error +#[test] +#[cfg(all(feature = "v110", ossl110))] +fn test_alpn_server_select_none() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let localhost = listener.local_addr().unwrap(); + // We create a different context instance for the server... + let listener_ctx = { + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER); + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) + .is_ok()); + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) + .unwrap(); + ctx.build() + }; + // Have the listener wait on the connection in a different thread. + thread::spawn(move || { + let (stream, _) = listener.accept().unwrap(); + assert!(Ssl::new(&listener_ctx).unwrap().accept(stream).is_err()); + }); -#[cfg(feature="dtlsv1")] -#[cfg(test)] -mod dtlsv1 { - use serialize::hex::FromHex; - use std::net::TcpStream; - use std::thread; - - use crypto::hash::Type::SHA256; - use ssl::SslMethod; - use ssl::SslMethod::Dtlsv1; - use ssl::{SslContext, SslStream}; - use ssl::SSL_VERIFY_PEER; - use x509::X509StoreContext; - - const PROTOCOL: SslMethod = Dtlsv1; - - #[test] - fn test_new_ctx() { - SslContext::new(PROTOCOL).unwrap(); - } + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER); + ctx.set_alpn_protocols(&[b"http/2"]).unwrap(); + ctx.set_ca_file(&Path::new("test/root-ca.pem")).unwrap(); + // Now connect to the socket and make sure the protocol negotiation works... + let stream = TcpStream::connect(localhost).unwrap(); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_err()); } #[test] -#[cfg(feature = "dtlsv1")] +#[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_read_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(Some("hello")); - let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let ctx = SslContext::builder(SslMethod::dtls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); let mut buf = [0u8; 100]; assert!(stream.read(&mut buf).is_ok()); } -#[test] -#[cfg(feature = "sslv2")] -fn test_sslv2_connect_failure() { - let (_s, tcp) = Server::new_tcp(&["-no_ssl2", "-www"]); - SslStream::connect(&SslContext::new(Sslv2).unwrap(), tcp) - .err() - .unwrap(); -} - fn wait_io(stream: &TcpStream, read: bool, timeout_ms: u32) -> bool { unsafe { let mut set: select::fd_set = mem::zeroed(); @@ -859,8 +800,7 @@ fn wait_io(stream: &TcpStream, read: bool, timeout_ms: u32) -> bool { } } -fn handshake(res: Result<SslStream<TcpStream>, HandshakeError<TcpStream>>) - -> SslStream<TcpStream> { +fn handshake(res: Result<SslStream<TcpStream>, HandshakeError<TcpStream>>) -> SslStream<TcpStream> { match res { Ok(s) => s, Err(HandshakeError::Interrupted(s)) => { @@ -875,8 +815,8 @@ fn handshake(res: Result<SslStream<TcpStream>, HandshakeError<TcpStream>>) fn test_write_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); - let cx = SslContext::new(Sslv23).unwrap(); - let mut stream = handshake(SslStream::connect(&cx, stream)); + let cx = SslContext::builder(SslMethod::tls()).unwrap().build(); + let mut stream = handshake(Ssl::new(&cx).unwrap().connect(stream)); let mut iterations = 0; loop { @@ -909,12 +849,12 @@ fn test_write_nonblocking() { } #[test] -#[cfg_attr(windows, ignore)] // FIXME flickers on appveyor +#[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_read_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); - let cx = SslContext::new(Sslv23).unwrap(); - let mut stream = handshake(SslStream::connect(&cx, stream)); + let cx = SslContext::builder(SslMethod::tls()).unwrap().build(); + let mut stream = handshake(Ssl::new(&cx).unwrap().connect(stream)); let mut iterations = 0; loop { @@ -965,7 +905,6 @@ fn test_read_nonblocking() { #[test] #[should_panic(expected = "blammo")] -#[cfg(feature = "nightly")] fn write_panic() { struct ExplodingStream(TcpStream); @@ -988,13 +927,12 @@ fn write_panic() { let (_s, stream) = Server::new(); let stream = ExplodingStream(stream); - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - let _ = SslStream::connect(&ctx, stream); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let _ = Ssl::new(&ctx.build()).unwrap().connect(stream); } #[test] #[should_panic(expected = "blammo")] -#[cfg(feature = "nightly")] fn read_panic() { struct ExplodingStream(TcpStream); @@ -1017,13 +955,12 @@ fn read_panic() { let (_s, stream) = Server::new(); let stream = ExplodingStream(stream); - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - let _ = SslStream::connect(&ctx, stream); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let _ = Ssl::new(&ctx.build()).unwrap().connect(stream); } #[test] #[should_panic(expected = "blammo")] -#[cfg(feature = "nightly")] fn flush_panic() { struct ExplodingStream(TcpStream); @@ -1046,32 +983,31 @@ fn flush_panic() { let (_s, stream) = Server::new(); let stream = ExplodingStream(stream); - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - let mut stream = SslStream::connect(&ctx, stream).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).ok().unwrap(); let _ = stream.flush(); } #[test] fn refcount_ssl_context() { let mut ssl = { - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - ssl::Ssl::new(&ctx).unwrap() + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ssl::Ssl::new(&ctx.build()).unwrap() }; { - let new_ctx_a = SslContext::new(SslMethod::Sslv23).unwrap(); + let new_ctx_a = SslContext::builder(SslMethod::tls()).unwrap().build(); let _new_ctx_b = ssl.set_ssl_context(&new_ctx_a); } } #[test] -#[cfg_attr(windows, ignore)] // don't have a trusted CA list easily available :( fn default_verify_paths() { - let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_default_verify_paths().unwrap(); ctx.set_verify(SSL_VERIFY_PEER); let s = TcpStream::connect("google.com:443").unwrap(); - let mut socket = SslStream::connect(&ctx, s).unwrap(); + let mut socket = Ssl::new(&ctx.build()).unwrap().connect(s).unwrap(); socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); let mut result = vec![]; @@ -1086,6 +1022,172 @@ fn default_verify_paths() { fn add_extra_chain_cert() { let cert = include_bytes!("../../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); - let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - ctx.add_extra_chain_cert(&cert).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.add_extra_chain_cert(cert).unwrap(); +} + +#[test] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] +fn verify_valid_hostname() { + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_default_verify_paths().unwrap(); + ctx.set_verify(SSL_VERIFY_PEER); + + let mut ssl = Ssl::new(&ctx.build()).unwrap(); + ssl.param_mut().set_hostflags(X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + ssl.param_mut().set_host("google.com").unwrap(); + + let s = TcpStream::connect("google.com:443").unwrap(); + let mut socket = ssl.connect(s).unwrap(); + + socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); + let mut result = vec![]; + socket.read_to_end(&mut result).unwrap(); + + println!("{}", String::from_utf8_lossy(&result)); + assert!(result.starts_with(b"HTTP/1.0")); + assert!(result.ends_with(b"</HTML>\r\n") || result.ends_with(b"</html>")); +} + +#[test] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] +fn verify_invalid_hostname() { + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_default_verify_paths().unwrap(); + ctx.set_verify(SSL_VERIFY_PEER); + + let mut ssl = Ssl::new(&ctx.build()).unwrap(); + ssl.param_mut().set_hostflags(X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + ssl.param_mut().set_host("foobar.com").unwrap(); + + let s = TcpStream::connect("google.com:443").unwrap(); + assert!(ssl.connect(s).is_err()); +} + +#[test] +fn connector_valid_hostname() { + let connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap().build(); + + let s = TcpStream::connect("google.com:443").unwrap(); + let mut socket = connector.connect("google.com", s).unwrap(); + + socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); + let mut result = vec![]; + socket.read_to_end(&mut result).unwrap(); + + println!("{}", String::from_utf8_lossy(&result)); + assert!(result.starts_with(b"HTTP/1.0")); + assert!(result.ends_with(b"</HTML>\r\n") || result.ends_with(b"</html>")); +} + +#[test] +fn connector_invalid_hostname() { + let connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap().build(); + + let s = TcpStream::connect("google.com:443").unwrap(); + assert!(connector.connect("foobar.com", s).is_err()); +} + +#[test] +fn connector_client_server_mozilla_intermediate() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let port = listener.local_addr().unwrap().port(); + + let t = thread::spawn(move || { + let key = PKey::private_key_from_pem(KEY).unwrap(); + let cert = X509::from_pem(CERT).unwrap(); + let connector = + SslAcceptorBuilder::mozilla_intermediate(SslMethod::tls(), &key, &cert, None::<X509>) + .unwrap() + .build(); + let stream = listener.accept().unwrap().0; + let mut stream = connector.accept(stream).unwrap(); + + stream.write_all(b"hello").unwrap(); + }); + + let mut connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); + connector.builder_mut().set_ca_file("test/root-ca.pem").unwrap(); + let connector = connector.build(); + + let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); + let mut stream = connector.connect("foobar.com", stream).unwrap(); + + let mut buf = [0; 5]; + stream.read_exact(&mut buf).unwrap(); + assert_eq!(b"hello", &buf); + + t.join().unwrap(); +} + +#[test] +fn connector_client_server_mozilla_modern() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let port = listener.local_addr().unwrap().port(); + + let t = thread::spawn(move || { + let key = PKey::private_key_from_pem(KEY).unwrap(); + let cert = X509::from_pem(CERT).unwrap(); + let connector = + SslAcceptorBuilder::mozilla_modern(SslMethod::tls(), &key, &cert, None::<X509>) + .unwrap() + .build(); + let stream = listener.accept().unwrap().0; + let mut stream = connector.accept(stream).unwrap(); + + stream.write_all(b"hello").unwrap(); + }); + + let mut connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); + connector.builder_mut().set_ca_file("test/root-ca.pem").unwrap(); + let connector = connector.build(); + + let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); + let mut stream = connector.connect("foobar.com", stream).unwrap(); + + let mut buf = [0; 5]; + stream.read_exact(&mut buf).unwrap(); + assert_eq!(b"hello", &buf); + + t.join().unwrap(); +} + +#[test] +fn shutdown() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let port = listener.local_addr().unwrap().port(); + + thread::spawn(move || { + let stream = listener.accept().unwrap().0; + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); + let ssl = Ssl::new(&ctx.build()).unwrap(); + let mut stream = ssl.accept(stream).unwrap(); + + stream.write_all(b"hello").unwrap(); + let mut buf = [0; 1]; + assert_eq!(stream.read(&mut buf).unwrap(), 0); + assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received); + }); + + let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let ssl = Ssl::new(&ctx.build()).unwrap(); + let mut stream = ssl.connect(stream).unwrap(); + + let mut buf = [0; 5]; + stream.read_exact(&mut buf).unwrap(); + assert_eq!(b"hello", &buf); + + assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Sent); + assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received); +} + +fn _check_kinds() { + fn is_send<T: Send>() {} + fn is_sync<T: Sync>() {} + + is_send::<SslStream<TcpStream>>(); + is_sync::<SslStream<TcpStream>>(); } |