diff options
| author | Steven Fackler <[email protected]> | 2015-12-17 21:26:06 -0800 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2015-12-17 21:26:06 -0800 |
| commit | 6195bd4fd8a46ab62cbbc5f654c9743371722dc1 (patch) | |
| tree | 0ccf253c93e6d4923c75ad51744e91dd1839f97f /openssl/src/ssl/mod.rs | |
| parent | Merge branch 'release-v0.7.2' into release (diff) | |
| parent | Release v0.7.3 (diff) | |
| download | rust-openssl-0.7.3.tar.xz rust-openssl-0.7.3.zip | |
Merge branch 'release-v0.7.3' into releasev0.7.3
Diffstat (limited to 'openssl/src/ssl/mod.rs')
| -rw-r--r-- | openssl/src/ssl/mod.rs | 476 |
1 files changed, 231 insertions, 245 deletions
diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 3b22c755..d529347f 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -45,7 +45,7 @@ extern "C" { } static mut VERIFY_IDX: c_int = -1; -static mut SNI_IDX: c_int = -1; +static mut SNI_IDX: c_int = -1; /// Manually initialize SSL. /// It is optional to call this function and safe to do so more than once. @@ -56,13 +56,11 @@ pub fn init() { INIT.call_once(|| { ffi::init(); - let verify_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, - None, None); + let verify_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); assert!(verify_idx >= 0); VERIFY_IDX = verify_idx; - let sni_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, - None, None); + let sni_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); assert!(sni_idx >= 0); SNI_IDX = sni_idx; }); @@ -234,9 +232,7 @@ lazy_static! { // Registers a destructor for the data which will be called // when context is freed fn get_verify_data_idx<T: Any + 'static>() -> c_int { - *INDEXES.lock().unwrap().entry(TypeId::of::<T>()).or_insert_with(|| { - get_new_idx::<T>() - }) + *INDEXES.lock().unwrap().entry(TypeId::of::<T>()).or_insert_with(|| get_new_idx::<T>()) } #[cfg(feature = "npn")] @@ -251,9 +247,12 @@ lazy_static! { /// Determine a new index to use for SSL CTX ex data. /// Registers a destruct for the data which will be called by openssl when the context is freed. fn get_new_idx<T>() -> c_int { - extern fn free_data_box<T>(_parent: *mut c_void, ptr: *mut c_void, - _ad: *mut ffi::CRYPTO_EX_DATA, _idx: c_int, - _argl: c_long, _argp: *mut c_void) { + extern "C" fn free_data_box<T>(_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<T> = unsafe { mem::transmute(ptr) }; } @@ -261,15 +260,13 @@ fn get_new_idx<T>() -> c_int { unsafe { let f: ffi::CRYPTO_EX_free = free_data_box::<T>; - let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, - None, Some(f)); + let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, Some(f)); assert!(idx >= 0); idx } } -extern fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) - -> c_int { +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(); let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); @@ -281,14 +278,16 @@ extern fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) match verify { None => preverify_ok, - Some(verify) => verify(preverify_ok != 0, &ctx) as c_int + Some(verify) => verify(preverify_ok != 0, &ctx) as c_int, } } } -extern fn raw_verify_with_data<T>(preverify_ok: c_int, - x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int - where T: Any + 'static { +extern "C" fn raw_verify_with_data<T>(preverify_ok: c_int, + x509_ctx: *mut ffi::X509_STORE_CTX) + -> c_int + where T: Any + 'static +{ unsafe { let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); @@ -304,15 +303,14 @@ extern fn raw_verify_with_data<T>(preverify_ok: c_int, let res = match verify { None => preverify_ok, - Some(verify) => verify(preverify_ok != 0, &ctx, data) as c_int + Some(verify) => verify(preverify_ok != 0, &ctx, data) as c_int, }; res } } -extern fn raw_sni(ssl: *mut ffi::SSL, ad: &mut c_int, _arg: *mut c_void) - -> 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); let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX); @@ -322,15 +320,16 @@ extern fn raw_sni(ssl: *mut ffi::SSL, ad: &mut c_int, _arg: *mut c_void) let res = match callback { None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, - Some(callback) => callback(&mut s, ad) + Some(callback) => callback(&mut s, ad), }; res } } -extern fn raw_sni_with_data<T>(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_void) -> c_int - where T: Any + 'static { +extern "C" fn raw_sni_with_data<T>(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_void) -> c_int + where T: Any + 'static +{ unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); @@ -343,7 +342,7 @@ extern fn raw_sni_with_data<T>(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_v let res = match callback { None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, - Some(callback) => callback(&mut s, ad, &*data) + Some(callback) => callback(&mut s, ad, &*data), }; // Since data might be required on the next verification @@ -357,25 +356,29 @@ extern fn raw_sni_with_data<T>(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_v #[cfg(any(feature = "npn", feature = "alpn"))] unsafe fn select_proto_using(ssl: *mut ffi::SSL, - out: *mut *mut c_uchar, outlen: *mut c_uchar, - inbuf: *const c_uchar, inlen: c_uint, - ex_data: c_int) -> c_int { - - // First, get the list of protocols (that the client should support) saved in the context - // extra data. - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, ex_data); - let protocols: &Vec<u8> = mem::transmute(protocols); - // Prepare the client list parameters to be passed to the OpenSSL function... - let client = protocols.as_ptr(); - 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. - 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 - } + out: *mut *mut c_uchar, + outlen: *mut c_uchar, + inbuf: *const c_uchar, + inlen: c_uint, + ex_data: c_int) + -> c_int { + + // First, get the list of protocols (that the client should support) saved in the context + // extra data. + let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); + let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, ex_data); + let protocols: &Vec<u8> = mem::transmute(protocols); + // Prepare the client list parameters to be passed to the OpenSSL function... + let client = protocols.as_ptr(); + 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. + 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`. @@ -385,23 +388,25 @@ unsafe fn select_proto_using(ssl: *mut ffi::SSL, /// function. The list of protocols supported by the client is found in the extra data of the /// OpenSSL context. #[cfg(feature = "npn")] -extern fn raw_next_proto_select_cb(ssl: *mut ffi::SSL, - out: *mut *mut c_uchar, outlen: *mut c_uchar, - inbuf: *const c_uchar, inlen: c_uint, - _arg: *mut c_void) -> c_int { - unsafe { - select_proto_using(ssl, out, outlen, inbuf, inlen, *NPN_PROTOS_IDX) - } +extern "C" fn raw_next_proto_select_cb(ssl: *mut ffi::SSL, + out: *mut *mut c_uchar, + outlen: *mut c_uchar, + inbuf: *const c_uchar, + inlen: c_uint, + _arg: *mut c_void) + -> c_int { + unsafe { select_proto_using(ssl, out, outlen, inbuf, inlen, *NPN_PROTOS_IDX) } } #[cfg(feature = "alpn")] -extern fn raw_alpn_select_cb(ssl: *mut ffi::SSL, - out: *mut *mut c_uchar, outlen: *mut c_uchar, - inbuf: *const c_uchar, inlen: c_uint, - _arg: *mut c_void) -> c_int { - unsafe { - select_proto_using(ssl, out, outlen, inbuf, inlen, *ALPN_PROTOS_IDX) - } +extern "C" fn raw_alpn_select_cb(ssl: *mut ffi::SSL, + out: *mut *mut c_uchar, + outlen: *mut c_uchar, + inbuf: *const c_uchar, + inlen: c_uint, + _arg: *mut c_void) + -> c_int { + unsafe { select_proto_using(ssl, out, outlen, inbuf, inlen, *ALPN_PROTOS_IDX) } } /// The function is given as the callback to `SSL_CTX_set_next_protos_advertised_cb`. @@ -412,9 +417,11 @@ extern fn raw_alpn_select_cb(ssl: *mut ffi::SSL, /// The list of supported protocols is found in the extra data of the OpenSSL /// context. #[cfg(feature = "npn")] -extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, - out: *mut *const c_uchar, outlen: *mut c_uint, - _arg: *mut c_void) -> c_int { +extern "C" fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, + out: *mut *const c_uchar, + outlen: *mut c_uint, + _arg: *mut c_void) + -> c_int { unsafe { // First, get the list of (supported) protocols saved in the context extra data. let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); @@ -437,8 +444,7 @@ extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, /// Convert a set of byte slices into a series of byte strings encoded for SSL. Encoding is a byte /// containing the length followed by the string. #[cfg(any(feature = "npn", feature = "alpn"))] -fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec<u8> -{ +fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec<u8> { let mut enc = Vec::new(); for string in strings { let len = string.len() as u8; @@ -453,14 +459,12 @@ fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec<u8> } /// The signature of functions that can be used to manually verify certificates -pub type VerifyCallback = fn(preverify_ok: bool, - x509_ctx: &X509StoreContext) -> bool; +pub type VerifyCallback = fn(preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool; /// The signature of functions that can be used to manually verify certificates /// when user-data should be carried for all verification process -pub type VerifyCallbackData<T> = fn(preverify_ok: bool, - x509_ctx: &X509StoreContext, - data: &T) -> bool; +pub type VerifyCallbackData<T> = fn(preverify_ok: bool, x509_ctx: &X509StoreContext, data: &T) + -> bool; /// The signature of functions that can be used to choose the context depending on the server name pub type ServerNameCallback = fn(ssl: &mut Ssl, ad: &mut i32) -> i32; @@ -469,7 +473,7 @@ pub type ServerNameCallbackData<T> = fn(ssl: &mut Ssl, ad: &mut i32, data: &T) - // FIXME: macro may be instead of inlining? #[inline] -fn wrap_ssl_result(res: c_int) -> Result<(),SslError> { +fn wrap_ssl_result(res: c_int) -> Result<(), SslError> { if res == 0 { Err(SslError::get()) } else { @@ -479,7 +483,7 @@ fn wrap_ssl_result(res: c_int) -> Result<(),SslError> { /// An SSL context object pub struct SslContext { - ctx: *mut ffi::SSL_CTX + ctx: *mut ffi::SSL_CTX, } unsafe impl Send for SslContext {} @@ -515,13 +519,10 @@ impl SslContext { } /// Configures the certificate verification method for new connections. - pub fn set_verify(&mut self, mode: SslVerifyMode, - verify: Option<VerifyCallback>) { + pub fn set_verify(&mut self, mode: SslVerifyMode, verify: Option<VerifyCallback>) { unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, VERIFY_IDX, - mem::transmute(verify)); - let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = - raw_verify; + ffi::SSL_CTX_set_ex_data(self.ctx, VERIFY_IDX, mem::transmute(verify)); + let f: extern "C" fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = raw_verify; ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f)); } @@ -531,18 +532,18 @@ impl SslContext { /// carrying supplied data. // Note: no option because there is no point to set data without providing // a function handling it - pub fn set_verify_with_data<T>(&mut self, mode: SslVerifyMode, + pub fn set_verify_with_data<T>(&mut self, + mode: SslVerifyMode, verify: VerifyCallbackData<T>, data: T) - where T: Any + 'static { + where T: Any + 'static + { let data = Box::new(data); unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, VERIFY_IDX, - mem::transmute(Some(verify))); - ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::<T>(), - mem::transmute(data)); - let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = - raw_verify_with_data::<T>; + ffi::SSL_CTX_set_ex_data(self.ctx, VERIFY_IDX, mem::transmute(Some(verify))); + ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::<T>(), mem::transmute(data)); + let f: extern "C" fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = + raw_verify_with_data::<T>; ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f)); } @@ -554,25 +555,25 @@ impl SslContext { /// with `set_ssl_context` pub fn set_servername_callback(&mut self, callback: Option<ServerNameCallback>) { unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, - mem::transmute(callback)); - let f: extern fn() = mem::transmute(raw_sni); + ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(callback)); + let f: extern "C" fn() = mem::transmute(raw_sni); ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); } } /// Configures the server name indication (SNI) callback for new connections /// carrying supplied data - pub fn set_servername_callback_with_data<T>(&mut self, callback: ServerNameCallbackData<T>, - data: T) - where T: Any + 'static { + pub fn set_servername_callback_with_data<T>(&mut self, + callback: ServerNameCallbackData<T>, + data: T) + where T: Any + 'static + { let data = Box::new(data); unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, - mem::transmute(Some(callback))); + ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(Some(callback))); ffi_extras::SSL_CTX_set_tlsext_servername_arg(self.ctx, mem::transmute(data)); - let f: extern fn() = mem::transmute(raw_sni_with_data::<T>); + let f: extern "C" fn() = mem::transmute(raw_sni_with_data::<T>); ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); } } @@ -590,91 +591,86 @@ impl SslContext { } } - pub fn set_tmp_dh(&self, dh: DH) -> Result<(),SslError> { - wrap_ssl_result(unsafe { - ffi_extras::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 - }) + pub fn set_tmp_dh(&self, dh: DH) -> Result<(), SslError> { + wrap_ssl_result(unsafe { ffi_extras::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<P: AsRef<Path>>(&mut self, file: P) -> Result<(),SslError> { + pub fn set_CA_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), SslError> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); - wrap_ssl_result( - unsafe { - ffi::SSL_CTX_load_verify_locations(self.ctx, file.as_ptr() as *const _, ptr::null()) - }) + wrap_ssl_result(unsafe { + ffi::SSL_CTX_load_verify_locations(self.ctx, file.as_ptr() as *const _, ptr::null()) + }) } /// Specifies the file that contains certificate - pub fn set_certificate_file<P: AsRef<Path>>(&mut self, file: P, file_type: X509FileType) - -> Result<(),SslError> { + pub fn set_certificate_file<P: AsRef<Path>>(&mut self, + file: P, + file_type: X509FileType) + -> Result<(), SslError> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); - wrap_ssl_result( - unsafe { - ffi::SSL_CTX_use_certificate_file(self.ctx, file.as_ptr() as *const _, file_type as c_int) - }) + wrap_ssl_result(unsafe { + ffi::SSL_CTX_use_certificate_file(self.ctx, + file.as_ptr() as *const _, + file_type as c_int) + }) } /// Specifies the file that contains certificate chain - pub fn set_certificate_chain_file<P: AsRef<Path>>(&mut self, file: P, file_type: X509FileType) - -> Result<(),SslError> { + pub fn set_certificate_chain_file<P: AsRef<Path>>(&mut self, + file: P, + file_type: X509FileType) + -> Result<(), SslError> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); - wrap_ssl_result( - unsafe { - ffi::SSL_CTX_use_certificate_chain_file(self.ctx, file.as_ptr() as *const _, file_type as c_int) - }) + wrap_ssl_result(unsafe { + ffi::SSL_CTX_use_certificate_chain_file(self.ctx, + file.as_ptr() as *const _, + file_type as c_int) + }) } /// Specifies the certificate - pub fn set_certificate(&mut self, cert: &X509) -> Result<(),SslError> { - wrap_ssl_result( - unsafe { - ffi::SSL_CTX_use_certificate(self.ctx, cert.get_handle()) - }) + pub fn set_certificate(&mut self, cert: &X509) -> Result<(), SslError> { + wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.ctx, cert.get_handle()) }) } /// Adds a certificate to the certificate chain presented together with the /// certificate specified using set_certificate() - pub fn add_extra_chain_cert(&mut self, cert: &X509) -> Result<(),SslError> { - wrap_ssl_result( - unsafe { - ffi_extras::SSL_CTX_add_extra_chain_cert(self.ctx, cert.get_handle()) as c_int - }) + pub fn add_extra_chain_cert(&mut self, cert: &X509) -> Result<(), SslError> { + wrap_ssl_result(unsafe { + ffi_extras::SSL_CTX_add_extra_chain_cert(self.ctx, cert.get_handle()) as c_int + }) } /// Specifies the file that contains private key - pub fn set_private_key_file<P: AsRef<Path>>(&mut self, file: P, - file_type: X509FileType) -> Result<(),SslError> { + pub fn set_private_key_file<P: AsRef<Path>>(&mut self, + file: P, + file_type: X509FileType) + -> Result<(), SslError> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); - wrap_ssl_result( - unsafe { - ffi::SSL_CTX_use_PrivateKey_file(self.ctx, file.as_ptr() as *const _, file_type as c_int) - }) + wrap_ssl_result(unsafe { + ffi::SSL_CTX_use_PrivateKey_file(self.ctx, + file.as_ptr() as *const _, + file_type as c_int) + }) } /// Specifies the private key - pub fn set_private_key(&mut self, key: &PKey) -> Result<(),SslError> { - wrap_ssl_result( - unsafe { - ffi::SSL_CTX_use_PrivateKey(self.ctx, key.get_handle()) - }) + pub fn set_private_key(&mut self, key: &PKey) -> Result<(), SslError> { + wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.ctx, key.get_handle()) }) } /// Check consistency of private key and certificate - pub fn check_private_key(&mut self) -> Result<(),SslError> { - wrap_ssl_result( - unsafe { - ffi::SSL_CTX_check_private_key(self.ctx) - }) + pub fn check_private_key(&mut self) -> Result<(), SslError> { + wrap_ssl_result(unsafe { ffi::SSL_CTX_check_private_key(self.ctx) }) } - pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(),SslError> { - wrap_ssl_result( - unsafe { - let cipher_list = CString::new(cipher_list).unwrap(); - ffi::SSL_CTX_set_cipher_list(self.ctx, cipher_list.as_ptr() as *const _) - }) + pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), SslError> { + wrap_ssl_result(unsafe { + let cipher_list = CString::new(cipher_list).unwrap(); + ffi::SSL_CTX_set_cipher_list(self.ctx, cipher_list.as_ptr() as *const _) + }) } /// If `onoff` is set to `true`, enable ECDHE for key exchange with compatible @@ -682,33 +678,24 @@ impl SslContext { /// /// This method requires OpenSSL >= 1.0.2 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_extras::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_int) - }) + pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), SslError> { + wrap_ssl_result(unsafe { ffi_extras::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 { - ffi_extras::SSL_CTX_set_options(self.ctx, raw_bits) - }; + let ret = unsafe { ffi_extras::SSL_CTX_set_options(self.ctx, raw_bits) }; SslContextOptions::from_bits(ret).unwrap() } pub fn get_options(&mut self) -> SslContextOptions { - let ret = unsafe { - ffi_extras::SSL_CTX_get_options(self.ctx) - }; + let ret = unsafe { ffi_extras::SSL_CTX_get_options(self.ctx) }; SslContextOptions::from_bits(ret).unwrap() } pub fn clear_options(&mut self, option: SslContextOptions) -> SslContextOptions { let raw_bits = option.bits(); - let ret = unsafe { - ffi_extras::SSL_CTX_clear_options(self.ctx, raw_bits) - }; + let ret = unsafe { ffi_extras::SSL_CTX_clear_options(self.ctx, raw_bits) }; SslContextOptions::from_bits(ret).unwrap() } @@ -725,15 +712,18 @@ impl SslContext { unsafe { // Attach the protocol list to the OpenSSL context structure, // so that we can refer to it within the callback. - ffi::SSL_CTX_set_ex_data(self.ctx, *NPN_PROTOS_IDX, - mem::transmute(protocols)); + ffi::SSL_CTX_set_ex_data(self.ctx, *NPN_PROTOS_IDX, mem::transmute(protocols)); // Now register the callback that performs the default protocol // matching based on the client-supported list of protocols that // has been saved. - ffi::SSL_CTX_set_next_proto_select_cb(self.ctx, raw_next_proto_select_cb, ptr::null_mut()); + ffi::SSL_CTX_set_next_proto_select_cb(self.ctx, + raw_next_proto_select_cb, + ptr::null_mut()); // Also register the callback to advertise these protocols, if a server socket is // created with the context. - ffi::SSL_CTX_set_next_protos_advertised_cb(self.ctx, raw_next_protos_advertise_cb, ptr::null_mut()); + ffi::SSL_CTX_set_next_protos_advertised_cb(self.ctx, + raw_next_protos_advertise_cb, + ptr::null_mut()); } } @@ -756,8 +746,7 @@ impl SslContext { // ssl ctx's ex_data so that we can configure a function to free it later. In the // future, it might make sense to pull this into our internal struct Ssl instead of // leaning on openssl and using function pointers. - ffi::SSL_CTX_set_ex_data(self.ctx, *ALPN_PROTOS_IDX, - mem::transmute(protocols)); + ffi::SSL_CTX_set_ex_data(self.ctx, *ALPN_PROTOS_IDX, mem::transmute(protocols)); // Now register the callback that performs the default protocol // matching based on the client-supported list of protocols that @@ -765,11 +754,10 @@ impl SslContext { ffi::SSL_CTX_set_alpn_select_cb(self.ctx, raw_alpn_select_cb, ptr::null_mut()); } } - } pub struct Ssl { - ssl: *mut ffi::SSL + ssl: *mut ffi::SSL, } unsafe impl Send for Ssl {} @@ -778,8 +766,8 @@ unsafe impl Sync for Ssl {} impl fmt::Debug for Ssl { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("Ssl") - .field("state", &self.state_string_long()) - .finish() + .field("state", &self.state_string_long()) + .finish() } } @@ -830,7 +818,7 @@ impl Ssl { let err = unsafe { ffi::SSL_get_error(self.ssl, ret) }; match LibSslError::from_i32(err as i32) { Some(err) => err, - None => unreachable!() + None => unreachable!(), } } @@ -855,7 +843,9 @@ impl Ssl { /// Sets the host name to be used with SNI (Server Name Indication). pub fn set_hostname(&self, hostname: &str) -> Result<(), SslError> { let cstr = CString::new(hostname).unwrap(); - let ret = unsafe { ffi_extras::SSL_set_tlsext_host_name(self.ssl, cstr.as_ptr() as *const _) }; + let ret = unsafe { + ffi_extras::SSL_set_tlsext_host_name(self.ssl, cstr.as_ptr() as *const _) + }; // For this case, 0 indicates failure. if ret == 0 { @@ -926,9 +916,7 @@ impl Ssl { /// Returns the number of bytes remaining in the currently processed TLS /// record. pub fn pending(&self) -> usize { - unsafe { - ffi::SSL_pending(self.ssl) as usize - } + unsafe { ffi::SSL_pending(self.ssl) as usize } } /// Returns the compression currently in use. @@ -963,9 +951,7 @@ impl Ssl { return None; } - unsafe { - String::from_utf8(CStr::from_ptr(name).to_bytes().to_vec()).ok() - } + unsafe { String::from_utf8(CStr::from_ptr(name as *const _).to_bytes().to_vec()).ok() } } /// change the context corresponding to the current connection @@ -1038,12 +1024,13 @@ impl<S> Drop for SslStream<S> { } } -impl<S> fmt::Debug for SslStream<S> where S: fmt::Debug { +impl<S> fmt::Debug for SslStream<S> where S: fmt::Debug +{ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("SslStream") - .field("stream", &self.get_ref()) - .field("ssl", &self.ssl()) - .finish() + .field("stream", &self.get_ref()) + .field("ssl", &self.ssl()) + .finish() } } @@ -1061,7 +1048,7 @@ impl<S: AsRawSocket> AsRawSocket for SslStream<S> { } } -impl<S: Read+Write> SslStream<S> { +impl<S: Read + Write> SslStream<S> { fn new_base(ssl: Ssl, stream: S) -> Self { unsafe { let (bio, method) = bio::new(stream).unwrap(); @@ -1083,16 +1070,10 @@ impl<S: Read+Write> SslStream<S> { if ret > 0 { Ok(stream) } else { - match stream.make_old_error(ret) { - SslError::StreamError(e) => { - // This is fine - nonblocking sockets will finish the handshake in read/write - if e.kind() == io::ErrorKind::WouldBlock { - Ok(stream) - } else { - Err(SslError::StreamError(e)) - } - } - e => Err(e) + match stream.make_error(ret) { + // This is fine - nonblocking sockets will finish the handshake in read/write + Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), + _ => Err(stream.make_old_error(ret)), } } } @@ -1105,16 +1086,10 @@ impl<S: Read+Write> SslStream<S> { if ret > 0 { Ok(stream) } else { - match stream.make_old_error(ret) { - SslError::StreamError(e) => { - // This is fine - nonblocking sockets will finish the handshake in read/write - if e.kind() == io::ErrorKind::WouldBlock { - Ok(stream) - } else { - Err(SslError::StreamError(e)) - } - } - e => Err(e) + match stream.make_error(ret) { + // This is fine - nonblocking sockets will finish the handshake in read/write + Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), + _ => Err(stream.make_old_error(ret)), } } } @@ -1132,6 +1107,32 @@ impl<S: Read+Write> SslStream<S> { pub fn accept_generic<T: IntoSsl>(ssl: T, stream: S) -> Result<SslStream<S>, SslError> { Self::accept(ssl, stream) } + + /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`. + /// + /// This is particularly useful with a nonblocking socket, where the error + /// value will identify if OpenSSL is waiting on read or write readiness. + pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { + let ret = self.ssl.read(buf); + if ret >= 0 { + Ok(ret as usize) + } else { + Err(self.make_error(ret)) + } + } + + /// Like `write`, but returns an `ssl::Error` rather than an `io::Error`. + /// + /// This is particularly useful with a nonblocking socket, where the error + /// value will identify if OpenSSL is waiting on read or write readiness. + pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> { + let ret = self.ssl.write(buf); + if ret >= 0 { + Ok(ret as usize) + } else { + Err(self.make_error(ret)) + } + } } impl<S> SslStream<S> { @@ -1154,8 +1155,10 @@ impl<S> SslStream<S> { LibSslError::ErrorZeroReturn => Error::ZeroReturn, LibSslError::ErrorWantWrite => Error::WantWrite(self.get_bio_error()), LibSslError::ErrorWantRead => Error::WantRead(self.get_bio_error()), - err => Error::Stream(io::Error::new(io::ErrorKind::Other, - format!("unexpected error {:?}", err))), + err => { + Error::Stream(io::Error::new(io::ErrorKind::Other, + format!("unexpected error {:?}", err))) + } } } @@ -1183,8 +1186,10 @@ impl<S> SslStream<S> { LibSslError::ErrorWantWrite | LibSslError::ErrorWantRead => { SslError::StreamError(self.get_bio_error()) } - err => SslError::StreamError(io::Error::new(io::ErrorKind::Other, - format!("unexpected error {:?}", err))), + err => { + SslError::StreamError(io::Error::new(io::ErrorKind::Other, + format!("unexpected error {:?}", err))) + } } } @@ -1192,8 +1197,10 @@ impl<S> SslStream<S> { let error = unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }; match error { Some(error) => error, - None => io::Error::new(io::ErrorKind::Other, - "BUG: got an ErrorSyscall without an error in the BIO?") + None => { + io::Error::new(io::ErrorKind::Other, + "BUG: got an ErrorSyscall without an error in the BIO?") + } } } @@ -1218,32 +1225,6 @@ impl<S> SslStream<S> { } } - /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`. - /// - /// This is particularly useful with a nonblocking socket, where the error - /// value will identify if OpenSSL is waiting on read or write readiness. - pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { - let ret = self.ssl.read(buf); - if ret >= 0 { - Ok(ret as usize) - } else { - Err(self.make_error(ret)) - } - } - - /// Like `write`, but returns an `ssl::Error` rather than an `io::Error`. - /// - /// This is particularly useful with a nonblocking socket, where the error - /// value will identify if OpenSSL is waiting on read or write readiness. - pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> { - let ret = self.ssl.write(buf); - if ret >= 0 { - Ok(ret as usize) - } else { - Err(self.make_error(ret)) - } - } - /// Returns the OpenSSL `Ssl` object associated with this stream. pub fn ssl(&self) -> &Ssl { &self.ssl @@ -1258,7 +1239,7 @@ impl SslStream<::std::net::TcpStream> { } } -impl<S: Read> Read for SslStream<S> { +impl<S: Read + Write> Read for SslStream<S> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { match self.ssl_read(buf) { Ok(n) => Ok(n), @@ -1271,7 +1252,7 @@ impl<S: Read> Read for SslStream<S> { } } -impl<S: Write> Write for SslStream<S> { +impl<S: Read + Write> Write for SslStream<S> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.ssl_write(buf).map_err(|e| { match e { @@ -1306,14 +1287,17 @@ impl<'a> IntoSsl for &'a SslContext { /// A utility type to help in cases where the use of SSL is decided at runtime. #[derive(Debug)] -pub enum MaybeSslStream<S> where S: Read+Write { +pub enum MaybeSslStream<S> + where S: Read + Write +{ /// A connection using SSL Ssl(SslStream<S>), /// A connection not using SSL Normal(S), } -impl<S> Read for MaybeSslStream<S> where S: Read+Write { +impl<S> Read for MaybeSslStream<S> where S: Read + Write +{ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { match *self { MaybeSslStream::Ssl(ref mut s) => s.read(buf), @@ -1322,7 +1306,8 @@ impl<S> Read for MaybeSslStream<S> where S: Read+Write { } } -impl<S> Write for MaybeSslStream<S> where S: Read+Write { +impl<S> Write for MaybeSslStream<S> where S: Read + Write +{ fn write(&mut self, buf: &[u8]) -> io::Result<usize> { match *self { MaybeSslStream::Ssl(ref mut s) => s.write(buf), @@ -1338,7 +1323,8 @@ impl<S> Write for MaybeSslStream<S> where S: Read+Write { } } -impl<S> MaybeSslStream<S> where S: Read+Write { +impl<S> MaybeSslStream<S> where S: Read + Write +{ /// Returns a reference to the underlying stream. pub fn get_ref(&self) -> &S { match *self { @@ -1423,7 +1409,7 @@ impl<S> NonblockingSslStream<S> { } } -impl<S: Read+Write> NonblockingSslStream<S> { +impl<S: Read + Write> NonblockingSslStream<S> { /// Create a new nonblocking client ssl connection on wrapped `stream`. /// /// Note that this method will most likely not actually complete the SSL @@ -1453,7 +1439,7 @@ impl<S: Read+Write> NonblockingSslStream<S> { SslError::OpenSslErrors(e.iter() .map(|e| OpensslError::from_error_code(e.error_code())) .collect()) - .into() + .into() } } } @@ -1477,7 +1463,7 @@ impl<S: Read+Write> NonblockingSslStream<S> { match self.0.ssl_read(buf) { Ok(n) => Ok(n), Err(Error::ZeroReturn) => Ok(0), - Err(e) => Err(self.convert_err(e)) + Err(e) => Err(self.convert_err(e)), } } |