summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README2
-rw-r--r--man/pass.116
-rwxr-xr-xsrc/password-store.sh55
-rw-r--r--src/platform/darwin.sh12
4 files changed, 65 insertions, 20 deletions
diff --git a/README b/README
index eae3666..6b59965 100644
--- a/README
+++ b/README
@@ -26,3 +26,5 @@ Depends on:
- GNU getopt
http://www.kernel.org/pub/linux/utils/util-linux/
http://software.frodo.looijaard.name/getopt/
+- qrencode
+ https://fukuchi.org/works/qrencode/
diff --git a/man/pass.1 b/man/pass.1
index 31f987d..71bfc7e 100644
--- a/man/pass.1
+++ b/man/pass.1
@@ -90,12 +90,15 @@ List names of passwords inside the tree that match \fIpass-names\fP by using the
.BR tree (1)
program. This command is alternatively named \fBsearch\fP.
.TP
-\fBshow\fP [ \fI--clip\fP[=\fIline-number\fP], \fI-c\fP[\fIline-number\fP] ] \fIpass-name\fP
+\fBshow\fP [ \fI--clip\fP[=\fIline-number\fP], \fI-c\fP[\fIline-number\fP] ] [ \fI--qrcode\fP[=\fIline-number\fP], \fI-q\fP[\fIline-number\fP] ] \fIpass-name\fP
Decrypt and print a password named \fIpass-name\fP. If \fI--clip\fP or \fI-c\fP
is specified, do not print the password but instead copy the first (or otherwise specified)
line to the clipboard using
.BR xclip (1)
-and then restore the clipboard after 45 (or \fIPASSWORD_STORE_CLIP_TIME\fP) seconds.
+and then restore the clipboard after 45 (or \fIPASSWORD_STORE_CLIP_TIME\fP) seconds. If \fI--qrcode\fP
+or \fI-q\fP is specified, do not print the password but instead display a QR code using
+.BR qrencode (1)
+either to the terminal or graphically if supported.
.TP
\fBinsert\fP [ \fI--echo\fP, \fI-e\fP | \fI--multiline\fP, \fI-m\fP ] [ \fI--force\fP, \fI-f\fP ] \fIpass-name\fP
Insert a new password into the password store called \fIpass-name\fP. This will
@@ -125,8 +128,10 @@ in generating passwords can be changed with the \fIPASSWORD_STORE_CHARACTER_SET\
If \fI--clip\fP or \fI-c\fP is specified, do not print the password but instead copy
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,
+and then restore the clipboard after 45 (or \fIPASSWORD_STORE_CLIP_TIME\fP) seconds. If \fI--qrcode\fP
+or \fI-q\fP is specified, do not print the password but instead display a QR code using
+.BR qrencode (1)
+either to the terminal or graphically if supported. Prompt before overwriting an existing password,
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.
@@ -461,7 +466,8 @@ The location of the text editor used by \fBedit\fP.
.BR gpg2 (1),
.BR tr (1),
.BR git (1),
-.BR xclip (1).
+.BR xclip (1),
+.BR qrencode (1).
.SH AUTHOR
.B pass
diff --git a/src/password-store.sh b/src/password-store.sh
index a5a8002..081057a 100755
--- a/src/password-store.sh
+++ b/src/password-store.sh
@@ -170,6 +170,23 @@ clip() {
) 2>/dev/null & disown
echo "Copied $2 to clipboard. Will clear in $CLIP_TIME seconds."
}
+
+qrcode() {
+ if [[ -n $DISPLAY || -n $WAYLAND_DISPLAY ]]; then
+ if type feh >/dev/null 2>&1; then
+ echo -n "$1" | qrencode --size 10 -o - | feh -x --title "pass: $2" -g +200+200 -
+ return
+ elif type gm >/dev/null 2>&1; then
+ echo -n "$1" | qrencode --size 10 -o - | gm display -title "pass: $2" -geometry +200+200 -
+ return
+ elif type display >/dev/null 2>&1; then
+ echo -n "$1" | qrencode --size 10 -o - | display -title "pass: $2" -geometry +200+200 -
+ return
+ fi
+ fi
+ echo -n "$1" | qrencode -t utf8
+}
+
tmpdir() {
[[ -n $SECURE_TMPDIR ]] && return
local warn=1
@@ -321,28 +338,33 @@ cmd_init() {
}
cmd_show() {
- local opts clip_location clip=0
- opts="$($GETOPT -o c:: -l clip:: -n "$PROGRAM" -- "$@")"
+ local opts selected_line clip=0 qrcode=0
+ opts="$($GETOPT -o q::c:: -l qrcode::,clip:: -n "$PROGRAM" -- "$@")"
local err=$?
eval set -- "$opts"
while true; do case $1 in
- -c|--clip) clip=1; clip_location="${2:-1}"; shift 2 ;;
+ -q|--qrcode) qrcode=1; selected_line="${2:-1}"; shift 2 ;;
+ -c|--clip) clip=1; selected_line="${2:-1}"; shift 2 ;;
--) shift; break ;;
esac done
- [[ $err -ne 0 ]] && die "Usage: $PROGRAM $COMMAND [--clip[=line-number],-c[line-number]] [pass-name]"
+ [[ $err -ne 0 || ( $qrcode -eq 1 && $clip -eq 1 ) ]] && die "Usage: $PROGRAM $COMMAND [--clip[=line-number],-c[line-number]] [--qrcode[=line-number],-q[line-number]] [pass-name]"
local path="$1"
local passfile="$PREFIX/$path.gpg"
check_sneaky_paths "$path"
if [[ -f $passfile ]]; then
- if [[ $clip -eq 0 ]]; then
+ if [[ $clip -eq 0 && $qrcode -eq 0 ]]; then
$GPG -d "${GPG_OPTS[@]}" "$passfile" || exit $?
else
- [[ $clip_location =~ ^[0-9]+$ ]] || die "Clip location '$clip_location' is not a number."
- local pass="$($GPG -d "${GPG_OPTS[@]}" "$passfile" | tail -n +${clip_location} | head -n 1)"
- [[ -n $pass ]] || die "There is no password to put on the clipboard at line ${clip_location}."
- clip "$pass" "$path"
+ [[ $selected_line =~ ^[0-9]+$ ]] || die "Clip location '$selected_line' is not a number."
+ local pass="$($GPG -d "${GPG_OPTS[@]}" "$passfile" | tail -n +${selected_line} | head -n 1)"
+ [[ -n $pass ]] || die "There is no password to put on the clipboard at line ${selected_line}."
+ if [[ $clip -eq 1 ]]; then
+ clip "$pass" "$path"
+ elif [[ $qrcode -eq 1 ]]; then
+ qrcode "$pass" "$path"
+ fi
fi
elif [[ -d $PREFIX/$path ]]; then
if [[ -z $path ]]; then
@@ -457,19 +479,20 @@ cmd_edit() {
}
cmd_generate() {
- local opts clip=0 force=0 characters="$CHARACTER_SET" inplace=0 pass
- opts="$($GETOPT -o ncif -l no-symbols,clip,in-place,force -n "$PROGRAM" -- "$@")"
+ local opts qrcode=0 clip=0 force=0 characters="$CHARACTER_SET" inplace=0 pass
+ opts="$($GETOPT -o nqcif -l no-symbols,qrcode,clip,in-place,force -n "$PROGRAM" -- "$@")"
local err=$?
eval set -- "$opts"
while true; do case $1 in
-n|--no-symbols) characters="$CHARACTER_SET_NO_SYMBOLS"; shift ;;
+ -q|--qrcode) qrcode=1; 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 && $# -ne 1 ) || ( $force -eq 1 && $inplace -eq 1 ) ]] && die "Usage: $PROGRAM $COMMAND [--no-symbols,-n] [--clip,-c] [--in-place,-i | --force,-f] pass-name [pass-length]"
+ [[ $err -ne 0 || ( $# -ne 2 && $# -ne 1 ) || ( $force -eq 1 && $inplace -eq 1 ) || ( $qrcode -eq 1 && $clip -eq 1 ) ]] && die "Usage: $PROGRAM $COMMAND [--no-symbols,-n] [--clip,-c] [--qrcode,-q] [--in-place,-i | --force,-f] pass-name [pass-length]"
local path="$1"
local length="${2:-$GENERATED_LENGTH}"
check_sneaky_paths "$path"
@@ -497,10 +520,12 @@ cmd_generate() {
[[ $inplace -eq 1 ]] && verb="Replace"
git_add_file "$passfile" "$verb generated password for ${path}."
- if [[ $clip -eq 0 ]]; then
- printf "\e[1m\e[37mThe generated password for \e[4m%s\e[24m is:\e[0m\n\e[1m\e[93m%s\e[0m\n" "$path" "$pass"
- else
+ if [[ $clip -eq 1 ]]; then
clip "$pass" "$path"
+ elif [[ $qrcode -eq 1 ]]; then
+ qrcode "$pass" "$path"
+ else
+ printf "\e[1m\e[37mThe generated password for \e[4m%s\e[24m is:\e[0m\n\e[1m\e[93m%s\e[0m\n" "$path" "$pass"
fi
}
diff --git a/src/platform/darwin.sh b/src/platform/darwin.sh
index 7b028f3..86eb325 100644
--- a/src/platform/darwin.sh
+++ b/src/platform/darwin.sh
@@ -31,5 +31,17 @@ tmpdir() {
mount -t hfs -o noatime -o nobrowse "$DARWIN_RAMDISK_DEV" "$SECURE_TMPDIR" || die "Error: could not mount filesystem on ramdisk."
}
+qrcode() {
+ if type imgcat >/dev/null 2>&1; then
+ echo -n "$1" | qrencode --size 10 -o - | imgcat
+ elif type gm >/dev/null 2>&1; then
+ echo -n "$1" | qrencode --size 10 -o - | gm display -title "pass: $2" -geometry +200+200 -
+ elif type display >/dev/null 2>&1; then
+ echo -n "$1" | qrencode --size 10 -o - | display -title "pass: $2" -geometry +200+200 -
+ else
+ echo -n "$1" | qrencode -t utf8
+ fi
+}
+
GETOPT="$(brew --prefix gnu-getopt 2>/dev/null || { which port &>/dev/null && echo /opt/local; } || echo /usr/local)/bin/getopt"
SHRED="srm -f -z"