Clean up SNI APIs
This commit is contained in:
parent
61f65cd8d6
commit
f09ca6fee2
|
|
@ -44,22 +44,11 @@ extern "C" {
|
||||||
fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX);
|
fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut SNI_IDX: c_int = -1;
|
|
||||||
|
|
||||||
/// Manually initialize SSL.
|
/// Manually initialize SSL.
|
||||||
/// It is optional to call this function and safe to do so more than once.
|
/// It is optional to call this function and safe to do so more than once.
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
static mut INIT: Once = ONCE_INIT;
|
static mut INIT: Once = ONCE_INIT;
|
||||||
|
unsafe { INIT.call_once(|| ffi::init()); }
|
||||||
unsafe {
|
|
||||||
INIT.call_once(|| {
|
|
||||||
ffi::init();
|
|
||||||
|
|
||||||
let sni_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None);
|
|
||||||
assert!(sni_idx >= 0);
|
|
||||||
SNI_IDX = sni_idx;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
|
@ -317,49 +306,30 @@ extern "C" fn ssl_raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_ST
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn raw_sni(ssl: *mut ffi::SSL, ad: &mut c_int, _arg: *mut c_void) -> c_int {
|
extern "C" fn raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c_int
|
||||||
unsafe {
|
where F: Fn(&mut Ssl) -> Result<(), SniError> + Any + 'static + Sync + Send
|
||||||
let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl);
|
|
||||||
let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX);
|
|
||||||
let callback: Option<ServerNameCallback> = mem::transmute(callback);
|
|
||||||
rust_SSL_clone(ssl);
|
|
||||||
let mut s = Ssl { ssl: ssl };
|
|
||||||
|
|
||||||
let res = match callback {
|
|
||||||
None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL,
|
|
||||||
Some(callback) => callback(&mut s, ad),
|
|
||||||
};
|
|
||||||
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn raw_sni_with_data<T>(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_void) -> c_int
|
|
||||||
where T: Any + 'static
|
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl);
|
let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl);
|
||||||
|
let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::<F>());
|
||||||
let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX);
|
let callback: &F = mem::transmute(callback);
|
||||||
let callback: Option<ServerNameCallbackData<T>> = mem::transmute(callback);
|
|
||||||
rust_SSL_clone(ssl);
|
rust_SSL_clone(ssl);
|
||||||
let mut s = Ssl { ssl: ssl };
|
let mut ssl = Ssl { ssl: ssl };
|
||||||
|
|
||||||
let data: &T = mem::transmute(arg);
|
match callback(&mut ssl) {
|
||||||
|
Ok(()) => ffi::SSL_TLSEXT_ERR_OK,
|
||||||
let res = match callback {
|
Err(SniError::Fatal(e)) => {
|
||||||
None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL,
|
*al = e;
|
||||||
Some(callback) => callback(&mut s, ad, &*data),
|
ffi::SSL_TLSEXT_ERR_ALERT_FATAL
|
||||||
};
|
}
|
||||||
|
Err(SniError::Warning(e)) => {
|
||||||
// Since data might be required on the next verification
|
*al = e;
|
||||||
// it is time to forget about it and avoid dropping
|
ffi::SSL_TLSEXT_ERR_ALERT_WARNING
|
||||||
// data will be freed once OpenSSL considers it is time
|
}
|
||||||
// to free all context data
|
Err(SniError::NoAck) => ffi::SSL_TLSEXT_ERR_NOACK,
|
||||||
res
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(any(feature = "npn", feature = "alpn"))]
|
#[cfg(any(feature = "npn", feature = "alpn"))]
|
||||||
unsafe fn select_proto_using(ssl: *mut ffi::SSL,
|
unsafe fn select_proto_using(ssl: *mut ffi::SSL,
|
||||||
|
|
@ -465,10 +435,12 @@ fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec<u8> {
|
||||||
enc
|
enc
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The signature of functions that can be used to choose the context depending on the server name
|
/// An error returned from an SNI callback.
|
||||||
pub type ServerNameCallback = fn(ssl: &mut Ssl, ad: &mut i32) -> i32;
|
pub enum SniError {
|
||||||
|
Fatal(c_int),
|
||||||
pub type ServerNameCallbackData<T> = fn(ssl: &mut Ssl, ad: &mut i32, data: &T) -> i32;
|
Warning(c_int),
|
||||||
|
NoAck,
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: macro may be instead of inlining?
|
// FIXME: macro may be instead of inlining?
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -552,30 +524,15 @@ impl SslContext {
|
||||||
|
|
||||||
/// Configures the server name indication (SNI) callback for new connections
|
/// Configures the server name indication (SNI) callback for new connections
|
||||||
///
|
///
|
||||||
/// obtain the server name with `get_servername` then set the corresponding context
|
/// Obtain the server name with `servername` then set the corresponding context
|
||||||
/// with `set_ssl_context`
|
/// with `set_ssl_context`
|
||||||
pub fn set_servername_callback(&mut self, callback: Option<ServerNameCallback>) {
|
pub fn set_servername_callback<F>(&mut self, callback: F)
|
||||||
unsafe {
|
where F: Fn(&mut Ssl) -> Result<(), SniError> + Any + 'static + Sync + Send
|
||||||
ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(callback));
|
|
||||||
let f: extern "C" fn(_, _, _) -> _ = raw_sni;
|
|
||||||
let f: extern "C" fn() = mem::transmute(f);
|
|
||||||
ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Configures the server name indication (SNI) callback for new connections
|
|
||||||
/// carrying supplied data
|
|
||||||
pub fn set_servername_callback_with_data<T>(&mut self,
|
|
||||||
callback: ServerNameCallbackData<T>,
|
|
||||||
data: T)
|
|
||||||
where T: Any + 'static
|
|
||||||
{
|
{
|
||||||
let data = Box::new(data);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(Some(callback)));
|
let callback = Box::new(callback);
|
||||||
|
ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::<F>(), mem::transmute(callback));
|
||||||
ffi_extras::SSL_CTX_set_tlsext_servername_arg(self.ctx, mem::transmute(data));
|
let f: extern "C" fn(_, _, _) -> _ = raw_sni::<F>;
|
||||||
let f: extern "C" fn(_, _, _) -> _ = raw_sni_with_data::<T>;
|
|
||||||
let f: extern "C" fn() = mem::transmute(f);
|
let f: extern "C" fn() = mem::transmute(f);
|
||||||
ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f));
|
ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue