freedombone-recoverkey 10KB

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