added tls processing
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing

This commit is contained in:
Jake Hillion 2022-05-23 19:42:07 +01:00
parent 20c2f8d5f7
commit 71888d40e7
3 changed files with 192 additions and 12 deletions

95
Cargo.lock generated
View File

@ -11,6 +11,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
[[package]]
name = "atty"
version = "0.2.14"
@ -28,6 +34,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -61,6 +73,12 @@ dependencies = [
"rustc_version",
]
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -106,6 +124,7 @@ dependencies = [
name = "clone-shim"
version = "0.1.0"
dependencies = [
"anyhow",
"clap 3.1.15",
"close_fds",
"criterion",
@ -116,6 +135,8 @@ dependencies = [
"libc",
"log",
"nix",
"rustls",
"rustls-pemfile",
"serde",
"serde_json",
"tempfile",
@ -427,6 +448,12 @@ dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
[[package]]
name = "oorandom"
version = "11.1.3"
@ -551,6 +578,21 @@ dependencies = [
"winapi",
]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]]
name = "rustc_version"
version = "0.4.0"
@ -560,6 +602,27 @@ dependencies = [
"semver",
]
[[package]]
name = "rustls"
version = "0.20.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033"
dependencies = [
"log",
"ring",
"sct",
"webpki",
]
[[package]]
name = "rustls-pemfile"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9"
dependencies = [
"base64",
]
[[package]]
name = "ryu"
version = "1.0.9"
@ -581,6 +644,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "semver"
version = "1.0.6"
@ -628,6 +701,12 @@ dependencies = [
"serde",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "strsim"
version = "0.10.0"
@ -725,6 +804,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "walkdir"
version = "2.3.2"
@ -800,6 +885,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webpki"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "winapi"
version = "0.3.9"

View File

@ -24,9 +24,12 @@ tempfile = "3.3"
[dev-dependencies]
criterion = "0.3"
anyhow = "1"
# examples/tls
httparse = "1"
rustls = "0.20"
rustls-pemfile = "1"
[[bench]]
name = "clone3"

View File

@ -1,21 +1,29 @@
use std::fs::File;
use std::io::{self, ErrorKind, Read, Write};
use std::io::{self, BufReader, ErrorKind, Read, Write};
use std::net::TcpStream;
use std::os::unix::io::AsRawFd;
use std::os::unix::net::UnixStream;
use std::sync::Arc;
use nix::poll::{poll, PollFd, PollFlags};
use rustls::ServerConnection;
use anyhow::Context;
const BUFFER_SIZE: usize = 4096;
pub(crate) fn handler(
http_trigger_socket: File,
_cert: File,
_key: File,
cert: File,
key: File,
mut stream: TcpStream,
) -> i32 {
let (mut socket, far_socket) = UnixStream::pair().unwrap();
let config = make_config(cert, key);
let mut tls_conn = rustls::ServerConnection::new(config).unwrap();
super::http_handler(&http_trigger_socket, far_socket);
stream.set_nonblocking(true).unwrap();
@ -32,13 +40,13 @@ pub(crate) fn handler(
if let Some(events) = to_poll[0].revents() {
if events.contains(PollFlags::POLLIN) {
handle_encrypted_data(&mut stream, &mut socket).unwrap();
handle_encrypted_data(&mut tls_conn, &mut stream, &mut socket).unwrap();
}
}
if let Some(events) = to_poll[1].revents() {
if events.contains(PollFlags::POLLIN) {
handle_new_data(&mut socket, &mut stream).unwrap();
handle_new_data(&mut tls_conn, &mut socket, &mut stream).unwrap();
}
if events.contains(PollFlags::POLLHUP) {
@ -51,29 +59,61 @@ pub(crate) fn handler(
exitcode::OK
}
fn handle_encrypted_data(stream: &mut impl Read, socket: &mut impl Write) -> io::Result<()> {
let mut buf = [0_u8; BUFFER_SIZE];
fn handle_encrypted_data(
tls_conn: &mut ServerConnection,
stream: &mut (impl Read + Write),
socket: &mut impl Write,
) -> anyhow::Result<()> {
println!("handling newly received encrypted data");
loop {
let read = non_blocking_read(stream, &mut buf)?;
let read = match tls_conn.read_tls(stream) {
Err(e) => {
if e.kind() == ErrorKind::WouldBlock {
0
} else {
return Err(e).context("io error reading from stream");
}
}
Ok(n) => n,
};
if read == 0 {
return Ok(());
}
socket.write_all(&buf[0..read]).unwrap();
let process_result = tls_conn.process_new_packets();
let write_tls_result = tls_conn.write_tls(stream);
let io_state = process_result.context("tls processing failure")?;
write_tls_result.context("tls write failure")?;
if io_state.plaintext_bytes_to_read() > 0 {
let mut reader = tls_conn
.reader()
.take(io_state.plaintext_bytes_to_read() as u64);
std::io::copy(&mut reader, socket)?;
}
}
}
fn handle_new_data(socket: &mut impl Read, stream: &mut impl Write) -> io::Result<()> {
let mut buf = [0_u8; BUFFER_SIZE];
fn handle_new_data(
tls_conn: &mut ServerConnection,
socket: &mut impl Read,
stream: &mut impl Write,
) -> anyhow::Result<()> {
println!("handling new data to encrypt");
let mut buf = [0_u8; BUFFER_SIZE];
loop {
let read = non_blocking_read(socket, &mut buf)?;
if read == 0 {
return Ok(());
}
stream.write_all(&buf[0..read]).unwrap();
tls_conn.writer().write_all(&buf[0..read])?;
tls_conn.write_tls(stream)?;
}
}
@ -89,3 +129,45 @@ fn non_blocking_read(reader: &mut impl io::Read, buf: &mut [u8]) -> io::Result<u
Ok(n) => Ok(n),
}
}
fn make_config(cert: File, key: File) -> Arc<rustls::ServerConfig> {
let certs = load_certs(cert);
let privkey = load_private_key(key);
let config = rustls::ServerConfig::builder()
.with_safe_default_cipher_suites()
.with_safe_default_kx_groups()
.with_safe_default_protocol_versions()
.expect("inconsistent cipher-suites/versions specified")
.with_no_client_auth()
.with_single_cert(certs, privkey)
.expect("bad certificates/private key");
Arc::new(config)
}
fn load_certs(certfile: File) -> Vec<rustls::Certificate> {
let mut reader = BufReader::new(certfile);
rustls_pemfile::certs(&mut reader)
.unwrap()
.iter()
.map(|v| rustls::Certificate(v.clone()))
.collect()
}
fn load_private_key(keyfile: File) -> rustls::PrivateKey {
let mut reader = BufReader::new(keyfile);
loop {
match rustls_pemfile::read_one(&mut reader).expect("cannot parse private key .pem file") {
Some(rustls_pemfile::Item::RSAKey(key)) => return rustls::PrivateKey(key),
Some(rustls_pemfile::Item::PKCS8Key(key)) => return rustls::PrivateKey(key),
Some(rustls_pemfile::Item::ECKey(key)) => return rustls::PrivateKey(key),
None => break,
_ => {}
}
}
panic!("no keys found (encrypted keys not supported)");
}