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 a79745956025de9d3c859f6eec9eb329f2717c24
parent 6cbb683f99385f02ad111ca03530be4c83c1ef1b
Author: Daniel GarcĂ­a <dani-garcia@users.noreply.github.com>
Date:   Sun, 20 Jan 2019 15:36:33 +0100

Implement HIBP check [WIP].
Add extra security attributes to admin cookie.
Error handling.

Diffstat:
Msrc/api/admin.rs | 4+++-
Msrc/api/core/mod.rs | 18++++++++++++++++++
Msrc/api/icons.rs | 6+++---
Msrc/error.rs | 24++++++++++++++----------
4 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/src/api/admin.rs b/src/api/admin.rs @@ -1,7 +1,7 @@ use rocket_contrib::json::Json; use serde_json::Value; -use rocket::http::{Cookie, Cookies}; +use rocket::http::{Cookie, Cookies, SameSite}; use rocket::request::{self, FlashMessage, Form, FromRequest, Request}; use rocket::response::{content::Html, Flash, Redirect}; use rocket::{Outcome, Route}; @@ -85,6 +85,8 @@ fn post_admin_login(data: Form<LoginForm>, mut cookies: Cookies, ip: ClientIp) - let cookie = Cookie::build(COOKIE_NAME, jwt) .path(ADMIN_PATH) + .max_age(chrono::Duration::minutes(20)) + .same_site(SameSite::Strict) .http_only(true) .finish(); diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs @@ -11,6 +11,7 @@ pub fn routes() -> Vec<Route> { get_eq_domains, post_eq_domains, put_eq_domains, + hibp_breach, ]; let mut routes = Vec::new(); @@ -128,3 +129,20 @@ fn post_eq_domains(data: JsonUpcase<EquivDomainData>, headers: Headers, conn: Db fn put_eq_domains(data: JsonUpcase<EquivDomainData>, headers: Headers, conn: DbConn) -> JsonResult { post_eq_domains(data, headers, conn) } + +#[get("/hibp/breach?<username>")] +fn hibp_breach(username: String) -> JsonResult { + let url = format!("https://haveibeenpwned.com/api/v2/breachedaccount/{}", username); + let user_agent = "Bitwarden_RS"; + + use reqwest::{header::USER_AGENT, Client}; + + let value: Value = Client::new() + .get(&url) + .header(USER_AGENT, user_agent) + .send()? + .error_for_status()? + .json()?; + + Ok(Json(value)) +} diff --git a/src/api/icons.rs b/src/api/icons.rs @@ -1,4 +1,3 @@ -use std::error::Error; use std::fs::{create_dir_all, remove_file, symlink_metadata, File}; use std::io::prelude::*; use std::time::SystemTime; @@ -9,6 +8,7 @@ use rocket::Route; use reqwest; +use crate::error::Error; use crate::CONFIG; pub fn routes() -> Vec<Route> { @@ -77,7 +77,7 @@ fn get_cached_icon(path: &str) -> Option<Vec<u8>> { None } -fn file_is_expired(path: &str, ttl: u64) -> Result<bool, Box<Error>> { +fn file_is_expired(path: &str, ttl: u64) -> Result<bool, Error> { let meta = symlink_metadata(path)?; let modified = meta.modified()?; let age = SystemTime::now().duration_since(modified)?; @@ -122,7 +122,7 @@ fn get_icon_url(domain: &str) -> String { } } -fn download_icon(url: &str) -> Result<Vec<u8>, reqwest::Error> { +fn download_icon(url: &str) -> Result<Vec<u8>, Error> { info!("Downloading icon for {}...", url); let mut res = reqwest::get(url)?; diff --git a/src/error.rs b/src/error.rs @@ -32,12 +32,14 @@ macro_rules! make_error { }; } -use diesel::result::Error as DieselError; -use jsonwebtoken::errors::Error as JwtError; -use serde_json::{Error as SerError, Value}; -use std::io::Error as IOError; +use diesel::result::Error as DieselErr; +use handlebars::RenderError as HbErr; +use jsonwebtoken::errors::Error as JWTErr; +use reqwest::Error as ReqErr; +use serde_json::{Error as SerdeErr, Value}; +use std::io::Error as IOErr; +use std::time::SystemTimeError as TimeErr; use u2f::u2ferror::U2fError as U2fErr; -use handlebars::RenderError as HbError; // Error struct // Contains a String error message, meant for the user and an enum variant, with an error of different types. @@ -49,13 +51,15 @@ make_error! { SimpleError(String): _no_source, _api_error, // Used for special return values, like 2FA errors JsonError(Value): _no_source, _serialize, - DbError(DieselError): _has_source, _api_error, + DbError(DieselErr): _has_source, _api_error, U2fError(U2fErr): _has_source, _api_error, - SerdeError(SerError): _has_source, _api_error, - JWTError(JwtError): _has_source, _api_error, - IoErrror(IOError): _has_source, _api_error, - TemplErrror(HbError): _has_source, _api_error, + SerdeError(SerdeErr): _has_source, _api_error, + JWTError(JWTErr): _has_source, _api_error, + TemplError(HbErr): _has_source, _api_error, //WsError(ws::Error): _has_source, _api_error, + IOError(IOErr): _has_source, _api_error, + TimeError(TimeErr): _has_source, _api_error, + ReqError(ReqErr): _has_source, _api_error, } impl std::fmt::Debug for Error {