Skip to content

Bug fixes and extensions in pursuit of haproxy support #90

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
| `SSL_CTX_set_client_CA_list` | | :white_check_mark: | :white_check_mark: | :exclamation: [^stub] |
| `SSL_CTX_set_client_cert_cb` | | | | :exclamation: [^stub] |
| `SSL_CTX_set_client_cert_engine` [^engine] | | | | |
| `SSL_CTX_set_client_hello_cb` | | | :white_check_mark: | :exclamation: [^stub] |
| `SSL_CTX_set_client_hello_cb` | | | :white_check_mark: | :white_check_mark: |
| `SSL_CTX_set_cookie_generate_cb` | | | | |
| `SSL_CTX_set_cookie_verify_cb` | | | | |
| `SSL_CTX_set_ct_validation_callback` [^ct] | | | | |
Expand All @@ -158,10 +158,10 @@
| `SSL_CTX_set_default_verify_store` | | | | :exclamation: [^stub] |
| `SSL_CTX_set_ex_data` | | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `SSL_CTX_set_generate_session_id` | | | | |
| `SSL_CTX_set_info_callback` | | :white_check_mark: | :white_check_mark: | :exclamation: [^stub] |
| `SSL_CTX_set_info_callback` | | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `SSL_CTX_set_keylog_callback` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :exclamation: [^stub] |
| `SSL_CTX_set_max_early_data` | | :white_check_mark: | | :white_check_mark: |
| `SSL_CTX_set_msg_callback` | :white_check_mark: | | :white_check_mark: | :exclamation: [^stub] |
| `SSL_CTX_set_msg_callback` | :white_check_mark: | | :white_check_mark: | :white_check_mark: |
| `SSL_CTX_set_next_proto_select_cb` [^nextprotoneg] | :white_check_mark: | | :white_check_mark: | :exclamation: [^stub] |
| `SSL_CTX_set_next_protos_advertised_cb` [^nextprotoneg] | | :white_check_mark: | :white_check_mark: | :exclamation: [^stub] |
| `SSL_CTX_set_not_resumable_session_callback` | | | | |
Expand Down Expand Up @@ -442,7 +442,7 @@
| `SSL_set_hostflags` | | | | |
| `SSL_set_info_callback` | | | | |
| `SSL_set_max_early_data` | | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `SSL_set_msg_callback` | | :white_check_mark: | :white_check_mark: | :exclamation: [^stub] |
| `SSL_set_msg_callback` | | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| `SSL_set_not_resumable_session_callback` | | | | |
| `SSL_set_num_tickets` | | | | :white_check_mark: |
| `SSL_set_options` | | :white_check_mark: | | :white_check_mark: |
Expand Down
88 changes: 85 additions & 3 deletions src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use openssl_sys::{SSL_TLSEXT_ERR_NOACK, SSL_TLSEXT_ERR_OK};
use rustls::AlertDescription;

