diff --git a/README.md b/README.md index c29320e..4ba51d8 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,16 @@ To run this example: cargo build --example pipes target/debug/clone-shim -s examples/pipes/spec.json target/debug/examples/pipes +### examples/pipes + +The pipes example shows some of the power of the shim by using pipes. The process "pipe_sender" sends two messages down a pipe that it's given by the shim. These two messages each spawn a completely isolated process, "pipe_receiver", that receives that message. + +To run this example: + + cargo build + cargo build --example tls + target/debug/clone-shim -s examples/tls/spec.json target/debug/examples/tls + ## Debugging the shim The shim can be debugged as with most processes, but it is exceptionally forky. Breaking before a clone in `rust-gdb` then running `set follow-fork-mode child` is often necessary. The best approach is to go in with a plan of attack. diff --git a/examples/tls/main.rs b/examples/tls/main.rs index 0087586..dda71b4 100644 --- a/examples/tls/main.rs +++ b/examples/tls/main.rs @@ -1,4 +1,5 @@ mod http; +mod tls; use std::fs::File; use std::net::{TcpListener, TcpStream}; @@ -7,6 +8,7 @@ fn main() { match std::env::args().next() { Some(s) => match s.as_str() { "connection_listener" => connection_listener_entrypoint(), + "tls_handler" => tls_handler_entrypoint(), "http_handler" => http_handler_entrypoint(), _ => unimplemented!(), @@ -24,12 +26,12 @@ fn connection_listener_entrypoint() { let _entrypoint = args.next(); - let http_handler_trigger = args.next(); - let http_handler_trigger: RawFd = http_handler_trigger - .expect("request handler required") + let tls_handler_trigger = args.next(); + let tls_handler_trigger: RawFd = tls_handler_trigger + .expect("tls handler trigger required") .parse() - .expect("tcp listener should be a file descriptor"); - let http_handler_trigger = unsafe { File::from_raw_fd(http_handler_trigger) }; + .expect("tls handler trigger should be a file descriptor"); + let tls_handler_trigger = unsafe { File::from_raw_fd(tls_handler_trigger) }; let tcp_listener = args.next(); let tcp_listener: RawFd = tcp_listener @@ -39,7 +41,7 @@ fn connection_listener_entrypoint() { let tcp_listener = unsafe { TcpListener::from_raw_fd(tcp_listener) }; // actual function body - fn connection_listener(http_handler_trigger: File, tcp_listener: TcpListener) -> i32 { + fn connection_listener(tls_handler_trigger: File, tcp_listener: TcpListener) -> i32 { println!("connection_listener entered"); // handle incoming connections @@ -53,14 +55,78 @@ fn connection_listener_entrypoint() { }; println!("received a new connection"); - http_handler(&http_handler_trigger, stream); + tls_handler(&tls_handler_trigger, stream); } exitcode::OK } // run function - std::process::exit(connection_listener(http_handler_trigger, tcp_listener)); + std::process::exit(connection_listener(tls_handler_trigger, tcp_listener)); +} + +fn tls_handler(trigger_socket: &File, stream: TcpStream) { + // imports + use nix::sys::socket::{sendmsg, ControlMessage, MsgFlags}; + use std::os::unix::io::AsRawFd; + + // send file descriptor(s) + let sockfd = trigger_socket.as_raw_fd(); + let fds = [stream.as_raw_fd()]; + + sendmsg::<()>( + sockfd, + &[], + &[ControlMessage::ScmRights(&fds)], + MsgFlags::empty(), + None, + ) + .unwrap(); +} + +fn tls_handler_entrypoint() { + // imports + use std::os::unix::io::{FromRawFd, RawFd}; + + // argument parsing + let mut args = std::env::args(); + + let _entrypoint = args.next(); + + let http_handler_trigger = args.next(); + let http_handler_trigger: RawFd = http_handler_trigger + .expect("http handler trigger required") + .parse() + .expect("http handler trigger should be a file descriptor"); + let http_handler_trigger = unsafe { File::from_raw_fd(http_handler_trigger) }; + + let tls_cert_file = args.next(); + let tls_cert_file: RawFd = tls_cert_file + .expect("tls cert file required") + .parse() + .expect("tls cert file should be a file descriptor"); + let tls_cert_file = unsafe { File::from_raw_fd(tls_cert_file) }; + + let tls_key_file = args.next(); + let tls_key_file: RawFd = tls_key_file + .expect("tls key file required") + .parse() + .expect("tls key file should be a file descriptor"); + let tls_key_file = unsafe { File::from_raw_fd(tls_key_file) }; + + let stream = args.next(); + let stream: RawFd = stream + .expect("request stream required") + .parse() + .expect("request stream should be a file descriptor"); + let stream = unsafe { TcpStream::from_raw_fd(stream) }; + + std::process::exit(tls::handler( + http_handler_trigger, + tls_cert_file, + tls_key_file, + stream, + )); } fn http_handler(trigger_socket: &File, stream: TcpStream) { diff --git a/examples/tls/spec.json b/examples/tls/spec.json index 6a4817f..72bd86d 100644 --- a/examples/tls/spec.json +++ b/examples/tls/spec.json @@ -1,6 +1,44 @@ { "entrypoints": { "connection_listener": { + "args": [ + "Entrypoint", + { + "FileSocket": { + "Tx": "tls" + } + }, + { + "TcpListener": { + "addr": "0.0.0.0:8443" + } + } + ], + "environment": [ + { + "Filesystem": { + "host_path": "/lib/x86_64-linux-gnu/libgcc_s.so.1", + "environment_path": "/lib/libgcc_s.so.1" + } + }, + { + "Filesystem": { + "host_path": "/lib/x86_64-linux-gnu/libc.so.6", + "environment_path": "/lib/libc.so.6" + } + }, + { + "Filesystem": { + "host_path": "/lib64/ld-linux-x86-64.so.2", + "environment_path": "/lib64/ld-linux-x86-64.so.2" + } + } + ] + }, + "tls_handler": { + "trigger": { + "FileSocket": "tls" + }, "args": [ "Entrypoint", { @@ -9,10 +47,12 @@ } }, { - "TcpListener": { - "addr": "0.0.0.0:8443" - } - } + "File": "/etc/ssl/certs/example.com.pem" + }, + { + "File": "/etc/ssl/private/example.com.key" + }, + "Trigger" ], "environment": [ { diff --git a/examples/tls/tls.rs b/examples/tls/tls.rs new file mode 100644 index 0000000..74bf5aa --- /dev/null +++ b/examples/tls/tls.rs @@ -0,0 +1,12 @@ +use std::fs::File; +use std::net::TcpStream; + +pub(crate) fn handler( + http_trigger_socket: File, + _cert: File, + _key: File, + stream: TcpStream, +) -> i32 { + super::http_handler(&http_trigger_socket, stream); + exitcode::OK +}