From ee120877435d8627064f8590a967314b9be87b1e Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Fri, 29 Apr 2016 11:11:43 -0700 Subject: Upgrade to work with bitflags 0.5 and 0.6 --- openssl/src/ssl/mod.rs | 84 +++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 4b3a4385..3610627a 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -69,44 +69,44 @@ pub fn init() { } bitflags! { - flags SslContextOptions: u64 { - const SSL_OP_MICROSOFT_SESS_ID_BUG = ffi_extras::SSL_OP_MICROSOFT_SESS_ID_BUG, - const SSL_OP_NETSCAPE_CHALLENGE_BUG = ffi_extras::SSL_OP_NETSCAPE_CHALLENGE_BUG, - const SSL_OP_LEGACY_SERVER_CONNECT = ffi_extras::SSL_OP_LEGACY_SERVER_CONNECT, - const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = ffi_extras::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG, - const SSL_OP_TLSEXT_PADDING = ffi_extras::SSL_OP_TLSEXT_PADDING, - const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = ffi_extras::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER, - const SSL_OP_SAFARI_ECDHE_ECDSA_BUG = ffi_extras::SSL_OP_SAFARI_ECDHE_ECDSA_BUG, - const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = ffi_extras::SSL_OP_SSLEAY_080_CLIENT_DH_BUG, - const SSL_OP_TLS_D5_BUG = ffi_extras::SSL_OP_TLS_D5_BUG, - const SSL_OP_TLS_BLOCK_PADDING_BUG = ffi_extras::SSL_OP_TLS_BLOCK_PADDING_BUG, - const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = ffi_extras::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, - const SSL_OP_NO_QUERY_MTU = ffi_extras::SSL_OP_NO_QUERY_MTU, - const SSL_OP_COOKIE_EXCHANGE = ffi_extras::SSL_OP_COOKIE_EXCHANGE, - const SSL_OP_NO_TICKET = ffi_extras::SSL_OP_NO_TICKET, - const SSL_OP_CISCO_ANYCONNECT = ffi_extras::SSL_OP_CISCO_ANYCONNECT, - const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = ffi_extras::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, - const SSL_OP_NO_COMPRESSION = ffi_extras::SSL_OP_NO_COMPRESSION, - const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = ffi_extras::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, - const SSL_OP_SINGLE_ECDH_USE = ffi_extras::SSL_OP_SINGLE_ECDH_USE, - const SSL_OP_SINGLE_DH_USE = ffi_extras::SSL_OP_SINGLE_DH_USE, - const SSL_OP_CIPHER_SERVER_PREFERENCE = ffi_extras::SSL_OP_CIPHER_SERVER_PREFERENCE, - const SSL_OP_TLS_ROLLBACK_BUG = ffi_extras::SSL_OP_TLS_ROLLBACK_BUG, - const SSL_OP_NO_SSLV2 = ffi_extras::SSL_OP_NO_SSLv2, - const SSL_OP_NO_SSLV3 = ffi_extras::SSL_OP_NO_SSLv3, - const SSL_OP_NO_DTLSV1 = ffi_extras::SSL_OP_NO_DTLSv1, - const SSL_OP_NO_TLSV1 = ffi_extras::SSL_OP_NO_TLSv1, - const SSL_OP_NO_DTLSV1_2 = ffi_extras::SSL_OP_NO_DTLSv1_2, - const SSL_OP_NO_TLSV1_2 = ffi_extras::SSL_OP_NO_TLSv1_2, - const SSL_OP_NO_TLSV1_1 = ffi_extras::SSL_OP_NO_TLSv1_1, - const SSL_OP_NETSCAPE_CA_DN_BUG = ffi_extras::SSL_OP_NETSCAPE_CA_DN_BUG, - const SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = ffi_extras::SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG, - const SSL_OP_CRYPTOPRO_TLSEXT_BUG = ffi_extras::SSL_OP_CRYPTOPRO_TLSEXT_BUG, - const SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = ffi_extras::SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG, - const SSL_OP_MSIE_SSLV2_RSA_PADDING = ffi_extras::SSL_OP_MSIE_SSLV2_RSA_PADDING, - const SSL_OP_PKCS1_CHECK_1 = ffi_extras::SSL_OP_PKCS1_CHECK_1, - const SSL_OP_PKCS1_CHECK_2 = ffi_extras::SSL_OP_PKCS1_CHECK_2, - const SSL_OP_EPHEMERAL_RSA = ffi_extras::SSL_OP_EPHEMERAL_RSA, + pub flags SslContextOptions: u64 { + const SSL_OP_MICROSOFT_SESS_ID_BUG = ::ffi_extras::SSL_OP_MICROSOFT_SESS_ID_BUG, + const SSL_OP_NETSCAPE_CHALLENGE_BUG = ::ffi_extras::SSL_OP_NETSCAPE_CHALLENGE_BUG, + const SSL_OP_LEGACY_SERVER_CONNECT = ::ffi_extras::SSL_OP_LEGACY_SERVER_CONNECT, + const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = ::ffi_extras::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG, + const SSL_OP_TLSEXT_PADDING = ::ffi_extras::SSL_OP_TLSEXT_PADDING, + const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = ::ffi_extras::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER, + const SSL_OP_SAFARI_ECDHE_ECDSA_BUG = ::ffi_extras::SSL_OP_SAFARI_ECDHE_ECDSA_BUG, + const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = ::ffi_extras::SSL_OP_SSLEAY_080_CLIENT_DH_BUG, + const SSL_OP_TLS_D5_BUG = ::ffi_extras::SSL_OP_TLS_D5_BUG, + const SSL_OP_TLS_BLOCK_PADDING_BUG = ::ffi_extras::SSL_OP_TLS_BLOCK_PADDING_BUG, + const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = ::ffi_extras::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, + const SSL_OP_NO_QUERY_MTU = ::ffi_extras::SSL_OP_NO_QUERY_MTU, + const SSL_OP_COOKIE_EXCHANGE = ::ffi_extras::SSL_OP_COOKIE_EXCHANGE, + const SSL_OP_NO_TICKET = ::ffi_extras::SSL_OP_NO_TICKET, + const SSL_OP_CISCO_ANYCONNECT = ::ffi_extras::SSL_OP_CISCO_ANYCONNECT, + const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = ::ffi_extras::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, + const SSL_OP_NO_COMPRESSION = ::ffi_extras::SSL_OP_NO_COMPRESSION, + const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = ::ffi_extras::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, + const SSL_OP_SINGLE_ECDH_USE = ::ffi_extras::SSL_OP_SINGLE_ECDH_USE, + const SSL_OP_SINGLE_DH_USE = ::ffi_extras::SSL_OP_SINGLE_DH_USE, + const SSL_OP_CIPHER_SERVER_PREFERENCE = ::ffi_extras::SSL_OP_CIPHER_SERVER_PREFERENCE, + const SSL_OP_TLS_ROLLBACK_BUG = ::ffi_extras::SSL_OP_TLS_ROLLBACK_BUG, + const SSL_OP_NO_SSLV2 = ::ffi_extras::SSL_OP_NO_SSLv2, + const SSL_OP_NO_SSLV3 = ::ffi_extras::SSL_OP_NO_SSLv3, + const SSL_OP_NO_DTLSV1 = ::ffi_extras::SSL_OP_NO_DTLSv1, + const SSL_OP_NO_TLSV1 = ::ffi_extras::SSL_OP_NO_TLSv1, + const SSL_OP_NO_DTLSV1_2 = ::ffi_extras::SSL_OP_NO_DTLSv1_2, + const SSL_OP_NO_TLSV1_2 = ::ffi_extras::SSL_OP_NO_TLSv1_2, + const SSL_OP_NO_TLSV1_1 = ::ffi_extras::SSL_OP_NO_TLSv1_1, + const SSL_OP_NETSCAPE_CA_DN_BUG = ::ffi_extras::SSL_OP_NETSCAPE_CA_DN_BUG, + const SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = ::ffi_extras::SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG, + const SSL_OP_CRYPTOPRO_TLSEXT_BUG = ::ffi_extras::SSL_OP_CRYPTOPRO_TLSEXT_BUG, + const SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = ::ffi_extras::SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG, + const SSL_OP_MSIE_SSLV2_RSA_PADDING = ::ffi_extras::SSL_OP_MSIE_SSLV2_RSA_PADDING, + const SSL_OP_PKCS1_CHECK_1 = ::ffi_extras::SSL_OP_PKCS1_CHECK_1, + const SSL_OP_PKCS1_CHECK_2 = ::ffi_extras::SSL_OP_PKCS1_CHECK_2, + const SSL_OP_EPHEMERAL_RSA = ::ffi_extras::SSL_OP_EPHEMERAL_RSA, const SSL_OP_ALL = SSL_OP_MICROSOFT_SESS_ID_BUG.bits|SSL_OP_NETSCAPE_CHALLENGE_BUG.bits |SSL_OP_LEGACY_SERVER_CONNECT.bits|SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG.bits |SSL_OP_TLSEXT_PADDING.bits|SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER.bits @@ -214,14 +214,14 @@ impl SslMethod { /// Determines the type of certificate verification used bitflags! { - flags SslVerifyMode: i32 { + pub flags SslVerifyMode: i32 { /// Verify that the server's certificate is trusted - const SSL_VERIFY_PEER = ffi::SSL_VERIFY_PEER, + const SSL_VERIFY_PEER = ::ffi::SSL_VERIFY_PEER, /// Do not verify the server's certificate - const SSL_VERIFY_NONE = ffi::SSL_VERIFY_NONE, + const SSL_VERIFY_NONE = ::ffi::SSL_VERIFY_NONE, /// Terminate handshake if client did not return a certificate. /// Use together with SSL_VERIFY_PEER. - const SSL_VERIFY_FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + const SSL_VERIFY_FAIL_IF_NO_PEER_CERT = ::ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT, } } -- cgit v1.2.3 From 50024ce33b804e16e0c8b42abace73e0e4779cda Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 29 Apr 2016 21:40:16 -0700 Subject: Ignore default verify paths test on windows --- openssl/src/ssl/tests/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 15811d99..ce153b8e 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -1061,6 +1061,7 @@ fn refcount_ssl_context() { } #[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(); ctx.set_default_verify_paths().unwrap(); -- cgit v1.2.3 From 62a7dd10e588d7636c7720af6786efaa7015246b Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 25 Apr 2016 22:26:46 -0700 Subject: Add Ssl::set_verify It also uses a better, closure based API than the existing callback methods. --- openssl/src/ssl/mod.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++ openssl/src/ssl/tests/mod.rs | 30 +++++++++++++++++++++++ 2 files changed, 87 insertions(+) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 3610627a..b3c558c4 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -227,6 +227,7 @@ bitflags! { lazy_static! { static ref INDEXES: Mutex> = Mutex::new(HashMap::new()); + static ref SSL_INDEXES: Mutex> = Mutex::new(HashMap::new()); } // Creates a static index for user data of type T @@ -236,6 +237,10 @@ fn get_verify_data_idx() -> c_int { *INDEXES.lock().unwrap().entry(TypeId::of::()).or_insert_with(|| get_new_idx::()) } +fn get_ssl_verify_data_idx() -> c_int { + *SSL_INDEXES.lock().unwrap().entry(TypeId::of::()).or_insert_with(|| get_new_ssl_idx::()) +} + #[cfg(feature = "npn")] lazy_static! { static ref NPN_PROTOS_IDX: c_int = get_new_idx::>(); @@ -267,6 +272,26 @@ fn get_new_idx() -> c_int { } } +fn get_new_ssl_idx() -> c_int { + extern "C" fn free_data_box(_parent: *mut c_void, + ptr: *mut c_void, + _ad: *mut ffi::CRYPTO_EX_DATA, + _idx: c_int, + _argl: c_long, + _argp: *mut c_void) { + if !ptr.is_null() { + let _: Box = unsafe { mem::transmute(ptr) }; + } + } + + unsafe { + let f: ffi::CRYPTO_EX_free = free_data_box::; + let idx = ffi::SSL_get_ex_new_index(0, ptr::null(), None, None, Some(f)); + assert!(idx >= 0); + idx + } +} + extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int { unsafe { let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); @@ -311,6 +336,21 @@ extern "C" fn raw_verify_with_data(preverify_ok: c_int, } } +extern "C" fn ssl_raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int + where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send +{ + unsafe { + let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); + let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); + let verify = ffi::SSL_get_ex_data(ssl, get_ssl_verify_data_idx::()); + let verify: &F = mem::transmute(verify); + + let ctx = X509StoreContext::new(x509_ctx); + + verify(preverify_ok != 0, &ctx) as c_int + } +} + extern "C" fn raw_sni(ssl: *mut ffi::SSL, ad: &mut c_int, _arg: *mut c_void) -> c_int { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); @@ -928,6 +968,23 @@ impl Ssl { } } + /// Sets the certificate verification callback to be used during the + /// handshake process. + /// + /// The callback is provided with a boolean indicating if the + /// preveification process was successful, and an object providing access + /// to the certificate chain. It should return `true` if the certificate + /// chain is valid and `false` otherwise. + pub fn set_verify(&mut self, mode: SslVerifyMode, verify: F) + where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send + { + unsafe { + let verify = Box::new(verify); + ffi::SSL_set_ex_data(self.ssl, get_ssl_verify_data_idx::(), mem::transmute(verify)); + ffi::SSL_set_verify(self.ssl, mode.bits as c_int, Some(ssl_raw_verify::)); + } + } + pub fn get_current_cipher<'a>(&'a self) -> Option> { unsafe { let ptr = ffi::SSL_get_current_cipher(self.ssl); diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index ce153b8e..608d6fd7 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -381,6 +381,36 @@ 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 node_hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b"; + let node_id = node_hash_str.from_hex().unwrap(); + ssl.set_verify(SSL_VERIFY_PEER, move |_, x509| { + CHECKED.store(1, Ordering::SeqCst); + match x509.get_current_cert() { + None => false, + Some(cert) => { + let fingerprint = cert.fingerprint(SHA256).unwrap(); + fingerprint == node_id + } + } + }); + + match SslStream::connect_generic(ssl, stream) { + Ok(_) => (), + Err(err) => panic!("Expected success, got {:?}", err) + } + + assert_eq!(CHECKED.load(Ordering::SeqCst), 1); +}); + // Make sure every write call translates to a write call to the underlying socket. #[test] fn test_write_hits_stream() { -- cgit v1.2.3 From 9b1eb6d94d88da1a466954f3709b8399583ec5da Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 1 May 2016 20:45:49 -0700 Subject: Add a version of Ssl::set_verify that doesn't set a callback --- openssl/src/ssl/mod.rs | 9 ++++++++- openssl/src/ssl/tests/mod.rs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index b3c558c4..aa785142 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -968,6 +968,13 @@ impl Ssl { } } + /// Sets the verification mode to be used during the handshake process. + /// + /// Use `set_verify_callback` to additionally add a callback. + pub fn set_verify(&mut self, mode: SslVerifyMode) { + unsafe { ffi::SSL_set_verify(self.ssl, mode.bits as c_int, None) } + } + /// Sets the certificate verification callback to be used during the /// handshake process. /// @@ -975,7 +982,7 @@ impl Ssl { /// preveification process was successful, and an object providing access /// to the certificate chain. It should return `true` if the certificate /// chain is valid and `false` otherwise. - pub fn set_verify(&mut self, mode: SslVerifyMode, verify: F) + pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send { unsafe { diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 608d6fd7..c3e7a363 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -392,7 +392,7 @@ run_test!(ssl_verify_callback, |method, stream| { let node_hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b"; let node_id = node_hash_str.from_hex().unwrap(); - ssl.set_verify(SSL_VERIFY_PEER, move |_, x509| { + ssl.set_verify_callback(SSL_VERIFY_PEER, move |_, x509| { CHECKED.store(1, Ordering::SeqCst); match x509.get_current_cert() { None => false, -- cgit v1.2.3