ac7d03
From e8f329dd4340d5216d86160a8065e0530b981b47 Mon Sep 17 00:00:00 2001
ac7d03
From: Pavel Vomacka <pvomacka@redhat.com>
ac7d03
Date: Thu, 6 Apr 2017 16:15:47 +0200
ac7d03
Subject: [PATCH] Turn on NSSOCSP check in mod_nss conf
ac7d03
ac7d03
Turn on NSSOCSP directive during install/replica install/upgrade.
ac7d03
That check whether the certificate which is used for login is
ac7d03
revoked or not using OSCP.
ac7d03
ac7d03
Marks the server cert in httpd NSS DB as trusted peer ('P,,')
ac7d03
to avoid chicken and egg problem when it is needed to contact
ac7d03
the OCSP responder when httpd is starting.
ac7d03
ac7d03
https://pagure.io/freeipa/issue/6370
ac7d03
ac7d03
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
ac7d03
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
ac7d03
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
ac7d03
Reviewed-By: Martin Basti <mbasti@redhat.com>
ac7d03
---
ac7d03
 freeipa.spec.in                       |  4 ++++
ac7d03
 install/restart_scripts/restart_httpd | 14 +++++++++++++-
ac7d03
 ipaserver/install/httpinstance.py     | 30 ++++++++++++++++++++++++++++++
ac7d03
 ipaserver/install/server/upgrade.py   | 25 +++++++++++++++++++++++++
ac7d03
 ipaserver/setup.py                    |  1 +
ac7d03
 5 files changed, 73 insertions(+), 1 deletion(-)
ac7d03
ac7d03
diff --git a/freeipa.spec.in b/freeipa.spec.in
ac7d03
index 1dd550bd39fd14349ede58bde337783aa5c0ea04..1b3ed15036eab6262b144d970cbdfdad31ac13ea 100644
ac7d03
--- a/freeipa.spec.in
ac7d03
+++ b/freeipa.spec.in
ac7d03
@@ -195,6 +195,7 @@ BuildRequires:  python-nose
ac7d03
 BuildRequires:  python-paste
ac7d03
 BuildRequires:  systemd-python
ac7d03
 BuildRequires:  python2-jinja2
ac7d03
+BuildRequires:  python-augeas
ac7d03
 
ac7d03
 %if 0%{?with_python3}
ac7d03
 # FIXME: this depedency is missing - server will not work
ac7d03
@@ -232,6 +233,7 @@ BuildRequires:  python3-nose
ac7d03
 BuildRequires:  python3-paste
ac7d03
 BuildRequires:  python3-systemd
ac7d03
 BuildRequires:  python3-jinja2
ac7d03
+BuildRequires:  python3-augeas
ac7d03
 %endif # with_python3
ac7d03
 %endif # with_lint
ac7d03
 
ac7d03
@@ -355,6 +357,7 @@ Requires: python-dns >= 1.15
ac7d03
 Requires: python-kdcproxy >= 0.3
ac7d03
 Requires: rpm-libs
ac7d03
 Requires: pki-base-python2
ac7d03
+Requires: python-augeas
ac7d03
 
ac7d03
 %description -n python2-ipaserver
ac7d03
 IPA is an integrated solution to provide centrally managed Identity (users,
ac7d03
@@ -384,6 +387,7 @@ Requires: python3-pyasn1
ac7d03
 Requires: python3-dbus
ac7d03
 Requires: python3-dns >= 1.15
ac7d03
 Requires: python3-kdcproxy >= 0.3
ac7d03
+Requires: python3-augeas
ac7d03
 Requires: rpm-libs
ac7d03
 Requires: pki-base-python3
ac7d03
 
ac7d03
diff --git a/install/restart_scripts/restart_httpd b/install/restart_scripts/restart_httpd
ac7d03
index d1684812904a9d32842a0ca548ec6b9df5a5a0b7..b661b82b896b109c3859ac82c2d84ab27b839f72 100644
ac7d03
--- a/install/restart_scripts/restart_httpd
ac7d03
+++ b/install/restart_scripts/restart_httpd
ac7d03
@@ -21,11 +21,23 @@
ac7d03
 
ac7d03
 import syslog
ac7d03
 import traceback
ac7d03
+from ipalib import api
ac7d03
 from ipaplatform import services
ac7d03
-from ipaserver.install import certs
ac7d03
+from ipaplatform.paths import paths
ac7d03
+from ipaserver.install import certs, installutils
ac7d03
 
ac7d03
 
ac7d03
 def _main():
ac7d03
+
ac7d03
+    api.bootstrap(in_server=True, context='restart', confdir=paths.ETC_IPA)
ac7d03
+    api.finalize()
ac7d03
+
ac7d03
+    db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR)
ac7d03
+    nickname = installutils.get_directive(paths.HTTPD_NSS_CONF, "NSSNickname")
ac7d03
+
ac7d03
+    # Add trust flag which set certificate trusted for SSL connections.
ac7d03
+    db.trust_root_cert(nickname, "P,,")
ac7d03
+
ac7d03
     syslog.syslog(syslog.LOG_NOTICE, 'certmonger restarted httpd')
