#!/bin/sh # Copyright 2021 Mitchell Riedstra # # Permission to use, copy, modify, and/or distribute this software for any purpose # with or without fee is hereby granted, provided that the above copyright notice # and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND # FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF # THIS SOFTWARE. # # Example storage plugin that's compatible with the original password # store set -e PASSWORD_STORE_DIR="${PASSWORD_STORE_DIR:-$HOME/.password-store}" PASSWORD_STORE_KEY="${PASSWORD_STORE_KEY:-}" USE_GIT=0 [ -e "${PASSWORD_STORE_DIR}/.git" ] && USE_GIT=1 umask "${PASSWORD_STORE_UMASK:-077}" __gpg_opts="-q -z0" # Helper functions _git_commit() { [ $USE_GIT -eq 0 ] && return cd "${PASSWORD_STORE_DIR}" git add --all git commit -am "DPW Auto-commit: $1" } _set_gpg_id() { if [ -n "$PASSWORD_STORE_KEY" ] ; then PASSWORD_STORE_KEY="$(echo "$PASSWORD_STORE_KEY" | tr ' ' '\n' \ | sed -e's/^/ -r/' | tr '\n' ' ')" return fi _pth="$1"; shift _pth="${PASSWORD_STORE_DIR}/$_pth" id_file="$(dirname "${_pth}")/.gpg-id" while true ; do # Break if id_file is above our password store directory case $id_file in ${PASSWORD_STORE_DIR}*) ;; *) break ;; esac if [ -e "$id_file" ] ; then keys="" while read -r key ; do keys="$keys -r $key" done < "$id_file" export PASSWORD_STORE_KEY="$keys" return fi # Pop this up a directory level for the next time 'round id_file="$(dirname "$id_file")" id_file="$(dirname "$id_file")/.gpg-id" done echo "No '.gpg-id' files found, is '$PASSWORD_STORE_DIR' initialized?" exit 1 } # Interface show() { pth="$1"; shift #shellcheck disable=SC2086 exec gpg $__gpg_opts -d < "${PASSWORD_STORE_DIR}/${pth}.gpg" } insert() { pth="$1"; shift _set_gpg_id "$pth" mkdir -p "$PASSWORD_STORE_DIR/$(dirname "$pth")" #shellcheck disable=SC2086 gpg $__gpg_opts -e ${PASSWORD_STORE_KEY} \ > "${PASSWORD_STORE_DIR}/${pth}.gpg" _git_commit "Insert: $pth" } list() { find "$PASSWORD_STORE_DIR/$1" -type f -iname "*.gpg" \ | while read -r line ; do line="${line##$PASSWORD_STORE_DIR}" line="${line#/}" line="${line#/}" line="${line%.gpg}" echo "$line" done } remove() { cd "$PASSWORD_STORE_DIR" recursive= force= while [ $# -gt 0 ] ; do case $1 in -r) recursive="-r" ; shift ;; -f) force="-f" ; shift ;; -rf|-fr) recursive="-r" ; force="-f" ; shift ;; *) break ;; esac ; done files= for fn in "$@" ; do if [ -e "${fn}.gpg" ] ; then files="${fn}.gpg " else files="$fn " fi done #shellcheck disable=SC2086 rm $recursive $force $files _git_commit "Remove: $*" } _init_help() { cat <... EOF exit 1 } _init() { USE_GIT=1 if [ -d "${PASSWORD_STORE_DIR}" ] ; then echo "Cannot init new password store, one exists" exit 1 fi while [ $# -gt 0 ] ; do case $1 in --no-git) USE_GIT=0 ; shift ;; -h|--help) _init_help ;; *) break ;; esac ; done if [ $# -eq 0 ] ; then echo "No GPG id supplied, bailing" exit 1 fi mkdir -p "${PASSWORD_STORE_DIR}" cd "${PASSWORD_STORE_DIR}" if [ $USE_GIT -eq 1 ] ; then git init cat >> .git/config <> .gitattributes fi for id in "$@" ; do echo "$id" >> .gpg-id done _git_commit echo "Password store initialized" } act="$1"; shift case $act in show) show "$@" ;; list) list "$@" ;; insert) insert "$@" ;; rm) remove "$@" ;; init) _init "$@" ;; *) echo "Bad command $act"; exit 1; ;; esac