Blob Blame History Raw
From e8f329dd4340d5216d86160a8065e0530b981b47 Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvomacka@redhat.com>
Date: Thu, 6 Apr 2017 16:15:47 +0200
Subject: [PATCH] Turn on NSSOCSP check in mod_nss conf

Turn on NSSOCSP directive during install/replica install/upgrade.
That check whether the certificate which is used for login is
revoked or not using OSCP.

Marks the server cert in httpd NSS DB as trusted peer ('P,,')
to avoid chicken and egg problem when it is needed to contact
the OCSP responder when httpd is starting.

https://pagure.io/freeipa/issue/6370

Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
Reviewed-By: Martin Basti <mbasti@redhat.com>
---
 freeipa.spec.in                       |  4 ++++
 install/restart_scripts/restart_httpd | 14 +++++++++++++-
 ipaserver/install/httpinstance.py     | 30 ++++++++++++++++++++++++++++++
 ipaserver/install/server/upgrade.py   | 25 +++++++++++++++++++++++++
 ipaserver/setup.py                    |  1 +
 5 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 1dd550bd39fd14349ede58bde337783aa5c0ea04..1b3ed15036eab6262b144d970cbdfdad31ac13ea 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -195,6 +195,7 @@ BuildRequires:  python-nose
 BuildRequires:  python-paste
 BuildRequires:  systemd-python
 BuildRequires:  python2-jinja2
+BuildRequires:  python-augeas
 
 %if 0%{?with_python3}
 # FIXME: this depedency is missing - server will not work
@@ -232,6 +233,7 @@ BuildRequires:  python3-nose
 BuildRequires:  python3-paste
 BuildRequires:  python3-systemd
 BuildRequires:  python3-jinja2
+BuildRequires:  python3-augeas
 %endif # with_python3
 %endif # with_lint
 
@@ -355,6 +357,7 @@ Requires: python-dns >= 1.15
 Requires: python-kdcproxy >= 0.3
 Requires: rpm-libs
 Requires: pki-base-python2
+Requires: python-augeas
 
 %description -n python2-ipaserver
 IPA is an integrated solution to provide centrally managed Identity (users,
@@ -384,6 +387,7 @@ Requires: python3-pyasn1
 Requires: python3-dbus
 Requires: python3-dns >= 1.15
 Requires: python3-kdcproxy >= 0.3
+Requires: python3-augeas
 Requires: rpm-libs
 Requires: pki-base-python3
 
diff --git a/install/restart_scripts/restart_httpd b/install/restart_scripts/restart_httpd
index d1684812904a9d32842a0ca548ec6b9df5a5a0b7..b661b82b896b109c3859ac82c2d84ab27b839f72 100644
--- a/install/restart_scripts/restart_httpd
+++ b/install/restart_scripts/restart_httpd
@@ -21,11 +21,23 @@
 
 import syslog
 import traceback
+from ipalib import api
 from ipaplatform import services
-from ipaserver.install import certs
+from ipaplatform.paths import paths
+from ipaserver.install import certs, installutils
 
 
 def _main():
+
+    api.bootstrap(in_server=True, context='restart', confdir=paths.ETC_IPA)
+    api.finalize()
+
+    db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR)
+    nickname = installutils.get_directive(paths.HTTPD_NSS_CONF, "NSSNickname")
+
+    # Add trust flag which set certificate trusted for SSL connections.
+    db.trust_root_cert(nickname, "P,,")
+
     syslog.syslog(syslog.LOG_NOTICE, 'certmonger restarted httpd')
 
     try:
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index 7898c53bc02785e2750dba61a5696f079355c9d7..ab688a85f157b1886842a91bb7d22f9ea99e3615 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -29,6 +29,7 @@ import pipes
 import locale
 
 import six
+from augeas import Augeas
 
 from ipalib.install import certmonger
 from ipaserver.install import service
@@ -153,6 +154,7 @@ class HTTPInstance(service.Service):
                   self.set_mod_nss_protocol)
         self.step("setting mod_nss password file", self.__set_mod_nss_passwordfile)
         self.step("enabling mod_nss renegotiate", self.enable_mod_nss_renegotiate)
+        self.step("enabling mod_nss OCSP", self.enable_mod_nss_ocsp)
         self.step("adding URL rewriting rules", self.__add_include)
         self.step("configuring httpd", self.__configure_http)
         self.step("setting up httpd keytab", self.request_service_keytab)
@@ -259,6 +261,31 @@ class HTTPInstance(service.Service):
         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSRenegotiation', 'on', False)
         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSRequireSafeNegotiation', 'on', False)
 
