From 064a1edc0b3b0ff6d0bbcc7805614f135c62e433 Mon Sep 17 00:00:00 2001 From: Andrew Lukoshko Date: Wed, 4 Oct 2023 12:51:10 +0000 Subject: [PATCH] import CS keylime-7.3.0-9.el9 --- .gitignore | 4 +- .keylime.metadata | 4 +- ...lt-values-that-need-reading-the-conf.patch | 130 ---------- ...e-of-Required-NotRequired-typing_ext.patch | 104 ++++++++ ...rver_t-tcp-connect-to-several-domain.patch | 27 ++ ...itch-to-sha256-hashes-for-signatures.patch | 67 ----- ...as-the-minimum-for-the-configuration.patch | 51 ++++ ...ove-option-to-log-into-separate-file.patch | 136 ---------- ...-str_to_version-for-the-upgrade-tool.patch | 88 +++++++ ...le-add-ignores-for-EV_PLATFORM_CONFI.patch | 50 ++++ SOURCES/0006-Revert-mapping-changes.patch | 43 +++ ...ession-close-using-a-session-manager.patch | 90 +++++++ ...read-parameters-from-verifier.conf-o.patch | 31 +++ SOURCES/0009-CVE-2023-38201.patch | 48 ++++ SOURCES/0010-CVE-2023-38200.patch | 69 +++++ ...tomatically-update-agent-API-version.patch | 244 ++++++++++++++++++ SPECS/keylime.spec | 125 ++++++--- 17 files changed, 944 insertions(+), 367 deletions(-) delete mode 100644 SOURCES/0001-Do-not-use-default-values-that-need-reading-the-conf.patch create mode 100644 SOURCES/0001-Remove-usage-of-Required-NotRequired-typing_ext.patch create mode 100644 SOURCES/0002-Allow-keylime_server_t-tcp-connect-to-several-domain.patch delete mode 100644 SOURCES/0002-Switch-to-sha256-hashes-for-signatures.patch create mode 100644 SOURCES/0003-Use-version-2.0-as-the-minimum-for-the-configuration.patch delete mode 100644 SOURCES/0003-logging-remove-option-to-log-into-separate-file.patch create mode 100644 SOURCES/0004-Duplicate-str_to_version-for-the-upgrade-tool.patch create mode 100644 SOURCES/0005-elchecking-example-add-ignores-for-EV_PLATFORM_CONFI.patch create mode 100644 SOURCES/0006-Revert-mapping-changes.patch create mode 100644 SOURCES/0007-Handle-session-close-using-a-session-manager.patch create mode 100644 SOURCES/0008-verifier-should-read-parameters-from-verifier.conf-o.patch create mode 100644 SOURCES/0009-CVE-2023-38201.patch create mode 100644 SOURCES/0010-CVE-2023-38200.patch create mode 100644 SOURCES/0011-Automatically-update-agent-API-version.patch diff --git a/.gitignore b/.gitignore index 333b933..39b0b2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -SOURCES/keylime-selinux-1.0.0.tar.gz -SOURCES/v6.5.2.tar.gz +SOURCES/keylime-selinux-1.2.0.tar.gz +SOURCES/v7.3.0.tar.gz diff --git a/.keylime.metadata b/.keylime.metadata index d577a83..89a2596 100644 --- a/.keylime.metadata +++ b/.keylime.metadata @@ -1,2 +1,2 @@ -a1154fc19d2ae6f52b6b77a39e62d2420c0f4c5e SOURCES/keylime-selinux-1.0.0.tar.gz -1c311bc1d3ab6c8050fd819410c593392187c2fa SOURCES/v6.5.2.tar.gz +9130beade415b8e3b02aac8d06678f2c45b939fe SOURCES/keylime-selinux-1.2.0.tar.gz +400e2b019060b8a6cc255dbfc14c582121acbee1 SOURCES/v7.3.0.tar.gz diff --git a/SOURCES/0001-Do-not-use-default-values-that-need-reading-the-conf.patch b/SOURCES/0001-Do-not-use-default-values-that-need-reading-the-conf.patch deleted file mode 100644 index 2c4ace1..0000000 --- a/SOURCES/0001-Do-not-use-default-values-that-need-reading-the-conf.patch +++ /dev/null @@ -1,130 +0,0 @@ -From d6dd71e3a3fe8e822fbcaa0d88f19a0c3332cacd Mon Sep 17 00:00:00 2001 -From: Sergio Correia -Date: Tue, 15 Nov 2022 07:09:13 -0300 -Subject: [PATCH] Do not use default values that need reading the config in - methods - -Following up from the recent refactoring that moved the EK validation -to cert_utils, in a few places were added default method values that -were reading the configuration files directly. - -It was not such a great idea becasue it then made those config files as -required to even import the modules. - -Example "from keylime import cert_utils" now also requires that the -tenant configuration be available for getting the path for the TPM -cert store. - -Let's stop doing that. - -Signed-off-by: Sergio Correia ---- - keylime/cert_utils.py | 5 +++-- - keylime/tenant.py | 2 +- - keylime/tpm/tpm_abstract.py | 2 +- - keylime/tpm/tpm_main.py | 4 ++-- - keylime/tpm_ek_ca.py | 6 +++--- - 5 files changed, 10 insertions(+), 9 deletions(-) - -diff --git a/keylime/cert_utils.py b/keylime/cert_utils.py -index d2fc54d..3576c64 100644 ---- a/keylime/cert_utils.py -+++ b/keylime/cert_utils.py -@@ -12,7 +12,7 @@ from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey - from pyasn1.codec.der import decoder, encoder - from pyasn1_modules import pem, rfc2459 - --from keylime import config, keylime_logging, tpm_ek_ca -+from keylime import keylime_logging, tpm_ek_ca - - # Issue #944 -- python-cryptography won't parse malformed certs, - # such as some Nuvoton ones we have encountered in the field. -@@ -56,9 +56,10 @@ def x509_pem_cert(pem_cert_data: str): - return x509.load_der_x509_certificate(data=encoder.encode(pyasn1_cert), backend=default_backend()) - - --def verify_ek(ekcert, tpm_cert_store=config.get("tenant", "tpm_cert_store")): -+def verify_ek(ekcert: bytes, tpm_cert_store: str) -> bool: - """Verify that the provided EK certificate is signed by a trusted root - :param ekcert: The Endorsement Key certificate in DER format -+ :param tpm_cert_store: The path for the TPM certificate store - :returns: True if the certificate can be verified, False otherwise - """ - try: -diff --git a/keylime/tenant.py b/keylime/tenant.py -index b574d04..076b849 100644 ---- a/keylime/tenant.py -+++ b/keylime/tenant.py -@@ -430,7 +430,7 @@ class Tenant: - elif ekcert is None: - logger.warning("No EK cert provided, require_ek_cert option in config set to True") - return False -- elif not self.tpm_instance.verify_ek(base64.b64decode(ekcert)): -+ elif not self.tpm_instance.verify_ek(base64.b64decode(ekcert), config.get("tenant", "tpm_cert_store")): - logger.warning("Invalid EK certificate") - return False - -diff --git a/keylime/tpm/tpm_abstract.py b/keylime/tpm/tpm_abstract.py -index ff41837..df6222c 100644 ---- a/keylime/tpm/tpm_abstract.py -+++ b/keylime/tpm/tpm_abstract.py -@@ -97,7 +97,7 @@ class AbstractTPM(metaclass=ABCMeta): - pass - - @abstractmethod -- def verify_ek(self, ekcert): -+ def verify_ek(self, ekcert, tpm_cert_store): - pass - - @abstractmethod -diff --git a/keylime/tpm/tpm_main.py b/keylime/tpm/tpm_main.py -index e1d1cf8..e244dfa 100644 ---- a/keylime/tpm/tpm_main.py -+++ b/keylime/tpm/tpm_main.py -@@ -776,12 +776,12 @@ class tpm(tpm_abstract.AbstractTPM): - os.remove(sesspath) - return key - -- def verify_ek(self, ekcert): -+ def verify_ek(self, ekcert, tpm_cert_store): - """Verify that the provided EK certificate is signed by a trusted root - :param ekcert: The Endorsement Key certificate in DER format - :returns: True if the certificate can be verified, false otherwise - """ -- return cert_utils.verify_ek(ekcert) -+ return cert_utils.verify_ek(ekcert, tpm_cert_store) - - def get_tpm_manufacturer(self, output=None): - vendorStr = None -diff --git a/keylime/tpm_ek_ca.py b/keylime/tpm_ek_ca.py -index fb66c07..bc84571 100644 ---- a/keylime/tpm_ek_ca.py -+++ b/keylime/tpm_ek_ca.py -@@ -1,13 +1,13 @@ - import glob - import os - --from keylime import config, keylime_logging -+from keylime import keylime_logging - - logger = keylime_logging.init_logging("tpm_ek_ca") - trusted_certs = {} - - --def check_tpm_cert_store(tpm_cert_store=config.get("tenant", "tpm_cert_store")): -+def check_tpm_cert_store(tpm_cert_store): - if not os.path.isdir(tpm_cert_store): - logger.error("The directory %s does not exist.", tpm_cert_store) - raise Exception(f"The directory {tpm_cert_store} does not exist.") -@@ -20,7 +20,7 @@ def check_tpm_cert_store(tpm_cert_store=config.get("tenant", "tpm_cert_store")): - raise Exception(f"The directory {tpm_cert_store} does not contain " f"any .pem files") - - --def cert_loader(tpm_cert_store=config.get("tenant", "tpm_cert_store")): -+def cert_loader(tpm_cert_store): - file_list = glob.glob(os.path.join(tpm_cert_store, "*.pem")) - my_trusted_certs = {} - for file_path in file_list: --- -2.38.1 - diff --git a/SOURCES/0001-Remove-usage-of-Required-NotRequired-typing_ext.patch b/SOURCES/0001-Remove-usage-of-Required-NotRequired-typing_ext.patch new file mode 100644 index 0000000..5782252 --- /dev/null +++ b/SOURCES/0001-Remove-usage-of-Required-NotRequired-typing_ext.patch @@ -0,0 +1,104 @@ +Subject: [PATCH] Remove usage of Required/NotRequired typing_ext + +Since we do not yet have typing_extensions packaged, let us not +use its functionality yet. +--- + keylime/ima/types.py | 33 ++++++++++++++------------------- + keylime/registrar_client.py | 8 +------- + 2 files changed, 15 insertions(+), 26 deletions(-) + +diff --git a/keylime/ima/types.py b/keylime/ima/types.py +index 99f0aa7..a0fffdf 100644 +--- a/keylime/ima/types.py ++++ b/keylime/ima/types.py +@@ -6,11 +6,6 @@ if sys.version_info >= (3, 8): + else: + from typing_extensions import Literal, TypedDict + +-if sys.version_info >= (3, 11): +- from typing import NotRequired, Required +-else: +- from typing_extensions import NotRequired, Required +- + ### Types for tpm_dm.py + + RuleAttributeType = Optional[Union[int, str, bool]] +@@ -51,7 +46,7 @@ class Rule(TypedDict): + + + class Policies(TypedDict): +- version: Required[int] ++ version: int + match_on: MatchKeyType + rules: Dict[str, Rule] + +@@ -60,27 +55,27 @@ class Policies(TypedDict): + + + class RPMetaType(TypedDict): +- version: Required[int] +- generator: NotRequired[int] +- timestamp: NotRequired[str] ++ version: int ++ generator: int ++ timestamp: str + + + class RPImaType(TypedDict): +- ignored_keyrings: Required[List[str]] +- log_hash_alg: Required[Literal["sha1", "sha256", "sha384", "sha512"]] ++ ignored_keyrings: List[str] ++ log_hash_alg: Literal["sha1", "sha256", "sha384", "sha512"] + dm_policy: Optional[Policies] + + + RuntimePolicyType = TypedDict( + "RuntimePolicyType", + { +- "meta": Required[RPMetaType], +- "release": NotRequired[int], +- "digests": Required[Dict[str, List[str]]], +- "excludes": Required[List[str]], +- "keyrings": Required[Dict[str, List[str]]], +- "ima": Required[RPImaType], +- "ima-buf": Required[Dict[str, List[str]]], +- "verification-keys": Required[str], ++ "meta": RPMetaType, ++ "release": int, ++ "digests": Dict[str, List[str]], ++ "excludes": List[str], ++ "keyrings": Dict[str, List[str]], ++ "ima": RPImaType, ++ "ima-buf": Dict[str, List[str]], ++ "verification-keys": str, + }, + ) +diff --git a/keylime/registrar_client.py b/keylime/registrar_client.py +index ab28977..ea5341b 100644 +--- a/keylime/registrar_client.py ++++ b/keylime/registrar_client.py +@@ -13,12 +13,6 @@ if sys.version_info >= (3, 8): + else: + from typing_extensions import TypedDict + +-if sys.version_info >= (3, 11): +- from typing import NotRequired +-else: +- from typing_extensions import NotRequired +- +- + class RegistrarData(TypedDict): + ip: Optional[str] + port: Optional[str] +@@ -27,7 +21,7 @@ class RegistrarData(TypedDict): + aik_tpm: str + ek_tpm: str + ekcert: Optional[str] +- provider_keys: NotRequired[Dict[str, str]] ++ provider_keys: Dict[str, str] + + + logger = keylime_logging.init_logging("registrar_client") +-- +2.41.0 + diff --git a/SOURCES/0002-Allow-keylime_server_t-tcp-connect-to-several-domain.patch b/SOURCES/0002-Allow-keylime_server_t-tcp-connect-to-several-domain.patch new file mode 100644 index 0000000..c54b161 --- /dev/null +++ b/SOURCES/0002-Allow-keylime_server_t-tcp-connect-to-several-domain.patch @@ -0,0 +1,27 @@ +From e8a1fa55ff0892ee2380e832ac94abc629b401d6 Mon Sep 17 00:00:00 2001 +From: Patrik Koncity +Date: Thu, 10 Aug 2023 07:47:04 -0400 +Subject: [PATCH 2/2] Allow keylime_server_t tcp connect to several domains + +--- + keylime-selinux-1.2.0/keylime.te | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/keylime-selinux-1.2.0/keylime.te b/keylime-selinux-1.2.0/keylime.te +index 8d47d26..8e6487b 100644 +--- a/keylime-selinux-1.2.0/keylime.te ++++ b/keylime-selinux-1.2.0/keylime.te +@@ -83,6 +83,10 @@ allow keylime_server_t self:udp_socket create_stream_socket_perms; + manage_dirs_pattern(keylime_server_t, keylime_log_t, keylime_log_t) + manage_files_pattern(keylime_server_t, keylime_log_t, keylime_log_t) + ++corenet_tcp_connect_http_cache_port(keylime_server_t) ++corenet_tcp_connect_mysqld_port(keylime_server_t) ++corenet_tcp_connect_postgresql_port(keylime_server_t) ++ + fs_getattr_all_fs(keylime_server_t) + fs_rw_inherited_tmpfs_files(keylime_server_t) + +-- +2.39.3 + diff --git a/SOURCES/0002-Switch-to-sha256-hashes-for-signatures.patch b/SOURCES/0002-Switch-to-sha256-hashes-for-signatures.patch deleted file mode 100644 index 6401048..0000000 --- a/SOURCES/0002-Switch-to-sha256-hashes-for-signatures.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 1f9ee7437f5b712a892c6d13ac8d75e128c1a16f Mon Sep 17 00:00:00 2001 -From: Stefan Berger -Date: Tue, 22 Nov 2022 10:56:43 -0500 -Subject: [PATCH] tests: Switch to sha256 hashes for signatures - -Resolves: https://github.com/keylime/keylime/issues/1202 -Signed-off-by: Stefan Berger ---- - test/test_ima_ast.py | 4 ++-- - test/test_ima_verification.py | 12 ++++++------ - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/test/test_ima_ast.py b/test/test_ima_ast.py -index cd54f95f9..e7d3841a7 100644 ---- a/test/test_ima_ast.py -+++ b/test/test_ima_ast.py -@@ -14,11 +14,11 @@ - VALID_ENTRIES = { - "ima-sig-rsa": ( - ast.ImaSig, -- "10 50873c47693cf9458e87eb4a02dd4f594f7a0c0f ima-sig sha1:1350320e5f7f51553bac8aa403489a1b135bc101 /usr/bin/dd 030202f3452d23010084c2a6cf7de1aeefa119220df0da265a7c44d34380f0d97002e7c778d09cfcf88c018e6595df3ee70eda926851f159332f852e7981a8fca1bc5e959958d06d234a0896861f13cc60da825905c8ed234df26c1deecfa816d5aa9bfb11b905e2814084a86b588be60423afada8dd0dd5a143774c6d890b64195ac42fb47ef5a9a00f0d6c80711d8e0c2b843ec38c02f60fd46bc46c7b4c329ad2dbb1b7625293703f9c739dc4c2bf0769126a2f3cb2cd031d1881cd0af64bf20fd474a993b48620f103a5c14999a2f17d60721bcc019a896b4138a688a59f50cb6cd94a4cfe3b8052e82dec025fef4feabb08c7ce412e3de850f903797e293ec27c329f57fd84e0", -+ "10 1e70a3e1af66f42826ad63b761b4cb9c4df195e1 ima-sig sha256:d33d5d13792292e202dbf69a6f1b07bc8a02f01424db8489ba7bb7d43c0290ef /usr/bin/dd 030204f3452d2301009dd340c852f37e35748363586939d4199b6684be27e7c1236ca1528f708372ed9cd52a0d991f66448790f5616ed5bd7f9bbd22193b1e3e54f6bf29a1497945a34d1b418b24f4cbeaef897bf3cebca27065ebb8761b46bc2662fe76f141245b9186a5ac8493c7f4976cf0d6dfc085c3e503e3f771bc3ccb121230db76fd8aba4f45f060ad64ab3afd99b4e52824b9eba12e93e46f9dcb2fa01d9cef89f298a0da02a82a4fb56924afd3e3c277a1302d99f770d488449df2d43eb5b174a0a528827e6877b965c2f0b7c89cf1aa26a7417a892df4c2294e2872d62748b72ea04ecb0689b5d792e615a9bf9d56f6e0f298560bf9441df0a22729c5f23389f028c25f", - ), - "ima-sig-ec": ( - ast.ImaSig, -- "10 06e804489a77ddab51b9ef27e17053c0e5d503bd ima-sig sha1:1cb84b12db45d7da8de58ba6744187db84082f0e /usr/bin/zmore 030202531f402500483046022100bff9c02dc7b270c83cc94bfec10eecd42831de2cdcb04f024369a14623bc3a91022100cc4d015ae932fb98d6846645ed7d1bb1afd4621ec9089bc087126f191886dd31", -+ "10 5d4d5141ccd5066d50dc3f21d79ba02fedc24256 ima-sig sha256:b8ae0b8dd04a5935cd8165aa2260cd11b658bd71629bdb52256a675a1f73907b /usr/bin/zmore 030204531f402500483046022100fe24678d21083ead47660e1a2d553a592d777c478d1b0466de6ed484b54956b3022100cad3adb37f277bbb03544d6107751b4cd4f2289d8353fa36257400a99334d5c3", - ), - "ima-sig-missing": ( - ast.ImaSig, -diff --git a/test/test_ima_verification.py b/test/test_ima_verification.py -index bdb929c9c..d2fc9ef16 100644 ---- a/test/test_ima_verification.py -+++ b/test/test_ima_verification.py -@@ -27,8 +27,8 @@ - "/lib/modules/5.4.48-openpower1/kernel/drivers/gpu/drm/drm_panel_orientation_quirks.ko": [ - "cd026b58efdf66658685430ff526490d54a430a3f0066a35ac26a8acab66c55d" - ], -- "/usr/bin/dd": ["1350320e5f7f51553bac8aa403489a1b135bc101"], -- "/usr/bin/zmore": ["1cb84b12db45d7da8de58ba6744187db84082f0e"], -+ "/usr/bin/dd": ["d33d5d13792292e202dbf69a6f1b07bc8a02f01424db8489ba7bb7d43c0290ef"], -+ "/usr/bin/zmore": ["b8ae0b8dd04a5935cd8165aa2260cd11b658bd71629bdb52256a675a1f73907b"], - "/usr/bin/zless": ["233ad3a8e77c63a7d9a56063ec2cad1eafa58850"], - }, - "keyrings": { -@@ -50,8 +50,8 @@ - "version": 1, - }, - "hashes": { -- "/usr/bin/dd": ["1350320e5f7f51553bac8aa403489a1b135bc102"], -- "/usr/bin/zmore": ["1cb84b12db45d7da8de58ba6744187db84082f01"], -+ "/usr/bin/dd": ["bad05d13792292e202dbf69a6f1b07bc8a02f01424db8489ba7bb7d43c0290ef"], -+ "/usr/bin/zmore": ["bad00b8dd04a5935cd8165aa2260cd11b658bd71629bdb52256a675a1f73907b"], - }, - } - -@@ -73,8 +73,8 @@ - # 1st signature: RSA - # 2nd signature: EC - SIGNATURES = ( -- "10 50873c47693cf9458e87eb4a02dd4f594f7a0c0f ima-sig sha1:1350320e5f7f51553bac8aa403489a1b135bc101 /usr/bin/dd 030202f3452d23010084c2a6cf7de1aeefa119220df0da265a7c44d34380f0d97002e7c778d09cfcf88c018e6595df3ee70eda926851f159332f852e7981a8fca1bc5e959958d06d234a0896861f13cc60da825905c8ed234df26c1deecfa816d5aa9bfb11b905e2814084a86b588be60423afada8dd0dd5a143774c6d890b64195ac42fb47ef5a9a00f0d6c80711d8e0c2b843ec38c02f60fd46bc46c7b4c329ad2dbb1b7625293703f9c739dc4c2bf0769126a2f3cb2cd031d1881cd0af64bf20fd474a993b48620f103a5c14999a2f17d60721bcc019a896b4138a688a59f50cb6cd94a4cfe3b8052e82dec025fef4feabb08c7ce412e3de850f903797e293ec27c329f57fd84e0\n" -- "10 06e804489a77ddab51b9ef27e17053c0e5d503bd ima-sig sha1:1cb84b12db45d7da8de58ba6744187db84082f0e /usr/bin/zmore 030202531f402500483046022100bff9c02dc7b270c83cc94bfec10eecd42831de2cdcb04f024369a14623bc3a91022100cc4d015ae932fb98d6846645ed7d1bb1afd4621ec9089bc087126f191886dd31\n" -+ "10 1e70a3e1af66f42826ad63b761b4cb9c4df195e1 ima-sig sha256:d33d5d13792292e202dbf69a6f1b07bc8a02f01424db8489ba7bb7d43c0290ef /usr/bin/dd 030204f3452d2301009dd340c852f37e35748363586939d4199b6684be27e7c1236ca1528f708372ed9cd52a0d991f66448790f5616ed5bd7f9bbd22193b1e3e54f6bf29a1497945a34d1b418b24f4cbeaef897bf3cebca27065ebb8761b46bc2662fe76f141245b9186a5ac8493c7f4976cf0d6dfc085c3e503e3f771bc3ccb121230db76fd8aba4f45f060ad64ab3afd99b4e52824b9eba12e93e46f9dcb2fa01d9cef89f298a0da02a82a4fb56924afd3e3c277a1302d99f770d488449df2d43eb5b174a0a528827e6877b965c2f0b7c89cf1aa26a7417a892df4c2294e2872d62748b72ea04ecb0689b5d792e615a9bf9d56f6e0f298560bf9441df0a22729c5f23389f028c25f\n" -+ "10 5d4d5141ccd5066d50dc3f21d79ba02fedc24256 ima-sig sha256:b8ae0b8dd04a5935cd8165aa2260cd11b658bd71629bdb52256a675a1f73907b /usr/bin/zmore 030204531f402500483046022100fe24678d21083ead47660e1a2d553a592d777c478d1b0466de6ed484b54956b3022100cad3adb37f277bbb03544d6107751b4cd4f2289d8353fa36257400a99334d5c3\n" - ) - - COMBINED = MEASUREMENTS + SIGNATURES diff --git a/SOURCES/0003-Use-version-2.0-as-the-minimum-for-the-configuration.patch b/SOURCES/0003-Use-version-2.0-as-the-minimum-for-the-configuration.patch new file mode 100644 index 0000000..4ecd144 --- /dev/null +++ b/SOURCES/0003-Use-version-2.0-as-the-minimum-for-the-configuration.patch @@ -0,0 +1,51 @@ +From b8e26ca5e98e1b842db2fc21411962d40f27c557 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Tue, 15 Aug 2023 07:19:28 -0400 +Subject: [PATCH 3/4] Use version 2.0 as the minimum for the configuration + +--- + keylime/cmd/convert_config.py | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/keylime/cmd/convert_config.py b/keylime/cmd/convert_config.py +index ac28151..1d71b99 100755 +--- a/keylime/cmd/convert_config.py ++++ b/keylime/cmd/convert_config.py +@@ -191,7 +191,13 @@ def output(components: List[str], config: RawConfigParser, templates: str, outdi + + # Check that there are templates for all components + for component in components: +- version = config[component]["version"].strip('" ') ++ # Minimum version. ++ version = '2.0' ++ if "version" in config[component]: ++ version = config[component]["version"].strip('" ') ++ else: ++ config[component]["version"] = version ++ + version_dir = os.path.join(templates, version) + if not os.path.isdir(version_dir): + raise Exception(f"Could not find directory {version_dir}") +@@ -292,15 +298,15 @@ def process_mapping( + raise Exception("Invalid version number found in old configuration") + + except (configparser.NoOptionError, configparser.NoSectionError): +- print(f"No version found in old configuration for {component}, using '1.0'") +- old_version = (1, 0) ++ print(f"No version found in old configuration for {component}, using '2.0'") ++ old_version = (2, 0) + else: + # If the old_version does not contain the component from the + # mapping, use the minimum version to use defaults +- old_version = (1, 0) ++ old_version = (2, 0) + + # Skip versions lower than the current version +- if old_version >= new_version: ++ if old_version >= new_version and component in old_config: + new[component] = old_config[component] + continue + +-- +2.39.3 + diff --git a/SOURCES/0003-logging-remove-option-to-log-into-separate-file.patch b/SOURCES/0003-logging-remove-option-to-log-into-separate-file.patch deleted file mode 100644 index e7e3672..0000000 --- a/SOURCES/0003-logging-remove-option-to-log-into-separate-file.patch +++ /dev/null @@ -1,136 +0,0 @@ -From eb5112dd597336b566378b3a157e76fe3cbbbfee Mon Sep 17 00:00:00 2001 -From: Thore Sommer -Date: Mon, 16 Jan 2023 07:26:08 -0300 -Subject: [PATCH 3/3] logging: remove option to log into separate file - -The implementation had the issue that only the main loggers were added and that -the permissions were not set strict enough. Users should use the logging -provided by systemd instead. - -Signed-off-by: Thore Sommer ---- - keylime.conf | 10 ---------- - keylime/keylime_logging.py | 31 ------------------------------ - scripts/templates/2.0/registrar.j2 | 9 --------- - scripts/templates/2.0/verifier.j2 | 9 --------- - 4 files changed, 59 deletions(-) - -diff --git a/keylime.conf b/keylime.conf -index d896f9f..043b6a8 100644 ---- a/keylime.conf -+++ b/keylime.conf -@@ -342,11 +342,6 @@ tomtou_errors = False - # signature check before storing them in the database. - require_allow_list_signatures = False - --# Destination for log output, in addition to console. Values can be 'file', --# with the file being named after the "service" - cloud_verifier - created under --# /var/log/keylime), 'stream' or it can be left empty (which results in --# logging to console only, recommended when running inside a container) --log_destination = file - - #============================================================================= - [tenant] -@@ -595,11 +590,6 @@ auto_migrate_db = True - # The file to use for SQLite persistence of provider hypervisor data. - prov_db_filename = provider_reg_data.sqlite - --# Destination for log output, in addition to console. Values can be 'file', --# with the file being named after the "service" - registrar - created under --# /var/log/keylime), 'stream' or it can be left empty (which results in --# logging to console only, recommended when running inside a container) --log_destination = file - - #============================================================================= - [ca] -diff --git a/keylime/keylime_logging.py b/keylime/keylime_logging.py -index bc8a11d..f7c7a8f 100644 ---- a/keylime/keylime_logging.py -+++ b/keylime/keylime_logging.py -@@ -1,17 +1,10 @@ - import logging --import os - from logging import Logger - from logging import config as logging_config - from typing import Any, Callable, Dict - - from keylime import config - --LOG_TO_FILE = set() --LOG_TO_STREAM = set() --LOGDIR = os.getenv("KEYLIME_LOGDIR", "/var/log/keylime") --# not clear that this works right. console logging may not work --LOGSTREAM = os.path.join(LOGDIR, "keylime-stream.log") -- - logging_config.fileConfig(config.get_config("logging")) - - -@@ -50,31 +43,7 @@ def log_http_response(logger: Logger, loglevel: int, response_body: Dict[str, An - - - def init_logging(loggername: str) -> Logger: -- -- if loggername in ("verifier", "registrar"): -- logdest = config.get(loggername, "log_destination", fallback="") -- if logdest == "file": -- LOG_TO_FILE.add(loggername) -- if logdest == "stream": -- LOG_TO_STREAM.add(loggername) -- - logger = logging.getLogger(f"keylime.{loggername}") - logging.getLogger("requests").setLevel(logging.WARNING) -- mainlogger = logging.getLogger("keylime") -- basic_formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s") -- if loggername in LOG_TO_FILE: -- logfilename = os.path.join(LOGDIR, f"{loggername}.log") -- if not os.path.exists(LOGDIR): -- os.makedirs(LOGDIR, 0o750) -- fh = logging.FileHandler(logfilename) -- fh.setLevel(logger.getEffectiveLevel()) -- fh.setFormatter(basic_formatter) -- mainlogger.addHandler(fh) -- -- if loggername in LOG_TO_STREAM: -- fh = logging.FileHandler(filename=LOGSTREAM, mode="w") -- fh.setLevel(logger.getEffectiveLevel()) -- fh.setFormatter(basic_formatter) -- mainlogger.addHandler(fh) - - return logger -diff --git a/scripts/templates/2.0/registrar.j2 b/scripts/templates/2.0/registrar.j2 -index 3d92303..8de7a50 100644 ---- a/scripts/templates/2.0/registrar.j2 -+++ b/scripts/templates/2.0/registrar.j2 -@@ -71,12 +71,3 @@ auto_migrate_db = {{ registrar.auto_migrate_db }} - - # The file to use for SQLite persistence of provider hypervisor data. - prov_db_filename: {{ registrar.prov_db_filename }} -- --# Destination for log output, in addition to console. If left empty, the log --# output will only be printed to console (recommended for containers to avoid --# filling data storage). The accepted values are: --# 'file': The log output will also be written to a file named after the --# component in '/var/log/keylime/registrar.log' --# 'stream': The log output will be written to a common file in --# 'var/log/keylime/keylime-stream.log' --log_destination = {{ registrar.log_destination }} -diff --git a/scripts/templates/2.0/verifier.j2 b/scripts/templates/2.0/verifier.j2 -index d1584df..7a66cb1 100644 ---- a/scripts/templates/2.0/verifier.j2 -+++ b/scripts/templates/2.0/verifier.j2 -@@ -196,12 +196,3 @@ zmq_port = {{ verifier.zmq_port }} - - # Webhook url for revocation notifications. - webhook_url = {{ verifier.webhook_url }} -- --# Destination for log output, in addition to console. If left empty, the log --# output will only be printed to console (recommended for containers to avoid --# filling data storage). The accepted values are: --# 'file': The log output will also be written to a file named after the --# component in '/var/log/keylime/verifier.log' --# 'stream': The log output will be written to a common file in --# 'var/log/keylime/keylime-stream.log' --log_destination = {{ verifier.log_destination }} --- -2.38.1 - diff --git a/SOURCES/0004-Duplicate-str_to_version-for-the-upgrade-tool.patch b/SOURCES/0004-Duplicate-str_to_version-for-the-upgrade-tool.patch new file mode 100644 index 0000000..66cb11b --- /dev/null +++ b/SOURCES/0004-Duplicate-str_to_version-for-the-upgrade-tool.patch @@ -0,0 +1,88 @@ +From dbd521e8e8f0ffd9ace79c7b9b888f4cb89488f9 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Tue, 15 Aug 2023 06:09:37 -0400 +Subject: [PATCH 4/4] Duplicate str_to_version for the upgrade tool + +So it does not depend on python-keylime +--- + keylime/cmd/convert_config.py | 24 ++++++++++++++++++++++-- + templates/2.0/adjust.py | 22 ++++++++++++++++++++-- + 2 files changed, 42 insertions(+), 4 deletions(-) + +diff --git a/keylime/cmd/convert_config.py b/keylime/cmd/convert_config.py +index c1c6180..cad5e31 100755 +--- a/keylime/cmd/convert_config.py ++++ b/keylime/cmd/convert_config.py +@@ -84,13 +84,33 @@ import importlib.util + import itertools + import json + import os ++import re + import shutil + from configparser import RawConfigParser +-from typing import List, Optional, Tuple ++from typing import List, Optional, Tuple, Union + + from jinja2 import Template + +-from keylime.common.version import str_to_version ++ ++def str_to_version(v_str: str) -> Union[Tuple[int, int], None]: ++ """ ++ Validates the string format and converts the provided string to a tuple of ++ ints which can be sorted and compared. ++ ++ :returns: Tuple with version number parts converted to int. In case of ++ invalid version string, returns None ++ """ ++ ++ # Strip to remove eventual quotes and spaces ++ v_str = v_str.strip('" ') ++ ++ m = re.match(r"^(\d+)\.(\d+)$", v_str) ++ ++ if not m: ++ return None ++ ++ return (int(m.group(1)), int(m.group(2))) ++ + + COMPONENTS = ["agent", "verifier", "tenant", "registrar", "ca", "logging"] + +diff --git a/templates/2.0/adjust.py b/templates/2.0/adjust.py +index 312b790..c1e582a 100644 +--- a/templates/2.0/adjust.py ++++ b/templates/2.0/adjust.py +@@ -2,9 +2,27 @@ import ast + import configparser + import re + from configparser import RawConfigParser +-from typing import Dict, List, Optional, Tuple ++from typing import Dict, List, Optional, Tuple, Union + +-from keylime.common.version import str_to_version ++ ++def str_to_version(v_str: str) -> Union[Tuple[int, int], None]: ++ """ ++ Validates the string format and converts the provided string to a tuple of ++ ints which can be sorted and compared. ++ ++ :returns: Tuple with version number parts converted to int. In case of ++ invalid version string, returns None ++ """ ++ ++ # Strip to remove eventual quotes and spaces ++ v_str = v_str.strip('" ') ++ ++ m = re.match(r"^(\d+)\.(\d+)$", v_str) ++ ++ if not m: ++ return None ++ ++ return (int(m.group(1)), int(m.group(2))) + + + def adjust(config: RawConfigParser, mapping: Dict) -> None: # pylint: disable=unused-argument +-- +2.39.3 + diff --git a/SOURCES/0005-elchecking-example-add-ignores-for-EV_PLATFORM_CONFI.patch b/SOURCES/0005-elchecking-example-add-ignores-for-EV_PLATFORM_CONFI.patch new file mode 100644 index 0000000..18a242d --- /dev/null +++ b/SOURCES/0005-elchecking-example-add-ignores-for-EV_PLATFORM_CONFI.patch @@ -0,0 +1,50 @@ +From f2432efbeb7b6305067111bb3a77ef5d7da4eb5b Mon Sep 17 00:00:00 2001 +From: Thore Sommer +Date: Thu, 10 Aug 2023 16:15:57 +0300 +Subject: [PATCH 5/6] elchecking/example: add ignores for + EV_PLATFORM_CONFIG_FLAGS + +These are generated by edk2 when used with QEMU, but we do not have a +reference for them. + +Signed-off-by: Thore Sommer +--- + keylime/mba/elchecking/example.py | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/keylime/mba/elchecking/example.py b/keylime/mba/elchecking/example.py +index 8885227..921db4e 100644 +--- a/keylime/mba/elchecking/example.py ++++ b/keylime/mba/elchecking/example.py +@@ -75,7 +75,6 @@ shim_authcode_sha256_no_secureboot = tests.obj_test( + kernel_cmdline=tests.type_test(str), + ) + +- + allowed_kernel_list_test_no_secureboot = tests.list_test(shim_authcode_sha256_no_secureboot) + + +@@ -303,6 +302,20 @@ class Example(policies.Policy): + ), + ), + ) ++ # edk2 measures up to 4 of those events, where we do not have a good way to get a reference ++ # See: ++ # - https://github.com/keylime/keylime/issues/1393 ++ # - https://github.com/tianocore/edk2/commit/935343cf1639a28530904a1e8d73d6517a07cbff ++ dispatcher.set( ++ (1, "EV_PLATFORM_CONFIG_FLAGS"), ++ tests.Or( ++ tests.OnceTest(tests.AcceptAll()), ++ tests.OnceTest(tests.AcceptAll()), ++ tests.OnceTest(tests.AcceptAll()), ++ tests.OnceTest(tests.AcceptAll()), ++ ), ++ ) ++ + dispatcher.set((4, "EV_EFI_ACTION"), tests.EvEfiActionTest(4)) + for pcr in range(8): + dispatcher.set((pcr, "EV_SEPARATOR"), tests.EvSeperatorTest()) +-- +2.39.3 + diff --git a/SOURCES/0006-Revert-mapping-changes.patch b/SOURCES/0006-Revert-mapping-changes.patch new file mode 100644 index 0000000..e06a1c0 --- /dev/null +++ b/SOURCES/0006-Revert-mapping-changes.patch @@ -0,0 +1,43 @@ +From ed213b9533535ceae5026b2fab274f80bcc58cb8 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Tue, 15 Aug 2023 09:18:32 -0400 +Subject: [PATCH 6/6] Revert mapping changes + +--- + templates/2.0/mapping.json | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/templates/2.0/mapping.json b/templates/2.0/mapping.json +index 66addbc..0036b63 100644 +--- a/templates/2.0/mapping.json ++++ b/templates/2.0/mapping.json +@@ -207,7 +207,7 @@ + "registrar_port": { + "section": "cloud_verifier", + "option": "registrar_port", +- "default": "8881" ++ "default": "8891" + }, + "tls_dir": { + "section": "cloud_verifier", +@@ -232,7 +232,7 @@ + "server_key_password": { + "section": "cloud_verifier", + "option": "private_key_pw", +- "default": "" ++ "default": "default" + }, + "enable_agent_mtls": { + "section": "cloud_verifier", +@@ -558,7 +558,7 @@ + "server_key_password": { + "section": "registrar", + "option": "private_key_pw", +- "default": "" ++ "default": "default" + }, + "server_cert": { + "section": "registrar", +-- +2.39.3 + diff --git a/SOURCES/0007-Handle-session-close-using-a-session-manager.patch b/SOURCES/0007-Handle-session-close-using-a-session-manager.patch new file mode 100644 index 0000000..ead77ea --- /dev/null +++ b/SOURCES/0007-Handle-session-close-using-a-session-manager.patch @@ -0,0 +1,90 @@ +From 3dc40e8b1878d84045ee80cb6d216348713c048a Mon Sep 17 00:00:00 2001 +From: Karel Srot +Date: Tue, 15 Aug 2023 10:00:50 +0200 +Subject: [PATCH 7/7] Handle session close using a session manager + +Resolves https://github.com/keylime/keylime/issues/1455 + +Signed-off-by: Karel Srot +--- + keylime/revocation_notifier.py | 50 +++++++++++++++++----------------- + packit-ci.fmf | 1 + + 2 files changed, 26 insertions(+), 25 deletions(-) + +diff --git a/keylime/revocation_notifier.py b/keylime/revocation_notifier.py +index 31a3095..5cc8b1a 100644 +--- a/keylime/revocation_notifier.py ++++ b/keylime/revocation_notifier.py +@@ -132,32 +132,32 @@ def notify_webhook(tosend: Dict[str, Any]) -> None: + def worker_webhook(tosend: Dict[str, Any], url: str) -> None: + interval = config.getfloat("verifier", "retry_interval") + exponential_backoff = config.getboolean("verifier", "exponential_backoff") +- session = requests.session() +- logger.info("Sending revocation event via webhook...") +- for i in range(config.getint("verifier", "max_retries")): +- next_retry = retry.retry_time(exponential_backoff, interval, i, logger) +- try: +- response = session.post(url, json=tosend, timeout=5) +- if response.status_code in [200, 202]: +- break +- +- logger.debug( +- "Unable to publish revocation message %d times via webhook, " +- "trying again in %d seconds. " +- "Server returned status code: %s", +- i, +- next_retry, +- response.status_code, +- ) +- except requests.exceptions.RequestException as e: +- logger.debug( +- "Unable to publish revocation message %d times via webhook, trying again in %d seconds: %s", +- i, +- next_retry, +- e, +- ) ++ with requests.Session() as session: ++ logger.info("Sending revocation event via webhook...") ++ for i in range(config.getint("verifier", "max_retries")): ++ next_retry = retry.retry_time(exponential_backoff, interval, i, logger) ++ try: ++ response = session.post(url, json=tosend, timeout=5) ++ if response.status_code in [200, 202]: ++ break ++ ++ logger.debug( ++ "Unable to publish revocation message %d times via webhook, " ++ "trying again in %d seconds. " ++ "Server returned status code: %s", ++ i, ++ next_retry, ++ response.status_code, ++ ) ++ except requests.exceptions.RequestException as e: ++ logger.debug( ++ "Unable to publish revocation message %d times via webhook, trying again in %d seconds: %s", ++ i, ++ next_retry, ++ e, ++ ) + +- time.sleep(next_retry) ++ time.sleep(next_retry) + + w = functools.partial(worker_webhook, tosend, url) + t = threading.Thread(target=w, daemon=True) +diff --git a/packit-ci.fmf b/packit-ci.fmf +index f4d2dae..7abe313 100644 +--- a/packit-ci.fmf ++++ b/packit-ci.fmf +@@ -108,6 +108,7 @@ adjust: + - /setup/configure_tpm_emulator + - /setup/install_upstream_keylime + - /setup/install_rust_keylime_from_copr ++ - /setup/configure_kernel_ima_module/ima_policy_simple + - /functional/basic-attestation-on-localhost + - /functional/basic-attestation-with-custom-certificates + - /functional/basic-attestation-without-mtls +-- +2.41.0 + diff --git a/SOURCES/0008-verifier-should-read-parameters-from-verifier.conf-o.patch b/SOURCES/0008-verifier-should-read-parameters-from-verifier.conf-o.patch new file mode 100644 index 0000000..efb3a2c --- /dev/null +++ b/SOURCES/0008-verifier-should-read-parameters-from-verifier.conf-o.patch @@ -0,0 +1,31 @@ +From aa891f456d5cf0fc23e16d87fb28efc79a0d8073 Mon Sep 17 00:00:00 2001 +From: Marcio Silva +Date: Wed, 23 Aug 2023 11:24:59 -0300 +Subject: [PATCH 8/8] verifier: should read parameters from verifier.conf only + +Single-line fix for #1446 + +The verifier should read "durable attestation" backend imports from +verifier.conf (and NOT from registrar.conf) + +Signed-off-by: Marcio Silva +--- + keylime/cloud_verifier_tornado.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/keylime/cloud_verifier_tornado.py b/keylime/cloud_verifier_tornado.py +index d65cb63..261022a 100644 +--- a/keylime/cloud_verifier_tornado.py ++++ b/keylime/cloud_verifier_tornado.py +@@ -51,7 +51,7 @@ except SQLAlchemyError as err: + sys.exit(1) + + try: +- rmc = record.get_record_mgt_class(config.get("registrar", "durable_attestation_import", fallback="")) ++ rmc = record.get_record_mgt_class(config.get("verifier", "durable_attestation_import", fallback="")) + if rmc: + rmc = rmc("verifier") + except record.RecordManagementException as rme: +-- +2.41.0 + diff --git a/SOURCES/0009-CVE-2023-38201.patch b/SOURCES/0009-CVE-2023-38201.patch new file mode 100644 index 0000000..cd1847d --- /dev/null +++ b/SOURCES/0009-CVE-2023-38201.patch @@ -0,0 +1,48 @@ +From 9e5ac9f25cd400b16d5969f531cee28290543f2a Mon Sep 17 00:00:00 2001 +From: Marcio Silva +Date: Wed, 12 Jul 2023 12:05:47 -0300 +Subject: [PATCH] Fix for CVE-2023-38201 (Security Advisory + GHSA-f4r5-q63f-gcww) + +In addition to remove the offending message, this patch also ensures +deletion of an agent's record from the database in case of failure after +a single attempt. + +Signed-off-by: Marcio Silva +--- + keylime/registrar_common.py | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/keylime/registrar_common.py b/keylime/registrar_common.py +index 1fd97cd0c..7f15ae430 100644 +--- a/keylime/registrar_common.py ++++ b/keylime/registrar_common.py +@@ -250,7 +250,9 @@ def get_network_params( + try: + port = int(port) + if port < 1 or port > 65535: +- logger.warning("Contact port for agent %s is not a number between 1 and got: %s.", agent_id, port) ++ logger.warning( ++ "Contact port for agent %s is not a number between 1 and 65535 got: %s.", agent_id, port ++ ) + port = None + except ValueError: + logger.warning("Contact port for agent %s is not a valid number got: %s.", agent_id, port) +@@ -447,7 +449,16 @@ def do_PUT(self) -> None: + logger.error("SQLAlchemy Error: %s", e) + raise + else: +- raise Exception(f"Auth tag {auth_tag} does not match expected value {ex_mac}") ++ if agent_id and session.query(RegistrarMain).filter_by(agent_id=agent_id).delete(): ++ try: ++ session.commit() ++ except SQLAlchemyError as e: ++ logger.error("SQLAlchemy Error: %s", e) ++ raise ++ ++ raise Exception( ++ f"Auth tag {auth_tag} for agent {agent_id} does not match expected value. The agent has been deleted from database, and a restart of it will be required" ++ ) + + web_util.echo_json_response(self, 200, "Success") + logger.info("PUT activated: %s", agent_id) diff --git a/SOURCES/0010-CVE-2023-38200.patch b/SOURCES/0010-CVE-2023-38200.patch new file mode 100644 index 0000000..7c06151 --- /dev/null +++ b/SOURCES/0010-CVE-2023-38200.patch @@ -0,0 +1,69 @@ +From e17d5a6a47c1405a799a06754d3e905856e3035d Mon Sep 17 00:00:00 2001 +From: florian <264356+flozilla@users.noreply.github.com> +Date: Tue, 11 Jul 2023 21:31:27 +0200 +Subject: [PATCH 10/10] CVE-2023-38200 + +Extend Registrar SSL socket to be non-blocking + +Fixes: CVE-2023-38200 + +Upstream: + - https://github.com/keylime/keylime/commit/c68d8f0b7 + - https://github.com/keylime/keylime/commit/27d515f4b +--- + keylime/registrar_common.py | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/keylime/registrar_common.py b/keylime/registrar_common.py +index d1d20dd..6441e3b 100644 +--- a/keylime/registrar_common.py ++++ b/keylime/registrar_common.py +@@ -2,8 +2,10 @@ import base64 + import http.server + import ipaddress + import os ++import select + import signal + import socket ++import ssl + import sys + import threading + from http.server import BaseHTTPRequestHandler, HTTPServer +@@ -77,6 +79,25 @@ class BaseHandler(BaseHTTPRequestHandler, SessionManager): + + + class ProtectedHandler(BaseHandler): ++ def handle(self) -> None: ++ """Need to perform SSL handshake here, as ++ do_handshake_on_connect=False for non-blocking SSL socket""" ++ while True: ++ try: ++ self.request.do_handshake() ++ break ++ except ssl.SSLWantReadError: ++ select.select([self.request], [], []) ++ except ssl.SSLWantWriteError: ++ select.select([], [self.request], []) ++ except ssl.SSLError as e: ++ logger.error("SSL connection error: %s", e) ++ return ++ except Exception as e: ++ logger.error("General communication failure: %s", e) ++ return ++ BaseHTTPRequestHandler.handle(self) ++ + def do_HEAD(self) -> None: + """HEAD not supported""" + web_util.echo_json_response(self, 405, "HEAD not supported") +@@ -494,7 +515,7 @@ def start(host: str, tlsport: int, port: int) -> None: + protected_server = RegistrarServer((host, tlsport), ProtectedHandler) + context = web_util.init_mtls("registrar", logger=logger) + if context is not None: +- protected_server.socket = context.wrap_socket(protected_server.socket, server_side=True) ++ protected_server.socket = context.wrap_socket(protected_server.socket, server_side=True, do_handshake_on_connect=False) + thread_protected_server = threading.Thread(target=protected_server.serve_forever) + + # Set up the unprotected registrar server +-- +2.41.0 + diff --git a/SOURCES/0011-Automatically-update-agent-API-version.patch b/SOURCES/0011-Automatically-update-agent-API-version.patch new file mode 100644 index 0000000..c87b309 --- /dev/null +++ b/SOURCES/0011-Automatically-update-agent-API-version.patch @@ -0,0 +1,244 @@ +From b0cf69c9db20eb319ea2e90c22f500e09b704224 Mon Sep 17 00:00:00 2001 +From: Anderson Toshiyuki Sasaki +Date: Wed, 23 Aug 2023 16:24:15 +0200 +Subject: [PATCH] Implement automatic agent API version bump + +Automatically update the agent supported API version in the database if +the agent is updated and its API version is bumped. + +Previously, if an agent was added to a verifier while it used an old API +version, and then it is updated with an API version bump, the +attestation would fail as the verifier would try to reach the agent +using the old API version. + +Fixes #1457 + +Signed-off-by: Anderson Toshiyuki Sasaki +--- + keylime/cloud_verifier_tornado.py | 185 +++++++++++++++++++++++++++--- + 1 file changed, 167 insertions(+), 18 deletions(-) + +diff --git a/keylime/cloud_verifier_tornado.py b/keylime/cloud_verifier_tornado.py +index 261022ac6..31e6f7159 100644 +--- a/keylime/cloud_verifier_tornado.py ++++ b/keylime/cloud_verifier_tornado.py +@@ -32,6 +32,7 @@ + ) + from keylime.agentstates import AgentAttestState, AgentAttestStates + from keylime.common import retry, states, validators ++from keylime.common.version import str_to_version + from keylime.da import record + from keylime.db.keylime_db import DBEngineManager, SessionManager + from keylime.db.verifier_db import VerfierMain, VerifierAllowlist +@@ -998,6 +999,80 @@ def data_received(self, chunk: Any) -> None: + raise NotImplementedError() + + ++async def update_agent_api_version(agent: Dict[str, Any], timeout: float = 60.0) -> Union[Dict[str, Any], None]: ++ agent_id = agent["agent_id"] ++ ++ logger.info("Agent %s API version bump detected, trying to update stored API version", agent_id) ++ kwargs = {} ++ if agent["ssl_context"]: ++ kwargs["context"] = agent["ssl_context"] ++ ++ res = tornado_requests.request( ++ "GET", ++ f"http://{agent['ip']}:{agent['port']}/version", ++ **kwargs, ++ timeout=timeout, ++ ) ++ response = await res ++ ++ if response.status_code != 200: ++ logger.warning( ++ "Could not get agent %s supported API version, Error: %s", ++ agent["agent_id"], ++ response.status_code, ++ ) ++ return None ++ ++ try: ++ json_response = json.loads(response.body) ++ new_version = json_response["results"]["supported_version"] ++ old_version = agent["supported_version"] ++ ++ # Only update the API version to use if it is supported by the verifier ++ if new_version in keylime_api_version.all_versions(): ++ new_version_tuple = str_to_version(new_version) ++ old_version_tuple = str_to_version(old_version) ++ ++ assert new_version_tuple, f"Agent {agent_id} version {new_version} is invalid" ++ assert old_version_tuple, f"Agent {agent_id} version {old_version} is invalid" ++ ++ # Check that the new version is greater than current version ++ if new_version_tuple <= old_version_tuple: ++ logger.warning( ++ "Agent %s API version %s is lower or equal to previous version %s", ++ agent_id, ++ new_version, ++ old_version, ++ ) ++ return None ++ ++ logger.info("Agent %s new API version %s is supported", agent_id, new_version) ++ session = get_session() ++ agent["supported_version"] = new_version ++ ++ # Remove keys that should not go to the DB ++ agent_db = dict(agent) ++ for key in exclude_db: ++ if key in agent_db: ++ del agent_db[key] ++ ++ session.query(VerfierMain).filter_by(agent_id=agent_id).update(agent_db) # pyright: ignore ++ session.commit() ++ else: ++ logger.warning("Agent %s new API version %s is not supported", agent_id, new_version) ++ return None ++ ++ except SQLAlchemyError as e: ++ logger.error("SQLAlchemy Error updating API version for agent %s: %s", agent_id, e) ++ return None ++ except Exception as e: ++ logger.exception(e) ++ return None ++ ++ logger.info("Agent %s API version updated to %s", agent["agent_id"], agent["supported_version"]) ++ return agent ++ ++ + async def invoke_get_quote( + agent: Dict[str, Any], runtime_policy: str, need_pubkey: bool, timeout: float = 60.0 + ) -> None: +@@ -1028,15 +1103,43 @@ async def invoke_get_quote( + # this is a connection error, retry get quote + if response.status_code in [408, 500, 599]: + asyncio.ensure_future(process_agent(agent, states.GET_QUOTE_RETRY)) +- else: +- # catastrophic error, do not continue +- logger.critical( +- "Unexpected Get Quote response error for cloud agent %s, Error: %s", +- agent["agent_id"], +- response.status_code, +- ) +- failure.add_event("no_quote", "Unexpected Get Quote reponse from agent", False) +- asyncio.ensure_future(process_agent(agent, states.FAILED, failure)) ++ return ++ ++ if response.status_code == 400: ++ try: ++ json_response = json.loads(response.body) ++ if "API version not supported" in json_response["status"]: ++ update = update_agent_api_version(agent) ++ updated = await update ++ ++ if updated: ++ asyncio.ensure_future(process_agent(updated, states.GET_QUOTE_RETRY)) ++ else: ++ logger.warning("Could not update stored agent %s API version", agent["agent_id"]) ++ failure.add_event( ++ "version_not_supported", ++ {"context": "Agent API version not supported", "data": json_response}, ++ False, ++ ) ++ asyncio.ensure_future(process_agent(agent, states.FAILED, failure)) ++ return ++ ++ except Exception as e: ++ logger.exception(e) ++ failure.add_event( ++ "exception", {"context": "Agent caused the verifier to throw an exception", "data": str(e)}, False ++ ) ++ asyncio.ensure_future(process_agent(agent, states.FAILED, failure)) ++ return ++ ++ # catastrophic error, do not continue ++ logger.critical( ++ "Unexpected Get Quote response error for cloud agent %s, Error: %s", ++ agent["agent_id"], ++ response.status_code, ++ ) ++ failure.add_event("no_quote", "Unexpected Get Quote reponse from agent", False) ++ asyncio.ensure_future(process_agent(agent, states.FAILED, failure)) + else: + try: + json_response = json.loads(response.body) +@@ -1100,15 +1203,43 @@ async def invoke_provide_v(agent: Dict[str, Any], timeout: float = 60.0) -> None + if response.status_code != 200: + if response.status_code in [408, 500, 599]: + asyncio.ensure_future(process_agent(agent, states.PROVIDE_V_RETRY)) +- else: +- # catastrophic error, do not continue +- logger.critical( +- "Unexpected Provide V response error for cloud agent %s, Error: %s", +- agent["agent_id"], +- response.status_code, +- ) +- failure.add_event("no_v", {"message": "Unexpected provide V response", "data": response.status_code}, False) +- asyncio.ensure_future(process_agent(agent, states.FAILED, failure)) ++ return ++ ++ if response.status_code == 400: ++ try: ++ json_response = json.loads(response.body) ++ if "API version not supported" in json_response["status"]: ++ update = update_agent_api_version(agent) ++ updated = await update ++ ++ if updated: ++ asyncio.ensure_future(process_agent(updated, states.PROVIDE_V_RETRY)) ++ else: ++ logger.warning("Could not update stored agent %s API version", agent["agent_id"]) ++ failure.add_event( ++ "version_not_supported", ++ {"context": "Agent API version not supported", "data": json_response}, ++ False, ++ ) ++ asyncio.ensure_future(process_agent(agent, states.FAILED, failure)) ++ return ++ ++ except Exception as e: ++ logger.exception(e) ++ failure.add_event( ++ "exception", {"context": "Agent caused the verifier to throw an exception", "data": str(e)}, False ++ ) ++ asyncio.ensure_future(process_agent(agent, states.FAILED, failure)) ++ return ++ ++ # catastrophic error, do not continue ++ logger.critical( ++ "Unexpected Provide V response error for cloud agent %s, Error: %s", ++ agent["agent_id"], ++ response.status_code, ++ ) ++ failure.add_event("no_v", {"message": "Unexpected provide V response", "data": response.status_code}, False) ++ asyncio.ensure_future(process_agent(agent, states.FAILED, failure)) + else: + asyncio.ensure_future(process_agent(agent, states.GET_QUOTE)) + +@@ -1134,6 +1265,24 @@ async def invoke_notify_error(agent: Dict[str, Any], tosend: Dict[str, Any], tim + agent["agent_id"], + ) + elif response.status_code != 200: ++ if response.status_code == 400: ++ try: ++ json_response = json.loads(response.body) ++ if "API version not supported" in json_response["status"]: ++ update = update_agent_api_version(agent) ++ updated = await update ++ ++ if updated: ++ asyncio.ensure_future(invoke_notify_error(updated, tosend)) ++ else: ++ logger.warning("Could not update stored agent %s API version", agent["agent_id"]) ++ ++ return ++ ++ except Exception as e: ++ logger.exception(e) ++ return ++ + logger.warning( + "Unexpected Notify Revocation response error for cloud agent %s, Error: %s", + agent["agent_id"], diff --git a/SPECS/keylime.spec b/SPECS/keylime.spec index 8a47a55..f106cb3 100644 --- a/SPECS/keylime.spec +++ b/SPECS/keylime.spec @@ -1,5 +1,5 @@ %global srcname keylime -%global policy_version 1.0.0 +%global policy_version 1.2.0 %global with_selinux 1 %global selinuxtype targeted @@ -8,8 +8,8 @@ %global debug_package %{nil} Name: keylime -Version: 6.5.2 -Release: 4%{?dist} +Version: 7.3.0 +Release: 9%{?dist} Summary: Open source TPM software for Bootstrapping and Maintaining Trust URL: https://github.com/keylime/keylime @@ -17,9 +17,17 @@ Source0: https://github.com/keylime/keylime/archive/refs/tags/v%{version} Source1: %{srcname}.sysusers Source2: https://github.com/RedHat-SP-Security/%{name}-selinux/archive/v%{policy_version}/keylime-selinux-%{policy_version}.tar.gz -Patch: 0001-Do-not-use-default-values-that-need-reading-the-conf.patch -Patch: 0002-Switch-to-sha256-hashes-for-signatures.patch -Patch: 0003-logging-remove-option-to-log-into-separate-file.patch +Patch: 0001-Remove-usage-of-Required-NotRequired-typing_ext.patch +Patch: 0002-Allow-keylime_server_t-tcp-connect-to-several-domain.patch +Patch: 0003-Use-version-2.0-as-the-minimum-for-the-configuration.patch +Patch: 0004-Duplicate-str_to_version-for-the-upgrade-tool.patch +Patch: 0005-elchecking-example-add-ignores-for-EV_PLATFORM_CONFI.patch +Patch: 0006-Revert-mapping-changes.patch +Patch: 0007-Handle-session-close-using-a-session-manager.patch +Patch: 0008-verifier-should-read-parameters-from-verifier.conf-o.patch +Patch: 0009-CVE-2023-38201.patch +Patch: 0010-CVE-2023-38200.patch +Patch: 0011-Automatically-update-agent-API-version.patch License: ASL 2.0 and MIT @@ -31,6 +39,7 @@ BuildRequires: python3-dbus BuildRequires: python3-jinja2 BuildRequires: python3-setuptools BuildRequires: systemd-rpm-macros +BuildRequires: tpm2-abrmd-selinux Requires: python3-%{srcname} = %{version}-%{release} Requires: %{srcname}-base = %{version}-%{release} @@ -52,7 +61,9 @@ Summary: The base package contains the default configuration License: MIT +Requires(pre): python3-jinja2 Requires(pre): shadow-utils +Requires(pre): util-linux Requires: procps-ng Requires: tpm2-tss @@ -88,6 +99,7 @@ Requires: python3-gpg Requires: python3-lark-parser Requires: python3-pyasn1 Requires: python3-pyasn1-modules +Requires: python3-jsonschema Requires: tpm2-tools Requires: openssl @@ -169,33 +181,26 @@ for comp in "verifier" "tenant" "registrar" "ca" "logging"; do install -Dpm 400 config/${comp}.conf %{buildroot}/%{_sysconfdir}/%{srcname} done -# Remove agent. -rm -f %{buildroot}/%{_bindir}/%{srcname}_agent -rm -f %{buildroot}%{python3_sitelib}/%{srcname}/__pycache__/%{srcname}_agent* -rm -f %{buildroot}%{python3_sitelib}/%{srcname}/cmd/__pycache__/agent.* -rm -f %{buildroot}%{python3_sitelib}/%{srcname}/cmd/agent.* -rm -f %{buildroot}%{python3_sitelib}/%{srcname}/%{srcname}_agent.* - -# Remove misc progs. -rm -f %{buildroot}/%{_bindir}/%{srcname}_ima_emulator -rm -f %{buildroot}/%{_bindir}/%{srcname}_userdata_encrypt - # Ship some scripts. mkdir -p %{buildroot}/%{_datadir}/%{srcname}/scripts -for s in create_allowlist.sh \ +for s in create_runtime_policy.sh \ create_mb_refstate \ - create_policy \ ek-openssl-verify; do install -Dpm 755 scripts/${s} \ %{buildroot}/%{_datadir}/%{srcname}/scripts/${s} done +# Ship configuration templates. +cp -r ./templates %{buildroot}%{_datadir}/%{srcname}/templates/ + +mkdir -p --mode=0755 %{buildroot}/%{_bindir} +install -Dpm 755 ./keylime/cmd/convert_config.py %{buildroot}/%{_bindir}/keylime_upgrade_config + %if 0%{?with_selinux} install -D -m 0644 %{srcname}.pp.bz2 %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype}/%{srcname}.pp.bz2 install -D -p -m 0644 keylime-selinux-%{policy_version}/%{srcname}.if %{buildroot}%{_datadir}/selinux/devel/include/distributed/%{srcname}.if %endif - install -Dpm 644 ./services/%{srcname}_verifier.service \ %{buildroot}%{_unitdir}/%{srcname}_verifier.service @@ -216,6 +221,10 @@ install -p -D -m 0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/%{srcname}.conf %sysusers_create_compat %{SOURCE1} exit 0 +%post base +/usr/bin/keylime_upgrade_config --component ca --component logging >/dev/null +exit 0 + %posttrans base if [ -d %{_sysconfdir}/%{srcname} ]; then chmod 500 %{_sysconfdir}/%{srcname} @@ -227,7 +236,6 @@ if [ -d %{_sysconfdir}/%{srcname} ]; then done fi - [ -d %{_sharedstatedir}/%{srcname} ] && \ chown -R %{srcname} %{_sharedstatedir}/%{srcname}/ @@ -240,10 +248,18 @@ fi exit 0 %post verifier +/usr/bin/keylime_upgrade_config --component verifier >/dev/null %systemd_post %{srcname}_verifier.service +exit 0 %post registrar +/usr/bin/keylime_upgrade_config --component registrar >/dev/null %systemd_post %{srcname}_registrar.service +exit 0 + +%post tenant +/usr/bin/keylime_upgrade_config --component tenant >/dev/null +exit 0 %preun verifier %systemd_preun %{srcname}_verifier.service @@ -288,16 +304,15 @@ fi %files verifier %license LICENSE %attr(500,%{srcname},%{srcname}) %dir %{_sysconfdir}/%{srcname}/verifier.conf.d -%config(noreplace) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/verifier.conf +%config(noreplace) %verify(not md5 size mode mtime) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/verifier.conf %{_bindir}/%{srcname}_verifier %{_bindir}/%{srcname}_ca -%{_bindir}/%{srcname}_migrations_apply %{_unitdir}/keylime_verifier.service %files registrar %license LICENSE %attr(500,%{srcname},%{srcname}) %dir %{_sysconfdir}/%{srcname}/registrar.conf.d -%config(noreplace) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/registrar.conf +%config(noreplace) %verify(not md5 size mode mtime) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/registrar.conf %{_bindir}/%{srcname}_registrar %{_unitdir}/keylime_registrar.service @@ -311,7 +326,7 @@ fi %files tenant %license LICENSE %attr(500,%{srcname},%{srcname}) %dir %{_sysconfdir}/%{srcname}/tenant.conf.d -%config(noreplace) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/tenant.conf +%config(noreplace) %verify(not md5 size mode mtime) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/tenant.conf %{_bindir}/%{srcname}_tenant %files -n python3-%{srcname} @@ -319,15 +334,18 @@ fi %{python3_sitelib}/%{srcname}-*.egg-info/ %{python3_sitelib}/%{srcname} %{_datadir}/%{srcname}/scripts/create_mb_refstate -%{_datadir}/%{srcname}/scripts/create_policy -%{_bindir}/keylime_convert_ima_policy +%{_bindir}/keylime_attest +%{_bindir}/keylime_convert_runtime_policy +%{_bindir}/keylime_create_policy +%{_bindir}/keylime_sign_runtime_policy +%{_bindir}/keylime_userdata_encrypt %files base %license LICENSE %doc README.md %attr(500,%{srcname},%{srcname}) %dir %{_sysconfdir}/%{srcname}/{ca,logging}.conf.d -%config(noreplace) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/ca.conf -%config(noreplace) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/logging.conf +%config(noreplace) %verify(not md5 size mode mtime) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/ca.conf +%config(noreplace) %verify(not md5 size mode mtime) %attr(400,%{srcname},%{srcname}) %{_sysconfdir}/%{srcname}/logging.conf %attr(700,%{srcname},%{srcname}) %dir %{_rundir}/%{srcname} %attr(700,%{srcname},%{srcname}) %dir %{_localstatedir}/log/%{srcname} %attr(700,%{srcname},%{srcname}) %dir %{_sharedstatedir}/%{srcname} @@ -335,13 +353,60 @@ fi %attr(400,%{srcname},%{srcname}) %{_sharedstatedir}/%{srcname}/tpm_cert_store/*.pem %{_tmpfilesdir}/%{srcname}.conf %{_sysusersdir}/%{srcname}.conf -%{_datadir}/%{srcname}/scripts/create_allowlist.sh +%{_datadir}/%{srcname}/scripts/create_runtime_policy.sh %{_datadir}/%{srcname}/scripts/ek-openssl-verify +%{_datadir}/%{srcname}/templates +%{_bindir}/keylime_upgrade_config %files %license LICENSE %changelog +* Wed Sep 06 2023 Sergio Correia - 7.3.0-9 +- Rebuild for properly tagging the resulting build + Resolves: RHEL-1898 + +* Fri Sep 01 2023 Sergio Correia - 7.3.0-8 +- Add missing dependencies python3-jinja2 and util-linux + Resolves: RHEL-1898 + +* Mon Aug 28 2023 Anderson Toshiyuki Sasaki - 7.3.0-7 +- Automatically update agent API version + Resolves: RHEL-1518 + +* Mon Aug 28 2023 Sergio Correia - 7.3.0-6 +- Fix registrar is subject to a DoS against SSL (CVE-2023-38200) + Resolves: rhbz#2222694 + +* Fri Aug 25 2023 Anderson Toshiyuki Sasaki - 7.3.0-5 +- Fix challenge-protocol bypass during agent registration (CVE-2023-38201) + Resolves: rhbz#2222695 + +* Tue Aug 22 2023 Sergio Correia - 7.3.0-4 +- Update spec file to use %verify(not md5 size mode mtime) for files updated in %post scriptlets + Resolves: RHEL-475 + +* Tue Aug 15 2023 Sergio Correia - 7.3.0-3 +- Fix Keylime configuration upgrades issues introduced in last rebase + Resolves: RHEL-475 +- Handle session close using a session manager + Resolves: RHEL-1252 +- Add ignores for EV_PLATFORM_CONFIG_FLAGS + Resolves: RHEL-947 + +* Tue Aug 8 2023 Patrik Koncity - 7.3.0-2 +- Keylime SELinux policy provides more restricted ports. +- New SELinux label for ports used by keylime. +- Adding tabrmd interfaces allow unix stream socket communication and dbus communication. +- Allow the keylime_server_t domain to get the attributes of all filesystems. + Resolves: RHEL-595 + Resolves: RHEL-390 + Resolves: RHEL-948 + +* Wed Jul 19 2023 Sergio Correia - 7.3.0-1 +- Update to 7.3.0 + Resolves: RHEL-475 + * Fri Jan 13 2023 Sergio Correia - 6.5.2-4 - Backport upstream PR#1240 - logging: remove option to log into separate file Resolves: rhbz#2154584 - keylime verifier is not logging to /var/log/keylime