Initial commit

This commit is contained in:
2024-01-15 20:21:10 +01:00
commit 21d2b16ee8
10 changed files with 854 additions and 0 deletions

12
bonknet_server/Cargo.toml Normal file
View File

@@ -0,0 +1,12 @@
[package]
name = "bonknet_server"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1", features = ["full"] }
rcgen = "0.12.0"
tokio-rustls = "0.25.0"
rustls-pemfile = "2.0.0"

View File

@@ -0,0 +1,86 @@
use std::fs::File;
use std::io::Write;
use rcgen::{self, BasicConstraints, Certificate, CertificateParams, DnType};
fn server_root_cert() -> Certificate {
let subject_alt_names = vec!["hello.world.example".into()];
let mut certparams = CertificateParams::new(subject_alt_names);
certparams.is_ca = rcgen::IsCa::Ca(BasicConstraints::Unconstrained);
let mut distname = rcgen::DistinguishedName::new();
distname.push(DnType::OrganizationName, "Eister Corporation");
distname.push(DnType::CommonName, "Bonknet Server Root Cert CA");
certparams.distinguished_name = distname;
Certificate::from_params(certparams).unwrap()
}
fn server_cert() -> Certificate {
let mut params = CertificateParams::new(vec!["entity.other.host".into(), "localhost".into()]);
params.distinguished_name.push(DnType::CommonName, "localhost");
params.use_authority_key_identifier_extension = true;
params.key_usages.push(rcgen::KeyUsagePurpose::DigitalSignature);
params
.extended_key_usages
.push(rcgen::ExtendedKeyUsagePurpose::ServerAuth);
Certificate::from_params(params).unwrap()
}
fn client_root_cert() -> Certificate {
let subject_alt_names = vec!["hello.world.example".into()];
let mut certparams = CertificateParams::new(subject_alt_names);
certparams.is_ca = rcgen::IsCa::Ca(BasicConstraints::Unconstrained);
let mut distname = rcgen::DistinguishedName::new();
distname.push(DnType::OrganizationName, "Eister Corporation");
distname.push(DnType::CommonName, "Bonknet Client Root Cert CA");
certparams.distinguished_name = distname;
Certificate::from_params(certparams).unwrap()
}
fn client_cert() -> Certificate {
let mut params = CertificateParams::new(vec!["entity.other.host".into(), "bonk.client.1".into()]);
params.distinguished_name.push(DnType::CommonName, "Client 1");
params.use_authority_key_identifier_extension = true;
params.key_usages.push(rcgen::KeyUsagePurpose::DigitalSignature);
params
.extended_key_usages
.push(rcgen::ExtendedKeyUsagePurpose::ClientAuth);
Certificate::from_params(params).unwrap()
}
fn main() -> std::io::Result<()> {
// SERVER
let server_root_cert = server_root_cert();
// The certificate is now valid for localhost and the domain "hello.world.example"
{
let mut certfile = File::create("server_root_cert.pem")?;
certfile.write_all(server_root_cert.serialize_pem().unwrap().as_bytes())?;
let mut privkfile = File::create("server_root_key.pem")?;
privkfile.write_all(server_root_cert.serialize_private_key_pem().as_bytes())?;
}
// Now create the leaf
let server_leaf_cert = server_cert();
{
let mut certfile = File::create("server_cert.pem")?;
certfile.write_all(server_leaf_cert.serialize_pem_with_signer(&server_root_cert).unwrap().as_bytes())?;
let mut privkfile = File::create("server_key.pem")?;
privkfile.write_all(server_leaf_cert.serialize_private_key_pem().as_bytes())?;
}
// CLIENT
let client_root_cert = client_root_cert();
// The certificate is now valid for localhost and the domain "hello.world.example"
{
let mut certfile = File::create("client_root_cert.pem")?;
certfile.write_all(client_root_cert.serialize_pem().unwrap().as_bytes())?;
let mut privkfile = File::create("client_root_key.pem")?;
privkfile.write_all(client_root_cert.serialize_private_key_pem().as_bytes())?;
}
// Now create the leaf
let client_leaf_cert = client_cert();
{
let mut certfile = File::create("client_cert.pem")?;
certfile.write_all(client_leaf_cert.serialize_pem_with_signer(&client_root_cert).unwrap().as_bytes())?;
let mut privkfile = File::create("client_key.pem")?;
privkfile.write_all(client_leaf_cert.serialize_private_key_pem().as_bytes())?;
}
println!("Certificates created");
Ok(())
}

View File

@@ -0,0 +1,75 @@
use tokio::net::{TcpListener};
use std::io::{BufReader, Error, ErrorKind};
use std::sync::{Arc};
use tokio_rustls::{TlsAcceptor};
use tokio_rustls::rustls::{RootCertStore, ServerConfig};
use tokio_rustls::rustls::server::WebPkiClientVerifier;
use rustls_pemfile::{read_one, Item};
use tokio::io::{AsyncWriteExt, copy, split};
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer};
fn load_cert(filename: &str) -> std::io::Result<CertificateDer> {
let cert_file = std::fs::File::open(filename).unwrap();
let mut buf = std::io::BufReader::new(cert_file);
if let Item::X509Certificate(cert) = read_one(&mut buf).unwrap().unwrap() {
Ok(cert)
} else {
eprintln!("File {} doesn't contain a X509 Certificate", filename);
Err(Error::new(ErrorKind::InvalidInput, "no x509 cert"))
}
}
fn load_prkey(filename: &str) -> std::io::Result<PrivatePkcs8KeyDer> {
let prkey_file = std::fs::File::open(filename).unwrap();
let mut buf = BufReader::new(prkey_file);
if let Item::Pkcs8Key(pkey) = read_one(&mut buf).unwrap().unwrap() {
Ok(pkey)
} else {
eprintln!("File {} doesn't contain a Pkcs8 Private Key", filename);
Err(Error::new(ErrorKind::InvalidInput, "no pkcs8key"))
}
}
#[tokio::main]
async fn main() {
let server_root_cert_der = load_cert("server_root_cert.pem").unwrap();
let server_cert_der = load_cert("server_cert.pem").unwrap();
let server_prkey_der = load_prkey("server_key.pem").unwrap();
// CLIENT ROOT
let client_root_cert_der = load_cert("client_root_cert.pem").unwrap();
// Client Verifier
let mut clientrootstore = RootCertStore::empty();
clientrootstore.add(client_root_cert_der).unwrap();
let client_verifier = WebPkiClientVerifier::builder(Arc::new(clientrootstore)).build().unwrap();
// Configure TLS
let tlsconfig = ServerConfig::builder()
// .with_no_client_auth()
.with_client_cert_verifier(client_verifier)
.with_single_cert(vec![server_cert_der.clone(), server_root_cert_der.clone()], server_prkey_der.into())
.unwrap();
let acceptor = TlsAcceptor::from(Arc::new(tlsconfig));
let listener = TcpListener::bind("localhost:6379").await.unwrap();
loop {
let (stream, peer_addr) = listener.accept().await.unwrap();
let acceptor = acceptor.clone();
let fut = async move {
let stream = acceptor.accept(stream).await?;
let (mut reader, mut writer) = split(stream);
let n = copy(&mut reader, &mut writer).await?;
writer.flush().await?;
println!("Echo: {} - {}", peer_addr, n);
Ok(()) as std::io::Result<()>
};
tokio::spawn(async move {
if let Err(err) = fut.await {
eprintln!("{:?}", err);
}
});
}
}