From 2d295c6f178ef1bb0d8d00b61418ccfd0068c7b8 Mon Sep 17 00:00:00 2001 From: Raul Gherman Date: Sat, 7 Sep 2024 17:57:03 +0300 Subject: [PATCH] [1] --- kaminari/src/lib.rs | 8 - kaminari/src/nop.rs | 13 +- kaminari/src/opt.rs | 2 +- kaminari/src/tls.rs | 385 ------------------------------------------ kaminari/src/trick.rs | 19 +-- kaminari/src/ws.rs | 42 ----- 6 files changed, 3 insertions(+), 466 deletions(-) diff --git a/kaminari/src/lib.rs b/kaminari/src/lib.rs index e6655a3..af3f1df 100644 --- a/kaminari/src/lib.rs +++ b/kaminari/src/lib.rs @@ -16,14 +16,6 @@ pub trait AsyncConnect { fn connect<'a>(&'a self, stream: S, buf: &'a mut [u8]) -> Self::ConnectFut<'a>; } -pub trait AsyncAccept { - type Stream: IOStream; - type AcceptFut<'a>: Future> - where - Self: 'a; - fn accept<'a>(&'a self, stream: S, buf: &'a mut [u8]) -> Self::AcceptFut<'a>; -} - pub mod nop; pub mod opt; pub mod trick; diff --git a/kaminari/src/nop.rs b/kaminari/src/nop.rs index 6a3fd45..0ab9d4d 100644 --- a/kaminari/src/nop.rs +++ b/kaminari/src/nop.rs @@ -2,7 +2,7 @@ use std::io::Result; use std::future::Future; use std::fmt::{Display, Formatter}; -use super::{IOStream, AsyncAccept, AsyncConnect}; +use super::{IOStream, AsyncConnect}; #[derive(Debug, Clone, Copy)] pub struct NopConnect {} @@ -28,14 +28,3 @@ where fn connect(&self, stream: S, _: &mut [u8]) -> Self::ConnectFut<'_> { async move { Ok(stream) } } } - -impl AsyncAccept for NopAccept -where - S: IOStream, -{ - type Stream = S; - - type AcceptFut<'a> = impl Future> where Self:'a; - - fn accept(&self, stream: S, _: &mut [u8]) -> Self::AcceptFut<'_> { async move { Ok(stream) } } -} diff --git a/kaminari/src/opt.rs b/kaminari/src/opt.rs index c0a30b8..f27bc61 100644 --- a/kaminari/src/opt.rs +++ b/kaminari/src/opt.rs @@ -5,7 +5,7 @@ use super::ws::WsConf; #[cfg(feature = "tls")] -use super::tls::{TlsClientConf, TlsServerConf}; +use super::tls::TlsClientConf; #[macro_export] macro_rules! has_opt { diff --git a/kaminari/src/tls.rs b/kaminari/src/tls.rs index 621f483..6bfae68 100644 --- a/kaminari/src/tls.rs +++ b/kaminari/src/tls.rs @@ -7,7 +7,6 @@ use super::{IOStream, AsyncAccept, AsyncConnect}; use tokio_rustls::rustls; use rustls::client::ClientConfig; -use rustls::server::ServerConfig; use rustls::pki_types::ServerName; use tokio_rustls::{TlsAcceptor, TlsConnector}; @@ -149,387 +148,3 @@ where } } } - -// ========== server ========== -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TlsServerConf { - pub crt: String, - pub key: String, - pub ocsp: String, - pub server_name: String, -} - -impl Display for TlsServerConf { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!( - f, - "cert: {}, key: {}, oscp: {}, server_name: {}", - self.crt, self.key, self.ocsp, self.server_name - ) - } -} - -#[derive(Clone)] -pub struct TlsAccept { - lis: T, - ac: TlsAcceptor, -} - -impl Display for TlsAccept -where - T: Display, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "[tls]{}", self.lis) } -} - -impl Debug for TlsAccept -where - T: Debug, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("TlsAccept").field("lis", &self.lis).finish() - } -} - -impl TlsAccept { - pub fn new(lis: T, conf: TlsServerConf) -> Self { - let TlsServerConf { - crt, - key, - ocsp, - server_name, - } = conf; - - let (cert, key) = if !crt.is_empty() && !key.is_empty() { - ( - utils::read_certificates(&crt).expect("failed to read certificate"), - utils::read_private_key(&key).expect("failed to read private key"), - ) - } else if !server_name.is_empty() { - utils::generate_self_signed(&server_name) - } else { - panic!("no certificate or private key supplied") - }; - - let ocsp = if !ocsp.is_empty() { - utils::read_ocsp(&ocsp).expect("failed to read ocsp") - } else { - Vec::new() - }; - - let conf = ServerConfig::builder() - .with_no_client_auth() - .with_single_cert_with_ocsp(cert, key, ocsp) - .expect("bad certificate or key"); - - Self { - lis, - ac: Arc::new(conf).into(), - } - } - - // use shared cert, key - pub fn new_shared(lis: T, conf: TlsServerConf) -> Self { - let TlsServerConf { - crt, - key, - ocsp, - server_name, - } = conf; - - let ocsp = if !ocsp.is_empty() { - Some(utils::read_ocsp(&ocsp).expect("failed to read ocsp")) - } else { - None - }; - - let cert_resolver = if !crt.is_empty() && !key.is_empty() { - utils::new_crt_key_resolver(crt, key, ocsp) - } else if !server_name.is_empty() { - utils::new_self_signed_resolver(server_name) - } else { - panic!("no certificate or private key supplied") - }; - - let conf = ServerConfig::builder() - .with_no_client_auth() - .with_cert_resolver(cert_resolver); - - Self { - lis, - ac: Arc::new(conf).into(), - } - } -} - -impl AsyncAccept for TlsAccept -where - S: IOStream, - T: AsyncAccept, -{ - type Stream = TlsServerStream; - - type AcceptFut<'a> = impl Future> +'a where Self:'a; - - fn accept<'a>(&'a self, stream: S, buf: &'a mut [u8]) -> Self::AcceptFut<'a> { - async move { - let stream = self.lis.accept(stream, buf).await?; - self.ac.accept(stream).await - } - } -} - -#[allow(unused)] -mod utils { - pub use client::*; - pub use server::*; - - mod client { - use std::sync::Arc; - use lazy_static::lazy_static; - - use tokio_rustls::rustls::{self, pki_types}; - use pki_types::{CertificateDer, PrivateKeyDer, ServerName}; - use rustls::{RootCertStore, DigitallySignedStruct, SignatureScheme}; - use rustls::client::WebPkiServerVerifier; - use rustls::client::danger::{ServerCertVerified, ServerCertVerifier, HandshakeSignatureValid}; - - pub fn firefox_roots() -> RootCertStore { - use webpki_roots::TLS_SERVER_ROOTS; - RootCertStore { - roots: Vec::from(TLS_SERVER_ROOTS), - } - } - - #[derive(Debug)] - pub struct SkipVerify {} - impl ServerCertVerifier for SkipVerify { - fn verify_server_cert( - &self, - _end_entity: &CertificateDer<'_>, - _intermediates: &[CertificateDer<'_>], - _server_name: &ServerName, - _ocsp_response: &[u8], - _now: pki_types::UnixTime, - ) -> Result { - Ok(ServerCertVerified::assertion()) - } - - fn verify_tls12_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - - fn verify_tls13_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - - fn supported_verify_schemes(&self) -> Vec { - vec![ - SignatureScheme::RSA_PKCS1_SHA1, - SignatureScheme::ECDSA_SHA1_Legacy, - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::RSA_PKCS1_SHA384, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::RSA_PKCS1_SHA512, - SignatureScheme::ECDSA_NISTP521_SHA512, - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PSS_SHA384, - SignatureScheme::RSA_PSS_SHA512, - SignatureScheme::ED25519, - SignatureScheme::ED448, - ] - } - } - - fn new_insecure_verifier() -> Arc { - lazy_static! { - static ref ARC: Arc = Arc::new(SkipVerify {}); - } - ARC.clone() - } - - fn new_firefox_verifier() -> Arc { - lazy_static! { - static ref ARC: Arc = { - let ff = Arc::new(firefox_roots()); - WebPkiServerVerifier::builder(Arc::new(firefox_roots())) - .build() - .unwrap() - }; - } - ARC.clone() - } - - pub fn new_verifier(insecure: bool) -> Arc { - if insecure { - new_insecure_verifier() - } else { - new_firefox_verifier() - } - } - } - - mod server { - use std::io::{BufReader, Result}; - use std::fs::{self, File}; - use std::sync::{Arc, Mutex}; - - use tokio_rustls::rustls::{self, pki_types}; - use pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer as Der}; - use rustls::sign; - use rustls::server::ResolvesServerCert; - use rustls::server::ClientHello; - - use rustls_pemfile::Item; - use webpki_roots::TLS_SERVER_ROOTS; - - use lazy_static::lazy_static; - - pub fn read_certificates(path: &str) -> Result>> { - let mut file = BufReader::new(File::open(path)?); - let mut certs = Vec::new(); - - // pem - while let Ok(Some(item)) = rustls_pemfile::read_one(&mut file) { - if let Item::X509Certificate(cert) = item { - certs.push(cert); - } - } - - // der - if certs.is_empty() { - certs = vec![CertificateDer::from(fs::read(path)?)]; - } - - Ok(certs) - } - - pub fn read_private_key(path: &str) -> Result> { - let mut file = BufReader::new(File::open(path)?); - let mut priv_key = None; - - // pem - while let Ok(Some(item)) = rustls_pemfile::read_one(&mut file) { - priv_key = Some(match item { - Item::Pkcs1Key(k) => k.into(), - Item::Pkcs8Key(k) => k.into(), - Item::Sec1Key(k) => k.into(), - _ => continue, - }); - break; - } - - // der - priv_key.map_or_else(|| fs::read(path).map(|x| Der::from(x).into()), Ok) - } - - pub fn read_ocsp(path: &str) -> Result> { fs::read(path) } - - pub fn generate_self_signed( - server_name: &str, - ) -> (Vec>, PrivateKeyDer<'static>) { - let self_signed = rcgen::generate_simple_self_signed(vec![server_name.to_string()]) - .expect("failed to generate self signed certificate and private key"); - - let key = Der::from(self_signed.serialize_private_key_der()).into(); - - let cert = self_signed - .serialize_der() - .map(CertificateDer::from) - .expect("failed to serialize self signed certificate"); - - (vec![cert], key) - } - - // copy from rustls: - // https://docs.rs/rustls/latest/src/rustls/server/handy.rs.html - #[derive(Debug)] - pub struct AlwaysResolvesChain(Arc); - - impl ResolvesServerCert for AlwaysResolvesChain { - fn resolve(&self, _: ClientHello) -> Option> { - Some(Arc::clone(&self.0)) - } - } - - pub fn new_resolver( - cert: Vec>, - priv_key: &PrivateKeyDer, - ocsp: Option>, - ) -> Arc { - // this is for ring - use rustls::crypto::ring as crypto; - let key = crypto::sign::any_supported_type(priv_key).expect("invalid key"); - Arc::new(AlwaysResolvesChain(Arc::new(sign::CertifiedKey { - cert, - key, - ocsp, - }))) - } - - pub fn new_self_signed_resolver(server_name: String) -> Arc { - type Store = Mutex)>>; - lazy_static! { - static ref STORE: Store = { Mutex::new(Vec::new()) }; - } - - // hold the lock - let mut store = STORE.lock().unwrap(); - - // simply increase ref count - if let Some(x) = store.iter().find(|(x, _)| *x == server_name) { - return x.1.clone(); - } - - // generate a new cert - let (cert, key) = generate_self_signed(&server_name); - let resolver = new_resolver(cert, &key, None); - - store.push((server_name, resolver.clone())); - store.shrink_to_fit(); - - resolver - } - - pub fn new_crt_key_resolver( - crt: String, - key: String, - ocsp: Option>, - ) -> Arc { - type Store = Mutex)>>; - lazy_static! { - static ref STORE: Store = { Mutex::new(Vec::new()) }; - } - - // hold the lock - let mut store = STORE.lock().unwrap(); - - // find based on key path, no real data - // simply increase ref count - if let Some(x) = store.iter().find(|(x, _)| *x == key) { - return x.1.clone(); - } - - // read cert and key - let cert = read_certificates(&crt).expect("failed to read certificate"); - let priv_key = read_private_key(&key).expect("failed to read private key"); - let resolver = new_resolver(cert, &priv_key, ocsp); - - store.push((key, resolver.clone())); - store.shrink_to_fit(); - - resolver - } - } -} diff --git a/kaminari/src/trick.rs b/kaminari/src/trick.rs index e133c6e..27d7767 100644 --- a/kaminari/src/trick.rs +++ b/kaminari/src/trick.rs @@ -2,7 +2,7 @@ use core::ops::Deref; use std::io::Result; use std::future::Future; -use super::{IOStream, AsyncAccept, AsyncConnect}; +use super::{IOStream, AsyncConnect}; // Safety: // pointer is not null once inited(comes from an immutable ref) @@ -56,20 +56,3 @@ where } } } - -impl AsyncAccept for Ref -where - S: IOStream, - T: AsyncAccept, -{ - type Stream = T::Stream; - - type AcceptFut<'a> = impl Future> +'a where Self:'a; - - fn accept<'a>(&'a self, stream: S, buf: &'a mut [u8]) -> Self::AcceptFut<'a> { - async move { - let stream = self.as_ref().accept(stream, buf).await?; - Ok(stream) - } - } -} diff --git a/kaminari/src/ws.rs b/kaminari/src/ws.rs index 9d748fc..4040e6d 100644 --- a/kaminari/src/ws.rs +++ b/kaminari/src/ws.rs @@ -121,45 +121,3 @@ where } } } - -// ========== server ========== -#[derive(Debug, Clone)] -pub struct WsAccept { - lis: T, - conf: WsConf, -} - -impl Display for WsAccept -where - T: Display, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "[ws]{}", self.lis) } -} - -impl WsAccept { - #[inline] - pub const fn new(lis: T, conf: WsConf) -> Self { Self { lis, conf } } -} - -impl AsyncAccept for WsAccept -where - S: IOStream, - T: AsyncAccept, -{ - type Stream = WsServerStream; - - type AcceptFut<'a> = impl Future> +'a where Self:'a; - - fn accept<'a>(&'a self, stream: S, buf: &'a mut [u8]) -> Self::AcceptFut<'a> { - async move { - let stream = self.lis.accept(stream, buf).await?; - - let stream = - Endpoint::<_, Server>::accept_async(stream, buf, &self.conf.host, &self.conf.path) - .await? - .guard(); - - Ok(stream) - } - } -}