ac7d03
 
ac7d03
     try:
ac7d03
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
ac7d03
index 7898c53bc02785e2750dba61a5696f079355c9d7..ab688a85f157b1886842a91bb7d22f9ea99e3615 100644
ac7d03
--- a/ipaserver/install/httpinstance.py
ac7d03
+++ b/ipaserver/install/httpinstance.py
ac7d03
@@ -29,6 +29,7 @@ import pipes
ac7d03
 import locale
ac7d03
 
ac7d03
 import six
ac7d03
+from augeas import Augeas
ac7d03
 
ac7d03
 from ipalib.install import certmonger
ac7d03
 from ipaserver.install import service
ac7d03
@@ -153,6 +154,7 @@ class HTTPInstance(service.Service):
ac7d03
                   self.set_mod_nss_protocol)
ac7d03
         self.step("setting mod_nss password file", self.__set_mod_nss_passwordfile)
ac7d03
         self.step("enabling mod_nss renegotiate", self.enable_mod_nss_renegotiate)
ac7d03
+        self.step("enabling mod_nss OCSP", self.enable_mod_nss_ocsp)
ac7d03
         self.step("adding URL rewriting rules", self.__add_include)
ac7d03
         self.step("configuring httpd", self.__configure_http)
ac7d03
         self.step("setting up httpd keytab", self.request_service_keytab)
ac7d03
@@ -259,6 +261,31 @@ class HTTPInstance(service.Service):
ac7d03
         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSRenegotiation', 'on', False)
ac7d03
         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSRequireSafeNegotiation', 'on', False)
ac7d03
 
ac7d03
+    def enable_mod_nss_ocsp(self):
ac7d03
+        aug = Augeas(flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD)
ac7d03
+
ac7d03
+        aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
ac7d03
+        aug.set('/augeas/load/Httpd/incl', paths.HTTPD_NSS_CONF)
ac7d03
+        aug.load()
ac7d03
+
ac7d03
+        path = '/files{}/VirtualHost'.format(paths.HTTPD_NSS_CONF)
ac7d03
+
ac7d03
+        ocsp_comment = aug.get(
ac7d03
+                        '{}/#comment[.=~regexp("NSSOCSP .*")]'.format(path))
ac7d03
+        ocsp_dir = aug.get('{}/directive[.="NSSOCSP"]'.format(path))
ac7d03
+
ac7d03
+        if ocsp_dir is None and ocsp_comment is not None:
ac7d03
+            # Directive is missing, comment is present
ac7d03
+            aug.set('{}/#comment[.=~regexp("NSSOCSP .*")]'.format(path),
ac7d03
+                    'NSSOCSP')
ac7d03
+            aug.rename('{}/#comment[.="NSSOCSP"]'.format(path), 'directive')
ac7d03
+        elif ocsp_dir is None:
ac7d03
+            # Directive is missing and comment is missing
ac7d03
+            aug.set('{}/directive[last()+1]'.format(path), "NSSOCSP")
ac7d03
+
ac7d03
+        aug.set('{}/directive[. = "NSSOCSP"]/arg'.format(path), 'on')
ac7d03
+        aug.save()
ac7d03
+
ac7d03
     def set_mod_nss_cipher_suite(self):
ac7d03
         ciphers = ','.join(NSS_CIPHER_SUITE)
ac7d03
         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSCipherSuite', ciphers, False)
ac7d03
@@ -351,6 +378,7 @@ class HTTPInstance(service.Service):
ac7d03
                           create=True)
ac7d03
         self.disable_system_trust()
