#!/usr/bin/env bash # Helpers err() { printf '%s\n' "$*" >&2; } die() { [[ "$1" ]] || { exit 113; } [[ "$2" ]] && err "$2" exit "$1" } vault_is_json() { pass "$1" | jshon -Q &>/dev/null; } vault_exists() [[ -f "${opts[store]}/$1.gpg" ]] check_argn() { # Check for the number of args the dumb way. (( $# < 2 )) && die 113 (( $# > 3 )) && die 113 declare length=$1 min=$2 max=$3 (( length < min )) && die 1 "Too few arguments" [[ "$max" ]] && { (( length > max )) && die 1 "Too many arguments" } return 0 } # Our options declare -A opts flags # Default opts opts[pw_len]=16 opts[login]='fbt@fleshless.org' opts[selection]="${X_SELECTION:-clipboard}" opts[store]="$HOME/.password-store" opts[tmp_dir]='/tmp' # Default flags flags[clip]=0 # Show must go on while (( $# )); do case $1 in # Options (-l) opts[pw_len]=$2; shift;; (-u) opts[login]=$2; shift;; (-s) opts[selection]=$2; shift;; # Flags (-c) flags[clip]=1;; # Non-numeric flags (-n) opts[action]='new';; (-g) opts[action]='get';; (-a) opts[action]='add';; (-e) if [[ "${opts[action]}" ]]; then flags[edit]=1 else opts[action]='edit' fi ;; # Misc (--) shift; break;; (-*) die 13 "Unknown key: $1";; (*) break;; esac shift done case "${opts[action]:-get}" in (new) check_argn "${#@}" 1 1; vault="$1" # Check if the damn thing already exists vault_exists "$vault" && die 1 "Vault '$vault' already exists" new_pass=$(pwgen "${opts[pw_len]}" 1) pass insert -m "$vault" < <( jshon -Q -n {} \ -s "$new_pass" -i "password" \ -s "${opts[login]}" -i "login" ) (( "${flags[clip]}" )) && { printf '%s' "$new_pass" | xclip -selection "${opts[selection]}" } ;; (get) check_argn "${#@}" 1 2; vault=$1 field=${2:-password} vault_exists "$vault" || die 1 "Vault does not exist: $1" if vault_is_json "$vault"; then pass=$(pass "$vault" | jshon -e "$field" -u) else [[ "$2" ]] && err "Warning: ignoring '$field', because '$vault' is not a json vault" pass=$(pass "$vault") fi if (( "${flags[clip]}" )); then printf '%s' "$pass" | xclip -selection "${opts[selection]}" else printf '%s\n' "$pass" fi ;; (add) check_argn "${#@}" 2 3; vault=$1 field=$2; data=$3 vault_exists "$vault" || die 1 "Vault does not exist: $1" vault_is_json "$vault" || die 1 "Not a valid json vault: $1" json=$( pass "$vault" ) jshon -s "$data" -i "$field" <<< "$json" | pass insert -m "$vault" ;; (edit) pass edit "$1";; esac (( "${flags[edit]}" )) && "$0" -e "$1"