diff --git a/rustls-libssl/MATRIX.md b/rustls-libssl/MATRIX.md index aa5f0bb..65c90e1 100644 --- a/rustls-libssl/MATRIX.md +++ b/rustls-libssl/MATRIX.md @@ -49,16 +49,16 @@ | `SSL_COMP_get_name` | | | | | `SSL_COMP_set0_compression_methods` | | | | | `SSL_CONF_CTX_clear_flags` | | | | -| `SSL_CONF_CTX_finish` | | | | -| `SSL_CONF_CTX_free` | | | | -| `SSL_CONF_CTX_new` | | | | +| `SSL_CONF_CTX_finish` | | | :exclamation: [^stub] | +| `SSL_CONF_CTX_free` | | | :exclamation: [^stub] | +| `SSL_CONF_CTX_new` | | | :exclamation: [^stub] | | `SSL_CONF_CTX_set1_prefix` | | | | -| `SSL_CONF_CTX_set_flags` | | | | +| `SSL_CONF_CTX_set_flags` | | | :exclamation: [^stub] | | `SSL_CONF_CTX_set_ssl` | | | | -| `SSL_CONF_CTX_set_ssl_ctx` | | | | -| `SSL_CONF_cmd` | | | | +| `SSL_CONF_CTX_set_ssl_ctx` | | | :exclamation: [^stub] | +| `SSL_CONF_cmd` | | | :exclamation: [^stub] | | `SSL_CONF_cmd_argv` | | | | -| `SSL_CONF_cmd_value_type` | | | | +| `SSL_CONF_cmd_value_type` | | | :exclamation: [^stub] | | `SSL_CTX_SRP_CTX_free` [^deprecatedin_3_0] [^srp] | | | | | `SSL_CTX_SRP_CTX_init` [^deprecatedin_3_0] [^srp] | | | | | `SSL_CTX_add1_to_CA_list` | | | | @@ -232,8 +232,8 @@ | `SSL_SESSION_get_max_fragment_length` | | | | | `SSL_SESSION_get_protocol_version` | | | | | `SSL_SESSION_get_ticket_lifetime_hint` | | | | -| `SSL_SESSION_get_time` | | | | -| `SSL_SESSION_get_timeout` | | | | +| `SSL_SESSION_get_time` | | | :white_check_mark: | +| `SSL_SESSION_get_timeout` | | | :white_check_mark: | | `SSL_SESSION_has_ticket` | | | | | `SSL_SESSION_is_resumable` | | | | | `SSL_SESSION_new` | | | | @@ -243,15 +243,15 @@ | `SSL_SESSION_set1_alpn_selected` | | | | | `SSL_SESSION_set1_hostname` | | | | | `SSL_SESSION_set1_id` | | | | -| `SSL_SESSION_set1_id_context` | | | | +| `SSL_SESSION_set1_id_context` | | | :white_check_mark: | | `SSL_SESSION_set1_master_key` | | | | | `SSL_SESSION_set1_ticket_appdata` | | | | | `SSL_SESSION_set_cipher` | | | | | `SSL_SESSION_set_ex_data` | | | | | `SSL_SESSION_set_max_early_data` | | | | | `SSL_SESSION_set_protocol_version` | | | | -| `SSL_SESSION_set_time` | | | | -| `SSL_SESSION_set_timeout` | | | | +| `SSL_SESSION_set_time` | | | :white_check_mark: | +| `SSL_SESSION_set_timeout` | | | :white_check_mark: | | `SSL_SESSION_up_ref` | | :white_check_mark: | :white_check_mark: | | `SSL_SRP_CTX_free` [^deprecatedin_3_0] [^srp] | | | | | `SSL_SRP_CTX_init` [^deprecatedin_3_0] [^srp] | | | | @@ -318,7 +318,7 @@ | `SSL_get1_peer_certificate` | :white_check_mark: | :white_check_mark: | :white_check_mark: | | `SSL_get1_session` | | :white_check_mark: | :white_check_mark: | | `SSL_get1_supported_ciphers` | | | | -| `SSL_get_SSL_CTX` | | | | +| `SSL_get_SSL_CTX` | | | :white_check_mark: | | `SSL_get_all_async_fds` | | | | | `SSL_get_async_status` | | | | | `SSL_get_certificate` | :white_check_mark: | :white_check_mark: | :white_check_mark: | @@ -409,7 +409,7 @@ | `SSL_rstate_string` | | | | | `SSL_rstate_string_long` | | | | | `SSL_select_next_proto` | | :white_check_mark: | :white_check_mark: | -| `SSL_sendfile` | | | | +| `SSL_sendfile` | | | :exclamation: [^stub] | | `SSL_session_reused` | | :white_check_mark: | :white_check_mark: | | `SSL_set0_CA_list` | | | | | `SSL_set0_rbio` | | | :white_check_mark: | @@ -498,7 +498,7 @@ | `SSL_use_certificate_file` | | | | | `SSL_use_psk_identity_hint` [^psk] | | | | | `SSL_verify_client_post_handshake` | | | | -| `SSL_version` | | | | +| `SSL_version` | | | :white_check_mark: | | `SSL_waiting_for_async` | | | | | `SSL_want` | | | :white_check_mark: | | `SSL_write` | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/rustls-libssl/Makefile b/rustls-libssl/Makefile index d79bb72..f1f937c 100644 --- a/rustls-libssl/Makefile +++ b/rustls-libssl/Makefile @@ -76,9 +76,9 @@ target/VERSION: ALWAYS echo "This is rustls-libssl `git describe --always`\nDate: `date`\nIncorporating:" > $@ $(CARGO) tree >> $@ -test-package: test-package-deb +test-package: test-package-deb-22 test-package-deb-24 -test-package-deb: package-deb +test-package-deb-22: package-deb mkdir --parents target/dist/test/ubuntu-22 cp target/dist/rustls-libssl_*.deb \ dist/test/deb-ubuntu-22/* \ @@ -89,6 +89,20 @@ test-package-deb: package-deb docker build --tag $@ target/dist/test/ubuntu-22 cd target/dist/test/ubuntu-22 && ./run-test.sh $@ +test-package-deb-24: package-deb + mkdir --parents target/dist/test/ubuntu-24 + cp target/dist/rustls-libssl_*.deb \ + dist/test/deb-ubuntu-22/* \ + test-ca/rsa/server.key \ + test-ca/rsa/server.cert \ + test-ca/rsa/ca.cert \ + target/dist/test/ubuntu-24 + # copy deb-ubuntu-24 files on top of -22 ones + cp dist/test/deb-ubuntu-24/* \ + target/dist/test/ubuntu-24 + docker build --tag $@ target/dist/test/ubuntu-24 + cd target/dist/test/ubuntu-24 && ./run-test.sh $@ + ALWAYS: ; .PHONY: all clean test integration format format-check package package-deb ALWAYS test-package test-package-deb diff --git a/rustls-libssl/build.rs b/rustls-libssl/build.rs index d676daf..58f1f8f 100644 --- a/rustls-libssl/build.rs +++ b/rustls-libssl/build.rs @@ -59,6 +59,13 @@ const ENTRYPOINTS: &[&str] = &[ "SSL_CIPHER_get_version", "SSL_CIPHER_standard_name", "SSL_clear_options", + "SSL_CONF_cmd", + "SSL_CONF_cmd_value_type", + "SSL_CONF_CTX_finish", + "SSL_CONF_CTX_free", + "SSL_CONF_CTX_new", + "SSL_CONF_CTX_set_flags", + "SSL_CONF_CTX_set_ssl_ctx", "SSL_connect", "SSL_ctrl", "SSL_CTX_add_client_CA", @@ -141,6 +148,7 @@ const ENTRYPOINTS: &[&str] = &[ "SSL_get_servername_type", "SSL_get_session", "SSL_get_shutdown", + "SSL_get_SSL_CTX", "SSL_get_state", "SSL_get_verify_depth", "SSL_get_verify_result", @@ -157,9 +165,15 @@ const ENTRYPOINTS: &[&str] = &[ "SSL_read", "SSL_read_early_data", "SSL_select_next_proto", + "SSL_sendfile", "SSL_SESSION_free", "SSL_SESSION_get_id", + "SSL_SESSION_get_time", + "SSL_SESSION_get_timeout", "SSL_session_reused", + "SSL_SESSION_set1_id_context", + "SSL_SESSION_set_time", + "SSL_SESSION_set_timeout", "SSL_SESSION_up_ref", "SSL_set0_rbio", "SSL_set0_wbio", @@ -183,6 +197,7 @@ const ENTRYPOINTS: &[&str] = &[ "SSL_use_certificate", "SSL_use_PrivateKey", "SSL_use_PrivateKey_file", + "SSL_version", "SSL_want", "SSL_write", "SSL_write_early_data", diff --git a/rustls-libssl/dist/bin/rustls-libssl-nginx b/rustls-libssl/dist/bin/rustls-libssl-nginx index e7804b4..5e1aed7 100755 --- a/rustls-libssl/dist/bin/rustls-libssl-nginx +++ b/rustls-libssl/dist/bin/rustls-libssl-nginx @@ -3,7 +3,7 @@ NGINX_DROP_IN_DIR=/etc/systemd/system/nginx.service.d/ DROP_IN=/usr/share/rustls-libssl/50-rustls-libssl.conf -distro=$(lsb_release --short --id 2>/dev/null || echo "Unknown") +distro=$(. /etc/lsb-release && echo $DISTRIB_ID || echo "Unknown") case $distro in "Debian") diff --git a/rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh b/rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh index 6ac2310..4e2a778 100755 --- a/rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh +++ b/rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh @@ -4,10 +4,10 @@ set -e TAG="$1" docker run --interactive --publish 8443:443 "$TAG" & -DOCKER_ID=$! sleep 2 output_got=$(curl --cacert ca.cert https://localhost:8443/) -kill "$DOCKER_ID" +docker stop "$(docker ps --quiet)" + diff --unified --report-identical-files <(echo "hello world") <(echo "$output_got") diff --git a/rustls-libssl/dist/test/deb-ubuntu-24/Dockerfile b/rustls-libssl/dist/test/deb-ubuntu-24/Dockerfile new file mode 100644 index 0000000..f7a2b42 --- /dev/null +++ b/rustls-libssl/dist/test/deb-ubuntu-24/Dockerfile @@ -0,0 +1,14 @@ +FROM ubuntu:24.04 +ENV DEBIAN_FRONTEND=noninteractive +RUN apt update && apt install -y curl nginx +ADD rustls-libssl_*.deb /root +ADD --chown=nobody:nogroup server.cert / +ADD --chown=nobody:nogroup server.key / +ADD ca.cert /root +ADD nginx.conf /etc/nginx/sites-enabled/default +RUN dpkg -i /root/rustls-libssl_*.deb + +# nb, this only affects systemd runs, but check it works at least +RUN rustls-libssl-nginx enable + +CMD /usr/bin/with-rustls-libssl nginx -g 'daemon off;' diff --git a/rustls-libssl/src/cache.rs b/rustls-libssl/src/cache.rs index 8371117..42f0563 100644 --- a/rustls-libssl/src/cache.rs +++ b/rustls-libssl/src/cache.rs @@ -11,6 +11,7 @@ use rustls::server::StoresServerSessions; use crate::entry::{ SSL_CTX_new_session_cb, SSL_CTX_sess_get_cb, SSL_CTX_sess_remove_cb, SSL_CTX, SSL_SESSION, }; +use crate::not_thread_safe::NotThreadSafe; use crate::{callbacks, SslSession, SslSessionLookup}; /// A container for session caches that can live inside @@ -118,11 +119,12 @@ impl Default for SessionCaches { #[derive(Debug)] pub struct ServerSessionStorage { - items: Mutex>>, + items: Mutex>>>, parameters: Mutex, op_count: AtomicUsize, } +#[allow(clippy::mutable_key_type)] // clippy can't see that we don't mutate SslSession::id impl ServerSessionStorage { fn new(max_size: usize) -> Self { Self { @@ -218,11 +220,11 @@ impl ServerSessionStorage { .unwrap_or_default() } - fn invoke_new_callback(&self, sess: Arc) -> bool { + fn invoke_new_callback(&self, sess: Arc>) -> bool { callbacks::invoke_session_new_callback(self.callbacks().new_callback, sess) } - fn invoke_remove_callback(&self, sess: Arc) { + fn invoke_remove_callback(&self, sess: Arc>) { let callbacks = self.callbacks(); callbacks::invoke_session_remove_callback( callbacks.remove_callback, @@ -231,26 +233,34 @@ impl ServerSessionStorage { ); } - fn invoke_get_callback(&self, id: &[u8]) -> Option> { + fn invoke_get_callback(&self, id: &[u8]) -> Option>> { callbacks::invoke_session_get_callback(self.callbacks().get_callback, id) } - fn build_new_session(&self, id: Vec, value: Vec) -> Arc { + fn build_new_session(&self, id: Vec, value: Vec) -> Arc> { let context = self.get_context(); - let time_out = ExpiryTime::calculate(TimeBase::now(), self.get_timeout()); - Arc::new(SslSession::new(id, value, context, time_out)) + Arc::new(NotThreadSafe::new(SslSession::new( + id, + value, + context, + TimeBase::now(), + self.get_timeout(), + ))) } /// Return `None` if `sess` has the wrong context value. - fn filter_session_context(&self, sess: Arc) -> Option> { - if self.get_context() == sess.context { + fn filter_session_context( + &self, + sess: Arc>, + ) -> Option>> { + if self.get_context() == sess.get().context { Some(sess) } else { None } } - fn insert(&self, new: Arc) -> bool { + fn insert(&self, new: Arc>) -> bool { self.tick(); let max_size = self @@ -272,7 +282,7 @@ impl ServerSessionStorage { } } - fn take(&self, id: &[u8]) -> Option> { + fn take(&self, id: &[u8]) -> Option>> { self.tick(); if let Ok(mut items) = self.items.lock() { @@ -282,7 +292,7 @@ impl ServerSessionStorage { } } - fn find_by_id(&self, id: &[u8]) -> Option> { + fn find_by_id(&self, id: &[u8]) -> Option>> { self.tick(); if let Ok(items) = self.items.lock() { @@ -318,7 +328,7 @@ impl ServerSessionStorage { // if we have a callback to invoke, do it the slow way let mut removal_list: BTreeSet<_> = items .iter() - .filter(|item| item.expired(at_time)) + .filter(|item| item.get().expired(at_time)) .cloned() .collect(); @@ -331,7 +341,7 @@ impl ServerSessionStorage { ); } } else { - items.retain(|item| !item.expired(at_time)); + items.retain(|item| !item.get().expired(at_time)); } } } @@ -345,8 +355,8 @@ impl ServerSessionStorage { } } - fn flush_oldest(items: &mut BTreeSet>) { - let oldest = items.iter().min_by_key(|item| item.expiry_time.0); + fn flush_oldest(items: &mut BTreeSet>>) { + let oldest = items.iter().min_by_key(|item| item.get().creation_time.0); if let Some(oldest) = oldest.cloned() { items.take(&oldest); } @@ -381,7 +391,7 @@ impl CacheParameters { #[derive(Debug)] pub struct SingleServerCache { parent: Arc, - most_recent_session: Mutex>>, + most_recent_session: Mutex>>>, } impl SingleServerCache { @@ -396,13 +406,13 @@ impl SingleServerCache { self.parent.mode() & CACHE_MODE_SERVER == CACHE_MODE_SERVER } - fn save_most_recent_session(&self, sess: Arc) { + fn save_most_recent_session(&self, sess: Arc>) { if let Ok(mut old) = self.most_recent_session.lock() { *old = Some(sess); } } - pub fn get_most_recent_session(&self) -> Option> { + pub fn get_most_recent_session(&self) -> Option>> { self.most_recent_session .lock() .ok() @@ -452,7 +462,7 @@ impl StoresServerSessions for SingleServerCache { .and_then(|sess| self.parent.filter_session_context(sess)); if let Some(sess) = sess { self.save_most_recent_session(sess.clone()); - return Some(sess.value.clone()); + return Some(sess.get().value.clone()); } } @@ -461,7 +471,7 @@ impl StoresServerSessions for SingleServerCache { .invoke_get_callback(id) .and_then(|sess| self.parent.filter_session_context(sess)) { - return Some(sess.value.clone()); + return Some(sess.get().value.clone()); } None @@ -483,7 +493,7 @@ impl StoresServerSessions for SingleServerCache { self.parent.invoke_remove_callback(sess.clone()); self.save_most_recent_session(sess.clone()); - return Some(sess.value.clone()); + return Some(sess.get().value.clone()); } } @@ -495,7 +505,7 @@ impl StoresServerSessions for SingleServerCache { { self.save_most_recent_session(sess.clone()); self.parent.invoke_remove_callback(sess.clone()); - return Some(sess.value.clone()); + return Some(sess.get().value.clone()); } None @@ -538,7 +548,7 @@ unsafe impl Send for CacheCallbacks {} pub struct ExpiryTime(pub u64); impl ExpiryTime { - fn calculate(now: TimeBase, life_time_secs: u64) -> ExpiryTime { + pub fn calculate(now: TimeBase, life_time_secs: u64) -> ExpiryTime { ExpiryTime(now.0.saturating_add(life_time_secs)) } @@ -548,7 +558,7 @@ impl ExpiryTime { } #[derive(Debug, Clone, Copy)] -pub struct TimeBase(u64); +pub struct TimeBase(pub u64); impl TimeBase { pub fn now() -> Self { @@ -571,7 +581,14 @@ mod tests { for i in 1..=5 { assert!(cache.insert( - SslSession::new(vec![i], vec![], vec![], ExpiryTime(10 + i as u64)).into() + NotThreadSafe::new(SslSession::new( + vec![i], + vec![], + vec![], + TimeBase(i as u64), + 10 + )) + .into() )); } @@ -591,7 +608,14 @@ mod tests { for i in 1..=5 { assert!(cache.insert( - SslSession::new(vec![i], vec![], vec![], ExpiryTime(10 + i as u64)).into() + NotThreadSafe::new(SslSession::new( + vec![i], + vec![], + vec![], + TimeBase(i as u64), + 10 + )) + .into() )); } @@ -608,7 +632,14 @@ mod tests { for i in 1..=5 { assert!(cache.insert( - SslSession::new(vec![i], vec![], vec![], ExpiryTime(10 + i as u64)).into() + NotThreadSafe::new(SslSession::new( + vec![i], + vec![], + vec![], + TimeBase(i as u64), + 10 + )) + .into() )); } @@ -619,7 +650,9 @@ mod tests { assert!(cache.find_by_id(&[5]).is_some()); cache.set_size(4); - assert!(cache.insert(SslSession::new(vec![6], vec![], vec![], ExpiryTime(16)).into())); + assert!(cache.insert( + NotThreadSafe::new(SslSession::new(vec![6], vec![], vec![], TimeBase(6), 10)).into() + )); assert!(cache.find_by_id(&[1]).is_none()); assert!(cache.find_by_id(&[2]).is_none()); @@ -634,10 +667,26 @@ mod tests { let cache = ServerSessionStorage::new(5); cache.set_context(b"hello"); - assert!(cache - .insert(SslSession::new(vec![1], vec![], b"hello".to_vec(), ExpiryTime(10)).into())); - assert!(cache - .insert(SslSession::new(vec![2], vec![], b"goodbye".to_vec(), ExpiryTime(10)).into())); + assert!(cache.insert( + NotThreadSafe::new(SslSession::new( + vec![1], + vec![], + b"hello".to_vec(), + TimeBase(5), + 5, + )) + .into() + )); + assert!(cache.insert( + NotThreadSafe::new(SslSession::new( + vec![2], + vec![], + b"goodbye".to_vec(), + TimeBase(5), + 5 + )) + .into() + )); assert!(cache .find_by_id(&[1]) diff --git a/rustls-libssl/src/callbacks.rs b/rustls-libssl/src/callbacks.rs index b7a727d..7d3da5c 100644 --- a/rustls-libssl/src/callbacks.rs +++ b/rustls-libssl/src/callbacks.rs @@ -13,6 +13,7 @@ use crate::entry::{ }; use crate::error::Error; use crate::ffi; +use crate::not_thread_safe::NotThreadSafe; /// Smuggling SSL* pointers from the outer entrypoint into the /// callback call site. @@ -189,7 +190,7 @@ impl Default for ServerNameCallbackConfig { /// It is unknowable if this means something was stored externally. pub fn invoke_session_new_callback( callback: SSL_CTX_new_session_cb, - sess: Arc, + sess: Arc>, ) -> bool { let callback = match callback { Some(callback) => callback, @@ -213,7 +214,7 @@ pub fn invoke_session_new_callback( pub fn invoke_session_get_callback( callback: SSL_CTX_sess_get_cb, id: &[u8], -) -> Option> { +) -> Option>> { let callback = match callback { Some(callback) => callback, None => { @@ -241,7 +242,7 @@ pub fn invoke_session_get_callback( pub fn invoke_session_remove_callback( callback: SSL_CTX_sess_remove_cb, ssl_ctx: *mut SSL_CTX, - sess: Arc, + sess: Arc>, ) { let callback = match callback { Some(callback) => callback, diff --git a/rustls-libssl/src/entry.rs b/rustls-libssl/src/entry.rs index cc8dc15..bfa4c47 100644 --- a/rustls-libssl/src/entry.rs +++ b/rustls-libssl/src/entry.rs @@ -647,6 +647,9 @@ entry! { sid_ctx_len: c_uint, ) -> c_int { let sid_ctx = try_slice!(sid_ctx, sid_ctx_len); + if sid_ctx.len() > SSL_MAX_SID_CTX_LENGTH { + return Error::not_supported("excess sid_ctx_len").raise().into(); + } try_clone_arc!(ctx) .get_mut() .set_session_id_context(sid_ctx); @@ -754,6 +757,12 @@ entry! { } } +entry! { + pub fn _SSL_get_SSL_CTX(ssl: *const SSL) -> *mut SSL_CTX { + Arc::as_ptr(&try_clone_arc!(ssl).get().ctx) as *mut SSL_CTX + } +} + entry! { pub fn _SSL_set_ex_data(ssl: *mut SSL, idx: c_int, data: *mut c_void) -> c_int { match try_clone_arc!(ssl).get_mut().set_ex_data(idx, data) { @@ -1163,6 +1172,19 @@ entry! { } } +entry! { + pub fn _SSL_version(ssl: *const SSL) -> c_int { + try_clone_arc!(ssl) + .get() + .conn() + .and_then(|conn| { + conn.protocol_version() + .map(|proto| u16::from(proto) as c_int) + }) + .unwrap_or_default() + } +} + entry! { pub fn _SSL_get_verify_result(ssl: *const SSL) -> c_long { try_clone_arc!(ssl).get().get_last_verification_result() @@ -1531,7 +1553,7 @@ entry! { } let sess = try_clone_arc!(sess); - let id = sess.get_id(); + let id = sess.get().get_id(); unsafe { *len = id.len() as c_uint }; id.as_ptr() } @@ -1545,6 +1567,55 @@ entry! { } } +entry! { + pub fn _SSL_SESSION_set_time(sess: *mut SSL_SESSION, time: c_long) -> c_long { + if time < 0 { + return 0; + } + try_clone_arc!(sess) + .get_mut() + .set_creation_time(time as u64); + C_INT_SUCCESS as c_long + } +} + +entry! { + pub fn _SSL_SESSION_get_time(sess: *const SSL_SESSION) -> c_long { + try_clone_arc!(sess).get().get_creation_time() as c_long + } +} + +entry! { + pub fn _SSL_SESSION_set_timeout(sess: *mut SSL_SESSION, time_out: c_long) -> c_long { + if time_out < 0 { + return 0; + } + try_clone_arc!(sess).get_mut().set_time_out(time_out as u64); + C_INT_SUCCESS as c_long + } +} + +entry! { + pub fn _SSL_SESSION_get_timeout(sess: *const SSL_SESSION) -> c_long { + try_clone_arc!(sess).get().get_time_out() as c_long + } +} + +entry! { + pub fn _SSL_SESSION_set1_id_context( + sess: *mut SSL_SESSION, + sid_ctx: *const c_uchar, + sid_ctx_len: c_uint, + ) -> c_int { + let slice = try_slice!(sid_ctx, sid_ctx_len); + if slice.len() > SSL_MAX_SID_CTX_LENGTH { + return Error::not_supported("excess sid_ctx_len").raise().into(); + } + try_clone_arc!(sess).get_mut().set_context(slice); + C_INT_SUCCESS + } +} + entry! { pub fn _d2i_SSL_SESSION( a: *mut *mut SSL_SESSION, @@ -1576,14 +1647,14 @@ entry! { // move along *pp unsafe { ptr::write(pp, ptr.add(consumed_bytes)) }; - to_arc_mut_ptr(sess) + to_arc_mut_ptr(NotThreadSafe::new(sess)) } } entry! { pub fn _i2d_SSL_SESSION(sess: *const SSL_SESSION, pp: *mut *mut c_uchar) -> c_int { let sess = try_clone_arc!(sess); - let encoded = sess.encode(); + let encoded = sess.get().encode(); if !pp.is_null() { let ptr = unsafe { ptr::read(pp) }; @@ -1604,7 +1675,7 @@ entry! { impl Castable for SSL_SESSION { type Ownership = OwnershipArc; - type RustType = SSL_SESSION; + type RustType = NotThreadSafe; } /// Normal OpenSSL return value convention success indicator. @@ -1615,6 +1686,8 @@ const C_INT_SUCCESS: c_int = 1; const FILETYPE_PEM: c_int = 1; const FILETYPE_DER: c_int = 2; +const SSL_MAX_SID_CTX_LENGTH: usize = 32; + /// Define an enum that can round trip through a c_int, with no /// UB for unknown values. macro_rules! num_enum { @@ -1871,6 +1944,50 @@ entry_stub! { pub fn _SSL_set_post_handshake_auth(_s: *mut SSL, _val: c_int); } +// no configuration command support + +entry_stub! { + pub fn _SSL_CONF_CTX_new() -> *mut SSL_CONF_CTX; +} + +entry_stub! { + pub fn _SSL_CONF_CTX_free(_cctx: *mut SSL_CONF_CTX); +} + +entry_stub! { + pub fn _SSL_CONF_CTX_finish(_cctx: *mut SSL_CONF_CTX) -> c_int; +} + +entry_stub! { + pub fn _SSL_CONF_CTX_set_flags(_cctx: *mut SSL_CONF_CTX, _flags: c_uint) -> c_uint; +} + +entry_stub! { + pub fn _SSL_CONF_CTX_set_ssl_ctx(_cctx: *mut SSL_CONF_CTX, _ctx: *mut SSL_CTX); +} + +entry_stub! { + pub fn _SSL_CONF_cmd(_ctx: *mut SSL_CONF_CTX, _opt: *mut c_char, _value: *mut c_char) -> c_int; +} + +entry_stub! { + pub fn _SSL_CONF_cmd_value_type(_ctx: *mut SSL_CONF_CTX, _opt: *mut c_char) -> c_int; +} + +pub struct SSL_CONF_CTX; + +// No kTLS/sendfile support + +entry_stub! { + pub fn _SSL_sendfile( + _ssl: *mut SSL, + _fd: c_int, + _offset: c_long, + _size: usize, + _flags: c_int, + ) -> c_long; +} + // --------------------- #[cfg(test)] @@ -2116,9 +2233,10 @@ mod tests { vec![1; 32], vec![2; 32], vec![3; 128], - crate::cache::ExpiryTime(123), + crate::cache::TimeBase(123), + 300, ); - let sess_ptr = to_arc_mut_ptr(sess); + let sess_ptr = to_arc_mut_ptr(NotThreadSafe::new(sess)); let mut buffer = [0u8; 1024]; let mut ptr = buffer.as_mut_ptr(); diff --git a/rustls-libssl/src/lib.rs b/rustls-libssl/src/lib.rs index 9307666..ceec0be 100644 --- a/rustls-libssl/src/lib.rs +++ b/rustls-libssl/src/lib.rs @@ -223,7 +223,8 @@ pub struct SslSession { id: SslSessionLookup, value: Vec, context: Vec, - expiry_time: cache::ExpiryTime, + creation_time: cache::TimeBase, + time_out: u64, } impl SslSession { @@ -237,13 +238,15 @@ impl SslSession { id: Vec, value: Vec, context: Vec, - expiry_time: cache::ExpiryTime, + creation_time: cache::TimeBase, + time_out: u64, ) -> Self { Self { id: SslSessionLookup(id), value, context, - expiry_time, + creation_time, + time_out, } } @@ -254,7 +257,8 @@ impl SslSession { let id_len = self.id.0.len().to_le_bytes(); let value_len = self.value.len().to_le_bytes(); let context_len = self.context.len().to_le_bytes(); - let expiry = self.expiry_time.0.to_le_bytes(); + let creation_time = self.creation_time.0.to_le_bytes(); + let time_out = self.time_out.to_le_bytes(); let mut ret = Vec::with_capacity( SslSession::MAGIC.len() @@ -264,7 +268,8 @@ impl SslSession { + self.value.len() + context_len.len() + self.context.len() - + expiry.len(), + + creation_time.len() + + time_out.len(), ); ret.extend_from_slice(SslSession::MAGIC); ret.extend_from_slice(&id_len); @@ -273,7 +278,8 @@ impl SslSession { ret.extend_from_slice(&self.value); ret.extend_from_slice(&context_len); ret.extend_from_slice(&self.context); - ret.extend_from_slice(&expiry); + ret.extend_from_slice(&creation_time); + ret.extend_from_slice(&time_out); ret } @@ -310,13 +316,15 @@ impl SslSession { let (value, slice) = split_at(slice, slice_to_usize(value_len))?; let (context_len, slice) = split_at(slice, usize_len)?; let (context, slice) = split_at(slice, slice_to_usize(context_len))?; - let (expiry, slice) = split_at(slice, u64_len)?; + let (creation_time, slice) = split_at(slice, u64_len)?; + let (time_out, slice) = split_at(slice, u64_len)?; Some(( Self { id: SslSessionLookup(id.to_vec()), value: value.to_vec(), context: context.to_vec(), - expiry_time: cache::ExpiryTime(slice_to_u64(expiry)), + creation_time: cache::TimeBase(slice_to_u64(creation_time)), + time_out: slice_to_u64(time_out), }, slice, )) @@ -326,12 +334,28 @@ impl SslSession { &self.id.0 } - pub fn expired(&self, at_time: cache::TimeBase) -> bool { - self.expiry_time.in_past(at_time) + pub fn get_creation_time(&self) -> u64 { + self.creation_time.0 + } + + pub fn set_creation_time(&mut self, new_time: u64) { + self.creation_time = cache::TimeBase(new_time); + } + + pub fn get_time_out(&self) -> u64 { + self.time_out } - pub fn older_than(&self, other: &Self) -> bool { - self.expiry_time.0 < other.expiry_time.0 + pub fn set_time_out(&mut self, time_out_secs: u64) { + self.time_out = time_out_secs; + } + + pub fn set_context(&mut self, new_context: &[u8]) { + self.context = new_context.to_vec(); + } + + pub fn expired(&self, at_time: cache::TimeBase) -> bool { + cache::ExpiryTime::calculate(self.creation_time, self.time_out).in_past(at_time) } } @@ -355,9 +379,9 @@ impl PartialEq for SslSession { impl Eq for SslSession {} -impl borrow::Borrow for Arc { +impl borrow::Borrow for Arc> { fn borrow(&self) -> &SslSessionLookup { - &self.id + &self.get().id } } @@ -365,7 +389,8 @@ impl fmt::Debug for SslSession { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { f.debug_struct("SslSession") .field("id", &self.id) - .field("expiry", &self.expiry_time) + .field("creation_time", &self.creation_time) + .field("time_out", &self.time_out) .finish_non_exhaustive() } } @@ -1398,7 +1423,7 @@ impl Ssl { } } - fn get_current_session(&self) -> Option> { + fn get_current_session(&self) -> Option>> { match &self.conn { ConnState::Server(_, _, cache) => cache.get_most_recent_session(), // divergence: `SSL_get1_session` etc only work for server SSLs diff --git a/rustls-libssl/src/not_thread_safe.rs b/rustls-libssl/src/not_thread_safe.rs index 1da63e0..4b87375 100644 --- a/rustls-libssl/src/not_thread_safe.rs +++ b/rustls-libssl/src/not_thread_safe.rs @@ -1,4 +1,6 @@ use core::cell::UnsafeCell; +use core::cmp; +use std::fmt; /// An extremely bad and unsafe laundering of pointer-to-references. /// @@ -33,3 +35,31 @@ impl NotThreadSafe { unsafe { &mut *self.cell.get() } } } + +impl fmt::Debug for NotThreadSafe { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + self.cell.fmt(f) + } +} + +impl Ord for NotThreadSafe { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.get().cmp(other.get()) + } +} + +impl + Ord> PartialOrd for NotThreadSafe { + fn partial_cmp(&self, other: &NotThreadSafe) -> Option { + Some(self.get().cmp(other.get())) + } +} + +impl Eq for NotThreadSafe {} + +impl PartialEq for NotThreadSafe { + fn eq(&self, other: &Self) -> bool { + self.get().eq(other.get()) + } +} + +unsafe impl Sync for NotThreadSafe {} diff --git a/rustls-libssl/tests/client.c b/rustls-libssl/tests/client.c index ab8416c..2d16e30 100644 --- a/rustls-libssl/tests/client.c +++ b/rustls-libssl/tests/client.c @@ -86,6 +86,7 @@ int main(int argc, char **argv) { SSL *ssl = SSL_new(ctx); dump_openssl_error_stack(); + assert(SSL_get_SSL_CTX(ssl) == ctx); printf("SSL_new: SSL_get_privatekey %s SSL_CTX_get0_privatekey\n", SSL_get_privatekey(ssl) == client_key ? "same as" : "differs to"); printf("SSL_new: SSL_get_certificate %s SSL_CTX_get0_certificate\n", @@ -122,6 +123,7 @@ int main(int argc, char **argv) { hexdump("alpn", alpn_ptr, alpn_len); printf("version: %s\n", SSL_get_version(ssl)); + printf("numeric version: %d\n", SSL_version(ssl)); printf("verify-result: %ld\n", SSL_get_verify_result(ssl)); printf("cipher: %s\n", SSL_CIPHER_standard_name(SSL_get_current_cipher(ssl))); diff --git a/rustls-libssl/tests/server.c b/rustls-libssl/tests/server.c index 747a18e..9e80647 100644 --- a/rustls-libssl/tests/server.c +++ b/rustls-libssl/tests/server.c @@ -76,6 +76,8 @@ static int sess_new_callback(SSL *ssl, SSL_SESSION *sess) { unsigned id_len = 0; SSL_SESSION_get_id(sess, &id_len); printf(" SSL_SESSION_get_id len=%u\n", id_len); + TRACE(SSL_SESSION_set_timeout(sess, SSL_SESSION_get_timeout(sess))); + TRACE(SSL_SESSION_set1_id_context(sess, (uint8_t *)"hello", 5)); return 0; } @@ -197,6 +199,7 @@ int main(int argc, char **argv) { hexdump("alpn", alpn_ptr, alpn_len); printf("version: %s\n", SSL_get_version(ssl)); + printf("numeric version: %d\n", SSL_version(ssl)); printf("verify-result: %ld\n", SSL_get_verify_result(ssl)); printf("cipher: %s\n", SSL_CIPHER_standard_name(SSL_get_current_cipher(ssl))); printf("SSL_get_servername: %s (%d)\n",