Blame


1 b93a49bc 2015-03-13 soeren+gi #!/bin/sh
2 f522506c 2016-08-16 soeren+gi # Copyright (C) 2013-2016 Sören Tempel
3 080fbd05 2017-07-02 xhr # Copyright (C) 2017 Matthias Schmidt
4 666022b7 2015-01-02 soeren+gi #
5 666022b7 2015-01-02 soeren+gi # This program is free software: you can redistribute it and/or modify
6 666022b7 2015-01-02 soeren+gi # it under the terms of the GNU General Public License as published by
7 666022b7 2015-01-02 soeren+gi # the Free Software Foundation, either version 3 of the License, or
8 666022b7 2015-01-02 soeren+gi # (at your option) any later version.
9 666022b7 2015-01-02 soeren+gi #
10 666022b7 2015-01-02 soeren+gi # This program is distributed in the hope that it will be useful,
11 666022b7 2015-01-02 soeren+gi # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 666022b7 2015-01-02 soeren+gi # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 666022b7 2015-01-02 soeren+gi # GNU General Public License for more details.
14 666022b7 2015-01-02 soeren+gi #
15 666022b7 2015-01-02 soeren+gi # You should have received a copy of the GNU General Public License
16 666022b7 2015-01-02 soeren+gi # along with this program. If not, see <http://www.gnu.org/licenses/>.
17 98cc485f 2013-11-14 git-nmeum
18 b2af058c 2017-07-04 xhr set -eu
19 b2af058c 2017-07-04 xhr
20 99d77107 2013-11-15 git-nmeum umask 077
21 99d77107 2013-11-15 git-nmeum
22 98cc485f 2013-11-14 git-nmeum ##
23 9f54b1bb 2017-07-04 xhr # Variables r/w
24 98cc485f 2013-11-14 git-nmeum ##
25 98cc485f 2013-11-14 git-nmeum
26 080fbd05 2017-07-02 xhr GPG_OPTS="--quiet --yes"
27 89fd4ad2 2017-07-04 xhr GPGB="gpg2"
28 ad8e14c1 2017-07-04 xhr TMPDIR="/tmp"
29 fea25380 2017-07-03 xhr NUKE="rm"
30 b2af058c 2017-07-04 xhr PASSWORD_STORE_KEY=${PASSWORD_STORE_KEY:-""}
31 1dcc939a 2017-07-04 xhr EDITOR=${EDITOR:-""}
32 a17f5db3 2020-10-05 noreply TOPTS="-C"
33 98cc485f 2013-11-14 git-nmeum
34 9f54b1bb 2017-07-04 xhr ##
35 9f54b1bb 2017-07-04 xhr # Variables r/o
36 9f54b1bb 2017-07-04 xhr ##
37 7b62edde 2014-11-30 git+mail
38 9f54b1bb 2017-07-04 xhr readonly STORE_DIR="${HOME}/.password-store"
39 bd3332af 2017-07-04 xhr readonly PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
40 1dcc939a 2017-07-04 xhr
41 98cc485f 2013-11-14 git-nmeum ##
42 98cc485f 2013-11-14 git-nmeum # Helper
43 98cc485f 2013-11-14 git-nmeum ##
44 98cc485f 2013-11-14 git-nmeum
45 9f54b1bb 2017-07-04 xhr if [ -r "${STORE_DIR}/.gpg-id" ] && [ -z "${PASSWORD_STORE_KEY}" ]; then
46 9f54b1bb 2017-07-04 xhr read -r PASSWORD_STORE_KEY < "${STORE_DIR}/.gpg-id"
47 9f54b1bb 2017-07-04 xhr fi
48 9f54b1bb 2017-07-04 xhr
49 c1cdc08b 2017-07-03 xhr usage() {
50 c1cdc08b 2017-07-03 xhr echo "Usage: $(basename $0) [option] [argument]"
51 c1cdc08b 2017-07-03 xhr echo
52 c1cdc08b 2017-07-03 xhr echo "Option can be one of the following"
53 c1cdc08b 2017-07-03 xhr echo
54 c1cdc08b 2017-07-03 xhr echo " show <entry> Shows password <entry>"
55 a17f5db3 2020-10-05 noreply echo " insert <entry> Inserts new <entry>"
56 c1cdc08b 2017-07-03 xhr echo " find <entry> Searches for <entry>"
57 c1cdc08b 2017-07-03 xhr echo " rm <entry> Removes <entry>"
58 c1cdc08b 2017-07-03 xhr echo
59 c1cdc08b 2017-07-03 xhr echo "If you do not specify an option, all entries will be shown"
60 c1cdc08b 2017-07-03 xhr exit 0
61 c1cdc08b 2017-07-03 xhr }
62 c1cdc08b 2017-07-03 xhr
63 98cc485f 2013-11-14 git-nmeum abort() {
64 c1fcb205 2017-07-03 xhr echo "$(basename ${0}): ${1}" 1>&2
65 c1fcb205 2017-07-03 xhr exit 1
66 98cc485f 2013-11-14 git-nmeum }
67 98cc485f 2013-11-14 git-nmeum
68 080fbd05 2017-07-02 xhr mygpg() {
69 fec3955f 2017-07-03 xhr
70 89fd4ad2 2017-07-04 xhr if [ -z "$(which gpg2 2> /dev/null)" ]; then
71 89fd4ad2 2017-07-04 xhr if [ -z "$(which gpg 2> /dev/null)" ]; then
72 ae641176 2017-07-04 xhr abort "gpg or gpg2 not found. Please install."
73 ae641176 2017-07-04 xhr else
74 89fd4ad2 2017-07-04 xhr GPGB="gpg"
75 ae641176 2017-07-04 xhr fi
76 fec3955f 2017-07-03 xhr fi
77 fec3955f 2017-07-03 xhr
78 fec3955f 2017-07-03 xhr if [ -n "${PASSWORD_STORE_KEY}" ]; then
79 ae641176 2017-07-04 xhr ${GPGB} ${GPG_OPTS} --recipient "${PASSWORD_STORE_KEY}" "$@"
80 fec3955f 2017-07-03 xhr else
81 ae641176 2017-07-04 xhr ${GPGB} ${GPG_OPTS} --default-recipient-self "$@"
82 fec3955f 2017-07-03 xhr fi
83 bd3332af 2017-07-04 xhr
84 bd3332af 2017-07-04 xhr return $?
85 51db0130 2016-05-24 soeren+gi }
86 51db0130 2016-05-24 soeren+gi
87 b93a49bc 2015-03-13 soeren+gi readpw() {
88 bad9c329 2015-05-26 soeren+gi if [ -t 0 ]; then
89 d4c9e192 2015-06-27 soeren+gi printf "%s" "${1}"
90 bad9c329 2015-05-26 soeren+gi stty -echo
91 bad9c329 2015-05-26 soeren+gi fi
92 bad9c329 2015-05-26 soeren+gi
93 b93a49bc 2015-03-13 soeren+gi IFS= read -r "${2}"
94 bad9c329 2015-05-26 soeren+gi [ -t 0 ] && stty echo
95 b93a49bc 2015-03-13 soeren+gi }
96 b93a49bc 2015-03-13 soeren+gi
97 dc1ea6be 2017-07-02 xhr entry_exists() {
98 dc1ea6be 2017-07-02 xhr local _entry_name="${1}"
99 dc1ea6be 2017-07-02 xhr local _entry_path="${STORE_DIR}/${_entry_name}.gpg"
100 dc1ea6be 2017-07-02 xhr
101 179af88f 2017-07-03 xhr if [ ! -f "${_entry_path}" ]; then
102 dc1ea6be 2017-07-02 xhr abort "The requested entry doesn't exist."
103 dc1ea6be 2017-07-02 xhr fi
104 dc1ea6be 2017-07-02 xhr }
105 dc1ea6be 2017-07-02 xhr
106 1add099f 2017-07-03 xhr choose_tmp() {
107 1add099f 2017-07-03 xhr # Create the temp file on a shared memory fs if available
108 1add099f 2017-07-03 xhr if [ -d "/dev/shm" -a -k "/dev/shm" ]; then
109 1add099f 2017-07-03 xhr TMPDIR="/dev/shm"
110 1add099f 2017-07-03 xhr fi
111 1add099f 2017-07-03 xhr }
112 1add099f 2017-07-03 xhr
113 fea25380 2017-07-03 xhr nuke_file() {
114 fea25380 2017-07-03 xhr OSV=$(uname -s)
115 fea25380 2017-07-03 xhr
116 fea25380 2017-07-03 xhr if [ -n ${OSV} ]; then
117 fea25380 2017-07-03 xhr if [ "${OSV}" = "Linux" ]; then
118 01452577 2020-10-05 thexhr if [[ -z "$(which shred 2> /dev/null)" ]]; then
119 01452577 2020-10-05 thexhr echo "Cannot find shred. Using rm"
120 01452577 2020-10-05 thexhr return
121 01452577 2020-10-05 thexhr fi
122 fea25380 2017-07-03 xhr NUKE="shred -u"
123 fea25380 2017-07-03 xhr elif [ "${OSV}" = "OpenBSD" -o "${OSV}" = "FreeBSD" -o "${OSV}" = "DragonFly" -o "${OSV}" = "NetBSD" ]; then
124 fea25380 2017-07-03 xhr NUKE="rm -P"
125 fea25380 2017-07-03 xhr fi
126 fea25380 2017-07-03 xhr fi
127 fea25380 2017-07-03 xhr }
128 fea25380 2017-07-03 xhr
129 98cc485f 2013-11-14 git-nmeum ##
130 98cc485f 2013-11-14 git-nmeum # Commands
131 98cc485f 2013-11-14 git-nmeum ##
132 98cc485f 2013-11-14 git-nmeum
133 98cc485f 2013-11-14 git-nmeum show() {
134 54d8a6df 2017-07-02 xhr local _entry_name="${1}"
135 54d8a6df 2017-07-02 xhr local _entry_path="${STORE_DIR}/${_entry_name}.gpg"
136 98cc485f 2013-11-14 git-nmeum
137 54d8a6df 2017-07-02 xhr if [ -z "${_entry_name}" ]; then
138 54d8a6df 2017-07-02 xhr abort "show needs an argument"
139 98cc485f 2013-11-14 git-nmeum fi
140 98cc485f 2013-11-14 git-nmeum
141 54d8a6df 2017-07-02 xhr entry_exists ${_entry_name}
142 98cc485f 2013-11-14 git-nmeum
143 b2af058c 2017-07-04 xhr mygpg --decrypt "${_entry_path}" || abort "Cannot open entry"
144 98cc485f 2013-11-14 git-nmeum }
145 98cc485f 2013-11-14 git-nmeum
146 98cc485f 2013-11-14 git-nmeum insert() {
147 54d8a6df 2017-07-02 xhr local _entry_name="${1}"
148 54d8a6df 2017-07-02 xhr local _entry_path="${STORE_DIR}/${_entry_name}.gpg"
149 98cc485f 2013-11-14 git-nmeum
150 54d8a6df 2017-07-02 xhr if [ -z "${_entry_name}" ]; then
151 a5472807 2017-07-02 xhr abort "insert needs an argument"
152 98cc485f 2013-11-14 git-nmeum fi
153 98cc485f 2013-11-14 git-nmeum
154 179af88f 2017-07-03 xhr if [ -f "${_entry_path}" ]; then
155 a5472807 2017-07-02 xhr abort "This entry already exists"
156 98cc485f 2013-11-14 git-nmeum fi
157 98cc485f 2013-11-14 git-nmeum
158 a3e9af3e 2015-09-24 soeren+gi password=""
159 54d8a6df 2017-07-02 xhr readpw "Password for '${_entry_name}': " password
160 a3e9af3e 2015-09-24 soeren+gi if [ -t 0 ]; then
161 a3e9af3e 2015-09-24 soeren+gi printf "\n"
162 a3e9af3e 2015-09-24 soeren+gi fi
163 a3e9af3e 2015-09-24 soeren+gi
164 b93a49bc 2015-03-13 soeren+gi if [ -z "${password}" ]; then
165 98cc485f 2013-11-14 git-nmeum abort "You didn't specify a password."
166 98cc485f 2013-11-14 git-nmeum fi
167 98cc485f 2013-11-14 git-nmeum
168 fd0070ba 2017-07-03 xhr command mkdir -p "${_entry_path%/*}" || abort "Cannot create password entry"
169 080fbd05 2017-07-02 xhr printf '%s\n' "${password}" | mygpg --encrypt \
170 54d8a6df 2017-07-02 xhr --output "${_entry_path}"
171 98cc485f 2013-11-14 git-nmeum }
172 98cc485f 2013-11-14 git-nmeum
173 080fbd05 2017-07-02 xhr show_all() {
174 a17f5db3 2020-10-05 noreply ${TREE} -l -x --noreport $TOPTS "${STORE_DIR}" -P "*.gpg" --prune | sed 's/\.gpg//'
175 080fbd05 2017-07-02 xhr }
176 080fbd05 2017-07-02 xhr
177 080fbd05 2017-07-02 xhr remove_entry() {
178 0dd6aa62 2017-07-03 xhr local _entry_name="${1}" _answer
179 080fbd05 2017-07-02 xhr
180 aa36579a 2017-07-03 xhr [ -z "${_entry_name}" ] && abort "rm needs an argument"
181 080fbd05 2017-07-02 xhr
182 54d8a6df 2017-07-02 xhr entry_exists ${_entry_name}
183 83a735d6 2020-10-05 thexhr
184 83a735d6 2020-10-05 thexhr nuke_file
185 54d8a6df 2017-07-02 xhr
186 e2ddb685 2017-07-04 xhr echo -n "$0: Really remove ${_entry_name} [y/N]? "
187 e2ddb685 2017-07-04 xhr read -r _answer
188 0dd6aa62 2017-07-03 xhr case "${_answer}" in
189 0dd6aa62 2017-07-03 xhr [yY]) command ${NUKE} -f "${STORE_DIR}/${_entry_name}.gpg" ;;
190 0dd6aa62 2017-07-03 xhr *) ;;
191 0dd6aa62 2017-07-03 xhr esac
192 080fbd05 2017-07-02 xhr }
193 080fbd05 2017-07-02 xhr
194 080fbd05 2017-07-02 xhr find_entry() {
195 080fbd05 2017-07-02 xhr local _entry_name="${1}"
196 080fbd05 2017-07-02 xhr
197 aa36579a 2017-07-03 xhr [ -z "${_entry_name}" ] && abort "find needs an argument"
198 a17f5db3 2020-10-05 noreply ${TREE} -l -x --noreport $TOPTS "${STORE_DIR}/" -P "*${_entry_name}*" --prune \
199 e38aa8f0 2017-07-03 xhr --matchdirs --ignore-case | sed 's/\.gpg//'
200 080fbd05 2017-07-02 xhr echo
201 080fbd05 2017-07-02 xhr }
202 080fbd05 2017-07-02 xhr
203 dc1ea6be 2017-07-02 xhr edit_entry() {
204 dc1ea6be 2017-07-02 xhr local _entry_name="${1}" _tmpfile
205 dc1ea6be 2017-07-02 xhr
206 aa36579a 2017-07-03 xhr [ -z "${_entry_name}" ] && abort "edit needs an argument"
207 dc1ea6be 2017-07-02 xhr
208 dc1ea6be 2017-07-02 xhr entry_exists ${_entry_name}
209 dc1ea6be 2017-07-02 xhr
210 83a735d6 2020-10-05 thexhr nuke_file
211 83a735d6 2020-10-05 thexhr
212 1add099f 2017-07-03 xhr choose_tmp
213 1add099f 2017-07-03 xhr _tmpfile=$(mktemp ${TMPDIR}/tpm.XXXXXXXXXX) || abort "Cannot create temporary file"
214 fea25380 2017-07-03 xhr trap "${NUKE} -f ${_tmpfile}; exit 0" 0 1 2 3 15
215 dc1ea6be 2017-07-02 xhr
216 bd3332af 2017-07-04 xhr mygpg --output ${_tmpfile} --decrypt "${STORE_DIR}/${_entry_name}.gpg" || \
217 bd3332af 2017-07-04 xhr abort "Cannot edit file"
218 dc1ea6be 2017-07-02 xhr
219 aa36579a 2017-07-03 xhr if [ -n "${EDITOR}" ]; then
220 fd0070ba 2017-07-03 xhr ${EDITOR} ${_tmpfile} || abort "Cannot open file using \$EDITOR"
221 dc1ea6be 2017-07-02 xhr else
222 fd0070ba 2017-07-03 xhr vi ${_tmpfile} || abort "Neither vi or an editor in \$EDITOR was found"
223 dc1ea6be 2017-07-02 xhr fi
224 dc1ea6be 2017-07-02 xhr
225 bd3332af 2017-07-04 xhr mygpg --output "${STORE_DIR}/${_entry_name}.gpg" --encrypt ${_tmpfile} || \
226 a17f5db3 2020-10-05 noreply abort "Cannot re-encrypt temporary file"
227 1add099f 2017-07-03 xhr
228 1add099f 2017-07-03 xhr # If the file is there, remove it
229 fea25380 2017-07-03 xhr [ -e "${_tmpfile}" ] && ${NUKE} -f "${_tmpfile}"
230 dc1ea6be 2017-07-02 xhr }
231 dc1ea6be 2017-07-02 xhr
232 98cc485f 2013-11-14 git-nmeum ##
233 98cc485f 2013-11-14 git-nmeum # Parse input
234 98cc485f 2013-11-14 git-nmeum ##
235 98cc485f 2013-11-14 git-nmeum
236 b2af058c 2017-07-04 xhr set +u
237 8779f26f 2017-07-03 xhr [ "${1}" != "insert" -a ! -d "${STORE_DIR}" ] && abort "Password directory does not exist."
238 a17f5db3 2020-10-05 noreply
239 a17f5db3 2020-10-05 noreply # Disable colors for colortree if NO_COLOR is set
240 a17f5db3 2020-10-05 noreply [[ -n $NO_COLOR ]] && TOPTS="-n"
241 b2af058c 2017-07-04 xhr set -u
242 e7691e01 2017-07-02 xhr
243 a80d4dc9 2017-07-08 xhr if [ ! -z "$(which colortree 2> /dev/null)" ]; then
244 598a12fe 2017-07-03 xhr TREE=colortree
245 a80d4dc9 2017-07-08 xhr elif [ ! -z "$(which tree 2> /dev/null)" ]; then
246 598a12fe 2017-07-03 xhr TREE=tree
247 598a12fe 2017-07-03 xhr else
248 598a12fe 2017-07-03 xhr abort "tpm needs tree or colortree to run. Please install"
249 598a12fe 2017-07-03 xhr fi
250 598a12fe 2017-07-03 xhr
251 080fbd05 2017-07-02 xhr if [ $# -eq 0 ]; then
252 080fbd05 2017-07-02 xhr show_all
253 080fbd05 2017-07-02 xhr exit 0
254 080fbd05 2017-07-02 xhr elif [ $# -gt 2 ]; then
255 1517b3d4 2016-05-24 soeren+gi abort "tpm doesn't accept more than two arguments."
256 44475a26 2015-09-25 soeren+gi fi
257 44475a26 2015-09-25 soeren+gi
258 ffd5a3e7 2015-10-12 soeren+gi case "${1}" in
259 ffd5a3e7 2015-10-12 soeren+gi "show") show "${2}" ;;
260 ffd5a3e7 2015-10-12 soeren+gi "insert") insert "${2}" ;;
261 080fbd05 2017-07-02 xhr "find") find_entry "${2}" ;;
262 080fbd05 2017-07-02 xhr "rm") remove_entry "${2}" ;;
263 dc1ea6be 2017-07-02 xhr "edit") edit_entry "${2}" ;;
264 c1cdc08b 2017-07-03 xhr "help") usage ;;
265 080fbd05 2017-07-02 xhr *) show "${1}" ;;
266 98cc485f 2013-11-14 git-nmeum esac
267 296a9b09 2015-02-18 soeren+gi
268 874893cc 2017-07-03 xhr exit 0