ac7d03
         self.create_password_conf()
ac7d03
+
ac7d03
         if self.pkcs12_info:
ac7d03
             if self.ca_is_configured:
ac7d03
                 trust_flags = 'CT,C,C'
ac7d03
@@ -375,6 +403,8 @@ class HTTPInstance(service.Service):
ac7d03
             self.__set_mod_nss_nickname(nickname)
ac7d03
             self.add_cert_to_service()
ac7d03
 
ac7d03
+            db.trust_root_cert(nickname, "P,,")
ac7d03
+
ac7d03
         else:
ac7d03
             if not self.promote:
ac7d03
                 ca_args = [
ac7d03
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
ac7d03
index 9aec2d857aee1a601f351218e253d44b14f6d4ec..7b0476d442902f2c3dc65819d54953e820f5e560 100644
ac7d03
--- a/ipaserver/install/server/upgrade.py
ac7d03
+++ b/ipaserver/install/server/upgrade.py
ac7d03
@@ -1392,6 +1392,24 @@ def fix_trust_flags():
ac7d03
     sysupgrade.set_upgrade_state('http', 'fix_trust_flags', True)
ac7d03
 
ac7d03
 
ac7d03
+def fix_server_cert_trust_flags():
ac7d03
+    root_logger.info(
ac7d03
+        '[Fixing server certificate trust flags in %s]' %
ac7d03
+        paths.HTTPD_ALIAS_DIR)
ac7d03
+
ac7d03
+    if sysupgrade.get_upgrade_state('http', 'fix_serv_cert_trust_flags'):
ac7d03
+        root_logger.info("Trust flags already processed")
ac7d03
+        return
ac7d03
+
ac7d03
+    db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR)
ac7d03
+    sc_nickname = installutils.get_directive(paths.HTTPD_NSS_CONF,
ac7d03
+                                             "NSSNickname")
ac7d03
+    # Add trust flag which set certificate trusted for SSL connections.
ac7d03
+    db.trust_root_cert(sc_nickname, "P,,")
ac7d03
+
ac7d03
+    sysupgrade.set_upgrade_state('http', 'fix_serv_cert_trust_flags', True)
ac7d03
+
ac7d03
+
ac7d03
 def update_mod_nss_protocol(http):
ac7d03
     root_logger.info('[Updating mod_nss protocol versions]')
ac7d03
 
ac7d03
@@ -1404,6 +1422,11 @@ def update_mod_nss_protocol(http):
ac7d03
     sysupgrade.set_upgrade_state('nss.conf', 'protocol_updated_tls12', True)
ac7d03
 
ac7d03
 
ac7d03
+def enable_mod_nss_ocsp(http):
ac7d03
+    root_logger.info('[Updating mod_nss enabling OCSP]')
ac7d03
+    http.enable_mod_nss_ocsp()
ac7d03
+
ac7d03
+
ac7d03
 def update_mod_nss_cipher_suite(http):
ac7d03
     root_logger.info('[Updating mod_nss cipher suite]')
ac7d03
 
ac7d03
@@ -1671,7 +1694,9 @@ def upgrade_configuration():
ac7d03
     update_ipa_httpd_service_conf(http)
ac7d03
     update_mod_nss_protocol(http)
ac7d03
     update_mod_nss_cipher_suite(http)
ac7d03
+    enable_mod_nss_ocsp(http)
ac7d03
     fix_trust_flags()
ac7d03
+    fix_server_cert_trust_flags()
ac7d03
     update_http_keytab(http)
ac7d03
     http.configure_gssproxy()
ac7d03
     http.start()
ac7d03
diff --git a/ipaserver/setup.py b/ipaserver/setup.py
ac7d03
index 42b0c1b0618ef9867acb1fe2add5702a756cf2d2..e0b69e547ef8c2b76ce14ab27c1c29260e33f57f 100755
ac7d03
--- a/ipaserver/setup.py
ac7d03
+++ b/ipaserver/setup.py
ac7d03
@@ -60,6 +60,7 @@ if __name__ == '__main__':
ac7d03
             "pyasn1",
ac7d03
             "pyldap",
ac7d03
             "six",
ac7d03
+            "python-augeas",
ac7d03
             # not available on PyPI
ac7d03
             # "python-libipa_hbac",
ac7d03
             # "python-sss",
ac7d03
-- 
ac7d03
2.9.3
ac7d03