diff --git a/Makefile b/Makefile index 3d702a1..34a875d 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,10 @@ PROGRAM := accountmanager.sh all: doc +README_new.md: doc/accountmanager.1 + groff -D utf8 -mandoc -Thtml "$<" |\ + pandoc -f html -t markdown_strict >"$@" + .PHONY: clean install doc doc: diff --git a/README.md b/README.md index 50812ce..f844aa1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ Database management functions: Account management functions: - **amngradd** − add an account credential to the database - - **amngrcreate** − create a new account credential to the database - **amngrcrypt** − crypt the given data with GnuPG - **amngrdelete** − delete an account - **amngrgen** − generate a encrypted random passphrase @@ -23,7 +22,6 @@ Account management functions: - **amngrgetpass** − copy active password of account to X clipboard - **amngrgetuser** − copy active username of account to X clipboard - **amngrid** − write the database id of a given account name to stdout - - **amngrlist** − list all accounts - **amngrrename** − rename an account - **amngrsearch** − pattern search accounts @@ -33,39 +31,35 @@ source **${PATH}/accountmanager.sh** **random** -**rand\_printable** \[*len*\] +**rand\_printable** \[**-h**\] \[*len*\] -**amngrdbinit** \[*dbfile*\] +**amngrdbinit** \[**-h**\] \[*dbfile*\] -**amngrdbdestroy** \[*dbfile*\] +**amngrdbdestroy** \[**-h**\] \[*dbfile*\] -**amngradd** **-u** *username* **-p** *password* \[**-d** *description*\] -\[**-D** *dbfile*\] \[**-r** *recipient*\] *account* +**amngradd** \[**-h**\] \[**-d** *description*\] \[**-D** *dbfile*\] +\[**-r** *recipient*\] *account* \[*username* \[*password*\]\] -**amngrcreate** **-u** *username* \[**-d** *description*\] \[**-D** -*dbfile*\] \[**-r** *recipient*\] *account* +**amngrcrypt** \[**-h**\] \[**-r** *recipient*\] *password* -**amngrcrypt** \[**-r** *recipient*\] *password* +**amngrdelete** \[**-h**\] \[**-D** *dbfile*\] *account* -**amngrdelete** *account* +**amngrgen** \[**-h**\] \[**-r** *recipient*\] \[*len*\] -**amngrgen** \[**-r** *recipient*\] \[*len*\] +**amngrgetoldpass** \[**-h**\] \[**-D** *dbfile*\] *account* -**amngrgetoldpass** *account* +**amngrgetolduser** \[**-h**\] \[**-c**\] \[**-D** *dbfile*\] *account* -**amngrgetolduser** *account* +**amngrgetpass** \[**-h**\] \[**-D** *dbfile*\] *account* \[*state*\] -**amngrgetpass** *account* +**amngrgetuser** \[**-h**\] \[**-c**\] \[**-D** *dbfile*\] *account* \[*state*\] -**amngrgetuser** *account* +**amngrid** \[**-h**\] \[**-D** *dbfile*\] *account* -**amngrid** *account* +**amngrrename** \[**-h**\] \[**-D** *dbfile*\] *old\_account* *new\_account* -**amngrlist** \[**-s** *separator*\] - -**amngrrename** *old\_account new\_account* - -**amngrsearch** \[**-s** *separator*\] *pattern* +**amngrsearch** \[**-h**\] \[**-D** *dbfile*\] \[**-s** *separator*\] +\[*pattern*\] ## DESCRIPTION @@ -84,55 +78,58 @@ pair. Takes no arguments and connect a non blocking random source to stdout. -**rand\_printable** \[*len*\] +**rand\_printable** \[**-h**\] \[*len*\] Uses **random** to write a string of random printable characters to stdout. All control characters ASCII-0 to ASCII-37 as well as ASCII-177 to 255, single and double quotes are filtered. The single and double quotes are filtered to prevent problems when they are used as string separators after shell expansion as in the SQL here documents used to -communicate with the SQLite database. +communicate with the SQLite database. The optional *len* argument specifies the string length to be written and defaults to 512. -**amngrdbinit** \[*dbfile*\] +**amngrdbinit** \[**-h**\] \[*dbfile*\] Create the SQLite database file. If the optional *dbfile* argument is given it specifies the fill path to the file to use, else the value of **$AMNGRDB** environment variable is used. -**amngrdbdestroy** \[*dbfile*\] +**amngrdbdestroy** \[**-h**\] \[*dbfile*\] Deletes the SQLite database file. If the optional *dbfile* argument is given it specifies the fill path to the file to use, else the value of **$AMNGRDB** environment variable is used. -**amngradd -u** *username* **-p** *password* \[**-d** *description*\] -\[**-D** *dbfile*\] \[**-r** *recipient*\] *account* +**amngradd** \[**-h**\] \[**-d** *description*\] \[**-D** *dbfile*\] +\[**-r** *recipient*\] *account* \[*username* \[*password*\]\] Adds an account credential and marks it as active. If the account already exist, the credential (*username* and *password*) is added to that account and the previously added credential is marked as old. If there was another even older credential that was already marked as old -this will be marked as inactive and this becomes inaccessible with this -tools (except for **amngrdelete**). -The necessary option **-u** specifies the username to be stored with -this credential pair. -The also necessary option **-p** specifies the password to be stored -and the length of *password* is not limited at all. -With option **-d** one can add a *description* to the account entry. -One can specify the *dbfile* with the option **-D** if that option is -not given the **$AMNGRDB** environment variable is used. - -**amngrcreate -u** *username* \[**-d** *description*\] \[**-D** -*dbfile*\] \[**-r** *recipient*\] *account* - -This will create a password with **amngrgen** and use that to add an -credential via **amngradd**. (See there for options description) -The added password will be copied to the X clipboard with -**amngrgetpass** for further use. - -**amngrcrypt** \[**-r** *recipient*\] *password* +this will be marked as inactive and thus becomes inaccessible with this +tools (except for **amngrdelete**). + +The *username* and the *account* name must not be longer than 128 +characters. The *password* is not limited in its length at all. If +*password* is omitted one will be generated with **amngrgen**. + +The *username* may also be omitted if there was a previously added +credentials pair for this account. In that case the previous username is +taken. It is a failure to provide a *password* without a *username*. +There is no way for the script to detect this condition and you will end +up with a credential where the username is the password and the password +was generated. + +Option **-d** adds a *description* to the account entry and option +**-D** specifys the *dbfile* to use. If that option is not given the +**$AMNGRDB** environment variable is used. + +If a password was generated with this call it will be stored in the X +clipboard. + +**amngrcrypt** \[**-h**\] \[**-r** *recipient*\] *password* Crypt the given plain text *password* with GnuPG and write it to stdout. @@ -140,58 +137,59 @@ The option **-r** specifies the recipient to use with the call to **gpg**. If it is not given the value of the **$AMNGRID** environment variable is used. -**amngrdelete** *account* +**amngrdelete** \[**-h**\] \[**-D** *dbfile*\] *account* Remove the *account* and all credential associated to it. -**amngrgen** \[**-r** *receipient*\] \[*len*\] +**amngrgen** \[**-h**\] \[**-r** *receipient*\] \[*len*\] Generate a password with **rand\_printable** and encrypt it via **amngrcrypt**. By default the password will be 10 characters long. That can be modified by the optional *len* argument. -**amngrgetoldpass** *account* +**amngrgetoldpass** \[**-h**\] \[**-D** *dbfile*\] *account* Read and decrypt the password associated with *account* that is flagged as old and store it into the X clipboard. -**amngrgetolduser** *account* +**amngrgetolduser** \[**-h**\] \[**-c**\] \[**-D** *dbfile*\] *account* Read and decrypt the username associated with *account* that is flagged as old and store it into the X clipboard. -**amngrgetpass** *account* +**amngrgetpass** \[**-h**\] \[**-D** *dbfile*\] *account* \[*state*\] Read and decrypt the password associated with *account* that is flagged -as active and store it into the X clipboard. +as active and store it into the X clipboard. The *state* argument might +be either 1 or 2 where 1 means get the current credential and 2 means +get the old credential. It defaults to 1. -**amngrgetuser** *account* +**amngrgetuser** \[**-h**\] \[**-c**\] \[**-D** *dbfile*\] *account* \[*state*\] Read and decrypt the username associated with *account* that is flagged -as active and store it into the X clipboard. +as active and store it into the X clipboard. The *state* argument might +be either 1 or 2 where 1 means get the current credential and 2 means +get the old credential. It defaults to 1. -**amngrid** *account* +**amngrid** \[**-h**\] \[**-D** *dbfile*\] *account* (This is primarily for internal use.) Get the database id associated to the given *account* argument. -**amngrlist** \[**-s** *separator*\] - -List all accounts currently stored within the database the output will -contain the name of the account, the username and the description -delimited by a *separator* string that can be specified with the **-s** -option. If the option is omitted the separator is " => ". Each row is -one account. - -**amngrrename** *old\_account new\_account* +**amngrrename** \[**-h**\] \[**-D** *dbfile*\] *old\_account +new\_account* Rename the account specified by *old\_account* to *new\_account*. -**amngrsearch** \[**-s** *separator*\] *pattern* +**amngrsearch** \[**-h**\] \[**-D** *dbfile*\] \[**-s** *separator*\] +\[*pattern*\] -List accounts where *pattern* exists in either the account name, the -username or the account description. The output is like the one -described with **amngrlist**. +List all accounts where *pattern* exists in either the account name, the +username or the account description. The output will contain the name of +the account, the username and the description delimited by a *separator* +string that can be specified with the **-s** option. If the option is +omitted the separator is " => ". Each row is one account. +If *pattern* is omitted all accounts will be listed. ## OPTIONS @@ -199,10 +197,17 @@ The options are consistent over all sub commands. However not all sub commands use all options and some sub commands take arguments that other get per option. (See **DESCRIPTION**) +**-h** − Write a short usage information. + **-u** − The login username of the credential for the account. **-p** − The plain text password of the credential for the account. +**-c** − By default this scripts stores the username into the X clipboard + whith **ambgrgetuser** and **amngrgetolduser**. When **-c** is given + the username is written to stdout. The password is never written to + stdout. + **-d** − The description for the account. **-D** − Select the database file to use instead of the one defined in the @@ -211,8 +216,8 @@ get per option. (See **DESCRIPTION**) **-r** − Select a recipient id for GnuPG encryption to use instead of the one defined in the **$AMNGRID** environment variable. -**-s** − The column separator for the **amngrlist** and - **amngrsearchcommands**. +**-s** − The column separator for the **amngrlist** and **amngrsearch** + commands. ## ENVIRONMENT @@ -231,7 +236,8 @@ option. **AMNGRPWLEN** -The password length to be used when generating new passwords. +The password length to be used when generating new passwords. If not +specified this defaults to 10. ## DEPENDENCIES @@ -257,7 +263,7 @@ To store the data within the X clipboard the **xclip** is needed. - **awk** - **basename** - **cat** - - **dnsdomainname** + - **dirname** - **echo** - **getopts** - **gpg** diff --git a/accountmanager.sh b/accountmanager.sh index 1d61254..096ca5c 100644 --- a/accountmanager.sh +++ b/accountmanager.sh @@ -7,15 +7,54 @@ AMNGRPWLEN="${AMNGRPWLEN:-10}" alias random="cat /dev/urandom" function rand_printable() { - if ! [[ "${1}" =~ "^[0-9]+$" ]] + 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 - printf "Usage: %s: [len]" "$0" + echo "${USAGE}" + return 1 fi + echo -n "$(random | tr -dc ' !#-&(-~' | head -c${1:-512})" } function amngrdbinit() { - local DB="${1:-${AMNGRDB}}" + 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; @@ -39,43 +78,198 @@ function amngrdbinit() { } function amngrdbdestroy() { - local DB="${1:-${AMNGRDB}}" - local CHECK + 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 shure you want to do this? + recover from this. Are you really sure you want to do this? EOT - echo -n "[Yes|[No]]: " && read CHECK + printf "Really remove %s (Yes|[No]): " "${DB}" && read CHECK CHECK="${CHECK:-No}" - test "${CHECK}" == "Yes" && rm -f "${AMNGRDB}" + test "${CHECK}" == "Yes" && rm -f "${DB}" } function amngrid() { - local ACCOUNT_NAME="${1}" - echo "$(sqlite3 "${AMNGRDB}" <<-EOD + 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 PLAIN="${1}" - echo -n "${PLAIN}" | gpg -aeqr "${AMNGRID}" + local OPT OPTARG OPTIND PLAIN RECIPIENT + 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;; + ?) + echo "${USAGE}" + return 1;; + esac + 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 LEN="${0:-${AMNGRPWLEN}}" - amngrcrypt "$(rand_printable "${LEN}")" + 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 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;; + ?) + echo "${USAGE}" + return 1;; + esac + done + shift $(($OPTIND-1)) + + RECIPIENT="${RECIPIENT:-${AMNGRID}}" + DB="${DB:-${AMNGRDB}}" + local ACCOUNT_NAME="${1}" - local USER="${2}" - local PASSWORD="$(amngrcrypt "${3}")" - local DESCRIPTION="${4:-NO DESCRIPTION}" - local ACCOUNT_ID="$(amngrid "${ACCOUNT_NAME}")" + 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; @@ -115,46 +309,100 @@ function amngradd() { EOD )" - sqlite3 "${AMNGRDB}" "${QUERY}" + sqlite3 "${DB}" "${QUERY}" } -function amngrcreate() { - local ACCOUNT_NAME="${1}" - local USER="${2}" - local DESCRIPTION="${3:-NO DESCRIPTION}" - local PASSWORD="$(rand_printable 10)" +function amngrgetuser() { + local OPT OPTARG OPTIND DB + local STDOUT=0 + local USAGE="$(cat <<-EOT + Usage: $0 [-h] [-c] [-D dbfile] account [state] + EOT + )" - amngradd "${ACCOUNT_NAME}" "${USER}" "${PASSWORD}" "${DESCRIPTION}" - amngrgetpass "${ACCOUNT_NAME}" -} + 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)) -function amngrgetuser() { 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 "${AMNGRDB}" <<-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 + 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() { - local ACCOUNT_NAME="${1}" - amngrgetuser "${ACCOUNT_NAME}" "2" + 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 "${AMNGRDB}" <<-EOD |\ + 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 @@ -164,26 +412,76 @@ function amngrgetpass() { } function amngrgetoldpass() { - local ACCOUNT_NAME="${1}" - amngrgetpass "${ACCOUNT_NAME}" "2" + 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}}" - test -z "${OLD_NAME}" -o -z "${NEW_NAME}" && return 1 + if [ -z "${OLD_NAME}" -o -z "${NEW_NAME}" ] + then + echo "${USAGE}" + return 1 + fi - sqlite3 "${AMNGRDB}" <<-EOD + 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 "${AMNGRDB}" <<-EOD + sqlite3 "${DB}" <<-EOD PRAGMA foreign_keys = ON; BEGIN TRANSACTION; DELETE FROM cred WHERE id IN ( @@ -195,42 +493,35 @@ function amngrdelete() { EOD } -function amngrlist() { - local SEPARATOR="${1:-" => "}" - sqlite3 -separator "${SEPARATOR}" "${AMNGRDB}" <<-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; - EOD -} - function amngrsearch() { - local PATTERN - local DELIMITER=" => " - local USAGE="$(printf "Usage: %s: [-d delimiter] pattern" "$0")" + local OPT OPTARG OPTIND SEPARATOR PATTERN + local USAGE="$(cat <<-EOT + Usage: $0 [-h] [-D dbfile] [-s separator] [pattern] + EOT + )" - while getopts d: opt + while getopts hD:s: OPT do - case $opt in - d) - DELIMITER="${OPTARG}";; + case $OPT in + D) + DB="${OPTARG}";; + s) + SEPARATOR="${OPTARG}";; + h) + echo "${USAGE}" + return 0;; ?) echo "${USAGE}" - exit 1;; + return 1;; esac done shift $(($OPTIND-1)) - if [ $# -lt 2 ] - then - echo "${USAGE}" - exit 1;; - fi - PATTERN="${1}" + SEPARATOR="${SEPARATOR:-" => "}" + DB="${DB:-${AMNGRDB}}" - sqlite3 -separator " => " "${AMNGRDB}" <<-EOD + 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 @@ -242,10 +533,10 @@ function amngrsearch() { case "$(basename -- "$0")" in random) random;; - rand_printable) rand_printable;; + rand_printable) rand_printable "$@";; - amngrdbinit) amngrdbinit;; - amngrdbdestroy) amngrdbdestroy;; + amngrdbinit) amngrdbinit "$@";; + amngrdbdestroy) amngrdbdestroy "$@";; amngradd) amngradd "$@";; amngrcreate) amngrcreate "$@";; @@ -257,7 +548,7 @@ case "$(basename -- "$0")" in amngrgetpass) amngrgetpass "$@";; amngrgetuser) amngrgetuser "$@";; amngrid) amngrid "$@";; - amngrlist) amngrlist;; + amngrlist) amngrlist "$@";; amngrrename) amngrrename "$@";; amngrsearch) amngrsearch "$@";; diff --git a/doc/accountmanager.1 b/doc/accountmanager.1 index 5067b79..8e3cc78 100644 --- a/doc/accountmanager.1 +++ b/doc/accountmanager.1 @@ -15,7 +15,6 @@ Database management functions: Account management functions: amngradd \- add an account credential to the database - amngrcreate \- create a new account credential to the database amngrcrypt \- crypt the given data with GnuPG amngrdelete \- delete an account amngrgen \- generate a encrypted random passphrase @@ -24,7 +23,6 @@ Account management functions: amngrgetpass \- copy active password of account to X clipboard amngrgetuser \- copy active username of account to X clipboard amngrid \- write the database id of a given account name to stdout - amngrlist \- list all accounts amngrrename \- rename an account amngrsearch \- pattern search accounts .SH SYNOPSIS @@ -34,75 +32,95 @@ source .B random .B rand_printable +.RB [ -h ] .RI [ len ] .B amngrdbinit +.RB [ -h ] .RI [ dbfile ] .B amngrdbdestroy +.RB [ -h ] .RI [ dbfile ] -.B amngradd -u -.I username -.B -p -.I password +.B amngradd +.RB [ -h ] .RB [ -d .IR description ] .RB [ -D .IR dbfile ] .RB [ -r .IR recipient ] -.I account - -.B amngrcreate -u -.I username -.RB [ -d -.IR description ] -.RB [ -D -.IR dbfile ] -.RB [ -r -.IR recipient ] -.I account +.I + account +.RI [ username +.RI [ password ]] .B amngrcrypt +.RB [ -h ] .RB [ -r .IR recipient ] .I password .B amngrdelete +.RB [ -h ] +.RB [ -D +.IR dbfile ] .I account .B amngrgen +.RB [ -h ] .RB [ -r .IR recipient ] .RI [ len ] .B amngrgetoldpass +.RB [ -h ] +.RB [ -D +.IR dbfile ] .I account .B amngrgetolduser +.RB [ -h ] +.RB [ -c ] +.RB [ -D +.IR dbfile ] .I account .B amngrgetpass +.RB [ -h ] +.RB [ -D +.IR dbfile ] .I account +.RI [ state ] .B amngrgetuser +.RB [ -h ] +.RB [ -c ] +.RB [ -D +.IR dbfile ] .I account +.RI [ state ] .B amngrid +.RB [ -h ] +.RB [ -D +.IR dbfile ] .I account -.B amngrlist -.RB [ -s -.IR separator ] - .B amngrrename +.RB [ -h ] +.RB [ -D +.IR dbfile ] .I old_account new_account .B amngrsearch +.RB [ -h ] +.RB [ -D +.IR dbfile ] .RB [ -s .IR separator ] -.I pattern +.RI [ pattern ] .SH DESCRIPTION This file can either be source into the current shell or used as a standalone shell script via the provided symlinks. When used as standalone @@ -116,7 +134,7 @@ pair. \fBrandom\fR Takes no arguments and connect a non blocking random source to stdout. .TP -\fBrand_printable\fR [\fIlen\fR] +\fBrand_printable\fR [\fB-h\fR] [\fIlen\fR] Uses \fBrandom\fR to write a string of random printable characters to stdout. All control characters ASCII-0 to ASCII-37 as well as ASCII-177 to 255, single and double quotes are filtered. The single @@ -126,100 +144,114 @@ documents used to communicate with the SQLite database. The optional \fIlen\fR argument specifies the string length to be written and defaults to 512. .TP -\fBamngrdbinit\fR [\fIdbfile\fR] +\fBamngrdbinit\fR [\fB-h\fR] [\fIdbfile\fR] Create the SQLite database file. If the optional \fIdbfile\fR argument is given it specifies the fill path to the file to use, else the value of \fB$AMNGRDB\fR environment variable is used. .TP -\fBamngrdbdestroy\fR [\fIdbfile\fR] +\fBamngrdbdestroy\fR [\fB-h\fR] [\fIdbfile\fR] Deletes the SQLite database file. If the optional \fIdbfile\fR argument is given it specifies the fill path to the file to use, else the value of \fB$AMNGRDB\fR environment variable is used. .TP -\fBamngradd\fR \fB-u\fR \fIusername\fR \fB-p\fR \fIpassword\fR \ -[\fB-d\fR \fIdescription\fR] [\fB-D\fR \fIdbfile\fR] \ -[\fB-r\fR \fIrecipient\fR] \fIaccount\fR +\fBamngradd\fR [\fB-h\fR] [\fB-d\fR \fIdescription\fR] \ +[\fB-D\fR \fIdbfile\fR] [\fB-r\fR \fIrecipient\fR] +.TQ + \fIaccount\fR [\fIusername\fR [\fIpassword\fR]] Adds an account credential and marks it as active. If the account already exist, the credential (\fIusername\fR and \fIpassword\fR) is added to that account and the previously added credential is marked as old. If there was another even older credential that was already marked as old -this will be marked as inactive and this becomes inaccessible with +this will be marked as inactive and thus becomes inaccessible with this tools (except for \fBamngrdelete\fR). - The necessary option \fB-u\fR specifies the username to be stored with -this credential pair. - The also necessary option \fB-p\fR specifies the password to be stored -and the length of \fIpassword\fR is not limited at all. - With option \fB-d\fR one can add a \fIdescription\fR to the account entry. -One can specify the \fIdbfile\fR with the option \fB-D\fR if that option is + The \fIusername\fR and the \fIaccount\fR name must not be longer than 128 +characters. The \fIpassword\fR is not limited in its length at all. If +\fIpassword\fR is omitted one will be generated with \fBamngrgen\fR. The +\fIusername\fR may also be omitted if there was a previously added credentials +pair for this account. In that case the previous username is taken. It is +a failure to provide a \fIpassword\fR without a \fIusername\fR. There is no +way for the script to detect this condition and you will end up with a +credential where the username is the password and the password was generated. + Option \fB-d\fR adds a \fIdescription\fR to the account entry and +option \fB-D\fR specifys the \fIdbfile\fR to use. If that option is not given the \fB$AMNGRDB\fR environment variable is used. + If a password was generated with this call it will be stored in the +X clipboard. .TP -\fBamngrcreate\fR \fB-u\fR \fIusername\fR [\fB-d\fR \fIdescription\fR] \ -[\fB-D\fR \fIdbfile\fR] [\fB-r\fR \fIrecipient\fR] \fIaccount\fR - This will create a password with \fBamngrgen\fR and use that to add an -credential via \fBamngradd\fR. (See there for options description) - The added password will be copied to the X clipboard with -\fBamngrgetpass\fR for further use. -.TP -\fBamngrcrypt\fR [\fB-r\fR \fIrecipient\fR] \fIpassword\fR +\fBamngrcrypt\fR [\fB-h\fR] [\fB-r\fR \fIrecipient\fR] \fIpassword\fR Crypt the given plain text \fIpassword\fR with GnuPG and write it to stdout. The option \fB-r\fR specifies the recipient to use with the call to \fBgpg\fR. If it is not given the value of the \fB$AMNGRID\fR environment variable is used. .TP -\fBamngrdelete\fR \fIaccount\fR +\fBamngrdelete\fR [\fB-h\fR] [\fB-D\fR \fIdbfile\fR] \fIaccount\fR Remove the \fIaccount\fR and all credential associated to it. .TP -\fBamngrgen\fR [\fB-r\fR \fIreceipient\fR] [\fIlen\fR] +\fBamngrgen\fR [\fB-h\fR] [\fB-r\fR \fIreceipient\fR] [\fIlen\fR] Generate a password with \fBrand_printable\fR and encrypt it via \fBamngrcrypt\fR. By default the password will be 10 characters long. That can be modified by the optional \fIlen\fR argument. .TP -\fBamngrgetoldpass\fR \fIaccount\fR +\fBamngrgetoldpass\fR [\fB-h\fR] [\fB-D\fR \fIdbfile\fR] \fIaccount\fR Read and decrypt the password associated with \fIaccount\fR that is flagged as old and store it into the X clipboard. .TP -\fBamngrgetolduser\fR \fIaccount\fR +\fBamngrgetolduser\fR [\fB-h\fR] [\fB-c\fR] [\fB-D\fR \fIdbfile\fR] \ +\fIaccount\fR Read and decrypt the username associated with \fIaccount\fR that is flagged as old and store it into the X clipboard. .TP -\fBamngrgetpass\fR \fIaccount\fR +\fBamngrgetpass\fR [\fB-h\fR] [\fB-D\fR \fIdbfile\fR] \fIaccount\fR \ +[\fIstate\fR] Read and decrypt the password associated with \fIaccount\fR that is -flagged as active and store it into the X clipboard. +flagged as active and store it into the X clipboard. The \fIstate\fR +argument might be either 1 or 2 where 1 means get the current credential +and 2 means get the old credential. It defaults to 1. .TP -\fBamngrgetuser\fR \fIaccount\fR +\fBamngrgetuser\fR [\fB-h\fR] [\fB-c\fR] [\fB-D\fR \fIdbfile\fR] \ +\fIaccount\fR \ +[\fIstate\fR] Read and decrypt the username associated with \fIaccount\fR that is -flagged as active and store it into the X clipboard. +flagged as active and store it into the X clipboard. The \fIstate\fR +argument might be either 1 or 2 where 1 means get the current credential +and 2 means get the old credential. It defaults to 1. .TP -\fBamngrid\fR \fIaccount\fR +\fBamngrid\fR [\fB-h\fR] [\fB-D\fR \fIdbfile\fR] \fIaccount\fR (This is primarily for internal use.) Get the database id associated to the given \fIaccount\fR argument. .TP -\fBamngrlist\fR [\fB-s\fR \fIseparator\fR] - List all accounts currently stored within the database the output -will contain the name of the account, the username and the description -delimited by a \fIseparator\fR string that can be specified with the -\fB-s\fR option. If the option is omitted the separator is " => ". Each -row is one account. -.TP -\fBamngrrename\fR \fIold_account\fR \fInew_account\fR +\fBamngrrename\fR [\fB-h\fR] [\fB-D\fR \fIdbfile\fR] \fIold_account\fR \ +\fInew_account\fR Rename the account specified by \fIold_account\fR to \fInew_account\fR. .TP -\fBamngrsearch\fR [\fB-s\fR \fIseparator\fR] \fIpattern\fR - List accounts where \fIpattern\fR exists in either the account name, the -username or the account description. The output is like the one -described with \fBamngrlist\fR. +\fBamngrsearch\fR [\fB-h\fR] [\fB-D\fR \fIdbfile\fR] \ +[\fB-s\fR \fIseparator\fR] [\fIpattern\fR] + List all accounts where \fIpattern\fR exists in either the account name, the +username or the account description. The output will contain the name of the +account, the username and the description delimited by a \fIseparator\fR +string that can be specified with the \fB-s\fR option. If the option is +omitted the separator is " => ". Each row is one account. + If \fIpattern\fR is omitted all accounts will be listed. .SH OPTIONS The options are consistent over all sub commands. However not all sub commands use all options and some sub commands take arguments that other get per option. (See \fBDESCRIPTION\fR) .TP +.B -h +Write a short usage information. +.TP .B -u The login username of the credential for the account. .TP .B -p The plain text password of the credential for the account. .TP +.B -c +By default this scripts stores the username into the X clipboard whith +\fBambgrgetuser\fR and \fBamngrgetolduser\fR. When \fB-c\fR is given +the username is written to stdout. The password is never written to stdout. +.TP .B -d The description for the account. .TP @@ -232,7 +264,7 @@ Select a recipient id for GnuPG encryption to use instead of the one defined in the \fB$AMNGRID\fR environment variable. .TP .B -s -The column separator for the \fBamngrlist\fR and \fBamngrsearch\R commands. +The column separator for the \fBamngrlist\fR and \fBamngrsearch\fR commands. .SH ENVIRONMENT .TP .B AMNGRDB @@ -246,7 +278,8 @@ both public and private key. Failure to do so will result in not decipherable data. This can be overruled with the \fB-r\fR command line option. .TP .B AMNGRPWLEN - The password length to be used when generating new passwords. + The password length to be used when generating new passwords. If not +specified this defaults to 10. .SH DEPENDENCIES A set of POSIX compliant shell utilities including a POSIX compliant shell as well are needed to run this script. @@ -274,7 +307,7 @@ comes from the use of foreign key constraints. .IP \[bu] \fBcat\fR .IP \[bu] -\fBdnsdomainname\fR +\fBdirname\fR .IP \[bu] \fBecho\fR .IP \[bu] diff --git a/doc/accountmanager.1.bz2 b/doc/accountmanager.1.bz2 new file mode 100644 index 0000000..ec81bf9 Binary files /dev/null and b/doc/accountmanager.1.bz2 differ