From d84c16423cf4568e4222afc05b57b1f1ad0c59fc Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 2 May 2024 13:38:48 +0100 Subject: [PATCH 01/10] Extend testing to cover ubuntu 24.04 Correct killing of docker process using `--init`. --- rustls-libssl/Makefile | 18 ++++++++++++++++-- .../dist/test/deb-ubuntu-22/run-test.sh | 2 +- .../dist/test/deb-ubuntu-24/Dockerfile | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 rustls-libssl/dist/test/deb-ubuntu-24/Dockerfile 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/dist/test/deb-ubuntu-22/run-test.sh b/rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh index 6ac2310..e51d89a 100755 --- a/rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh +++ b/rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh @@ -3,7 +3,7 @@ set -e TAG="$1" -docker run --interactive --publish 8443:443 "$TAG" & +docker run --init --interactive --publish 8443:443 "$TAG" & DOCKER_ID=$! sleep 2 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;' From 95a0003b44d2f2b908dd02bc805c3f77478b8c26 Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 2 May 2024 14:34:56 +0100 Subject: [PATCH 02/10] Prepare to support mutability for SSL_SESSION objects --- rustls-libssl/src/cache.rs | 101 +++++++++++++++++++-------- rustls-libssl/src/callbacks.rs | 7 +- rustls-libssl/src/entry.rs | 10 +-- rustls-libssl/src/lib.rs | 6 +- rustls-libssl/src/not_thread_safe.rs | 30 ++++++++ 5 files changed, 113 insertions(+), 41 deletions(-) diff --git a/rustls-libssl/src/cache.rs b/rustls-libssl/src/cache.rs index 8371117..fce46fa 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,31 @@ 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, time_out, + ))) } /// 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 +279,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 +289,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 +325,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 +338,7 @@ impl ServerSessionStorage { ); } } else { - items.retain(|item| !item.expired(at_time)); + items.retain(|item| !item.get().expired(at_time)); } } } @@ -345,8 +352,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().expiry_time.0); if let Some(oldest) = oldest.cloned() { items.take(&oldest); } @@ -381,7 +388,7 @@ impl CacheParameters { #[derive(Debug)] pub struct SingleServerCache { parent: Arc, - most_recent_session: Mutex>>, + most_recent_session: Mutex>>>, } impl SingleServerCache { @@ -396,13 +403,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 +459,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 +468,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 +490,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 +502,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 @@ -571,7 +578,13 @@ 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![], + ExpiryTime(10 + i as u64) + )) + .into() )); } @@ -591,7 +604,13 @@ 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![], + ExpiryTime(10 + i as u64) + )) + .into() )); } @@ -608,7 +627,13 @@ 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![], + ExpiryTime(10 + i as u64) + )) + .into() )); } @@ -619,7 +644,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![], ExpiryTime(16))).into() + )); assert!(cache.find_by_id(&[1]).is_none()); assert!(cache.find_by_id(&[2]).is_none()); @@ -634,10 +661,24 @@ 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(), + ExpiryTime(10) + )) + .into() + )); + assert!(cache.insert( + NotThreadSafe::new(SslSession::new( + vec![2], + vec![], + b"goodbye".to_vec(), + ExpiryTime(10) + )) + .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..57b5f1e 100644 --- a/rustls-libssl/src/entry.rs +++ b/rustls-libssl/src/entry.rs @@ -1531,7 +1531,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() } @@ -1576,14 +1576,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 +1604,7 @@ entry! { impl Castable for SSL_SESSION { type Ownership = OwnershipArc; - type RustType = SSL_SESSION; + type RustType = NotThreadSafe; } /// Normal OpenSSL return value convention success indicator. @@ -2118,7 +2118,7 @@ mod tests { vec![3; 128], crate::cache::ExpiryTime(123), ); - 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..f5c131f 100644 --- a/rustls-libssl/src/lib.rs +++ b/rustls-libssl/src/lib.rs @@ -355,9 +355,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 } } @@ -1398,7 +1398,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 {} From d9067b4493a66bdc48a101beda7692a88c1eb40a Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 2 May 2024 14:59:20 +0100 Subject: [PATCH 03/10] Support SSL_SESSION time manipulation functions --- rustls-libssl/MATRIX.md | 8 +++--- rustls-libssl/build.rs | 4 +++ rustls-libssl/src/cache.rs | 30 ++++++++++++++--------- rustls-libssl/src/entry.rs | 37 +++++++++++++++++++++++++++- rustls-libssl/src/lib.rs | 47 ++++++++++++++++++++++++++---------- rustls-libssl/tests/server.c | 1 + 6 files changed, 98 insertions(+), 29 deletions(-) diff --git a/rustls-libssl/MATRIX.md b/rustls-libssl/MATRIX.md index aa5f0bb..cade57a 100644 --- a/rustls-libssl/MATRIX.md +++ b/rustls-libssl/MATRIX.md @@ -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` | | | | @@ -250,8 +250,8 @@ | `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] | | | | diff --git a/rustls-libssl/build.rs b/rustls-libssl/build.rs index d676daf..4b1b91b 100644 --- a/rustls-libssl/build.rs +++ b/rustls-libssl/build.rs @@ -159,7 +159,11 @@ const ENTRYPOINTS: &[&str] = &[ "SSL_select_next_proto", "SSL_SESSION_free", "SSL_SESSION_get_id", + "SSL_SESSION_get_time", + "SSL_SESSION_get_timeout", "SSL_session_reused", + "SSL_SESSION_set_time", + "SSL_SESSION_set_timeout", "SSL_SESSION_up_ref", "SSL_set0_rbio", "SSL_set0_wbio", diff --git a/rustls-libssl/src/cache.rs b/rustls-libssl/src/cache.rs index fce46fa..42f0563 100644 --- a/rustls-libssl/src/cache.rs +++ b/rustls-libssl/src/cache.rs @@ -239,9 +239,12 @@ impl ServerSessionStorage { 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(NotThreadSafe::new(SslSession::new( - id, value, context, time_out, + id, + value, + context, + TimeBase::now(), + self.get_timeout(), ))) } @@ -353,7 +356,7 @@ impl ServerSessionStorage { } fn flush_oldest(items: &mut BTreeSet>>) { - let oldest = items.iter().min_by_key(|item| item.get().expiry_time.0); + let oldest = items.iter().min_by_key(|item| item.get().creation_time.0); if let Some(oldest) = oldest.cloned() { items.take(&oldest); } @@ -545,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)) } @@ -555,7 +558,7 @@ impl ExpiryTime { } #[derive(Debug, Clone, Copy)] -pub struct TimeBase(u64); +pub struct TimeBase(pub u64); impl TimeBase { pub fn now() -> Self { @@ -582,7 +585,8 @@ mod tests { vec![i], vec![], vec![], - ExpiryTime(10 + i as u64) + TimeBase(i as u64), + 10 )) .into() )); @@ -608,7 +612,8 @@ mod tests { vec![i], vec![], vec![], - ExpiryTime(10 + i as u64) + TimeBase(i as u64), + 10 )) .into() )); @@ -631,7 +636,8 @@ mod tests { vec![i], vec![], vec![], - ExpiryTime(10 + i as u64) + TimeBase(i as u64), + 10 )) .into() )); @@ -645,7 +651,7 @@ mod tests { cache.set_size(4); assert!(cache.insert( - NotThreadSafe::new(SslSession::new(vec![6], vec![], vec![], ExpiryTime(16))).into() + NotThreadSafe::new(SslSession::new(vec![6], vec![], vec![], TimeBase(6), 10)).into() )); assert!(cache.find_by_id(&[1]).is_none()); @@ -666,7 +672,8 @@ mod tests { vec![1], vec![], b"hello".to_vec(), - ExpiryTime(10) + TimeBase(5), + 5, )) .into() )); @@ -675,7 +682,8 @@ mod tests { vec![2], vec![], b"goodbye".to_vec(), - ExpiryTime(10) + TimeBase(5), + 5 )) .into() )); diff --git a/rustls-libssl/src/entry.rs b/rustls-libssl/src/entry.rs index 57b5f1e..b106332 100644 --- a/rustls-libssl/src/entry.rs +++ b/rustls-libssl/src/entry.rs @@ -1545,6 +1545,40 @@ 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 _d2i_SSL_SESSION( a: *mut *mut SSL_SESSION, @@ -2116,7 +2150,8 @@ 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(NotThreadSafe::new(sess)); diff --git a/rustls-libssl/src/lib.rs b/rustls-libssl/src/lib.rs index f5c131f..53a117b 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,24 @@ 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 set_time_out(&mut self, time_out_secs: u64) { + self.time_out = time_out_secs; } - pub fn older_than(&self, other: &Self) -> bool { - self.expiry_time.0 < other.expiry_time.0 + pub fn expired(&self, at_time: cache::TimeBase) -> bool { + cache::ExpiryTime::calculate(self.creation_time, self.time_out).in_past(at_time) } } @@ -365,7 +385,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() } } diff --git a/rustls-libssl/tests/server.c b/rustls-libssl/tests/server.c index 747a18e..554f696 100644 --- a/rustls-libssl/tests/server.c +++ b/rustls-libssl/tests/server.c @@ -76,6 +76,7 @@ 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))); return 0; } From 97689d995f2192f6746c4b0438ec1f21f606bf7b Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 2 May 2024 15:23:24 +0100 Subject: [PATCH 04/10] Implement `SSL_SESSION_set1_id_context` Ensure limitations on ID contexts are applied. --- rustls-libssl/MATRIX.md | 2 +- rustls-libssl/build.rs | 1 + rustls-libssl/src/entry.rs | 20 ++++++++++++++++++++ rustls-libssl/src/lib.rs | 4 ++++ rustls-libssl/tests/server.c | 1 + 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/rustls-libssl/MATRIX.md b/rustls-libssl/MATRIX.md index cade57a..d26342e 100644 --- a/rustls-libssl/MATRIX.md +++ b/rustls-libssl/MATRIX.md @@ -243,7 +243,7 @@ | `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` | | | | diff --git a/rustls-libssl/build.rs b/rustls-libssl/build.rs index 4b1b91b..5b4da4a 100644 --- a/rustls-libssl/build.rs +++ b/rustls-libssl/build.rs @@ -162,6 +162,7 @@ const ENTRYPOINTS: &[&str] = &[ "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", diff --git a/rustls-libssl/src/entry.rs b/rustls-libssl/src/entry.rs index b106332..0d36455 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); @@ -1579,6 +1582,21 @@ entry! { } } +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, @@ -1649,6 +1667,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 { diff --git a/rustls-libssl/src/lib.rs b/rustls-libssl/src/lib.rs index 53a117b..ceec0be 100644 --- a/rustls-libssl/src/lib.rs +++ b/rustls-libssl/src/lib.rs @@ -350,6 +350,10 @@ impl SslSession { 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) } diff --git a/rustls-libssl/tests/server.c b/rustls-libssl/tests/server.c index 554f696..0bf6391 100644 --- a/rustls-libssl/tests/server.c +++ b/rustls-libssl/tests/server.c @@ -77,6 +77,7 @@ static int sess_new_callback(SSL *ssl, SSL_SESSION *sess) { 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; } From ab97862ff45ae70d30310896ba80921f2e531259 Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 2 May 2024 15:45:11 +0100 Subject: [PATCH 05/10] Implement `SSL_get_SSL_CTX` --- rustls-libssl/MATRIX.md | 2 +- rustls-libssl/build.rs | 1 + rustls-libssl/src/entry.rs | 6 ++++++ rustls-libssl/tests/client.c | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/rustls-libssl/MATRIX.md b/rustls-libssl/MATRIX.md index d26342e..a7d6781 100644 --- a/rustls-libssl/MATRIX.md +++ b/rustls-libssl/MATRIX.md @@ -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: | diff --git a/rustls-libssl/build.rs b/rustls-libssl/build.rs index 5b4da4a..95d6f06 100644 --- a/rustls-libssl/build.rs +++ b/rustls-libssl/build.rs @@ -141,6 +141,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", diff --git a/rustls-libssl/src/entry.rs b/rustls-libssl/src/entry.rs index 0d36455..e88243f 100644 --- a/rustls-libssl/src/entry.rs +++ b/rustls-libssl/src/entry.rs @@ -757,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) { diff --git a/rustls-libssl/tests/client.c b/rustls-libssl/tests/client.c index ab8416c..6b3c672 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", From 918741a1190ffe2ffe651fed037d94d201a5e572 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Thu, 2 May 2024 09:56:16 -0400 Subject: [PATCH 06/10] Implement `SSL_version` Similar to the already implemented `SSL_get_version()`, but returning the IANA registered protocol identifier constant as an `int`, instead of its name as a `*char`. --- rustls-libssl/MATRIX.md | 2 +- rustls-libssl/build.rs | 1 + rustls-libssl/src/entry.rs | 13 +++++++++++++ rustls-libssl/tests/client.c | 1 + rustls-libssl/tests/server.c | 1 + 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/rustls-libssl/MATRIX.md b/rustls-libssl/MATRIX.md index a7d6781..f588b7c 100644 --- a/rustls-libssl/MATRIX.md +++ b/rustls-libssl/MATRIX.md @@ -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/build.rs b/rustls-libssl/build.rs index 95d6f06..d74b47e 100644 --- a/rustls-libssl/build.rs +++ b/rustls-libssl/build.rs @@ -189,6 +189,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/src/entry.rs b/rustls-libssl/src/entry.rs index e88243f..5c64a81 100644 --- a/rustls-libssl/src/entry.rs +++ b/rustls-libssl/src/entry.rs @@ -1172,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() diff --git a/rustls-libssl/tests/client.c b/rustls-libssl/tests/client.c index 6b3c672..2d16e30 100644 --- a/rustls-libssl/tests/client.c +++ b/rustls-libssl/tests/client.c @@ -123,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 0bf6391..9e80647 100644 --- a/rustls-libssl/tests/server.c +++ b/rustls-libssl/tests/server.c @@ -199,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", From 2e9cb8d0b469749f89194a98f3d872df604b631d Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Thu, 2 May 2024 10:25:58 -0400 Subject: [PATCH 07/10] Stub out SSL_CONF_XXX fns --- rustls-libssl/MATRIX.md | 14 +++++++------- rustls-libssl/build.rs | 7 +++++++ rustls-libssl/src/entry.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/rustls-libssl/MATRIX.md b/rustls-libssl/MATRIX.md index f588b7c..6c3001c 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` | | | | diff --git a/rustls-libssl/build.rs b/rustls-libssl/build.rs index d74b47e..dbc8ade 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", diff --git a/rustls-libssl/src/entry.rs b/rustls-libssl/src/entry.rs index 5c64a81..3f2efee 100644 --- a/rustls-libssl/src/entry.rs +++ b/rustls-libssl/src/entry.rs @@ -1944,6 +1944,38 @@ 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; + // --------------------- #[cfg(test)] From 55f2c39f075ce87404c6a8a483ae6502573a5f38 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Thu, 2 May 2024 11:10:47 -0400 Subject: [PATCH 08/10] Stub out `SSL_sendfile` --- rustls-libssl/MATRIX.md | 2 +- rustls-libssl/build.rs | 1 + rustls-libssl/src/entry.rs | 12 ++++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/rustls-libssl/MATRIX.md b/rustls-libssl/MATRIX.md index 6c3001c..65c90e1 100644 --- a/rustls-libssl/MATRIX.md +++ b/rustls-libssl/MATRIX.md @@ -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: | diff --git a/rustls-libssl/build.rs b/rustls-libssl/build.rs index dbc8ade..58f1f8f 100644 --- a/rustls-libssl/build.rs +++ b/rustls-libssl/build.rs @@ -165,6 +165,7 @@ 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", diff --git a/rustls-libssl/src/entry.rs b/rustls-libssl/src/entry.rs index 3f2efee..bfa4c47 100644 --- a/rustls-libssl/src/entry.rs +++ b/rustls-libssl/src/entry.rs @@ -1976,6 +1976,18 @@ entry_stub! { 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)] From b0c771d37b86f744772d0546dc95198f39208cd7 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Thu, 2 May 2024 10:35:43 -0400 Subject: [PATCH 09/10] dist: more aggressive docker stop Trying to avoid a second test instance run after the first encountering an error of the form: ``` Bind for 0.0.0.0:8443 failed: port is already allocated. ``` --- rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 e51d89a..4e2a778 100755 --- a/rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh +++ b/rustls-libssl/dist/test/deb-ubuntu-22/run-test.sh @@ -3,11 +3,11 @@ set -e TAG="$1" -docker run --init --interactive --publish 8443:443 "$TAG" & -DOCKER_ID=$! +docker run --interactive --publish 8443:443 "$TAG" & 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") From 7e2202dda1d420d5f73a23dae29c9d2279faa46b Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Thu, 2 May 2024 16:44:18 +0100 Subject: [PATCH 10/10] Avoid using lsb_release This is from an optional package. Instead rely on sh and /etc/lsb-release. --- rustls-libssl/dist/bin/rustls-libssl-nginx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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")