Update x509

This commit is contained in:
Steven Fackler 2016-10-31 20:54:34 -07:00
parent ff12d37aef
commit cd7fa9fca2
5 changed files with 62 additions and 139 deletions

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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() {

View File

@ -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);
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<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,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<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.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<Vec<u8>, 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<X509Req, ErrorStack> {
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<Vec<u8>, 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<Vec<u8>, 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.