* [pbs-devel] [PATCH backup 1/2] tfa: remember recovery indices
@ 2021-01-18 11:46 Wolfgang Bumiller
2021-01-18 11:46 ` [pbs-devel] [PATCH backup 2/2] gui: enumerate recovery keys and list in 2nd factor window Wolfgang Bumiller
2021-01-18 12:52 ` [pbs-devel] applied: [PATCH backup 1/2] tfa: remember recovery indices Thomas Lamprecht
0 siblings, 2 replies; 4+ messages in thread
From: Wolfgang Bumiller @ 2021-01-18 11:46 UTC (permalink / raw)
To: pbs-devel
and tell the client which keys are still available rather
than just yes/no/low
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
src/config/tfa.rs | 76 ++++++++++++++++++++++-------------------------
1 file changed, 35 insertions(+), 41 deletions(-)
diff --git a/src/config/tfa.rs b/src/config/tfa.rs
index e0f2fcfe..5d01ea82 100644
--- a/src/config/tfa.rs
+++ b/src/config/tfa.rs
@@ -1088,7 +1088,7 @@ impl TfaUserData {
#[derive(Deserialize, Serialize)]
pub struct Recovery {
secret: String,
- entries: Vec<String>,
+ entries: Vec<Option<String>>,
}
impl Recovery {
@@ -1116,7 +1116,7 @@ impl Recovery {
AsHex(&b[6..8]),
);
- this.entries.push(this.hash(entry.as_bytes())?);
+ this.entries.push(Some(this.hash(entry.as_bytes())?));
original.push(entry);
}
@@ -1138,31 +1138,32 @@ impl Recovery {
Ok(AsHex(&hmac).to_string())
}
- /// Shortcut to get the count.
- fn len(&self) -> usize {
- self.entries.len()
+ /// Iterator over available keys.
+ fn available(&self) -> impl Iterator<Item = &str> {
+ self.entries.iter().filter_map(Option::as_deref)
}
- /// Check if this entry is empty.
- fn is_empty(&self) -> bool {
- self.entries.is_empty()
+ /// Count the available keys.
+ fn count_available(&self) -> usize {
+ self.available().count()
}
/// Convenience serde method to check if either the option is `None` or the content `is_empty`.
fn option_is_empty(this: &Option<Self>) -> bool {
- this.as_ref().map_or(true, Self::is_empty)
+ this.as_ref()
+ .map_or(true, |this| this.count_available() == 0)
}
/// Verify a key and remove it. Returns whether the key was valid. Errors on openssl errors.
fn verify(&mut self, key: &str) -> Result<bool, Error> {
let hash = self.hash(key.as_bytes())?;
- Ok(match self.entries.iter().position(|entry| *entry == hash) {
- Some(index) => {
- self.entries.remove(index);
- true
+ for entry in &mut self.entries {
+ if entry.as_ref() == Some(&hash) {
+ *entry = None;
+ return Ok(true);
}
- None => false,
- })
+ }
+ Ok(false)
}
}
@@ -1283,45 +1284,38 @@ pub fn verify_challenge(
}
/// Used to inform the user about the recovery code status.
-#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize)]
-#[serde(rename_all = "kebab-case")]
-pub enum RecoveryState {
- Unavailable,
- Low,
- Available,
-}
+///
+/// This contains the available key indices.
+#[derive(Clone, Default, Eq, PartialEq, Deserialize, Serialize)]
+pub struct RecoveryState(Vec<usize>);
impl RecoveryState {
- fn from_count(count: usize) -> Self {
- match count {
- 0 => RecoveryState::Unavailable,
- 1..=3 => RecoveryState::Low,
- _ => RecoveryState::Available,
- }
- }
-
- // serde needs `&self` but this is a tiny Copy type, so we mark this as inline
- #[inline]
fn is_unavailable(&self) -> bool {
- *self == RecoveryState::Unavailable
- }
-}
-
-impl Default for RecoveryState {
- fn default() -> Self {
- RecoveryState::Unavailable
+ self.0.is_empty()
}
}
impl From<&Option<Recovery>> for RecoveryState {
fn from(r: &Option<Recovery>) -> Self {
match r {
- Some(r) => Self::from_count(r.len()),
- None => RecoveryState::Unavailable,
+ Some(r) => Self::from(r),
+ None => Self::default(),
}
}
}
+impl From<&Recovery> for RecoveryState {
+ fn from(r: &Recovery) -> Self {
+ Self(
+ r.entries
+ .iter()
+ .enumerate()
+ .filter_map(|(idx, key)| if key.is_some() { Some(idx) } else { None })
+ .collect(),
+ )
+ }
+}
+
/// When sending a TFA challenge to the user, we include information about what kind of challenge
/// the user may perform. If webauthn credentials are available, a webauthn challenge will be
/// included.
--
2.20.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [pbs-devel] [PATCH backup 2/2] gui: enumerate recovery keys and list in 2nd factor window
2021-01-18 11:46 [pbs-devel] [PATCH backup 1/2] tfa: remember recovery indices Wolfgang Bumiller
@ 2021-01-18 11:46 ` Wolfgang Bumiller
2021-01-18 12:52 ` [pbs-devel] applied: " Thomas Lamprecht
2021-01-18 12:52 ` [pbs-devel] applied: [PATCH backup 1/2] tfa: remember recovery indices Thomas Lamprecht
1 sibling, 1 reply; 4+ messages in thread
From: Wolfgang Bumiller @ 2021-01-18 11:46 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
www/LoginView.js | 20 +++++++++++++++++---
www/window/AddTfaRecovery.js | 7 ++++++-
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/www/LoginView.js b/www/LoginView.js
index fa8772b5..2dd84de9 100644
--- a/www/LoginView.js
+++ b/www/LoginView.js
@@ -281,9 +281,9 @@ Ext.define('PBS.login.TfaWindow', {
me.lookup('totpButton').setVisible(false);
}
- if (!view.challenge.recovery) {
+ if (!view.challenge.recovery || !view.challenge.recovery.length) {
me.lookup('recoveryButton').setVisible(false);
- } else if (view.challenge.recovery === "low") {
+ } else if (view.challenge.recovery.length <= 3) {
me.lookup('recoveryButton')
.setIconCls('fa fa-fw fa-exclamation-triangle');
}
@@ -384,7 +384,12 @@ Ext.define('PBS.login.TfaWindow', {
me.lookup('webauthnButton').setVisible(false);
me.lookup('recoveryButton').setText(gettext("Confirm"));
me.lookup('recoveryInfo').setVisible(true);
- if (view.challenge.recovery === "low") {
+ console.log("RECOVERY:", view.challenge.recovery);
+ me.lookup('availableRecovery').update(Ext.String.htmlEncode(
+ gettext('Available recovery keys: ') + view.challenge.recovery.join(', ')
+ ));
+ me.lookup('availableRecovery').setVisible(true);
+ if (view.challenge.recovery.length <= 3) {
me.lookup('recoveryLow').setVisible(true);
}
}
@@ -456,6 +461,15 @@ Ext.define('PBS.login.TfaWindow', {
textAlign: "center",
},
},
+ {
+ xtype: 'box',
+ padding: '0 5',
+ reference: 'availableRecovery',
+ hidden: true,
+ style: {
+ textAlign: "center",
+ },
+ },
{
xtype: 'box',
padding: '0 5',
diff --git a/www/window/AddTfaRecovery.js b/www/window/AddTfaRecovery.js
index b63e8576..1718f026 100644
--- a/www/window/AddTfaRecovery.js
+++ b/www/window/AddTfaRecovery.js
@@ -24,7 +24,12 @@ Ext.define('PBS.window.AddTfaRecovery', {
return;
}
- let values = response.result.data.recovery.join("\n");
+ let values = response
+ .result
+ .data
+ .recovery
+ .map((v, i) => `${i}: ${v}`)
+ .join("\n");
Ext.create('PBS.window.TfaRecoveryShow', {
autoShow: true,
userid: this.getViewModel().get('userid'),
--
2.20.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [pbs-devel] applied: [PATCH backup 1/2] tfa: remember recovery indices
2021-01-18 11:46 [pbs-devel] [PATCH backup 1/2] tfa: remember recovery indices Wolfgang Bumiller
2021-01-18 11:46 ` [pbs-devel] [PATCH backup 2/2] gui: enumerate recovery keys and list in 2nd factor window Wolfgang Bumiller
@ 2021-01-18 12:52 ` Thomas Lamprecht
1 sibling, 0 replies; 4+ messages in thread
From: Thomas Lamprecht @ 2021-01-18 12:52 UTC (permalink / raw)
To: Proxmox Backup Server development discussion, Wolfgang Bumiller
On 18.01.21 12:46, Wolfgang Bumiller wrote:
> and tell the client which keys are still available rather
> than just yes/no/low
>
> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
> ---
> src/config/tfa.rs | 76 ++++++++++++++++++++++-------------------------
> 1 file changed, 35 insertions(+), 41 deletions(-)
>
>
applied, thanks!
^ permalink raw reply [flat|nested] 4+ messages in thread
* [pbs-devel] applied: [PATCH backup 2/2] gui: enumerate recovery keys and list in 2nd factor window
2021-01-18 11:46 ` [pbs-devel] [PATCH backup 2/2] gui: enumerate recovery keys and list in 2nd factor window Wolfgang Bumiller
@ 2021-01-18 12:52 ` Thomas Lamprecht
0 siblings, 0 replies; 4+ messages in thread
From: Thomas Lamprecht @ 2021-01-18 12:52 UTC (permalink / raw)
To: Proxmox Backup Server development discussion, Wolfgang Bumiller
On 18.01.21 12:46, Wolfgang Bumiller wrote:
> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
> ---
> www/LoginView.js | 20 +++++++++++++++++---
> www/window/AddTfaRecovery.js | 7 ++++++-
> 2 files changed, 23 insertions(+), 4 deletions(-)
>
>
applied, thanks!
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-01-18 12:52 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-18 11:46 [pbs-devel] [PATCH backup 1/2] tfa: remember recovery indices Wolfgang Bumiller
2021-01-18 11:46 ` [pbs-devel] [PATCH backup 2/2] gui: enumerate recovery keys and list in 2nd factor window Wolfgang Bumiller
2021-01-18 12:52 ` [pbs-devel] applied: " Thomas Lamprecht
2021-01-18 12:52 ` [pbs-devel] applied: [PATCH backup 1/2] tfa: remember recovery indices Thomas Lamprecht
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal