from testing.test_crypto import HeaderTest, AESGCMTest
from testing.test_multivol import MultivolGnuFormatTest, MultivolPaxFormatTest
from testing.test_concat_compress import ConcatCompressTest
-from testing.test_recover import RecoverTest, RecoverGZTest, RecoverGZAESTest
+from testing.test_recover import \
+ RecoverCorruptPayloadTest \
+ , RecoverCorruptPayloadGZTest \
+ , RecoverCorruptPayloadGZAESTest \
+ , RecoverCorruptHeaderGZTest \
+ , RecoverCorruptHeaderGZAESTest
from testing.test_rescue_tar import RescueTarTest
from testing.test_encryption import EncryptionTest
from testing.test_deltatar import (DeltaTarTest, DeltaTar2Test,
, DeltaTarAes128ConcatTest
, HeaderTest, AESGCMTest
# testing.test_recover
- , RecoverTest, RecoverGZTest, RecoverGZAESTest
+ , RecoverCorruptPayloadTest
+ , RecoverCorruptPayloadGZTest
+ , RecoverCorruptPayloadGZAESTest
+ , RecoverCorruptHeaderGZTest
+ , RecoverCorruptHeaderGZAESTest
]:
try:
t = group (n)
return True
+def corrupt_header (_, fname, compress, encrypt):
+ """
+ Modify a significant byte in the object header of the format.
+ """
+ if encrypt is True: # damage GCM tag
+ flip_bits (fname, crypto.HDR_OFF_TAG + 1)
+ elif compress is True: # invalidate magic
+ flip_bits (fname, 1)
+ else: # Fudge checksum. From tar(5):
+ #
+ # struct header_gnu_tar {
+ # char name[100];
+ # char mode[8];
+ # char uid[8];
+ # char gid[8];
+ # char size[12];
+ # char mtime[12];
+ # char checksum[8];
+ # …
+ flip_bits (fname, 100 + 8 + 8 + 8 + 12 + 12 + 1)
+
+
+def corrupt_payload_start (_, fname, compress, encrypt):
+ """
+ Modify the byte following the object header structure of the format.
+ """
+ if encrypt is True:
+ flip_bits (fname, crypto.PDTCRYPT_HDR_SIZE + 1)
+ elif compress is True:
+ flip_bits (fname, gz_header_size (fname) + 1)
+ else:
+ flip_bits (fname, tarfile.BLOCKSIZE + 1)
+
+
+
###############################################################################
## tests ##
###############################################################################
COMPRESSION = None
PASSWORD = None
FAILURES = 0
+ CORRUPT = corrupt_payload_start
def setUp(self):
shutil.rmtree (self.dst_path)
shutil.rmtree (self.src_path)
- if self.PASSWORD is not None:
- flip_bits (backup_full, crypto.PDTCRYPT_HDR_SIZE + 1)
- elif self.COMPRESSION is not None:
- flip_bits (backup_full, gz_header_size (backup_full) + 1)
- else:
- flip_bits (backup_full, tarfile.BLOCKSIZE + 1)
+ self.CORRUPT (backup_full,
+ self.COMPRESSION is not None,
+ self.PASSWORD is not None)
# normal restore must fail
try:
except tarfile.CompressionError:
if self.PASSWORD is not None or self.COMPRESSION is not None:
pass
+ else:
+ raise
except tarfile.ReadError:
- if self.PASSWORD is not None or self.COMPRESSION is not None:
+ # can happen with all three modes
+ pass
+ except tarfile.DecryptionError:
+ if self.PASSWORD is not None:
pass
+ else:
+ raise
os.chdir (self.pwd) # not restored due to the error above
# but recover will succeed
"%s/%s" % (bak_path, index_file)
])
+ print ("¤¤¤ failed", failed)
assert len (failed) == self.FAILURES
# with one file missing
shutil.rmtree (self.dst_path)
-class RecoverGZTest (RecoverTest):
+class RecoverCorruptPayloadTest (RecoverTest):
+ COMPRESSION = None
+ PASSWORD = None
+ FAILURES = 0
+
+
+class RecoverCorruptPayloadGZTest (RecoverTest):
+ COMPRESSION = "#gz"
+ PASSWORD = None
+ FAILURES = 1
+
+
+class RecoverCorruptPayloadGZAESTest (RecoverTest):
+ COMPRESSION = "#gz"
+ PASSWORD = TEST_PASSWORD
+ FAILURES = 1
+
+
+class RecoverCorruptHeaderGZTest (RecoverTest):
COMPRESSION = "#gz"
PASSWORD = None
FAILURES = 1
+ CORRUPT = corrupt_header
-class RecoverGZAESTest (RecoverTest):
+class RecoverCorruptHeaderGZAESTest (RecoverTest):
COMPRESSION = "#gz"
PASSWORD = TEST_PASSWORD
FAILURES = 1
+ CORRUPT = corrupt_header