You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
566 lines
11 KiB
566 lines
11 KiB
#!/bin/sh
|
|
|
|
AMNGRDB="${AMNGRDB:-${HOME}/.account.db}"
|
|
AMNGRID="${AMNGRID:-${USER}@${HOSTNAME}}"
|
|
AMNGRPWLEN="${AMNGRPWLEN:-10}"
|
|
|
|
alias random="cat /dev/urandom"
|
|
|
|
function rand_printable() {
|
|
local OPT OPTARG OPTIND
|
|
local USAGE="$(printf "Usage: %s [-h] [len]" "$0")"
|
|
|
|
while getopts h OPT
|
|
do
|
|
case $OPT in
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
if ! [[ "${1}" =~ ^[0-9]*$ ]]
|
|
then
|
|
echo "${USAGE}"
|
|
return 1
|
|
fi
|
|
|
|
echo -n "$(random | tr -dc ' !#-&(-~' | head -c${1:-512})"
|
|
}
|
|
|
|
function amngrdbinit() {
|
|
local OPT OPTARG OPTIND DB
|
|
local USAGE="$(printf "Usage: %s [-h] [dbfile]" "$0")"
|
|
|
|
while getopts h OPT
|
|
do
|
|
case $OPT in
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
DB="${1:-${AMNGRDB}}"
|
|
if [ ! \( -d "$(dirname "${DB}")" \) ]
|
|
then
|
|
echo "${USAGE}"
|
|
return 1
|
|
fi
|
|
|
|
sqlite3 "${DB}" <<-EOD
|
|
PRAGMA foreign_keys = ON;
|
|
CREATE TABLE IF NOT EXISTS account (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name VARCHAR(128) UNIQUE NOT NULL,
|
|
desc TEXT DEFAULT NULL);
|
|
CREATE TABLE IF NOT EXISTS cred (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user VARCHAR(128) NOT NULL,
|
|
pass TEXT NOT NULL);
|
|
CREATE TABLE IF NOT EXISTS account_cred (
|
|
account_id INTEGER,
|
|
cred_id INTEGER,
|
|
state SMALLINT(1) NOT NULL,
|
|
FOREIGN KEY(account_id) REFERENCES account(id)
|
|
ON UPDATE CASCADE ON DELETE CASCADE,
|
|
FOREIGN KEY(cred_id) REFERENCES cred(id)
|
|
ON UPDATE CASCADE ON DELETE CASCADE);
|
|
EOD
|
|
}
|
|
|
|
function amngrdbdestroy() {
|
|
local OPT OPTARG OPTIND DB CHECK
|
|
local USAGE="$(printf "Usage: %s [-h] [dbfile]" "$0")"
|
|
|
|
while getopts h OPT
|
|
do
|
|
case $OPT in
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
DB="${1:-${AMNGRDB}}"
|
|
cat <<-EOT
|
|
WARNING: You are about to remove your account data. There is no way to
|
|
recover from this. Are you really sure you want to do this?
|
|
EOT
|
|
printf "Really remove %s (Yes|[No]): " "${DB}" && read CHECK
|
|
CHECK="${CHECK:-No}"
|
|
|
|
test "${CHECK}" == "Yes" && rm -f "${DB}"
|
|
}
|
|
|
|
function amngrid() {
|
|
local OPT OPTARG OPTIND ACCOUNT_NAME DB
|
|
local USAGE="$(printf "Usage: %s [-h] [-D dbfile] account" "$0")"
|
|
|
|
while getopts hD: OPT
|
|
do
|
|
case $OPT in
|
|
D)
|
|
DB="${OPTARG}";;
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
ACCOUNT_NAME="${1}"
|
|
DB="${DB:-${AMNGRDB}}"
|
|
|
|
if [ -z "${ACCOUNT_NAME}" ]
|
|
then
|
|
echo "${USAGE}"
|
|
return 1
|
|
fi
|
|
|
|
echo "$(sqlite3 "${DB}" <<-EOD
|
|
SELECT id FROM account WHERE name='${ACCOUNT_NAME}';
|
|
EOD
|
|
)"
|
|
}
|
|
|
|
function amngrcrypt() {
|
|
local OPT OPTARG OPTIND PLAIN RECIPIENT
|
|
local OPTEND=0
|
|
local USAGE="$(printf "Usage: %s [-h] [-r recipient] password" "$0")"
|
|
|
|
while getopts hr:- OPT
|
|
do
|
|
case $OPT in
|
|
r)
|
|
RECIPIENT="${OPTARG}";;
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
-)
|
|
OPTEND=1;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
test ${OPTEND} -eq 1 && break
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
RECIPIENT="${RECIPIENT:-${AMNGRID}}"
|
|
PLAIN="${1}"
|
|
|
|
if [ -z "${PLAIN}" ]
|
|
then
|
|
echo "${USAGE}"
|
|
return 1
|
|
fi
|
|
|
|
echo -n "${PLAIN}" | gpg -aeqr "${RECIPIENT}"
|
|
}
|
|
|
|
function amngrgen() {
|
|
local OPT OPTARG OPTIND RECIPIENT
|
|
local USAGE="$(printf "Usage: %s [-h] [-r recipient] [len]" "$0")"
|
|
|
|
while getopts hr: OPT
|
|
do
|
|
case $OPT in
|
|
r)
|
|
RECIPIENT="${OPTARG}";;
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
local LEN="${1:-${AMNGRPWLEN}}"
|
|
|
|
if [ "${RECIPIENT}" ]
|
|
then
|
|
amngrcrypt -r "${RECIPIENT}" "$(rand_printable "${LEN}")"
|
|
else
|
|
amngrcrypt "$(rand_printable "${LEN}")"
|
|
fi
|
|
}
|
|
|
|
function amngradd() {
|
|
local OPT OPTARG OPTIND DESCRIPTION RECIPIENT DB
|
|
local OPTEND=0
|
|
local USAGE="$(cat <<-EOT
|
|
Usage: $0 [-h] [-d description] [-D dbfile] [-r recipient]
|
|
account [username [password]]
|
|
EOT
|
|
)"
|
|
|
|
while getopts d:D:hr:- OPT
|
|
do
|
|
case $OPT in
|
|
d)
|
|
DESCRIPTION="${OPTARG}";;
|
|
D)
|
|
DB="${OPTARG}";;
|
|
r)
|
|
RECIPIENT="${OPTARG}";;
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
-)
|
|
OPTEND=1;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
test ${OPTEND} -eq 1 && break
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
RECIPIENT="${RECIPIENT:-${AMNGRID}}"
|
|
DB="${DB:-${AMNGRDB}}"
|
|
|
|
local ACCOUNT_NAME="${1}"
|
|
DESCRIPTION="${DESCRIPTION:-NO DESCRIPTION}"
|
|
|
|
if [ -z "${ACCOUNT_NAME}" ]
|
|
then
|
|
echo "No account name given."
|
|
echo "${USAGE}"
|
|
return 1
|
|
fi
|
|
|
|
if [ "${2}" ]
|
|
then
|
|
USER="${2}"
|
|
else
|
|
USER="$(amngrgetuser -D "${DB}" -c "${ACCOUNT_NAME}")"
|
|
fi
|
|
|
|
if [ -z "${USER}" ]
|
|
then
|
|
printf "Can't find current user for account %s\n" "${ACCOUNT_NAME}"
|
|
echo "${USAGE}"
|
|
return 2
|
|
fi
|
|
|
|
if [ "${3}" ]
|
|
then
|
|
PASSWORD="$(amngrcrypt -r "${RECIPIENT}" -- "${3}")"
|
|
else
|
|
PASSWORD="$(amngrgen -r "${RECIPIENT}")"
|
|
echo -n "${PASSWORD}" | gpg -dq | xclip -i
|
|
fi
|
|
|
|
if [ -z "${PASSWORD}" ]
|
|
then
|
|
printf "Failed to create encrypted password for account %s\n" \
|
|
"${ACCOUNT_NAME}"
|
|
echo "${USAGE}"
|
|
return 3
|
|
fi
|
|
|
|
local ACCOUNT_ID="$(amngrid -D "${DB}" "${ACCOUNT_NAME}")"
|
|
local QUERY="$(cat <<-EOD
|
|
PRAGMA foreign_keys = ON;
|
|
BEGIN TRANSACTION;
|
|
INSERT INTO cred (user, pass)
|
|
VALUES ('${USER}', '${PASSWORD}');
|
|
EOD
|
|
)"
|
|
|
|
if [ -z "${ACCOUNT_ID}" ]
|
|
then
|
|
QUERY="$(cat <<-EOD
|
|
${QUERY}
|
|
INSERT INTO account (name, desc)
|
|
VALUES ('${ACCOUNT_NAME}', '${DESCRIPTION}');
|
|
EOD
|
|
)"
|
|
else
|
|
QUERY="$(cat <<-EOD
|
|
${QUERY}
|
|
UPDATE account_cred SET state=0
|
|
WHERE account_id=(SELECT id FROM account
|
|
WHERE name='${ACCOUNT_NAME}' AND state=2);
|
|
UPDATE account_cred SET state=2
|
|
WHERE account_id=(SELECT id FROM account
|
|
WHERE name='${ACCOUNT_NAME}' AND state=1);
|
|
EOD
|
|
)"
|
|
fi
|
|
|
|
QUERY="$(cat <<-EOD
|
|
${QUERY}
|
|
INSERT INTO account_cred (account_id, cred_id, state)
|
|
VALUES ((SELECT id FROM account WHERE name='${ACCOUNT_NAME}'),
|
|
(SELECT id FROM cred WHERE user='${USER}' AND pass='${PASSWORD}'),
|
|
1);
|
|
COMMIT TRANSACTION;
|
|
EOD
|
|
)"
|
|
|
|
sqlite3 "${DB}" "${QUERY}"
|
|
}
|
|
|
|
function amngrgetuser() {
|
|
local OPT OPTARG OPTIND DB
|
|
local STDOUT=0
|
|
local USAGE="$(cat <<-EOT
|
|
Usage: $0 [-h] [-c] [-D dbfile] account [state]
|
|
EOT
|
|
)"
|
|
|
|
while getopts hcD: OPT
|
|
do
|
|
case $OPT in
|
|
c)
|
|
STDOUT=1;;
|
|
D)
|
|
DB="${OPTARG}";;
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
local ACCOUNT_NAME="${1}"
|
|
local STATE="${2:-"1"}"
|
|
DB="${DB:-${AMNGRDB}}"
|
|
|
|
if [ -z "${ACCOUNT_NAME}" ]
|
|
then
|
|
echo "${USAGE}"
|
|
return 1
|
|
fi
|
|
test "${STATE}" != "1" -a "${STATE}" != "2" && STATE="1"
|
|
|
|
if [ $STDOUT -eq 0 ]
|
|
then
|
|
sqlite3 "${DB}" <<-EOD |\
|
|
awk 'NR>1{print p}{p=$0}END{ORS="";print}' | xclip -i
|
|
SELECT user FROM account
|
|
JOIN account_cred ON account.id=account_cred.account_id
|
|
JOIN cred ON cred.id=account_cred.cred_id
|
|
WHERE name='${ACCOUNT_NAME}' AND state=${STATE};
|
|
EOD
|
|
else
|
|
sqlite3 "${DB}" <<-EOD |\
|
|
awk 'NR>1{print p}{p=$0}END{ORS="";print}'
|
|
SELECT user FROM account
|
|
JOIN account_cred ON account.id=account_cred.account_id
|
|
JOIN cred ON cred.id=account_cred.cred_id
|
|
WHERE name='${ACCOUNT_NAME}' AND state=${STATE};
|
|
EOD
|
|
fi
|
|
}
|
|
|
|
function amngrgetolduser() {
|
|
amngrgetuser "$@" "2"
|
|
}
|
|
|
|
function amngrgetpass() {
|
|
local OPT OPTARG OPTIND DB
|
|
local USAGE="$(printf "Usage: %s [-h] [-D dbfile] account [state]" "$0")"
|
|
|
|
while getopts hD: OPT
|
|
do
|
|
case $OPT in
|
|
D)
|
|
DB="${OPTARG}";;
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
local ACCOUNT_NAME="${1}"
|
|
local STATE="${2:-1}"
|
|
DB="${DB:-${AMNGRDB}}"
|
|
|
|
if [ -z "${ACCOUNT_NAME}" ]
|
|
then
|
|
echo "${USAGE}"
|
|
return 1
|
|
fi
|
|
test "${STATE}" != "1" -a "${STATE}" != "2" && STATE="1"
|
|
|
|
sqlite3 "${DB}" <<-EOD |\
|
|
awk 'NR>1{print p}{p=$0}END{ORS="";print}' | gpg -dq | xclip -i
|
|
SELECT pass FROM account
|
|
JOIN account_cred ON account.id=account_cred.account_id
|
|
JOIN cred ON cred.id=account_cred.cred_id
|
|
WHERE name='${ACCOUNT_NAME}' AND state=${STATE};
|
|
EOD
|
|
}
|
|
|
|
function amngrgetoldpass() {
|
|
amngrgetpass "$@" "2"
|
|
}
|
|
|
|
function amngrrename() {
|
|
local OPT OPTARG OPTIND DB
|
|
local USAGE="$(cat <<-EOT
|
|
Usage: $0 [-h] [-D dbfile] old_account new_account
|
|
EOT
|
|
)"
|
|
|
|
while getopts hD: OPT
|
|
do
|
|
case $OPT in
|
|
D)
|
|
DB="${OPTARG}";;
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
local OLD_NAME="${1}"
|
|
local NEW_NAME="${2}"
|
|
DB="${DB:-${AMNGRDB}}"
|
|
|
|
if [ -z "${OLD_NAME}" -o -z "${NEW_NAME}" ]
|
|
then
|
|
echo "${USAGE}"
|
|
return 1
|
|
fi
|
|
|
|
sqlite3 "${DB}" <<-EOD
|
|
UPDATE account SET name='${NEW_NAME}'
|
|
WHERE name='${OLD_NAME}';
|
|
EOD
|
|
}
|
|
|
|
function amngrdelete() {
|
|
local OPT OPTARG OPTIND DB
|
|
local USAGE="$(printf "Usage: %s [-h] [-D dbfile] account" "$0")"
|
|
|
|
while getopts hD: OPT
|
|
do
|
|
case $OPT in
|
|
D)
|
|
DB="${OPTARG}";;
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
local ACCOUNT_NAME="${1}"
|
|
DB="${DB:-${AMNGRDB}}"
|
|
|
|
if [ -z "${ACCOUNT_NAME}" ]
|
|
then
|
|
echo "${USAGE}"
|
|
return 1
|
|
fi
|
|
|
|
sqlite3 "${DB}" <<-EOD
|
|
PRAGMA foreign_keys = ON;
|
|
BEGIN TRANSACTION;
|
|
DELETE FROM cred WHERE id IN (
|
|
SELECT cred_id FROM account
|
|
JOIN account_cred ON account.id=account_cred.account_id
|
|
WHERE name='${ACCOUNT_NAME}');
|
|
DELETE FROM account WHERE name='${ACCOUNT_NAME}';
|
|
COMMIT TRANSACTION;
|
|
EOD
|
|
}
|
|
|
|
function amngrsearch() {
|
|
local OPT OPTARG OPTIND SEPARATOR PATTERN
|
|
local USAGE="$(cat <<-EOT
|
|
Usage: $0 [-h] [-D dbfile] [-s separator] [pattern]
|
|
EOT
|
|
)"
|
|
|
|
while getopts hD:s: OPT
|
|
do
|
|
case $OPT in
|
|
D)
|
|
DB="${OPTARG}";;
|
|
s)
|
|
SEPARATOR="${OPTARG}";;
|
|
h)
|
|
echo "${USAGE}"
|
|
return 0;;
|
|
?)
|
|
echo "${USAGE}"
|
|
return 1;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND-1))
|
|
|
|
PATTERN="${1}"
|
|
SEPARATOR="${SEPARATOR:-" => "}"
|
|
DB="${DB:-${AMNGRDB}}"
|
|
|
|
sqlite3 -separator "${SEPARATOR}" "${DB}" <<-EOD
|
|
SELECT name, user, desc FROM account
|
|
JOIN account_cred ON account.id=account_cred.account_id
|
|
JOIN cred ON cred.id=account_cred.cred_id
|
|
WHERE state=1 AND (
|
|
name LIKE '%${PATTERN}%' OR user LIKE '%${PATTERN}%' OR
|
|
desc LIKE '%${PATTERN}%');
|
|
EOD
|
|
}
|
|
|
|
case "$(basename -- "$0")" in
|
|
random) random;;
|
|
rand_printable) rand_printable "$@";;
|
|
|
|
amngrdbinit) amngrdbinit "$@";;
|
|
amngrdbdestroy) amngrdbdestroy "$@";;
|
|
|
|
amngradd) amngradd "$@";;
|
|
amngrcreate) amngrcreate "$@";;
|
|
amngrcrypt) amngrcrypt "$@";;
|
|
amngrdelete) amngrdelete "$@";;
|
|
amngrgen) amngrgen "$@";;
|
|
amngrgetoldpass) amngrgetoldpass "$@";;
|
|
amngrgetolduser) amngrgetolduser "$@";;
|
|
amngrgetpass) amngrgetpass "$@";;
|
|
amngrgetuser) amngrgetuser "$@";;
|
|
amngrid) amngrid "$@";;
|
|
amngrlist) amngrlist "$@";;
|
|
amngrrename) amngrrename "$@";;
|
|
amngrsearch) amngrsearch "$@";;
|
|
|
|
*) ;;
|
|
esac
|
|
|
|
# vim: set ft=sh ts=4 sw=4:
|