Update to modern code

master
Edward Shen 2021-12-01 22:08:40 -08:00
parent 63eba4dc37
commit a838a94ce9
Signed by: edward
GPG Key ID: 19182661E818369F
6 changed files with 493 additions and 512 deletions

916
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@ codegen-units = 1
debug = 1
[dependencies]
actix-web = { version = "4.0.0-beta.4", features = [ "rustls" ] }
actix-web = { version = "4.0.0-beta.8", features = [ "rustls" ] }
arc-swap = "1"
async-trait = "0.1"
base64 = "0.13"
@ -29,7 +29,7 @@ bincode = "1"
bytes = { version = "1", features = [ "serde" ] }
chacha20 = "0.7"
chrono = { version = "0.4", features = [ "serde" ] }
clap = { version = "3.0.0-beta.2", features = [ "wrap_help" ] }
clap = { version = "3.0.0-beta.4", features = [ "wrap_help" ] }
ctrlc = "3"
dotenv = "0.15"
flate2 = { version = "1", features = [ "tokio" ] }
@ -44,7 +44,8 @@ parking_lot = "0.11"
prometheus = { version = "0.12", features = [ "process" ] }
redis = "0.21"
reqwest = { version = "0.11", default_features = false, features = [ "json", "stream", "rustls-tls" ] }
rustls = "0.19"
rustls = "0.20"
rustls-pemfile = "0.2"
serde = "1"
serde_json = "1"
serde_repr = "0.1"

View File

@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};
use clap::{crate_authors, crate_description, crate_version, Clap};
use clap::{crate_authors, crate_description, crate_version, Parser};
use log::LevelFilter;
use once_cell::sync::OnceCell;
use serde::{Deserialize, Serialize};
@ -301,7 +301,7 @@ struct YamlExtendedOptions {
redis_url: Option<Url>,
}
#[derive(Clap, Clone)]
#[derive(Parser, Clone)]
#[clap(version = crate_version!(), author = crate_authors!(), about = crate_description!())]
struct CliArgs {
/// The port to listen on.

View File

@ -22,7 +22,9 @@ use config::Config;
use maxminddb::geoip2;
use parking_lot::RwLock;
use redis::Client as RedisClient;
use rustls::{NoClientAuth, ServerConfig};
use rustls::server::NoClientAuth;
use rustls::ServerConfig;
use sodiumoxide::crypto::stream::xchacha20::gen_key;
use state::{RwLockServerState, ServerState};
use stop::send_stop;
@ -239,11 +241,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
server.bind(bind_address)?.run().await?;
} else {
// Rustls only supports TLS 1.2 and 1.3.
let tls_config = {
let mut tls_config = ServerConfig::new(NoClientAuth::new());
tls_config.cert_resolver = Arc::new(DynamicServerCert);
tls_config
};
let tls_config = ServerConfig::builder()
.with_safe_defaults()
.with_client_cert_verifier(NoClientAuth::new())
.with_cert_resolver(Arc::new(DynamicServerCert));
server.bind_rustls(bind_address, tls_config)?.run().await?;
}

View File

