187 lines
5.1 KiB
Rust
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);
|
|
}
|