Ordering auth methods in the CLI (#2508)

* rewriting ordering of authallowed enum
* ordering the authstate in the CLI

---------

Co-authored-by: William Brown <william@blackhats.net.au>
This commit is contained in:
James Hodgkinson 2024-02-15 12:31:01 +10:00 committed by GitHub
parent e880a63be4
commit 6b44495704
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 23 deletions

View file

@ -1012,30 +1012,26 @@ impl PartialEq for AuthAllowed {
} }
} }
impl From<&AuthAllowed> for u8 {
fn from(a: &AuthAllowed) -> u8 {
match a {
AuthAllowed::Anonymous => 0,
AuthAllowed::Password => 1,
AuthAllowed::BackupCode => 2,
AuthAllowed::Totp => 3,
AuthAllowed::Passkey(_) => 4,
AuthAllowed::SecurityKey(_) => 5,
}
}
}
impl Eq for AuthAllowed {} impl Eq for AuthAllowed {}
impl Ord for AuthAllowed { impl Ord for AuthAllowed {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
if self.eq(other) { let self_ord: u8 = self.into();
Ordering::Equal let other_ord: u8 = other.into();
} else { self_ord.cmp(&other_ord)
// Relies on the fact that match is executed in order!
match (self, other) {
(AuthAllowed::Anonymous, _) => Ordering::Less,
(_, AuthAllowed::Anonymous) => Ordering::Greater,
(AuthAllowed::Password, _) => Ordering::Less,
(_, AuthAllowed::Password) => Ordering::Greater,
(AuthAllowed::BackupCode, _) => Ordering::Less,
(_, AuthAllowed::BackupCode) => Ordering::Greater,
(AuthAllowed::Totp, _) => Ordering::Less,
(_, AuthAllowed::Totp) => Ordering::Greater,
(AuthAllowed::SecurityKey(_), _) => Ordering::Less,
(_, AuthAllowed::SecurityKey(_)) => Ordering::Greater,
(AuthAllowed::Passkey(_), _) => Ordering::Less,
// Unreachable
// (_, AuthAllowed::Passkey(_)) => Ordering::Greater,
}
}
} }
} }

View file

@ -1,4 +1,5 @@
use crate::common::OpType; use crate::common::OpType;
use std::cmp::Reverse;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fs::{create_dir, File}; use std::fs::{create_dir, File};
use std::io::{self, BufReader, BufWriter, ErrorKind, IsTerminal, Write}; use std::io::{self, BufReader, BufWriter, ErrorKind, IsTerminal, Write};
@ -264,16 +265,18 @@ async fn process_auth_state(
} }
_ => { _ => {
let mut options = Vec::new(); let mut options = Vec::new();
// because we want them in "most secure to least secure" order.
allowed.sort_unstable_by(|a, b| Reverse(a).cmp(&Reverse(b)));
for val in allowed.iter() { for val in allowed.iter() {
options.push(val.to_string()); options.push(val.to_string());
} }
let msg = "Please choose what credential to provide:"; let msg = "Please choose which credential to provide:";
let selection = get_index_choice_dialoguer(msg, &options); let selection = get_index_choice_dialoguer(msg, &options);
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
allowed allowed
.get(selection) .get(selection)
.expect("can not fail - bounds already checked.") .expect("Failed to select an authentication option!")
} }
}; };
@ -391,7 +394,7 @@ impl LoginOpt {
}; };
// What auth mechanisms exist? // What auth mechanisms exist?
let mechs: Vec<_> = client let mut mechs: Vec<_> = client
.auth_step_init(username) .auth_step_init(username)
.await .await
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
@ -401,6 +404,8 @@ impl LoginOpt {
.into_iter() .into_iter()
.collect(); .collect();
mechs.sort_unstable_by(|a, b| Reverse(a).cmp(&Reverse(b)));
let mech = match mechs.len() { let mech = match mechs.len() {
0 => { 0 => {
error!("Error during authentication init phase: Server offered no authentication mechanisms"); error!("Error during authentication init phase: Server offered no authentication mechanisms");