From cd7fa9fca29296adebe37dfc20d3cebc96010534 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 31 Oct 2016 20:54:34 -0700 Subject: [PATCH] Update x509 --- openssl-sys/src/lib.rs | 4 +- openssl/src/ssl/connector.rs | 23 +++--- openssl/src/ssl/mod.rs | 16 ++--- openssl/src/ssl/tests/mod.rs | 23 +----- openssl/src/x509/mod.rs | 135 ++++++++++------------------------- 5 files changed, 62 insertions(+), 139 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 7f92f3a3..ae423099 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1658,12 +1658,14 @@ extern { pub fn X509_EXTENSION_free(ext: *mut X509_EXTENSION); + pub fn X509_NAME_free(x: *mut X509_NAME); pub fn X509_NAME_add_entry_by_txt(x: *mut X509_NAME, field: *const c_char, ty: c_int, bytes: *const c_uchar, len: c_int, loc: c_int, set: c_int) -> c_int; pub fn X509_NAME_get_index_by_NID(n: *mut X509_NAME, nid: c_int, last_pos: c_int) ->c_int; pub fn ASN1_STRING_length(x: *const ASN1_STRING) -> c_int; - pub fn X509_STORE_CTX_get_current_cert(ct: *mut X509_STORE_CTX) -> *mut X509; + pub fn X509_STORE_CTX_free(ctx: *mut X509_STORE_CTX); + pub fn X509_STORE_CTX_get_current_cert(ctx: *mut X509_STORE_CTX) -> *mut X509; pub fn X509_STORE_CTX_get_error(ctx: *mut X509_STORE_CTX) -> c_int; pub fn X509_STORE_CTX_get_ex_data(ctx: *mut X509_STORE_CTX, idx: c_int) -> *mut c_void; pub fn X509_STORE_CTX_get_error_depth(ctx: *mut X509_STORE_CTX) -> c_int; diff --git a/openssl/src/ssl/connector.rs b/openssl/src/ssl/connector.rs index 752126e0..a1bcfa77 100644 --- a/openssl/src/ssl/connector.rs +++ b/openssl/src/ssl/connector.rs @@ -5,7 +5,7 @@ use error::ErrorStack; use ssl::{self, SslMethod, SslContextBuilder, SslContext, Ssl, SSL_VERIFY_PEER, SslStream, HandshakeError}; use pkey::PKey; -use x509::X509Ref; +use x509::X509; use types::Ref; // apps/dh2048.pem @@ -118,11 +118,11 @@ impl SslAcceptorBuilder { /// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS pub fn mozilla_intermediate(method: SslMethod, private_key: &Ref, - certificate: &X509Ref, + certificate: &Ref, chain: I) -> Result where I: IntoIterator, - I::Item: AsRef + I::Item: AsRef> { let mut ctx = try!(ctx(method)); let dh = try!(Dh::from_pem(DHPARAM_PEM.as_bytes())); @@ -153,11 +153,11 @@ impl SslAcceptorBuilder { /// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS pub fn mozilla_modern(method: SslMethod, private_key: &Ref, - certificate: &X509Ref, + certificate: &Ref, chain: I) -> Result where I: IntoIterator, - I::Item: AsRef + I::Item: AsRef> { let mut ctx = try!(ctx(method)); try!(setup_curves(&mut ctx)); @@ -171,11 +171,11 @@ impl SslAcceptorBuilder { fn finish_setup(mut ctx: SslContextBuilder, private_key: &Ref, - certificate: &X509Ref, + certificate: &Ref, chain: I) -> Result where I: IntoIterator, - I::Item: AsRef + I::Item: AsRef> { try!(ctx.set_private_key(private_key)); try!(ctx.set_certificate(certificate)); @@ -255,11 +255,12 @@ mod verify { use std::net::IpAddr; use nid; - use x509::{X509StoreContextRef, X509Ref, GeneralNames, X509NameRef}; + use x509::{X509StoreContext, X509, GeneralNames, X509Name}; + use types::Ref; pub fn verify_callback(domain: &str, preverify_ok: bool, - x509_ctx: &X509StoreContextRef) + x509_ctx: &Ref) -> bool { if !preverify_ok || x509_ctx.error_depth() != 0 { return preverify_ok; @@ -271,7 +272,7 @@ mod verify { } } - fn verify_hostname(domain: &str, cert: &X509Ref) -> bool { + fn verify_hostname(domain: &str, cert: &Ref) -> bool { match cert.subject_alt_names() { Some(names) => verify_subject_alt_names(domain, &names), None => verify_subject_name(domain, &cert.subject_name()), @@ -303,7 +304,7 @@ mod verify { false } - fn verify_subject_name(domain: &str, subject_name: &X509NameRef) -> bool { + fn verify_subject_name(domain: &str, subject_name: &Ref) -> bool { if let Some(pattern) = subject_name.text_by_nid(nid::COMMONNAME) { // Unlike with SANs, IP addresses in the subject name don't have a // different encoding. We need to pass this down to matches_dns to diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 42c38980..68d411c7 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -92,7 +92,7 @@ use ffi; use {init, cvt, cvt_p}; use dh::Dh; use ec_key::EcKey; -use x509::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError}; +use x509::{X509StoreContext, X509FileType, X509, X509VerifyError}; #[cfg(any(ossl102, ossl110))] use verify::X509VerifyParam; use pkey::PKey; @@ -262,7 +262,7 @@ fn get_new_ssl_idx() -> c_int { } extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int - where F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send + where F: Fn(bool, &Ref) -> bool + Any + 'static + Sync + Send { unsafe { let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); @@ -271,14 +271,14 @@ extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_ let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); let verify: &F = &*(verify as *mut F); - let ctx = X509StoreContextRef::from_ptr(x509_ctx); + let ctx = Ref::from_ptr(x509_ctx); verify(preverify_ok != 0, ctx) as 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, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send + where F: Fn(bool, &Ref) -> bool + Any + 'static + Sync + Send { unsafe { let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); @@ -286,7 +286,7 @@ extern "C" fn ssl_raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_ST let verify = ffi::SSL_get_ex_data(ssl as *const _, get_ssl_verify_data_idx::()); let verify: &F = &*(verify as *mut F); - let ctx = X509StoreContextRef::from_ptr(x509_ctx); + let ctx = Ref::from_ptr(x509_ctx); verify(preverify_ok != 0, ctx) as c_int } @@ -463,7 +463,7 @@ impl SslContextBuilder { /// Configures the certificate verification method for new connections and /// registers a verification callback. pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) - where F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send + where F: Fn(bool, &Ref) -> bool + Any + 'static + Sync + Send { unsafe { let verify = Box::new(verify); @@ -584,7 +584,7 @@ impl SslContextBuilder { } /// Specifies the certificate - pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { + pub fn set_certificate(&mut self, cert: &Ref) -> Result<(), ErrorStack> { unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) } } @@ -874,7 +874,7 @@ impl Ref { /// to the certificate chain. It should return `true` if the certificate /// chain is valid and `false` otherwise. pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) - where F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send + where F: Fn(bool, &Ref) -> bool + Any + 'static + Sync + Send { unsafe { let verify = Box::new(verify); diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index a874fe3b..13b3a8a7 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -20,7 +20,7 @@ use ssl::SSL_VERIFY_PEER; use ssl::{SslMethod, HandshakeError}; use ssl::{SslContext, SslStream, Ssl, ShutdownResult, SslConnectorBuilder, SslAcceptorBuilder, Error}; -use x509::X509StoreContextRef; +use x509::X509StoreContext; use x509::X509FileType; use x509::X509; #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] @@ -171,8 +171,9 @@ macro_rules! run_test( use ssl::{SslContext, Ssl, SslStream}; use ssl::SSL_VERIFY_PEER; use hash::MessageDigest; - use x509::X509StoreContextRef; + use x509::X509StoreContext; use serialize::hex::FromHex; + use types::Ref; use super::Server; #[test] @@ -771,24 +772,6 @@ fn test_alpn_server_select_none() { assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_err()); } -#[cfg(test)] -mod dtlsv1 { - use serialize::hex::FromHex; - use std::net::TcpStream; - use std::thread; - - use hash::MessageDigest; - use ssl::SslMethod; - use ssl::{SslContext, SslStream}; - use ssl::SSL_VERIFY_PEER; - use x509::X509StoreContextRef; - - #[test] - fn test_new_ctx() { - SslContext::builder(SslMethod::dtls()).unwrap(); - } -} - #[test] #[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_read_dtlsv1() { diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index d3f7fbc0..bb2c7544 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -7,7 +7,6 @@ use std::ffi::{CStr, CString}; use std::fmt; use std::marker::PhantomData; use std::mem; -use std::ops::Deref; use std::ptr; use std::slice; use std::str; @@ -22,7 +21,6 @@ use rand::rand_bytes; use error::ErrorStack; use ffi; use nid::Nid; -use opaque::Opaque; use types::{OpenSslType, Ref}; #[cfg(ossl10x)] @@ -49,28 +47,20 @@ pub enum X509FileType { Default = ffi::X509_FILETYPE_DEFAULT, } -pub struct X509StoreContextRef(Opaque); - -impl X509StoreContextRef { - pub unsafe fn from_ptr<'a>(ctx: *mut ffi::X509_STORE_CTX) -> &'a X509StoreContextRef { - &*(ctx as *mut _) - } - - pub fn as_ptr(&self) -> *mut ffi::X509_STORE_CTX { - self as *const _ as *mut _ - } +type_!(X509StoreContext, ffi::X509_STORE_CTX, ffi::X509_STORE_CTX_free); +impl Ref { pub fn error(&self) -> Option { unsafe { X509VerifyError::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr()) as c_long) } } - pub fn current_cert(&self) -> Option<&X509Ref> { + pub fn current_cert(&self) -> Option<&Ref> { unsafe { let ptr = ffi::X509_STORE_CTX_get_current_cert(self.as_ptr()); if ptr.is_null() { None } else { - Some(X509Ref::from_ptr(ptr)) + Some(Ref::from_ptr(ptr)) } } } @@ -346,23 +336,13 @@ impl X509Generator { } } -/// A borrowed public key certificate. -pub struct X509Ref(Opaque); +type_!(X509, ffi::X509, ffi::X509_free); -impl X509Ref { - /// Creates a new `X509Ref` wrapping the provided handle. - pub unsafe fn from_ptr<'a>(x509: *mut ffi::X509) -> &'a X509Ref { - &*(x509 as *mut _) - } - - pub fn as_ptr(&self) -> *mut ffi::X509 { - self as *const _ as *mut _ - } - - pub fn subject_name(&self) -> &X509NameRef { +impl Ref { + pub fn subject_name(&self) -> &Ref { unsafe { let name = ffi::X509_get_subject_name(self.as_ptr()); - X509NameRef::from_ptr(name) + Ref::from_ptr(name) } } @@ -437,7 +417,7 @@ impl X509Ref { } } -impl ToOwned for X509Ref { +impl ToOwned for Ref { type Owned = X509; fn to_owned(&self) -> X509 { @@ -448,15 +428,7 @@ impl ToOwned for X509Ref { } } -/// An owned public key certificate. -pub struct X509(*mut ffi::X509); - impl X509 { - /// Returns a new `X509`, taking ownership of the handle. - pub unsafe fn from_ptr(x509: *mut ffi::X509) -> X509 { - X509(x509) - } - /// Reads a certificate from DER. pub fn from_der(buf: &[u8]) -> Result { unsafe { @@ -480,49 +452,27 @@ impl X509 { } } -impl Deref for X509 { - type Target = X509Ref; - - fn deref(&self) -> &X509Ref { - unsafe { X509Ref::from_ptr(self.0) } - } -} - impl Clone for X509 { fn clone(&self) -> X509 { self.to_owned() } } -impl Drop for X509 { - fn drop(&mut self) { - unsafe { ffi::X509_free(self.as_ptr()) }; - } -} - -impl AsRef for X509 { - fn as_ref(&self) -> &X509Ref { +impl AsRef> for X509 { + fn as_ref(&self) -> &Ref { &*self } } -impl Borrow for X509 { - fn borrow(&self) -> &X509Ref { +impl Borrow> for X509 { + fn borrow(&self) -> &Ref { &*self } } -pub struct X509NameRef(Opaque); - -impl X509NameRef { - pub unsafe fn from_ptr<'a>(ptr: *mut ffi::X509_NAME) -> &'a X509NameRef { - &*(ptr as *mut _) - } - - pub fn as_ptr(&self) -> *mut ffi::X509_NAME { - self as *const _ as *mut _ - } +type_!(X509Name, ffi::X509_NAME, ffi::X509_NAME_free); +impl Ref { pub fn text_by_nid(&self, nid: Nid) -> Option { unsafe { let loc = ffi::X509_NAME_get_index_by_NID(self.as_ptr(), nid.as_raw(), -1); @@ -554,18 +504,29 @@ impl X509NameRef { } } -/// A certificate signing request -pub struct X509Req(*mut ffi::X509_REQ); +type_!(X509Req, ffi::X509_REQ, ffi::X509_REQ_free); + +impl Ref { + /// Writes CSR as PEM + pub fn to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.as_ptr(), self.as_ptr()) } != 1 { + return Err(ErrorStack::get()); + } + Ok(mem_bio.get_buf().to_owned()) + } + + /// Returns a DER serialized form of the CSR + pub fn to_der(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + unsafe { + ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.as_ptr()); + } + Ok(mem_bio.get_buf().to_owned()) + } +} impl X509Req { - pub unsafe fn from_ptr(handle: *mut ffi::X509_REQ) -> X509Req { - X509Req(handle) - } - - pub fn as_ptr(&self) -> *mut ffi::X509_REQ { - self.0 - } - /// Reads CSR from PEM pub fn from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); @@ -577,30 +538,6 @@ impl X509Req { Ok(X509Req::from_ptr(handle)) } } - - /// Writes CSR as PEM - pub fn to_pem(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.as_ptr(), self.0) } != 1 { - return Err(ErrorStack::get()); - } - Ok(mem_bio.get_buf().to_owned()) - } - - /// Returns a DER serialized form of the CSR - pub fn to_der(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { - ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.0); - } - Ok(mem_bio.get_buf().to_owned()) - } -} - -impl Drop for X509Req { - fn drop(&mut self) { - unsafe { ffi::X509_REQ_free(self.0) }; - } } /// A collection of X.509 extensions.