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 ssl::AlpnError;
|
||||
use ssl::{ClientHello, SelectCertError};
|
||||
use ssl::{
|
||||
SniError, Ssl, SslAlert, SslContext, SslContextRef, SslRef, SslSession, SslSessionRef,
|
||||
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
|
||||
where
|
||||
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);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
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.
|
||||
///
|
||||
|
|
@ -1560,6 +1588,9 @@ pub struct CipherBits {
|
|||
pub algorithm: i32,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct ClientHello(ffi::SSL_CLIENT_HELLO);
|
||||
|
||||
/// Information about a 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());
|
||||
}
|
||||
|
||||
#[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]
|
||||
#[should_panic(expected = "blammo")]
|
||||
fn write_panic() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue