filters.encryption.inc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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 (count($options) > 1) {
  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('AES Encryption Module'), 'http://drupal.org/project/aes'))),
  51. );
  52. }
  53. return $form;
  54. }
  55. /**
  56. * Returns a list of backup filetypes.
  57. */
  58. public 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. * Gets the compression options as an options array for a form item.
  70. */
  71. public 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 encrypts a file.
  81. */
  82. public 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
  87. // decrpypt.
  88. $data = pack("a*H2", $data, "80");
  89. if ($data = aes_encrypt($data, FALSE)) {
  90. $dest->put_contents($data);
  91. $success = TRUE;
  92. }
  93. }
  94. }
  95. return $success;
  96. }
  97. /**
  98. * AES decodes a file.
  99. */
  100. public function aes_decrypt($source, $dest) {
  101. $success = FALSE;
  102. if (function_exists('aes_decrypt')) {
  103. if ($data = $source->get_contents()) {
  104. if ($data = aes_decrypt($data, FALSE)) {
  105. // Trim all the padding zeros plus our non-zero marker.
  106. $data = substr(rtrim($data, "\0"), 0, -1);
  107. $dest->put_contents($data);
  108. $success = TRUE;
  109. }
  110. }
  111. }
  112. return $success;
  113. }
  114. /**
  115. * Compresses a file with the given settings.
  116. *
  117. * Also updates settings to reflect new file mime and file extension.
  118. */
  119. public function file_encrypt($file, $settings) {
  120. if (!empty($settings->filters['encryption'])) {
  121. switch ($settings->filters['encryption']) {
  122. case "aes":
  123. $from = $file->push_type('aes');
  124. $from = new backup_file(array('filepath' => $from));
  125. if (!$success = $this->aes_encrypt($from, $file)) {
  126. $file = NULL;
  127. }
  128. break;
  129. }
  130. if (!$file) {
  131. _backup_migrate_message("Could not encrypt backup file. Try backing up without encryption.", array(), 'error');
  132. }
  133. }
  134. return $file;
  135. }
  136. /**
  137. * Decompresses a file with the given settings.
  138. *
  139. * Also updates settings to reflect new file mime and file extension.
  140. */
  141. public function file_decrypt($file) {
  142. $success = FALSE;
  143. if ($file) {
  144. switch ($file->type_id()) {
  145. case "aes":
  146. $from = $file->pop_type();
  147. $success = $this->aes_decrypt($from, $file);
  148. break;
  149. default:
  150. return $file;
  151. }
  152. if (!$success) {
  153. if (function_exists('aes_decrypt')) {
  154. _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');
  155. }
  156. else {
  157. _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');
  158. }
  159. }
  160. }
  161. return $success ? $file : NULL;
  162. }
  163. }