summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCian Bagshaw <cian@cianb.xyz>2023-10-06 01:43:07 +0100
committerCian Bagshaw <cian@cianb.xyz>2023-10-06 01:43:07 +0100
commita0f5171c15be52412be9e30a0011bbbf82f32b6b (patch)
treed685a30234cb5cd9169d5e0d1ea031d91b7f7f3f
downloadspass-master.tar.bz2
spass-master.zip
Initial commitHEADmaster
Moved from dotFiles repo
-rw-r--r--spass81
1 files changed, 81 insertions, 0 deletions
diff --git a/spass b/spass
new file mode 100644
index 0000000..c577461
--- /dev/null
+++ b/spass
@@ -0,0 +1,81 @@
1#!/bin/sh
2# spass - simple, secure password storage and retrieval
3
4[ -z "$XDG_DATA_HOME" ] && XDG_DATA_HOME="$HOME/.local/share"
5[ -z "$PASSDIR" ] && PASSDIR="$XDG_DATA_HOME/pass"
6
7all() { basename -s ".gpg" -a "$PASSDIR"/*.gpg; }
8error() { echo "$(basename "$0"): error: $1" 1>&2; stty echo; exit; }
9format() { sed -n '/[^\S\r\n]/ { 1s/^/password: /; 2s/^/username: /; 3s/^/totp: /; 4s/^/notes: /; p }'; }
10
11if [ "$1" = "init" ]; then
12 if [ -z "$2" ]
13 then error "gpg key not specified"
14 elif gpg -K "$2" >/dev/null 2>&1
15 then mkdir -p "$PASSDIR"; echo "$2" > "$PASSDIR/.gpg-id"
16 else error "gpg key doesn't exist"
17 fi; exit
18elif [ -f "$PASSDIR/.gpg-id" ]
19 then GPG_ID="$(cat "$PASSDIR/.gpg-id")"
20 else error "password store not initialised!"
21fi;
22
23show() {
24 [ ! -f "$PASSDIR/$1.gpg" ] && error "no such entry: $1"
25 gpg -dq "$PASSDIR/$1.gpg" | case "$2" in
26 all) format;;
27 notes) sed -n 4p;;
28 totp) sed -n 3p | oathtool --base32 --totp -;;
29 name) sed -n 2p;;
30 *) sed -n 1p;;
31 esac
32}
33
34dump() {
35 for f in $(all)
36 do printf "# %s\n%s\n\n" "$f" "$(show "$f" all)"
37 done | head -n -1;
38}
39
40add() {
41 [ -z "$1" ] && error "entry name not specified"
42 printf "username: "; read -r u
43 stty -echo
44 printf "password: "; read -r p1; printf "\npassword (again): "; read -r p2
45 printf "\ntotp: "; read -r t1; printf "\ntotp (again): "; read -r t2
46 stty echo
47 printf "\nnotes: "; read -r n
48 [ "$p1" != "$p2" ] && error "passwords don't match"
49 [ "$t1" != "$t2" ] && error "totps don't match"
50 printf "%s\n%s\n%s\n%s" "$p1" "$u" "$t1" "$n" | gpg -eqr "$GPG_ID" -o "$PASSDIR/$1.gpg"
51}
52
53move() {
54 [ $# -lt 2 ] && error "source and destination not specified"
55 mv "$PASSDIR/$1.gpg" "$PASSDIR/$2.gpg"
56}
57
58remove () {
59 [ ! -f "$PASSDIR/$1.gpg" ] && error "entry does not exist: $1"
60 printf "are you sure you want to remove %s? [y/N] " $1; read -r c
61 [ "$c" = "y" ] || [ "$c" = "Y" ] && rm "$PASSDIR/$1.gpg"
62}
63
64sel() {
65 [ -z "$1" ] && error "no menu program specified"
66 ENTRY="$(all | $@)"; [ -z "$ENTRY" ] && exit
67 INFO="$(printf "pass\nname\ntotp\nnotes" | "$@")"; [ -z "$INFO" ] && exit
68 for p in $(pgrep "$(basename "$0")" | head -n -2); do kill "$p"; done
69 show "$ENTRY" "$INFO" | tr -d "\n" | xclip -selection clipboard
70 notify-send "$(basename "$0")" "$INFO copied to clipboard\nclearing in 10s"
71 sleep 10; xclip -selection clipboard < /dev/null
72}
73
74case "$1" in
75 mv) shift; move "$@";;
76 rm) shift; remove "$@";;
77 sel) shift; sel "$@";;
78 add ) add "$2";;
79 dump) dump;;
80 *) if [ -z "$1" ]; then all; else show "$@"; fi;;
81esac