mirror of
https://github.com/octoleo/Purse.git
synced 2024-12-28 03:45:04 +00:00
Small refactor, add help doc, simplify prompts
This commit is contained in:
parent
d14f551e87
commit
274954953c
162
pwd.sh
162
pwd.sh
@ -1,6 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Script for managing passwords in a GnuPG symmetrically encrypted file.
|
||||
|
||||
set -o errtrace
|
||||
set -o nounset
|
||||
@ -14,6 +12,7 @@ safe="${PWDSH_SAFE:=pwd.sh.safe}"
|
||||
fail () {
|
||||
# Print an error message and exit.
|
||||
|
||||
printf "\n\n"
|
||||
tput setaf 1 1 1 ; echo "Error: ${1}" ; tput sgr0
|
||||
exit 1
|
||||
}
|
||||
@ -22,7 +21,7 @@ fail () {
|
||||
get_pass () {
|
||||
# Prompt for a password.
|
||||
|
||||
password=''
|
||||
password=""
|
||||
prompt="${1}"
|
||||
|
||||
while IFS= read -p "${prompt}" -r -s -n 1 char ; do
|
||||
@ -40,28 +39,22 @@ get_pass () {
|
||||
password+="${char}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z "${password}" ]] ; then
|
||||
fail "No password provided"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
decrypt () {
|
||||
# Decrypt with a password.
|
||||
|
||||
echo "${1}" | ${gpg} \
|
||||
--decrypt --armor --batch \
|
||||
--passphrase-fd 0 "${2}" 2>/dev/null
|
||||
echo "${1}" | ${gpg} --armor --batch \
|
||||
--decrypt --passphrase-fd 0 "${2}" 2>/dev/null
|
||||
}
|
||||
|
||||
|
||||
encrypt () {
|
||||
# Encrypt with a password.
|
||||
|
||||
${gpg} \
|
||||
--symmetric --armor --batch --yes \
|
||||
--passphrase-fd 3 \
|
||||
${gpg} --armor --batch \
|
||||
--symmetric --yes --passphrase-fd 3 \
|
||||
--output "${2}" "${3}" 3< <(echo "${1}")
|
||||
}
|
||||
|
||||
@ -69,25 +62,22 @@ encrypt () {
|
||||
read_pass () {
|
||||
# Read a password from safe.
|
||||
|
||||
if [[ ! -s ${safe} ]] ; then
|
||||
fail "No passwords found"
|
||||
fi
|
||||
if [[ ! -s ${safe} ]] ; then fail "No password safe found" ; fi
|
||||
|
||||
if [[ -z "${2+x}" ]] ; then
|
||||
read -r -p "
|
||||
Username to read? (default: all) " username
|
||||
if [[ -z "${2+x}" ]] ; then read -r -p "
|
||||
Username (Enter for all): " username
|
||||
else
|
||||
username="${2}"
|
||||
fi
|
||||
|
||||
if [[ -z "${username}" || "${username}" == "all" ]] ; then
|
||||
username=""
|
||||
fi
|
||||
if [[ -z "${username}" || "${username}" == "all" ]] ; then username="" ; fi
|
||||
|
||||
get_pass "
|
||||
Enter password to unlock ${safe}: "
|
||||
while [[ -z "${password}" ]] ; do get_pass "
|
||||
Password to unlock ${safe}: " ; done
|
||||
printf "\n\n"
|
||||
decrypt ${password} ${safe} | grep -F " ${username}" || fail "Decryption failed"
|
||||
|
||||
decrypt ${password} ${safe} | grep -F " ${username}" \
|
||||
|| fail "Decryption failed"
|
||||
}
|
||||
|
||||
|
||||
@ -97,26 +87,24 @@ gen_pass () {
|
||||
len=50
|
||||
max=100
|
||||
|
||||
if [[ -z "${3+x}" ]] ; then
|
||||
read -p "
|
||||
Password length? (default: ${len}, max: ${max}) " length
|
||||
if [[ -z "${3+x}" ]] ; then read -p "
|
||||
|
||||
Password length (default: ${len}, max: ${max}): " length
|
||||
else
|
||||
length="${3}"
|
||||
fi
|
||||
|
||||
if [[ ${length} =~ ^[0-9]+$ ]] ; then
|
||||
len=${length}
|
||||
fi
|
||||
if [[ ${length} =~ ^[0-9]+$ ]] ; then len=${length} ; fi
|
||||
|
||||
# base64: 4 characters for every 3 bytes
|
||||
${gpg} --gen-random --armor 0 "$((${max} * 3/4))" | cut -c -${len}
|
||||
${gpg} --armor --gen-random 0 "$((${max} * 3/4))" | cut -c -"${len}"
|
||||
}
|
||||
|
||||
|
||||
write_pass () {
|
||||
# Write a password in safe.
|
||||
|
||||
# If no password provided, clear the entry by writing an empty line.
|
||||
# If no password (delete action), clear the entry by writing an empty line.
|
||||
if [[ -z "${userpass+x}" ]] ; then
|
||||
entry=" "
|
||||
else
|
||||
@ -124,7 +112,7 @@ write_pass () {
|
||||
fi
|
||||
|
||||
get_pass "
|
||||
Enter password to unlock ${safe}: " ; echo
|
||||
Password to unlock ${safe}: " ; echo
|
||||
|
||||
# If safe exists, decrypt it and filter out username, or bail on error.
|
||||
# If successful, append entry, or blank line.
|
||||
@ -138,33 +126,25 @@ write_pass () {
|
||||
echo "${entry}") | \
|
||||
(${filter} "^[[:space:]]*$|^mtime:[[:digit:]]+$";echo mtime:$(date +%s)) | \
|
||||
encrypt ${password} ${safe}.new - || fail "Write to safe failed"
|
||||
mv ${safe}.new ${safe}
|
||||
mv ${safe}{.new,}
|
||||
}
|
||||
|
||||
|
||||
create_username () {
|
||||
# Create username with password.
|
||||
new_entry () {
|
||||
# Prompt for new username and/or password.
|
||||
|
||||
if [[ -z "${2+x}" ]] ; then
|
||||
read -r -p "
|
||||
if [[ -z "${2+x}" ]] ; then read -r -p "
|
||||
Username: " username
|
||||
else
|
||||
username="${2}"
|
||||
fi
|
||||
|
||||
if [[ -z "${3+x}" ]] ; then
|
||||
read -p "
|
||||
Generate password? (y/n, default: y) " rand_pass
|
||||
else
|
||||
rand_pass=""
|
||||
if [[ -z "${3+x}" ]] ; then get_pass "
|
||||
Password for \"${username}\" (Enter to generate): "
|
||||
userpass="${password}"
|
||||
fi
|
||||
|
||||
if [[ "${rand_pass}" =~ ^([nN][oO]|[nN])$ ]]; then
|
||||
get_pass "
|
||||
Enter password for \"${username}\": " ; echo
|
||||
userpass=${password}
|
||||
else
|
||||
userpass=$(gen_pass "$@")
|
||||
if [[ -z "${password}" ]] ; then userpass=$(gen_pass "$@")
|
||||
if [[ -z "${4+x}" || ! "${4}" =~ ^([qQ])$ ]] ; then
|
||||
echo "
|
||||
Password: ${userpass}"
|
||||
@ -172,42 +152,82 @@ create_username () {
|
||||
fi
|
||||
}
|
||||
|
||||
print_help () {
|
||||
# Print help text.
|
||||
|
||||
sanity_check () {
|
||||
# Make sure required programs are installed and are executable.
|
||||
echo "
|
||||
pwd.sh is a shell script to manage passwords with GnuPG symmetric encryption.
|
||||
|
||||
if [[ -z ${gpg} && ! -x ${gpg} ]] ; then
|
||||
fail "GnuPG is not available"
|
||||
fi
|
||||
The script can be run interactively as './pwd.sh' or with the following args:
|
||||
|
||||
* 'r' to read a password
|
||||
* 'w' to write a password
|
||||
* 'd' to delete a password
|
||||
* 'h' to see this help text
|
||||
|
||||
A username can be supplied as an additional argument or 'all' for all entries.
|
||||
|
||||
For writing, a password length can be appended. Append 'q' to suppress output.
|
||||
|
||||
Examples:
|
||||
|
||||
* Read all passwords:
|
||||
|
||||
./pwd.sh r all
|
||||
|
||||
* Write a password for 'github':
|
||||
|
||||
./pwd.sh w github
|
||||
|
||||
* Generate a 50 character password for 'github' and write:
|
||||
|
||||
./pwd.sh w github 50
|
||||
|
||||
* To suppress the generated password:
|
||||
|
||||
./pwd.sh w github 50 q
|
||||
|
||||
* Delete password for 'mail':
|
||||
|
||||
./pwd.sh d mail
|
||||
|
||||
A password cannot be supplied as an argument, nor is used as one throughout
|
||||
the script, to prevent it from appearing in process listing or logs.
|
||||
|
||||
To report a bug, visit https://github.com/drduh/pwd.sh
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
sanity_check
|
||||
if [[ -z ${gpg} && ! -x ${gpg} ]] ; then fail "GnuPG is not available" ; fi
|
||||
|
||||
if [[ -z "${1+x}" ]] ; then
|
||||
read -n 1 -p "
|
||||
Read, write, or delete password? (r/w/d, default: r) " action
|
||||
printf "\n"
|
||||
else
|
||||
password=""
|
||||
|
||||
action=""
|
||||
if [[ -n "${1+x}" ]] ; then
|
||||
action="${1}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${action}" =~ ^([wW])$ ]] ; then
|
||||
create_username "$@"
|
||||
while [[ -z "${action}" ]] ;
|
||||
do read -n 1 -p "
|
||||
Read, Write, or Delete password (or Help): " action
|
||||
printf "\n"
|
||||
done
|
||||
|
||||
if [[ "${action}" =~ ^([hH])$ ]] ; then
|
||||
print_help
|
||||
elif [[ "${action}" =~ ^([wW])$ ]] ; then
|
||||
new_entry "$@"
|
||||
write_pass
|
||||
|
||||
elif [[ "${action}" =~ ^([dD])$ ]] ; then
|
||||
if [[ -z "${2+x}" ]] ; then
|
||||
read -p "
|
||||
Username to delete? " username
|
||||
if [[ -z "${2+x}" ]] ; then read -p "
|
||||
Username: " username
|
||||
else
|
||||
username="${2}"
|
||||
fi
|
||||
write_pass
|
||||
|
||||
else
|
||||
read_pass "$@"
|
||||
fi
|
||||
|
||||
tput setaf 2 2 2 ; echo "
|
||||
Done" ; tput sgr0
|
||||
printf "\n" ; tput setaf 2 2 2 ; echo "Done" ; tput sgr0
|
||||
|
Loading…
Reference in New Issue
Block a user