pass- posix password manager 🔒 |
git clone git://git.acid.vegas/pass.git |
Log | Files | Refs | Archive | README | LICENSE |
pass (4060B)
1 #!/bin/sh 2 # posix password manager - developed by acidvegas (https://git.acid.vegas/pass) 3 umask 077 4 export GPG_TTY=$(tty) 5 6 GPG_ID="acidvegas" # change me 7 GPG_OPTS="-q --yes --compress-algo=none --no-encrypt-to --batch" 8 METHOD="type" 9 PASS_DIR=$HOME/.secrets 10 11 if [ -z $EDITOR ]; then 12 export EDITOR=nano 13 fi 14 15 mkdir -p $PASS_DIR 16 17 edit() { 18 template="pw.XXXXXXXXXXXXX" 19 if [ -d /dev/shm ] && [ -w /dev/shm ] && [ -x /dev/shm ]; then 20 tmp=$(mktemp /dev/shm/$template) 21 elif [ ! -z $PREFIX ] && [ -d $PREFIX/tmp ]; then 22 tmp=$(mktemp $PREFIX/usr/tmp/$template) # For users on Termux 23 else 24 echo "warning: /dev/shm does not exist or is missing permissions required for temporary files (using insecure fallback to /tmp directory)" 25 tmp=$(mktemp /tmp/$template) 26 fi 27 rm_tmp() { 28 rm -rf "$tmp" 29 } 30 trap rm_tmp EXIT 31 if [ -f $PASS_DIR/$1.gpg ]; then 32 gpg -d -o $tmp $GPG_OPTS $PASS_DIR/$1.gpg || exit 1 33 $EDITOR $tmp 34 if [ ! "$(gpg -d $GPG_OPTS $PASS_DIR/$1.gpg)" = "$(cat $tmp)" ]; then 35 gpg -e -r $GPG_ID -o $PASS_DIR/$1.gpg $GPG_OPTS $tmp 36 fi 37 else 38 $EDITOR $tmp 39 if [ -f $tmp ]; then 40 mkdir -p $(dirname $PASS_DIR/$1) 41 gpg -e -r $GPG_ID -o $PASS_DIR/$1.gpg $GPG_OPTS $tmp 42 fi 43 fi 44 } 45 46 generate() { 47 case ${1#[-+]} in 48 *[!0-9]* | '') echo "error: invalid number" ;; 49 *) cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $1 | head -n 1 ;; 50 esac 51 } 52 53 menu() { 54 cwd=$PASS_DIR 55 while : 56 do 57 if [ $cwd = $PASS_DIR ]; then 58 cmd=$(ls -p $cwd | sed 's/\.gpg$//' | dmenu -l 5 "$@") 59 else 60 cmd=$({ echo ".."; ls -p $cwd | sed 's/\.gpg$//'; } | dmenu -l 5 "$@") 61 fi 62 if [ -z $cmd ]; then 63 break 64 elif [ $cmd = '..' ]; then 65 cwd=$(dirname $cwd) 66 elif [ -d $cwd/$cmd ]; then 67 cwd=$cwd/$cmd 68 elif [ -f $cwd/$cmd ]; then 69 if [ $METHOD = "copy" ]; then 70 export PINENTRY_USER_DATA="dmenu" | gpg -d $GPG_OPTS $cwd/$cmd | dmenu "$@" | xclip -selection clipboard 71 sleep 3 && xclip -selection clipboard /dev/nul 72 elif [ $METHOD = "type" ]; then 73 export PINENTRY_USER_DATA="dmenu" | gpg -d $GPG_OPTS $cwd/$cmd | dmenu "$@" | xdotool type --delay 3 "$D" 74 fi 75 break 76 fi 77 done 78 } 79 80 otp() { 81 if [ -f $PASS_DIR/$1.gpg ]; then 82 otp_uri=$(gpg -d $GPG_OPTS $PASS_DIR/$1.gpg | tail -n 1) || exit 1 83 if [ "$(echo $otp_uri | head -c 10)" = "otpauth://" ]; then 84 secret=$(echo "$otp_uri" | sed 's/.*secret=//' | cut -f1 -d'&') 85 oathtool -b --totp $secret 86 else 87 echo "error: OTP URI invalid or not found for '$1'" 88 fi 89 else 90 echo "error: '$1' does not exist" 91 fi 92 } 93 94 show() { 95 if [ -d $PASS_DIR/$1 ]; then 96 echo $1 97 tree -NCl --noreport $PASS_DIR/$1 3>&- | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( ->|$)/\1\2/g' 98 elif [ -f $PASS_DIR/$1.gpg ]; then 99 gpg -d $GPG_OPTS $PASS_DIR/$1.gpg 100 else 101 echo "error: '$1' does not exist" 102 fi 103 } 104 105 # Main 106 command -v gpg >/dev/null || { echo "error: missing required package 'gpg'"; exit 1; } 107 command -v tree >/dev/null || { echo "error: missing required package 'tree'"; exit 1; } 108 if [ "$#" = '1' ]; then 109 if [ $1 = 'menu' ]; then 110 command -v dmenu >/dev/null || { echo "error: missing required package 'dmenu'"; exit 1; } 111 command -v pinentry >/dev/null || { echo "error: missing required package 'pinentry'"; exit 1; } 112 command -v pinentry-dmenu >/dev/null || { echo "error: missing required package 'pinentry-dmenu'"; exit 1; } 113 if [ $METHOD = "copy" ]; then 114 command -v dmenu >/dev/null || { echo "error: missing required package 'xclip'"; exit 1; } 115 elif [ $METHOD = 'type' ]; then 116 command -v xdotool >/dev/null || { echo "error: missing required package 'xdotool'"; exit 1; } 117 else 118 echo "error: invalid menu method (must be 'copy' or 'type')" 119 exit 1 120 fi 121 menu 122 else 123 show $1 124 fi 125 elif [ "$#" = '2' ]; then 126 if [ "$1" = 'edit' ]; then 127 edit $2 128 elif [ "$1" = 'gen' ]; then 129 generate $2 130 elif [ "$1" = 'otp' ]; then 131 command -v oathtool >/dev/null || { echo "error: missing required package 'oathtool'"; exit 1; } 132 otp $2 133 fi 134 else 135 tree -NCl --noreport $PASS_DIR 3>&- | tail -n +2 | sed -E 's/\.gpg(\x1B\[[0-9]+m)?( ->|$)/\1\2/g' 136 fi