filters.encryption.inc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <?php
  2. /**
  3. * @file
  4. * A filter for encrypting bckups with AES.
  5. */
  6. /**
  7. * A filter for encrypting backup files.
  8. *
  9. * @ingroup backup_migrate_filters
  10. */
  11. class backup_migrate_filter_encryption extends backup_migrate_filter {
  12. public $op_weights = array('backup' => 170, 'restore' => -170);
  13. /**
  14. * Called on a backup file after the backup has been completed.
  15. */
  16. public function backup($file, $settings) {
  17. return $this->file_encrypt($file, $settings);
  18. }
  19. /**
  20. * Called on a backup file before importing it.
  21. */
  22. public function restore($file, $settings) {
  23. return $this->file_decrypt($file);
  24. }
  25. /**
  26. * Gets the form for the settings for this filter.
  27. */
  28. public function backup_settings_default() {
  29. return array('encryption' => 'none');
  30. }
  31. /**
  32. * Gets the form for the settings for this filter.
  33. */
  34. public function backup_settings_form($settings) {
  35. $form = array();
  36. $options = $this->_backup_migrate_get_encryption_form_item_options();
  37. if (array_intersect_key($options, array_flip(array('aes', 'encrypt')))) {
  38. $form['file']['encryption'] = array(
  39. "#type" => "select",
  40. "#title" => t("File Encryption"),
  41. "#options" => $options,
  42. "#default_value" => @$settings['encryption'],
  43. '#description' => t('Encrypted files can only be restored by Backup and Migrate and only on sites with the same encryption key.'),
  44. );
  45. }
  46. else {
  47. $form['file']['encryption'] = array(
  48. "#type" => 'item',
  49. "#title" => t("File Encryption"),
  50. "#markup" => t('Install the !link to enable backup file encryption.', array('!link' => l(t('Encrypt module'), 'http://drupal.org/project/encrypt'))),
  51. );
  52. }
  53. // If the Encrypt method is available add a configuration field.
  54. if (array_key_exists('encrypt', $options)) {
  55. $form['file']['encrypt_config'] = array(
  56. '#type' => 'select',
  57. '#title' => t('Encryption Configuration'),
  58. '#options' => encrypt_get_configs_as_options(),
  59. '#default_value' => @$settings['encrypt_config'],
  60. '#description' => t('Select a configuration to use for encryption.'),
  61. '#states' => array(
  62. 'visible' => array(
  63. ':input[name="filters[encryption]"]' => array('value' => 'encrypt'),
  64. ),
  65. ),
  66. );
  67. }
  68. return $form;
  69. }
  70. /**
  71. * Returns a list of backup filetypes.
  72. */
  73. public function file_types() {
  74. return array(
  75. "aes" => array(
  76. "extension" => "aes",
  77. "filemime" => "application/octet-stream",
  78. "backup" => TRUE,
  79. "restore" => TRUE,
  80. ),
  81. "encrypt" => array(
  82. "extension" => "encrypt",
  83. "filemime" => "application/octet-stream",
  84. "backup" => TRUE,
  85. "restore" => TRUE,
  86. ),
  87. );
  88. }
  89. /**
  90. * Gets the compression options as an options array for a form item.
  91. */
  92. public function _backup_migrate_get_encryption_form_item_options() {
  93. $options = array();
  94. $options = array('' => t('No Encryption'));
  95. if (@function_exists("aes_encrypt")) {
  96. $options['aes'] = t("AES Encryption");
  97. }
  98. if (@function_exists("encrypt")) {
  99. $options['encrypt'] = t("Encryption With Encrypt Module");
  100. }
  101. return $options;
  102. }
  103. /**
  104. * AES encrypts a file.
  105. */
  106. public function aes_encrypt($source, $dest) {
  107. $success = FALSE;
  108. if (function_exists('aes_encrypt')) {
  109. if ($data = $source->get_contents()) {
  110. // Add a marker to the end of the data so we can trim the padding on
  111. // decrpypt.
  112. $data = pack("a*H2", $data, "80");
  113. if ($data = aes_encrypt($data, FALSE)) {
  114. $dest->put_contents($data);
  115. $success = TRUE;
  116. }
  117. }
  118. }
  119. return $success;
  120. }
  121. /**
  122. * AES decodes a file.
  123. */
  124. public function aes_decrypt($source, $dest) {
  125. $success = FALSE;
  126. if (function_exists('aes_decrypt')) {
  127. if ($data = $source->get_contents()) {
  128. if ($data = aes_decrypt($data, FALSE)) {
  129. // Trim all the padding zeros plus our non-zero marker.
  130. $data = substr(rtrim($data, "\0"), 0, -1);
  131. $dest->put_contents($data);
  132. $success = TRUE;
  133. }
  134. }
  135. }
  136. return $success;
  137. }
  138. /**
  139. * Encrypts a file with the Encrypt module.
  140. */
  141. public function encrypt($source, $dest, $settings) {
  142. $success = FALSE;
  143. if (function_exists('encrypt')) {
  144. if (!empty($settings->filters['encrypt_config'])) {
  145. $config_name = $settings->filters['encrypt_config'];
  146. }
  147. else {
  148. $config = encrypt_get_default_config();
  149. $config_name = $config['name'];
  150. }
  151. if ($data = $source->get_contents()) {
  152. // Add a marker to the end of the data so we can trim the padding on decrypt.
  153. $data = pack("a*H2", $data, "80");
  154. if ($data = encrypt($data, array('base64' => FALSE), NULL, NULL, $config_name)) {
  155. $dest->put_contents($data);
  156. $success = TRUE;
  157. }
  158. }
  159. }
  160. return $success;
  161. }
  162. /**
  163. * Decrypts a file with the Encrypt module.
  164. */
  165. public function decrypt($source, $dest) {
  166. $success = FALSE;
  167. if (function_exists('decrypt')) {
  168. if ($data = $source->get_contents()) {
  169. if ($data = decrypt($data)) {
  170. // Trim all the padding zeros plus our non-zero marker.
  171. $data = substr(rtrim($data, "\0"), 0, -1);
  172. $dest->put_contents($data);
  173. $success = TRUE;
  174. }
  175. }
  176. }
  177. return $success;
  178. }
  179. /**
  180. * Encrypts a file with the given settings.
  181. *
  182. * Also updates settings to reflect new file mime and file extension.
  183. */
  184. public function file_encrypt($file, $settings) {
  185. if (!empty($settings->filters['encryption'])) {
  186. switch ($settings->filters['encryption']) {
  187. case "aes":
  188. $from = $file->push_type('aes');
  189. $from = new backup_file(array('filepath' => $from));
  190. if (!$success = $this->aes_encrypt($from, $file)) {
  191. $file = NULL;
  192. }
  193. break;
  194. case "encrypt":
  195. $from = $file->push_type('encrypt');
  196. $from = new backup_file(array('filepath' => $from));
  197. if (!$success = $this->encrypt($from, $file, $settings)) {
  198. $file = NULL;
  199. }
  200. break;
  201. }
  202. if (!$file) {
  203. _backup_migrate_message("Could not encrypt backup file. Try backing up without encryption.", array(), 'error');
  204. }
  205. }
  206. return $file;
  207. }
  208. /**
  209. * Decrypts a file with the given settings.
  210. *
  211. * Also updates settings to reflect new file mime and file extension.
  212. */
  213. public function file_decrypt($file) {
  214. $success = FALSE;
  215. if ($file) {
  216. switch ($file->type_id()) {
  217. case "aes":
  218. $from = $file->pop_type();
  219. $success = $this->aes_decrypt($from, $file);
  220. break;
  221. case "encrypt":
  222. $from = $file->pop_type();
  223. $success = $this->decrypt($from, $file);
  224. break;
  225. default:
  226. return $file;
  227. }
  228. if (!$success) {
  229. switch ($file->type_id()) {
  230. case 'aes':
  231. if (function_exists('aes_decrypt')) {
  232. _backup_migrate_message("Could not decrpyt backup file. Please check that the file is valid and that the encryption key of the server matches the server that created the backup.", array(), 'error');
  233. }
  234. else {
  235. _backup_migrate_message('You must install the !link to restore encrypted backkups.', array('!link' => l(t('AES Encryption Module'), 'http://drupal.org/project/aes')), 'error');
  236. }
  237. break;
  238. case 'encrypt':
  239. if (function_exists('decrypt')) {
  240. _backup_migrate_message("Could not decrypt backup file. Please check that the file is valid and that the encryption key of the server matches the server that created the backup.", array(), 'error');
  241. }
  242. else {
  243. _backup_migrate_message('You must install the !link to restore encrypted backups.', array('!link' => l(t('Encrypt module'), 'http://drupal.org/project/encrypt')), 'error');
  244. }
  245. break;
  246. }
  247. }
  248. }
  249. return $success ? $file : NULL;
  250. }
  251. }