95ea96
From e4084fc1608cd13e73ce201471ff518105f4b9f5 Mon Sep 17 00:00:00 2001
95ea96
From: Christian Heimes <cheimes@redhat.com>
95ea96
Date: Fri, 22 Jun 2018 12:17:23 +0200
95ea96
Subject: [PATCH] Ensure that public cert and CA bundle are readable
95ea96
95ea96
In CIS hardened mode, the process umask is 027. This results in some
95ea96
files not being world readable. Ensure that write_certificate_list()
95ea96
calls in client installer, server installer, and upgrader create cert
95ea96
bundles with permission bits 0644.
95ea96
95ea96
Fixes: https://pagure.io/freeipa/issue/7594
95ea96
Signed-off-by: Christian Heimes <cheimes@redhat.com>
95ea96
Reviewed-By: Tibor Dudlak <tdudlak@redhat.com>
95ea96
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
95ea96
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
95ea96
---
95ea96
 ipaclient/install/client.py                | 10 +++++++---
95ea96
 ipaclient/install/ipa_certupdate.py        |  4 ++--
95ea96
 ipalib/x509.py                             |  5 ++++-
95ea96
 ipaserver/install/cainstance.py            |  2 +-
95ea96
 ipaserver/install/httpinstance.py          |  2 +-
95ea96
 ipaserver/install/installutils.py          |  6 +++++-
95ea96
 ipaserver/install/krbinstance.py           |  2 +-
95ea96
 ipaserver/install/server/replicainstall.py |  2 +-
95ea96
 8 files changed, 22 insertions(+), 11 deletions(-)
95ea96
95ea96
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
95ea96
index 0fbe31b762561b3e2ee2f35a666a93de8857bced..a1c74b41f790917a302ab32f6be7a4d23a989708 100644
95ea96
--- a/ipaclient/install/client.py
95ea96
+++ b/ipaclient/install/client.py
95ea96
@@ -1837,7 +1837,7 @@ def get_ca_certs(fstore, options, server, basedn, realm):
95ea96
 
95ea96
     if ca_certs is not None:
95ea96
         try:
95ea96
-            x509.write_certificate_list(ca_certs, ca_file)
95ea96
+            x509.write_certificate_list(ca_certs, ca_file, mode=0o644)
95ea96
         except Exception as e:
95ea96
             if os.path.exists(ca_file):
95ea96
                 try:
95ea96
@@ -2775,10 +2775,14 @@ def _install(options):
95ea96
 
95ea96
     x509.write_certificate_list(
95ea96
         [c for c, n, t, u in ca_certs if t is not False],
95ea96
-        paths.KDC_CA_BUNDLE_PEM)
95ea96
+        paths.KDC_CA_BUNDLE_PEM,
95ea96
+        mode=0o644
95ea96
+    )
95ea96
     x509.write_certificate_list(
95ea96
         [c for c, n, t, u in ca_certs if t is not False],
95ea96
-        paths.CA_BUNDLE_PEM)
95ea96
+        paths.CA_BUNDLE_PEM,
95ea96
+        mode=0o644
95ea96
+    )
95ea96
 
95ea96
     # Add the CA certificates to the IPA NSS database
95ea96
     logger.debug("Adding CA certificates to the IPA NSS database.")
95ea96
diff --git a/ipaclient/install/ipa_certupdate.py b/ipaclient/install/ipa_certupdate.py
95ea96
index 875cd7000c09aee044c5141a889617c9195182b1..878af250428fbf122c048d612fefc17e4ea674ff 100644
95ea96
--- a/ipaclient/install/ipa_certupdate.py
95ea96
+++ b/ipaclient/install/ipa_certupdate.py
95ea96
@@ -187,10 +187,10 @@ def update_server(certs):
95ea96
     update_file(paths.CACERT_PEM, certs)
95ea96
 
95ea96
 
95ea96
-def update_file(filename, certs, mode=0o444):
95ea96
+def update_file(filename, certs, mode=0o644):
95ea96
     certs = (c[0] for c in certs if c[2] is not False)
95ea96
     try:
95ea96
-        x509.write_certificate_list(certs, filename)
95ea96
+        x509.write_certificate_list(certs, filename, mode=mode)
95ea96
     except Exception as e:
95ea96
         logger.error("failed to update %s: %s", filename, e)
95ea96
 
95ea96
diff --git a/ipalib/x509.py b/ipalib/x509.py
95ea96
index 67a9af4c5d3456f8cdd6d966373be75d7036f1b7..cfacfa6fc784a4bc1559d68da0cc505874346e22 100644
95ea96
--- a/ipalib/x509.py
95ea96
+++ b/ipalib/x509.py
95ea96
@@ -36,6 +36,7 @@ import datetime
95ea96
 import ipaddress
95ea96
 import ssl
95ea96
 import base64
95ea96
+import os
95ea96
 import re
95ea96
 
95ea96
 from cryptography import x509 as crypto_x509
95ea96
@@ -519,7 +520,7 @@ def write_certificate(cert, filename):
95ea96
         raise errors.FileError(reason=str(e))
95ea96
 
95ea96
 
