diff options
Diffstat (limited to 'openssl')
| -rw-r--r-- | openssl/Cargo.toml | 10 | ||||
| -rw-r--r-- | openssl/src/crypto/pkey.rs | 38 | ||||
| -rw-r--r-- | openssl/src/lib.rs | 5 | ||||
| -rw-r--r-- | openssl/src/ssl/bio.rs | 12 | ||||
| -rw-r--r-- | openssl/src/ssl/mod.rs | 25 | ||||
| -rw-r--r-- | openssl/src/ssl/tests/mod.rs | 17 | ||||
| -rw-r--r-- | openssl/src/version.rs | 89 |
7 files changed, 178 insertions, 18 deletions
diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 09f84433..08f5a6cd 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "openssl" -version = "0.7.9" +version = "0.7.10" authors = ["Steven Fackler <[email protected]>"] license = "Apache-2.0" description = "OpenSSL bindings" repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.9/openssl" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.10/openssl" readme = "../README.md" keywords = ["crypto", "tls", "ssl", "dtls"] build = "build.rs" @@ -30,10 +30,10 @@ nightly = [] [dependencies] bitflags = "0.4" -lazy_static = "0.1" +lazy_static = "0.2" libc = "0.2" -openssl-sys = { version = "0.7.9", path = "../openssl-sys" } -openssl-sys-extras = { version = "0.7.9", path = "../openssl-sys-extras" } +openssl-sys = { version = "0.7.10", path = "../openssl-sys" } +openssl-sys-extras = { version = "0.7.10", path = "../openssl-sys-extras" } [build-dependencies] gcc = "0.3" diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index f945276d..ba0a16b6 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -609,11 +609,19 @@ impl Drop for PKey { impl Clone for PKey { fn clone(&self) -> Self { - unsafe { - let new_evp = ffi::EVP_PKEY_new(); - assert!(ffi::EVP_PKEY_copy_parameters(new_evp, self.evp) == 0); - PKey::from_handle(new_evp, self.parts) + let mut pkey = PKey::from_handle(unsafe { ffi::EVP_PKEY_new() }, self.parts); + // copy by encoding to DER and back + match self.parts { + Parts::Public => { + pkey.load_pub(&self.save_pub()[..]); + }, + Parts::Both => { + pkey.load_priv(&self.save_priv()[..]); + }, + Parts::Neither => { + }, } + pkey } } @@ -874,4 +882,26 @@ mod tests { assert!(old_pkey_n == pkey.get_rsa().n().unwrap()); } + + #[test] + fn test_pkey_clone_copies_private() { + let mut pkey = super::PKey::new(); + pkey.gen(512); + + let pkey2 = pkey.clone(); + + assert!(pkey.get_rsa().q().unwrap() == pkey2.get_rsa().q().unwrap()); + } + + #[test] + fn test_pkey_clone_copies_public() { + let mut pkey = super::PKey::new(); + pkey.gen(512); + let mut pub_key = super::PKey::new(); + pub_key.load_pub(&pkey.save_pub()[..]); + + let pub_key2 = pub_key.clone(); + + assert!(pub_key.get_rsa().n().unwrap() == pub_key2.get_rsa().n().unwrap()); + } } diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index ad982597..63926615 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -1,5 +1,5 @@ -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.9")] -#![cfg_attr(feature = "nightly", feature(const_fn, recover, panic_propagate))] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.10")] +#![cfg_attr(feature = "nightly", feature(const_fn))] #[macro_use] extern crate bitflags; @@ -25,3 +25,4 @@ pub mod dh; pub mod ssl; pub mod x509; pub mod nid; +pub mod version; diff --git a/openssl/src/ssl/bio.rs b/openssl/src/ssl/bio.rs index 4adbfbe2..e53545d7 100644 --- a/openssl/src/ssl/bio.rs +++ b/openssl/src/ssl/bio.rs @@ -82,12 +82,12 @@ unsafe fn state<'a, S: 'a>(bio: *mut BIO) -> &'a mut StreamState<S> { } #[cfg(feature = "nightly")] -fn recover<F, T>(f: F) -> Result<T, Box<Any + Send>> where F: FnOnce() -> T { - ::std::panic::recover(::std::panic::AssertRecoverSafe(f)) +fn catch_unwind<F, T>(f: F) -> Result<T, Box<Any + Send>> where F: FnOnce() -> T { + ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(f)) } #[cfg(not(feature = "nightly"))] -fn recover<F, T>(f: F) -> Result<T, Box<Any + Send>> where F: FnOnce() -> T { +fn catch_unwind<F, T>(f: F) -> Result<T, Box<Any + Send>> where F: FnOnce() -> T { Ok(f()) } @@ -97,7 +97,7 @@ unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_ let state = state::<S>(bio); let buf = slice::from_raw_parts(buf as *const _, len as usize); - match recover(|| state.stream.write(buf)) { + match catch_unwind(|| state.stream.write(buf)) { Ok(Ok(len)) => len as c_int, Ok(Err(err)) => { if retriable_error(&err) { @@ -119,7 +119,7 @@ unsafe extern "C" fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int) let state = state::<S>(bio); let buf = slice::from_raw_parts_mut(buf as *mut _, len as usize); - match recover(|| state.stream.read(buf)) { + match catch_unwind(|| state.stream.read(buf)) { Ok(Ok(len)) => len as c_int, Ok(Err(err)) => { if retriable_error(&err) { @@ -154,7 +154,7 @@ unsafe extern "C" fn ctrl<S: Write>(bio: *mut BIO, if cmd == BIO_CTRL_FLUSH { let state = state::<S>(bio); - match recover(|| state.stream.flush()) { + match catch_unwind(|| state.stream.flush()) { Ok(Ok(())) => 1, Ok(Err(err)) => { state.error = Some(err); diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 7b5cf492..4b3a4385 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -612,6 +612,15 @@ impl SslContext { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 }) } + /// Use the default locations of trusted certificates for verification. + /// + /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR` + /// environment variables if present, or defaults specified at OpenSSL + /// build time otherwise. + pub fn set_default_verify_paths(&mut self) -> Result<(), SslError> { + wrap_ssl_result(unsafe { ffi::SSL_CTX_set_default_verify_paths(self.ctx) }) + } + #[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> { @@ -621,6 +630,20 @@ impl SslContext { }) } + /// Set the context identifier for sessions + /// + /// This value identifies the server's session cache to a clients, telling them when they're + /// able to reuse sessions. Should be set to a unique value per server, unless multiple servers + /// share a session cache. + /// + /// This value should be set when using client certificates, or each request will fail + /// handshake and need to be restarted. + pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), SslError> { + wrap_ssl_result(unsafe { + ffi::SSL_CTX_set_session_id_context(self.ctx, sid_ctx.as_ptr(), sid_ctx.len() as u32) + }) + } + /// Specifies the file that contains certificate pub fn set_certificate_file<P: AsRef<Path>>(&mut self, file: P, @@ -1309,7 +1332,7 @@ impl<S> SslStream<S> { #[cfg(feature = "nightly")] fn check_panic(&mut self) { if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } { - ::std::panic::propagate(err) + ::std::panic::resume_unwind(err) } } diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index be35d7ef..15811d99 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -1059,3 +1059,20 @@ fn refcount_ssl_context() { let _new_ctx_b = ssl.set_ssl_context(&new_ctx_a); } } + +#[test] +fn default_verify_paths() { + let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap(); + ctx.set_default_verify_paths().unwrap(); + ctx.set_verify(SSL_VERIFY_PEER, None); + let s = TcpStream::connect("google.com:443").unwrap(); + let mut socket = SslStream::connect(&ctx, 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>")); +} diff --git a/openssl/src/version.rs b/openssl/src/version.rs new file mode 100644 index 00000000..323cf1e2 --- /dev/null +++ b/openssl/src/version.rs @@ -0,0 +1,89 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use ffi; +use std::ffi::CStr; + +/// OPENSSL_VERSION_NUMBER is a numeric release version identifier: +/// +/// `MNNFFPPS: major minor fix patch status` +/// +/// The status nibble has one of the values 0 for development, 1 to e for betas 1 to 14, and f for release. +/// +/// for example +/// +/// `0x000906000 == 0.9.6 dev` +/// `0x000906023 == 0.9.6b beta 3` +/// `0x00090605f == 0.9.6e release` +/// +/// Versions prior to 0.9.3 have identifiers < 0x0930. Versions between 0.9.3 and 0.9.5 had a version identifier with this interpretation: +/// +/// `MMNNFFRBB major minor fix final beta/patch` +/// +/// for example +/// +/// `0x000904100 == 0.9.4 release` +/// `0x000905000 == 0.9.5 dev` +/// +/// Version 0.9.5a had an interim interpretation that is like the current one, except the patch level got the highest bit set, to keep continuity. The number was therefore 0x0090581f +/// +/// The return value of this function can be compared to the macro to make sure that the correct version of the library has been loaded, especially when using DLLs on Windows systems. +pub fn number() -> i64 { + unsafe { ffi::SSLeay() as i64 } +} + + +/// The text variant of the version number and the release date. For example, "OpenSSL 0.9.5a 1 Apr 2000". +pub fn version() -> &'static str { + unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_VERSION)).to_str().unwrap() } +} + +/// The compiler flags set for the compilation process in the form "compiler: ..." if available or +/// "compiler: information not available" otherwise. +pub fn c_flags() -> &'static str { + unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_CFLAGS)).to_str().unwrap() } +} + +/// The date of the build process in the form "built on: ..." if available or "built on: date not available" otherwise. +pub fn built_on() -> &'static str { + unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_BUILT_ON)).to_str().unwrap() } +} + +/// The "Configure" target of the library build in the form "platform: ..." if available or "platform: information not available" otherwise. +pub fn platform() -> &'static str { + unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_PLATFORM)).to_str().unwrap() } +} + +/// The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "..."" if available or "OPENSSLDIR: N/A" otherwise. +pub fn dir() -> &'static str { + unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_DIR)).to_str().unwrap() } +} + +/// This test ensures that we do not segfault when calling the functions of this module +/// and that the strings respect a reasonable format. +#[test] +fn test_versions() { + println!("Number: '{}'", number()); + println!("Version: '{}'", version()); + println!("C flags: '{}'", c_flags()); + println!("Built on: '{}'", built_on()); + println!("Platform: '{}'", platform()); + println!("Dir: '{}'", dir()); + + assert!(number() > 0); + assert!(version().starts_with("OpenSSL")); + assert!(c_flags().starts_with("compiler:")); + assert!(built_on().starts_with("built on:")); + assert!(dir().starts_with("OPENSSLDIR:")); +}
\ No newline at end of file |