URL: https://github.com/freeipa/freeipa/pull/2057 Author: tiran Title: #2057: Ensure that public cert and CA bundle are readable Action: opened
PR body: """ In CIS hardened mode, the process umask is 027. This results in some files not being world readable. Ensure that write_certificate_list() calls in client installer, server installer, and upgrader create cert bundles with permission bits 0644. Make CA bundles, certs, and cert directories world-accessible in upgrader. Fixes: pagure.io/freeipa/issue/7594 """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/2057/head:pr2057 git checkout pr2057
From d35680f5d41417c1e20c27bba8ff0747b916e38d Mon Sep 17 00:00:00 2001 From: Christian Heimes <chei...@redhat.com> Date: Fri, 22 Jun 2018 12:17:23 +0200 Subject: [PATCH 1/4] Ensure that public cert and CA bundle are readable In CIS hardened mode, the process umask is 027. This results in some files not being world readable. Ensure that write_certificate_list() calls in client installer, server installer, and upgrader create cert bundles with permission bits 0644. Fixes: https://pagure.io/freeipa/issue/7594 Signed-off-by: Christian Heimes <chei...@redhat.com> --- ipaclient/install/client.py | 10 +++++++--- ipaclient/install/ipa_certupdate.py | 4 ++-- ipalib/x509.py | 4 +++- ipaserver/install/cainstance.py | 2 +- ipaserver/install/httpinstance.py | 2 +- ipaserver/install/installutils.py | 6 +++++- ipaserver/install/krbinstance.py | 2 +- ipaserver/install/server/replicainstall.py | 2 +- 8 files changed, 21 insertions(+), 11 deletions(-) diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py index 64e3ef90d9..72858490da 100644 --- a/ipaclient/install/client.py +++ b/ipaclient/install/client.py @@ -1879,7 +1879,7 @@ def http_url(): if ca_certs is not None: try: - x509.write_certificate_list(ca_certs, ca_file) + x509.write_certificate_list(ca_certs, ca_file, mode=0o644) except Exception as e: if os.path.exists(ca_file): try: @@ -2874,10 +2874,14 @@ def _install(options): x509.write_certificate_list( [c for c, n, t, u in ca_certs if t is not False], - paths.KDC_CA_BUNDLE_PEM) + paths.KDC_CA_BUNDLE_PEM, + mode=0o644 + ) x509.write_certificate_list( [c for c, n, t, u in ca_certs if t is not False], - paths.CA_BUNDLE_PEM) + paths.CA_BUNDLE_PEM, + mode=0o644 + ) # Add the CA certificates to the IPA NSS database logger.debug("Adding CA certificates to the IPA NSS database.") diff --git a/ipaclient/install/ipa_certupdate.py b/ipaclient/install/ipa_certupdate.py index a67a0eae60..ea3765fcf6 100644 --- a/ipaclient/install/ipa_certupdate.py +++ b/ipaclient/install/ipa_certupdate.py @@ -186,10 +186,10 @@ def update_server(certs): update_file(paths.CACERT_PEM, certs) -def update_file(filename, certs, mode=0o444): +def update_file(filename, certs, mode=0o644): certs = (c[0] for c in certs if c[2] is not False) try: - x509.write_certificate_list(certs, filename) + x509.write_certificate_list(certs, filename, mode=mode) except Exception as e: logger.error("failed to update %s: %s", filename, e) diff --git a/ipalib/x509.py b/ipalib/x509.py index 7986ddbf5f..11d390d20a 100644 --- a/ipalib/x509.py +++ b/ipalib/x509.py @@ -553,7 +553,7 @@ def write_certificate(cert, filename): raise errors.FileError(reason=str(e)) -def write_certificate_list(certs, filename): +def write_certificate_list(certs, filename, mode=None): """ Write a list of certificates to a file in PEM format. @@ -563,6 +563,8 @@ def write_certificate_list(certs, filename): try: with open(filename, 'wb') as f: + if mode is not None: + os.fchmod(f.fileno(), mode) for cert in certs: f.write(cert.public_bytes(Encoding.PEM)) except (IOError, OSError) as e: diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index 6f95c8254d..8d01f37924 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -848,7 +848,7 @@ def __export_ca_chain(self): for path in [paths.IPA_CA_CRT, paths.KDC_CA_BUNDLE_PEM, paths.CA_BUNDLE_PEM]: - x509.write_certificate_list(certlist, path) + x509.write_certificate_list(certlist, path, mode=0o644) def __request_ra_certificate(self): """ diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index d91fb4c10f..3fc21fd3f9 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -432,7 +432,7 @@ def __publish_ca_cert(self): raise RuntimeError("HTTPD cert was issued by an unknown CA.") # at this time we can assume any CA cert will be valid since this is # only run during installation - x509.write_certificate_list(certlist, paths.CA_CRT) + x509.write_certificate_list(certlist, paths.CA_CRT, mode=0o644) def is_kdcproxy_configured(self): """Check if KDC proxy has already been configured in the past""" diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py index 53b825aac3..a50084f18d 100644 --- a/ipaserver/install/installutils.py +++ b/ipaserver/install/installutils.py @@ -1104,7 +1104,11 @@ def load_external_cert(files, ca_subject): cert_file.flush() ca_file = tempfile.NamedTemporaryFile() - x509.write_certificate_list(ca_cert_chain[1:], ca_file.name) + x509.write_certificate_list( + ca_cert_chain[1:], + ca_file.name, + mode=0o644 + ) ca_file.flush() return cert_file, ca_file diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py index 6ba05b2867..023ccef5a4 100644 --- a/ipaserver/install/krbinstance.py +++ b/ipaserver/install/krbinstance.py @@ -502,7 +502,7 @@ def _install_pkinit_ca_bundle(self): self.api.env.realm, False) ca_certs = [c for c, _n, t, _u in ca_certs if t is not False] - x509.write_certificate_list(ca_certs, paths.CACERT_PEM) + x509.write_certificate_list(ca_certs, paths.CACERT_PEM, mode=0o644) def issue_selfsigned_pkinit_certs(self): self._call_certmonger(certmonger_ca="SelfSign") diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index caf3e8a54a..3ec2d6526a 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -145,7 +145,7 @@ def install_ca_cert(ldap, base_dn, realm, cafile, destfile=paths.IPA_CA_CRT): pass else: certs = [c[0] for c in certs if c[2] is not False] - x509.write_certificate_list(certs, destfile) + x509.write_certificate_list(certs, destfile, mode=0o644) except Exception as e: raise ScriptError("error copying files: " + str(e)) return destfile From 8b5e408f88d2ab0ca9c077219e1b6f479a972ca0 Mon Sep 17 00:00:00 2001 From: Christian Heimes <chei...@redhat.com> Date: Fri, 22 Jun 2018 12:22:06 +0200 Subject: [PATCH 2/4] Always make ipa.p11-kit world-readable Ensure that ipa.p11-kit is always world-readable. Fixes: https://pagure.io/freeipa/issue/7594 Signed-off-by: Christian Heimes <chei...@redhat.com> --- ipaplatform/redhat/tasks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py index eb75557a17..237681c0f3 100644 --- a/ipaplatform/redhat/tasks.py +++ b/ipaplatform/redhat/tasks.py @@ -280,6 +280,7 @@ def insert_ca_certs_into_systemwide_ca_store(self, ca_certs): try: f = open(new_cacert_path, 'w') + os.fchmod(f.fileno(), 0o644) except IOError as e: logger.info("Failed to open %s: %s", new_cacert_path, e) return False From 085e436b738eae641c5dac6736d7500736a463e3 Mon Sep 17 00:00:00 2001 From: Christian Heimes <chei...@redhat.com> Date: Fri, 22 Jun 2018 12:25:33 +0200 Subject: [PATCH 3/4] Make /etc/httpd/alias world readable & executable The directory /etc/httpd/alias contains public key material. It must be world readable and executable, so any client can read public certs. Note: executable for a directory means, that a process is allowed to traverse into the directory. Fixes: https://pagure.io/freeipa/issue/7594 Signed-off-by: Christian Heimes <chei...@redhat.com> --- ipaserver/install/httpinstance.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index 3fc21fd3f9..0341da8beb 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -181,7 +181,8 @@ def __configure_http(self): session_dir = os.path.dirname(self.sub_dict['GSSAPI_SESSION_KEY']) if not os.path.isdir(session_dir): os.makedirs(session_dir) - os.chmod(session_dir, 0o755) + # Must be world-readable / executable + os.chmod(session_dir, 0o755) target_fname = paths.HTTPD_IPA_CONF http_txt = ipautil.template_file( From 65e1ad2e3487b0d9ac63a9d3289c8e77dc8fb263 Mon Sep 17 00:00:00 2001 From: Christian Heimes <chei...@redhat.com> Date: Fri, 22 Jun 2018 12:53:19 +0200 Subject: [PATCH 4/4] Fix permission of public files in upgrader Make CA bundles, certs, and cert directories world-accessible in upgrader. Fixes: https://pagure.io/freeipa/issue/7594 Signed-off-by: Christian Heimes <chei...@redhat.com> --- ipaserver/install/server/upgrade.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index d102a47442..0fe3dd10a7 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -4,12 +4,14 @@ from __future__ import print_function, absolute_import +import errno import logging import re import os import shutil import pwd import fileinput +import stat import sys import tempfile from contextlib import contextmanager @@ -1700,6 +1702,34 @@ def migrate_to_authselect(): sysupgrade.set_upgrade_state('authcfg', 'migrated_to_authselect', True) +def fix_permissions(): + """Fix permission of public accessible files and directories + + In case IPA was installed with restricted umask, some public files and + directories may not be readable and accessible. + + See https://pagure.io/freeipa/issue/7594 + """ + candidates = [ + os.path.dirname(paths.GSSAPI_SESSION_KEY), + paths.CA_BUNDLE_PEM, + paths.KDC_CA_BUNDLE_PEM, + paths.IPA_CA_CRT, + paths.IPA_P11_KIT, + ] + for filename in candidates: + try: + s = os.stat(filename) + except OSError as e: + if e.errno != errno.ENOENT: + raise + continue + mode = 0o755 if stat.S_ISDIR(s.st_mode) else 0o644 + if mode != stat.S_IMODE(s.st_mode): + logger.debug("Fix permission of %s to %o", filename, mode) + os.chmod(filename, mode) + + def upgrade_configuration(): """ Execute configuration upgrade of the IPA services @@ -1724,6 +1754,7 @@ def upgrade_configuration(): ntpd_cleanup(fqdn, fstore) check_certs() + fix_permissions() auto_redirect = find_autoredirect(fqdn) sub_dict = dict(
_______________________________________________ FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/freeipa-devel@lists.fedorahosted.org/message/NRNXID6QSQQH6BFFKTRP7OGJIQD6BKI3/