diff options
| author | Steven Fackler <[email protected]> | 2018-08-28 22:02:55 -0700 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2018-08-31 20:23:55 -0700 |
| commit | bc4e47a321a71f9299c24a94b1bdcaa78383e75d (patch) | |
| tree | 7b6fcfdc2372e3bf1c936bbb2762434122489e2d /openssl/src/ssl/test.rs | |
| parent | Bump Appveyor test versions (diff) | |
| download | rust-openssl-bc4e47a321a71f9299c24a94b1bdcaa78383e75d.tar.xz rust-openssl-bc4e47a321a71f9299c24a94b1bdcaa78383e75d.zip | |
Fix lookup errors with SNI callback.
The job of an SNI callback is typically to swap out the context
associated with an SSL depending on the domain the client is trying to
talk to. Typically, only the callbacks associated with the current
context are used, but this is not the case for the SNI callback.
If SNI is run for a second time on a connection (i.e. in a
renegotiation) and the context was replaced with one that didn't itself
register an SNI callback, the old callback would run but wouldn't be
able to find its state in the context's ex data. To work around this, we
pass the pointer to the callback data directly to the callback to make
sure it's always available. It still lives in ex data to handle the
lifetime management.
Closes #979
Diffstat (limited to 'openssl/src/ssl/test.rs')
| -rw-r--r-- | openssl/src/ssl/test.rs | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/openssl/src/ssl/test.rs b/openssl/src/ssl/test.rs index 1c44c0b1..e1a6a04b 100644 --- a/openssl/src/ssl/test.rs +++ b/openssl/src/ssl/test.rs @@ -29,7 +29,7 @@ use ssl::{ }; #[cfg(any(ossl102, ossl110))] use x509::verify::X509CheckFlags; -use x509::{X509Name, X509StoreContext, X509VerifyResult, X509}; +use x509::{X509, X509Name, X509StoreContext, X509VerifyResult}; use std::net::UdpSocket; @@ -1754,3 +1754,42 @@ fn psk_ciphers() { assert!(CLIENT_CALLED.load(Ordering::SeqCst) && SERVER_CALLED.load(Ordering::SeqCst)); } + +#[test] +fn sni_callback_swapped_ctx() { + static CALLED_BACK: AtomicBool = ATOMIC_BOOL_INIT; + + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let port = listener.local_addr().unwrap().port(); + + let guard = thread::spawn(move || { + let stream = listener.accept().unwrap().0; + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_servername_callback(|_, _| { + CALLED_BACK.store(true, Ordering::SeqCst); + Ok(()) + }); + let mut ssl = Ssl::new(&ctx.build()).unwrap(); + + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_certificate_file(&Path::new("test/cert.pem"), SslFiletype::PEM) + .unwrap(); + ctx.set_private_key_file(&Path::new("test/key.pem"), SslFiletype::PEM) + .unwrap(); + ssl.set_ssl_context(&ctx.build()).unwrap(); + + let mut stream = ssl.accept(stream).unwrap(); + stream.write_all(&[0]).unwrap(); + }); + + 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(); + stream.read_exact(&mut [0]).unwrap(); + + assert!(CALLED_BACK.load(Ordering::SeqCst)); + + guard.join().unwrap(); +} |