diff options
| -rw-r--r-- | man/pass.1 | 6 | ||||
| -rwxr-xr-x | src/password-store.sh | 28 | ||||
| -rwxr-xr-x | tests/pwgen | 2 | ||||
| -rwxr-xr-x | tests/t0010-generate-tests.sh | 6 | 
4 files changed, 33 insertions, 9 deletions
| @@ -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 |