use crate::entry::{
SSL_CTX_alpn_select_cb_func, SSL_CTX_cert_cb_func, SSL_CTX_new_session_cb,
SSL_CTX_servername_callback_func, SSL_CTX_sess_get_cb, SSL_CTX_sess_remove_cb,
_SSL_SESSION_free, SSL, SSL_CTX, SSL_SESSION,
SSL_CTX_alpn_select_cb_func, SSL_CTX_cert_cb_func, SSL_CTX_info_callback_func,
SSL_CTX_new_session_cb, SSL_CTX_servername_callback_func, SSL_CTX_sess_get_cb,
SSL_CTX_sess_remove_cb, SSL_client_hello_cb_func, _SSL_SESSION_free, SSL, SSL_CTX, SSL_SESSION,
};
use crate::error::Error;
use crate::ffi;
Expand Down Expand Up @@ -160,6 +160,9 @@ impl ServerNameCallbackConfig {

match result {
SSL_TLSEXT_ERR_OK => Ok(()),
// in practice no client does anything if SNI is not acked, and rustls
// acks any syntactically valid extension (and ignores invalid ones, because OpenSSL)
SSL_TLSEXT_ERR_NOACK => Ok(()),
_ => Err(Error::not_supported(
"SSL_CTX_servername_callback_func return error",
)),
Expand Down Expand Up @@ -237,3 +240,82 @@ pub fn invoke_session_remove_callback(

_SSL_SESSION_free(sess_ptr);
}

/// Configuration needed to call an [`SSL_CTX_info_callback_func`] later
#[derive(Debug, Default, Clone)]
pub struct InfoCallbackConfig {
pub cb: SSL_CTX_info_callback_func,
}

impl InfoCallbackConfig {
pub fn invoke(&self, info: Info) {
let Some(callback) = self.cb else {
return;
};

let ssl = SslCallbackContext::ssl_ptr();
unsafe { callback(ssl, info.typ(), info.val()) };
}
}

pub enum Info {
/// `SSL_CB_ALERT | SSL_CB_READ`
AlertReceived(AlertDescription),

/// `SSL_CB_ALERT | SSL_CB_WRITE`
AlertSent(AlertDescription),
}

impl Info {
fn typ(&self) -> c_int {
match self {
Self::AlertReceived(_) => SSL_CB_ALERT | SSL_CB_READ,
Self::AlertSent(_) => SSL_CB_ALERT | SSL_CB_WRITE,
}
}

fn val(&self) -> c_int {
match self {
Self::AlertReceived(a) | Self::AlertSent(a) => u8::from(*a) as c_int,
}
}
}

const SSL_CB_ALERT: c_int = 0x4000;
const SSL_CB_READ: c_int = 0x0004;
const SSL_CB_WRITE: c_int = 0x0008;

/// Configuration needed to call a client hello callback later
#[derive(Debug, Default, Clone)]
pub struct ClientHelloCallbackConfig {
pub cb: SSL_client_hello_cb_func,
pub context: *mut c_void,
}

impl ClientHelloCallbackConfig {
pub fn invoke(&self) -> Result<(), Error> {
let Some(callback) = self.cb else {
return Ok(());
};

let internal_error = u8::from(AlertDescription::InternalError) as c_int;

let ssl = SslCallbackContext::ssl_ptr();
let mut alert = internal_error;
let result = unsafe { callback(ssl, &mut alert as *mut c_int, self.context) };

if alert != internal_error {
log::trace!("NYI: customised alert during client hello callback");
}

match result {
i if i < 0 => Err(Error::not_supported(
"SSL_client_hello_cb_func requesting suspension",
)),
0 => Err(Error::not_supported(
"SSL_client_hello_cb_func returning error",
)),
_ => Ok(()),
}
}
}
108 changes: 63 additions & 45 deletions src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use std::{fs, path::PathBuf};
use openssl_sys::{
stack_st_SSL_CIPHER, stack_st_X509, stack_st_X509_NAME, stack_st_void, NID_undef,
OPENSSL_malloc, TLSEXT_NAMETYPE_host_name, BIGNUM, EVP_CIPHER_CTX, EVP_PKEY, HMAC_CTX,
OPENSSL_NPN_NEGOTIATED, OPENSSL_NPN_NO_OVERLAP, X509, X509_STORE, X509_STORE_CTX,
OPENSSL_NPN_NEGOTIATED, OPENSSL_NPN_NO_OVERLAP, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER,
SSL_MODE_AUTO_RETRY, SSL_MODE_ENABLE_PARTIAL_WRITE, SSL_MODE_RELEASE_BUFFERS, X509, X509_STORE,
X509_STORE_CTX,
};
use rustls::pki_types::pem::PemObject;
use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
Expand Down Expand Up @@ -240,8 +242,18 @@ entry! {

match SslCtrl::try_from(cmd) {
Ok(SslCtrl::Mode) => {
log::warn!("unimplemented SSL_CTX_set_mode()");
0
const RUSTLS_DEFAULT_EQUIVALENTS: c_long = SSL_MODE_AUTO_RETRY
| SSL_MODE_ENABLE_PARTIAL_WRITE
| SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
| SSL_MODE_RELEASE_BUFFERS;
match larg & !RUSTLS_DEFAULT_EQUIVALENTS {
// Application is requesting behaviour we already implement.
0 => C_INT_SUCCESS as c_long,
_ => {
log::warn!("unhandled SSL_CTX_set_mode({larg:x})");
0
}
}
}
Ok(SslCtrl::SetMsgCallbackArg) => {
log::warn!("unimplemented SSL_CTX_set_msg_callback_arg()");
Expand Down Expand Up @@ -691,6 +703,39 @@ entry! {
}
}

entry! {
pub fn _SSL_CTX_set_info_callback(ctx: *mut SSL_CTX, cb: SSL_CTX_info_callback_func) {
try_clone_arc!(ctx).get_mut().set_info_callback(cb);
}
}

pub type SSL_CTX_info_callback_func =
Option<unsafe extern "C" fn(ssl: *mut SSL, type_: c_int, val: c_int)>;

entry! {
pub fn _SSL_CTX_set_msg_callback(_ctx: *mut SSL_CTX, _cb: SSL_CTX_msg_cb_func) {
log::warn!("SSL_CTX_set_msg_callback not implemented; callback will not be called");
}
}

entry! {
pub fn _SSL_set_msg_callback(_ssl: *mut SSL, _cb: SSL_CTX_msg_cb_func) {
log::warn!("SSL_set_msg_callback not implemented; callback will not be called");
}
}

pub type SSL_CTX_msg_cb_func = Option<
unsafe extern "C" fn(
write_p: c_int,
version: c_int,
content_type: c_int,
buf: *const c_void,
len: usize,
ssl: *mut SSL,
arg: *mut c_void,
),
>;

entry! {
pub fn _SSL_CTX_get_max_early_data(ctx: *const SSL_CTX) -> u32 {
try_clone_arc!(ctx).get().get_max_early_data()
Expand Down Expand Up @@ -856,6 +901,21 @@ pub type custom_ext_parse_cb = Option<
) -> c_int,
>;

entry! {
pub fn _SSL_CTX_set_client_hello_cb(
ctx: *mut SSL_CTX,
cb: SSL_client_hello_cb_func,
arg: *mut c_void,
) {
try_clone_arc!(ctx)
.get_mut()
.set_client_hello_callback(cb, arg);
}
}

pub type SSL_client_hello_cb_func =
Option<unsafe extern "C" fn(_ssl: *mut SSL, _al: *mut c_int, _arg: *mut c_void) -> c_int>;

impl Castable for SSL_CTX {
type Ownership = OwnershipArc;
type RustType = NotThreadSafe<Self>;
Expand Down Expand Up @@ -2196,17 +2256,6 @@ pub type SSL_CTX_tlsext_ticket_key_evp_cb_func = Option<
) -> c_int,
>;

entry_stub! {
pub fn _SSL_CTX_set_client_hello_cb(
_ctx: *mut SSL_CTX,
_cb: SSL_client_hello_cb_func,
_arg: *mut c_void,
);
}

pub type SSL_client_hello_cb_func =
Option<unsafe extern "C" fn(_ssl: *mut SSL, _al: *mut c_int, _arg: *mut c_void) -> c_int>;

entry_stub! {
pub fn _SSL_state_string(_ssl: *const SSL) -> *const c_char;
}
Expand Down Expand Up @@ -2293,37 +2342,6 @@ entry_stub! {
) -> c_int;
}

// no individual message logging

entry_stub! {
pub fn _SSL_CTX_set_msg_callback(_ctx: *mut SSL_CTX, _cb: SSL_CTX_msg_cb_func);
}

entry_stub! {
pub fn _SSL_set_msg_callback(_ssl: *mut SSL, _cb: SSL_CTX_msg_cb_func);
}

pub type SSL_CTX_msg_cb_func = Option<
unsafe extern "C" fn(
write_p: c_int,
version: c_int,
content_type: c_int,
buf: *const c_void,
len: usize,
ssl: *mut SSL,
arg: *mut c_void,
),
>;

// no state machine observation

entry_stub! {
pub fn _SSL_CTX_set_info_callback(
_ctx: *mut SSL_CTX,
_cb: Option<unsafe extern "C" fn(ssl: *const SSL, type_: c_int, val: c_int)>,
);
}

// no NPN (obsolete precursor to ALPN)

entry_stub! {
Expand Down
Loading