···11+import tarfile
22+import sys
33+44+55+def process_columns(line: list[str]) -> tuple[str, list[str]]:
66+ match line:
77+ case [name, h_prefix, nrbytes, flags]:
88+ return (h_prefix, flags.lower().split(","))
99+ case other:
1010+ raise Exception("Unsupported hashes.conf line format", other)
1111+1212+1313+def find_tar_file(tar: tarfile.TarFile, requested_name: str):
1414+ """Attempts to find a single file with given name in tarball."""
1515+ all_names = tar.getnames()
1616+1717+ if requested_name in all_names:
1818+ return requested_name
1919+2020+ requested_suffix = f"/{requested_name}"
2121+ candidate_names = [name for name in all_names if name.endswith(requested_suffix)]
2222+ match candidate_names:
2323+ case [real_name]:
2424+ return real_name
2525+ case other:
2626+ raise KeyError(
2727+ f"Could not locate a single {requested_name} in the contents of the tarball."
2828+ )
2929+3030+3131+hashes_path = "lib/hashes.conf"
3232+3333+3434+def main() -> None:
3535+ match sys.argv:
3636+ case [_name, src, enable_hashes, "--", *enabled_crypt_scheme_ids]:
3737+ pass
3838+ case other:
3939+ raise Exception(
4040+ "Incorrect number of arguments. Usage: check_passthru_matches.py <src> <enable_hashes> -- <enabled_crypt_scheme_ids...>"
4141+ )
4242+4343+ with tarfile.open(src, "r") as tar:
4444+ real_hashes_path = find_tar_file(tar, hashes_path)
4545+ config = tar.extractfile(real_hashes_path).read().decode("utf-8")
4646+4747+ formats = [
4848+ process_columns(columns)
4949+ for line in config.splitlines()
5050+ if not line.startswith("#") and len(columns := line.split()) > 0
5151+ ]
5252+ expected_supported_formats = set(
5353+ prefix
5454+ for (prefix, flags) in formats
5555+ if enable_hashes in flags or enable_hashes == "all"
5656+ )
5757+ passthru_supported_schemes = set(
5858+ f"${scheme}$" for scheme in enabled_crypt_scheme_ids
5959+ )
6060+6161+ assert (
6262+ len(expected_supported_formats - passthru_supported_schemes) == 0
6363+ ), f"libxcrypt package enables the following crypt schemes that are not listed in passthru.enabledCryptSchemeIds: {expected_supported_formats - passthru_supported_schemes}"
6464+ assert (
6565+ len(passthru_supported_schemes - expected_supported_formats) == 0
6666+ ), f"libxcrypt package lists the following crypt schemes in passthru.enabledCryptSchemeIds that are not supported: {passthru_supported_schemes - expected_supported_formats}"
6767+6868+6969+if __name__ == "__main__":
7070+ main()