filters.encryption.inc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. var $op_weights = array('backup' => 170, 'restore' => -170);
  13. /**
  14. * This function is called on a backup file after the backup has been completed.
  15. */
  16. function backup($file, &$settings) {
  17. return $this->file_encrypt($file, $settings);
  18. }
  19. /**
  20. * This function is called on a backup file before importing it.
  21. */
  22. function restore($file, &$settings) {
  23. return $this->file_decrypt($file);
  24. }
  25. /**
  26. * Get the form for the settings for this filter.
  27. */
  28. function backup_settings_default() {
  29. return array('encryption' => 'none');
  30. }
  31. /**
  32. * Get the form for the settings for this filter.
  33. */
  34. function backup_settings_form($settings) {
  35. $form = array();
  36. $options = $this->_backup_migrate_get_encryption_form_item_options();
  37. if (count($options) > 1) {
  38. $form['file']['encryption'] = array(
  39. "#type" => "select",
  40. "#title" => t("File Encryption (EXPERIMENTAL)"),
  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. <strong>This functionality is experimental, and should only be used for testing.</strong>'),
  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('AES Encryption Module'), 'http://drupal.org/project/aes'))),
  51. );
  52. }
  53. return $form;
  54. }
  55. /**
  56. * Return a list of backup filetypes.
  57. */
  58. function file_types() {
  59. return array(
  60. "aes" => array(
  61. "extension" => "aes",
  62. "filemime" => "application/octet-stream",
  63. "backup" => TRUE,
  64. "restore" => TRUE,
  65. ),
  66. );
  67. }
  68. /**
  69. * Get the compression options as an options array for a form item.
  70. */
  71. function _backup_migrate_get_encryption_form_item_options() {
  72. $options = array();
  73. $options = array('' => t('No Encryption'));
  74. if (@function_exists("aes_encrypt")) {
  75. $options['aes'] = t("AES Encryption");
  76. }
  77. return $options;
  78. }
  79. /**
  80. * AES encrypt a file.
  81. */
  82. function aes_encrypt($source, $dest) {
  83. $success = FALSE;
  84. if (function_exists('aes_encrypt')) {
  85. if ($data = $source->get_contents()) {
  86. // Add a marker to the end of the data so we can trim the padding on decrpypt.
  87. $data = pack("a*H2", $data, "80");
  88. if ($data = aes_encrypt($data, FALSE)) {
  89. $dest->put_contents($data);
  90. $success = TRUE;
  91. }
  92. }
  93. }
  94. return $success;
  95. }
  96. /**
  97. * Gzip decode a file.
  98. */
  99. function aes_decrypt($source, $dest) {
  100. $success = FALSE;
  101. if (function_exists('aes_decrypt')) {
  102. if ($data = $source->get_contents()) {
  103. if ($data = aes_decrypt($data, FALSE)) {
  104. // Trim all the padding zeros plus our non-zero marker.
  105. $data = substr(rtrim($data, "\0"), 0, -1);
  106. $dest->put_contents($data);
  107. $success = TRUE;
  108. }
  109. }
  110. }
  111. return $success;
  112. }
  113. /**
  114. * Compress a file with the given settings.
  115. * Also updates settings to reflect new file mime and file extension.
  116. */
  117. function file_encrypt($file, $settings) {
  118. if (!empty($settings->filters['encryption'])) {
  119. switch ($settings->filters['encryption']) {
  120. case "aes":
  121. $from = $file->push_type('aes');
  122. $from = new backup_file(array('filepath' => $from));
  123. if (!$success = $this->aes_encrypt($from, $file)) {
  124. $file = NULL;
  125. }
  126. break;
  127. }
  128. if (!$file) {
  129. _backup_migrate_message("Could not encrypt backup file. Try backing up without encryption.", array(), 'error');
  130. }
  131. }
  132. return $file;
  133. }
  134. /**
  135. * Decompress a file with the given settings.
  136. * Also updates settings to reflect new file mime and file extension.
  137. */
  138. function file_decrypt($file) {
  139. $success = FALSE;
  140. if ($file) {
  141. switch ($file->type_id()) {
  142. case "aes":
  143. $from = $file->pop_type();
  144. $success = $this->aes_decrypt($from, $file);
  145. break;
  146. default:
  147. return $file;
  148. break;
  149. }
  150. if (!$success) {
  151. if (function_exists('aes_decrypt')) {
  152. _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');
  153. }
  154. else {
  155. _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');
  156. }
  157. }
  158. }
  159. return $success ? $file : NULL;
  160. }
  161. }