passman 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #!/bin/bash
  2. #
  3. # Companion password manager for quickpass.
  4. #
  5. # A few things worth noting before you decide to use this program:
  6. #
  7. # - An accredited security audit has NOT been performed on this program yet.
  8. # - This program relies on GnuPG and a PGP key to perform encryption and
  9. # decryption, so make sure you use a strong (>4000 bits) key!
  10. # - Unlike KeePass, this program does NOT encrypt the RAM it uses, nor does
  11. # it encrypt the entire database. Decide for yourself if this is enough.
  12. #
  13. # Inspired by alimiracles `pm` file.
  14. #
  15. # Copyright (c) 2016 ali abdul ghani <alimiracle@riseup.net>
  16. # Copyright (c) 2016 kzimmermann <kzimmermann@vivaldi.net>
  17. #
  18. # This file is part of quickpass
  19. #
  20. # quickpass is free software: you can redistribute it and/or modify
  21. # it under the terms of the GNU General Public License as published by
  22. # the Free Software Foundation, either version 3 of the License, or
  23. # (at your option) any later version.
  24. # quickpass is distributed in the hope that it will be useful,
  25. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. # GNU General Public License for more details.
  28. # You should have received a copy of the GNU General Public License
  29. # along with quickpass. If not, see <http://www.gnu.org/licenses/>.
  30. #
  31. #-- predefined variables --#
  32. VAULT="$HOME/.quickpassdb"
  33. # change this to a private key available in your keyring.
  34. # you can use any format that gpg accepts, like an email address or fingerprint
  35. RECIPIENT=""
  36. #-- /predefined variables --#
  37. #-- Function definitions --
  38. error() {
  39. # shorthand for a quit-due-to-error message.
  40. echo "Error: $1"
  41. exit 1
  42. }
  43. helper() {
  44. cat <<EOF
  45. $(basename $0): a password manager for quickpass.
  46. USAGE $(basename $0) COMMAND [ARGUMENT]
  47. COMMANDS are:
  48. -h, --help: this help message.
  49. -n, --new [SERVICE NAME]: creates a new entry in the vault using quickpass.
  50. -r, --read [SERVICE NAME]: decrypts and reads the entry for [SERVICE NAME].
  51. -d, --delete [SERVICE NAME]: deletes entry for [SERVICE NAME].
  52. -l, --list: lists all available password entries.
  53. -L, --length [N]: generates passwords of N characters long instead of 32.
  54. EOF
  55. if [[ -n "$RECIPIENT" ]]
  56. then
  57. cat <<EOF
  58. The current recipient (user) is: $RECIPIENT.
  59. $(gpg --list-keys $RECIPIENT)
  60. EOF
  61. else
  62. echo "Error: you have not specified a recipient (vault user) yet."
  63. echo "Please change the line RECIPIENT=\"\" to your gpg key to use it."
  64. exit 1
  65. fi
  66. }
  67. create_db() {
  68. # create a db if there's none available.
  69. if [[ ! -f "$VAULT" ]]
  70. then
  71. sqlite3 "$VAULT" "
  72. CREATE TABLE IF NOT EXISTS entries (
  73. service TEXT PRIMARY KEY,
  74. password TEXT
  75. )"
  76. echo "New password vault created at $VAULT"
  77. else
  78. echo "A password vault already exists at $VAULT."
  79. fi
  80. }
  81. new_entry() {
  82. # add a new row in the password database.
  83. service="$1"
  84. if [[ -z "$LENGTH" ]]
  85. then
  86. encrypted=$(quickpass -p | gpg -a -e -r $RECIPIENT)
  87. else
  88. encrypted=$(quickpass -p -l $LENGTH | gpg -a -e -r $RECIPIENT)
  89. fi
  90. sqlite3 "$VAULT" "
  91. INSERT INTO entries (service, password)
  92. VALUES ('$service', '$encrypted')" || error "could not insert into vault..."
  93. if [[ -z "$LENGTH" ]]
  94. then
  95. echo "Created 1 new password entry for service '$service'"
  96. else
  97. echo "Created 1 new password $LENGTH characters long for service '$service'"
  98. fi
  99. }
  100. delete_entry() {
  101. # remove a row from the database.
  102. sanity=$(sqlite3 "$VAULT" "
  103. SELECT service FROM entries
  104. WHERE service = '$1'
  105. ")
  106. [[ -z "$sanity" ]] && error "entry '$1' not found"
  107. printf "Would you like to delete entry '$1'? (y/n) "
  108. read decision
  109. if [[ "$decision" == "y" ]]
  110. then
  111. sqlite3 "$VAULT" "
  112. DELETE FROM entries
  113. WHERE service = '$1'
  114. "
  115. echo "Entry '$1' deleted."
  116. else
  117. echo "Aborted."
  118. exit 1
  119. fi
  120. }
  121. read_entry() {
  122. # return a decrypted row from the database
  123. encrypted=$(sqlite3 "$VAULT" "
  124. SELECT password FROM entries
  125. WHERE service = '$1'
  126. ")
  127. if [[ -n "$encrypted" ]]
  128. then
  129. echo "Unlock your key to obtain the password"
  130. printf %b "$encrypted" | gpg --decrypt | xsel -i -b
  131. echo "Password copied to the clipboard."
  132. printf "Clearing automatically in "
  133. for i in $(seq 1 10)
  134. do
  135. printf "$(expr 11 - $i)... "
  136. sleep 1
  137. done
  138. echo $RANDOM | xsel -i -b
  139. echo "** Cleared. **"
  140. else
  141. echo "Entry $1 doesn't exist in the vault."
  142. echo "Use '--list' to see all available entries."
  143. exit 1
  144. fi
  145. }
  146. list_entry() {
  147. # list all available entries from the database:
  148. echo "You have the following password entries available here:"
  149. sqlite3 "$VAULT" "SELECT service FROM entries"
  150. }
  151. #-- /Function definitions --
  152. [[ -z $(which sqlite3) ]] && error "sqlite3 not found."
  153. [[ -z $(which gpg) ]] && error "gpg not found."
  154. [[ -z "$RECIPIENT" ]] && helper
  155. [[ ! -f "$VAULT" ]] && create_db
  156. # We can only perform an action at a time. Sorry.
  157. action=""
  158. while [[ -n "$1" ]]
  159. do
  160. case "$1" in
  161. "-h" | "--help" )
  162. helper
  163. exit 0
  164. ;;
  165. "-n" | "--new" )
  166. [[ -n "$action" ]] && error "one action at a time only."
  167. action="new"
  168. shift
  169. [[ -z "$1" ]] && error "Missing arguments. See --help"
  170. token="$1"
  171. ;;
  172. "-r" | "--read" )
  173. [[ -n "$action" ]] && error "one action at a time only."
  174. action="read"
  175. shift
  176. [[ -z "$1" ]] && error "Missing arguments. See --help"
  177. token="$1"
  178. ;;
  179. "-d" | "--delete" )
  180. [[ -n "$action" ]] && error "one action at a time only."
  181. action="delete"
  182. shift
  183. [[ -z "$1" ]] && error "Missing arguments. See --help"
  184. token="$1"
  185. ;;
  186. "-l" | "--list" )
  187. list_entry
  188. exit 0
  189. ;;
  190. "-L" | "--length" )
  191. shift
  192. [[ -z "$1" ]] && error "Missing arguments. See --help"
  193. LENGTH="$1"
  194. ;;
  195. * )
  196. echo "Unknown option '$1'"
  197. exit 1
  198. ;;
  199. esac
  200. shift
  201. done
  202. # No argument?
  203. if [[ -z "$action" ]]
  204. then
  205. echo "No action specified to proceed."
  206. helper
  207. exit 1
  208. fi
  209. case "$action" in
  210. "new" )
  211. new_entry "$token"
  212. ;;
  213. "read" )
  214. read_entry "$token"
  215. ;;
  216. "delete" )
  217. delete_entry "$token"
  218. ;;
  219. esac