return path
- def initialize_encryption (self, mode):
+ def initialize_encryption (self, mode, strict_validation=True):
+ """
+ :type strict_validation: bool
+ :param strict_validation: Enable strict IV checking in the crypto
+ layer. Should be disabled when dealing with
+ potentially corrupted data.
+ """
password = self.password
key = self.crypto_key
nacl = self.nacl
version=self.crypto_version,
paramversion=self.crypto_paramversion)
if mode == CRYPTO_MODE_DECRYPT:
- return crypto.Decrypt (password=password, key=key)
+ return crypto.Decrypt (password=password, key=key,
+ strict_ivs=strict_validation)
raise Exception ("invalid encryption mode [%r]" % mode)
- def open_auxiliary_file(self, path, mode='r', kind=AUXILIARY_FILE_INDEX):
+ def open_auxiliary_file(self, path, mode='r', kind=AUXILIARY_FILE_INDEX,
+ strict_validation=True):
'''
Given the specified configuration, opens a file for reading or writing,
inheriting the encryption and compression settings from the backup.
if mode == "w":
crypto_ctx = self.initialize_encryption (CRYPTO_MODE_ENCRYPT)
elif mode == "r":
- crypto_ctx = self.initialize_encryption (CRYPTO_MODE_DECRYPT)
+ crypto_ctx = self.initialize_encryption (CRYPTO_MODE_DECRYPT,
+ strict_validation=strict_validation)
if crypto_ctx is not None:
if kind == AUXILIARY_FILE_INFO:
index_sink.close()
- def iterate_index_path(self, index_path):
+ def iterate_index_path(self, index_path, strict_validation=True):
'''
Returns an index iterator. Internally, it uses a classic iterator class.
We do that instead of just yielding so that the iterator object can have
Allows this iterator to be used with the "with" statement
'''
if self.f is None:
- self.f = self.delta_tar.open_auxiliary_file(self.index_path, 'r')
+ self.f = self.delta_tar.open_auxiliary_file \
+ (self.index_path,
+ 'r',
+ strict_validation=strict_validation)
# check index header
j, l_no = self.delta_tar._parse_json_line(self.f, 0)
if j.get("type", '') != 'python-delta-tar-index' or\
if self.delta_tar.password is not None:
decryptor = crypto.Decrypt \
(password=self.delta_tar.password,
- key=self.delta_tar.crypto_key)
+ key=self.delta_tar.crypto_key,
+ strict_ivs=False)
self.tar_obj = tarfile.TarFile.open(self.tar_path,
mode='r' + self.delta_tar.mode,
format=tarfile.GNU_FORMAT,
tarobj.open_volume(volume_path, encryption=encryption)
if self.decryptor is None:
- self.decryptor = self.initialize_encryption (CRYPTO_MODE_DECRYPT)
+ self.decryptor = \
+ self.initialize_encryption (CRYPTO_MODE_DECRYPT,
+ strict_validation=False)
backup_path = os.path.dirname(backup_tar_path)
if not os.path.isabs(backup_path):
def restore_backup(self, target_path, backup_indexes_paths=[],
backup_tar_path=None, restore_callback=None,
- disaster=tarfile.TOLERANCE_STRICT, backup_index=None):
+ disaster=tarfile.TOLERANCE_STRICT, backup_index=None,
+ strict_validation=True):
'''
Restores a backup.
# setup for decrypting payload
if self.decryptor is None:
- self.decryptor = self.initialize_encryption (CRYPTO_MODE_DECRYPT)
+ self.decryptor = \
+ self.initialize_encryption (CRYPTO_MODE_DECRYPT,
+ strict_validation=strict_validation)
if mode == 'tar':
index_it = self.iterate_tar_path(backup_tar_path)
try:
# get iterator from newest index at _data[0]
index1 = helper._data[0]["path"]
- index_it = self.iterate_index_path(index1)
+ index_it = \
+ self.iterate_index_path(index1,
+ strict_validation=strict_validation)
except tarfile.DecryptionError as exn:
self.logger.error("failed to decrypt file [%s]: %s; is this an "
"actual encrypted index file?"
backup_index=backup_index,
disaster=disaster)
+ index_decryptor = helper._data[0]["decryptor"]
dir_it = self._recursive_walk_dir('.')
dir_path_it = self.jsonize_path_iterator(dir_it)
"""
return self.restore_backup(target_path,
backup_indexes_paths=backup_indexes_paths,
- disaster=tarfile.TOLERANCE_RECOVER)
+ disaster=tarfile.TOLERANCE_RECOVER,
+ strict_validation=False)
def rescue_backup(self, target_path, backup_tar_path,
return self.restore_backup(target_path,
backup_index=backup_index,
backup_tar_path=backup_tar_path,
- disaster=tarfile.TOLERANCE_RESCUE)
+ disaster=tarfile.TOLERANCE_RESCUE,
+ strict_validation=False)
def _parse_json_line(self, f, l_no):
self._decryptors = []
self._disaster = disaster
+ # Disable strict checking for linearly increasing IVs when running
+ # in rescue or recover mode.
+ strict_validation = disaster == tarfile.TOLERANCE_STRICT
+
try:
import grp, pwd
except ImportError:
decryptor = None
if self._password is not None:
decryptor = crypto.Decrypt (password=self._password,
- key=self._crypto_key)
+ key=self._crypto_key,
+ strict_ivs=strict_validation)
# make paths absolute to avoid cwd problems
if not os.path.isabs(index):
self._deltatar.logger.warning('tarfile: %s' % e)
@staticmethod
- def new_volume_handler(deltarobj, cwd, is_full, backup_path, encryption, tarobj, base_name, volume_number):
+ def new_volume_handler(deltarobj, cwd, is_full, backup_path, decryptor, tarobj, base_name, volume_number):
'''
- Handles the new volumes
+ Set up a new volume and perform the tasks necessary for transitioning
+ to the next one.
'''
volume_name = deltarobj.volume_name_func(backup_path, is_full,
volume_number, guess_name=True)
# we convert relative paths into absolute because CWD is changed
if not os.path.isabs(volume_path):
volume_path = os.path.join(cwd, volume_path)
- tarobj.open_volume(volume_path, encryption=encryption)
+
+ tarobj.open_volume(volume_path, encryption=decryptor)
def restore_file(self, file_data, index_data, path, l_no, unprefixed_path):
'''