vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit 95d906bdbbfd2ca526d04c92f8d33358a0865a06
parent 994669fb6962cdae7ca5e5c3a0649bd5863eb03b
Author: Daniel GarcĂ­a <dani-garcia@users.noreply.github.com>
Date:   Thu, 15 Apr 2021 18:24:04 +0200

Merge branch 'master' into fmt
Diffstat:
MCargo.lock | 39+++++++++++++++++++++++++++++++++++++++
MCargo.toml | 2+-
Msrc/api/admin.rs | 10++++------
Msrc/api/core/mod.rs | 8+++-----
Msrc/api/core/two_factor/duo.rs | 14+++++++-------
Msrc/api/icons.rs | 6+++---
Msrc/static/templates/admin/settings.hbs | 6+++++-
Msrc/util.rs | 19+++++++++++++++++--
8 files changed, 79 insertions(+), 25 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -564,6 +564,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] name = "encoding_rs" version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2213,6 +2219,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-native-tls", + "tokio-socks", "tokio-util", "url 2.2.1", "wasm-bindgen", @@ -2768,6 +2775,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.65", +] + +[[package]] name = "threadpool" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2866,6 +2893,18 @@ dependencies = [ ] [[package]] +name = "tokio-socks" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" +dependencies = [ + "either", + "futures-util", + "thiserror", + "tokio", +] + +[[package]] name = "tokio-util" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml @@ -32,7 +32,7 @@ rocket = { version = "0.5.0-dev", features = ["tls"], default-features = false } rocket_contrib = "0.5.0-dev" # HTTP client -reqwest = { version = "0.11.2", features = ["blocking", "json", "gzip", "brotli"] } +reqwest = { version = "0.11.2", features = ["blocking", "json", "gzip", "brotli", "socks"] } # multipart/form-data support multipart = { version = "0.17.1", features = ["server"], default-features = false } diff --git a/src/api/admin.rs b/src/api/admin.rs @@ -3,7 +3,7 @@ use serde::de::DeserializeOwned; use serde_json::Value; use std::{env, time::Duration}; -use reqwest::{blocking::Client, header::USER_AGENT}; + use rocket::{ http::{Cookie, Cookies, SameSite}, request::{self, FlashMessage, Form, FromRequest, Outcome, Request}, @@ -19,7 +19,7 @@ use crate::{ db::{backup_database, get_sql_server_version, models::*, DbConn, DbConnType}, error::{Error, MapResult}, mail, - util::{format_naive_datetime_local, get_display_size, is_running_in_docker}, + util::{format_naive_datetime_local, get_display_size, is_running_in_docker, get_reqwest_client}, CONFIG, }; @@ -469,24 +469,22 @@ struct GitCommit { } fn get_github_api<T: DeserializeOwned>(url: &str) -> Result<T, Error> { - let github_api = Client::builder().build()?; + let github_api = get_reqwest_client(); Ok(github_api .get(url) .timeout(Duration::from_secs(10)) - .header(USER_AGENT, "Bitwarden_RS") .send()? .error_for_status()? .json::<T>()?) } fn has_http_access() -> bool { - let http_access = Client::builder().build().unwrap(); + let http_access = get_reqwest_client(); match http_access .head("https://github.com/dani-garcia/bitwarden_rs") .timeout(Duration::from_secs(10)) - .header(USER_AGENT, "Bitwarden_RS") .send() { Ok(r) => r.status().is_success(), diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs @@ -37,6 +37,7 @@ use crate::{ auth::Headers, db::DbConn, error::Error, + util::get_reqwest_client, }; #[put("/devices/identifier/<uuid>/clear-token")] @@ -141,18 +142,15 @@ fn put_eq_domains(data: JsonUpcase<EquivDomainData>, headers: Headers, conn: DbC #[get("/hibp/breach?<username>")] fn hibp_breach(username: String) -> JsonResult { - let user_agent = "Bitwarden_RS"; let url = format!( "https://haveibeenpwned.com/api/v3/breachedaccount/{}?truncateResponse=false&includeUnverified=false", username ); - use reqwest::{blocking::Client, header::USER_AGENT}; - if let Some(api_key) = crate::CONFIG.hibp_api_key() { - let hibp_client = Client::builder().build()?; + let hibp_client = get_reqwest_client(); - let res = hibp_client.get(&url).header(USER_AGENT, user_agent).header("hibp-api-key", api_key).send()?; + let res = hibp_client.get(&url).header("hibp-api-key", api_key).send()?; // If we get a 404, return a 404, it means no breached accounts if res.status() == 404 { diff --git a/src/api/core/two_factor/duo.rs b/src/api/core/two_factor/duo.rs @@ -12,6 +12,7 @@ use crate::{ DbConn, }, error::MapResult, + util::get_reqwest_client, CONFIG, }; @@ -189,9 +190,7 @@ fn activate_duo_put(data: JsonUpcase<EnableDuoData>, headers: Headers, conn: DbC } fn duo_api_request(method: &str, path: &str, params: &str, data: &DuoData) -> EmptyResult { - const AGENT: &str = "bitwarden_rs:Duo/1.0 (Rust)"; - - use reqwest::{blocking::Client, header::*, Method}; + use reqwest::{header, Method}; use std::str::FromStr; // https://duo.com/docs/authapi#api-details @@ -203,11 +202,12 @@ fn duo_api_request(method: &str, path: &str, params: &str, data: &DuoData) -> Em let m = Method::from_str(method).unwrap_or_default(); - Client::new() - .request(m, &url) + let client = get_reqwest_client(); + + client.request(m, &url) .basic_auth(username, Some(password)) - .header(USER_AGENT, AGENT) - .header(DATE, date) + .header(header::USER_AGENT, "bitwarden_rs:Duo/1.0 (Rust)") + .header(header::DATE, date) .send()? .error_for_status()?; diff --git a/src/api/icons.rs b/src/api/icons.rs @@ -12,7 +12,7 @@ use regex::Regex; use reqwest::{blocking::Client, blocking::Response, header, Url}; use rocket::{http::ContentType, http::Cookie, response::Content, Route}; -use crate::{error::Error, util::Cached, CONFIG}; +use crate::{error::Error, util::{Cached, get_reqwest_client_builder}, CONFIG}; pub fn routes() -> Vec<Route> { routes![icon] @@ -33,11 +33,11 @@ static CLIENT: Lazy<Client> = Lazy::new(|| { ); // Reuse the client between requests - Client::builder() + get_reqwest_client_builder() .timeout(Duration::from_secs(CONFIG.icon_download_timeout())) .default_headers(default_headers) .build() - .unwrap() + .expect("Failed to build icon client") }); // Build Regex only once since this takes a lot of time. diff --git a/src/static/templates/admin/settings.hbs b/src/static/templates/admin/settings.hbs @@ -116,7 +116,11 @@ data-target="#g_database">Backup Database</button></div> <div id="g_database" class="card-body collapse" data-parent="#config-form"> <div class="small mb-3"> - NOTE: A local installation of sqlite3 is required for this section to work. + WARNING: This function only creates a backup copy of the SQLite database. + This does not include any configuration or file attachment data that may + also be needed to fully restore a bitwarden_rs instance. For details on + how to perform complete backups, refer to the wiki page on + <a href="https://github.com/dani-garcia/bitwarden_rs/wiki/Backing-up-your-vault">backups</a>. </div> <button type="button" class="btn btn-primary" onclick="backupDatabase();">Backup Database</button> </div> diff --git a/src/util.rs b/src/util.rs @@ -478,7 +478,6 @@ pub fn retry<F, T, E>(func: F, max_tries: u32) -> Result<T, E> where F: Fn() -> Result<T, E>, { - use std::{thread::sleep, time::Duration}; let mut tries = 0; loop { @@ -497,12 +496,13 @@ where } } +use std::{thread::sleep, time::Duration}; + pub fn retry_db<F, T, E>(func: F, max_tries: u32) -> Result<T, E> where F: Fn() -> Result<T, E>, E: std::error::Error, { - use std::{thread::sleep, time::Duration}; let mut tries = 0; loop { @@ -522,3 +522,18 @@ where } } } + +use reqwest::{blocking::{Client, ClientBuilder}, header}; + +pub fn get_reqwest_client() -> Client { + get_reqwest_client_builder().build().expect("Failed to build client") +} + +pub fn get_reqwest_client_builder() -> ClientBuilder { + let mut headers = header::HeaderMap::new(); + headers.insert(header::USER_AGENT, header::HeaderValue::from_static("Bitwarden_RS")); + Client::builder() + .default_headers(headers) + .timeout(Duration::from_secs(10)) + +}