From a3bf510c440d9e0f17b5c33866d9e4cc10a7f627 Mon Sep 17 00:00:00 2001 From: Vecna Date: Sat, 25 Mar 2023 14:36:04 -0400 Subject: [PATCH] Start adding args, support promoting to trust level 1 --- Cargo.toml | 2 + src/bin/lox_client.rs | 126 +++++++++++++++++++++++++++++------------- src/client_lib.rs | 11 ++-- 3 files changed, 96 insertions(+), 43 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3f537de..cb333fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,9 @@ edition = "2021" [dependencies] #lox = { git = "https://git-crysp.uwaterloo.ca/iang/lox.git", branch = "vvecna/lox_test" } lox = { git = "https://gitlab.torproject.org/onyinyang/lox.git" } +curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] } ed25519-dalek = { version = "1", features = ["serde"] } +getopts = "0.2" serde = "1" bincode = "1" serde_json = "1.0" diff --git a/src/bin/lox_client.rs b/src/bin/lox_client.rs index 7adb6d2..0901991 100644 --- a/src/bin/lox_client.rs +++ b/src/bin/lox_client.rs @@ -3,16 +3,61 @@ mod client_lib; use client_lib::*; +use curve25519_dalek::scalar::Scalar; +use getopts::Options; +use lox::bridge_table::BridgeLine; use lox::IssuerPubKey; +use serde::Serialize; use std::env::args; use std::fs::File; use std::io::Write; use std::path::Path; +// Prints the argument details for this program +fn print_usage(program: &str, opts: Options) { + let brief = format!("Usage: {} [options]", program); + print!("{}", opts.usage(&brief)); +} + +// Helper function to save serializable objects to files +fn save_object(obj: T, filename: &str) { + let mut outfile = File::create(filename).expect(&("Failed to create ".to_string() + filename)); + write!(outfile, "{}", serde_json::to_string(&obj).unwrap()) + .expect(&("Failed to write to ".to_string() + filename)); +} + #[tokio::main] async fn main() { - // TODO: Do proper argument handling - let server_addr = args().nth(1).unwrap(); // must include http:// + let args: Vec = args().collect(); + + let mut opts = Options::new(); + opts.optflag("h", "help", "print this help menu"); + opts.optflag("L", "level-up", "increase trust level"); + opts.optflag("N", "new-lox-cred", "get a new Lox Credential"); + opts.optopt( + "", + "server", + "Lox Auth server address [http://localhost:8001]", + "ADDR", + ); + + let matches = match opts.parse(&args[1..]) { + Ok(m) => m, + Err(f) => { + panic!("{}", f.to_string()) + } + }; + + if matches.opt_present("h") { + print_usage(&args[0], opts); + return; + } + + let server_addr = if matches.opt_present("server") { + matches.opt_str("server").unwrap() + } else { + "http://localhost:8001".to_string() + }; // Get Lox Authority public keys // TODO: Make this filename configurable @@ -26,51 +71,56 @@ async fn main() { // download from Lox Auth let pubkeys = get_lox_auth_keys(&server_addr).await; // save to file for next time - let mut lox_auth_pubkeys_outfile = File::create(lox_auth_pubkeys_filename) - .expect("Failed to create lox_auth pubkeys file"); - write!( - lox_auth_pubkeys_outfile, - "{}", - serde_json::to_string(&pubkeys).unwrap() - ) - .expect("Failed to write to lox_auth pubkeys file"); + save_object(&pubkeys, &lox_auth_pubkeys_filename); pubkeys }; // Get Lox Credential and BridgeLine - // TODO: Make these filenames configurable let lox_cred_filename = "lox_cred.json"; let bridgeline_filename = "bridgeline.json"; - let (lox_cred, bridgeline) = if Path::new(lox_cred_filename).exists() - && Path::new(bridgeline_filename).exists() + let (lox_cred, bridgeline) = if matches.opt_present("N") + || !Path::new(lox_cred_filename).exists() + || !Path::new(bridgeline_filename).exists() { - let lox_cred_infile = File::open(lox_cred_filename).unwrap(); - let lox_cred = serde_json::from_reader(lox_cred_infile).unwrap(); - let bridgeline_infile = File::open(bridgeline_filename).unwrap(); - let bridgeline = serde_json::from_reader(bridgeline_infile).unwrap(); - (lox_cred, bridgeline) - } else { - // get new credential based on an open invite + // get new Lox Credential let open_invite = get_open_invitation(&server_addr).await; - let (cred, bridgeline) = + let (cred, bl) = get_lox_credential(&server_addr, &open_invite, get_lox_pub(&lox_auth_pubkeys)).await; + // save to files for next time - let mut lox_cred_outfile = - File::create(lox_cred_filename).expect("Failed to create lox credential file"); - write!( - lox_cred_outfile, - "{}", - serde_json::to_string(&cred).unwrap() - ) - .expect("Failed to write to lox credential file"); - let mut bridgeline_outfile = - File::create(bridgeline_filename).expect("Failed to create bridgeline file"); - write!( - bridgeline_outfile, - "{}", - serde_json::to_string(&bridgeline).unwrap() - ) - .expect("Failed to write to bridgeline file"); - (cred, bridgeline) + save_object(&cred, &lox_cred_filename); + save_object(&bl, &bridgeline_filename); + (cred, bl) + } else { + // Read existing Lox Credential and BridgeLine from files + let cred = serde_json::from_reader(File::open(lox_cred_filename).unwrap()).unwrap(); + let bl = serde_json::from_reader(File::open(bridgeline_filename).unwrap()).unwrap(); + (cred, bl) }; + + if matches.opt_present("L") { + // If trust level is 0, do trust promotion, otherwise level up. + if lox_cred.trust_level == Scalar::zero() { + let migration_cred = + trust_promotion(&server_addr, &lox_cred, get_lox_pub(&lox_auth_pubkeys)).await; + let cred = trust_migration( + &server_addr, + &lox_cred, + &migration_cred, + get_lox_pub(&lox_auth_pubkeys), + get_migration_pub(&lox_auth_pubkeys), + ) + .await; + } else { + let encbuckets = get_reachability_credential(&server_addr).await; + let cred = level_up( + &server_addr, + &lox_cred, + &encbuckets, + get_lox_pub(&lox_auth_pubkeys), + get_reachability_pub(&lox_auth_pubkeys), + ) + .await; + } + } } diff --git a/src/client_lib.rs b/src/client_lib.rs index 95a06b9..8cc2600 100644 --- a/src/client_lib.rs +++ b/src/client_lib.rs @@ -66,10 +66,10 @@ pub async fn get_lox_auth_keys(server_addr: &str) -> Vec { } // Get encrypted bridge table -pub async fn get_reachability_credential(server_addr: &str) -> EncBridgeTable { +pub async fn get_reachability_credential(server_addr: &str) -> Vec<[u8; ENC_BUCKET_BYTES]> { let resp = net_request(server_addr.to_string() + "/reachability", [].to_vec()).await; - let reachability_cred = serde_json::from_slice(&resp).unwrap(); - reachability_cred + let reachability_cred: EncBridgeTable = serde_json::from_slice(&resp).unwrap(); + reachability_cred.etable } // Get an open invitation @@ -100,9 +100,10 @@ pub async fn trust_promotion( lox_pub: &IssuerPubKey, ) -> lox::cred::Migration { let (req, state) = - trust_promotion::request(&lox_cred, &lox_pub, today(Duration::ZERO)).unwrap(); +// trust_promotion::request(&lox_cred, &lox_pub, today(Duration::ZERO)).unwrap(); + trust_promotion::request(&lox_cred, &lox_pub, today(Duration::from_secs(60 * 60 * 24 * 31))).unwrap(); // FOR TESTING ONLY let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); - let encoded_resp = net_request(server_addr.to_string() + "/promreq", encoded_req).await; + let encoded_resp = net_request(server_addr.to_string() + "/trustpromo", encoded_req).await; let decoded_resp: trust_promotion::Response = serde_json::from_slice(&encoded_resp).unwrap(); let migration_cred = trust_promotion::handle_response(state, decoded_resp).unwrap(); migration_cred