From 276fb973ab8517f3ec888b4ee2114d982131293c Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 6 May 2014 17:23:50 +0200 Subject: generate: add --in-place option --- man/pass.1 | 6 ++++-- src/password-store.sh | 28 +++++++++++++++++++++------- tests/pwgen | 2 ++ tests/t0010-generate-tests.sh | 6 ++++++ 4 files changed, 33 insertions(+), 9 deletions(-) create mode 100755 tests/pwgen diff --git a/man/pass.1 b/man/pass.1 index 35c81ee..a433a72 100644 --- a/man/pass.1 +++ b/man/pass.1 @@ -110,7 +110,7 @@ ensure that temporary files are created in \fI/dev/shm\fP in order to avoid writ difficult-to-erase disk sectors. If \fI/dev/shm\fP is not accessible, fallback to the ordinary \fITMPDIR\fP location, and print a warning. .TP -\fBgenerate\fP [ \fI--no-symbols\fP, \fI-n\fP ] [ \fI--clip\fP, \fI-c\fP ] [ \fI--force\fP, \fI-f\fP ] \fIpass-name pass-length\fP +\fBgenerate\fP [ \fI--no-symbols\fP, \fI-n\fP ] [ \fI--clip\fP, \fI-c\fP ] [ \fI--in-place\fP, \fI-i\fP ] [ \fI--force\fP, \fI-f\fP ] \fIpass-name pass-length\fP Generate a new password using .BR pwgen (1) of length \fIpass-length\fP and insert into \fIpass-name\fP. If \fI--no-symbols\fP or \fI-n\fP @@ -120,7 +120,9 @@ it to the clipboard using .BR xclip (1) and then restore the clipboard after 45 (or \fIPASSWORD_STORE_CLIP_TIME\fP) seconds. Prompt before overwriting an existing password, -unless \fI--force\fP or \fI-f\fP is specified. +unless \fI--force\fP or \fI-f\fP is specified. If \fI--in-place\fP or \fI-i\fP is +specified, do not interactively prompt, and only replace the first line of the password +file with the new generated password, keeping the remainder of the file intact. .TP \fBrm\fP [ \fI--recursive\fP, \fI-r\fP ] [ \fI--force\fP, \fI-f\fP ] \fIpass-name\fP Remove the password named \fIpass-name\fP from the password store. This command is diff --git a/src/password-store.sh b/src/password-store.sh index 8e80798..8e1a124 100755 --- a/src/password-store.sh +++ b/src/password-store.sh @@ -230,10 +230,11 @@ cmd_usage() { overwriting existing password unless forced. $PROGRAM edit pass-name Insert a new password or edit an existing password using ${EDITOR:-vi}. - $PROGRAM generate [--no-symbols,-n] [--clip,-c] [--force,-f] pass-name pass-length + $PROGRAM generate [--no-symbols,-n] [--clip,-c] [--in-place,-i] [--force,-f] pass-name pass-length Generate a new password of pass-length with optionally no symbols. Optionally put it on the clipboard and clear board after 45 seconds. Prompt before overwriting existing password unless forced. + Optionally replace only the first line of an existing file with a new password. $PROGRAM rm [--recursive,-r] [--force,-f] pass-name Remove existing password or directory, optionally forcefully. $PROGRAM mv [--force,-f] old-path new-path @@ -430,18 +431,19 @@ cmd_edit() { } cmd_generate() { - local opts clip=0 force=0 symbols="-y" - opts="$($GETOPT -o ncf -l no-symbols,clip,force -n "$PROGRAM" -- "$@")" + local opts clip=0 force=0 symbols="-y" inplace=0 + opts="$($GETOPT -o ncif -l no-symbols,clip,in-place,force -n "$PROGRAM" -- "$@")" local err=$? eval set -- "$opts" while true; do case $1 in -n|--no-symbols) symbols=""; shift ;; -c|--clip) clip=1; shift ;; -f|--force) force=1; shift ;; + -i|--in-place) inplace=1; shift ;; --) shift; break ;; esac done - [[ $err -ne 0 || $# -ne 2 ]] && die "Usage: $PROGRAM $COMMAND [--no-symbols,-n] [--clip,-c] [--force,-f] pass-name pass-length" + [[ $err -ne 0 || $# -ne 2 ]] && die "Usage: $PROGRAM $COMMAND [--no-symbols,-n] [--clip,-c] [--in-place,-i] [--force,-f] pass-name pass-length" local path="$1" local length="$2" check_sneaky_paths "$path" @@ -450,12 +452,24 @@ cmd_generate() { set_gpg_recipients "$(dirname "$path")" local passfile="$PREFIX/$path.gpg" - [[ $force -eq 0 && -e $passfile ]] && yesno "An entry already exists for $path. Overwrite it?" + [[ $inplace -eq 0 && $force -eq 0 && -e $passfile ]] && yesno "An entry already exists for $path. Overwrite it?" local pass="$(pwgen -s $symbols $length 1)" [[ -n $pass ]] || exit 1 - $GPG -e "${GPG_RECIPIENT_ARGS[@]}" -o "$passfile" "${GPG_OPTS[@]}" <<<"$pass" - git_add_file "$passfile" "Add generated password for $path to store." + if [[ $inplace -eq 0 ]]; then + $GPG -e "${GPG_RECIPIENT_ARGS[@]}" -o "$passfile" "${GPG_OPTS[@]}" <<<"$pass" + else + local passfile_temp="${passfile}.tmp.${RANDOM}.${RANDOM}.${RANDOM}.${RANDOM}.--" + if $GPG -d "${GPG_OPTS[@]}" "$passfile" | sed $'1c \\\n'"$(sed 's/[\/&]/\\&/g' <<<"$pass")"$'\n' | $GPG -e "${GPG_RECIPIENT_ARGS[@]}" -o "$passfile_temp" "${GPG_OPTS[@]}"; then + mv "$passfile_temp" "$passfile" + else + rm -f "$passfile_temp" + die "Could not reencrypt new password." + fi + fi + local verb="Add" + [[ $inplace -eq 1 ]] && verb="Replace" + git_add_file "$passfile" "$verb generated password for ${path}." if [[ $clip -eq 0 ]]; then echo "The generated password to $path is:" diff --git a/tests/pwgen b/tests/pwgen new file mode 100755 index 0000000..c83eec9 --- /dev/null +++ b/tests/pwgen @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +echo "${FAKE_PWGEN_PASSWORD:-Hello World}" diff --git a/tests/t0010-generate-tests.sh b/tests/t0010-generate-tests.sh index da5e41f..cadb76f 100755 --- a/tests/t0010-generate-tests.sh +++ b/tests/t0010-generate-tests.sh @@ -10,4 +10,10 @@ test_expect_success 'Test "generate" command' ' [[ $("$PASS" show cred | wc -m) -eq 20 ]] ' +test_expect_success 'Test replacement of first line' ' + "$PASS" insert -m cred2 <<<"$(printf "this is a big\\npassword\\nwith\\nmany\\nlines\\nin it bla bla")" && + PATH="$TEST_HOME:$PATH" FAKE_PWGEN_PASSWORD="This is a fake password" "$PASS" generate -i cred2 88 && + [[ $("$PASS" show cred2) == "$(printf "This is a fake password\\npassword\\nwith\\nmany\\nlines\\nin it bla bla")" ]] +' + test_done -- cgit v1.2.3