+    def enable_mod_nss_ocsp(self):
+        aug = Augeas(flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD)
+
+        aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
+        aug.set('/augeas/load/Httpd/incl', paths.HTTPD_NSS_CONF)
+        aug.load()
+
+        path = '/files{}/VirtualHost'.format(paths.HTTPD_NSS_CONF)
+
+        ocsp_comment = aug.get(
+                        '{}/#comment[.=~regexp("NSSOCSP .*")]'.format(path))
+        ocsp_dir = aug.get('{}/directive[.="NSSOCSP"]'.format(path))
+
+        if ocsp_dir is None and ocsp_comment is not None:
+            # Directive is missing, comment is present
+            aug.set('{}/#comment[.=~regexp("NSSOCSP .*")]'.format(path),
+                    'NSSOCSP')
+            aug.rename('{}/#comment[.="NSSOCSP"]'.format(path), 'directive')
+        elif ocsp_dir is None:
+            # Directive is missing and comment is missing
+            aug.set('{}/directive[last()+1]'.format(path), "NSSOCSP")
+
+        aug.set('{}/directive[. = "NSSOCSP"]/arg'.format(path), 'on')
+        aug.save()
+
     def set_mod_nss_cipher_suite(self):
         ciphers = ','.join(NSS_CIPHER_SUITE)
         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSCipherSuite', ciphers, False)
@@ -351,6 +378,7 @@ class HTTPInstance(service.Service):
                           create=True)
         self.disable_system_trust()
         self.create_password_conf()
+
         if self.pkcs12_info:
             if self.ca_is_configured:
                 trust_flags = 'CT,C,C'
@@ -375,6 +403,8 @@ class HTTPInstance(service.Service):
             self.__set_mod_nss_nickname(nickname)
             self.add_cert_to_service()
 
+            db.trust_root_cert(nickname, "P,,")
+
         else:
             if not self.promote:
                 ca_args = [
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 9aec2d857aee1a601f351218e253d44b14f6d4ec..7b0476d442902f2c3dc65819d54953e820f5e560 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1392,6 +1392,24 @@ def fix_trust_flags():
     sysupgrade.set_upgrade_state('http', 'fix_trust_flags', True)
 
 
+def fix_server_cert_trust_flags():
+    root_logger.info(
+        '[Fixing server certificate trust flags in %s]' %
+        paths.HTTPD_ALIAS_DIR)
+
+    if sysupgrade.get_upgrade_state('http', 'fix_serv_cert_trust_flags'):
+        root_logger.info("Trust flags already processed")
+        return
+
+    db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR)
+    sc_nickname = installutils.get_directive(paths.HTTPD_NSS_CONF,
+                                             "NSSNickname")
+    # Add trust flag which set certificate trusted for SSL connections.
+    db.trust_root_cert(sc_nickname, "P,,")
+
+    sysupgrade.set_upgrade_state('http', 'fix_serv_cert_trust_flags', True)
+
+
 def update_mod_nss_protocol(http):
     root_logger.info('[Updating mod_nss protocol versions]')
 
@@ -1404,6 +1422,11 @@ def update_mod_nss_protocol(http):
     sysupgrade.set_upgrade_state('nss.conf', 'protocol_updated_tls12', True)
 
 
+def enable_mod_nss_ocsp(http):
+    root_logger.info('[Updating mod_nss enabling OCSP]')
+    http.enable_mod_nss_ocsp()
+
+
 def update_mod_nss_cipher_suite(http):
     root_logger.info('[Updating mod_nss cipher suite]')
 
@@ -1671,7 +1694,9 @@ def upgrade_configuration():
     update_ipa_httpd_service_conf(http)
     update_mod_nss_protocol(http)
     update_mod_nss_cipher_suite(http)
+    enable_mod_nss_ocsp(http)
     fix_trust_flags()
+    fix_server_cert_trust_flags()
     update_http_keytab(http)
     http.configure_gssproxy()
     http.start()
diff --git a/ipaserver/setup.py b/ipaserver/setup.py
index 42b0c1b0618ef9867acb1fe2add5702a756cf2d2..e0b69e547ef8c2b76ce14ab27c1c29260e33f57f 100755
--- a/ipaserver/setup.py
+++ b/ipaserver/setup.py
@@ -60,6 +60,7 @@ if __name__ == '__main__':
             "pyasn1",
             "pyldap",
             "six",
+            "python-augeas",
             # not available on PyPI
             # "python-libipa_hbac",
             # "python-sss",
-- 
2.9.3