From ad0a078a5a2c4c9efd16b20ff47cc4e1ef922dab Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 25 Mar 2023 16:46:12 -0400 Subject: clippy, fmt, etc --- src/actions.rs | 47 ++++++++-- src/api.rs | 211 ++++++++++++++++++++++--------------------- src/bin/rbw-agent/actions.rs | 27 ++++-- src/db.rs | 4 +- src/error.rs | 1 - src/identity.rs | 36 +++++--- 6 files changed, 193 insertions(+), 133 deletions(-) diff --git a/src/actions.rs b/src/actions.rs index 7212415..b07cf44 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -1,4 +1,4 @@ -use crate::{prelude::*, api::KdfType}; +use crate::prelude::*; pub async fn register( email: &str, @@ -18,12 +18,27 @@ pub async fn login( password: crate::locked::Password, two_factor_token: Option<&str>, two_factor_provider: Option, -) -> Result<(String, String, KdfType, u32, Option, Option, String)> { +) -> Result<( + String, + String, + crate::api::KdfType, + u32, + Option, + Option, + String, +)> { let (client, config) = api_client_async().await?; - let (kdf, iterations, memory, parallelism) = client.prelogin(email).await?; + let (kdf, iterations, memory, parallelism) = + client.prelogin(email).await?; - let identity = - crate::identity::Identity::new(email, &password, kdf, iterations, memory, parallelism)?; + let identity = crate::identity::Identity::new( + email, + &password, + kdf, + iterations, + memory, + parallelism, + )?; let (access_token, refresh_token, protected_key) = client .login( email, @@ -34,13 +49,21 @@ pub async fn login( ) .await?; - Ok((access_token, refresh_token, kdf, iterations, memory, parallelism, protected_key)) + Ok(( + access_token, + refresh_token, + kdf, + iterations, + memory, + parallelism, + protected_key, + )) } pub fn unlock( email: &str, password: &crate::locked::Password, - kdf: KdfType, + kdf: crate::api::KdfType, iterations: u32, memory: Option, parallelism: Option, @@ -51,8 +74,14 @@ pub fn unlock( crate::locked::Keys, std::collections::HashMap, )> { - let identity = - crate::identity::Identity::new(email, password, kdf, iterations, memory, parallelism)?; + let identity = crate::identity::Identity::new( + email, + password, + kdf, + iterations, + memory, + parallelism, + )?; let protected_key = crate::cipherstring::CipherString::new(protected_key)?; diff --git a/src/api.rs b/src/api.rs index 85a0ce5..bf608b3 100644 --- a/src/api.rs +++ b/src/api.rs @@ -58,27 +58,27 @@ pub enum TwoFactorProviderType { } impl TwoFactorProviderType { + #[must_use] pub fn message(&self) -> &str { match *self { - TwoFactorProviderType::Authenticator => "Enter the 6 digit verification code from your authenticator app.", - TwoFactorProviderType::Email => "Enter the PIN you received via email.", + Self::Authenticator => "Enter the 6 digit verification code from your authenticator app.", + Self::Email => "Enter the PIN you received via email.", _ => "Enter the code." } } + #[must_use] pub fn header(&self) -> &str { match *self { - TwoFactorProviderType::Authenticator => "Authenticator App", - TwoFactorProviderType::Email => "Email Code", - _ => "Two Factor Authentication" + Self::Authenticator => "Authenticator App", + Self::Email => "Email Code", + _ => "Two Factor Authentication", } } + #[must_use] pub fn grab(&self) -> bool { - match *self { - TwoFactorProviderType::Email => false, - _ => true - } + !matches!(self, Self::Email) } } @@ -162,6 +162,96 @@ impl std::str::FromStr for TwoFactorProviderType { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum KdfType { + Pbkdf2 = 0, + Argon2id = 1, +} + +impl<'de> serde::Deserialize<'de> for KdfType { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct KdfTypeVisitor; + impl<'de> serde::de::Visitor<'de> for KdfTypeVisitor { + type Value = KdfType; + + fn expecting( + &self, + formatter: &mut std::fmt::Formatter, + ) -> std::fmt::Result { + formatter.write_str("kdf id") + } + + fn visit_str( + self, + value: &str, + ) -> std::result::Result + where + E: serde::de::Error, + { + value.parse().map_err(serde::de::Error::custom) + } + + fn visit_u64( + self, + value: u64, + ) -> std::result::Result + where + E: serde::de::Error, + { + std::convert::TryFrom::try_from(value) + .map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_any(KdfTypeVisitor) + } +} + +impl std::convert::TryFrom for KdfType { + type Error = Error; + + fn try_from(ty: u64) -> Result { + match ty { + 0 => Ok(Self::Pbkdf2), + 1 => Ok(Self::Argon2id), + _ => Err(Error::InvalidKdfType { + ty: format!("{ty}"), + }), + } + } +} + +impl std::str::FromStr for KdfType { + type Err = Error; + + fn from_str(ty: &str) -> Result { + match ty { + "0" => Ok(Self::Pbkdf2), + "1" => Ok(Self::Argon2id), + _ => Err(Error::InvalidKdfType { ty: ty.to_string() }), + } + } +} + +impl serde::Serialize for KdfType { + fn serialize( + &self, + serializer: S, + ) -> std::result::Result + where + S: serde::Serializer, + { + let s = match self { + Self::Pbkdf2 => "0", + Self::Argon2id => "1", + }; + serializer.serialize_str(s) + } +} + #[derive(serde::Serialize, Debug)] struct PreloginReq { email: String, @@ -634,7 +724,10 @@ impl Client { } } - pub async fn prelogin(&self, email: &str) -> Result<(KdfType, u32, Option, Option)> { + pub async fn prelogin( + &self, + email: &str, + ) -> Result<(KdfType, u32, Option, Option)> { let prelogin = PreloginReq { email: email.to_string(), }; @@ -646,7 +739,12 @@ impl Client { .await .map_err(|source| Error::Reqwest { source })?; let prelogin_res: PreloginRes = res.json_with_path().await?; - Ok((prelogin_res.kdf, prelogin_res.kdf_iterations, prelogin_res.kdf_memory, prelogin_res.kdf_parallelism)) + Ok(( + prelogin_res.kdf, + prelogin_res.kdf_iterations, + prelogin_res.kdf_memory, + prelogin_res.kdf_parallelism, + )) } pub async fn register( @@ -1218,94 +1316,3 @@ fn classify_login_error(error_res: &ConnectErrorRes, code: u16) -> Error { log::warn!("unexpected error received during login: {:?}", error_res); Error::RequestFailed { status: code } } - - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum KdfType { - Pbkdf2 = 0, - Argon2id = 1, -} - -impl<'de> serde::Deserialize<'de> for KdfType { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct KdfTypeVisitor; - impl<'de> serde::de::Visitor<'de> for KdfTypeVisitor { - type Value = KdfType; - - fn expecting( - &self, - formatter: &mut std::fmt::Formatter, - ) -> std::fmt::Result { - formatter.write_str("two factor provider id") - } - - fn visit_str( - self, - value: &str, - ) -> std::result::Result - where - E: serde::de::Error, - { - value.parse().map_err(serde::de::Error::custom) - } - - fn visit_u64( - self, - value: u64, - ) -> std::result::Result - where - E: serde::de::Error, - { - std::convert::TryFrom::try_from(value) - .map_err(serde::de::Error::custom) - } - } - - deserializer.deserialize_any(KdfTypeVisitor) - } -} - -impl std::convert::TryFrom for KdfType { - type Error = Error; - - fn try_from(ty: u64) -> Result { - match ty { - 0 => Ok(Self::Pbkdf2), - 1 => Ok(Self::Argon2id), - _ => Err(Error::InvalidTwoFactorProvider { - ty: format!("{ty}"), - }), - } - } -} - -impl std::str::FromStr for KdfType { - type Err = Error; - - fn from_str(ty: &str) -> Result { - match ty { - "0" => Ok(Self::Pbkdf2), - "1" => Ok(Self::Argon2id), - _ => Err(Error::InvalidTwoFactorProvider { ty: ty.to_string() }), - } - } -} - -impl serde::Serialize for KdfType { - fn serialize( - &self, - serializer: S, - ) -> std::result::Result - where - S: serde::Serializer, - { - let s = match self { - Self::Pbkdf2 => "0", - Self::Argon2id => "1", - }; - serializer.serialize_str(s) - } -} diff --git a/src/bin/rbw-agent/actions.rs b/src/bin/rbw-agent/actions.rs index 361009b..e857a1e 100644 --- a/src/bin/rbw-agent/actions.rs +++ b/src/bin/rbw-agent/actions.rs @@ -1,5 +1,4 @@ use anyhow::Context as _; -use rbw::api::KdfType; pub async fn register( sock: &mut crate::sock::Sock, @@ -153,7 +152,7 @@ pub async fn login( rbw::api::TwoFactorProviderType::Email, ]; - for provider in supported_types.into_iter() { + for provider in supported_types { if providers.contains(&provider) { let ( access_token, @@ -218,7 +217,15 @@ async fn two_factor( email: &str, password: rbw::locked::Password, provider: rbw::api::TwoFactorProviderType, -) -> anyhow::Result<(String, String, KdfType, u32, Option, Option, String)> { +) -> anyhow::Result<( + String, + String, + rbw::api::KdfType, + u32, + Option, + Option, + String, +)> { let mut err_msg = None; for i in 1_u8..=3 { let err = if i > 1 { @@ -248,7 +255,15 @@ async fn two_factor( ) .await { - Ok((access_token, refresh_token, kdf, iterations, memory, parallelism, protected_key)) => { + Ok(( + access_token, + refresh_token, + kdf, + iterations, + memory, + parallelism, + protected_key, + )) => { return Ok(( access_token, refresh_token, @@ -296,7 +311,7 @@ async fn login_success( state: std::sync::Arc>, access_token: String, refresh_token: String, - kdf: KdfType, + kdf: rbw::api::KdfType, iterations: u32, memory: Option, parallelism: Option, @@ -370,7 +385,7 @@ pub async fn unlock( )); }; - let memory= db.memory; + let memory = db.memory; let parallelism = db.parallelism; let Some(protected_key) = db.protected_key diff --git a/src/db.rs b/src/db.rs index 74be28a..73a69d1 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,4 +1,4 @@ -use crate::{prelude::*, api::KdfType}; +use crate::prelude::*; use std::io::{Read as _, Write as _}; use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _}; @@ -164,7 +164,7 @@ pub struct Db { pub access_token: Option, pub refresh_token: Option, - pub kdf: Option, + pub kdf: Option, pub iterations: Option, pub memory: Option, pub parallelism: Option, diff --git a/src/error.rs b/src/error.rs index 9b7261f..31edaf3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -228,7 +228,6 @@ pub enum Error { #[error("error writing to pinentry stdin")] WriteStdin { source: tokio::io::Error }, - #[error("invalid kdf type: {ty}")] InvalidKdfType { ty: String }, } diff --git a/src/identity.rs b/src/identity.rs index 9bc435f..123dc31 100644 --- a/src/identity.rs +++ b/src/identity.rs @@ -1,6 +1,7 @@ -use crate::{prelude::*, api::KdfType}; -use sha2::Digest; -use argon2::Argon2; +use crate::prelude::*; + +use sha1::Digest as _; + pub struct Identity { pub email: String, pub keys: crate::locked::Keys, @@ -11,7 +12,7 @@ impl Identity { pub fn new( email: &str, password: &crate::locked::Password, - kdf: KdfType, + kdf: crate::api::KdfType, iterations: u32, memory: Option, parallelism: Option, @@ -25,7 +26,7 @@ impl Identity { let enc_key = &mut keys.data_mut()[0..32]; match kdf { - KdfType::Pbkdf2 => { + crate::api::KdfType::Pbkdf2 => { pbkdf2::pbkdf2::>( password.password(), email.as_bytes(), @@ -35,25 +36,34 @@ impl Identity { .map_err(|_| Error::Pbkdf2)?; } - KdfType::Argon2id => { + crate::api::KdfType::Argon2id => { let mut hasher = sha2::Sha256::new(); hasher.update(email.as_bytes()); - let mut salt = hasher.finalize(); + let salt = hasher.finalize(); let mut output_key_material = [0u8]; - let argon2_config = Argon2::new( + let argon2_config = argon2::Argon2::new( argon2::Algorithm::Argon2id, argon2::Version::V0x13, - argon2::Params::new(memory.unwrap() * 1024, + argon2::Params::new( + memory.unwrap() * 1024, iterations.get(), parallelism.unwrap(), - Some(32)).unwrap()); - argon2::Argon2::hash_password_into(&argon2_config, password.password(), &mut salt, &mut output_key_material) - .map_err(|_| Error::Argon2)?; + Some(32), + ) + .unwrap(), + ); + argon2::Argon2::hash_password_into( + &argon2_config, + password.password(), + &salt, + &mut output_key_material, + ) + .map_err(|_| Error::Argon2)?; enc_key.copy_from_slice(&output_key_material); } }; - + let mut hash = crate::locked::Vec::new(); hash.extend(std::iter::repeat(0).take(32)); pbkdf2::pbkdf2::>( -- cgit v1.2.3-54-g00ecf