diff --git a/bffhd/authentication/db.rs b/bffhd/authentication/db.rs index 1f1064a..f9149c7 100644 --- a/bffhd/authentication/db.rs +++ b/bffhd/authentication/db.rs @@ -1,11 +1,11 @@ use std::sync::Arc; -use super::Environment; -use super::AllocAdapter; -use super::DB; -use super::raw::RawDB; -use super::{DatabaseFlags, WriteFlags}; +use crate::db::Environment; +use crate::db::AllocAdapter; +use crate::db::DB; +use crate::db::RawDB; +use crate::db::{DatabaseFlags, WriteFlags}; use crate::db::Result; -use super::Transaction; +use crate::db::Transaction; use argon2; diff --git a/bffhd/db/mod.rs b/bffhd/db/mod.rs index 93139f7..4072414 100644 --- a/bffhd/db/mod.rs +++ b/bffhd/db/mod.rs @@ -46,6 +46,8 @@ use std::collections::HashMap; use crate::resource::state::{OwnedEntry, State, db::StateDB}; use std::iter::FromIterator; use std::ops::Deref; +use crate::authentication::db::PassDB; +use crate::resource::db::ResourceDB; use crate::utils::oid::{ArchivedObjectIdentifier, ObjectIdentifier}; use crate::resource::state::value::SerializeValue; diff --git a/bffhd/resource/db.rs b/bffhd/resource/db.rs index aac4323..73bd1cf 100644 --- a/bffhd/resource/db.rs +++ b/bffhd/resource/db.rs @@ -1,8 +1,8 @@ use rkyv::{Archive, Serialize, Deserialize}; -use super::DB; +use crate::db::DB; use crate::db::{AlignedAdapter, AllocAdapter}; -use crate::db::raw::RawDB; +use crate::db::RawDB; use std::sync::Arc; use crate::db::{Environment, DatabaseFlags}; use crate::db::Result; diff --git a/bffhd/users/mod.rs b/bffhd/users/mod.rs index c0f2424..1764b1d 100644 --- a/bffhd/users/mod.rs +++ b/bffhd/users/mod.rs @@ -28,10 +28,9 @@ use api::user::{ }; mod db; -mod pass; pub use db::UserDB; -pub use pass::PassDB; +pub use crate::authentication::db::PassDB; #[derive(Debug, Clone, Archive, Serialize, Deserialize, serde::Serialize, serde::Deserialize)] /// User API endpoint diff --git a/bffhd/users/pass.rs b/bffhd/users/pass.rs deleted file mode 100644 index 5dc6568..0000000 --- a/bffhd/users/pass.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::sync::Arc; -use rand::RngCore; -use crate::db::{RawDB, DB, AllocAdapter, Environment, Result, DBError}; -use crate::db::{DatabaseFlags, WriteFlags}; - -use rkyv::{Serialize, Deserialize, Archived, Archive}; - -#[repr(transparent)] -#[derive(Debug, Clone, Eq, PartialEq, Archive, Serialize, Deserialize)] -pub struct Password(String); - -fn check_password(stored: &Archived, input: &[u8]) -> argon2::Result { - argon2::verify_encoded(stored.0.as_str(), input) -} - -type Adapter = AllocAdapter; - -#[derive(Clone, Debug)] -/// Internal Password Database -pub struct PassDB { - env: Arc, - db: DB, -} - -impl PassDB { - pub unsafe fn new(env: Arc, db: RawDB) -> Self { - let db = DB::new_unchecked(db); - Self { env, db } - } - - pub unsafe fn open(env: Arc) -> Result { - let db = RawDB::open(&env, Some("user"))?; - Ok(Self::new(env, db)) - } - - pub unsafe fn create(env: Arc) -> Result { - let flags = DatabaseFlags::empty(); - let db = RawDB::create(&env, Some("user"), flags)?; - Ok(Self::new(env, db)) - } - - /// Verify if the given password matches for the given user. - pub fn verify_password(&self, uid: &str, password: &[u8]) - -> Result>> - { - let txn = self.env.begin_ro_txn()?; - if let Some(stored) = self.db.get(&txn, &uid.as_bytes())? { - Ok(Some(check_password(stored, password))) - } else { - Ok(None) - } - } - - /// Set or update a password for a given uid. - /// - /// The given uid must not be "" and the given password must be 1..=1024 bytes. - pub fn set_password(&self, uid: &str, password: &[u8]) -> Result<()> { - debug_assert!(!uid.is_empty()); - debug_assert!(0 < password.len() && password.len() <= 1024); - - let config = argon2::Config::default(); - let mut salt: [u8; 16] = [0u8; 16]; - rand::thread_rng().fill_bytes(&mut salt); - let encoded = argon2::hash_encoded(password, &salt, &config) - .expect("Hashing given user password failed"); - let pwd = Password(encoded); - - let mut txn = self.env.begin_rw_txn()?; - self.db.put(&mut txn, &uid.as_bytes(), &pwd, WriteFlags::empty())?; - Ok(()) - } - - /// Delete an password entry from the database. - /// - /// Returns `Ok(false)` if no entry existed for the given user. - /// Thus, if this function returns `Ok(_)` you can be sure this db contains no password hash - /// for the given uid. - pub fn delete_password(&self, uid: &str) -> Result { - let mut txn = self.env.begin_rw_txn()?; - match self.db.del(&mut txn, &uid.as_bytes()) { - Ok(_) => Ok(true), - Err(DBError::LMDB(lmdb::Error::NotFound)) => Ok(false), - Err(e) => Err(e), - } - } - - /// Return all entries in this db in the form [(uid, password hash)]. - pub fn get_all(&self) -> Result> { - let txn = self.env.begin_ro_txn()?; - let mut cursor = self.db.open_ro_cursor(&txn)?; - let iter = cursor.iter_start(); - let mut out = Vec::new(); - let mut deserializer = rkyv::Infallible; - for passentry in iter { - let (uid, password) = passentry?; - let uid = unsafe { std::str::from_utf8_unchecked(uid).to_string() }; - let password: Password = password.deserialize(&mut deserializer).unwrap(); - out.push((uid, password)); - } - - Ok(out) - } -} \ No newline at end of file