mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-09-10 02:35:58 +03:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f571df7367 | ||
|
de51bc782e | ||
|
c5aef60bd7 | ||
|
8b07ecb937 | ||
|
6f52104324 | ||
|
1d7f704754 |
549
Cargo.lock
generated
549
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -11,9 +11,7 @@ publish = false
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["enable_yubikey"]
|
|
||||||
enable_syslog = ["syslog", "fern/syslog-4"]
|
enable_syslog = ["syslog", "fern/syslog-4"]
|
||||||
enable_yubikey = ["yubico"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Web framework for nightly with a focus on ease-of-use, expressibility, and speed.
|
# Web framework for nightly with a focus on ease-of-use, expressibility, and speed.
|
||||||
@@ -21,7 +19,7 @@ rocket = { version = "0.4.0", features = ["tls"], default-features = false }
|
|||||||
rocket_contrib = "0.4.0"
|
rocket_contrib = "0.4.0"
|
||||||
|
|
||||||
# HTTP client
|
# HTTP client
|
||||||
reqwest = "0.9.6"
|
reqwest = "0.9.8"
|
||||||
|
|
||||||
# multipart/form-data support
|
# multipart/form-data support
|
||||||
multipart = "0.15.4"
|
multipart = "0.15.4"
|
||||||
@@ -74,7 +72,7 @@ jsonwebtoken = "5.0.1"
|
|||||||
u2f = "0.1.4"
|
u2f = "0.1.4"
|
||||||
|
|
||||||
# Yubico Library
|
# Yubico Library
|
||||||
yubico = { version = "=0.4.0", features = ["online"], default-features = false, optional = true }
|
yubico = { version = "0.5.0", features = ["online"], default-features = false }
|
||||||
|
|
||||||
# A `dotenv` implementation for Rust
|
# A `dotenv` implementation for Rust
|
||||||
dotenv = { version = "0.13.0", default-features = false }
|
dotenv = { version = "0.13.0", default-features = false }
|
||||||
@@ -104,6 +102,3 @@ rmp = { git = 'https://github.com/dani-garcia/msgpack-rust' }
|
|||||||
# Use new native_tls version 0.2
|
# Use new native_tls version 0.2
|
||||||
lettre = { git = 'https://github.com/lettre/lettre', rev = 'c988b1760ad81' }
|
lettre = { git = 'https://github.com/lettre/lettre', rev = 'c988b1760ad81' }
|
||||||
lettre_email = { git = 'https://github.com/lettre/lettre', rev = 'c988b1760ad81' }
|
lettre_email = { git = 'https://github.com/lettre/lettre', rev = 'c988b1760ad81' }
|
||||||
|
|
||||||
# Allows optional libusb support
|
|
||||||
yubico = { git = 'https://github.com/dani-garcia/yubico-rs' }
|
|
||||||
|
@@ -55,8 +55,7 @@ COPY . .
|
|||||||
|
|
||||||
# Build
|
# Build
|
||||||
RUN rustup target add aarch64-unknown-linux-gnu
|
RUN rustup target add aarch64-unknown-linux-gnu
|
||||||
# TODO: Enable yubico when #262 is fixed
|
RUN cargo build --release --target=aarch64-unknown-linux-gnu -v
|
||||||
RUN cargo build --release --target=aarch64-unknown-linux-gnu -v --no-default-features
|
|
||||||
|
|
||||||
######################## RUNTIME IMAGE ########################
|
######################## RUNTIME IMAGE ########################
|
||||||
# Create a new stage with a minimal image
|
# Create a new stage with a minimal image
|
||||||
|
@@ -11,7 +11,9 @@
|
|||||||
|
|
||||||
Image is based on [Rust implementation of Bitwarden API](https://github.com/dani-garcia/bitwarden_rs).
|
Image is based on [Rust implementation of Bitwarden API](https://github.com/dani-garcia/bitwarden_rs).
|
||||||
|
|
||||||
_*Note, that this project is not associated with the [Bitwarden](https://bitwarden.com/) project nor 8bit Solutions LLC._
|
**This project is not associated with the [Bitwarden](https://bitwarden.com/) project nor 8bit Solutions LLC.**
|
||||||
|
|
||||||
|
#### ⚠️**IMPORTANT**⚠️: When using this server, please report any Bitwarden related bug-reports or suggestions [here](https://github.com/dani-garcia/bitwarden_rs/issues/new), regardless of whatever clients you are using (mobile, desktop, browser...). DO NOT use the official support channels.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -632,7 +632,7 @@ fn share_cipher_by_uuid(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/ciphers/<uuid>/attachment", format = "multipart/form-data", data = "<data>")]
|
#[post("/ciphers/<uuid>/attachment", format = "multipart/form-data", data = "<data>")]
|
||||||
fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers: Headers, conn: DbConn) -> JsonResult {
|
fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult {
|
||||||
let cipher = match Cipher::find_by_uuid(&uuid, &conn) {
|
let cipher = match Cipher::find_by_uuid(&uuid, &conn) {
|
||||||
Some(cipher) => cipher,
|
Some(cipher) => cipher,
|
||||||
None => err!("Cipher doesn't exist"),
|
None => err!("Cipher doesn't exist"),
|
||||||
@@ -692,6 +692,8 @@ fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers
|
|||||||
})
|
})
|
||||||
.expect("Error processing multipart data");
|
.expect("Error processing multipart data");
|
||||||
|
|
||||||
|
nt.send_cipher_update(UpdateType::CipherUpdate, &cipher, &cipher.update_users_revision(&conn));
|
||||||
|
|
||||||
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, &conn)))
|
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, &conn)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,8 +704,9 @@ fn post_attachment_admin(
|
|||||||
content_type: &ContentType,
|
content_type: &ContentType,
|
||||||
headers: Headers,
|
headers: Headers,
|
||||||
conn: DbConn,
|
conn: DbConn,
|
||||||
|
nt: Notify,
|
||||||
) -> JsonResult {
|
) -> JsonResult {
|
||||||
post_attachment(uuid, data, content_type, headers, conn)
|
post_attachment(uuid, data, content_type, headers, conn, nt)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post(
|
#[post(
|
||||||
@@ -721,7 +724,7 @@ fn post_attachment_share(
|
|||||||
nt: Notify,
|
nt: Notify,
|
||||||
) -> JsonResult {
|
) -> JsonResult {
|
||||||
_delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &conn, &nt)?;
|
_delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &conn, &nt)?;
|
||||||
post_attachment(uuid, data, content_type, headers, conn)
|
post_attachment(uuid, data, content_type, headers, conn, nt)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/ciphers/<uuid>/attachment/<attachment_id>/delete-admin")]
|
#[post("/ciphers/<uuid>/attachment/<attachment_id>/delete-admin")]
|
||||||
@@ -929,6 +932,6 @@ fn _delete_cipher_attachment_by_id(
|
|||||||
|
|
||||||
// Delete attachment
|
// Delete attachment
|
||||||
attachment.delete(&conn)?;
|
attachment.delete(&conn)?;
|
||||||
nt.send_cipher_update(UpdateType::CipherDelete, &cipher, &cipher.update_users_revision(&conn));
|
nt.send_cipher_update(UpdateType::CipherUpdate, &cipher, &cipher.update_users_revision(&conn));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -15,18 +15,8 @@ use crate::auth::Headers;
|
|||||||
|
|
||||||
use rocket::Route;
|
use rocket::Route;
|
||||||
|
|
||||||
#[cfg(feature = "enable_yubikey")]
|
|
||||||
fn yubi_routes() -> Vec<Route> {
|
|
||||||
routes![generate_yubikey, activate_yubikey, activate_yubikey_put]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "enable_yubikey"))]
|
|
||||||
fn yubi_routes() -> Vec<Route> {
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
let mut routes = routes![
|
routes![
|
||||||
get_twofactor,
|
get_twofactor,
|
||||||
get_recover,
|
get_recover,
|
||||||
recover,
|
recover,
|
||||||
@@ -39,11 +29,10 @@ pub fn routes() -> Vec<Route> {
|
|||||||
generate_u2f_challenge,
|
generate_u2f_challenge,
|
||||||
activate_u2f,
|
activate_u2f,
|
||||||
activate_u2f_put,
|
activate_u2f_put,
|
||||||
];
|
generate_yubikey,
|
||||||
|
activate_yubikey,
|
||||||
routes.append(&mut yubi_routes());
|
activate_yubikey_put,
|
||||||
|
]
|
||||||
routes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/two-factor")]
|
#[get("/two-factor")]
|
||||||
@@ -496,8 +485,8 @@ pub struct YubikeyMetadata {
|
|||||||
pub Nfc: bool,
|
pub Nfc: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "enable_yubikey")]
|
use yubico::config::Config;
|
||||||
use yubico::{config::Config, Yubico};
|
use yubico::Yubico;
|
||||||
|
|
||||||
fn parse_yubikeys(data: &EnableYubikeyData) -> Vec<String> {
|
fn parse_yubikeys(data: &EnableYubikeyData) -> Vec<String> {
|
||||||
let mut yubikeys: Vec<String> = Vec::new();
|
let mut yubikeys: Vec<String> = Vec::new();
|
||||||
@@ -535,7 +524,6 @@ fn jsonify_yubikeys(yubikeys: Vec<String>) -> serde_json::Value {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "enable_yubikey")]
|
|
||||||
fn verify_yubikey_otp(otp: String) -> JsonResult {
|
fn verify_yubikey_otp(otp: String) -> JsonResult {
|
||||||
if !CONFIG.yubico_cred_set {
|
if !CONFIG.yubico_cred_set {
|
||||||
err!("`YUBICO_CLIENT_ID` or `YUBICO_SECRET_KEY` environment variable is not set. Yubikey OTP Disabled")
|
err!("`YUBICO_CLIENT_ID` or `YUBICO_SECRET_KEY` environment variable is not set. Yubikey OTP Disabled")
|
||||||
@@ -557,7 +545,6 @@ fn verify_yubikey_otp(otp: String) -> JsonResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "enable_yubikey")]
|
|
||||||
#[post("/two-factor/get-yubikey", data = "<data>")]
|
#[post("/two-factor/get-yubikey", data = "<data>")]
|
||||||
fn generate_yubikey(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> JsonResult {
|
fn generate_yubikey(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> JsonResult {
|
||||||
if !CONFIG.yubico_cred_set {
|
if !CONFIG.yubico_cred_set {
|
||||||
@@ -593,7 +580,6 @@ fn generate_yubikey(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "enable_yubikey")]
|
|
||||||
#[post("/two-factor/yubikey", data = "<data>")]
|
#[post("/two-factor/yubikey", data = "<data>")]
|
||||||
fn activate_yubikey(data: JsonUpcase<EnableYubikeyData>, headers: Headers, conn: DbConn) -> JsonResult {
|
fn activate_yubikey(data: JsonUpcase<EnableYubikeyData>, headers: Headers, conn: DbConn) -> JsonResult {
|
||||||
let data: EnableYubikeyData = data.into_inner().data;
|
let data: EnableYubikeyData = data.into_inner().data;
|
||||||
@@ -655,18 +641,11 @@ fn activate_yubikey(data: JsonUpcase<EnableYubikeyData>, headers: Headers, conn:
|
|||||||
Ok(Json(result))
|
Ok(Json(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "enable_yubikey")]
|
|
||||||
#[put("/two-factor/yubikey", data = "<data>")]
|
#[put("/two-factor/yubikey", data = "<data>")]
|
||||||
fn activate_yubikey_put(data: JsonUpcase<EnableYubikeyData>, headers: Headers, conn: DbConn) -> JsonResult {
|
fn activate_yubikey_put(data: JsonUpcase<EnableYubikeyData>, headers: Headers, conn: DbConn) -> JsonResult {
|
||||||
activate_yubikey(data, headers, conn)
|
activate_yubikey(data, headers, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "enable_yubikey"))]
|
|
||||||
pub fn validate_yubikey_login(_: &str, _: &str, _: &DbConn) -> EmptyResult {
|
|
||||||
err!("Yubikey functionality is disabled. If you are using AArch64, check #262")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "enable_yubikey")]
|
|
||||||
pub fn validate_yubikey_login(user_uuid: &str, response: &str, conn: &DbConn) -> EmptyResult {
|
pub fn validate_yubikey_login(user_uuid: &str, response: &str, conn: &DbConn) -> EmptyResult {
|
||||||
if response.len() != 44 {
|
if response.len() != 44 {
|
||||||
err!("Invalid Yubikey OTP length");
|
err!("Invalid Yubikey OTP length");
|
||||||
|
@@ -85,6 +85,8 @@ impl Attachment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_by_id(id: &str, conn: &DbConn) -> Option<Self> {
|
pub fn find_by_id(id: &str, conn: &DbConn) -> Option<Self> {
|
||||||
|
let id = id.to_lowercase();
|
||||||
|
|
||||||
attachments::table
|
attachments::table
|
||||||
.filter(attachments::id.eq(id))
|
.filter(attachments::id.eq(id))
|
||||||
.first::<Self>(&**conn)
|
.first::<Self>(&**conn)
|
||||||
|
14
src/main.rs
14
src/main.rs
@@ -21,7 +21,7 @@ extern crate derive_more;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate num_derive;
|
extern crate num_derive;
|
||||||
|
|
||||||
use rocket::Rocket;
|
use rocket::{fairing::AdHoc, Rocket};
|
||||||
use std::{
|
use std::{
|
||||||
path::Path,
|
path::Path,
|
||||||
process::{exit, Command},
|
process::{exit, Command},
|
||||||
@@ -47,6 +47,7 @@ fn init_rocket() -> Rocket {
|
|||||||
.manage(db::init_pool())
|
.manage(db::init_pool())
|
||||||
.manage(api::start_notification_server())
|
.manage(api::start_notification_server())
|
||||||
.attach(util::AppHeaders())
|
.attach(util::AppHeaders())
|
||||||
|
.attach(unofficial_warning())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Embed the migrations from the migrations folder into the application
|
// Embed the migrations from the migrations folder into the application
|
||||||
@@ -91,6 +92,7 @@ fn init_logging() -> Result<(), fern::InitError> {
|
|||||||
})
|
})
|
||||||
.level(log::LevelFilter::Debug)
|
.level(log::LevelFilter::Debug)
|
||||||
.level_for("hyper", log::LevelFilter::Warn)
|
.level_for("hyper", log::LevelFilter::Warn)
|
||||||
|
.level_for("rustls", log::LevelFilter::Warn)
|
||||||
.level_for("ws", log::LevelFilter::Info)
|
.level_for("ws", log::LevelFilter::Info)
|
||||||
.level_for("multipart", log::LevelFilter::Info)
|
.level_for("multipart", log::LevelFilter::Info)
|
||||||
.chain(std::io::stdout());
|
.chain(std::io::stdout());
|
||||||
@@ -219,6 +221,16 @@ fn check_web_vault() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unofficial_warning() -> AdHoc {
|
||||||
|
AdHoc::on_launch("Unofficial Warning", |_| {
|
||||||
|
warn!("/--------------------------------------------------------------------\\");
|
||||||
|
warn!("| This is an *unofficial* Bitwarden implementation, DO NOT use the |");
|
||||||
|
warn!("| official channels to report bugs/features, regardless of client. |");
|
||||||
|
warn!("| Report URL: https://github.com/dani-garcia/bitwarden_rs/issues/new |");
|
||||||
|
warn!("\\--------------------------------------------------------------------/");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
// Load the config from .env or from environment variables
|
// Load the config from .env or from environment variables
|
||||||
static ref CONFIG: Config = Config::load();
|
static ref CONFIG: Config = Config::load();
|
||||||
|
Reference in New Issue
Block a user