Commit e5123d26 authored by Steven Fackler's avatar Steven Fackler
Browse files

Bind remove and get session callbacks

parent 4dffa0c3
Loading
Loading
Loading
Loading
+49 −1
Original line number Diff line number Diff line
@@ -12,7 +12,8 @@ use dh::Dh;
#[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))]
use ec::EcKey;
use pkey::Params;
use ssl::{get_callback_idx, get_ssl_callback_idx, SniError, SslAlert, SslRef, SslSession};
use ssl::{get_callback_idx, get_ssl_callback_idx, SniError, SslAlert, SslContextRef, SslRef,
          SslSession, SslSessionRef};
#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110),
          all(feature = "v111", ossl111)))]
use ssl::AlpnError;
@@ -295,3 +296,50 @@ where
    // the return code doesn't indicate error vs success, but whether or not we consumed the session
    1
}

pub unsafe extern "C" fn raw_remove_session<F>(
    ctx: *mut ffi::SSL_CTX,
    session: *mut ffi::SSL_SESSION,
) where
    F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
{
    let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>());
    let callback = &*(callback as *mut F);

    let ctx = SslContextRef::from_ptr(ctx);
    let session = SslSessionRef::from_ptr(session);

    callback(ctx, session)
}

#[cfg(any(ossl110, ossl111))]
type DataPtr = *const c_uchar;
#[cfg(not(any(ossl110, ossl111)))]
type DataPtr = *mut c_uchar;

pub unsafe extern "C" fn raw_get_session<F>(
    ssl: *mut ffi::SSL,
    data: DataPtr,
    len: c_int,
    copy: *mut c_int,
) -> *mut ffi::SSL_SESSION
where
    F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
{
    let ctx = ffi::SSL_get_SSL_CTX(ssl as *const _);
    let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>());
    let callback = &*(callback as *mut F);

    let ssl = SslRef::from_ptr_mut(ssl);
    let data = slice::from_raw_parts(data as *const u8, len as usize);

    match callback(ssl, data) {
        Some(session) => {
            let p = session.as_ptr();
            mem::forget(p);
            *copy = 0;
            p
        }
        None => ptr::null_mut(),
    }
}
+52 −0
Original line number Diff line number Diff line
@@ -1195,6 +1195,58 @@ impl SslContextBuilder {
        }
    }

    /// Sets the callback which is called when sessions are removed from the context.
    ///
    /// Sessions can be removed because they have timed out or because they are considered faulty.
    ///
    /// This corresponds to [`SSL_CTX_sess_set_remove_cb`].
    ///
    /// [`SSL_CTX_sess_set_remove_cb`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_sess_set_new_cb.html
    pub fn set_remove_session_callback<F>(&mut self, callback: F)
    where
        F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
    {
        unsafe {
            let callback = Box::new(callback);
            ffi::SSL_CTX_set_ex_data(
                self.as_ptr(),
                get_callback_idx::<F>(),
                Box::into_raw(callback) as *mut _,
            );
            ffi::SSL_CTX_sess_set_remove_cb(
                self.as_ptr(),
                Some(callbacks::raw_remove_session::<F>),
            );
        }
    }

    /// Sets the callback which is called when a client proposed to resume a session but it was not
    /// found in the internal cache.
    ///
    /// The callback is passed a reference to the session ID provided by the client. It should
    /// return the session corresponding to that ID if available. This is only used for servers, not
    /// clients.
    ///
    /// This corresponds to [`SSL_CTX_sess_set_get_cb`].
    ///
    /// # Safety
    ///
    /// The returned `SslSession` must not be associated with a different `SslContext`.
    ///
    /// [`SSL_CTX_sess_set_get_cb`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_sess_set_new_cb.html
    pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
    where
        F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
    {
        let callback = Box::new(callback);
        ffi::SSL_CTX_set_ex_data(
            self.as_ptr(),
            get_callback_idx::<F>(),
            Box::into_raw(callback) as *mut _,
        );
        ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
    }

    /// Sets the session caching mode use for connections made with the context.
    ///
    /// Returns the previous session caching mode.