freedombone-recoverkey 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #!/bin/bash
  2. #
  3. # .---. . .
  4. # | | |
  5. # |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-.
  6. # | | (.-' (.-' ( | ( )| | | | )( )| | (.-'
  7. # ' ' --' --' -' - -' ' ' -' -' -' ' - --'
  8. #
  9. # Freedom in the Cloud
  10. #
  11. # A script which recovers a user's gpg key from a number of fragments
  12. # License
  13. # =======
  14. #
  15. # Copyright (C) 2015-2016 Bob Mottram <bob@robotics.uk.to>
  16. #
  17. # This program is free software: you can redistribute it and/or modify
  18. # it under the terms of the GNU Affero General Public License as published by
  19. # the Free Software Foundation, either version 3 of the License, or
  20. # (at your option) any later version.
  21. #
  22. # This program is distributed in the hope that it will be useful,
  23. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. # GNU Affero General Public License for more details.
  26. #
  27. # You should have received a copy of the GNU Affero General Public License
  28. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  29. PROJECT_NAME='freedombone'
  30. export TEXTDOMAIN=${PROJECT_NAME}-recoverkey
  31. export TEXTDOMAINDIR="/usr/share/locale"
  32. FRIENDS_SERVERS_LIST=
  33. MY_USERNAME=
  34. GPG_USB_DRIVE='sdb1'
  35. function show_help {
  36. echo ''
  37. echo $"${PROJECT_NAME}-recoverkey -u [username] -d [drive]"
  38. echo $' -l [friends servers list filename]'
  39. echo ''
  40. exit 0
  41. }
  42. while [[ $# > 1 ]]
  43. do
  44. key="$1"
  45. case $key in
  46. -h|--help)
  47. show_help
  48. ;;
  49. -u|--user)
  50. shift
  51. MY_USERNAME="$1"
  52. ;;
  53. # backup list filename
  54. # typically /home/$USER/backup.list
  55. -l|--list)
  56. shift
  57. FRIENDS_SERVERS_LIST="$1"
  58. ;;
  59. -d|--drive)
  60. shift
  61. GPG_USB_DRIVE=/dev/${1}1
  62. ;;
  63. *)
  64. # unknown option
  65. ;;
  66. esac
  67. shift
  68. done
  69. if [ ! $MY_USERNAME ]; then
  70. show_help
  71. fi
  72. if [ ! -d /home/$MY_USERNAME ]; then
  73. echo $"User $MY_USERNAME does not exist on the system"
  74. exit 7270
  75. fi
  76. if [ ! $MY_USERNAME ]; then
  77. echo $'No username given'
  78. exit 3578
  79. fi
  80. if [ ! -d /home/$MY_USERNAME ]; then
  81. echo $"User $MY_USERNAME does not exist on the system"
  82. exit 7270
  83. fi
  84. FRAGMENTS_DIR=/home/$MY_USERNAME/.gnupg_fragments
  85. function reconstruct_key {
  86. if [ ! -d /home/$MY_USERNAME/.gnupg_fragments ]; then
  87. return
  88. fi
  89. cd /home/$MY_USERNAME/.gnupg_fragments
  90. no_of_shares=$(ls -afq keyshare.asc.* | wc -l)
  91. if (( no_of_shares < 4 )); then
  92. dialog --title $"Encryption keys" --msgbox $'Not enough fragments to reconstruct the key' 6 70
  93. exit 7348
  94. fi
  95. apt-get -y install libgfshare-bin gnupg
  96. gfcombine /home/$MY_USERNAME/.gnupg_fragments/keyshare*
  97. if [ ! "$?" = "0" ]; then
  98. dialog --title $"Encryption keys" --msgbox $'Unable to reconstruct the key' 6 70
  99. exit 7348
  100. fi
  101. KEYS_FILE=/home/$MY_USERNAME/.gnupg_fragments/keyshare.asc
  102. if [ ! -f $KEYS_FILE ]; then
  103. dialog --title $"Encryption keys" --msgbox $'Unable to reconstruct the key' 6 70
  104. fi
  105. su -c "gpg --allow-secret-key-import --import $KEYS_FILE" - $MY_USERNAME
  106. if [ ! "$?" = "0" ]; then
  107. echo $'Unable to import gpg key'
  108. shred -zu $KEYS_FILE
  109. rm -rf /home/$MY_USERNAME/.tempgnupg
  110. exit 9654
  111. fi
  112. shred -zu $KEYS_FILE
  113. dialog --title $"Encryption keys" --msgbox $'Key has been reconstructed' 6 70
  114. }
  115. function interactive_gpg_from_usb {
  116. dialog --title $"Encryption keys" \
  117. --msgbox $'Plug in a USB drive containing a copy of your full key or key fragment' 6 70
  118. HOME_DIR=/home/$MY_USERNAME
  119. GPG_LOADING="yes"
  120. SSH_IMPORTED="no"
  121. GPG_CTR=0
  122. while [[ $GPG_LOADING == "yes" ]]
  123. do
  124. if [ ! -b $GPG_USB_DRIVE ]; then
  125. GPG_USB_DRIVE='/dev/sdc1'
  126. if [ ! -b $GPG_USB_DRIVE ]; then
  127. GPG_USB_DRIVE='/dev/sdd1'
  128. if [ ! -b $GPG_USB_DRIVE ]; then
  129. if (( GPG_CTR > 0 )); then
  130. reconstruct_key
  131. return 0
  132. fi
  133. dialog --title $"Encryption keys" --msgbox $'No USB drive found' 6 30
  134. exit 27852
  135. fi
  136. fi
  137. fi
  138. GPG_USB_MOUNT='/mnt/usb'
  139. umount -f $GPG_USB_MOUNT
  140. if [ ! -d $GPG_USB_MOUNT ]; then
  141. mkdir -p $GPG_USB_MOUNT
  142. fi
  143. if [ -f /dev/mapper/encrypted_usb ]; then
  144. rm -rf /dev/mapper/encrypted_usb
  145. fi
  146. cryptsetup luksClose encrypted_usb
  147. cryptsetup luksOpen $GPG_USB_DRIVE encrypted_usb
  148. if [ "$?" = "0" ]; then
  149. GPG_USB_DRIVE=/dev/mapper/encrypted_usb
  150. fi
  151. mount $GPG_USB_DRIVE $GPG_USB_MOUNT
  152. if [ ! "$?" = "0" ]; then
  153. if (( GPG_CTR > 0 )); then
  154. rm -rf $GPG_USB_MOUNT
  155. reconstruct_key
  156. return 0
  157. fi
  158. dialog --title $"Encryption keys" \
  159. --msgbox $"There was a problem mounting the USB drive to $GPG_USB_MOUNT" 6 70
  160. rm -rf $GPG_USB_MOUNT
  161. exit 74393
  162. fi
  163. if [ ! -d $GPG_USB_MOUNT/.gnupg ]; then
  164. if [ ! -d $GPG_USB_MOUNT/.gnupg_fragments ]; then
  165. if (( GPG_CTR > 0 )); then
  166. umount -f $GPG_USB_MOUNT
  167. rm -rf $GPG_USB_MOUNT
  168. reconstruct_key
  169. return 0
  170. fi
  171. dialog --title $"Encryption keys" \
  172. --msgbox $"The directory $GPG_USB_MOUNT/.gnupg or $GPG_USB_MOUNT/.gnupg_fragments was not found" 6 70
  173. umount -f $GPG_USB_MOUNT
  174. rm -rf $GPG_USB_MOUNT
  175. exit 723814
  176. fi
  177. fi
  178. if [ -d $GPG_USB_MOUNT/.gnupg ]; then
  179. if [ ! -d $HOME_DIR/.gnupg ]; then
  180. mkdir $HOME_DIR/.gnupg
  181. fi
  182. cp -r $GPG_USB_MOUNT/.gnupg/* $HOME_DIR/.gnupg
  183. GPG_LOADING="no"
  184. dialog --title $"Encryption keys" \
  185. --msgbox $"GPG Keyring loaded to $HOME_DIR" 6 70
  186. else
  187. if [ ! -d $HOME_DIR/.gnupg_fragments ]; then
  188. mkdir $HOME_DIR/.gnupg_fragments
  189. fi
  190. cp -r $GPG_USB_MOUNT/.gnupg_fragments/* $HOME_DIR/.gnupg_fragments
  191. fi
  192. if [[ $SSH_IMPORTED == "no" ]]; then
  193. if [ -d $GPG_USB_MOUNT/.ssh ]; then
  194. if [ ! -d $HOME_DIR/.ssh ]; then
  195. mkdir $HOME_DIR/.ssh
  196. fi
  197. cp $GPG_USB_MOUNT/.ssh/* $HOME_DIR/.ssh
  198. dialog --title $"Encryption keys" \
  199. --msgbox $"ssh keys imported" 6 70
  200. SSH_IMPORTED="yes"
  201. fi
  202. fi
  203. umount -f $GPG_USB_MOUNT
  204. rm -rf $GPG_USB_MOUNT
  205. if [[ $GPG_LOADING == "yes" ]]; then
  206. dialog --title $"Encryption keys" \
  207. --msgbox $"Now remove the USB drive. Insert the next drive containing a key fragment, or select Ok to finish" 6 70
  208. fi
  209. GPG_CTR=$((GPG_CTR + 1))
  210. done
  211. }
  212. # if no remote backup list was given then assume recover from USB
  213. if [ ! $FRIENDS_SERVERS_LIST ]; then
  214. interactive_gpg_from_usb
  215. exit 0
  216. fi
  217. # obtain shares/fragments from remote locations
  218. if [ $FRIENDS_SERVERS_LIST ]; then
  219. # For each remote server
  220. while read remote_server
  221. do
  222. # Get the server and its password
  223. # Format is:
  224. # username@domain:/home/username <port number> <ssh password>
  225. REMOTE_SERVER=$(echo "${remote_server}" | awk -F ' ' '{print $1}')
  226. if [ $REMOTE_SERVER ]; then
  227. REMOTE_SSH_PORT=$(echo "${remote_server}" | awk -F ' ' '{print $2}')
  228. REMOTE_PASSWORD=$(echo "${remote_server}" | awk -F ' ' '{print $3}')
  229. # create a directory if it doesn't exist
  230. if [ ! -d /home/$MY_USERNAME/.gnupg_fragments ]; then
  231. mkdir -p /home/$MY_USERNAME/.gnupg_fragments
  232. fi
  233. echo -n $"Starting key retrieval from $REMOTE_SERVER..."
  234. /usr/bin/sshpass -p $REMOTE_PASSWORD \
  235. scp -r -P $REMOTE_SSH_PORT $REMOTE_SERVER/.gnupg_fragments/* /home/$MY_USERNAME/.gnupg_fragments
  236. if [ ! "$?" = "0" ]; then
  237. echo $'FAILED'
  238. else
  239. echo $'Ok'
  240. fi
  241. fi
  242. done < $FRIENDS_SERVERS_LIST
  243. fi
  244. # was a directory created?
  245. if [ ! -d $FRAGMENTS_DIR ]; then
  246. echo $'No fragments have been recovered, so the key cannot be recovered'
  247. exit 7483
  248. fi
  249. # was anything downloaded?
  250. cd $FRAGMENTS_DIR
  251. no_of_shares=$(ls -afq keyshare.asc.* | wc -l)
  252. if (( no_of_shares == 0 )); then
  253. echo $'No key fragments were retrieved'
  254. exit 76882
  255. fi
  256. # set permissions on the fragments
  257. chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.gnupg_fragments
  258. # decrypt the file
  259. KEYS_FILE=$FRAGMENTS_DIR/keyshare.asc
  260. cd $FRAGMENTS_DIR
  261. gfcombine $KEYS_FILE.*
  262. if [ ! -f $KEYS_FILE ]; then
  263. echo $'Unable to decrypt key. This may mean that not enough fragments are available'
  264. exit 6283
  265. fi
  266. echo $'Key fragments recombined'
  267. # import the gpg key
  268. su -c "gpg --allow-secret-key-import --import $KEYS_FILE" - $MY_USERNAME
  269. if [ ! "$?" = "0" ]; then
  270. echo $'Unable to import gpg key'
  271. shred -zu $KEYS_FILE
  272. exit 3682
  273. fi
  274. shred -zu $KEYS_FILE
  275. chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.gnupg
  276. chmod -R 600 /home/$MY_USERNAME/.gnupg
  277. echo $'GPG key was recovered'
  278. exit 0