use std::any::Any;
use crate::users::UsersFile;
use quincy::config::ServerProtocolConfig;
use quincy::error::{AuthError, Result};
use quinn::Connection;
use reishi_quinn::PeerIdentity;
use rustls::pki_types::CertificateDer;
pub fn identify_peer(
connection: &Connection,
protocol: &ServerProtocolConfig,
users: &UsersFile,
) -> Result<String> {
let peer_identity = connection
.peer_identity()
.ok_or(AuthError::HandshakeRejected)?;
match protocol {
ServerProtocolConfig::Noise(_) => identify_noise_peer(peer_identity, users),
ServerProtocolConfig::Tls(_) => identify_tls_peer(peer_identity, users),
}
}
fn identify_noise_peer(peer_identity: Box<dyn Any>, users: &UsersFile) -> Result<String> {
let noise_identity = peer_identity
.downcast_ref::<PeerIdentity>()
.ok_or(AuthError::HandshakeRejected)?;
if let Some(pq_pubkey) = &noise_identity.pq_public_key {
return users
.find_user_by_noise_pq_pubkey(pq_pubkey)
.map(|user| user.to_string())
.ok_or(AuthError::UserUnknown.into());
}
users
.find_user_by_noise_pubkey(&noise_identity.public_key)
.map(|user| user.to_string())
.ok_or(AuthError::UserUnknown.into())
}
fn identify_tls_peer(peer_identity: Box<dyn Any>, users: &UsersFile) -> Result<String> {
let certs = peer_identity
.downcast_ref::<Vec<CertificateDer<'static>>>()
.ok_or(AuthError::HandshakeRejected)?;
let end_entity = certs.first().ok_or(AuthError::HandshakeRejected)?;
let fingerprint = quincy::certificates::compute_cert_fingerprint(end_entity);
users
.find_user_by_cert_fingerprint(&fingerprint)
.map(|s| s.to_string())
.ok_or(AuthError::UserUnknown.into())
}