def test_missing_firmware(self): cabarchive = CabArchive() cabarchive['firmware123.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = _get_valid_metainfo() with self.assertRaises(MetadataInvalid): ufile = UploadedFile() ufile.parse('foo.cab', cabarchive.save())
def test_invalid_version_format(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = _get_valid_metainfo(version_format='foo') with self.assertRaises(MetadataInvalid): ufile = UploadedFile() ufile.parse('foo.cab', cabarchive.save())
def _sign_fw(fw): # load the .cab file download_dir = app.config['DOWNLOAD_DIR'] fn = os.path.join(download_dir, fw.filename) try: with open(fn, 'rb') as f: cabarchive = CabArchive(f.read()) except IOError as e: raise NotImplementedError('cannot read %s: %s' % (fn, str(e))) # sign each component in the archive print('Signing: %s' % fn) for md in fw.mds: try: ploader.archive_sign(cabarchive, cabarchive[md.filename_contents]) except KeyError as _: raise NotImplementedError('no {} firmware found'.format(md.filename_contents)) # overwrite old file cab_data = cabarchive.save() with open(fn, 'wb') as f: f.write(cab_data) # inform the plugin loader ploader.file_modified(fn) # update the database fw.checksum_signed = hashlib.sha1(cab_data).hexdigest() fw.signed_timestamp = datetime.datetime.utcnow() db.session.commit()
def test_metainfo_invalid(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = CabFile(b'<compoXXXXnent/>') with self.assertRaises(MetadataInvalid): ufile = UploadedFile() ufile.parse('foo.cab', cabarchive.save())
def test_uncompressed(self): cabarchive = CabArchive() cabarchive['README.txt'] = CabFile(b'foofoofoofoofoofoofoofoo') cabarchive['firmware.bin'] = CabFile(b'barbarbarbarbarbarbarbar') buf = cabarchive.save() self.assertEqual(len(buf), 156) self.assertEqual(hashlib.sha1(buf).hexdigest(), '676654685d6b5918d68081a786ae1d4dbfeb5e01')
def test_autogenerated(self): cabarchive = CabArchive() cabarchive['0x0962_nonsecure.bin'] = _get_valid_firmware() cabarchive['NVM0.metainfo.xml'] = _get_generated_metainfo() ufile = UploadedFile() _add_version_formats(ufile) ufile.parse('foo.cab', cabarchive.save())
def test_compressed(self): cabarchive = CabArchive() cabarchive['README.txt'] = CabFile(b'foofoofoofoofoofoofoofoo') cabarchive['firmware.bin'] = CabFile(b'barbarbarbarbarbarbarbar') buf = cabarchive.save(compress=True) self.assertEqual(len(buf), 122) self.assertEqual(hashlib.sha1(buf).hexdigest(), '74e94703c403aa93b16d01b088eb52e3a9c73288')
def test_invalid_type(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() with self.assertRaises(FileNotSupported): ufile = UploadedFile() _add_version_formats(ufile) ufile.parse('foo.doc', cabarchive.save())
def test_metainfo_missing(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() with self.assertRaises(MetadataInvalid): ufile = UploadedFile() _add_version_formats(ufile) ufile.parse('foo.cab', cabarchive.save())
def test_metadata(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = _get_valid_metainfo() ufile = UploadedFile() ufile.parse('foo.cab', cabarchive.save()) self.assertTrue(ufile.fw.mds[0].inhibit_download) self.assertTrue(ufile.fw.mds[0].version_format == 'quad')
def test_release_date(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = _get_alternate_metainfo() ufile = UploadedFile() _add_version_formats(ufile) ufile.parse('foo.cab', cabarchive.save()) self.assertEqual(ufile.fw.mds[0].release_timestamp, 1562025600)
def test_ddf_fixed(self): arc = CabArchive() with open("data/ddf-fixed.cab", "rb") as f: arc.parse(f.read()) self.assertEqual(len(arc), 2) cff = arc.find_file("*.txt") self.assertEqual(cff.buf, b"test123")
def test_release_mentions_file(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['README.txt'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = \ _get_valid_metainfo(release_description='See README.txt for details.') with self.assertRaises(MetadataInvalid): ufile = UploadedFile() ufile.parse('foo.cab', cabarchive.save())
def test_invalid_bom(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = CabFile(b'\xEF\xBB\xBF<?xml version="1.0" encoding="UTF-8"?>\n' b'<component type="firmware"/>\n') with self.assertRaises(MetadataInvalid): ufile = UploadedFile() _add_version_formats(ufile) ufile.parse('foo.cab', cabarchive.save())
def test_inf_invalid(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = CabFile(b'<component/>') cabarchive['firmware.inf'] = CabFile(b'fubar') with self.assertRaises(MetadataInvalid): ufile = UploadedFile() _add_version_formats(ufile) ufile.parse('foo.cab', cabarchive.save())
def main(): parser = argparse.ArgumentParser(description="Process cabinet archives.") parser.add_argument( "--decompress", action="store_true", help="decompress the archives", default=False, ) parser.add_argument( "--autorepack", action="store_true", help="Repack using cabextract when required", default=False, ) parser.add_argument( "--info", action="store_true", help="Show the files inside the archive", default=True, ) parser.add_argument( "--outdir", type=str, help="Specify the output directory for decompression", default=".", ) if len(sys.argv) == 1: print("No input files given") return 1 args, argv = parser.parse_known_args() for arg in argv: arc = CabArchive() try: with open(arg, "rb") as f: arc.parse(f.read()) except NotSupportedError as e: if not args.autorepack: print("Failed to parse: {}; perhaps try --autorepack".format( str(e))) return 1 repack(arc, arg) print("Parsing {}:".format(arg)) if args.info: for fn in arc: print(fn) if args.decompress: for fn in arc: path = os.path.join(args.outdir, fn) os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, "wb") as f: print("Writing {}:".format(fn)) f.write(arc[fn].buf) return 0
def test_valid_path_back(self): cabarchive = CabArchive() cabarchive['DriverPackage\\firmware.bin'] = _get_valid_firmware() cabarchive['DriverPackage\\firmware.metainfo.xml'] = _get_valid_metainfo() ufile = UploadedFile() ufile.parse('foo.cab', cabarchive.save()) cabarchive2 = ufile.cabarchive_repacked self.assertIsNotNone(cabarchive2['firmware.bin']) self.assertIsNotNone(cabarchive2['firmware.metainfo.xml'])
def test_multi_folder(self): # open a folder with multiple folders arc = CabArchive() with open("data/multi-folder.cab", "rb") as f: arc.parse(f.read()) self.assertEqual(len(arc), 2) cff = arc.find_file("*.txt") self.assertEqual(cff.buf, b"test123")
def test_valid(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = _get_valid_metainfo() ufile = UploadedFile() _add_version_formats(ufile) ufile.parse('foo.cab', cabarchive.save()) cabarchive2 = ufile.cabarchive_repacked self.assertIsNotNone(cabarchive2['firmware.bin']) self.assertIsNotNone(cabarchive2['firmware.metainfo.xml'])
def test_invalid_xml_header(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = CabFile(b'<!-- Copyright 2015 Richard Hughes <*****@*****.**> -->\n' b'<?xml version="1.0" encoding="UTF-8"?>\n' b'<component type="firmware"/>\n') with self.assertRaises(MetadataInvalid): ufile = UploadedFile() _add_version_formats(ufile) ufile.parse('foo.cab', cabarchive.save())
def parse(self, filename, data, use_hashed_prefix=True): # check size self._data_size = len(data) if self._data_size > 104857600: raise FileTooLarge('File too large, limit is 100Mb') if self._data_size < 1024: raise FileTooSmall('File too small, minimum is 1k') # get new filename self.fw.checksum_upload_sha1 = hashlib.sha1(data).hexdigest() self.fw.checksum_upload_sha256 = hashlib.sha256(data).hexdigest() if use_hashed_prefix: self.fw.filename = self.fw.checksum_upload_sha256 + '-' + filename.replace( '.zip', '.cab') else: self.fw.filename = filename.replace('.zip', '.cab') # parse the file try: if filename.endswith('.cab'): self.cabarchive_upload = CabArchive(data, flattern=True) else: self.cabarchive_upload = _repackage_archive(filename, data) except NotImplementedError as e: raise FileNotSupported('Invalid file type: %s' % str(e)) # load metainfo files cabfiles = [ cabfile for cabfile in self.cabarchive_upload.values() if fnmatch.fnmatch(cabfile.filename, '*.metainfo.xml') ] if not cabfiles: raise MetadataInvalid( 'The firmware file had no .metainfo.xml files') # parse each MetaInfo file for cabfile in cabfiles: self._parse_metainfo(cabfile) # verify .inf files if they exists inffiles = [ cabfile for cabfile in self.cabarchive_upload.values() if fnmatch.fnmatch(cabfile.filename, '*.inf') ] for cabfile in inffiles: # add to the archive self.cabarchive_repacked[cabfile.filename] = cabfile # parse if self.enable_inf_parsing: encoding = detect_encoding_from_bom(cabfile.buf) self._parse_inf(cabfile.buf.decode(encoding))
def test_zdict(self): # parse multi folder compressed archive that saves zdict arc = CabArchive() with open("data/multi-folder-compressed.cab", "rb") as f: arc.parse(f.read()) cff = arc["test\\example.jpg"] self.assertEqual( hashlib.sha1(cff.buf).hexdigest(), "60880cf6f2a93616ba8d965bfbca72a56fb736bb", )
def test_valid_with_ignored_inf(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = _get_valid_metainfo(enable_inf_parsing=False) cabarchive['firmware.inf'] = CabFile(b'fubar') ufile = UploadedFile() _add_version_formats(ufile) ufile.parse('foo.cab', cabarchive.save()) cabarchive2 = ufile.cabarchive_repacked self.assertIsNotNone(cabarchive2['firmware.bin']) self.assertIsNotNone(cabarchive2['firmware.metainfo.xml']) self.assertIsNotNone(cabarchive2['firmware.inf'])
def test_simple(self): with open("data/simple.cab", "rb") as f: old = f.read() arc = CabArchive() arc.parse(old) cff = arc["test.txt"] self.assertEqual(cff.filename, "test.txt") self.assertEqual(cff.buf, b"test123") self.assertEqual(len(cff.buf), 7) self.assertEqual(cff.date.year, 2015) _check_range(arc.save(), old)
def test_multiple_metainfo_same_firmware(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware1.metainfo.xml'] = _get_valid_metainfo() cabarchive['firmware2.metainfo.xml'] = _get_valid_metainfo() ufile = UploadedFile() ufile.parse('foo.cab', cabarchive.save()) cabarchive2 = ufile.cabarchive_repacked self.assertIsNotNone(cabarchive2['firmware.bin']) self.assertIsNotNone(cabarchive2['firmware1.metainfo.xml']) self.assertIsNotNone(cabarchive2['firmware2.metainfo.xml'])
def test_extra_files(self): cabarchive = CabArchive() cabarchive['firmware.bin'] = _get_valid_firmware() cabarchive['firmware.metainfo.xml'] = _get_valid_metainfo() cabarchive['README.txt'] = CabFile(b'fubar') ufile = UploadedFile() ufile.parse('foo.cab', cabarchive.save()) cabarchive2 = ufile.cabarchive_repacked self.assertIsNotNone(cabarchive2['firmware.bin']) self.assertIsNotNone(cabarchive2['firmware.metainfo.xml']) with self.assertRaises(KeyError): self.assertIsNotNone(cabarchive2['README.txt'])
def test_create_compressed(self): cabarchive = CabArchive() # make predictable dt_epoch = datetime.datetime.fromtimestamp(0, datetime.timezone.utc) cabarchive["README.txt"] = CabFile(b"foofoofoofoofoofoofoofoo", mtime=dt_epoch) cabarchive["firmware.bin"] = CabFile(b"barbarbarbarbarbarbarbar", mtime=dt_epoch) buf = cabarchive.save(compress=True) self.assertEqual(len(buf), 122) self.assertEqual( hashlib.sha1(buf).hexdigest(), "74e94703c403aa93b16d01b088eb52e3a9c73288")
def test_checksums(self): with open('contrib/hughski-colorhug2-2.0.3.cab', 'rb') as f: cabarchive = CabArchive(f.read()) results = { 'firmware.bin' : 'c57c7de8f7029acc44a4bfad6efd6ab0a7092cc6', 'firmware.inf' : 'b0cb43bfb2f55fd15a8814c5c5c7b9f2ce2f4572', 'firmware.metainfo.xml' : 'e69b16c9d6ad67db52029f9db8f4e077d19c2558', } for fn in results: self.assertTrue(hashlib.sha1(cabarchive[fn].buf).hexdigest() == results[fn])
def test_values(self): # parse junk with self.assertRaises(CorruptionError): CabArchive().parse(b"hello") try: self.assertEqual( subprocess.call(["cabextract", "--test", "hello"]), 1) except FileNotFoundError as _: pass
def test_checksums(self): with open('contrib/hughski-colorhug2-2.0.3.cab', 'rb') as f: cabarchive = CabArchive(f.read()) results = { 'firmware.bin': 'c57c7de8f7029acc44a4bfad6efd6ab0a7092cc6', 'firmware.inf': 'b0cb43bfb2f55fd15a8814c5c5c7b9f2ce2f4572', 'firmware.metainfo.xml': 'a8fda77f8baa56917ee1201b72747612c49e855b', } for fn in results: self.assertEqual( hashlib.sha1(cabarchive[fn].buf).hexdigest(), results[fn])