Skip to content

Commit

Permalink
example(bindings): client hello cb example (#4385)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmayclin authored Mar 27, 2024
1 parent e1f6f01 commit ba825b8
Show file tree
Hide file tree
Showing 14 changed files with 420 additions and 1 deletion.
21 changes: 20 additions & 1 deletion .github/workflows/ci_rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ on:
env:
# Pin the nightly toolchain to prevent breakage.
# This should be occasionally updated.
RUST_NIGHTLY_TOOLCHAIN: nightly-2022-08-03
RUST_NIGHTLY_TOOLCHAIN: nightly-2024-01-01
ROOT_PATH: bindings/rust
EXAMPLE_WORKSPACE: bindings/rust-examples

jobs:
generate:
Expand Down Expand Up @@ -78,6 +79,24 @@ jobs:
- name: bench tests
working-directory: ${{env.ROOT_PATH}}/bench
run: cargo test

s2n-tls-binding-examples:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: actions-rs/toolchain@v1
id: toolchain
with:
toolchain: stable
override: true

- name: generate bindings
run: ${{env.ROOT_PATH}}/generate.sh --skip-tests

- name: build examples
working-directory: ${{env.EXAMPLE_WORKSPACE}}
run: cargo build

generate-openssl-102:
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions bindings/rust-examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*target/
*Cargo.lock
12 changes: 12 additions & 0 deletions bindings/rust-examples/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[workspace]
members = [
"client-hello-config-resolution",
]
resolver = "2"

[workspace.package]
version = "0.0.1"
authors = ["AWS s2n"]
publish = false
license = "Apache-2.0"
edition = "2021"
13 changes: 13 additions & 0 deletions bindings/rust-examples/client-hello-config-resolution/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "client-hello-config-resolution"
version.workspace = true
authors.workspace = true
publish.workspace = true
license.workspace = true
edition.workspace = true

[dependencies]
clap = { version = "4", features = ["derive"] }
s2n-tls = { path = "../../rust/s2n-tls" }
s2n-tls-tokio = { path = "../../rust/s2n-tls-tokio" }
tokio = { version = "1", features = ["full"] }
43 changes: 43 additions & 0 deletions bindings/rust-examples/client-hello-config-resolution/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
This example shows how to use the s2n-tls client hello callback to configure different TLS configs based on the Server Name Indication (SNI) in the client hello. The [server](src/bin/server.rs) sets up two configs for two different sni's, `www.wombat.com` and `www.kangaroo.com`. These configs are set up with different cipher preferences so that the allowed TLS versions are dependent on the client SNI.

To run this example, first start the server in one terminal
```
cargo run --bin server
```
Then run the client in another terminal, setting the appropriate SNI.

### Kangaroo SNI
```
cargo run --bin client www.kangaroo.com
```
```
TlsStream {
connection: Connection {
handshake_type: "NEGOTIATED|FULL_HANDSHAKE|MIDDLEBOX_COMPAT",
cipher_suite: "TLS_AES_128_GCM_SHA256",
actual_protocol_version: TLS13,
selected_curve: "x25519",
..
},
}
The server said Hello, you are speaking to www.kangaroo.com
```
We can see that the server successfully responded with the appropriate `www.kangaroo.com` certificate, resulting in a successful handshake.

### Wombat SNI
```
cargo run --bin client www.wombat.com
```
```
TlsStream {
connection: Connection {
handshake_type: "NEGOTIATED|FULL_HANDSHAKE|TLS12_PERFECT_FORWARD_SECRECY",
cipher_suite: "ECDHE-ECDSA-AES128-SHA",
actual_protocol_version: TLS12,
selected_curve: "secp256r1",
..
},
}
The server said Hello, you are speaking to www.wombat.com
```
Once again there is a successful handshake showing that the server responded with the proper certificate. In this case, the config that the server configured for `www.wombat.com` did not support TLS 1.3, so the TLS 1.2 was negotiated instead.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIB3DCCAWKgAwIBAgIUaAjZTaFhJNRyFtFQut1CdrY7RH0wCgYIKoZIzj0EAwMw
HDELMAkGA1UEBhMCVVMxDTALBgNVBAMMBHJvb3QwIBcNMjQwMTI3MDAwODQ4WhgP
MjIwMzA3MDQwMDA4NDhaMBwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQDDARyb290MHYw
EAYHKoZIzj0CAQYFK4EEACIDYgAEclmOmfFLoQR+mupZSc7J3IfZ6OV0IphUHWwv
iH9BvkGh4OX+RZfafa4hw90A5fk0ps520Dt04tHwotLBNkdQcWDJunOhw8ydebIP
TaP0V8OgxFs+P4kpBkMVNB3H+PK6o2MwYTAdBgNVHQ4EFgQU2ic6pZKpiyOr5aPt
YhABB9hJC5QwHwYDVR0jBBgwFoAU2ic6pZKpiyOr5aPtYhABB9hJC5QwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwCgYIKoZIzj0EAwMDaAAwZQIxAMtZ
+QqC0LGdqUxdr2woMr6pUNAaZYaxm6APPqyKsjVqNaKadiSueNbbbc+seKJXbwIw
Zl0HNHzmoNAMkpgx5BCukjL1v07C571diSW4Z/P96t8tUzi/2rUOoFlJYU0B8cib
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env bash

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

# immediately bail if any command fails
set -e

echo "generating CA"
openssl req -new -noenc -x509 \
-newkey ec \
-pkeyopt ec_paramgen_curve:P-384 \
-keyout ca-key.pem \
-out ca-cert.pem \
-days 65536 \
-SHA384 \
-subj "/C=US/CN=root" \
-addext "basicConstraints = critical,CA:true" \
-addext "keyUsage = critical,keyCertSign"

echo "generating wombat private key and CSR"
openssl req -new -noenc \
-newkey ec \
-pkeyopt ec_paramgen_curve:P-384 \
-keyout wombat-key.pem \
-out wombat.csr \
-subj "/C=US/CN=wombat" \
-addext "subjectAltName = DNS:www.wombat.com"

echo "generating kangaroo private key and CSR"
openssl req -new -noenc \
-newkey ec \
-pkeyopt ec_paramgen_curve:P-384 \
-keyout kangaroo-key.pem \
-out kangaroo.csr \
-subj "/C=US/CN=kangaroo" \
-addext "subjectAltName = DNS:www.kangaroo.com"

echo "generating wombat server certificate and signing it"
openssl x509 -days 65536 \
-req -in wombat.csr \
-SHA384 \
-CA ca-cert.pem \
-CAkey ca-key.pem \
-CAcreateserial \
-out wombat-cert.pem \
-copy_extensions=copyall

echo "generating kangaroo certificate and signing it"
openssl x509 -days 65536 \
-req -in kangaroo.csr \
-SHA384 \
-CA ca-cert.pem \
-CAkey ca-key.pem \
-CAcreateserial \
-out kangaroo-cert.pem \
-copy_extensions=copyall

touch wombat-chain.pem
cat wombat-cert.pem >> wombat-chain.pem
cat ca-cert.pem >> wombat-chain.pem

touch kangaroo-chain.pem
cat kangaroo-cert.pem >> kangaroo-chain.pem
cat ca-cert.pem >> kangaroo-chain.pem

echo "verifying server certificates"
openssl verify -CAfile ca-cert.pem wombat-cert.pem
openssl verify -CAfile ca-cert.pem kangaroo-cert.pem

# certificate signing requests are never used after the certs are generated
rm wombat.csr
rm kangaroo.csr
rm ca-cert.srl

# the private keys of the CA are never needed after signing
rm ca-key.pem
rm wombat-cert.pem
rm kangaroo-cert.pem

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIB3TCCAWKgAwIBAgIUJhUgxiGTEOtg0JBtu9SrS7PPvo0wCgYIKoZIzj0EAwMw
HDELMAkGA1UEBhMCVVMxDTALBgNVBAMMBHJvb3QwIBcNMjQwMTI3MDAwODQ4WhgP
MjIwMzA3MDQwMDA4NDhaMCAxCzAJBgNVBAYTAlVTMREwDwYDVQQDDAhrYW5nYXJv
bzB2MBAGByqGSM49AgEGBSuBBAAiA2IABCzesg6GHI5tMP4JuMvpiVHsc+CStyTy
JQQZ4jyj4fVfgqCcPVo6qJq6DjPepMRkm5tLtFrdavl8/ZZpiCi5vLSymUxliFXD
9DD8GO5naaBnW2EmuYCcNrB0FJJfKZurVKNfMF0wGwYDVR0RBBQwEoIQd3d3Lmth
bmdhcm9vLmNvbTAdBgNVHQ4EFgQUNmsIZH0IDGVlSy7V6BYZTE6NX1QwHwYDVR0j
BBgwFoAU2ic6pZKpiyOr5aPtYhABB9hJC5QwCgYIKoZIzj0EAwMDaQAwZgIxAJzE
GC8hKsqTmDxI4r7bewI/vjtKyEUf0BDJfRrSLixPySYRTbx950iHMo6kXB0DEwIx
AO02gaF9weybuklR+DZ/j6EEZk4HlaRvN575vKmdDYIUF4KpFcT/8f85+5klj9Tl
Hg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB3DCCAWKgAwIBAgIUaAjZTaFhJNRyFtFQut1CdrY7RH0wCgYIKoZIzj0EAwMw
HDELMAkGA1UEBhMCVVMxDTALBgNVBAMMBHJvb3QwIBcNMjQwMTI3MDAwODQ4WhgP
MjIwMzA3MDQwMDA4NDhaMBwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQDDARyb290MHYw
EAYHKoZIzj0CAQYFK4EEACIDYgAEclmOmfFLoQR+mupZSc7J3IfZ6OV0IphUHWwv
iH9BvkGh4OX+RZfafa4hw90A5fk0ps520Dt04tHwotLBNkdQcWDJunOhw8ydebIP
TaP0V8OgxFs+P4kpBkMVNB3H+PK6o2MwYTAdBgNVHQ4EFgQU2ic6pZKpiyOr5aPt
YhABB9hJC5QwHwYDVR0jBBgwFoAU2ic6pZKpiyOr5aPtYhABB9hJC5QwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwCgYIKoZIzj0EAwMDaAAwZQIxAMtZ
+QqC0LGdqUxdr2woMr6pUNAaZYaxm6APPqyKsjVqNaKadiSueNbbbc+seKJXbwIw
Zl0HNHzmoNAMkpgx5BCukjL1v07C571diSW4Z/P96t8tUzi/2rUOoFlJYU0B8cib
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDB8OJA0z/nzPkogIasW
B8xhhROb0sDbHEqYwStAdDKEWGCLGyy46/5sMprtht8bBpahZANiAAQs3rIOhhyO
bTD+CbjL6YlR7HPgkrck8iUEGeI8o+H1X4KgnD1aOqiaug4z3qTEZJubS7Ra3Wr5
fP2WaYgouby0splMZYhVw/Qw/BjuZ2mgZ1thJrmAnDawdBSSXymbq1Q=
-----END PRIVATE KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIB2DCCAV6gAwIBAgIUJhUgxiGTEOtg0JBtu9SrS7PPvowwCgYIKoZIzj0EAwMw
HDELMAkGA1UEBhMCVVMxDTALBgNVBAMMBHJvb3QwIBcNMjQwMTI3MDAwODQ4WhgP
MjIwMzA3MDQwMDA4NDhaMB4xCzAJBgNVBAYTAlVTMQ8wDQYDVQQDDAZ3b21iYXQw
djAQBgcqhkjOPQIBBgUrgQQAIgNiAARUye9Qgw5N7T8nk6DFoUwPVzSnQy9v4v0V
8SOUZmRwBqmFSJ9Vm988BwAcPFHdmQ13Za4XTkDbQvMmgzntIIIziiyaJQAazRFG
Y2Ex4V/YBiIsuh5wPOXjtvOtgVMXBgijXTBbMBkGA1UdEQQSMBCCDnd3dy53b21i
YXQuY29tMB0GA1UdDgQWBBS+Tbl0gagSNimLM5q2EgeBIMEAfzAfBgNVHSMEGDAW
gBTaJzqlkqmLI6vlo+1iEAEH2EkLlDAKBggqhkjOPQQDAwNoADBlAjAKqbrvk9by
G278VLs7F8uvc1mFYYWv/ZnnQIEJT8srO+P57PtC5FBId5oK28P41EUCMQCim4LR
KzY/PcdY8NlAcHu/caWvGH2+FWm7jFyr8As5oXT0swbqYmMqpaK6E2EZNIk=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB3DCCAWKgAwIBAgIUaAjZTaFhJNRyFtFQut1CdrY7RH0wCgYIKoZIzj0EAwMw
HDELMAkGA1UEBhMCVVMxDTALBgNVBAMMBHJvb3QwIBcNMjQwMTI3MDAwODQ4WhgP
MjIwMzA3MDQwMDA4NDhaMBwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQDDARyb290MHYw
EAYHKoZIzj0CAQYFK4EEACIDYgAEclmOmfFLoQR+mupZSc7J3IfZ6OV0IphUHWwv
iH9BvkGh4OX+RZfafa4hw90A5fk0ps520Dt04tHwotLBNkdQcWDJunOhw8ydebIP
TaP0V8OgxFs+P4kpBkMVNB3H+PK6o2MwYTAdBgNVHQ4EFgQU2ic6pZKpiyOr5aPt
YhABB9hJC5QwHwYDVR0jBBgwFoAU2ic6pZKpiyOr5aPtYhABB9hJC5QwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwCgYIKoZIzj0EAwMDaAAwZQIxAMtZ
+QqC0LGdqUxdr2woMr6pUNAaZYaxm6APPqyKsjVqNaKadiSueNbbbc+seKJXbwIw
Zl0HNHzmoNAMkpgx5BCukjL1v07C571diSW4Z/P96t8tUzi/2rUOoFlJYU0B8cib
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDDO2TkDRDnGfKAvjH9+
SliejJgLp6ONEdNAgfimOEDWgfMJiyYEPp9WhZkASDVTaB2hZANiAARUye9Qgw5N
7T8nk6DFoUwPVzSnQy9v4v0V8SOUZmRwBqmFSJ9Vm988BwAcPFHdmQ13Za4XTkDb
QvMmgzntIIIziiyaJQAazRFGY2Ex4V/YBiIsuh5wPOXjtvOtgVMXBgg=
-----END PRIVATE KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
stable
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use clap::Parser;
use s2n_tls::security::DEFAULT_TLS13;

use std::error::Error;
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
net::*,
};

const PORT: u16 = 1738;

#[derive(Debug, Parser)]
struct Cli {
/// value to specify for the SNI
sni: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let args = Cli::parse();
let mut config = s2n_tls::config::Config::builder();
let ca: Vec<u8> = std::fs::read(env!("CARGO_MANIFEST_DIR").to_owned() + "/certs/ca-cert.pem")?;
config.set_security_policy(&DEFAULT_TLS13)?;
config.trust_pem(&ca)?;

let client = s2n_tls_tokio::TlsConnector::new(config.build()?);
let stream = TcpStream::connect(("127.0.0.1", PORT)).await?;
// request a TLS connection on the TCP stream while setting the sni
let mut tls = match client.connect(&args.sni, stream).await {
Ok(tls) => tls,
Err(e) => {
println!("error during handshake: {:?}", e);
return Ok(());
}
};
println!("{:#?}", tls);

let mut server_response = String::new();
tls.read_to_string(&mut server_response).await?;
println!("The server said {server_response}");
tls.shutdown().await?;

Ok(())
}
Loading

0 comments on commit ba825b8

Please sign in to comment.