Hook up get challenge endpoint

This commit is contained in:
nielsandriesse 2021-03-17 11:51:11 +11:00
parent 19682ad036
commit 251a893662
2 changed files with 26 additions and 16 deletions

View file

@ -10,14 +10,14 @@ use super::models;
use super::rpc; use super::rpc;
use super::storage; use super::storage;
pub async fn get_challenge(hex_public_key: String, pool: &storage::DatabaseConnectionPool) -> Result<Response, Rejection> { pub async fn get_challenge(hex_public_key: &str, pool: &storage::DatabaseConnectionPool) -> Result<Response, Rejection> {
// Validate the public key // Validate the public key
if !is_valid_public_key(&hex_public_key) { if !is_valid_public_key(hex_public_key) {
println!("Ignoring challenge request for invalid public key."); println!("Ignoring challenge request for invalid public key.");
return Err(warp::reject::custom(Error::ValidationFailed)); return Err(warp::reject::custom(Error::ValidationFailed));
} }
// Convert the public key to bytes and cut off the version byte // Convert the public key to bytes and cut off the version byte
let public_key: Vec<u8> = hex::decode(&hex_public_key).unwrap()[1..].to_vec(); let public_key: Vec<u8> = hex::decode(hex_public_key).unwrap()[1..].to_vec();
// Generate an ephemeral key pair // Generate an ephemeral key pair
let (ephemeral_private_key, ephemeral_public_key) = crypto::generate_ephemeral_x25519_key_pair().await; let (ephemeral_private_key, ephemeral_public_key) = crypto::generate_ephemeral_x25519_key_pair().await;
// Generate a symmetric key from the requesting user's public key and the ephemeral private key // Generate a symmetric key from the requesting user's public key and the ephemeral private key
@ -27,18 +27,20 @@ pub async fn get_challenge(hex_public_key: String, pool: &storage::DatabaseConne
thread_rng().fill(&mut token[..]); thread_rng().fill(&mut token[..]);
// Store the (pending) token // Store the (pending) token
// A given public key can have multiple pending tokens // A given public key can have multiple pending tokens
let now = chrono::Utc::now().timestamp(); {
let mut conn = pool.get().map_err(|_| Error::DatabaseFailedInternally)?; let now = chrono::Utc::now().timestamp();
let tx = conn.transaction().map_err(|_| Error::DatabaseFailedInternally)?; let mut conn = pool.get().map_err(|_| Error::DatabaseFailedInternally)?;
let stmt = format!("INSERT INTO {} (public_key, timestamp, token) VALUES (?1, ?2, ?3)", storage::PENDING_TOKENS_TABLE); let tx = conn.transaction().map_err(|_| Error::DatabaseFailedInternally)?;
match tx.execute(&stmt, params![ hex_public_key, now, token.to_vec() ]) { let stmt = format!("INSERT INTO {} (public_key, timestamp, token) VALUES (?1, ?2, ?3)", storage::PENDING_TOKENS_TABLE);
Ok(_) => (), let _ = match tx.execute(&stmt, params![ hex_public_key, now, token.to_vec() ]) {
Err(e) => { Ok(rows) => rows,
println!("Couldn't insert pending token due to error: {}.", e); Err(e) => {
return Err(warp::reject::custom(Error::DatabaseFailedInternally)); println!("Couldn't insert pending token due to error: {}.", e);
} return Err(warp::reject::custom(Error::DatabaseFailedInternally));
} }
tx.commit().map_err(|_| Error::DatabaseFailedInternally)?; };
tx.commit().map_err(|_| Error::DatabaseFailedInternally)?;
};
// Encrypt the token with the symmetric key // Encrypt the token with the symmetric key
let ciphertext = crypto::encrypt_aes_gcm(&token, &symmetric_key).await?; let ciphertext = crypto::encrypt_aes_gcm(&token, &symmetric_key).await?;
// Return // Return

View file

@ -58,6 +58,14 @@ async fn handle_get_request(rpc_call: RpcCall, uri: http::Uri, pool: &storage::D
"/moderators" => return handlers::get_moderators(pool).await, "/moderators" => return handlers::get_moderators(pool).await,
"/block_list" => return handlers::get_banned_public_keys(pool).await, "/block_list" => return handlers::get_banned_public_keys(pool).await,
"/member_count" => return handlers::get_member_count(pool).await, "/member_count" => return handlers::get_member_count(pool).await,
"/challenge" => {
let public_key = uri.query();
if public_key == None {
println!("Ignoring RPC call with invalid or unused endpoint: {}.", rpc_call.endpoint);
return Err(warp::reject::custom(Error::InvalidRpcCall));
}
return handlers::get_challenge(uri.query().unwrap(), pool).await;
},
_ => { _ => {
println!("Ignoring RPC call with invalid or unused endpoint: {}.", rpc_call.endpoint); println!("Ignoring RPC call with invalid or unused endpoint: {}.", rpc_call.endpoint);
return Err(warp::reject::custom(Error::InvalidRpcCall)); return Err(warp::reject::custom(Error::InvalidRpcCall));
@ -69,7 +77,7 @@ async fn handle_post_request(rpc_call: RpcCall, uri: http::Uri, pool: &storage::
match uri.path() { match uri.path() {
"/messages" => { "/messages" => {
let message = match serde_json::from_str(&rpc_call.body) { let message = match serde_json::from_str(&rpc_call.body) {
Ok(query_options) => query_options, Ok(message) => message,
Err(e) => { Err(e) => {
println!("Couldn't parse message from: {} due to error: {}.", rpc_call.body, e); println!("Couldn't parse message from: {} due to error: {}.", rpc_call.body, e);
return Err(warp::reject::custom(Error::InvalidRpcCall)); return Err(warp::reject::custom(Error::InvalidRpcCall));