-
Notifications
You must be signed in to change notification settings - Fork 722
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cc4e4e5
commit 7f6e08b
Showing
6 changed files
with
216 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[package] | ||
name = "serialize" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
bytes = { version = "1"} | ||
s2n-tls = { version = "=0.2.5", path = "../s2n-tls" } | ||
s2n-tls-tokio = { version = "=0.2.5", path = "../s2n-tls-tokio" } | ||
turmoil = { version = "0.6.2" } | ||
tokio = { version = "1" } | ||
anyhow = { version = "1" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
use bytes::{Bytes, BytesMut}; | ||
use s2n_tls::callbacks::ConnectionFuture; | ||
use s2n_tls::config::{Config, ConnectionInitializer}; | ||
use s2n_tls::connection::Connection; | ||
use s2n_tls::enums::{Mode, SerializationVersion}; | ||
use s2n_tls::pool::ConfigPoolBuilder; | ||
use s2n_tls::security; | ||
use s2n_tls_tokio::{TlsAcceptor, TlsConnector, TlsStream}; | ||
use std::net::{IpAddr, Ipv4Addr}; | ||
use std::pin::Pin; | ||
use std::time::Duration; | ||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; | ||
use turmoil::net::{TcpListener, TcpStream}; | ||
use turmoil::{Builder, Result}; | ||
|
||
const WRITE_BEFORE_HANDOFF: bool = true; | ||
|
||
// /// Holds ssl connection bytes for QP to rehydrate SSL session using | ||
// /// s2n config builder's `set_connection_initializer` | ||
struct ConnectionHydrator { | ||
connection_bytes: Bytes, | ||
} | ||
|
||
// impl ConnectionInitializer for ConnectionHydrator { | ||
// fn initialize_connection( | ||
// &self, | ||
// connection: &mut Connection, | ||
// ) -> anyhow::Result<Option<Pin<Box<dyn ConnectionFuture>>>, s2n_tls::error::Error> { | ||
// connection.deserialize(&self.connection_bytes)?; | ||
// Ok(None) | ||
// } | ||
// } | ||
|
||
fn get_default_tls_config() -> Config { | ||
let mut builder = Config::builder(); | ||
unsafe { builder.disable_x509_verification().unwrap() }; | ||
builder.set_security_policy(&security::DEFAULT).unwrap(); | ||
builder | ||
.set_serialization_version(SerializationVersion::V1) | ||
.unwrap(); | ||
builder.with_system_certs(true).unwrap(); | ||
pub static CERT_PEM: &[u8] = include_bytes!(concat!( | ||
env!("CARGO_MANIFEST_DIR"), | ||
"/../s2n-tls-tokio/examples/certs/cert_rsa.pem" | ||
)); | ||
pub static KEY_PEM: &[u8] = include_bytes!(concat!( | ||
env!("CARGO_MANIFEST_DIR"), | ||
"/../s2n-tls-tokio/examples/certs/key_rsa.pem" | ||
)); | ||
builder.load_pem(CERT_PEM, KEY_PEM).unwrap(); | ||
builder.build().unwrap() | ||
} | ||
|
||
#[test] | ||
fn s2n_session_transfer() -> Result { | ||
let mut sim = Builder::new().enable_tokio_io().build(); | ||
|
||
sim.host("upstream", || async { | ||
// Connect to Relay via TLS | ||
let relay_tcp = TcpStream::connect(("relay", 1994)).await?; | ||
let config = get_default_tls_config(); | ||
let connector = TlsConnector::new(config); | ||
let mut relay_tls = connector.connect("relay", relay_tcp).await?; | ||
// Talk with Relay a bit | ||
if WRITE_BEFORE_HANDOFF { | ||
assert_write_i32(&mut relay_tls, 100, 0).await; | ||
assert_read_i32(&mut relay_tls, 101, 0).await; | ||
} | ||
// Write an int and increment it as it passes back and forth | ||
for i in 0..5 { | ||
assert_write_i32(&mut relay_tls, i * 2, 0).await; | ||
assert_read_i32(&mut relay_tls, i * 2 + 1, 0).await; | ||
} | ||
|
||
// Wait a bit for downstream to wrap up before closing | ||
tokio::time::sleep(Duration::from_secs(1)).await; | ||
|
||
Ok(()) | ||
}); | ||
|
||
sim.host("downstream", || async { | ||
// Connect from Relay | ||
let listener = TcpListener::bind((IpAddr::from(Ipv4Addr::UNSPECIFIED), 1995)).await?; | ||
let (mut relay_tcp, _) = listener.accept().await?; | ||
// Receive and deserialize upstream TLS connection | ||
let len = relay_tcp.read_i32().await?; | ||
let mut upstream_conn_buf = vec![0; len as usize]; | ||
relay_tcp.read_exact(&mut upstream_conn_buf).await?; | ||
let connection_bytes = Bytes::from(upstream_conn_buf); | ||
// let upstream_conn = ConnectionHydrator { connection_bytes }; | ||
// // Connect from Relay via assumed upstream TLS connection | ||
// let mut builder = Config::builder(); | ||
// builder.set_security_policy(&security::DEFAULT_TLS13)?; | ||
// builder.set_connection_initializer(upstream_conn)?; | ||
// let config = builder.build()?; | ||
// let acceptor = TlsAcceptor::new(config); | ||
let mut s2n_server = s2n_tls::connection::Connection::new(Mode::Server); | ||
s2n_server.deserialize(&connection_bytes)?; | ||
let mut relay_tls = TlsStream::new(s2n_server, relay_tcp)?; | ||
//let mut relay_tls = acceptor.accept(relay_tcp).await?; | ||
// Read an int and increment it as it passes back and forth | ||
for i in 0..5 { | ||
assert_read_i32(&mut relay_tls, i * 2, 2).await; | ||
assert_write_i32(&mut relay_tls, i * 2 + 1, 2).await; | ||
} | ||
|
||
// Wait a bit for upstream to wrap up before closing | ||
tokio::time::sleep(Duration::from_secs(1)).await; | ||
|
||
Ok(()) | ||
}); | ||
|
||
sim.client("relay", async { | ||
// Accept TLS connection from upstream | ||
let listener = TcpListener::bind((IpAddr::from(Ipv4Addr::UNSPECIFIED), 1994)).await?; | ||
let (upstream_tcp, _) = listener.accept().await?; | ||
let config = get_default_tls_config(); | ||
let pool = ConfigPoolBuilder::new(Mode::Server, config).build(); | ||
let acceptor = TlsAcceptor::new(pool); | ||
let mut upstream_tls = acceptor.accept(upstream_tcp).await?; | ||
// Chat with upstream a bit | ||
if WRITE_BEFORE_HANDOFF { | ||
assert_read_i32(&mut upstream_tls, 100, 1).await; | ||
assert_write_i32(&mut upstream_tls, 101, 1).await; | ||
} | ||
// Serialize upstream TLS connection and write to downstream before wiping connection | ||
let connection_len = upstream_tls.as_mut().serialization_length()?; | ||
let mut connection_buf = vec![0; connection_len]; | ||
upstream_tls.as_mut().serialize(&mut connection_buf)?; | ||
upstream_tls.as_mut().wipe()?; | ||
|
||
// Connect to downstream and send serialized upstream TLS connection | ||
let mut downstream_tcp = TcpStream::connect(("downstream", 1995)).await?; | ||
downstream_tcp.write_i32(connection_len as i32).await?; | ||
downstream_tcp.write_all(connection_buf.as_slice()).await?; | ||
|
||
let mut from_upstream = BytesMut::new(); | ||
let mut from_downstream = BytesMut::new(); | ||
|
||
loop { | ||
tokio::select! { | ||
res = upstream_tls.get_mut().read_buf(&mut from_upstream) => { | ||
let n = res?; | ||
if n == 0 { | ||
break; | ||
} | ||
downstream_tcp.write_all_buf(&mut from_upstream).await?; | ||
}, | ||
res = downstream_tcp.read_buf(&mut from_downstream) => { | ||
let n = res?; | ||
if n == 0 { | ||
break; | ||
} | ||
upstream_tls.get_mut().write_all_buf(&mut from_downstream).await?; | ||
} | ||
} | ||
} | ||
|
||
Ok(()) | ||
}); | ||
|
||
sim.run() | ||
} | ||
|
||
async fn assert_write_i32<S>(tls: &mut S, data: i32, source: i32) | ||
where | ||
S: AsyncRead + AsyncWrite + Unpin, | ||
{ | ||
println!("{:?} is writing {:?}", source, data); | ||
if let Err(e) = tls.write_i32(data).await { | ||
panic!("failed to write i32={data} with error {e:?}"); | ||
} | ||
} | ||
|
||
async fn assert_read_i32<S>(tls: &mut S, expected: i32, source: i32) | ||
where | ||
S: AsyncRead + AsyncWrite + Unpin, | ||
{ | ||
println!("{:?} is reading {:?}", source, expected); | ||
match tls.read_i32().await { | ||
Ok(data) => { | ||
assert_eq!(data, expected); | ||
println!("{:?} read {:?}", source, data); | ||
} | ||
Err(e) => { | ||
panic!( | ||
"{:?} failed to read i32 (expected={expected}) with error {e:?}", | ||
source | ||
); | ||
} | ||
} | ||
} |