catch incomplete trailing header in tolerant recovery
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Fri, 11 Aug 2017 09:50:55 +0000 (11:50 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 2 Apr 2018 11:34:09 +0000 (13:34 +0200)
This makes decryption in recovery mode resistant against
malformed trailing data which would otherwise error out for the
entire buffered chunk on account of a decryption failure.

deltatar/deltatar.py
deltatar/tarfile.py

index 1b15a0a..9a96467 100644 (file)
@@ -1382,7 +1382,7 @@ class DeltaTar(object):
             helper = RestoreHelper(self, cwd, backup_path=backup_tar_path,
                                    tarobj=index_it.tar_obj)
         elif mode == "diff":
-            helper = RestoreHelper(self, cwd, backup_indexes_paths)
+            helper = RestoreHelper(self, cwd, backup_indexes_paths, disaster=disaster)
             # get iterator from newest index at _data[0]
             index_it = self.iterate_index_path(helper._data[0]["path"])
 
@@ -1861,7 +1861,8 @@ class RestoreHelper(object):
                     concat='#' in self._deltatar.mode,
                     encryption=index_data["decryptor"],
                     new_volume_handler=index_data['new_volume_handler'],
-                    save_to_members=False)
+                    save_to_members=False,
+                    tolerant=self._disaster)
 
                 member = index_data['tarobj'].__iter__().__next__()
 
index 49678cc..2629e44 100644 (file)
@@ -1017,9 +1017,15 @@ class _Stream:
             if self.arcmode & ARCMODE_ENCRYPT:
                 if self.remainder <= 0:
                     # prepare next object
-                    if self._init_read_encrypt () is False: # EOF
-                        buf = None
-                        break # while
+                    try:
+                        if self._init_read_encrypt () is False: # EOF
+                            buf = None
+                            break # while
+                    except DecryptionError:
+                        if self.tolerant:
+                            self.buf = b"".join (t [good_crypto:])
+                            return b"".join (t [:good_crypto])
+                        raise
 
                 # only read up to the end of the encrypted object
                 todo = min (size, self.remainder)
@@ -2072,7 +2078,7 @@ class TarFile(object):
 
     @classmethod
     def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE,
-             encryption=None, compresslevel=9, **kwargs):
+             encryption=None, compresslevel=9, tolerant=False, **kwargs):
         """Open a tar archive for reading, writing or appending. Return
            an appropriate TarFile class.
 
@@ -2169,7 +2175,7 @@ class TarFile(object):
 
             stream = _Stream(name, filemode, comptype, fileobj, bufsize,
                              concat=True, encryption=encryption,
-                             compresslevel=compresslevel)
+                             compresslevel=compresslevel, tolerant=tolerant)
             kwargs ["concat"] = True
             try:
                 t = cls(name, filemode, stream, **kwargs)