boring2/boring/src/ssl/test/session.rs

187 lines
5.1 KiB
Rust

use std::io::Write;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::OnceLock;
use crate::ssl::test::server::Server;
use crate::ssl::{
ErrorCode, GetSessionPendingError, HandshakeError, Ssl, SslContext, SslContextBuilder,
SslMethod, SslOptions, SslSession, SslSessionCacheMode, SslVersion,
};
#[test]
fn idle_session() {
let ctx = SslContext::builder(SslMethod::tls()).unwrap().build();
let ssl = Ssl::new(&ctx).unwrap();
assert!(ssl.session().is_none());
}
#[test]
fn active_session() {
let server = Server::builder().build();
let s = server.client().connect();
let session = s.ssl().session().unwrap();
let len = session.master_key_len();
let mut buf = vec![0; len - 1];
let copied = session.master_key(&mut buf);
assert_eq!(copied, buf.len());
let mut buf = vec![0; len + 1];
let copied = session.master_key(&mut buf);
assert_eq!(copied, len);
}
#[test]
fn new_get_session_callback() {
static FOUND_SESSION: AtomicBool = AtomicBool::new(false);
static SERVER_SESSION_DER: OnceLock<Vec<u8>> = OnceLock::new();
static CLIENT_SESSION_DER: OnceLock<Vec<u8>> = OnceLock::new();
let mut server = Server::builder();
server.expected_connections_count(2);
server
.ctx()
.set_max_proto_version(Some(SslVersion::TLS1_2))
.unwrap();
server.ctx().set_options(SslOptions::NO_TICKET);
server
.ctx()
.set_session_cache_mode(SslSessionCacheMode::SERVER | SslSessionCacheMode::NO_INTERNAL);
server.ctx().set_new_session_callback(|_, session| {
SERVER_SESSION_DER.set(session.to_der().unwrap()).unwrap()
});
unsafe {
server.ctx().set_get_session_callback(|_, id| {
let Some(der) = SERVER_SESSION_DER.get() else {
return Ok(None);
};
let session = SslSession::from_der(der).unwrap();
FOUND_SESSION.store(true, Ordering::SeqCst);
assert_eq!(id, session.id());
Ok(Some(session))
});
}
server.ctx().set_session_id_context(b"foo").unwrap();
let server = server.build();
let mut client = server.client();
client
.ctx()
.set_session_cache_mode(SslSessionCacheMode::CLIENT);
client.ctx().set_new_session_callback(|_, session| {
CLIENT_SESSION_DER.set(session.to_der().unwrap()).unwrap()
});
let client = client.build();
client.builder().connect();
assert!(CLIENT_SESSION_DER.get().is_some());
assert!(SERVER_SESSION_DER.get().is_some());
assert!(!FOUND_SESSION.load(Ordering::SeqCst));
let mut ssl_builder = client.builder();
unsafe {
ssl_builder
.ssl()
.set_session(&SslSession::from_der(CLIENT_SESSION_DER.get().unwrap()).unwrap())
.unwrap();
}
ssl_builder.connect();
assert!(FOUND_SESSION.load(Ordering::SeqCst));
}
#[test]
fn new_get_session_callback_pending() {
static CALLED_SERVER_CALLBACK: AtomicBool = AtomicBool::new(false);
let mut server = Server::builder();
server
.ctx()
.set_max_proto_version(Some(SslVersion::TLS1_2))
.unwrap();
server.ctx().set_options(SslOptions::NO_TICKET);
server
.ctx()
.set_session_cache_mode(SslSessionCacheMode::SERVER | SslSessionCacheMode::NO_INTERNAL);
unsafe {
server.ctx().set_get_session_callback(|_, _| {
if !CALLED_SERVER_CALLBACK.swap(true, Ordering::SeqCst) {
return Err(GetSessionPendingError);
}
Ok(None)
});
}
server.ctx().set_session_id_context(b"foo").unwrap();
server.err_cb(|error| {
let HandshakeError::WouldBlock(mid_handshake) = error else {
panic!("should be WouldBlock");
};
assert!(mid_handshake.error().would_block());
assert_eq!(mid_handshake.error().code(), ErrorCode::PENDING_SESSION);
let mut socket = mid_handshake.handshake().unwrap();
socket.write_all(&[0]).unwrap();
});
let server = server.build();
let mut client = server.client();
client
.ctx()
.set_session_cache_mode(SslSessionCacheMode::CLIENT);
client.connect();
}
#[test]
fn new_session_callback_swapped_ctx() {
static CALLED_BACK: AtomicBool = AtomicBool::new(false);
let mut server = Server::builder();
server.ctx().set_session_id_context(b"foo").unwrap();
let server = server.build();
let mut client = server.client();
client
.ctx()
.set_session_cache_mode(SslSessionCacheMode::CLIENT | SslSessionCacheMode::NO_INTERNAL);
client
.ctx()
.set_new_session_callback(|_, _| CALLED_BACK.store(true, Ordering::SeqCst));
let mut client = client.build().builder();
let ctx = SslContextBuilder::new(SslMethod::tls()).unwrap().build();
client.ssl().set_ssl_context(&ctx).unwrap();
client.connect();
assert!(CALLED_BACK.load(Ordering::SeqCst));
}
#[test]
fn session_cache_size() {
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_session_cache_size(1234);
let ctx = ctx.build();
assert_eq!(ctx.session_cache_size(), 1234);
}