From eea4f7357d7a3e3b365d887671ba78fd386a6d2d Mon Sep 17 00:00:00 2001 From: Daniel Mueller Date: Wed, 9 Jan 2019 16:31:31 -0800 Subject: Honor context provided Admin & User PIN in pin commands The second source of interactivity comes from the pin set and pin unblock commands, which also inquire with the pinentry module to ask the user for a PIN. This change adjusts the two commands to honor the PINs as available in the command execution context. It also updates the documentation to reflect the availability of the newly introduced and honored environment variables NITROCLI_ADMIN_PIN & NITROCLI_USER_PIN as well as NITROCLI_NEW_ADMIN_PIN & NITROCLI_NEW_USER_PIN. --- nitrocli/CHANGELOG.md | 3 +++ nitrocli/doc/nitrocli.1 | 19 +++++++++++++++++++ nitrocli/doc/nitrocli.1.pdf | Bin 14513 -> 15436 bytes nitrocli/src/commands.rs | 42 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/nitrocli/CHANGELOG.md b/nitrocli/CHANGELOG.md index da44c4a..fe9b69c 100644 --- a/nitrocli/CHANGELOG.md +++ b/nitrocli/CHANGELOG.md @@ -6,6 +6,9 @@ Unreleased - Added the `-f`/`--format` option for the `otp set` subcommand to choose the secret format - Deprecated the `--ascii` option +- Honor `NITROCLI_ADMIN_PIN` and `NITROCLI_USER_PIN` as well as + `NITROCLI_NEW_ADMIN_PIN` and `NITROCLI_NEW_USER_PIN` environment + variables for non-interactive PIN supply - Format `nitrokey` reported errors in more user-friendly format - Bumped `nitrokey` dependency to `0.3.1` diff --git a/nitrocli/doc/nitrocli.1 b/nitrocli/doc/nitrocli.1 index 036c25f..234b588 100644 --- a/nitrocli/doc/nitrocli.1 +++ b/nitrocli/doc/nitrocli.1 @@ -220,6 +220,25 @@ The admin PIN cannot be unblocked. This operation is equivalent to the unblock PIN option provided by \fBgpg\fR(1) (using the \fB\-\-change\-pin\fR option). +.SH ENVIRONMENT +The program honors a set of environment variables that can be used to +suppress interactive PIN entry through \fBpinentry\fR(1). The following +variables are recognized: +.TP +.B NITROCLI_ADMIN_PIN +The admin PIN to use. +.TP +.B NITROCLI_USER_PIN +The user PIN to use. +.TP +.B NITROCLI_NEW_ADMIN_PIN +The new admin PIN to set. This variable is only used by the \fBnitrocli +pin set\fR command for the \fBadmin\fR type. +.TP +.B NITROCLI_NEW_USER_PIN +The new user PIN to set. This variable is only used by the \fBnitrocli +pin set\fR command for the \fBuser\fR type. + .SH EXAMPLES .SS One-time passwords Configure a one-time password slot with a hexadecimal secret representation: diff --git a/nitrocli/doc/nitrocli.1.pdf b/nitrocli/doc/nitrocli.1.pdf index 5fa9049..3d28310 100644 Binary files a/nitrocli/doc/nitrocli.1.pdf and b/nitrocli/doc/nitrocli.1.pdf differ diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index 6316c92..f8765cc 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -610,7 +610,7 @@ fn check_pin(pin_type: pinentry::PinType, pin: &str) -> Result<()> { } } -fn choose_pin(pin_type: pinentry::PinType) -> Result { +fn choose_pin_with_pinentry(pin_type: pinentry::PinType) -> Result { pinentry::clear_pin(pin_type)?; let new_pin = pinentry::inquire_pin(pin_type, pinentry::Mode::Choose, None)?; pinentry::clear_pin(pin_type)?; @@ -626,10 +626,46 @@ fn choose_pin(pin_type: pinentry::PinType) -> Result { } } +/// Choose a PIN of the given type. +/// +/// If the user has set the respective environment variable for the +/// given PIN type, it will be used. +fn choose_pin( + ctx: &mut args::ExecCtx<'_>, + pin_type: pinentry::PinType, + new: bool, +) -> Result { + let new_pin = match pin_type { + pinentry::PinType::Admin => { + if new { + &ctx.new_admin_pin + } else { + &ctx.admin_pin + } + } + pinentry::PinType::User => { + if new { + &ctx.new_user_pin + } else { + &ctx.user_pin + } + } + }; + + if let Some(new_pin) = new_pin { + new_pin + .to_str() + .ok_or_else(|| Error::Error("Failed to read PIN: invalid Unicode data found".into())) + .map(ToOwned::to_owned) + } else { + choose_pin_with_pinentry(pin_type) + } +} + /// Change a PIN. pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pin_type: pinentry::PinType) -> Result<()> { let device = get_device(ctx)?; - let new_pin = choose_pin(pin_type)?; + let new_pin = choose_pin(ctx, pin_type, true)?; try_with_pin( ctx, pin_type, @@ -644,7 +680,7 @@ pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pin_type: pinentry::PinType) -> Resu /// Unblock and reset the user PIN. pub fn pin_unblock(ctx: &mut args::ExecCtx<'_>) -> Result<()> { let device = get_device(ctx)?; - let user_pin = choose_pin(pinentry::PinType::User)?; + let user_pin = choose_pin(ctx, pinentry::PinType::User, false)?; try_with_pin( ctx, pinentry::PinType::Admin, -- cgit v1.2.3