Skip to content

Commit

Permalink
License checking over HTTPS
Browse files Browse the repository at this point in the history
  • Loading branch information
thebracket committed Jan 9, 2025
1 parent 5c4272f commit 7628c97
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 35 deletions.
1 change: 1 addition & 0 deletions src/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src/rust/lqosd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ dryoc = { version ="0.6.0", features = ["serde"] }
miniz_oxide = "0.8.0"
tungstenite = { version = "0", features = [ "native-tls" ] } # For WebSockets
native-tls = "0.2"
ureq = { version = "2.12.1", features = ["json", "native-tls"] }


# For memory debugging
allocative = { version = "0.3.3", features = [ "dashmap" ] }
Expand All @@ -63,4 +65,3 @@ allocative_derive = "0.3.3"
#[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies]
#jemallocator = { workspace = true }
mimalloc = { workspace = true }
ureq = { version = "2.12.1", features = ["json"] }
82 changes: 48 additions & 34 deletions src/rust/lqosd/src/lts2_sys/lts2_client/license_check.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::sync::Arc;
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use std::net::TcpStream;
use std::sync::Mutex;
use std::time::Duration;
use axum::http::StatusCode;
use native_tls::TlsConnector;
use timerfd::{SetTimeFlags, TimerFd, TimerState};
use tracing::{error, info, warn};
use uuid::Uuid;
use lqos_config::load_config;
use crate::lts2_sys::lts2_client::{get_remote_host, nacl_blob};
Expand All @@ -25,17 +28,21 @@ impl Default for LicenseStatus {
}
}

#[derive(Deserialize, Debug)]
pub(crate) struct LicenseResponse {
#[derive(Serialize, Deserialize)]
pub struct LicenseRequest {
pub license: Uuid,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct LicenseResponse {
pub valid: bool,
pub license_state: i32,
pub expiration_date: i64,
}

pub(crate) fn license_check_loop(
license_status: Arc<Mutex<LicenseStatus>>,
) {
let keys = KeyStore::new();

let mut tfd = TimerFd::new().unwrap();
assert_eq!(tfd.get_state(), TimerState::Disarmed);
tfd.set_state(TimerState::Periodic{
Expand All @@ -50,7 +57,7 @@ pub(crate) fn license_check_loop(
if !license_key.is_empty() {
if let Ok(lic) = Uuid::parse_str(&license_key) {
let remote_host = get_remote_host();
remote_license_check(remote_host, &keys, lic, license_status.clone());
remote_license_check(remote_host, lic, license_status.clone());
} else {
println!("Invalid license key: {}", license_key);
}
Expand All @@ -61,40 +68,47 @@ pub(crate) fn license_check_loop(

fn remote_license_check(
remote_host: String,
keys: &KeyStore,
lic: Uuid,
license_status: Arc<Mutex<LicenseStatus>>,
) {
println!("Checking license key with remote host: {}", remote_host);
if let Ok(mut socket) = TcpStream::connect(format!("{}:9122", remote_host)) {
if let Err(e) = nacl_blob::transmit_hello(&keys, 0x8342, 1, &mut socket) {
println!("Failed to send hello to license server. {e:?}");
return;
}
info!("Checking license key with remote host: {}", remote_host);
let url = format!("https://{}/license/license_check", remote_host);
// Make a ureq request to the remote host. POST a LicenseRequest with the license key.

if let Ok((server_hello, _)) = nacl_blob::receive_hello(&mut socket) {
if let Err(e) = nacl_blob::transmit_payload(&keys, &server_hello.public_key, &lic, &mut socket) {
println!("Failed to send license key to license server. {e:?}");
return;
}
let Ok(tls) = TlsConnector::builder()
.danger_accept_invalid_certs(true)
.danger_accept_invalid_hostnames(true)
.build() else {
error!("Failed to build TLS connector.");
return;
};
let tls = Arc::new(tls);

if let Ok((response, _)) = nacl_blob::receive_payload::<LicenseResponse>(&keys, &server_hello.public_key, &mut socket) {
println!("Received license response from license server: {response:?}");
let mut license_lock = license_status.lock().unwrap();
license_lock.valid = response.license_state != 0;
license_lock.license_type = response.license_state;
license_lock.trial_expires = response.expiration_date as i32;
let client = ureq::builder()
.timeout_connect(Duration::from_secs(20))
.tls_connector(tls.clone())
.build();

} else {
println!("Failed to receive license response from license server.");
return;
}
} else {
println!("Failed to receive hello from license server.");
return;
}
} else {
println!("Failed to connect to license server. This is not fatal - we'll try again.");
let result = client
.post(&url)
.send_json(serde_json::json!(&LicenseRequest { license: lic }));
if result.is_err() {
warn!("Failed to connect to license server. This is not fatal - we'll try again. {result:?}");
return;
}
let Ok(response) = result else {
warn!("Failed to receive license response from license server.");
return;
};
let response = response.into_json::<LicenseResponse>();
if response.is_err() {
warn!("Failed to receive license response from license server.");
return;
}
let response = response.unwrap();
info!("Received license response from license server: {response:?}");
let mut license_lock = license_status.lock().unwrap();
license_lock.valid = response.valid;
license_lock.license_type = response.license_state;
license_lock.trial_expires = response.expiration_date as i32;
}

0 comments on commit 7628c97

Please sign in to comment.