diff options
Diffstat (limited to 'nitrocli/src/args.rs')
-rw-r--r-- | nitrocli/src/args.rs | 112 |
1 files changed, 111 insertions, 1 deletions
diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs index f4035e6..c27fbc2 100644 --- a/nitrocli/src/args.rs +++ b/nitrocli/src/args.rs @@ -84,12 +84,14 @@ impl str::FromStr for Command { #[derive(Debug)] enum OtpCommand { Get, + Set, } impl OtpCommand { fn execute(&self, args: Vec<String>) -> Result<()> { match *self { OtpCommand::Get => otp_get(args), + OtpCommand::Set => otp_set(args), } } } @@ -101,6 +103,7 @@ impl fmt::Display for OtpCommand { "{}", match *self { OtpCommand::Get => "get", + OtpCommand::Set => "set", } ) } @@ -112,6 +115,7 @@ impl str::FromStr for OtpCommand { fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { match s { "get" => Ok(OtpCommand::Get), + "set" => Ok(OtpCommand::Set), _ => Err(()), } } @@ -148,6 +152,46 @@ impl str::FromStr for OtpAlgorithm { } } +#[derive(Clone, Copy, Debug)] +enum OtpMode { + SixDigits, + EightDigits, +} + +impl fmt::Display for OtpMode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match *self { + OtpMode::SixDigits => "6", + OtpMode::EightDigits => "8", + } + ) + } +} + +impl str::FromStr for OtpMode { + type Err = (); + + fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { + match s { + "6" => Ok(OtpMode::SixDigits), + "8" => Ok(OtpMode::EightDigits), + _ => Err(()), + } + } +} + +impl From<OtpMode> for nitrokey::OtpMode { + fn from(mode: OtpMode) -> Self { + match mode { + OtpMode::SixDigits => nitrokey::OtpMode::SixDigits, + OtpMode::EightDigits => nitrokey::OtpMode::EightDigits, + } + } +} + fn parse(parser: &argparse::ArgumentParser<'_>, args: Vec<String>) -> Result<()> { if let Err(err) = parser.parse(args, &mut io::stdout(), &mut io::stderr()) { Err(Error::ArgparseError(err)) @@ -201,7 +245,7 @@ fn otp(args: Vec<String>) -> Result<()> { let _ = parser.refer(&mut subcommand).required().add_argument( "subcommand", argparse::Store, - "The subcommand to execute (get)", + "The subcommand to execute (get|set)", ); let _ = parser.refer(&mut subargs).add_argument( "arguments", @@ -238,6 +282,72 @@ fn otp_get(args: Vec<String>) -> Result<()> { commands::otp_get(slot, algorithm) } +/// Configure a one-time password slot on the Nitrokey device. +pub fn otp_set(args: Vec<String>) -> Result<()> { + let mut slot: u8 = 0; + let mut algorithm = OtpAlgorithm::Totp; + let mut name = "".to_owned(); + let mut secret = "".to_owned(); + let mut digits = OtpMode::SixDigits; + let mut counter: u64 = 0; + let mut time_window: u16 = 30; + let mut ascii = false; + let mut parser = argparse::ArgumentParser::new(); + parser.set_description("Configures a one-time password slot"); + let _ = + parser + .refer(&mut slot) + .required() + .add_argument("slot", argparse::Store, "The OTP slot to use"); + let _ = parser.refer(&mut algorithm).add_option( + &["-a", "--algorithm"], + argparse::Store, + "The OTP algorithm to use (hotp or totp, default: totp", + ); + let _ = parser.refer(&mut name).required().add_argument( + "name", + argparse::Store, + "The name of the slot", + ); + let _ = parser.refer(&mut secret).required().add_argument( + "secret", + argparse::Store, + "The secret to store on the slot as a hexadecimal string (unless --ascii is set)", + ); + let _ = parser.refer(&mut digits).add_option( + &["-d", "--digits"], + argparse::Store, + "The number of digits to use for the one-time password (6 or 8, default: 6)", + ); + let _ = parser.refer(&mut counter).add_option( + &["-c", "--counter"], + argparse::Store, + "The counter value for HOTP (default: 0)", + ); + let _ = parser.refer(&mut time_window).add_option( + &["-t", "--time-window"], + argparse::Store, + "The time window for TOTP (default: 30)", + ); + let _ = parser.refer(&mut ascii).add_option( + &["--ascii"], + argparse::StoreTrue, + "Interpret the given secret as an ASCII string of the secret", + ); + parse(&parser, args)?; + drop(parser); + + let data = nitrokey::OtpSlotData { + number: slot, + name, + secret, + mode: nitrokey::OtpMode::from(digits), + use_enter: false, + token_id: None, + }; + commands::otp_set(data, algorithm, counter, time_window, ascii) +} + /// Parse the command-line arguments and return the selected command and /// the remaining arguments for the command. fn parse_arguments(args: Vec<String>) -> Result<(Command, Vec<String>)> { |