From 4119ccd0cf3f52a997e0b48af7ffcd4c0872e7db Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Wed, 10 Apr 2024 17:04:04 +0100 Subject: [PATCH] Implement `SSL_set[01]_chain` & `SSL_clear_chain_certs` Plus the `SSL_CTX` equivalents. --- rustls-libssl/src/entry.rs | 38 ++++++++++++++++++++++++++++++++++++-- rustls-libssl/src/x509.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/rustls-libssl/src/entry.rs b/rustls-libssl/src/entry.rs index c9001bd..0f640cd 100644 --- a/rustls-libssl/src/entry.rs +++ b/rustls-libssl/src/entry.rs @@ -22,7 +22,7 @@ use crate::ffi::{ free_arc, str_from_cstring, to_arc_mut_ptr, try_clone_arc, try_from, try_mut_slice_int, try_ref_from_ptr, try_slice, try_slice_int, try_str, Castable, OwnershipArc, OwnershipRef, }; -use crate::x509::{load_certs, OwnedX509}; +use crate::x509::{load_certs, OwnedX509, OwnedX509Stack}; use crate::ShutdownResult; /// Makes a entry function definition. @@ -162,7 +162,7 @@ entry! { pub fn _SSL_CTX_ctrl(ctx: *mut SSL_CTX, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long { let ctx = try_clone_arc!(ctx); - let result = if let Ok(mut _inner) = ctx.lock() { + let result = if let Ok(mut inner) = ctx.lock() { match SslCtrl::try_from(cmd) { Ok(SslCtrl::Mode) => { log::warn!("unimplemented SSL_CTX_set_mode()"); @@ -180,6 +180,23 @@ entry! { // not a defined operation in the OpenSSL API 0 } + Ok(SslCtrl::SetChain) => { + let chain = if parg.is_null() { + // this is `SSL_CTX_clear_chain_certs` + vec![] + } else { + match larg { + // this is `SSL_CTX_set1_chain` (incs ref) + 1 => OwnedX509Stack::new_copy(parg as *mut stack_st_X509).to_rustls(), + // this is `SSL_CTX_set0_chain` (retain ref) + _ => OwnedX509Stack::new(parg as *mut stack_st_X509).to_rustls(), + } + }; + + inner.stage_certificate_chain(chain); + C_INT_SUCCESS as i64 + } + Err(()) => { log::warn!("unimplemented _SSL_CTX_ctrl(..., {cmd}, {larg}, ...)"); 0 @@ -574,6 +591,22 @@ entry! { let hostname = try_str!(parg as *const c_char); inner.set_sni_hostname(hostname) as c_long } + Ok(SslCtrl::SetChain) => { + let chain = if parg.is_null() { + // this is `SSL_clear_chain_certs` + vec![] + } else { + match larg { + // this is `SSL_set1_chain` (incs ref) + 1 => OwnedX509Stack::new_copy(parg as *mut stack_st_X509).to_rustls(), + // this is `SSL_set0_chain` (retain ref) + _ => OwnedX509Stack::new(parg as *mut stack_st_X509).to_rustls(), + } + }; + + inner.stage_certificate_chain(chain); + C_INT_SUCCESS as i64 + } Err(()) => { log::warn!("unimplemented _SSL_ctrl(..., {cmd}, {larg}, ...)"); 0 @@ -1231,6 +1264,7 @@ num_enum! { Mode = 33, SetMsgCallbackArg = 16, SetTlsExtHostname = 55, + SetChain = 88, SetMaxProtoVersion = 124, } } diff --git a/rustls-libssl/src/x509.rs b/rustls-libssl/src/x509.rs index 2cfb71d..b6bc991 100644 --- a/rustls-libssl/src/x509.rs +++ b/rustls-libssl/src/x509.rs @@ -27,6 +27,35 @@ impl OwnedX509Stack { } } + /// Make one by adopting ownership of an existing pointer. + pub fn new(raw: *mut stack_st_X509) -> Self { + Self { raw } + } + + /// Make one by copying existing stack. + pub fn new_copy(other: *const stack_st_X509) -> Self { + let mut ret = Self::empty(); + + let len = match unsafe { OPENSSL_sk_num(other as *const OPENSSL_STACK) } { + -1 => 0, + x => x as usize, + }; + + for index in 0..len { + let item_ptr = unsafe { + OPENSSL_sk_value(other as *const OPENSSL_STACK, index as c_int) as *mut X509 + }; + // item_ptr belongs to caller. + let item = OwnedX509::new(item_ptr); + // item belongs to `OwnedX509` -- ensure caller's ref is not stolen + item.up_ref(); + // `ret` takes its own ref + ret.push(&item); + } + + ret + } + pub fn from_rustls(certs: &Vec>) -> Self { let mut r = Self::empty(); for c in certs {