On macOS the way for password managers to temporarily put sensitive data
on the clipboard is by tagging the data.
Therefore a pre/post hook will not be a good solution for macOS, instead
it should be a callback that places the content on the clipboard.
A simple interface would be a function that accepts $password and
$duration, the default implementation on macOS (using `pbcopy` and
`pbpaste`) would be something like this:
function user_function {
password="$1"
duration="$2"
old="$(pbpaste)"
printf "%s" "$password" | pbcopy
sleep "$duration"
if [[ "$(pbpaste)" == "$password" ]]; then
printf "%s" "$old" | pbcopy
fi
}
The advantage of using pre/post hooks is that it does not become the job
of the callback to sleep nor check if content has changed.
However, for the latter, a callback might do better than `pass` itself,
for example on macOS the clipboard has a change counter, so the callback
can check that to learn about changes.
Furthermore for the `sleep`: Having the callback perform the sleep, we
avoid having to introduce state that is shared between the pre and post
hook, if we also want to improve restoring content (e.g. on macOS `pass`
will currently not restore non-text content or text with multiple
representations).
So all in all, I think the interface should be a single function that
does all the work, instead of introducing hooks, as I don’t think the
complexity of implementing a callback is higher than writing hooks, and
a function is much less limited, e.g. on macOS we will be able both to
tag the content (for clipboard managers) and we will be able to do a
better job at restoring the old clipboard data, neither of which is
possible with the hooks.
For the records though, in order to improve things on macOS, we will
need to write a compiled helper and use that instead of
`pbcopy`/`pbpaste`.
On 5 Jul 2020, at 8:20, Dov Feldstern wrote:
# HG changeset patch
# User Dov Feldstern <[email protected]>
# Date 1593908715 -10800
# Sun Jul 05 03:25:15 2020 +0300
# Node ID d4af3f470f3f04fb81bbcb079556ea56e8e43898
# Parent dcfa9a1c9c827206f899e7ba604f42366fbd60f3
RFC: hooks for clipboard manager integration
I've been using password-store for a few months now, and am very happy
with it
-- thanks to all involved!
One thing that I'm still grappling with is how to avoid having the
passwords
get stored by my clipboard manager (currently copyq). I see that
discussions of
this come up in the mailing list every once in a while, for various
clipboard
managers; and also from the clipboard manager side, I see that many
clipboard
managers discuss how to deal with the issue of passwords. But there
doesn't
seem to be any standard way, which obviously makes dealing with this
in a
generic way a bit difficult...
In this patch, I propose to add hooks, which can then be implemented
as
appropriate for the various clipboard managers. I moved the handling
for
klipper into the "default" hook, and in contrib/ I added a reference
implementation for how I'd like passwords to be handled for copyq --
so this
demonstrates that the method works for at least two password managers
;) .
I am offering this here as an RFC: is this kind of approach acceptable
to the
project? If so, probably the hooking mechanism should be designed a
bit more
throughly than what I've done here (I am also not very proficient in
bash
programming, so there's probably a nicer way to add hooks than what
I've
done...). But once such a hooking mechanism is in place, I think it
offers a
more scalable solution for dealing with the variety of clipboard
managers, and
will probably also find a bunch of other use cases, as well...
I'd be glad to hear any thoughts on this...
Thanks!
Dov
diff -r dcfa9a1c9c82 -r d4af3f470f3f contrib/hooks/copyq.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/hooks/copyq.sh Sun Jul 05 03:25:15 2020 +0300
@@ -0,0 +1,11 @@
+hook_clip_pre_copy_pw() {
+ copyq disable
+}
+
+hook_clip_post_copy_pw() {
+ copyq enable
+}
+
+hook_clip_pre_restore() {
+ return
+}
diff -r dcfa9a1c9c82 -r d4af3f470f3f src/password-store.sh
--- a/src/password-store.sh Thu Jun 25 23:41:11 2020 +0200
+++ b/src/password-store.sh Sun Jul 05 03:25:15 2020 +0300
@@ -14,6 +14,7 @@
PREFIX="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
EXTENSIONS="${PASSWORD_STORE_EXTENSIONS_DIR:-$PREFIX/.extensions}"
+HOOKS="${PASSWORD_STORE_HOOKS_DIR:-$PREFIX/.hooks}"
X_SELECTION="${PASSWORD_STORE_X_SELECTION:-clipboard}"
CLIP_TIME="${PASSWORD_STORE_CLIP_TIME:-45}"
GENERATED_LENGTH="${PASSWORD_STORE_GENERATED_LENGTH:-25}"
@@ -152,6 +153,25 @@
# BEGIN platform definable
#
+hook_clip_pre_copy_pw() {
+ return
+}
+
+hook_clip_post_copy_pw() {
+ return
+}
+
+hook_clip_pre_restore() {
+ # It might be nice to programatically check to see if klipper
exists,
+ # as well as checking for other common clipboard managers. But for
now,
+ # this works fine -- if qdbus isn't there or if klipper isn't
running,
+ # this essentially becomes a no-op.
+ #
+ # Clipboard managers frequently write their history out in
plaintext,
+ # so we axe it here:
+ qdbus org.kde.klipper /klipper
org.kde.klipper.klipper.clearClipboardHistory &>/dev/null
+}
+
clip() {
if [[ -n $WAYLAND_DISPLAY ]]; then
local copy_cmd=( wl-copy )
@@ -175,21 +195,15 @@
# trailing new lines.
pkill -f "^$sleep_argv0" 2>/dev/null && sleep 0.5
local before="$("${paste_cmd[@]}" 2>/dev/null | $BASE64)"
+ hook_clip_pre_copy_pw
echo -n "$1" | "${copy_cmd[@]}" || die "Error: Could not copy data
to the clipboard"
+ hook_clip_post_copy_pw
(
( exec -a "$sleep_argv0" bash <<<"trap 'kill %1' TERM; sleep
'$CLIP_TIME' & wait" )
local now="$("${paste_cmd[@]}" | $BASE64)"
[[ $now != $(echo -n "$1" | $BASE64) ]] && before="$now"
- # It might be nice to programatically check to see if klipper
exists,
- # as well as checking for other common clipboard managers. But for
now,
- # this works fine -- if qdbus isn't there or if klipper isn't
running,
- # this essentially becomes a no-op.
- #
- # Clipboard managers frequently write their history out in
plaintext,
- # so we axe it here:
- qdbus org.kde.klipper /klipper
org.kde.klipper.klipper.clearClipboardHistory &>/dev/null
-
+ hook_clip_pre_restore
echo "$before" | $BASE64 -d | "${copy_cmd[@]}"
) >/dev/null 2>&1 & disown
echo "Copied $2 to clipboard. Will clear in $CLIP_TIME seconds."
@@ -246,6 +260,10 @@
source "$(dirname "$0")/platform/$(uname | cut -d _ -f 1 | tr
'[:upper:]' '[:lower:]').sh" 2>/dev/null # PLATFORM_FUNCTION_FILE
+for hook in $HOOKS/*.sh; do
+ source $hook
+done
+
#
# END platform definable
#