95ea96
-def write_certificate_list(certs, filename):
95ea96
+def write_certificate_list(certs, filename, mode=None):
95ea96
     """
95ea96
     Write a list of certificates to a file in PEM format.
95ea96
 
95ea96
@@ -529,6 +530,8 @@ def write_certificate_list(certs, filename):
95ea96
 
95ea96
     try:
95ea96
         with open(filename, 'wb') as f:
95ea96
+            if mode is not None:
95ea96
+                os.fchmod(f.fileno(), mode)
95ea96
             for cert in certs:
95ea96
                 f.write(cert.public_bytes(Encoding.PEM))
95ea96
     except (IOError, OSError) as e:
95ea96
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
95ea96
index ffcebd719a16ebc5a991b35507b96411ad31eb10..d6e467097808594756d947fa721b8cf10fe7d043 100644
95ea96
--- a/ipaserver/install/cainstance.py
95ea96
+++ b/ipaserver/install/cainstance.py
95ea96
@@ -848,7 +848,7 @@ class CAInstance(DogtagInstance):
95ea96
         for path in [paths.IPA_CA_CRT,
95ea96
                      paths.KDC_CA_BUNDLE_PEM,
95ea96
                      paths.CA_BUNDLE_PEM]:
95ea96
-            x509.write_certificate_list(certlist, path)
95ea96
+            x509.write_certificate_list(certlist, path, mode=0o644)
95ea96
 
95ea96
     def __request_ra_certificate(self):
95ea96
         """
95ea96
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
95ea96
index 3f83248dd89118aeecfbf458c5079dde8b2cb93d..05b88998353597aebc39b6dad5e1a688dca84f49 100644
95ea96
--- a/ipaserver/install/httpinstance.py
95ea96
+++ b/ipaserver/install/httpinstance.py
95ea96
@@ -481,7 +481,7 @@ class HTTPInstance(service.Service):
95ea96
             raise RuntimeError("HTTPD cert was issued by an unknown CA.")
95ea96
         # at this time we can assume any CA cert will be valid since this is
95ea96
         # only run during installation
95ea96
-        x509.write_certificate_list(certlist, paths.CA_CRT)
95ea96
+        x509.write_certificate_list(certlist, paths.CA_CRT, mode=0o644)
95ea96
 
95ea96
     def is_kdcproxy_configured(self):
95ea96
         """Check if KDC proxy has already been configured in the past"""
95ea96
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
95ea96
index 6614da69a0a046cdfa1b309f77972ead9de1279f..64beeffaebc4bcfe2b11dbf1109e54d7a9479d67 100644
95ea96
--- a/ipaserver/install/installutils.py
95ea96
+++ b/ipaserver/install/installutils.py
95ea96
@@ -1314,7 +1314,11 @@ def load_external_cert(files, ca_subject):
95ea96
     cert_file.flush()
95ea96
 
95ea96
     ca_file = tempfile.NamedTemporaryFile()
95ea96
-    x509.write_certificate_list(ca_cert_chain[1:], ca_file.name)
95ea96
+    x509.write_certificate_list(
95ea96
+        ca_cert_chain[1:],
95ea96
+        ca_file.name,
95ea96
+        mode=0o644
95ea96
+    )
95ea96
     ca_file.flush()
95ea96
 
95ea96
     return cert_file, ca_file
95ea96
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
95ea96
index 09cafb7b84623594fe88083f5b914cee0f050409..a3079bd6304a41116f9aa5e78b6c6c71d72d7aa6 100644
95ea96
--- a/ipaserver/install/krbinstance.py
95ea96
+++ b/ipaserver/install/krbinstance.py
95ea96
@@ -495,7 +495,7 @@ class KrbInstance(service.Service):
95ea96
                                           self.api.env.realm,
95ea96
                                           False)
95ea96
         ca_certs = [c for c, _n, t, _u in ca_certs if t is not False]
95ea96
-        x509.write_certificate_list(ca_certs, paths.CACERT_PEM)
95ea96
+        x509.write_certificate_list(ca_certs, paths.CACERT_PEM, mode=0o644)
95ea96
 
95ea96
     def issue_selfsigned_pkinit_certs(self):
95ea96
         self._call_certmonger(certmonger_ca="SelfSign")
95ea96
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
95ea96
index 525a62c474c7429b7efee4853eb71e487e656bba..eb354f81ba6e4cbc3848f9c24338fb85cc7639ae 100644
95ea96
--- a/ipaserver/install/server/replicainstall.py
95ea96
+++ b/ipaserver/install/server/replicainstall.py
95ea96
@@ -147,7 +147,7 @@ def install_ca_cert(ldap, base_dn, realm, cafile, destfile=paths.IPA_CA_CRT):
95ea96
                 pass
95ea96
         else:
95ea96
             certs = [c[0] for c in certs if c[2] is not False]
95ea96
-            x509.write_certificate_list(certs, destfile)
95ea96
+            x509.write_certificate_list(certs, destfile, mode=0o644)
95ea96
     except Exception as e:
95ea96
         raise ScriptError("error copying files: " + str(e))
95ea96
     return destfile
95ea96
-- 
95ea96
2.17.1
95ea96