freedombone-recoverkey 9.3KB

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