Commit cd7fa9fc authored by Steven Fackler's avatar Steven Fackler
Browse files

Update x509

parent ff12d37a
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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;
+12 −11
Original line number Diff line number Diff line
@@ -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<I>(method: SslMethod,
                                   private_key: &Ref<PKey>,
                                   certificate: &X509Ref,
                                   certificate: &Ref<X509>,
                                   chain: I)
                                   -> Result<SslAcceptorBuilder, ErrorStack>
        where I: IntoIterator,
              I::Item: AsRef<X509Ref>
              I::Item: AsRef<Ref<X509>>
    {
        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<I>(method: SslMethod,
                             private_key: &Ref<PKey>,
                             certificate: &X509Ref,
                             certificate: &Ref<X509>,
                             chain: I)
                             -> Result<SslAcceptorBuilder, ErrorStack>
        where I: IntoIterator,
              I::Item: AsRef<X509Ref>
              I::Item: AsRef<Ref<X509>>
    {
        let mut ctx = try!(ctx(method));
        try!(setup_curves(&mut ctx));
@@ -171,11 +171,11 @@ impl SslAcceptorBuilder {

    fn finish_setup<I>(mut ctx: SslContextBuilder,
                       private_key: &Ref<PKey>,
                       certificate: &X509Ref,
                       certificate: &Ref<X509>,
                       chain: I)
                       -> Result<SslAcceptorBuilder, ErrorStack>
        where I: IntoIterator,
              I::Item: AsRef<X509Ref>
              I::Item: AsRef<Ref<X509>>
    {
        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<X509StoreContext>)
                           -> 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<X509>) -> 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<X509Name>) -> 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
+8 −8
Original line number Diff line number Diff line
@@ -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<T>() -> c_int {
}

extern "C" fn raw_verify<F>(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<X509StoreContext>) -> 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<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_
        let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::<F>());
        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<F>(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<X509StoreContext>) -> 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<F>(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::<F>());
        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<F>(&mut self, mode: SslVerifyMode, verify: F)
        where F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send
        where F: Fn(bool, &Ref<X509StoreContext>) -> 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<X509>) -> Result<(), ErrorStack> {
        unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
    }

@@ -874,7 +874,7 @@ impl Ref<Ssl> {
    /// to the certificate chain. It should return `true` if the certificate
    /// chain is valid and `false` otherwise.
    pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
        where F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send
        where F: Fn(bool, &Ref<X509StoreContext>) -> bool + Any + 'static + Sync + Send
    {
        unsafe {
            let verify = Box::new(verify);
+3 −20
Original line number Diff line number Diff line
@@ -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() {
+30 −93
Original line number Diff line number Diff line
@@ -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<X509StoreContext> {
    pub fn error(&self) -> Option<X509VerifyError> {
        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<X509>> {
        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);

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 _
    }
type_!(X509, ffi::X509, ffi::X509_free);

    pub fn subject_name(&self) -> &X509NameRef {
impl Ref<X509> {
    pub fn subject_name(&self) -> &Ref<X509Name> {
        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<X509> {
    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<X509, ErrorStack> {
        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<X509Ref> for X509 {
    fn as_ref(&self) -> &X509Ref {
impl AsRef<Ref<X509>> for X509 {
    fn as_ref(&self) -> &Ref<X509> {
        &*self
    }
}

impl Borrow<X509Ref> for X509 {
    fn borrow(&self) -> &X509Ref {
impl Borrow<Ref<X509>> for X509 {
    fn borrow(&self) -> &Ref<X509> {
        &*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<X509Name> {
    pub fn text_by_nid(&self, nid: Nid) -> Option<CryptoString> {
        unsafe {
            let loc = ffi::X509_NAME_get_index_by_NID(self.as_ptr(), nid.as_raw(), -1);
@@ -554,34 +504,13 @@ impl X509NameRef {
    }
}

/// A certificate signing request
pub struct X509Req(*mut ffi::X509_REQ);

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<X509Req, ErrorStack> {
        let mem_bio = try!(MemBioSlice::new(buf));
        unsafe {
            let handle = try!(cvt_p(ffi::PEM_read_bio_X509_REQ(mem_bio.as_ptr(),
                                                               ptr::null_mut(),
                                                               None,
                                                               ptr::null_mut())));
            Ok(X509Req::from_ptr(handle))
        }
    }
type_!(X509Req, ffi::X509_REQ, ffi::X509_REQ_free);

impl Ref<X509Req> {
    /// Writes CSR as PEM
    pub fn to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
        let mem_bio = try!(MemBio::new());
        if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.as_ptr(), self.0) } != 1 {
        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())
@@ -591,15 +520,23 @@ impl X509Req {
    pub fn to_der(&self) -> Result<Vec<u8>, ErrorStack> {
        let mem_bio = try!(MemBio::new());
        unsafe {
            ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.0);
            ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.as_ptr());
        }
        Ok(mem_bio.get_buf().to_owned())
    }
}

impl Drop for X509Req {
    fn drop(&mut self) {
        unsafe { ffi::X509_REQ_free(self.0) };
impl X509Req {
    /// Reads CSR from PEM
    pub fn from_pem(buf: &[u8]) -> Result<X509Req, ErrorStack> {
        let mem_bio = try!(MemBioSlice::new(buf));
        unsafe {
            let handle = try!(cvt_p(ffi::PEM_read_bio_X509_REQ(mem_bio.as_ptr(),
                                                               ptr::null_mut(),
                                                               None,
                                                               ptr::null_mut())));
            Ok(X509Req::from_ptr(handle))
        }
    }
}