Support loading certificates in the server

This commit is contained in:
Olivier 'reivilibre' 2022-01-17 19:48:53 +00:00
parent ff32b0c0f3
commit 471f594345
2 changed files with 38 additions and 21 deletions

View File

@ -31,4 +31,4 @@ quinn = { version = "0.8.0", features = [] }
# Compression and Encryption
zstd = "0.9.2+zstd.1.5.1"
rustls = "0.20.2"
rcgen = { version = "0.8.14", features = ["pem", "x509-parser"] }
rcgen = { version = "0.8.14", features = ["x509-parser"] }

View File

@ -4,7 +4,8 @@ use futures_util::StreamExt;
use quinn::Endpoint;
use rcgen::{BasicConstraints, Certificate, CertificateParams, IsCa, KeyPair};
use rustls::internal::msgs::codec::Codec;
use std::io::Read;
use rustls::{PrivateKey, RootCertStore};
use std::io::{BufReader, Cursor, Read};
use std::net::SocketAddr;
use std::path::{Path, PathBuf};
use std::str::FromStr;
@ -27,17 +28,17 @@ pub enum Command {
},
}
pub async fn write_file(path: &Path, content: &str) -> anyhow::Result<()> {
pub async fn write_file(path: &Path, content: &[u8]) -> anyhow::Result<()> {
let mut file = File::create(path).await?;
file.write_all(content.as_bytes()).await?;
file.write_all(content).await?;
Ok(())
}
pub async fn read_file(path: &Path) -> anyhow::Result<String> {
pub async fn read_file(path: &Path) -> anyhow::Result<Vec<u8>> {
let mut file = File::open(path).await?;
let mut string = String::new();
file.read_to_string(&mut string).await?;
Ok(string)
let mut bytes = Vec::new();
file.read_to_end(&mut bytes).await?;
Ok(bytes)
}
#[tokio::main]
@ -56,19 +57,19 @@ async fn main() -> anyhow::Result<()> {
// TODO don't hard code a date :-).
ca_params.not_after = rcgen::date_time_ymd(2042, 1, 1);
let ca_cert = Certificate::from_params(ca_params)?;
let cert_pem = ca_cert.serialize_pem()?;
let key_pem = ca_cert.serialize_private_key_pem();
let cert_der = ca_cert.serialize_der()?;
let key_der = ca_cert.serialize_private_key_der();
write_file(&ca_key_path, &key_pem).await?;
write_file(&ca_cert_path, &cert_pem).await?;
write_file(&ca_key_path, &key_der).await?;
write_file(&ca_cert_path, &cert_der).await?;
}
let ca_key_pem = read_file(&ca_key_path).await?;
let ca_cert_pem = read_file(&ca_cert_path).await?;
let ca_key_der = read_file(&ca_key_path).await?;
let ca_cert_der = read_file(&ca_cert_path).await?;
let ca_keypair = KeyPair::from_pem(&ca_key_pem)?;
let ca_cert = Certificate::from_params(CertificateParams::from_ca_cert_pem(
&ca_cert_pem,
let ca_keypair = KeyPair::from_der(&ca_key_der)?;
let ca_cert = Certificate::from_params(CertificateParams::from_ca_cert_der(
&ca_cert_der,
ca_keypair,
)?)?;
@ -79,12 +80,12 @@ async fn main() -> anyhow::Result<()> {
let leaf_cert = Certificate::from_params(cert_params)?;
write_file(
&ca_dir.join(format!("{}.key", &name)),
&leaf_cert.serialize_private_key_pem(),
&leaf_cert.serialize_private_key_der(),
)
.await?;
write_file(
&ca_dir.join(format!("{}.pem", &name)),
&leaf_cert.serialize_pem_with_signer(&ca_cert)?,
&leaf_cert.serialize_der_with_signer(&ca_cert)?,
)
.await?;
}
@ -92,11 +93,27 @@ async fn main() -> anyhow::Result<()> {
println!("Hello, world!");
let mut root_cert_store = RootCertStore::empty();
// TODO take ca path from config
let ca_cert_der = read_file(Path::new("ca/ca.pem")).await?;
let ca_cert = rustls::Certificate::read_bytes(&ca_cert_der).ok_or_else(|| anyhow!(""))?;
root_cert_store.add(&ca_cert)?;
// TODO we want to check the names of the clients. Figure out how.
let verifier = rustls::server::AllowAnyAuthenticatedClient::new(root_cert_store);
// TODO take cert path from config
let server_cert_der = read_file(Path::new("ca/server.pem")).await?;
let server_cert =
rustls::Certificate::read_bytes(&server_cert_der).ok_or_else(|| anyhow!(""))?;
let server_key_der = read_file(Path::new("ca/server.key")).await?;
let server_key = PrivateKey(server_key_der);
//let x = quinn::ServerConfig::with_native_roots();
let crypto = rustls::ServerConfig::builder()
.with_safe_defaults()
.with_client_cert_verifier(todo!())
.with_single_cert(todo!(), todo!())?;
.with_client_cert_verifier(verifier)
.with_single_cert(vec![server_cert], server_key)?;
let crypto = Arc::new(crypto);
let x = quinn::ServerConfig::with_crypto(crypto);
let (ep, mut incoming) =