Use the real structure with Server-Broker-Client instead of Client-Server-Requester previously used in Bonk v1
This commit is contained in:
164
bonknet_broker/src/bin/init_certs.rs
Normal file
164
bonknet_broker/src/bin/init_certs.rs
Normal file
@@ -0,0 +1,164 @@
|
||||
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(), "bonk.server.1".into()]);
|
||||
params.distinguished_name.push(DnType::CommonName, "Server 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 guestserver_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 Guest Server Root Cert CA");
|
||||
certparams.distinguished_name = distname;
|
||||
Certificate::from_params(certparams).unwrap()
|
||||
}
|
||||
|
||||
fn guestserver_cert() -> Certificate {
|
||||
let mut params = CertificateParams::new(vec!["entity.other.host".into(), "bonk.guestserver.1".into()]);
|
||||
params.distinguished_name.push(DnType::CommonName, "Guest Server 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 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 broker_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 Broker Root Cert CA");
|
||||
certparams.distinguished_name = distname;
|
||||
Certificate::from_params(certparams).unwrap()
|
||||
}
|
||||
|
||||
fn broker_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 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("certs/server_root_cert.pem")?;
|
||||
certfile.write_all(server_root_cert.serialize_pem().unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("certs/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("certs/server_cert.pem")?;
|
||||
certfile.write_all(server_leaf_cert.serialize_pem_with_signer(&server_root_cert).unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("certs/server_key.pem")?;
|
||||
privkfile.write_all(server_leaf_cert.serialize_private_key_pem().as_bytes())?;
|
||||
}
|
||||
// GUESTSERVER
|
||||
let guestserver_root_cert = guestserver_root_cert();
|
||||
// The certificate is now valid for localhost and the domain "hello.world.example"
|
||||
{
|
||||
let mut certfile = File::create("certs/guestserver_root_cert.pem")?;
|
||||
certfile.write_all(guestserver_root_cert.serialize_pem().unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("certs/guestserver_root_key.pem")?;
|
||||
privkfile.write_all(guestserver_root_cert.serialize_private_key_pem().as_bytes())?;
|
||||
}
|
||||
// Now create the leaf
|
||||
let guestserver_leaf_cert = guestserver_cert();
|
||||
{
|
||||
let mut certfile = File::create("certs/guestserver_cert.pem")?;
|
||||
certfile.write_all(guestserver_leaf_cert.serialize_pem_with_signer(&guestserver_root_cert).unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("certs/guestserver_key.pem")?;
|
||||
privkfile.write_all(guestserver_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("certs/client_root_cert.pem")?;
|
||||
certfile.write_all(client_root_cert.serialize_pem().unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("certs/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("certs/client_cert.pem")?;
|
||||
certfile.write_all(client_leaf_cert.serialize_pem_with_signer(&client_root_cert).unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("certs/client_key.pem")?;
|
||||
privkfile.write_all(client_leaf_cert.serialize_private_key_pem().as_bytes())?;
|
||||
}
|
||||
// BROKER
|
||||
let requester_root_cert = broker_root_cert();
|
||||
// The certificate is now valid for localhost and the domain "hello.world.example"
|
||||
{
|
||||
let mut certfile = File::create("certs/broker_root_cert.pem")?;
|
||||
certfile.write_all(requester_root_cert.serialize_pem().unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("certs/broker_root_key.pem")?;
|
||||
privkfile.write_all(requester_root_cert.serialize_private_key_pem().as_bytes())?;
|
||||
}
|
||||
// Now create the leaf
|
||||
let requester_leaf_cert = broker_cert();
|
||||
{
|
||||
let mut certfile = File::create("certs/broker_cert.pem")?;
|
||||
certfile.write_all(requester_leaf_cert.serialize_pem_with_signer(&requester_root_cert).unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("certs/broker_key.pem")?;
|
||||
privkfile.write_all(requester_leaf_cert.serialize_private_key_pem().as_bytes())?;
|
||||
}
|
||||
println!("Certificates created");
|
||||
Ok(())
|
||||
}
|
||||
200
bonknet_broker/src/main.rs
Normal file
200
bonknet_broker/src/main.rs
Normal file
@@ -0,0 +1,200 @@
|
||||
use actix::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use libbonknet::{load_cert, load_prkey, FromServerMessage, RequiredReplyValues, FromGuestServerMessage};
|
||||
use rustls::{RootCertStore, ServerConfig};
|
||||
use rustls::server::WebPkiClientVerifier;
|
||||
use actix_tls::accept::rustls_0_22::{Acceptor as RustlsAcceptor, TlsStream};
|
||||
use actix_server::Server;
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_service::{ServiceFactoryExt as _};
|
||||
use futures_util::{StreamExt};
|
||||
use thiserror::Error;
|
||||
use tokio_util::codec::{Framed, LengthDelimitedCodec};
|
||||
use tracing::{info, error};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
enum DBError {
|
||||
#[error("Certificate is already registered with name {0}")]
|
||||
CertAlreadyRegistered(String),
|
||||
// #[error("Generic Failure")]
|
||||
// GenericFailure,
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "Result<(), DBError>")]
|
||||
struct RegisterServer {
|
||||
cert: Vec<u8>,
|
||||
name: String,
|
||||
}
|
||||
|
||||
// TODO: Move into Sqlite DB with unique check on col1 and col2!!!! Right now name is not unique
|
||||
struct ServerCertDB {
|
||||
db: HashMap<Vec<u8>, String>, // Cert to Name
|
||||
}
|
||||
|
||||
impl Actor for ServerCertDB {
|
||||
type Context = Context<Self>;
|
||||
}
|
||||
|
||||
impl Handler<RegisterServer> for ServerCertDB {
|
||||
type Result = Result<(), DBError>;
|
||||
|
||||
fn handle(&mut self, msg: RegisterServer, _ctx: &mut Self::Context) -> Self::Result {
|
||||
match self.db.get(&msg.cert) {
|
||||
None => {
|
||||
self.db.insert(msg.cert, msg.name);
|
||||
Ok(())
|
||||
}
|
||||
Some(name) => {
|
||||
Err(DBError::CertAlreadyRegistered(name.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GuestServerConnection {
|
||||
stream: TlsStream<TcpStream>,
|
||||
}
|
||||
|
||||
impl Actor for GuestServerConnection {
|
||||
type Context = Context<Self>;
|
||||
}
|
||||
|
||||
struct ServerConnection<T: 'static> {
|
||||
stream: Framed<TlsStream<TcpStream>, T>,
|
||||
name: String
|
||||
}
|
||||
|
||||
impl<T> ServerConnection<T> {
|
||||
fn new(stream: TlsStream<TcpStream>, codec: T) -> Self {
|
||||
let stream = Framed::new(stream, codec);
|
||||
ServerConnection {
|
||||
stream,
|
||||
name: "Polnareffland1".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Actor for ServerConnection<T> {
|
||||
type Context = Context<Self>;
|
||||
}
|
||||
|
||||
#[actix_rt::main]
|
||||
async fn main() {
|
||||
// Tracing Subscriber
|
||||
let subscriber = tracing_subscriber::FmtSubscriber::new();
|
||||
tracing::subscriber::set_global_default(subscriber).unwrap();
|
||||
// BROKER CERTS
|
||||
let broker_root_cert_der = load_cert("certs/broker_root_cert.pem").unwrap();
|
||||
let broker_cert_der = load_cert("certs/broker_cert.pem").unwrap();
|
||||
let broker_prkey_der = load_prkey("certs/broker_key.pem").unwrap();
|
||||
// SERVER ROOT
|
||||
let server_root_cert_der = load_cert("certs/server_root_cert.pem").unwrap();
|
||||
// GUESTSERVER ROOT
|
||||
let guestserver_root_cert_der = load_cert("certs/guestserver_root_cert.pem").unwrap();
|
||||
// CLIENT ROOT
|
||||
let client_root_cert_der = load_cert("certs/client_root_cert.pem").unwrap();
|
||||
// Client Verifier
|
||||
let mut broker_root_store = RootCertStore::empty();
|
||||
broker_root_store.add(server_root_cert_der.clone()).unwrap();
|
||||
broker_root_store.add(client_root_cert_der.clone()).unwrap();
|
||||
broker_root_store.add(guestserver_root_cert_der.clone()).unwrap();
|
||||
let server_verifier = WebPkiClientVerifier::builder(Arc::new(broker_root_store)).build().unwrap();
|
||||
// Configure TLS
|
||||
let server_tlsconfig = ServerConfig::builder()
|
||||
// .with_no_client_auth()
|
||||
.with_client_cert_verifier(server_verifier)
|
||||
.with_single_cert(vec![broker_cert_der.clone(), broker_root_cert_der.clone()], broker_prkey_der.into())
|
||||
.unwrap();
|
||||
let server_acceptor = RustlsAcceptor::new(server_tlsconfig);
|
||||
|
||||
let server_root_cert_der = Arc::new(server_root_cert_der);
|
||||
let client_root_cert_der = Arc::new(client_root_cert_der);
|
||||
let guestserver_root_cert_der = Arc::new(guestserver_root_cert_der);
|
||||
|
||||
Server::build()
|
||||
.bind("server-command", ("localhost", 2541), move || {
|
||||
let server_root_cert_der = Arc::clone(&server_root_cert_der);
|
||||
let client_root_cert_der = Arc::clone(&client_root_cert_der);
|
||||
let guestserver_root_cert_der = Arc::clone(&guestserver_root_cert_der);
|
||||
let _server_db_addr = ServerCertDB {
|
||||
db: HashMap::new(),
|
||||
}.start();
|
||||
|
||||
// Set up TLS service factory
|
||||
server_acceptor
|
||||
.clone()
|
||||
.map_err(|err| println!("Rustls error: {:?}", err))
|
||||
.and_then(move |stream: TlsStream<TcpStream>| {
|
||||
let server_root_cert_der = Arc::clone(&server_root_cert_der);
|
||||
let client_root_cert_der = Arc::clone(&client_root_cert_der);
|
||||
let guestserver_root_cert_der = Arc::clone(&guestserver_root_cert_der);
|
||||
async move {
|
||||
let peer_cert_der = stream.get_ref().1.peer_certificates().unwrap().last().unwrap().clone();
|
||||
if peer_cert_der == *server_root_cert_der {
|
||||
info!("Server connection");
|
||||
let framed = Framed::new(stream, LengthDelimitedCodec::new());
|
||||
framed.for_each(|item| async move {
|
||||
match item {
|
||||
Ok(buf) => {
|
||||
use FromServerMessage::*;
|
||||
let msg: FromServerMessage = rmp_serde::from_slice(&buf).unwrap();
|
||||
info!("{:?}", msg);
|
||||
match msg {
|
||||
RequiredReply(v) => match v {
|
||||
RequiredReplyValues::Ok => {
|
||||
info!("Required Reply OK")
|
||||
}
|
||||
RequiredReplyValues::GenericFailure { .. } => {
|
||||
info!("Required Reply Generic Failure")
|
||||
}
|
||||
}
|
||||
ChangeName { name } => {
|
||||
info!("Requested Change Name to Name {}", name);
|
||||
}
|
||||
WhoAmI => {
|
||||
info!("Requested WhoAmI");
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
info!("Disconnection: {:?}", e);
|
||||
}
|
||||
}
|
||||
}).await;
|
||||
info!("Disconnection!");
|
||||
} else if peer_cert_der == *guestserver_root_cert_der {
|
||||
info!("GuestServer connection");
|
||||
let framed = Framed::new(stream, LengthDelimitedCodec::new());
|
||||
framed.for_each(|item| async move {
|
||||
match item {
|
||||
Ok(buf) => {
|
||||
use FromGuestServerMessage::*;
|
||||
let msg: FromGuestServerMessage = rmp_serde::from_slice(&buf).unwrap();
|
||||
info!("{:?}", msg);
|
||||
match msg {
|
||||
Announce { name } => {
|
||||
info!("Announced with name {}", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
info!("Disconnection: {:?}", e);
|
||||
}
|
||||
}
|
||||
}).await;
|
||||
} else if peer_cert_der == *client_root_cert_der {
|
||||
info!("Client connection");
|
||||
} else {
|
||||
error!("Unknown Root Certificate");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
}).unwrap()
|
||||
.workers(1)
|
||||
.run()
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
Reference in New Issue
Block a user