Support client CA advertisement
This commit is contained in:
parent
a4e0581e4f
commit
1edb6f682e
|
|
@ -1580,6 +1580,7 @@ extern {
|
||||||
pub fn SSL_get_privatekey(ssl: *mut SSL) -> *mut EVP_PKEY;
|
pub fn SSL_get_privatekey(ssl: *mut SSL) -> *mut EVP_PKEY;
|
||||||
#[cfg(not(ossl101))]
|
#[cfg(not(ossl101))]
|
||||||
pub fn SSL_get_privatekey(ssl: *const SSL) -> *mut EVP_PKEY;
|
pub fn SSL_get_privatekey(ssl: *const SSL) -> *mut EVP_PKEY;
|
||||||
|
pub fn SSL_load_client_CA_file(file: *const c_char) -> *mut stack_st_X509_NAME;
|
||||||
|
|
||||||
#[cfg(not(osslconf = "OPENSSL_NO_COMP"))]
|
#[cfg(not(osslconf = "OPENSSL_NO_COMP"))]
|
||||||
pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char;
|
pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char;
|
||||||
|
|
@ -1610,6 +1611,7 @@ extern {
|
||||||
pub fn SSL_CTX_use_PrivateKey_file(ctx: *mut SSL_CTX, key_file: *const c_char, file_type: c_int) -> c_int;
|
pub fn SSL_CTX_use_PrivateKey_file(ctx: *mut SSL_CTX, key_file: *const c_char, file_type: c_int) -> c_int;
|
||||||
pub fn SSL_CTX_use_PrivateKey(ctx: *mut SSL_CTX, key: *mut EVP_PKEY) -> c_int;
|
pub fn SSL_CTX_use_PrivateKey(ctx: *mut SSL_CTX, key: *mut EVP_PKEY) -> c_int;
|
||||||
pub fn SSL_CTX_check_private_key(ctx: *const SSL_CTX) -> c_int;
|
pub fn SSL_CTX_check_private_key(ctx: *const SSL_CTX) -> c_int;
|
||||||
|
pub fn SSL_CTX_set_client_CA_list(ctx: *mut SSL_CTX, list: *mut stack_st_X509_NAME);
|
||||||
|
|
||||||
#[cfg(not(ossl101))]
|
#[cfg(not(ossl101))]
|
||||||
pub fn SSL_CTX_get0_certificate(ctx: *const SSL_CTX) -> *mut X509;
|
pub fn SSL_CTX_get0_certificate(ctx: *const SSL_CTX) -> *mut X509;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@ pub struct stack_st_X509 {
|
||||||
pub stack: _STACK,
|
pub stack: _STACK,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct stack_st_X509_NAME {
|
||||||
|
pub stack: _STACK,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct stack_st_X509_ATTRIBUTE {
|
pub struct stack_st_X509_ATTRIBUTE {
|
||||||
pub stack: _STACK,
|
pub stack: _STACK,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ pub enum stack_st_GENERAL_NAME {}
|
||||||
pub enum stack_st_OPENSSL_STRING {}
|
pub enum stack_st_OPENSSL_STRING {}
|
||||||
pub enum stack_st_void {}
|
pub enum stack_st_void {}
|
||||||
pub enum stack_st_X509 {}
|
pub enum stack_st_X509 {}
|
||||||
|
pub enum stack_st_X509_NAME {}
|
||||||
pub enum stack_st_X509_ATTRIBUTE {}
|
pub enum stack_st_X509_ATTRIBUTE {}
|
||||||
pub enum stack_st_X509_EXTENSION {}
|
pub enum stack_st_X509_EXTENSION {}
|
||||||
pub enum X509 {}
|
pub enum X509 {}
|
||||||
|
|
|
||||||
|
|
@ -277,7 +277,6 @@ mod verify {
|
||||||
use nid;
|
use nid;
|
||||||
use x509::{X509StoreContextRef, X509Ref, X509NameRef, GeneralName};
|
use x509::{X509StoreContextRef, X509Ref, X509NameRef, GeneralName};
|
||||||
use stack::Stack;
|
use stack::Stack;
|
||||||
use types::OpenSslTypeRef;
|
|
||||||
|
|
||||||
pub fn verify_callback(domain: &str,
|
pub fn verify_callback(domain: &str,
|
||||||
preverify_ok: bool,
|
preverify_ok: bool,
|
||||||
|
|
|
||||||
|
|
@ -93,13 +93,14 @@ use std::sync::Mutex;
|
||||||
use {init, cvt, cvt_p};
|
use {init, cvt, cvt_p};
|
||||||
use dh::DhRef;
|
use dh::DhRef;
|
||||||
use ec_key::EcKeyRef;
|
use ec_key::EcKeyRef;
|
||||||
use x509::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError};
|
use x509::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError, X509Name};
|
||||||
#[cfg(any(ossl102, ossl110))]
|
#[cfg(any(ossl102, ossl110))]
|
||||||
use verify::X509VerifyParamRef;
|
use verify::X509VerifyParamRef;
|
||||||
use pkey::PKeyRef;
|
use pkey::PKeyRef;
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
use types::{OpenSslType, OpenSslTypeRef};
|
use types::{OpenSslType, OpenSslTypeRef};
|
||||||
use util::Opaque;
|
use util::Opaque;
|
||||||
|
use stack::Stack;
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod connector;
|
mod connector;
|
||||||
|
|
@ -542,6 +543,16 @@ impl SslContextBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the list of CAs sent to the client.
|
||||||
|
///
|
||||||
|
/// The CA certificates must still be added to the trust root.
|
||||||
|
pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
|
||||||
|
unsafe {
|
||||||
|
ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
|
||||||
|
mem::forget(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the context identifier for sessions
|
/// Set the context identifier for sessions
|
||||||
///
|
///
|
||||||
/// This value identifies the server's session cache to a clients, telling them when they're
|
/// This value identifies the server's session cache to a clients, telling them when they're
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ use ssl::SSL_VERIFY_PEER;
|
||||||
use ssl::{SslMethod, HandshakeError};
|
use ssl::{SslMethod, HandshakeError};
|
||||||
use ssl::{SslContext, SslStream, Ssl, ShutdownResult, SslConnectorBuilder, SslAcceptorBuilder,
|
use ssl::{SslContext, SslStream, Ssl, ShutdownResult, SslConnectorBuilder, SslAcceptorBuilder,
|
||||||
Error};
|
Error};
|
||||||
use x509::{X509StoreContext, X509, X509_FILETYPE_PEM};
|
use x509::{X509StoreContext, X509, X509Name, X509_FILETYPE_PEM};
|
||||||
#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
|
#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
|
||||||
use x509::verify::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS;
|
use x509::verify::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS;
|
||||||
use pkey::PKey;
|
use pkey::PKey;
|
||||||
|
|
@ -1184,6 +1184,15 @@ fn shutdown() {
|
||||||
assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received);
|
assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn client_ca_list() {
|
||||||
|
let names = X509Name::load_client_ca_file("test/root-ca.pem").unwrap();
|
||||||
|
assert_eq!(names.len(), 1);
|
||||||
|
|
||||||
|
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||||
|
ctx.set_client_ca_list(names);
|
||||||
|
}
|
||||||
|
|
||||||
fn _check_kinds() {
|
fn _check_kinds() {
|
||||||
fn is_send<T: Send>() {}
|
fn is_send<T: Send>() {}
|
||||||
fn is_sync<T: Sync>() {}
|
fn is_sync<T: Sync>() {}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use std::error::Error;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::path::Path;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
@ -498,6 +499,22 @@ impl Stackable for X509 {
|
||||||
|
|
||||||
type_!(X509Name, X509NameRef, ffi::X509_NAME, ffi::X509_NAME_free);
|
type_!(X509Name, X509NameRef, ffi::X509_NAME, ffi::X509_NAME_free);
|
||||||
|
|
||||||
|
impl X509Name {
|
||||||
|
/// Loads subject names from a file containing PEM-formatted certificates.
|
||||||
|
///
|
||||||
|
/// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`.
|
||||||
|
pub fn load_client_ca_file<P: AsRef<Path>>(file: P) -> Result<Stack<X509Name>, ErrorStack> {
|
||||||
|
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
|
||||||
|
unsafe {
|
||||||
|
cvt_p(ffi::SSL_load_client_CA_file(file.as_ptr())).map(|p| Stack::from_ptr(p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stackable for X509Name {
|
||||||
|
type StackType = ffi::stack_st_X509_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
impl X509NameRef {
|
impl X509NameRef {
|
||||||
pub fn entries_by_nid<'a>(&'a self, nid: Nid) -> X509NameEntries<'a> {
|
pub fn entries_by_nid<'a>(&'a self, nid: Nid) -> X509NameEntries<'a> {
|
||||||
X509NameEntries {
|
X509NameEntries {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue