From acfab191e6bb33f840f0a7106c3eb4cd1ab76267 Mon Sep 17 00:00:00 2001 From: Tad Fisher Date: Sun, 19 Mar 2017 23:09:24 -0700 Subject: Support --echo and reading key from stdin --- otp.bash | 50 +++++++++++++++++++++++++++++++++++++------------- pass-otp.1 | 14 ++++++++------ test/insert.t | 24 ++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/otp.bash b/otp.bash index 664a37b..8b80554 100755 --- a/otp.bash +++ b/otp.bash @@ -88,9 +88,10 @@ Usage: $PROGRAM otp [show] [--clip,-c] pass-name Generate an OTP code and optionally put it on the clipboard. If put on the clipboard, it will be cleared in $CLIP_TIME seconds. - $PROGRAM otp insert [--force,-f] uri pass-name - Insert new OTP key URI. Prompt before overwriting existing password - unless forced. + $PROGRAM otp insert [--force,-f] [--echo,-e] [uri] pass-name + Insert a new OTP key URI. If one is not supplied, it will be read from + stdin. Optionally, echo the input. Prompt before overwriting existing + password unless forced. $PROGRAM otp uri [--clip,-c] [--qrcode,-q] pass-name Display the key URI stored in pass-name. Optionally, put it on the clipboard, or display a QR code. @@ -103,22 +104,45 @@ _EOF } cmd_otp_insert() { - local opts force=0 - opts="$($GETOPT -o f -l force -n "$PROGRAM" -- "$@")" + local opts force=0 echo=0 + opts="$($GETOPT -o fe -l force,echo -n "$PROGRAM" -- "$@")" local err=$? eval set -- "$opts" while true; do case $1 in - -f|--force) force=1; shift ;; - --) shift; break ;; - esac done - - [[ $err -ne 0 || $# -ne 2 ]] && die "Usage: $PROGRAM $COMMAND insert [--force,-f] uri pass-name" + -f|--force) force=1; shift ;; + -e|--echo) echo=1; shift ;; + --) shift; break ;; + esac done - local uri="$1" + [[ $err -ne 0 || ($# -ne 1 && $# -ne 2) ]] && die "Usage: $PROGRAM $COMMAND insert [--force,-f] [uri] pass-name" + + local path uri + if [[ $# -eq 1 ]]; then + path="$1" + if [[ -t 0 ]]; then + if [[ $echo -eq 0 ]]; then + while true; do + read -r -p "Enter otpauth:// URI for $path: " -s uri || exit 1 + echo + read -r -p "Retype otpauth:// URI for $path: " -s uri_again || exit 1 + echo + [[ "$uri" == "$uri_again" ]] && break + die "Error: the entered URIs do not match." + done + else + read -r -p "Enter otpauth:// URI for $path: " -e uri + fi + else + read -r uri + fi + else + uri="$1" + path="$2" + fi otp_parse_uri "$uri" - otp_insert "$2" $force "$otp_uri" "Add OTP secret for $2 to store." + otp_insert "$path" $force "$otp_uri" "Add OTP secret for $2 to store." } cmd_otp_code() { @@ -217,7 +241,7 @@ cmd_otp_uri() { } cmd_otp_validate() { - otp_parse_uri "$1" + otp_parse_uri "$1" } case "$1" in diff --git a/pass-otp.1 b/pass-otp.1 index ca298dc..69ff10d 100644 --- a/pass-otp.1 +++ b/pass-otp.1 @@ -1,4 +1,4 @@ -.TH PASS-OTP 1 "2017 February 14" "Password store OTP extension" +.TH PASS-OTP 1 "2017 March 19" "Password store OTP extension" .SH NAME pass-otp - A \fBpass\fP(1) extension for managing one-time-password (OTP) tokens. @@ -30,21 +30,23 @@ If no COMMAND is specified, COMMAND defaults to \fBcode\fP. .TP \fBotp code\fP [ \fI--clip\fP, \fI-c\fP ] \fIpass-name\fP -Generate and print an OTP code from the secret key stored in \fIpass-name\fP. If -\fI--clip\fP or \fI-c\fP is specified, do not print the code but instead copy it to the clipboard using -.BR xclip (1) +Generate and print an OTP code from the secret key stored in \fIpass-name\fP +using \fBoathtool\fP(1). If \fI--clip\fP or \fI-c\fP is specified, do not print +the code but instead copy it to the clipboard using \fBxclip\fP(1) and then restore the clipboard after 45 (or \fIPASSWORD_STORE_CLIP_TIME\fP) seconds. This command is alternatively named \fBshow\fP. .TP -\fBotp insert\fP [ \fI--force\fP, \fI-f\fP ] \fIuri\fP \fIpass-name\fP +\fBotp insert\fP [ \fI--force\fP, \fI-f\fP ] [ \fI--echo\fP, \fI-e\fP ] [ \fIuri\fP ] \fIpass-name\fP Insert a new OTP secret specified by \fIuri\fP into the password store at \fIpass-name\fP. \fIuri\fP must be formatted according to the Key Uri Format; see the documentation at .UR https://\:github.\:com/\:google/\:google-authenticator/\:wiki/\:Key-Uri-Format .UE . -Prompt before overwriting an existing password, unless +If \fIuri\fP is not specified, it will be consumed from stdin; specify +\fI--echo\fP or \fI-e\fP to show a visible prompt when running this command +interactively. Prompt before overwriting an existing password, unless \fI--force\fP or \fI-f\fP is specified. This command is alternatively named \fBadd\fP. diff --git a/test/insert.t b/test/insert.t index da6477c..0c19d11 100755 --- a/test/insert.t +++ b/test/insert.t @@ -32,4 +32,28 @@ test_expect_success 'Force overwrites key URI' ' [[ $("$PASS" show passfile) == "$uri2" ]] ' +test_expect_success 'Reads non-terminal input' ' + uri="otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example" + + test_pass_init && + "$PASS" otp insert passfile <<< "$uri" && + [[ $("$PASS" show passfile) == "$uri" ]] +' + +test_expect_success 'Reads terminal input in noecho mode' ' + uri="otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example" + + test_pass_init && + test_faketty "$PASS" otp insert passfile < <(echo -ne "$uri\n$uri\n") && + [[ $("$PASS" show passfile) == "$uri" ]] +' + +test_expect_success 'Reads terminal input in echo mode' ' + uri="otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example" + + test_pass_init && + test_faketty "$PASS" otp insert -e passfile <<< "$uri" && + [[ $("$PASS" show passfile) == "$uri" ]] +' + test_done -- cgit v1.2.3