spm

simple password manager
git clone anongit@rnpnr.xyz:spm.git
Log | Files | Refs | Feed | README | LICENSE

spm (2381B)


      1 #!/bin/sh
      2 # Copyright (C) 2013-2016 Sören Tempel
      3 # Copyright (C) 2016, 2017 Klemens Nanni <kl3@posteo.org>
      4 #
      5 # This program is free software: you can redistribute it and/or modify
      6 # it under the terms of the GNU General Public License as published by
      7 # the Free Software Foundation, either version 3 of the License, or
      8 # (at your option) any later version.
      9 #
     10 # This program is distributed in the hope that it will be useful,
     11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     13 # GNU General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU General Public License
     16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
     17 
     18 set -u
     19 umask u=rwx,go=
     20 
     21 ## Variables
     22 GPG_OPTS='--quiet --yes --batch'
     23 STORE_DIR="${PASSWORD_STORE_DIR:-${HOME}/.spm}"
     24 
     25 ## Helper
     26 die() {
     27 	echo "$@" >&2
     28 	exit 1
     29 }
     30 
     31 check() {
     32 	[ -n "${entry}" ] || die "spm: no such entry"
     33 
     34 	[ $(printf '%s' "${entry}" | wc -l) -eq 0 ] ||
     35 		die "spm: ambigious expression"
     36 }
     37 
     38 gpg() {
     39 	if [ -z "${PASSWORD_STORE_KEY}" ]; then
     40 		gpg2 ${GPG_OPTS} --default-recipient-self "${@}"
     41 	else
     42 		gpg2 ${GPG_OPTS} --recipient "${PASSWORD_STORE_KEY}" "${@}"
     43 	fi
     44 }
     45 
     46 readpw() {
     47 	[ -t 0 ] && stty -echo && printf '%s' "${1}"
     48 	IFS= read -r "${2}"
     49 	[ -t 0 ] && stty echo
     50 	[ -z "${2}" ] && die "spm: empty password"
     51 }
     52 
     53 find() {
     54 	command find "${STORE_DIR}" -name "*.gpg" -type f -o -type l | grep -ie "${1}"
     55 }
     56 
     57 ## Commands
     58 add() {
     59 	[ -e "${STORE_DIR}"/"${1}" ] && die "spm: entry already exists"
     60 
     61 	password=
     62 	readpw "Password for '${1}': " password
     63 	[ -t 0 ] && printf '\n'
     64 
     65 	group="${1%/*}"
     66 	[ "${group}" = "${1}" ] && group=
     67 
     68 	mkdir -p "${STORE_DIR}"/"${group}" &&
     69 		printf '%s\n' "${password}" |
     70 			gpg --encrypt --output "${STORE_DIR}"/"${1}.gpg"
     71 }
     72 
     73 list() {
     74 	[ -d "${STORE_DIR}"/"${1:-}" ] || die "spm list: no such group"
     75 	find "${STORE_DIR}"/"${1:-}"
     76 }
     77 
     78 del() {
     79 	entry=$(find "${1}" | head -n2)
     80 	check; command rm "${entry}" && printf '\n'
     81 }
     82 
     83 search() {
     84 	find "${1}"
     85 }
     86 
     87 show() {
     88 	entry=$(find "${1}" | head -n2)
     89 	check; gpg --decrypt "${entry}"
     90 }
     91 
     92 ## Parse input
     93 [ $# -gt 2 ] && die "spm: wrong number of arguments"
     94 
     95 case "${1}" in
     96 add|del|search|show)
     97 	[ -z "${2:-}" ] && die "spm: empty name"
     98 	${1} "${2}"
     99 	;;
    100 list)
    101 	list "${2:-.}"
    102 	;;
    103 *)
    104 	die "usage: ${0} add|del|list|search|show [[group/]entry|expression]"
    105 	;;
    106 esac