commit
d13801410d
|
@ -3,7 +3,6 @@ use std::convert::TryInto;
|
|||
use std::path::Path;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use chrono;
|
||||
use log::{error, info, warn};
|
||||
use rand::{thread_rng, Rng};
|
||||
use rusqlite::params;
|
||||
|
@ -143,7 +142,7 @@ pub async fn store_file(
|
|||
// Check authorization level if needed
|
||||
match rpc::MODE {
|
||||
rpc::Mode::OpenGroupServer => {
|
||||
let auth_token = auth_token.ok_or(warp::reject::custom(Error::NoAuthToken))?;
|
||||
let auth_token = auth_token.ok_or_else(|| warp::reject::custom(Error::NoAuthToken))?;
|
||||
let (has_authorization_level, _) =
|
||||
has_authorization_level(&auth_token, AuthorizationLevel::Basic, pool)?;
|
||||
if !has_authorization_level {
|
||||
|
@ -178,10 +177,7 @@ pub async fn store_file(
|
|||
// room_id is guaranteed to be present at this point because we checked the auth
|
||||
// token (the auth token will have been rejected if room_id is missing).
|
||||
let room_id = room_id.unwrap();
|
||||
match std::fs::create_dir_all(format!("files/{}_files", &room_id)) {
|
||||
Ok(_) => (),
|
||||
Err(_) => (),
|
||||
};
|
||||
let _ = std::fs::create_dir_all(format!("files/{}_files", &room_id));
|
||||
let raw_path = format!("files/{}_files/{}", &room_id, &id);
|
||||
let path = Path::new(&raw_path);
|
||||
let mut file = match File::create(path).await {
|
||||
|
@ -216,7 +212,7 @@ pub async fn get_file(
|
|||
// Check authorization level if needed
|
||||
match rpc::MODE {
|
||||
rpc::Mode::OpenGroupServer => {
|
||||
let auth_token = auth_token.ok_or(warp::reject::custom(Error::NoAuthToken))?;
|
||||
let auth_token = auth_token.ok_or_else(|| warp::reject::custom(Error::NoAuthToken))?;
|
||||
let (has_authorization_level, _) =
|
||||
has_authorization_level(&auth_token, AuthorizationLevel::Basic, pool)?;
|
||||
if !has_authorization_level {
|
||||
|
@ -336,8 +332,9 @@ pub fn get_auth_token_challenge(
|
|||
) -> Result<models::Challenge, Rejection> {
|
||||
// Doesn't return a response directly for testing purposes
|
||||
// Get the public key
|
||||
let hex_public_key =
|
||||
query_params.get("public_key").ok_or(warp::reject::custom(Error::InvalidRpcCall))?;
|
||||
let hex_public_key = query_params
|
||||
.get("public_key")
|
||||
.ok_or_else(|| warp::reject::custom(Error::InvalidRpcCall))?;
|
||||
// Validate the public key
|
||||
if !is_valid_public_key(hex_public_key) {
|
||||
warn!("Ignoring challenge request for invalid public key: {}.", hex_public_key);
|
||||
|
@ -406,7 +403,7 @@ pub fn claim_auth_token(
|
|||
let index = pending_tokens
|
||||
.iter()
|
||||
.position(|(_, pending_token)| *pending_token == claim)
|
||||
.ok_or_else(|| Error::Unauthorized)?;
|
||||
.ok_or(Error::Unauthorized)?;
|
||||
let token = &pending_tokens[index].1;
|
||||
// Store the claimed token
|
||||
let stmt = format!(
|
||||
|
@ -598,7 +595,7 @@ pub fn delete_message(
|
|||
let raw_query =
|
||||
format!("SELECT public_key FROM {} WHERE id = (?1)", storage::MESSAGES_TABLE);
|
||||
let mut query = conn.prepare(&raw_query).map_err(|_| Error::DatabaseFailedInternally)?;
|
||||
let rows = match query.query_map(params![id], |row| Ok(row.get(0)?)) {
|
||||
let rows = match query.query_map(params![id], |row| row.get(0)) {
|
||||
Ok(rows) => rows,
|
||||
Err(e) => {
|
||||
error!("Couldn't delete message due to error: {}.", e);
|
||||
|
@ -608,7 +605,8 @@ pub fn delete_message(
|
|||
let public_keys: Vec<String> = rows.filter_map(|result| result.ok()).collect();
|
||||
public_keys.get(0).map(|s| s.to_string())
|
||||
};
|
||||
let sender = sender_option.ok_or(warp::reject::custom(Error::DatabaseFailedInternally))?;
|
||||
let sender =
|
||||
sender_option.ok_or_else(|| warp::reject::custom(Error::DatabaseFailedInternally))?;
|
||||
if !is_moderator(&requesting_public_key, pool)? && requesting_public_key != sender {
|
||||
return Err(warp::reject::custom(Error::Unauthorized));
|
||||
}
|
||||
|
@ -891,7 +889,7 @@ pub fn get_member_count(
|
|||
// Query the database
|
||||
let raw_query = format!("SELECT public_key FROM {}", storage::TOKENS_TABLE);
|
||||
let mut query = conn.prepare(&raw_query).map_err(|_| Error::DatabaseFailedInternally)?;
|
||||
let rows = match query.query_map(params![], |row| Ok(row.get(0)?)) {
|
||||
let rows = match query.query_map(params![], |row| row.get(0)) {
|
||||
Ok(rows) => rows,
|
||||
Err(e) => {
|
||||
error!("Couldn't query database due to error: {}.", e);
|
||||
|
@ -1063,7 +1061,7 @@ fn get_moderators_vector(pool: &storage::DatabaseConnectionPool) -> Result<Vec<S
|
|||
// Query the database
|
||||
let raw_query = format!("SELECT public_key FROM {}", storage::MODERATORS_TABLE);
|
||||
let mut query = conn.prepare(&raw_query).map_err(|_| Error::DatabaseFailedInternally)?;
|
||||
let rows = match query.query_map(params![], |row| Ok(row.get(0)?)) {
|
||||
let rows = match query.query_map(params![], |row| row.get(0)) {
|
||||
Ok(rows) => rows,
|
||||
Err(e) => {
|
||||
error!("Couldn't query database due to error: {}.", e);
|
||||
|
@ -1089,7 +1087,7 @@ fn get_banned_public_keys_vector(
|
|||
// Query the database
|
||||
let raw_query = format!("SELECT public_key FROM {}", storage::BLOCK_LIST_TABLE);
|
||||
let mut query = conn.prepare(&raw_query).map_err(|_| Error::DatabaseFailedInternally)?;
|
||||
let rows = match query.query_map(params![], |row| Ok(row.get(0)?)) {
|
||||
let rows = match query.query_map(params![], |row| row.get(0)) {
|
||||
Ok(rows) => rows,
|
||||
Err(e) => {
|
||||
error!("Couldn't query database due to error: {}.", e);
|
||||
|
@ -1126,7 +1124,7 @@ fn get_public_key_for_auth_token(
|
|||
// Query the database
|
||||
let raw_query = format!("SELECT public_key FROM {} WHERE token = (?1)", storage::TOKENS_TABLE);
|
||||
let mut query = conn.prepare(&raw_query).map_err(|_| Error::DatabaseFailedInternally)?;
|
||||
let rows = match query.query_map(params![auth_token], |row| Ok(row.get(0)?)) {
|
||||
let rows = match query.query_map(params![auth_token], |row| row.get(0)) {
|
||||
Ok(rows) => rows,
|
||||
Err(e) => {
|
||||
error!("Couldn't query database due to error: {}.", e);
|
||||
|
@ -1143,7 +1141,7 @@ fn has_authorization_level(
|
|||
) -> Result<(bool, String), Rejection> {
|
||||
// Check that we have a public key associated with the given auth token
|
||||
let public_key_option = get_public_key_for_auth_token(auth_token, pool)?;
|
||||
let public_key = public_key_option.ok_or(warp::reject::custom(Error::NoAuthToken))?;
|
||||
let public_key = public_key_option.ok_or_else(|| warp::reject::custom(Error::NoAuthToken))?;
|
||||
// Check that the given public key isn't banned
|
||||
if is_banned(&public_key, pool)? {
|
||||
return Err(warp::reject::custom(Error::Unauthorized));
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::needless_return, clippy::upper_case_acronyms)]
|
||||
|
||||
use parking_lot::RwLock;
|
||||
use std::fs;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
|
@ -9,7 +11,6 @@ use std::{
|
|||
use futures::join;
|
||||
use log::info;
|
||||
use structopt::StructOpt;
|
||||
use tokio;
|
||||
use warp::Filter;
|
||||
|
||||
mod crypto;
|
||||
|
|
|
@ -65,7 +65,7 @@ fn parse_onion_request_payload(
|
|||
}
|
||||
// Extract the different components
|
||||
// This is safe because we know blob has a length of at least 4 bytes
|
||||
let size = as_le_u32(&blob[0..4].try_into().unwrap()) as usize;
|
||||
let size = u32::from_le_bytes(blob[0..4].try_into().unwrap()) as usize;
|
||||
let ciphertext: Vec<u8> = blob[4..(4 + size)].try_into().unwrap();
|
||||
let utf8_json: Vec<u8> = blob[(4 + size)..].try_into().unwrap();
|
||||
// Parse JSON
|
||||
|
@ -118,12 +118,3 @@ async fn encrypt_response(response: Response, symmetric_key: &[u8]) -> Result<Re
|
|||
warp::http::Response::builder().status(StatusCode::OK.as_u16()).body(json).into_response();
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
// Utilities
|
||||
|
||||
fn as_le_u32(array: &[u8; 4]) -> u32 {
|
||||
((array[0] as u32) << 00)
|
||||
+ ((array[1] as u32) << 08)
|
||||
+ ((array[2] as u32) << 16)
|
||||
+ ((array[3] as u32) << 24)
|
||||
}
|
||||
|
|
22
src/rpc.rs
22
src/rpc.rs
|
@ -31,9 +31,9 @@ pub async fn handle_rpc_call(rpc_call: RpcCall) -> Result<Response, Rejection> {
|
|||
// Adding "http://placeholder.io" in front of the endpoint is a workaround
|
||||
// for the fact that the URL crate doesn't accept relative URLs. There are
|
||||
// other (cleaner) ways to fix this but they tend to be much more complex.
|
||||
let raw_uri = format!("http://placeholder.io/{}", rpc_call.endpoint.trim_start_matches("/"));
|
||||
let raw_uri = format!("http://placeholder.io/{}", rpc_call.endpoint.trim_start_matches('/'));
|
||||
let path: String = match raw_uri.parse::<http::Uri>() {
|
||||
Ok(uri) => uri.path().trim_start_matches("/").to_string(),
|
||||
Ok(uri) => uri.path().trim_start_matches('/').to_string(),
|
||||
Err(e) => {
|
||||
warn!("Couldn't parse URI from: {} due to error: {}.", &raw_uri, e);
|
||||
return Err(warp::reject::custom(Error::InvalidRpcCall));
|
||||
|
@ -85,7 +85,7 @@ async fn handle_get_request(
|
|||
return Ok(warp::reply::json(&response).into_response());
|
||||
} else if path.starts_with("rooms") {
|
||||
reject_if_file_server_mode(path)?;
|
||||
let components: Vec<&str> = path.split("/").collect(); // Split on subsequent slashes
|
||||
let components: Vec<&str> = path.split('/').collect(); // Split on subsequent slashes
|
||||
if components.len() == 1 {
|
||||
return handlers::get_all_rooms();
|
||||
} else if components.len() == 2 {
|
||||
|
@ -118,7 +118,7 @@ async fn handle_get_request(
|
|||
// This route requires auth in open group server mode, but not in file server mode
|
||||
let pool = get_pool_for_room(&rpc_call)?;
|
||||
if path.starts_with("files") {
|
||||
let components: Vec<&str> = path.split("/").collect(); // Split on subsequent slashes
|
||||
let components: Vec<&str> = path.split('/').collect(); // Split on subsequent slashes
|
||||
if components.len() != 2 {
|
||||
warn!("Invalid endpoint: {}.", rpc_call.endpoint);
|
||||
return Err(warp::reject::custom(Error::InvalidRpcCall));
|
||||
|
@ -135,7 +135,7 @@ async fn handle_get_request(
|
|||
.map(|json| warp::reply::json(&json).into_response());
|
||||
}
|
||||
// Handle routes that require authorization
|
||||
let auth_token = auth_token.ok_or(warp::reject::custom(Error::NoAuthToken))?;
|
||||
let auth_token = auth_token.ok_or_else(|| warp::reject::custom(Error::NoAuthToken))?;
|
||||
match path {
|
||||
"messages" => {
|
||||
reject_if_file_server_mode(path)?;
|
||||
|
@ -227,10 +227,10 @@ async fn handle_post_request(
|
|||
return handlers::store_file(room_id, &json.file, auth_token, &pool).await;
|
||||
}
|
||||
// Handle routes that require authorization
|
||||
let auth_token = auth_token.ok_or(warp::reject::custom(Error::NoAuthToken))?;
|
||||
let auth_token = auth_token.ok_or_else(|| warp::reject::custom(Error::NoAuthToken))?;
|
||||
if path.starts_with("rooms") {
|
||||
reject_if_file_server_mode(path)?;
|
||||
let components: Vec<&str> = path.split("/").collect(); // Split on subsequent slashes
|
||||
let components: Vec<&str> = path.split('/').collect(); // Split on subsequent slashes
|
||||
if components.len() == 3 && components[2] == "image" {
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct JSON {
|
||||
|
@ -331,11 +331,11 @@ async fn handle_delete_request(
|
|||
pool: &storage::DatabaseConnectionPool,
|
||||
) -> Result<Response, Rejection> {
|
||||
// Check that the auth token is present
|
||||
let auth_token = auth_token.ok_or(warp::reject::custom(Error::NoAuthToken))?;
|
||||
let auth_token = auth_token.ok_or_else(|| warp::reject::custom(Error::NoAuthToken))?;
|
||||
// DELETE /messages/:server_id
|
||||
if path.starts_with("messages") {
|
||||
reject_if_file_server_mode(path)?;
|
||||
let components: Vec<&str> = path.split("/").collect(); // Split on subsequent slashes
|
||||
let components: Vec<&str> = path.split('/').collect(); // Split on subsequent slashes
|
||||
if components.len() != 2 {
|
||||
warn!("Invalid endpoint: {}.", path);
|
||||
return Err(warp::reject::custom(Error::InvalidRpcCall));
|
||||
|
@ -352,7 +352,7 @@ async fn handle_delete_request(
|
|||
// DELETE /block_list/:public_key
|
||||
if path.starts_with("block_list") {
|
||||
reject_if_file_server_mode(path)?;
|
||||
let components: Vec<&str> = path.split("/").collect(); // Split on subsequent slashes
|
||||
let components: Vec<&str> = path.split('/').collect(); // Split on subsequent slashes
|
||||
if components.len() != 2 {
|
||||
warn!("Invalid endpoint: {}.", path);
|
||||
return Err(warp::reject::custom(Error::InvalidRpcCall));
|
||||
|
@ -368,7 +368,7 @@ async fn handle_delete_request(
|
|||
// DELETE /moderators/:public_key
|
||||
if path.starts_with("moderators") {
|
||||
reject_if_file_server_mode(path)?;
|
||||
let components: Vec<&str> = path.split("/").collect(); // Split on subsequent slashes
|
||||
let components: Vec<&str> = path.split('/').collect(); // Split on subsequent slashes
|
||||
if components.len() != 2 {
|
||||
warn!("Invalid endpoint: {}.", path);
|
||||
return Err(warp::reject::custom(Error::InvalidRpcCall));
|
||||
|
|
|
@ -258,7 +258,7 @@ pub async fn prune_files(file_expiration: i64) {
|
|||
Ok(query) => query,
|
||||
Err(e) => return error!("Couldn't prune files due to error: {}.", e),
|
||||
};
|
||||
let rows = match query.query_map(params![expiration], |row| Ok(row.get(0)?)) {
|
||||
let rows = match query.query_map(params![expiration], |row| row.get(0)) {
|
||||
Ok(rows) => rows,
|
||||
Err(e) => {
|
||||
return error!("Couldn't prune files due to error: {}.", e);
|
||||
|
@ -300,7 +300,7 @@ fn get_all_room_ids() -> Result<Vec<String>, Error> {
|
|||
// Query the database
|
||||
let raw_query = format!("SELECT id FROM {}", MAIN_TABLE);
|
||||
let mut query = conn.prepare(&raw_query).map_err(|_| Error::DatabaseFailedInternally)?;
|
||||
let rows = match query.query_map(params![], |row| Ok(row.get(0)?)) {
|
||||
let rows = match query.query_map(params![], |row| row.get(0)) {
|
||||
Ok(rows) => rows,
|
||||
Err(e) => {
|
||||
error!("Couldn't query database due to error: {}.", e);
|
||||
|
|
Loading…
Reference in New Issue