diff options
| author | Alex Crichton <[email protected]> | 2016-09-30 00:43:05 -0700 |
|---|---|---|
| committer | Alex Crichton <[email protected]> | 2016-10-12 22:49:55 -0700 |
| commit | 43c951f743e68fac5f45119eda7c994882a1d489 (patch) | |
| tree | 45169f1b92858a3ba2ad0287de1bf1ecb395804b /openssl/src/x509 | |
| parent | Rename NoPadding to None (diff) | |
| download | rust-openssl-43c951f743e68fac5f45119eda7c994882a1d489.tar.xz rust-openssl-43c951f743e68fac5f45119eda7c994882a1d489.zip | |
Add support for OpenSSL 1.1.0
This commit is relatively major refactoring of the `openssl-sys` crate as well
as the `openssl` crate itself. The end goal here was to support OpenSSL 1.1.0,
and lots of other various tweaks happened along the way. The major new features
are:
* OpenSSL 1.1.0 is supported
* OpenSSL 0.9.8 is no longer supported (aka all OSX users by default)
* All FFI bindings are verified with the `ctest` crate (same way as the `libc`
crate)
* CI matrixes are vastly expanded to include 32/64 of all platforms, more
OpenSSL version coverage, as well as ARM coverage on Linux
* The `c_helpers` module is completely removed along with the `gcc` dependency.
* The `openssl-sys` build script was completely rewritten
* Now uses `OPENSSL_DIR` to find the installation, not include/lib env vars.
* Better error messages for mismatched versions.
* Better error messages for failing to find OpenSSL on a platform (more can be
done here)
* Probing of OpenSSL build-time configuration to inform the API of the `*-sys`
crate.
* Many Cargo features have been removed as they're now enabled by default.
As this is a breaking change to both the `openssl` and `openssl-sys` crates this
will necessitate a major version bump of both. There's still a few more API
questions remaining but let's hash that out on a PR!
Closes #452
Diffstat (limited to 'openssl/src/x509')
| -rw-r--r-- | openssl/src/x509/mod.rs | 132 | ||||
| -rw-r--r-- | openssl/src/x509/tests.rs | 2 |
2 files changed, 103 insertions, 31 deletions
diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index f5369447..086342dd 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -12,7 +12,6 @@ use std::marker::PhantomData; use HashTypeInternals; use asn1::Asn1Time; -#[cfg(feature = "x509_expiry")] use asn1::Asn1TimeRef; use bio::{MemBio, MemBioSlice}; @@ -24,6 +23,19 @@ use ffi; use nid::Nid; use error::ErrorStack; +#[cfg(ossl10x)] +use ffi::{ + X509_set_notBefore, + X509_set_notAfter, + ASN1_STRING_data, +}; +#[cfg(ossl110)] +use ffi::{ + X509_set1_notBefore as X509_set_notBefore, + X509_set1_notAfter as X509_set_notAfter, + ASN1_STRING_get0_data as ASN1_STRING_data, +}; + pub mod extension; use self::extension::{ExtensionType, Extension}; @@ -36,7 +48,7 @@ pub struct SslString(&'static str); impl<'s> Drop for SslString { fn drop(&mut self) { unsafe { - ffi::CRYPTO_free(self.0.as_ptr() as *mut c_void); + CRYPTO_free!(self.0.as_ptr() as *mut c_void); } } } @@ -50,8 +62,8 @@ impl Deref for SslString { } impl SslString { - unsafe fn new(buf: *const c_char, len: c_int) -> SslString { - let slice = slice::from_raw_parts(buf as *const _, len as usize); + unsafe fn new(buf: *const u8, len: c_int) -> SslString { + let slice = slice::from_raw_parts(buf, len as usize); SslString(str::from_utf8_unchecked(slice)) } } @@ -311,11 +323,11 @@ impl X509Generator { let not_before = try!(Asn1Time::days_from_now(0)); let not_after = try!(Asn1Time::days_from_now(self.days)); - try_ssl!(ffi::X509_set_notBefore(x509.as_ptr(), not_before.as_ptr() as *const _)); + try_ssl!(X509_set_notBefore(x509.as_ptr(), not_before.as_ptr() as *const _)); // If prev line succeded - ownership should go to cert mem::forget(not_before); - try_ssl!(ffi::X509_set_notAfter(x509.as_ptr(), not_after.as_ptr() as *const _)); + try_ssl!(X509_set_notAfter(x509.as_ptr(), not_after.as_ptr() as *const _)); // If prev line succeded - ownership should go to cert mem::forget(not_after); @@ -350,9 +362,6 @@ impl X509Generator { } /// Obtain a certificate signing request (CSR) - /// - /// Requries the `x509_generator_request` feature. - #[cfg(feature = "x509_generator_request")] pub fn request(&self, p_key: &PKey) -> Result<X509Req, ErrorStack> { let cert = match self.sign(p_key) { Ok(c) => c, @@ -363,9 +372,9 @@ impl X509Generator { let req = ffi::X509_to_X509_REQ(cert.as_ptr(), ptr::null_mut(), ptr::null()); try_ssl_null!(req); - let exts = ::c_helpers::rust_0_8_X509_get_extensions(cert.as_ptr()); + let exts = compat::X509_get0_extensions(cert.as_ptr()); if exts != ptr::null_mut() { - try_ssl!(ffi::X509_REQ_add_extensions(req, exts)); + try_ssl!(ffi::X509_REQ_add_extensions(req, exts as *mut _)); } let hash_fn = self.hash_type.evp_md(); @@ -438,22 +447,18 @@ impl<'a> X509Ref<'a> { } /// Returns certificate Not After validity period. - /// Requires the `x509_expiry` feature. - #[cfg(feature = "x509_expiry")] pub fn not_after<'b>(&'b self) -> Asn1TimeRef<'b> { unsafe { - let date = ::c_helpers::rust_0_8_X509_get_notAfter(self.0); + let date = compat::X509_get_notAfter(self.0); assert!(!date.is_null()); Asn1TimeRef::from_ptr(date) } } /// Returns certificate Not Before validity period. - /// Requires the `x509_expiry` feature. - #[cfg(feature = "x509_expiry")] pub fn not_before<'b>(&'b self) -> Asn1TimeRef<'b> { unsafe { - let date = ::c_helpers::rust_0_8_X509_get_notBefore(self.0); + let date = compat::X509_get_notBefore(self.0); assert!(!date.is_null()); Asn1TimeRef::from_ptr(date) } @@ -496,7 +501,7 @@ impl X509 { /// Reads a certificate from DER. pub fn from_der(buf: &[u8]) -> Result<X509, ErrorStack> { unsafe { - let mut ptr = buf.as_ptr() as *mut _; + let mut ptr = buf.as_ptr(); let len = cmp::min(buf.len(), c_long::max_value() as usize) as c_long; let x509 = try_ssl_null!(ffi::d2i_X509(ptr::null_mut(), &mut ptr, len)); Ok(X509::from_ptr(x509)) @@ -524,13 +529,11 @@ impl Deref for X509 { } } -#[cfg(feature = "x509_clone")] impl Clone for X509 { - /// Requires the `x509_clone` feature. fn clone(&self) -> X509 { unsafe { - ::c_helpers::rust_0_8_X509_clone(self.as_ptr()); - X509::new(self.as_ptr()) + compat::X509_up_ref(self.as_ptr()); + X509::from_ptr(self.as_ptr()) } } } @@ -561,7 +564,7 @@ impl<'x> X509Name<'x> { return None; } - let mut str_from_asn1: *mut c_char = ptr::null_mut(); + let mut str_from_asn1: *mut u8 = ptr::null_mut(); let len = ffi::ASN1_STRING_to_UTF8(&mut str_from_asn1, asn1_str); if len < 0 { @@ -779,22 +782,43 @@ pub struct GeneralNames<'a> { } impl<'a> Drop for GeneralNames<'a> { + #[cfg(ossl10x)] fn drop(&mut self) { unsafe { // This transmute is dubious but it's what openssl itself does... - let free: unsafe extern "C" fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free; - let free: unsafe extern "C" fn(*mut c_void) = mem::transmute(free); + let free: unsafe extern fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free; + let free: unsafe extern fn(*mut c_void) = mem::transmute(free); ffi::sk_pop_free(&mut (*self.stack).stack, Some(free)); } } + + #[cfg(ossl110)] + fn drop(&mut self) { + unsafe { + // This transmute is dubious but it's what openssl itself does... + let free: unsafe extern fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free; + let free: unsafe extern fn(*mut c_void) = mem::transmute(free); + ffi::OPENSSL_sk_pop_free(self.stack as *mut _, Some(free)); + } + } } impl<'a> GeneralNames<'a> { /// Returns the number of `GeneralName`s in this structure. pub fn len(&self) -> usize { + self._len() + } + + #[cfg(ossl10x)] + fn _len(&self) -> usize { unsafe { (*self.stack).stack.num as usize } } + #[cfg(ossl110)] + fn _len(&self) -> usize { + unsafe { ffi::OPENSSL_sk_num(self.stack as *const _) as usize } + } + /// Returns the specified `GeneralName`. /// /// # Panics @@ -803,14 +827,23 @@ impl<'a> GeneralNames<'a> { pub fn get(&self, idx: usize) -> GeneralName<'a> { unsafe { assert!(idx < self.len()); - GeneralName { - name: *(*self.stack).stack.data.offset(idx as isize) as *const ffi::GENERAL_NAME, + name: self._get(idx), m: PhantomData, } } } + #[cfg(ossl10x)] + unsafe fn _get(&self, idx: usize) -> *const ffi::GENERAL_NAME { + *(*self.stack).stack.data.offset(idx as isize) as *const ffi::GENERAL_NAME + } + + #[cfg(ossl110)] + unsafe fn _get(&self, idx: usize) -> *const ffi::GENERAL_NAME { + ffi::OPENSSL_sk_value(self.stack as *const _, idx as c_int) as *mut _ + } + /// Returns an iterator over the `GeneralName`s in this structure. pub fn iter(&self) -> GeneralNamesIter { GeneralNamesIter { @@ -870,7 +903,7 @@ impl<'a> GeneralName<'a> { return None; } - let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _); + let ptr = ASN1_STRING_data((*self.name).d as *mut _); let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); let slice = slice::from_raw_parts(ptr as *const u8, len as usize); @@ -888,7 +921,7 @@ impl<'a> GeneralName<'a> { return None; } - let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _); + let ptr = ASN1_STRING_data((*self.name).d as *mut _); let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); Some(slice::from_raw_parts(ptr as *const u8, len as usize)) @@ -904,3 +937,44 @@ fn test_negative_serial() { "All serials should be positive"); } } + +#[cfg(ossl110)] +mod compat { + pub use ffi::X509_getm_notAfter as X509_get_notAfter; + pub use ffi::X509_getm_notBefore as X509_get_notBefore; + pub use ffi::X509_up_ref; + pub use ffi::X509_get0_extensions; +} + +#[cfg(ossl10x)] +#[allow(bad_style)] +mod compat { + use libc::c_int; + use ffi; + + pub unsafe fn X509_get_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME { + (*(*(*x).cert_info).validity).notAfter + } + + pub unsafe fn X509_get_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME { + (*(*(*x).cert_info).validity).notBefore + } + + pub unsafe fn X509_up_ref(x: *mut ffi::X509) { + ffi::CRYPTO_add_lock(&mut (*x).references, + 1, + ffi::CRYPTO_LOCK_X509, + "mod.rs\0".as_ptr() as *const _, + line!() as c_int); + } + + pub unsafe fn X509_get0_extensions(cert: *const ffi::X509) + -> *const ffi::stack_st_X509_EXTENSION { + let info = (*cert).cert_info; + if info.is_null() { + 0 as *mut _ + } else { + (*info).extensions + } + } +} diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index eac08941..07d9e1d4 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -69,7 +69,6 @@ fn test_cert_gen_extension_bad_ordering() { } #[test] -#[cfg(feature = "x509_generator_request")] fn test_req_gen() { let pkey = pkey(); @@ -93,7 +92,6 @@ fn test_cert_loading() { } #[test] -#[cfg(feature = "x509_expiry")] fn test_cert_issue_validity() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); |