@ -2,9 +2,9 @@ use std::net::{IpAddr, SocketAddr};
use std::sync::atomic::Ordering;
use std::{io::BufReader, sync::Arc};
use rustls::internal::pemfile::{certs, rsa_private_keys};
use rustls::sign::{RSASigningKey, SigningKey};
use rustls::Certificate;
use rustls::sign::{CertifiedKey, RsaSigningKey, SigningKey};
use rustls::{Certificate, PrivateKey};
use rustls_pemfile::{certs, rsa_private_keys};
use serde::de::{MapAccess, Visitor};
use serde::{Deserialize, Serialize};
use serde_repr::Deserialize_repr;
@ -15,8 +15,8 @@ use url::Url;
use crate::client::HTTP_CLIENT;
use crate::config::{ClientSecret, Config};
use crate::state::{
RwLockServerState, PREVIOUSLY_COMPROMISED, PREVIOUSLY_PAUSED, TLS_CERTS,
TLS_PREVIOUSLY_CREATED, TLS_SIGNING_KEY,
RwLockServerState, CERTIFIED_KEY, PREVIOUSLY_COMPROMISED, PREVIOUSLY_PAUSED,
TLS_PREVIOUSLY_CREATED,
};
use crate::units::{Bytes, BytesPerSecond, Port};
use crate::CLIENT_API_VERSION;
@ -104,7 +104,7 @@ pub enum ErrorCode {
pub struct Tls {
pub created_at: String,
pub priv_key: Arc<Box<dyn SigningKey>>,
pub priv_key: Arc<RsaSigningKey>,
pub certs: Vec<Certificate>,
}
@ -137,7 +137,8 @@ impl<'de> Deserialize<'de> for Tls {
priv_key = rsa_private_keys(&mut BufReader::new(value.as_bytes()))
.ok()
.and_then(|mut v| {
v.pop().and_then(|key| RSASigningKey::new(&key).ok())
v.pop()
.and_then(|key| RsaSigningKey::new(&PrivateKey(key)).ok())
});
}
"certificate" => {
@ -150,8 +151,8 @@ impl<'de> Deserialize<'de> for Tls {
match (created_at, priv_key, certificates) {
(Some(created_at), Some(priv_key), Some(certificates)) => Ok(Tls {
created_at,
priv_key: Arc::new(Box::new(priv_key)),
certs: certificates,
priv_key: Arc::new(priv_key),
certs: certificates.into_iter().map(Certificate).collect(),
}),
_ => Err(serde::de::Error::custom("Could not deserialize tls info")),
}
@ -213,8 +214,12 @@ pub async fn update_server_state(
.get()
.unwrap()
.swap(Arc::new(tls.created_at));
TLS_SIGNING_KEY.get().unwrap().swap(tls.priv_key);
TLS_CERTS.get().unwrap().swap(Arc::new(tls.certs));
CERTIFIED_KEY.store(Some(Arc::new(CertifiedKey {
cert: tls.certs.clone(),
key: Arc::clone(&tls.priv_key) as Arc<dyn SigningKey>,
ocsp: None,
sct_list: None,
})));
}
let previously_compromised = PREVIOUSLY_COMPROMISED.load(Ordering::Acquire);

View File

@ -1,15 +1,16 @@
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use crate::client::HTTP_CLIENT;
use crate::config::{ClientSecret, Config, OFFLINE_MODE};
use crate::ping::{Request, Response, CONTROL_CENTER_PING_URL};
use arc_swap::ArcSwap;
use arc_swap::{ArcSwap, ArcSwapOption};
use once_cell::sync::OnceCell;
use parking_lot::RwLock;
use rustls::sign::{CertifiedKey, SigningKey};
use rustls::server::{ClientHello, ResolvesServerCert};
use rustls::sign::{CertifiedKey, RsaSigningKey, SigningKey};
use rustls::Certificate;
use rustls::{ClientHello, ResolvesServerCert};
use sodiumoxide::crypto::box_::{PrecomputedKey, PRECOMPUTEDKEYBYTES};
use thiserror::Error;
use tracing::{error, info, warn};
@ -26,8 +27,10 @@ pub static PREVIOUSLY_PAUSED: AtomicBool = AtomicBool::new(false);
pub static PREVIOUSLY_COMPROMISED: AtomicBool = AtomicBool::new(false);
pub static TLS_PREVIOUSLY_CREATED: OnceCell<ArcSwap<String>> = OnceCell::new();
pub static TLS_SIGNING_KEY: OnceCell<ArcSwap<Box<dyn SigningKey>>> = OnceCell::new();
pub static TLS_CERTS: OnceCell<ArcSwap<Vec<Certificate>>> = OnceCell::new();
static TLS_SIGNING_KEY: OnceCell<ArcSwap<RsaSigningKey>> = OnceCell::new();
static TLS_CERTS: OnceCell<ArcSwap<Vec<Certificate>>> = OnceCell::new();
pub static CERTIFIED_KEY: ArcSwapOption<CertifiedKey> = ArcSwapOption::const_empty();
#[derive(Error, Debug)]
pub enum ServerInitError {
@ -91,6 +94,14 @@ impl ServerState {
info!("This client's URL has been set to {}", resp.url);
let tls = resp.tls.unwrap();
CERTIFIED_KEY.store(Some(Arc::new(CertifiedKey {
cert: tls.certs.clone(),
key: Arc::clone(&tls.priv_key) as Arc<dyn SigningKey>,
ocsp: None,
sct_list: None,
})));
std::mem::drop(
TLS_PREVIOUSLY_CREATED.set(ArcSwap::from_pointee(tls.created_at)),
);
@ -146,22 +157,9 @@ pub struct RwLockServerState(pub RwLock<ServerState>);
pub struct DynamicServerCert;
impl ResolvesServerCert for DynamicServerCert {
fn resolve(&self, _: ClientHello) -> Option<CertifiedKey> {
fn resolve(&self, _: ClientHello) -> Option<Arc<CertifiedKey>> {
// TODO: wait for actix-web to use a new version of rustls so we can
// remove cloning the certs all the time
Some(CertifiedKey {
cert: TLS_CERTS
.get()
.expect("tls cert to exist")
.load()
.as_ref()
.clone(),
key: TLS_SIGNING_KEY
.get()
.expect("tls signing key to exist")
.load_full(),
ocsp: None,
sct_list: None,
})
CERTIFIED_KEY.load_full()
}
}