This commit is contained in:
Herbert Wolverson 2023-04-13 14:40:27 +00:00
parent b0a14a1a27
commit 19f34f252e
7 changed files with 153 additions and 119 deletions

105
src/rust/Cargo.lock generated
View File

@ -9,20 +9,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
<<<<<<< Updated upstream
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"getrandom 0.2.9",
"once_cell",
"version_check",
]
[[package]]
=======
>>>>>>> Stashed changes
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -143,7 +140,6 @@ dependencies = [
"proc-macro2",
"quote",
"syn 2.0.14",
<<<<<<< Updated upstream
]
[[package]]
@ -153,8 +149,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
dependencies = [
"num-traits",
=======
>>>>>>> Stashed changes
]
[[package]]
@ -408,8 +402,6 @@ dependencies = [
]
[[package]]
<<<<<<< Updated upstream
=======
name = "cipher"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -421,7 +413,6 @@ dependencies = [
]
[[package]]
>>>>>>> Stashed changes
name = "clang-sys"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -746,8 +737,6 @@ dependencies = [
]
[[package]]
<<<<<<< Updated upstream
=======
name = "curve25519-dalek"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -761,7 +750,6 @@ dependencies = [
]
[[package]]
>>>>>>> Stashed changes
name = "dashmap"
version = "5.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -822,8 +810,6 @@ dependencies = [
"proc-macro2-diagnostics",
"quote",
"syn 2.0.14",
<<<<<<< Updated upstream
=======
]
[[package]]
@ -833,7 +819,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
>>>>>>> Stashed changes
]
[[package]]
@ -844,29 +829,7 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "dlopen2"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b121caccfc363e4d9a4589528f3bef7c71b83c6ed01c8dc68cbeeb7fd29ec698"
dependencies = [
"dlopen2_derive",
"libc",
"once_cell",
"winapi",
]
[[package]]
name = "dlopen2_derive"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a09ac8bb8c16a282264c379dffba707b9c998afc7506009137f3c6136888078"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"subtle",
]
[[package]]
@ -925,12 +888,12 @@ dependencies = [
]
[[package]]
<<<<<<< Updated upstream
name = "dotenvy"
version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
=======
[[package]]
name = "dryoc"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -944,12 +907,12 @@ dependencies = [
"libc",
"rand_core 0.6.4",
"salsa20",
"serde",
"sha2",
"subtle",
"winapi",
"zeroize",
]
>>>>>>> Stashed changes
[[package]]
name = "either"
@ -1127,7 +1090,6 @@ dependencies = [
]
[[package]]
<<<<<<< Updated upstream
name = "futures-intrusive"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -1142,11 +1104,6 @@ dependencies = [
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
=======
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
>>>>>>> Stashed changes
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
@ -1215,15 +1172,9 @@ dependencies = [
[[package]]
name = "getrandom"
<<<<<<< Updated upstream
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
=======
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
>>>>>>> Stashed changes
dependencies = [
"cfg-if",
"libc",
@ -1231,8 +1182,6 @@ dependencies = [
]
[[package]]
<<<<<<< Updated upstream
=======
name = "getrandom"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -1244,7 +1193,6 @@ dependencies = [
]
[[package]]
>>>>>>> Stashed changes
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -1327,7 +1275,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
<<<<<<< Updated upstream
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -1348,12 +1295,10 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
"digest 0.10.6",
]
[[package]]
=======
>>>>>>> Stashed changes
name = "http"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -1483,6 +1428,15 @@ dependencies = [
"libc",
]
[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -1729,6 +1683,7 @@ version = "0.1.0"
dependencies = [
"bincode",
"criterion",
"dryoc",
"log",
"lqos_config",
"lqos_utils",
@ -1959,7 +1914,7 @@ version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
dependencies = [
"digest",
"digest 0.10.6",
]
[[package]]
@ -2585,7 +2540,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags 1.3.2",
<<<<<<< Updated upstream
]
[[package]]
@ -2594,11 +2548,9 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"getrandom 0.2.9",
"redox_syscall 0.2.16",
"thiserror",
=======
>>>>>>> Stashed changes
]
[[package]]
@ -2837,7 +2789,6 @@ dependencies = [
"libc",
"linux-raw-sys",
"windows-sys 0.48.0",
<<<<<<< Updated upstream
]
[[package]]
@ -2858,8 +2809,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
dependencies = [
"base64",
=======
>>>>>>> Stashed changes
]
[[package]]
@ -3025,7 +2974,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
"digest 0.10.6",
]
[[package]]
@ -3111,7 +3060,6 @@ dependencies = [
[[package]]
name = "spin"
<<<<<<< Updated upstream
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
@ -3132,11 +3080,6 @@ dependencies = [
"nom",
"unicode_categories",
]
=======
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
>>>>>>> Stashed changes
[[package]]
name = "sqlite"
@ -3340,9 +3283,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "subtle"
version = "2.5.0"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
@ -3807,15 +3750,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c"
[[package]]
<<<<<<< Updated upstream
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
=======
>>>>>>> Stashed changes
name = "url"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -4298,8 +4238,6 @@ dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
<<<<<<< Updated upstream
=======
]
[[package]]
@ -4320,5 +4258,4 @@ dependencies = [
"proc-macro2",
"quote",
"syn 2.0.14",
>>>>>>> Stashed changes
]

View File

@ -1,9 +1,5 @@
<<<<<<< Updated upstream
use lqos_bus::long_term_stats::{LicenseCheck, LicenseReply};
use pgdb::sqlx::{Pool, Postgres};
=======
use lqos_bus::long_term_stats::{LicenseReply, LicenseRequest};
>>>>>>> Stashed changes
use pgdb::sqlx::{Pool, Postgres};
use std::net::SocketAddr;
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
@ -52,7 +48,11 @@ pub async fn start() -> anyhow::Result<()> {
}
}
async fn decode(buf: &[u8], address: SocketAddr, pool: Pool<Postgres>) -> anyhow::Result<LicenseReply> {
async fn decode(
buf: &[u8],
address: SocketAddr,
pool: Pool<Postgres>,
) -> anyhow::Result<LicenseReply> {
const U64SIZE: usize = std::mem::size_of::<u64>();
let version_buf = &buf[0..2].try_into()?;
let version = u16::from_be_bytes(*version_buf);
@ -64,7 +64,7 @@ async fn decode(buf: &[u8], address: SocketAddr, pool: Pool<Postgres>) -> anyhow
1 => {
let start = 2 + U64SIZE;
let end = start + size as usize;
let payload: LicenseCheck = serde_cbor::from_slice(&buf[start..end])?;
let payload: LicenseRequest = serde_cbor::from_slice(&buf[start..end])?;
let license = check_license(&payload, address, pool).await?;
Ok(license)
}
@ -80,29 +80,36 @@ async fn check_license(
address: SocketAddr,
pool: Pool<Postgres>,
) -> anyhow::Result<LicenseReply> {
log::info!("Checking license from {address:?}, key: {}", request.key);
if request.key == "test" {
log::info!("License is valid");
Ok(LicenseReply::Valid {
expiry: 0, // Temporary value
stats_host: "127.0.0.1:9127".to_string(), // Also temporary
})
} else {
match pgdb::get_stats_host_for_key(pool, &request.key).await {
Ok(host) => {
match request {
LicenseRequest::LicenseCheck { key } => {
log::info!("Checking license from {address:?}, key: {key}");
if key == "test" {
log::info!("License is valid");
return Ok(LicenseReply::Valid {
expiry: 0, // Temporary value
stats_host: host,
});
}
Err(e) => {
log::warn!("Unable to get stats host for key: {e:?}");
}
}
Ok(LicenseReply::Valid {
expiry: 0, // Temporary value
stats_host: "127.0.0.1:9127".to_string(), // Also temporary
})
} else {
match pgdb::get_stats_host_for_key(pool, key).await {
Ok(host) => {
log::info!("License is valid");
return Ok(LicenseReply::Valid {
expiry: 0, // Temporary value
stats_host: host,
});
}
Err(e) => {
log::warn!("Unable to get stats host for key: {e:?}");
}
}
log::info!("License is denied");
Ok(LicenseReply::Denied)
log::info!("License is denied");
Ok(LicenseReply::Denied)
}
}
LicenseRequest::KeyExchange { node_id, license_key, public_key } => {
Ok(LicenseReply::Denied)
}
}
}

View File

@ -18,6 +18,7 @@ tokio = { version = "1", features = [ "rt", "macros", "net", "io-util", "time" ]
log = "0"
nix = "0"
serde_cbor = "0" # For RFC8949/7409 format C binary objects
dryoc = { version = "0.5", features = ["serde"] }
[dev-dependencies]
criterion = { version = "0", features = [ "html_reports", "async_tokio"] }

View File

@ -1,3 +1,4 @@
use dryoc::dryocbox::PublicKey;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use tokio::{
@ -102,7 +103,7 @@ pub enum LicenseRequest {
/// The license key of the requesting shaper node
license_key: String,
/// The sodium-style public key of the requesting shaper node
public_key: Vec<u8>,
public_key: PublicKey,
}
}
@ -121,7 +122,7 @@ pub enum LicenseReply {
/// Key Exchange
MyPublicKey{
/// The server's public key
public_key: Vec<u8>,
public_key: PublicKey,
}
}
@ -162,7 +163,27 @@ fn build_license_request(key: String) -> Result<Vec<u8>, LicenseCheckError> {
Ok(result)
}
const LICENSE_SERVER: &str = "192.168.100.11:9126";
fn build_key_exchange_request(node_id: String, license_key: String, public_key: PublicKey) -> Result<Vec<u8>, LicenseCheckError> {
let mut result = Vec::new();
let payload = serde_cbor::to_vec(&LicenseRequest::KeyExchange { node_id, license_key, public_key });
if let Err(e) = payload {
log::warn!("Unable to serialize statistics. Not sending them.");
log::warn!("{e:?}");
return Err(LicenseCheckError::SerializeFail);
}
let payload = payload.unwrap();
// Store the version as network order
result.extend(1u16.to_be_bytes());
// Store the payload size as network order
result.extend((payload.len() as u64).to_be_bytes());
// Store the payload itself
result.extend(payload);
Ok(result)
}
const LICENSE_SERVER: &str = "192.168.100.10:9126";
/// Ask the license server if the license is valid
///
@ -199,6 +220,37 @@ pub async fn ask_license_server(key: String) -> Result<LicenseReply, LicenseChec
}
}
/// Ask the license server for the public key
pub async fn exchange_keys_with_license_server(node_id: String, license_key: String, public_key: PublicKey) -> Result<LicenseReply, LicenseCheckError> {
if let Ok(buffer) = build_key_exchange_request(node_id, license_key, public_key) {
let stream = TcpStream::connect(LICENSE_SERVER).await;
if let Err(e) = &stream {
if e.kind() == std::io::ErrorKind::NotFound {
log::error!("Unable to access {LICENSE_SERVER}. Check that lqosd is running and you have appropriate permissions.");
return Err(LicenseCheckError::SendFail);
}
}
let mut stream = stream.unwrap(); // This unwrap is safe, we checked that it exists previously
let ret = stream.write(&buffer).await;
if ret.is_err() {
log::error!("Unable to write to {LICENSE_SERVER} stream.");
log::error!("{:?}", ret);
return Err(LicenseCheckError::SendFail);
}
let mut buf = Vec::with_capacity(10240);
let ret = stream.read_to_end(&mut buf).await;
if ret.is_err() {
log::error!("Unable to read from {LICENSE_SERVER} stream.");
log::error!("{:?}", ret);
return Err(LicenseCheckError::SendFail);
}
decode_response(&buf)
} else {
Err(LicenseCheckError::SerializeFail)
}
}
fn decode_response(buf: &[u8]) -> Result<LicenseReply, LicenseCheckError> {
const U64SIZE: usize = std::mem::size_of::<u64>();
let version_buf = &buf[0..2]

View File

@ -29,7 +29,7 @@ dashmap = "5"
num-traits = "0.2"
thiserror = "1"
reqwest = { version = "0.11", features = ["json"] }
dryoc = "0.5"
dryoc = { version = "0.5", features = ["serde"] }
# Support JemAlloc on supported platforms
[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies]

View File

@ -1,6 +1,10 @@
use lqos_bus::long_term_stats::StatsSubmission;
use std::sync::atomic::AtomicBool;
use lqos_bus::long_term_stats::{StatsSubmission, exchange_keys_with_license_server};
use lqos_config::EtcLqos;
use once_cell::sync::Lazy;
use tokio::sync::Mutex;
use crate::long_term_stats::pki::store_server_public_key;
use super::pki::KEYPAIR;
struct QueueSubmission {
attempts: u8,
@ -33,8 +37,37 @@ impl Queue {
}
pub(crate) static QUEUE: Lazy<Queue> = Lazy::new(Queue::new);
static DONE_KEY_EXCHANGE: AtomicBool = AtomicBool::new(false);
async fn send_queue(host: String) {
if !DONE_KEY_EXCHANGE.load(std::sync::atomic::Ordering::Relaxed) {
let cfg = EtcLqos::load().unwrap();
let node_id = cfg.node_id.unwrap();
let license_key = cfg.long_term_stats.unwrap().license_key.unwrap();
let keypair = (KEYPAIR.read().unwrap()).clone();
match exchange_keys_with_license_server(node_id, license_key, keypair.public_key.clone()).await {
Ok(lqos_bus::long_term_stats::LicenseReply::MyPublicKey { public_key }) => {
store_server_public_key(&public_key);
log::info!("Received a public key for the server");
}
Ok(_) => {
log::warn!("License server sent an unexpected response.");
return;
}
Err(e) => {
log::warn!("Error exchanging keys with license server: {}", e);
return;
}
}
DONE_KEY_EXCHANGE.store(true, std::sync::atomic::Ordering::Relaxed);
}
if !DONE_KEY_EXCHANGE.load(std::sync::atomic::Ordering::Relaxed) {
log::warn!("Not sending stats because key exchange failed.");
return;
}
let url = format!("http://{host}:9127/submit");
let mut lock = QUEUE.queue.lock().await;

View File

@ -1,10 +1,14 @@
use std::sync::RwLock;
use dryoc::dryocbox::*;
use once_cell::sync::Lazy;
static KEYPAIR: Lazy<RwLock<KeyPair>> = Lazy::new(|| RwLock::new(generate_new_keypair()));
pub(crate) static KEYPAIR: Lazy<RwLock<KeyPair>> = Lazy::new(|| RwLock::new(generate_new_keypair()));
pub(crate) static SERVER_PUBLIC_KEY: Lazy<RwLock<Option<PublicKey>>> = Lazy::new(|| RwLock::new(None));
pub(crate) fn generate_new_keypair() -> KeyPair {
KeyPair::gen()
}
pub(crate) fn store_server_public_key(key: &PublicKey) {
*SERVER_PUBLIC_KEY.write().unwrap() = Some(key.clone());
}