Achieve first working Announce registration for Guests

This commit is contained in:
2024-02-12 22:00:41 +01:00
parent 857b9171af
commit 9e3d4c5fe3
6 changed files with 447 additions and 636 deletions

843
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -16,11 +16,11 @@ actix-tls = { version = "3.3.0", features = ["rustls-0_22"] }
rustls = "0.22.2" rustls = "0.22.2"
tracing = "0.1" tracing = "0.1"
tracing-subscriber = "0.3" tracing-subscriber = "0.3"
futures-util = "0.3.30" futures = "0.3"
thiserror = "1.0.56" thiserror = "1.0.56"
tokio-util = { version = "0.7.10", features = ["codec"] } tokio-util = { version = "0.7.10", features = ["codec"] }
rmp-serde = "1.1.2" rmp-serde = "1.1.2"
rcgen = "0.12.1" rcgen = { version = "0.12.1", features = ["x509-parser"] }
[[bin]] [[bin]]
name = "init_certs" name = "init_certs"

View File

@@ -1,17 +1,37 @@
use actix::prelude::*; use actix::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use libbonknet::{load_cert, load_prkey, FromServerMessage, RequiredReplyValues, FromGuestServerMessage}; use libbonknet::{load_cert, load_prkey, FromServerMessage, RequiredReplyValues, FromGuestServerMessage, ToGuestServerMessage};
use rustls::{RootCertStore, ServerConfig}; use rustls::{RootCertStore, ServerConfig};
use rustls::server::WebPkiClientVerifier; use rustls::server::WebPkiClientVerifier;
use actix_tls::accept::rustls_0_22::{Acceptor as RustlsAcceptor, TlsStream}; use actix_tls::accept::rustls_0_22::{Acceptor as RustlsAcceptor, TlsStream};
use actix_server::Server; use actix_server::Server;
use actix_rt::net::TcpStream; use actix_rt::net::TcpStream;
use actix_service::{ServiceFactoryExt as _}; use actix_service::{ServiceFactoryExt as _};
use futures_util::{StreamExt}; use futures::{StreamExt, SinkExt};
use thiserror::Error; use thiserror::Error;
use tokio_util::codec::{Framed, LengthDelimitedCodec}; use tokio_util::codec::{Framed, LengthDelimitedCodec};
use tracing::{info, error}; use tracing::{info, error};
use rcgen::{Certificate, CertificateParams, DnType, KeyPair};
struct ServerCert {
cert: Vec<u8>,
prkey: Vec<u8>,
}
fn generate_server_cert(root_cert: &Certificate, name: &str) -> ServerCert {
let mut params = CertificateParams::new(vec!["entity.other.host".into(), format!("bonk.server.{name}")]);
params.distinguished_name.push(DnType::CommonName, format!("{name}"));
params.use_authority_key_identifier_extension = true;
params.key_usages.push(rcgen::KeyUsagePurpose::DigitalSignature);
params
.extended_key_usages
.push(rcgen::ExtendedKeyUsagePurpose::ClientAuth);
let certificate = Certificate::from_params(params).unwrap();
let cert = certificate.serialize_der_with_signer(root_cert).unwrap();
let prkey = certificate.serialize_private_key_der();
ServerCert { cert, prkey }
}
#[derive(Error, Debug)] #[derive(Error, Debug)]
enum DBError { enum DBError {
@@ -21,6 +41,12 @@ enum DBError {
// GenericFailure, // GenericFailure,
} }
#[derive(Message)]
#[rtype(result = "bool")]
struct IsNameRegistered {
name: String,
}
#[derive(Message)] #[derive(Message)]
#[rtype(result = "Result<(), DBError>")] #[rtype(result = "Result<(), DBError>")]
struct RegisterServer { struct RegisterServer {
@@ -53,6 +79,14 @@ impl Handler<RegisterServer> for ServerCertDB {
} }
} }
impl Handler<IsNameRegistered> for ServerCertDB {
type Result = bool;
fn handle(&mut self, msg: IsNameRegistered, _ctx: &mut Self::Context) -> Self::Result {
self.db.values().any(|x| *x == msg.name)
}
}
struct GuestServerConnection { struct GuestServerConnection {
stream: TlsStream<TcpStream>, stream: TlsStream<TcpStream>,
} }
@@ -91,6 +125,7 @@ async fn main() {
let broker_prkey_der = load_prkey("certs/broker_key.pem").unwrap(); let broker_prkey_der = load_prkey("certs/broker_key.pem").unwrap();
// SERVER ROOT // SERVER ROOT
let server_root_cert_der = load_cert("certs/server_root_cert.pem").unwrap(); let server_root_cert_der = load_cert("certs/server_root_cert.pem").unwrap();
let server_root_prkey_der = load_prkey("certs/server_root_key.pem").unwrap();
// GUESTSERVER ROOT // GUESTSERVER ROOT
let guestserver_root_cert_der = load_cert("certs/guestserver_root_cert.pem").unwrap(); let guestserver_root_cert_der = load_cert("certs/guestserver_root_cert.pem").unwrap();
// CLIENT ROOT // CLIENT ROOT
@@ -110,17 +145,25 @@ async fn main() {
let server_acceptor = RustlsAcceptor::new(server_tlsconfig); let server_acceptor = RustlsAcceptor::new(server_tlsconfig);
let server_root_cert_der = Arc::new(server_root_cert_der); let server_root_cert_der = Arc::new(server_root_cert_der);
let server_root_prkey = KeyPair::from_der(server_root_prkey_der.secret_pkcs8_der()).unwrap();
let client_root_cert_der = Arc::new(client_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); let guestserver_root_cert_der = Arc::new(guestserver_root_cert_der);
let server_root_cert = Arc::new(Certificate::from_params(CertificateParams::from_ca_cert_der(
&*server_root_cert_der,
server_root_prkey
).unwrap()).unwrap());
let server_db_addr = ServerCertDB {
db: HashMap::new(),
}.start();
Server::build() Server::build()
.bind("server-command", ("localhost", 2541), move || { .bind("server-command", ("localhost", 2541), move || {
let server_root_cert_der = Arc::clone(&server_root_cert_der); let server_root_cert_der = Arc::clone(&server_root_cert_der);
let client_root_cert_der = Arc::clone(&client_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 guestserver_root_cert_der = Arc::clone(&guestserver_root_cert_der);
let _server_db_addr = ServerCertDB { let server_root_cert = Arc::clone(&server_root_cert);
db: HashMap::new(), let server_db_addr = server_db_addr.clone();
}.start();
// Set up TLS service factory // Set up TLS service factory
server_acceptor server_acceptor
@@ -130,6 +173,8 @@ async fn main() {
let server_root_cert_der = Arc::clone(&server_root_cert_der); let server_root_cert_der = Arc::clone(&server_root_cert_der);
let client_root_cert_der = Arc::clone(&client_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 guestserver_root_cert_der = Arc::clone(&guestserver_root_cert_der);
let server_root_cert = Arc::clone(&server_root_cert);
let server_db_addr = server_db_addr.clone();
async move { async move {
let peer_cert_der = stream.get_ref().1.peer_certificates().unwrap().last().unwrap().clone(); let peer_cert_der = stream.get_ref().1.peer_certificates().unwrap().last().unwrap().clone();
if peer_cert_der == *server_root_cert_der { if peer_cert_der == *server_root_cert_der {
@@ -166,24 +211,51 @@ async fn main() {
info!("Disconnection!"); info!("Disconnection!");
} else if peer_cert_der == *guestserver_root_cert_der { } else if peer_cert_der == *guestserver_root_cert_der {
info!("GuestServer connection"); info!("GuestServer connection");
let framed = Framed::new(stream, LengthDelimitedCodec::new()); let server_root_cert = Arc::clone(&server_root_cert);
framed.for_each(|item| async move { let codec = LengthDelimitedCodec::new();
match item { let mut transport = Framed::new(stream, codec);
Ok(buf) => { loop {
use FromGuestServerMessage::*; match transport.next().await {
let msg: FromGuestServerMessage = rmp_serde::from_slice(&buf).unwrap(); None => {
info!("{:?}", msg); info!("Transport returned None");
match msg { }
Announce { name } => { Some(item) => {
info!("Announced with name {}", name); 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);
if server_db_addr.send(IsNameRegistered { name: name.clone() }).await.unwrap() {
info!("Name {} already registered!", name);
let reply = ToGuestServerMessage::FailedNameAlreadyOccupied;
transport.send(rmp_serde::to_vec(&reply).unwrap().into()).await.unwrap();
break; // Stop reading
} else {
let cert = generate_server_cert(&server_root_cert, name.as_str());
server_db_addr.send(RegisterServer {
cert: cert.cert.clone(),
name,
}).await.unwrap().unwrap();
let reply = ToGuestServerMessage::OkAnnounce {
server_cert: cert.cert,
server_prkey: cert.prkey
};
transport.send(rmp_serde::to_vec(&reply).unwrap().into()).await.unwrap();
}
}
}
}
Err(e) => {
info!("Disconnection: {:?}", e);
break;
} }
} }
} }
Err(e) => {
info!("Disconnection: {:?}", e);
}
} }
}).await; }
} else if peer_cert_der == *client_root_cert_der { } else if peer_cert_der == *client_root_cert_der {
info!("Client connection"); info!("Client connection");
} else { } else {

View File

@@ -13,7 +13,6 @@ futures = "0.3"
rcgen = "0.12.0" rcgen = "0.12.0"
tokio-rustls = "0.25.0" tokio-rustls = "0.25.0"
rustls-pemfile = "2.0.0" rustls-pemfile = "2.0.0"
serde = { version = "1.0", features = ["derive"] }
rmp-serde = "1.1.2" rmp-serde = "1.1.2"
tracing = "0.1" tracing = "0.1"
console-subscriber = "0.2.0" tracing-subscriber = "0.3"

View File

@@ -1,37 +1,35 @@
use std::sync::Arc; use std::sync::Arc;
use futures::SinkExt; use futures::{StreamExt, SinkExt};
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio_rustls::rustls::{ClientConfig, RootCertStore}; use tokio_rustls::rustls::{ClientConfig, RootCertStore};
use tokio_rustls::rustls::pki_types::{ServerName}; use tokio_rustls::rustls::pki_types::{ServerName, CertificateDer, PrivatePkcs8KeyDer};
use tokio_rustls::TlsConnector; use tokio_rustls::TlsConnector;
use tokio_util::codec::{Framed, LengthDelimitedCodec}; use tokio_util::codec::{Framed, LengthDelimitedCodec};
use serde::{Serialize, Deserialize}; use libbonknet::*;
use libbonknet::{load_cert, load_prkey, FromServerMessage}; use tracing::{info, error};
#[derive(Debug, Serialize, Deserialize)]
enum ClientMessage {
Response { status_code: u32, msg: Option<String> },
Announce { name: String },
Required { id: String },
NotRequired { id: String },
}
#[tokio::main] #[tokio::main]
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
let client_name = "Polnareffland1"; // Tracing Subscriber
let subscriber = tracing_subscriber::FmtSubscriber::new();
tracing::subscriber::set_global_default(subscriber).unwrap();
// Root certs to verify the server is the right one // Root certs to verify the server is the right one
let mut broker_root_cert_store = RootCertStore::empty(); let mut broker_root_cert_store = RootCertStore::empty();
let broker_root_cert_der = load_cert("certs/broker_root_cert.pem").unwrap(); let broker_root_cert_der = load_cert("certs/broker_root_cert.pem").unwrap();
broker_root_cert_store.add(broker_root_cert_der).unwrap(); broker_root_cert_store.add(broker_root_cert_der).unwrap();
// Auth Cert to send the server who am I // Public CA that will be used to generate the Server certificate
let root_server_cert = load_cert("certs/server_root_cert.pem").unwrap(); let root_server_cert = load_cert("certs/server_root_cert.pem").unwrap();
let server_cert = load_cert("certs/server_cert.pem").unwrap(); // Guest CA
let server_prkey = load_prkey("certs/server_key.pem").unwrap(); let root_guestserver_cert = load_cert("certs/guestserver_root_cert.pem").unwrap();
// Certificate used to do the first authentication
let guestserver_cert = load_cert("certs/guestserver_cert.pem").unwrap();
let guestserver_prkey = load_prkey("certs/guestserver_key.pem").unwrap();
// Load TLS Config // Load TLS Config
let tlsconfig = ClientConfig::builder() let tlsconfig = ClientConfig::builder()
.with_root_certificates(broker_root_cert_store) .with_root_certificates(broker_root_cert_store.clone())
// .with_no_client_auth(); // .with_no_client_auth();
.with_client_auth_cert(vec![server_cert, root_server_cert], server_prkey.into()) .with_client_auth_cert(vec![guestserver_cert, root_guestserver_cert], guestserver_prkey.into())
.unwrap(); .unwrap();
let connector = TlsConnector::from(Arc::new(tlsconfig)); let connector = TlsConnector::from(Arc::new(tlsconfig));
let dnsname = ServerName::try_from("localhost").unwrap(); let dnsname = ServerName::try_from("localhost").unwrap();
@@ -40,14 +38,72 @@ async fn main() -> std::io::Result<()> {
let stream = connector.connect(dnsname, stream).await?; let stream = connector.connect(dnsname, stream).await?;
let mut transport = Framed::new(stream, LengthDelimitedCodec::new()); let mut transport = Framed::new(stream, LengthDelimitedCodec::new());
let msg = FromGuestServerMessage::Announce { name: "cicciopizza".into() };
let msg1 = FromServerMessage::WhoAmI; transport.send(rmp_serde::to_vec(&msg).unwrap().into()).await.unwrap();
transport.send(rmp_serde::to_vec(&msg1).unwrap().into()).await.unwrap(); let mut myserver_cert: Option<CertificateDer> = None;
for i in 0..10 { let mut myserver_prkey: Option<PrivatePkcs8KeyDer> = None;
let msg = FromServerMessage::ChangeName { name: format!("{client_name}-{i}") }; match transport.next().await {
transport.send(rmp_serde::to_vec(&msg).unwrap().into()).await.unwrap(); None => {
tokio::time::sleep(std::time::Duration::from_secs(1)).await; info!("None in the transport.next() ???");
}
Some(item) => match item {
Ok(buf) => {
use ToGuestServerMessage::*;
let msg: ToGuestServerMessage = rmp_serde::from_slice(&buf).unwrap();
info!("{:?}", msg);
match msg {
OkAnnounce { server_cert, server_prkey } => {
info!("Ok Announce");
let (server_cert, server_prkey) = okannounce_to_cert(server_cert, server_prkey);
myserver_cert = Some(server_cert);
myserver_prkey = Some(server_prkey);
}
FailedNameAlreadyOccupied => {
error!("Failed Announce");
return Ok(());
}
}
}
Err(e) => {
error!("Error: {:?}", e);
}
}
} }
if let (Some(server_cert), Some(server_prkey)) = (myserver_cert, myserver_prkey) {
let tlsconfig = ClientConfig::builder()
.with_root_certificates(broker_root_cert_store)
.with_client_auth_cert(vec![server_cert, root_server_cert], server_prkey.into())
.unwrap();
let connector = TlsConnector::from(Arc::new(tlsconfig));
let dnsname = ServerName::try_from("localhost").unwrap();
let stream = TcpStream::connect("localhost:2541").await?;
let stream = connector.connect(dnsname, stream).await?;
let transport = Framed::new(stream, LengthDelimitedCodec::new());
transport.for_each(|item| async move {
match item {
Ok(buf) => {
use ToServerMessage::*;
let msg: ToServerMessage = rmp_serde::from_slice(&buf).unwrap();
match msg {
Required { id } => {
info!("I'm required with Connection ID {}", id);
}
YouAre(name) => match name {
YouAreValues::Registered { name } => {
info!("I am {}", name);
}
YouAreValues::NotRegistered => {
info!("I'm not registered");
}
}
}
}
Err(e) => {
error!("Error: {:?}", e);
}
}
}).await;
}
Ok(()) Ok(())
} }

View File

@@ -57,6 +57,21 @@ pub enum FromGuestServerMessage {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum ToGuestServerMessage { pub enum ToGuestServerMessage {
OkAnnounce {}, OkAnnounce {server_cert: Vec<u8>, server_prkey: Vec<u8>},
FailedAnnounce { status_code: u32, msg: Option<String> }, // TODO: make it better? FailedNameAlreadyOccupied,
}
pub fn okannounce_to_cert<'a>(server_cert: Vec<u8>, server_prkey: Vec<u8>) -> (CertificateDer<'a>, PrivatePkcs8KeyDer<'a>) {
let server_cert = CertificateDer::from(server_cert);
let server_prkey = PrivatePkcs8KeyDer::from(server_prkey);
(server_cert, server_prkey)
}
impl ToGuestServerMessage {
pub fn make_okannounce(server_cert: CertificateDer, server_prkey: PrivatePkcs8KeyDer) -> Self {
ToGuestServerMessage::OkAnnounce{
server_cert: server_cert.to_vec(),
server_prkey: server_prkey.secret_pkcs8_der().to_vec()
}
}
} }