Skip to content

Commit

Permalink
Implement SSL_CTX_set_cert_cb
Browse files Browse the repository at this point in the history
  • Loading branch information
ctz committed Apr 3, 2024
1 parent 0c76fa1 commit 3f710c4
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 2 deletions.
2 changes: 1 addition & 1 deletion rustls-libssl/MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
| `SSL_CTX_set_async_callback` | | | |
| `SSL_CTX_set_async_callback_arg` | | | |
| `SSL_CTX_set_block_padding` | | | |
| `SSL_CTX_set_cert_cb` | | :white_check_mark: | |
| `SSL_CTX_set_cert_cb` | | :white_check_mark: | :white_check_mark: |
| `SSL_CTX_set_cert_store` | | | |
| `SSL_CTX_set_cert_verify_callback` | | | |
| `SSL_CTX_set_cipher_list` | :white_check_mark: | :white_check_mark: | :exclamation: [^stub] |
Expand Down
1 change: 1 addition & 0 deletions rustls-libssl/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const ENTRYPOINTS: &[&str] = &[
"SSL_CTX_sess_set_remove_cb",
"SSL_CTX_set_alpn_protos",
"SSL_CTX_set_alpn_select_cb",
"SSL_CTX_set_cert_cb",
"SSL_CTX_set_cipher_list",
"SSL_CTX_set_ciphersuites",
"SSL_CTX_set_default_passwd_cb",
Expand Down
42 changes: 41 additions & 1 deletion rustls-libssl/src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use std::collections::VecDeque;
use openssl_sys::SSL_TLSEXT_ERR_OK;

use crate::entry::{
SSL_CTX_alpn_select_cb_func, _internal_SSL_complete_accept, _internal_SSL_set_alpn_choice, SSL,
SSL_CTX_alpn_select_cb_func, SSL_CTX_cert_cb_func, _internal_SSL_complete_accept,
_internal_SSL_set_alpn_choice, SSL,
};
use crate::error::Error;

Expand Down Expand Up @@ -119,6 +120,45 @@ impl PendingCallback for AlpnPendingCallback {
}
}

/// Configuration needed to create a `CertPendingCallback` later
#[derive(Debug, Clone)]
pub struct CertCallbackConfig {
pub cb: SSL_CTX_cert_cb_func,
pub context: *mut c_void,
}

impl Default for CertCallbackConfig {
fn default() -> Self {
Self {
cb: None,
context: ptr::null_mut(),
}
}
}

pub struct CertPendingCallback {
pub config: CertCallbackConfig,
pub ssl: *mut SSL,
}

impl PendingCallback for CertPendingCallback {
fn call(self: Box<Self>) -> Result<(), Error> {
let callback = match self.config.cb {
Some(callback) => callback,
None => {
return Ok(());
}
};

let result = unsafe { callback(self.ssl, self.config.context) };

match result {
1 => Ok(()),
_ => Err(Error::not_supported("SSL_CTX_cert_cb_func returned != 1")),
}
}
}

/// The last callback during acceptance of a connection by a server.
///
/// This completes the creation of the `ServerConfig` and `ServerConnection`.
Expand Down
12 changes: 12 additions & 0 deletions rustls-libssl/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,18 @@ entry! {
}
}

pub type SSL_CTX_cert_cb_func =
Option<unsafe extern "C" fn(ssl: *mut SSL, arg: *mut c_void) -> c_int>;

entry! {
pub fn _SSL_CTX_set_cert_cb(ctx: *mut SSL_CTX, cb: SSL_CTX_cert_cb_func, arg: *mut c_void) {
let ctx = try_clone_arc!(ctx);
if let Ok(mut inner) = ctx.lock() {
inner.set_cert_cb(cb, arg);
};
}
}

impl Castable for SSL_CTX {
type Ownership = OwnershipArc;
type RustType = Mutex<SSL_CTX>;
Expand Down
13 changes: 13 additions & 0 deletions rustls-libssl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ pub struct SslContext {
verify_x509_store: x509::OwnedX509Store,
alpn: Vec<Vec<u8>>,
alpn_callback: callbacks::AlpnCallbackConfig,
cert_callback: callbacks::CertCallbackConfig,
auth_keys: sign::CertifiedKeySet,
}

Expand All @@ -226,6 +227,7 @@ impl SslContext {
verify_x509_store: x509::OwnedX509Store::new(),
alpn: vec![],
alpn_callback: callbacks::AlpnCallbackConfig::default(),
cert_callback: callbacks::CertCallbackConfig::default(),
auth_keys: sign::CertifiedKeySet::default(),
}
}
Expand Down Expand Up @@ -272,6 +274,10 @@ impl SslContext {
self.alpn_callback = callbacks::AlpnCallbackConfig { cb, context };
}

fn set_cert_cb(&mut self, cb: entry::SSL_CTX_cert_cb_func, context: *mut c_void) {
self.cert_callback = callbacks::CertCallbackConfig { cb, context };
}

fn stage_certificate_chain(&mut self, chain: Vec<CertificateDer<'static>>) {
self.auth_keys.stage_certificate_chain(chain)
}
Expand Down Expand Up @@ -352,6 +358,7 @@ struct Ssl {
verify_server_name: Option<ServerName<'static>>,
alpn: Vec<Vec<u8>>,
alpn_callback: callbacks::AlpnCallbackConfig,
cert_callback: callbacks::CertCallbackConfig,
sni_server_name: Option<ServerName<'static>>,
bio: Option<bio::Bio>,
conn: ConnState,
Expand Down Expand Up @@ -381,6 +388,7 @@ impl Ssl {
verify_server_name: None,
alpn: inner.alpn.clone(),
alpn_callback: inner.alpn_callback.clone(),
cert_callback: inner.cert_callback.clone(),
sni_server_name: None,
bio: None,
conn: ConnState::Nothing,
Expand Down Expand Up @@ -574,6 +582,11 @@ impl Ssl {
}));
}

callbacks.add(Box::new(callbacks::CertPendingCallback {
config: self.cert_callback.clone(),
ssl: callbacks.ssl_ptr(),
}));

// must be last: trigger the transition `Accepted` -> `Server`
callbacks.add(Box::new(callbacks::CompleteAcceptPendingCallback {
ssl: callbacks.ssl_ptr(),
Expand Down
12 changes: 12 additions & 0 deletions rustls-libssl/tests/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ static int alpn_callback(SSL *ssl, const uint8_t **out, uint8_t *outlen,
}
}

static int cert_cookie = 12345;

static int cert_callback(SSL *ssl, void *arg) {
printf("in cert_callback\n");
assert(ssl != NULL);
assert(arg == &cert_cookie);
return 1;
}

int main(int argc, char **argv) {
if (argc != 5) {
printf("%s <port> <key-file> <cert-chain-file> <cacert>|unauth\n\n",
Expand Down Expand Up @@ -105,6 +114,9 @@ int main(int argc, char **argv) {
SSL_CTX_set_alpn_select_cb(ctx, alpn_callback, &alpn_cookie);
dump_openssl_error_stack();

SSL_CTX_set_cert_cb(ctx, cert_callback, &cert_cookie);
dump_openssl_error_stack();

X509 *client_cert = NULL;
EVP_PKEY *client_key = NULL;
TRACE(SSL_CTX_use_certificate_chain_file(ctx, certfile));
Expand Down

0 comments on commit 3f710c4

Please sign in to comment.