From 4db78c4b469b2ba6be651a03fcd63e97948979f9 Mon Sep 17 00:00:00 2001 From: Marco Fargetta Date: Fri, 21 Jul 2023 18:09:17 +0200 Subject: [PATCH] Add callback for CRL validation at application level Add new field in CMS for a callback validation of certificate instantiated by PKISocketFactory. This is useful for OCSP where the OCSP protocol cannot be enabled and the verification is done on CRLs. Solve RHCS-4262 --- .../netscape/cms/ocsp/CRLLdapValidator.java | 80 +++++++++++++++++++ .../java/com/netscape/cms/ocsp/LDAPStore.java | 2 +- .../org/dogtagpki/server/ocsp/OCSPEngine.java | 13 +++ .../java/com/netscape/cmscore/apps/CMS.java | 11 +++ .../cmscore/ldapconn/PKISocketFactory.java | 4 +- 5 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 base/ocsp/src/main/java/com/netscape/cms/ocsp/CRLLdapValidator.java diff --git a/base/ocsp/src/main/java/com/netscape/cms/ocsp/CRLLdapValidator.java b/base/ocsp/src/main/java/com/netscape/cms/ocsp/CRLLdapValidator.java new file mode 100644 index 00000000000..712262c9803 --- /dev/null +++ b/base/ocsp/src/main/java/com/netscape/cms/ocsp/CRLLdapValidator.java @@ -0,0 +1,80 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.ocsp; + +import java.security.cert.X509CRLEntry; +import java.util.Enumeration; + +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.netscape.security.x509.X509CRLImpl; +import org.mozilla.jss.ssl.SSLCertificateApprovalCallback; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; + +public class CRLLdapValidator implements SSLCertificateApprovalCallback { + + public static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CRLLdapValidator.class); + + private LDAPStore crlStore; + + + + public CRLLdapValidator(LDAPStore crlStore) { + super(); + this.crlStore = crlStore; + } + + + @Override + public boolean approve(X509Certificate certificate, ValidityStatus currentStatus) { + logger.info("CRLLdapValidator: validate of peer's certificate for the connection " + certificate.getSubjectDN().toString()); + ICRLIssuingPointRecord pt = null; + try { + Enumeration eCRL = crlStore.searchAllCRLIssuingPointRecord(-1); + while (eCRL.hasMoreElements() && pt == null) { + ICRLIssuingPointRecord tPt = eCRL.nextElement(); + logger.debug("CRLLdapValidator: CRL check issuer " + tPt.getId()); + if(tPt.getId().equals(certificate.getIssuerDN().toString())) { + pt = tPt; + } + } + } catch (EBaseException e) { + logger.error("CRLLdapValidator: problem find CRL issuing point for " + certificate.getIssuerDN().toString()); + return false; + } + if (pt == null) { + logger.error("CRLLdapValidator: CRL issuing point not found for " + certificate.getIssuerDN().toString()); + return false; + } + try { + X509CRLImpl crl = new X509CRLImpl(pt.getCRL()); + X509CRLEntry crlentry = crl.getRevokedCertificate(certificate.getSerialNumber()); + + if (crlentry == null) { + if (crlStore.isNotFoundGood()) { + return true; + } + } + } catch (Exception e) { + logger.error("CRLLdapValidator: crl check error. " + e.getMessage()); + } + return false; + } + +} diff --git a/base/ocsp/src/main/java/com/netscape/cms/ocsp/LDAPStore.java b/base/ocsp/src/main/java/com/netscape/cms/ocsp/LDAPStore.java index fb4e321877c..60d212ca6d2 100644 --- a/base/ocsp/src/main/java/com/netscape/cms/ocsp/LDAPStore.java +++ b/base/ocsp/src/main/java/com/netscape/cms/ocsp/LDAPStore.java @@ -17,7 +17,6 @@ // --- END COPYRIGHT BLOCK --- package com.netscape.cms.ocsp; -import java.lang.Integer; import java.math.BigInteger; import java.security.MessageDigest; import java.security.cert.X509CRL; @@ -238,6 +237,7 @@ public void startup() throws EBaseException { updater.start(); } + CMS.setApprovalCallbask(new CRLLdapValidator(this)); } @Override diff --git a/base/ocsp/src/main/java/org/dogtagpki/server/ocsp/OCSPEngine.java b/base/ocsp/src/main/java/org/dogtagpki/server/ocsp/OCSPEngine.java index 0832864ab1d..e11e594b154 100644 --- a/base/ocsp/src/main/java/org/dogtagpki/server/ocsp/OCSPEngine.java +++ b/base/ocsp/src/main/java/org/dogtagpki/server/ocsp/OCSPEngine.java @@ -24,8 +24,11 @@ import com.netscape.certsrv.base.ISubsystem; import com.netscape.cmscore.apps.CMS; import com.netscape.cmscore.apps.CMSEngine; +import com.netscape.cmscore.apps.DatabaseConfig; import com.netscape.cmscore.apps.EngineConfig; import com.netscape.cmscore.base.ConfigStorage; +import com.netscape.cmscore.ldapconn.PKISocketConfig; +import com.netscape.cmsutil.password.IPasswordStore; import com.netscape.ocsp.OCSPAuthority; @WebListener @@ -68,6 +71,16 @@ public void initSubsystem(ISubsystem subsystem, IConfigStore subsystemConfig) th } } + @Override + public void initDBSubsystem() throws Exception { + + DatabaseConfig dbConfig = config.getDatabaseConfig(); + PKISocketConfig socketConfig = config.getSocketConfig(); + IPasswordStore passwordStore = getPasswordStore(); + + dbSubsystem.init(dbConfig, socketConfig, passwordStore); + } + protected void startupSubsystems() throws Exception { for (ISubsystem subsystem : subsystems.values()) { diff --git a/base/server/src/main/java/com/netscape/cmscore/apps/CMS.java b/base/server/src/main/java/com/netscape/cmscore/apps/CMS.java index a5b8a1be6f3..966e11b8507 100644 --- a/base/server/src/main/java/com/netscape/cmscore/apps/CMS.java +++ b/base/server/src/main/java/com/netscape/cmscore/apps/CMS.java @@ -23,6 +23,7 @@ import java.util.Locale; import java.util.ResourceBundle; +import org.mozilla.jss.ssl.SSLCertificateApprovalCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,6 +54,8 @@ public final class CMS { private static CMSEngine engine; + private static SSLCertificateApprovalCallback approvalCallbask; + public static CMSEngine getCMSEngine() { return engine; } @@ -61,6 +64,14 @@ public static void setCMSEngine(CMSEngine engine) { CMS.engine = engine; } + public static SSLCertificateApprovalCallback getApprovalCallbask() { + return approvalCallbask; + } + + public static void setApprovalCallbask(SSLCertificateApprovalCallback approvalCallbask) { + CMS.approvalCallbask = approvalCallbask; + } + /** * Return the product name from /usr/share/pki/CS_SERVER_VERSION * which is provided by the server theme package. diff --git a/base/server/src/main/java/com/netscape/cmscore/ldapconn/PKISocketFactory.java b/base/server/src/main/java/com/netscape/cmscore/ldapconn/PKISocketFactory.java index ccbebdc7c0c..aa99b8ab1c8 100644 --- a/base/server/src/main/java/com/netscape/cmscore/ldapconn/PKISocketFactory.java +++ b/base/server/src/main/java/com/netscape/cmscore/ldapconn/PKISocketFactory.java @@ -151,7 +151,7 @@ public SSLSocket makeSSLSocket(String host, int port) throws UnknownHostExceptio SSLSocket s; if (mClientAuthCertNickname == null) { - s = new SSLSocket(host, port); + s = new SSLSocket(host, port, null, 0, CMS.getApprovalCallbask(), null); } else { // Let's create a selection callback in the case the client auth @@ -161,7 +161,7 @@ public SSLSocket makeSSLSocket(String host, int port) throws UnknownHostExceptio Socket js = new Socket(InetAddress.getByName(host), port); s = new SSLSocket(js, host, - null, + CMS.getApprovalCallbask(), new SSLClientCertificateSelectionCB(mClientAuthCertNickname)); }