Introduce set_select_certificate_callback
This commit is contained in:
parent
8b6767094d
commit
9c5c7e3db5
|
|
@ -12,6 +12,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
use ssl::AlpnError;
|
use ssl::AlpnError;
|
||||||
|
use ssl::{ClientHello, SelectCertError};
|
||||||
use ssl::{
|
use ssl::{
|
||||||
SniError, Ssl, SslAlert, SslContext, SslContextRef, SslRef, SslSession, SslSessionRef,
|
SniError, Ssl, SslAlert, SslContext, SslContextRef, SslRef, SslSession, SslSessionRef,
|
||||||
SESSION_CTX_INDEX,
|
SESSION_CTX_INDEX,
|
||||||
|
|
@ -190,6 +191,25 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn raw_select_cert<F>(
|
||||||
|
client_hello: *const ffi::SSL_CLIENT_HELLO,
|
||||||
|
) -> ffi::ssl_select_cert_result_t
|
||||||
|
where
|
||||||
|
F: Fn(&ClientHello) -> Result<(), SelectCertError> + Sync + Send + 'static,
|
||||||
|
{
|
||||||
|
let ssl = SslRef::from_ptr_mut((*client_hello).ssl);
|
||||||
|
let client_hello = &*(client_hello as *const ClientHello);
|
||||||
|
let callback = ssl
|
||||||
|
.ssl_context()
|
||||||
|
.ex_data(SslContext::cached_ex_index::<F>())
|
||||||
|
.expect("BUG: select cert callback missing") as *const F;
|
||||||
|
|
||||||
|
match (*callback)(client_hello) {
|
||||||
|
Ok(()) => ffi::ssl_select_cert_result_t::ssl_select_cert_success,
|
||||||
|
Err(e) => e.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe extern "C" fn raw_tlsext_status<F>(ssl: *mut ffi::SSL, _: *mut c_void) -> c_int
|
pub unsafe extern "C" fn raw_tlsext_status<F>(ssl: *mut ffi::SSL, _: *mut c_void) -> c_int
|
||||||
where
|
where
|
||||||
F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
|
F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
|
||||||
|
|
|
||||||
|
|
@ -463,6 +463,15 @@ impl AlpnError {
|
||||||
pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
|
pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An error returned from a certificate selection callback.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub struct SelectCertError(ffi::ssl_select_cert_result_t);
|
||||||
|
|
||||||
|
impl SelectCertError {
|
||||||
|
/// A fatal error occured and the handshake should be terminated.
|
||||||
|
pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_error);
|
||||||
|
}
|
||||||
|
|
||||||
/// An SSL/TLS protocol version.
|
/// An SSL/TLS protocol version.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct SslVersion(u16);
|
pub struct SslVersion(u16);
|
||||||
|
|
@ -1084,6 +1093,25 @@ impl SslContextBuilder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Sets a callback that is called before most ClientHello processing and before the decision whether
|
||||||
|
/// to resume a session is made. The callback may inspect the ClientHello and configure the
|
||||||
|
/// connection.
|
||||||
|
///
|
||||||
|
/// This corresponds to [`SSL_CTX_set_select_certificate_cb`].
|
||||||
|
///
|
||||||
|
/// [`SSL_CTX_set_select_certificate_cb`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_select_certificate_cb.html
|
||||||
|
pub fn set_select_certificate_callback<F>(&mut self, callback: F)
|
||||||
|
where
|
||||||
|
F: Fn(&ClientHello) -> Result<(), SelectCertError> + Sync + Send + 'static,
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
|
||||||
|
ffi::SSL_CTX_set_select_certificate_cb(
|
||||||
|
self.as_ptr(),
|
||||||
|
Some(callbacks::raw_select_cert::<F>),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks for consistency between the private key and certificate.
|
/// Checks for consistency between the private key and certificate.
|
||||||
///
|
///
|
||||||
|
|
@ -1560,6 +1588,9 @@ pub struct CipherBits {
|
||||||
pub algorithm: i32,
|
pub algorithm: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct ClientHello(ffi::SSL_CLIENT_HELLO);
|
||||||
|
|
||||||
/// Information about a cipher.
|
/// Information about a cipher.
|
||||||
pub struct SslCipher(*mut ffi::SSL_CIPHER);
|
pub struct SslCipher(*mut ffi::SSL_CIPHER);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -480,6 +480,31 @@ fn test_alpn_server_unilateral() {
|
||||||
assert_eq!(None, s.ssl().selected_alpn_protocol());
|
assert_eq!(None, s.ssl().selected_alpn_protocol());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_select_cert_ok() {
|
||||||
|
let mut server = Server::builder();
|
||||||
|
server
|
||||||
|
.ctx()
|
||||||
|
.set_select_certificate_callback(|_client_hello| Ok(()));
|
||||||
|
let server = server.build();
|
||||||
|
|
||||||
|
let client = server.client();
|
||||||
|
client.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_select_cert_error() {
|
||||||
|
let mut server = Server::builder();
|
||||||
|
server.should_error();
|
||||||
|
server
|
||||||
|
.ctx()
|
||||||
|
.set_select_certificate_callback(|_client_hello| Err(ssl::SelectCertError::ERROR));
|
||||||
|
let server = server.build();
|
||||||
|
|
||||||
|
let client = server.client();
|
||||||
|
client.connect_err();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "blammo")]
|
#[should_panic(expected = "blammo")]
|
||||||
fn write_panic() {
|
fn write_panic() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue