diff --git a/crates/lox-distributor/.gitignore b/crates/lox-distributor/.gitignore index ea8c4bf..96ef6c0 100644 --- a/crates/lox-distributor/.gitignore +++ b/crates/lox-distributor/.gitignore @@ -1 +1,2 @@ /target +Cargo.lock diff --git a/crates/lox-distributor/Cargo.toml b/crates/lox-distributor/Cargo.toml index 5562358..c82ba43 100644 --- a/crates/lox-distributor/Cargo.toml +++ b/crates/lox-distributor/Cargo.toml @@ -15,4 +15,4 @@ serde = "1" serde_with = "1.9.1" serde_json = "1.0.87" -lox = { git = "https://git-crysp.uwaterloo.ca/iang/lox.git" } +lox = { git = "https://gitlab.torproject.org/onyinyang/lox.git"} \ No newline at end of file diff --git a/crates/lox-distributor/src/main.rs b/crates/lox-distributor/src/main.rs index 5ef6842..ccf4c21 100644 --- a/crates/lox-distributor/src/main.rs +++ b/crates/lox-distributor/src/main.rs @@ -6,16 +6,19 @@ use std::{ use hyper::{ header::HeaderValue, + server::conn::AddrStream, service::{make_service_fn, service_fn}, - Body, Request, Response, Server, + Body, Method, Request, Response, Server, StatusCode, }; +use lox::bridge_table::BridgeLine; +use lox::{BridgeAuth, BridgeDb, OPENINV_LENGTH}; use rand::RngCore; use serde::{Deserialize, Serialize}; use serde_json; use serde_with::serde_as; - -use lox::bridge_table::BridgeLine; -use lox::{BridgeAuth, BridgeDb, OPENINV_LENGTH}; +use std::fs::File; +use std::io::Write; +use std::path::Path; #[serde_as] #[derive(Serialize, Deserialize)] @@ -26,7 +29,7 @@ pub struct Invite { /// Create a random BridgeLine for testing ONLY. Do not use in production! /// This was copied directly from lox/src/bridge_table.rs in order -/// to easily initialize a bridgedb/bridgeauth with structurally +/// to easily initialize a bridgedb/lox_auth with structurally /// correct buckets to be used for Lox requests/verifications/responses. /// In production, existing bridges should be translated into this format /// in a private function and sorted into buckets (3 bridges/bucket is suggested @@ -65,35 +68,86 @@ pub fn random() -> BridgeLine { res } +#[derive(Clone)] +struct LoxServerContext { + pubkey_filename: String, + db: Arc>, + ba: Arc>, +} + +async fn handle( + context: LoxServerContext, + // addr: SocketAddr, + req: Request, +) -> Result, Infallible> { + match (req.method(), req.uri().path()) { + (&Method::GET, "/") | (&Method::GET, "/index.html") => { + Ok::<_, Infallible>(generate_invite(context.db)) + } + (&Method::GET, "/pubkeys") => Ok::<_, Infallible>(send_keys(&context.pubkey_filename)), + //(&Method::POST, "/json_api") => api_post_response(req).await, + //(&Method::GET, "/json_api") => api_get_response().await, + _ => { + // Return 404 not found response. + Ok(Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::from("Not found")) + .unwrap()) + } + } +} + #[tokio::main] async fn main() { + let lox_auth_pubkeys_filename = "lox_auth_pubkeys.json"; let num_buckets = 5; - // Create and initialize a new db and bridgeauth + // Create and initialize a new db and lox_auth let mut bridgedb = BridgeDb::new(); - let mut bridgeauth = BridgeAuth::new(bridgedb.pubkey); + let mut lox_auth = BridgeAuth::new(bridgedb.pubkey); // Make 3 x num_buckets open invitation bridges, in sets of 3 for _ in 0..num_buckets { - let bucket = [ - random(), - random(), - random(), - ]; - bridgeauth.add_openinv_bridges(bucket, &mut bridgedb); + let bucket = [random(), random(), random()]; + lox_auth.add_openinv_bridges(bucket, &mut bridgedb); } // Create the encrypted bridge table - bridgeauth.enc_bridge_table(); + lox_auth.enc_bridge_table(); - let db = Arc::new(Mutex::new(bridgedb)); + // output lox_auth pubkeys if the file doesn't exist + if !Path::new(lox_auth_pubkeys_filename).exists() { + // vector of public keys (to serialize) + let lox_auth_pubkeys = vec![ + &lox_auth.lox_pub, + &lox_auth.migration_pub, + &lox_auth.migrationkey_pub, + &lox_auth.reachability_pub, + &lox_auth.invitation_pub, + ]; - let new_service = make_service_fn(move |_conn| { - let db = db.clone(); - async move { - Ok::<_, Infallible>(service_fn(move |_req: Request| { - let db = db.clone(); - async move { Ok::<_, Infallible>(generate_invite(db)) } - })) - } + // output lox_auth public keys + 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(&lox_auth_pubkeys).unwrap() + ) + .expect("Failed to write to lox_auth pubkeys file"); + } + + let context = LoxServerContext { + pubkey_filename: lox_auth_pubkeys_filename.into(), + db: Arc::new(Mutex::new(bridgedb)), + ba: Arc::new(Mutex::new(lox_auth)), + }; + + let new_service = make_service_fn(move |_conn: &AddrStream| { + let context = context.clone(); + let service = service_fn(move |req| { + // let addr = conn.remote_addr(); + handle(context.clone(), req) + }); + async move { Ok::<_, Infallible>(service) } }); let addr = SocketAddr::from(([127, 0, 0, 1], 8001)); @@ -123,3 +177,11 @@ fn generate_invite(db: Arc>) -> Response { .insert("Access-Control-Allow-Origin", HeaderValue::from_static("*")); resp } + +fn send_keys(pubkeys_filename: &str) -> Response { + let json_keys = serde_json::to_string(pubkeys_filename).expect("JSON was not well-formatted"); + let mut resp = Response::new(Body::from(json_keys)); + resp.headers_mut() + .insert("Content-Type", HeaderValue::from_static("application/json")); + resp +}