diff --git a/SOURCES/pki-core-added-global-TCP-Keep-Alive-option.patch b/SOURCES/pki-core-added-global-TCP-Keep-Alive-option.patch new file mode 100644 index 0000000..5693769 --- /dev/null +++ b/SOURCES/pki-core-added-global-TCP-Keep-Alive-option.patch @@ -0,0 +1,779 @@ +commit 55a18f821446f69331b50b8126f86b30312245c2 +Author: Endi S. Dewata +Date: Sat Jan 7 02:32:47 2017 +0100 + + Added global TCP Keep-Alive option. + + A new tcp.keepAlive parameter has been added for CS.cfg to + configure the TCP Keep-Alive option for all LDAP connections + created by PKI server. By default the option is enabled. + + The LdapJssSSLSocketFactory has been modified to support both + plain and secure sockets. For clarity, the socket factory has been + renamed to PKISocketFactory. + + All codes that create LDAP connections have been modified to use + PKISocketFactory such that the TCP Keep-Alive option can be applied + globally. + + https://fedorahosted.org/pki/ticket/2564 + + (cherry picked from commit b3ee1c28f658a70468c5a5fcf3cb4840574be756) + (cherry picked from commit 4252656c27f230a5198a01a6085dad4b8e4df59f) + +diff --git a/base/common/src/com/netscape/certsrv/apps/CMS.java b/base/common/src/com/netscape/certsrv/apps/CMS.java +index bc82a98..907b5bb 100644 +--- a/base/common/src/com/netscape/certsrv/apps/CMS.java ++++ b/base/common/src/com/netscape/certsrv/apps/CMS.java +@@ -91,6 +91,7 @@ import com.netscape.cmsutil.password.IPasswordStore; + import netscape.ldap.LDAPConnection; + import netscape.ldap.LDAPException; + import netscape.ldap.LDAPSSLSocketFactoryExt; ++import netscape.ldap.LDAPSocketFactory; + import netscape.security.util.ObjectIdentifier; + import netscape.security.x509.Extension; + import netscape.security.x509.GeneralName; +@@ -1345,6 +1346,10 @@ public final class CMS { + return _engine.getLdapJssSSLSocketFactory(); + } + ++ public static LDAPSocketFactory getLDAPSocketFactory(boolean secure) { ++ return _engine.getLDAPSocketFactory(secure); ++ } ++ + /** + * Creates a LDAP Auth Info object. + * +diff --git a/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java b/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java +index f781c41..7cf73fa 100644 +--- a/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java ++++ b/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java +@@ -75,6 +75,7 @@ import com.netscape.cmsutil.password.IPasswordStore; + import netscape.ldap.LDAPConnection; + import netscape.ldap.LDAPException; + import netscape.ldap.LDAPSSLSocketFactoryExt; ++import netscape.ldap.LDAPSocketFactory; + import netscape.security.util.ObjectIdentifier; + import netscape.security.x509.Extension; + import netscape.security.x509.GeneralName; +@@ -648,6 +649,13 @@ public interface ICMSEngine extends ISubsystem { + public LDAPSSLSocketFactoryExt getLdapJssSSLSocketFactory(); + + /** ++ * Creates an LDAP socket factory. ++ * ++ * @return LDAP SSL socket factory ++ */ ++ public LDAPSocketFactory getLDAPSocketFactory(boolean secure); ++ ++ /** + * Creates a LDAP Auth Info object. + * + * @return LDAP authentication info +diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCaCertPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCaCertPublisher.java +index f740ef3..c7f818a 100644 +--- a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCaCertPublisher.java ++++ b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCaCertPublisher.java +@@ -22,6 +22,15 @@ import java.security.cert.X509Certificate; + import java.util.Locale; + import java.util.Vector; + ++import com.netscape.certsrv.apps.CMS; ++import com.netscape.certsrv.base.EBaseException; ++import com.netscape.certsrv.base.IConfigStore; ++import com.netscape.certsrv.base.IExtendedPluginInfo; ++import com.netscape.certsrv.ldap.ELdapException; ++import com.netscape.certsrv.ldap.ELdapServerDownException; ++import com.netscape.certsrv.logging.ILogger; ++import com.netscape.certsrv.publish.ILdapPublisher; ++ + import netscape.ldap.LDAPAttribute; + import netscape.ldap.LDAPConnection; + import netscape.ldap.LDAPEntry; +@@ -32,15 +41,6 @@ import netscape.ldap.LDAPSSLSocketFactoryExt; + import netscape.ldap.LDAPSearchResults; + import netscape.ldap.LDAPv2; + +-import com.netscape.certsrv.apps.CMS; +-import com.netscape.certsrv.base.EBaseException; +-import com.netscape.certsrv.base.IConfigStore; +-import com.netscape.certsrv.base.IExtendedPluginInfo; +-import com.netscape.certsrv.ldap.ELdapException; +-import com.netscape.certsrv.ldap.ELdapServerDownException; +-import com.netscape.certsrv.logging.ILogger; +-import com.netscape.certsrv.publish.ILdapPublisher; +- + /** + * Interface for publishing a CA certificate to + * +@@ -179,9 +179,11 @@ public class LdapCaCertPublisher + int portVal = Integer.parseInt(port); + int version = Integer.parseInt(mConfig.getString("version", "2")); + String cert_nick = mConfig.getString("clientCertNickname", null); +- LDAPSSLSocketFactoryExt sslSocket = null; ++ LDAPSSLSocketFactoryExt sslSocket; + if (cert_nick != null) { + sslSocket = CMS.getLdapJssSSLSocketFactory(cert_nick); ++ } else { ++ sslSocket = CMS.getLdapJssSSLSocketFactory(); + } + String mgr_dn = mConfig.getString("bindDN", null); + String mgr_pwd = mConfig.getString("bindPWD", null); +diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCrlPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCrlPublisher.java +index 80ffa3c..64df143 100644 +--- a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCrlPublisher.java ++++ b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapCrlPublisher.java +@@ -22,6 +22,15 @@ import java.security.cert.X509CRL; + import java.util.Locale; + import java.util.Vector; + ++import com.netscape.certsrv.apps.CMS; ++import com.netscape.certsrv.base.EBaseException; ++import com.netscape.certsrv.base.IConfigStore; ++import com.netscape.certsrv.base.IExtendedPluginInfo; ++import com.netscape.certsrv.ldap.ELdapException; ++import com.netscape.certsrv.ldap.ELdapServerDownException; ++import com.netscape.certsrv.logging.ILogger; ++import com.netscape.certsrv.publish.ILdapPublisher; ++ + import netscape.ldap.LDAPAttribute; + import netscape.ldap.LDAPConnection; + import netscape.ldap.LDAPConstraints; +@@ -33,15 +42,6 @@ import netscape.ldap.LDAPSSLSocketFactoryExt; + import netscape.ldap.LDAPSearchResults; + import netscape.ldap.LDAPv2; + +-import com.netscape.certsrv.apps.CMS; +-import com.netscape.certsrv.base.EBaseException; +-import com.netscape.certsrv.base.IConfigStore; +-import com.netscape.certsrv.base.IExtendedPluginInfo; +-import com.netscape.certsrv.ldap.ELdapException; +-import com.netscape.certsrv.ldap.ELdapServerDownException; +-import com.netscape.certsrv.logging.ILogger; +-import com.netscape.certsrv.publish.ILdapPublisher; +- + /** + * For publishing master or global CRL. + * Publishes (replaces) the CRL in the CA's LDAP entry. +@@ -170,9 +170,11 @@ public class LdapCrlPublisher implements ILdapPublisher, IExtendedPluginInfo { + int portVal = Integer.parseInt(port); + int version = Integer.parseInt(mConfig.getString("version", "2")); + String cert_nick = mConfig.getString("clientCertNickname", null); +- LDAPSSLSocketFactoryExt sslSocket = null; ++ LDAPSSLSocketFactoryExt sslSocket; + if (cert_nick != null) { + sslSocket = CMS.getLdapJssSSLSocketFactory(cert_nick); ++ } else { ++ sslSocket = CMS.getLdapJssSSLSocketFactory(); + } + String mgr_dn = mConfig.getString("bindDN", null); + String mgr_pwd = mConfig.getString("bindPWD", null); +diff --git a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapUserCertPublisher.java b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapUserCertPublisher.java +index a01cf80..e87fca9 100644 +--- a/base/server/cms/src/com/netscape/cms/publish/publishers/LdapUserCertPublisher.java ++++ b/base/server/cms/src/com/netscape/cms/publish/publishers/LdapUserCertPublisher.java +@@ -23,15 +23,6 @@ import java.util.Enumeration; + import java.util.Locale; + import java.util.Vector; + +-import netscape.ldap.LDAPAttribute; +-import netscape.ldap.LDAPConnection; +-import netscape.ldap.LDAPEntry; +-import netscape.ldap.LDAPException; +-import netscape.ldap.LDAPModification; +-import netscape.ldap.LDAPSSLSocketFactoryExt; +-import netscape.ldap.LDAPSearchResults; +-import netscape.ldap.LDAPv2; +- + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.base.EBaseException; + import com.netscape.certsrv.base.IConfigStore; +@@ -42,6 +33,15 @@ import com.netscape.certsrv.logging.AuditFormat; + import com.netscape.certsrv.logging.ILogger; + import com.netscape.certsrv.publish.ILdapPublisher; + ++import netscape.ldap.LDAPAttribute; ++import netscape.ldap.LDAPConnection; ++import netscape.ldap.LDAPEntry; ++import netscape.ldap.LDAPException; ++import netscape.ldap.LDAPModification; ++import netscape.ldap.LDAPSSLSocketFactoryExt; ++import netscape.ldap.LDAPSearchResults; ++import netscape.ldap.LDAPv2; ++ + /** + * Interface for mapping a X509 certificate to a LDAP entry + * +@@ -134,9 +134,11 @@ public class LdapUserCertPublisher implements ILdapPublisher, IExtendedPluginInf + int portVal = Integer.parseInt(port); + int version = Integer.parseInt(mConfig.getString("version", "2")); + String cert_nick = mConfig.getString("clientCertNickname", null); +- LDAPSSLSocketFactoryExt sslSocket = null; ++ LDAPSSLSocketFactoryExt sslSocket; + if (cert_nick != null) { + sslSocket = CMS.getLdapJssSSLSocketFactory(cert_nick); ++ } else { ++ sslSocket = CMS.getLdapJssSSLSocketFactory(); + } + String mgr_dn = mConfig.getString("bindDN", null); + String mgr_pwd = mConfig.getString("bindPWD", null); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java +index 423fad3..22dd8c1 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java +@@ -27,9 +27,6 @@ import javax.servlet.ServletException; + import javax.servlet.http.HttpServletRequest; + import javax.servlet.http.HttpServletResponse; + +-import netscape.ldap.LDAPConnection; +-import netscape.ldap.LDAPException; +- + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.authority.IAuthority; + import com.netscape.certsrv.authority.ICertAuthority; +@@ -67,6 +64,9 @@ import com.netscape.certsrv.publish.RulePlugin; + import com.netscape.certsrv.security.ICryptoSubsystem; + import com.netscape.cmsutil.password.IPasswordStore; + ++import netscape.ldap.LDAPConnection; ++import netscape.ldap.LDAPException; ++ + /** + * A class representing an publishing servlet for the + * Publishing subsystem. This servlet is responsible +@@ -770,14 +770,13 @@ public class PublisherAdminServlet extends AdminServlet { + } + } else { + try { ++ conn = new LDAPConnection( ++ CMS.getLDAPSocketFactory(secure)); + if (secure) { +- conn = new LDAPConnection( +- CMS.getLdapJssSSLSocketFactory()); + params.put(Constants.PR_CONN_INITED, + "Create ssl LDAPConnection" + + dashes(70 - 25) + " Success"); + } else { +- conn = new LDAPConnection(); + params.put(Constants.PR_CONN_INITED, + "Create LDAPConnection" + + dashes(70 - 21) + " Success"); +diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java +index c62087e..af0d44e 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java +@@ -143,7 +143,7 @@ import com.netscape.cmscore.ldapconn.LdapAuthInfo; + import com.netscape.cmscore.ldapconn.LdapBoundConnFactory; + import com.netscape.cmscore.ldapconn.LdapBoundConnection; + import com.netscape.cmscore.ldapconn.LdapConnInfo; +-import com.netscape.cmscore.ldapconn.LdapJssSSLSocketFactory; ++import com.netscape.cmscore.ldapconn.PKISocketFactory; + import com.netscape.cmscore.logging.Auditor; + import com.netscape.cmscore.logging.LogSubsystem; + import com.netscape.cmscore.logging.Logger; +@@ -174,6 +174,7 @@ import com.netscape.cmsutil.util.Utils; + import netscape.ldap.LDAPConnection; + import netscape.ldap.LDAPException; + import netscape.ldap.LDAPSSLSocketFactoryExt; ++import netscape.ldap.LDAPSocketFactory; + import netscape.security.extensions.CertInfo; + import netscape.security.pkcs.ContentInfo; + import netscape.security.pkcs.PKCS7; +@@ -480,9 +481,7 @@ public class CMSEngine implements ICMSEngine { + String host = info.getHost(); + int port = info.getPort(); + +- LDAPConnection conn = info.getSecure() ? +- new LDAPConnection(CMS.getLdapJssSSLSocketFactory()) : +- new LDAPConnection(); ++ LDAPConnection conn = new LDAPConnection(CMS.getLDAPSocketFactory(info.getSecure())); + + System.out.println("testLDAPConnection connecting to " + host + ":" + port); + +@@ -1027,11 +1026,15 @@ public class CMSEngine implements ICMSEngine { + + public LDAPSSLSocketFactoryExt getLdapJssSSLSocketFactory( + String certNickname) { +- return new LdapJssSSLSocketFactory(certNickname); ++ return new PKISocketFactory(certNickname); + } + + public LDAPSSLSocketFactoryExt getLdapJssSSLSocketFactory() { +- return new LdapJssSSLSocketFactory(); ++ return new PKISocketFactory(true); ++ } ++ ++ public LDAPSocketFactory getLDAPSocketFactory(boolean secure) { ++ return new PKISocketFactory(secure); + } + + public ILdapAuthInfo getLdapAuthInfo() { +diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java +index 52cdc4b..5d5e142 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAnonConnection.java +@@ -40,7 +40,7 @@ public class LdapAnonConnection extends LDAPConnection { + */ + public LdapAnonConnection(LdapConnInfo connInfo) + throws LDAPException { +- super(connInfo.getSecure() ? new LdapJssSSLSocketFactory() : null); ++ super(new PKISocketFactory(connInfo.getSecure())); + + // Set option to automatically follow referrals. + // rebind info is also anonymous. +diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java +index 787967a..a326344 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapBoundConnection.java +@@ -19,6 +19,8 @@ package com.netscape.cmscore.ldapconn; + + import java.util.Properties; + ++import com.netscape.certsrv.apps.CMS; ++ + import netscape.ldap.LDAPConnection; + import netscape.ldap.LDAPException; + import netscape.ldap.LDAPRebind; +@@ -26,8 +28,6 @@ import netscape.ldap.LDAPRebindAuth; + import netscape.ldap.LDAPSocketFactory; + import netscape.ldap.LDAPv2; + +-import com.netscape.certsrv.apps.CMS; +- + /** + * A LDAP connection that is bound to a server host, port, secure type. + * and authentication. +@@ -56,8 +56,8 @@ public class LdapBoundConnection extends LDAPConnection { + // this LONG line to satisfy super being the first call. (yuk) + super( + authInfo.getAuthType() == LdapAuthInfo.LDAP_AUTHTYPE_SSLCLIENTAUTH ? +- new LdapJssSSLSocketFactory(authInfo.getParms()[0]) : +- (connInfo.getSecure() ? new LdapJssSSLSocketFactory() : null)); ++ new PKISocketFactory(authInfo.getParms()[0]) : ++ new PKISocketFactory(connInfo.getSecure())); + + // Set option to automatically follow referrals. + // Use the same credentials to follow referrals; this is the easiest +diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java +deleted file mode 100644 +index b54d1e2..0000000 +--- a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapJssSSLSocketFactory.java ++++ /dev/null +@@ -1,177 +0,0 @@ +-// --- 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.cmscore.ldapconn; +- +-import java.io.IOException; +-import java.net.InetAddress; +-import java.net.Socket; +-import java.net.UnknownHostException; +-import java.util.Iterator; +-import java.util.Vector; +- +-import netscape.ldap.LDAPException; +-import netscape.ldap.LDAPSSLSocketFactoryExt; +- +-import org.mozilla.jss.ssl.SSLClientCertificateSelectionCallback; +-import org.mozilla.jss.ssl.SSLHandshakeCompletedEvent; +-import org.mozilla.jss.ssl.SSLHandshakeCompletedListener; +-import org.mozilla.jss.ssl.SSLSocket; +- +-import com.netscape.certsrv.apps.CMS; +-import com.netscape.certsrv.logging.ILogger; +- +-/** +- * Uses HCL ssl socket. +- * +- * @author Lily Hsiao lhsiao@netscape.com +- */ +-public class LdapJssSSLSocketFactory implements LDAPSSLSocketFactoryExt { +- private String mClientAuthCertNickname = null; +- private boolean mClientAuth = false; +- +- public LdapJssSSLSocketFactory() { +- } +- +- public LdapJssSSLSocketFactory(String certNickname) { +- mClientAuthCertNickname = certNickname; +- } +- +- public Socket makeSocket(String host, int port) throws LDAPException { +- SSLSocket s = null; +- +- try { +- /* +- * let inherit TLS range and cipher settings +- */ +- +- if (mClientAuthCertNickname == null) { +- s = new SSLSocket(host, port); +- } +- else { +- //Let's create a selection callback in the case the client auth +- //No longer manually set the cert name. +- //This two step process, used in the JSS client auth test suite, +- //appears to be needed to get this working. +- +- Socket js = new Socket(InetAddress.getByName(host), port); +- s = new SSLSocket(js, host, +- null, +- new SSLClientCertificateSelectionCB(mClientAuthCertNickname)); +- } +- +- s.setUseClientMode(true); +- s.enableV2CompatibleHello(false); +- +- SSLHandshakeCompletedListener listener = null; +- +- listener = new ClientHandshakeCB(this); +- s.addHandshakeCompletedListener(listener); +- +- if (mClientAuthCertNickname != null) { +- mClientAuth = true; +- CMS.debug("LdapJssSSLSocket: set client auth cert nickname " + +- mClientAuthCertNickname); +- +- //We have already established the manual cert selection callback +- //Doing it this way will provide some debugging info on the candidate certs +- } +- s.forceHandshake(); +- +- } catch (UnknownHostException e) { +- log(ILogger.LL_FAILURE, +- CMS.getLogMessage("CMSCORE_LDAPCONN_UNKNOWN_HOST")); +- throw new LDAPException( +- "Cannot Create JSS SSL Socket - Unknown host: " + e); +- +- } catch (IOException e) { +- if (s != null) { +- try { +- s.close(); +- } catch (IOException e1) { +- e1.printStackTrace(); +- } +- } +- log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAPCONN_IO_ERROR", e.toString())); +- throw new LDAPException("IO Error creating JSS SSL Socket: " + e); +- } +- +- return s; +- } +- +- public boolean isClientAuth() { +- return mClientAuth; +- } +- +- public Object getCipherSuites() { +- return null; +- } +- +- public void log(int level, String msg) { +- } +- +- static class ClientHandshakeCB implements SSLHandshakeCompletedListener { +- Object sc; +- +- public ClientHandshakeCB(Object sc) { +- this.sc = sc; +- } +- +- public void handshakeCompleted(SSLHandshakeCompletedEvent event) { +- CMS.debug("SSL handshake happened"); +- } +- } +- +- static class SSLClientCertificateSelectionCB implements SSLClientCertificateSelectionCallback { +- String desiredCertName = null; +- +- public SSLClientCertificateSelectionCB(String clientAuthCertNickname) { +- CMS.debug("SSLClientCertificateSelectionCB: Setting desired cert nickname to: " + clientAuthCertNickname); +- desiredCertName = clientAuthCertNickname; +- } +- +- @Override +- public String select(Vector certs) { +- +- CMS.debug("SSLClientCertificatSelectionCB: Entering!"); +- +- if(desiredCertName == null) { +- return null; +- } +- +- @SuppressWarnings("unchecked") +- Iterator itr = certs.iterator(); +- String selection = null; +- +- while(itr.hasNext()){ +- String candidate = itr.next(); +- CMS.debug("Candidate cert: " + candidate); +- if(desiredCertName.equalsIgnoreCase(candidate)) { +- selection = candidate; +- CMS.debug("SSLClientCertificateSelectionCB: desired cert found in list: " + desiredCertName); +- break; +- } +- } +- +- CMS.debug("SSLClientCertificateSelectionCB: returning: " + selection); +- return selection; +- +- } +- +- } +- +-} +diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java +new file mode 100644 +index 0000000..d0c23ed +--- /dev/null ++++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java +@@ -0,0 +1,211 @@ ++// --- 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.cmscore.ldapconn; ++ ++import java.io.IOException; ++import java.net.InetAddress; ++import java.net.Socket; ++import java.net.UnknownHostException; ++import java.util.Iterator; ++import java.util.Vector; ++ ++import org.mozilla.jss.ssl.SSLClientCertificateSelectionCallback; ++import org.mozilla.jss.ssl.SSLHandshakeCompletedEvent; ++import org.mozilla.jss.ssl.SSLHandshakeCompletedListener; ++import org.mozilla.jss.ssl.SSLSocket; ++ ++import com.netscape.certsrv.apps.CMS; ++import com.netscape.certsrv.base.IConfigStore; ++ ++import netscape.ldap.LDAPException; ++import netscape.ldap.LDAPSSLSocketFactoryExt; ++ ++/** ++ * Uses HCL ssl socket. ++ * ++ * @author Lily Hsiao lhsiao@netscape.com ++ */ ++public class PKISocketFactory implements LDAPSSLSocketFactoryExt { ++ ++ private boolean secure; ++ private String mClientAuthCertNickname; ++ private boolean mClientAuth; ++ private boolean keepAlive; ++ ++ public PKISocketFactory() { ++ init(); ++ } ++ ++ public PKISocketFactory(boolean secure) { ++ this.secure = secure; ++ init(); ++ } ++ ++ public PKISocketFactory(String certNickname) { ++ this.secure = true; ++ mClientAuthCertNickname = certNickname; ++ init(); ++ } ++ ++ public void init() { ++ try { ++ IConfigStore cs = CMS.getConfigStore(); ++ keepAlive = cs.getBoolean("tcp.keepAlive", true); ++ CMS.debug("TCP Keep-Alive: " + keepAlive); ++ ++ } catch (Exception e) { ++ CMS.debug(e); ++ throw new RuntimeException("Unable to read TCP configuration: " + e, e); ++ } ++ } ++ ++ public SSLSocket makeSSLSocket(String host, int port) throws UnknownHostException, IOException { ++ ++ /* ++ * let inherit TLS range and cipher settings ++ */ ++ ++ SSLSocket s; ++ ++ if (mClientAuthCertNickname == null) { ++ s = new SSLSocket(host, port); ++ ++ } else { ++ // Let's create a selection callback in the case the client auth ++ // No longer manually set the cert name. ++ // This two step process, used in the JSS client auth test suite, ++ // appears to be needed to get this working. ++ ++ Socket js = new Socket(InetAddress.getByName(host), port); ++ s = new SSLSocket(js, host, ++ null, ++ new SSLClientCertificateSelectionCB(mClientAuthCertNickname)); ++ } ++ ++ s.setUseClientMode(true); ++ s.enableV2CompatibleHello(false); ++ ++ SSLHandshakeCompletedListener listener = null; ++ ++ listener = new ClientHandshakeCB(this); ++ s.addHandshakeCompletedListener(listener); ++ ++ if (mClientAuthCertNickname != null) { ++ mClientAuth = true; ++ CMS.debug("LdapJssSSLSocket: set client auth cert nickname " + ++ mClientAuthCertNickname); ++ ++ //We have already established the manual cert selection callback ++ //Doing it this way will provide some debugging info on the candidate certs ++ } ++ s.forceHandshake(); ++ ++ return s; ++ } ++ ++ public Socket makeSocket(String host, int port) throws LDAPException { ++ ++ Socket s = null; ++ ++ try { ++ if (!secure) { ++ s = new Socket(host, port); ++ ++ } else { ++ s = makeSSLSocket(host, port); ++ } ++ ++ s.setKeepAlive(keepAlive); ++ ++ } catch (Exception e) { ++ CMS.debug(e); ++ if (s != null) { ++ try { ++ s.close(); ++ } catch (IOException e1) { ++ CMS.debug(e1); ++ } ++ } ++ throw new LDAPException("Unable to create socket: " + e); ++ } ++ ++ return s; ++ } ++ ++ public boolean isClientAuth() { ++ return mClientAuth; ++ } ++ ++ public Object getCipherSuites() { ++ return null; ++ } ++ ++ public void log(int level, String msg) { ++ } ++ ++ static class ClientHandshakeCB implements SSLHandshakeCompletedListener { ++ Object sc; ++ ++ public ClientHandshakeCB(Object sc) { ++ this.sc = sc; ++ } ++ ++ public void handshakeCompleted(SSLHandshakeCompletedEvent event) { ++ CMS.debug("SSL handshake happened"); ++ } ++ } ++ ++ static class SSLClientCertificateSelectionCB implements SSLClientCertificateSelectionCallback { ++ String desiredCertName = null; ++ ++ public SSLClientCertificateSelectionCB(String clientAuthCertNickname) { ++ CMS.debug("SSLClientCertificateSelectionCB: Setting desired cert nickname to: " + clientAuthCertNickname); ++ desiredCertName = clientAuthCertNickname; ++ } ++ ++ @Override ++ public String select(Vector certs) { ++ ++ CMS.debug("SSLClientCertificatSelectionCB: Entering!"); ++ ++ if(desiredCertName == null) { ++ return null; ++ } ++ ++ @SuppressWarnings("unchecked") ++ Iterator itr = certs.iterator(); ++ String selection = null; ++ ++ while(itr.hasNext()){ ++ String candidate = itr.next(); ++ CMS.debug("Candidate cert: " + candidate); ++ if(desiredCertName.equalsIgnoreCase(candidate)) { ++ selection = candidate; ++ CMS.debug("SSLClientCertificateSelectionCB: desired cert found in list: " + desiredCertName); ++ break; ++ } ++ } ++ ++ CMS.debug("SSLClientCertificateSelectionCB: returning: " + selection); ++ return selection; ++ ++ } ++ ++ } ++ ++} +diff --git a/base/server/test/com/netscape/cmscore/app/CMSEngineDefaultStub.java b/base/server/test/com/netscape/cmscore/app/CMSEngineDefaultStub.java +index d2b7fe8..73d039f 100644 +--- a/base/server/test/com/netscape/cmscore/app/CMSEngineDefaultStub.java ++++ b/base/server/test/com/netscape/cmscore/app/CMSEngineDefaultStub.java +@@ -60,6 +60,7 @@ import com.netscape.cmsutil.password.IPasswordStore; + import netscape.ldap.LDAPConnection; + import netscape.ldap.LDAPException; + import netscape.ldap.LDAPSSLSocketFactoryExt; ++import netscape.ldap.LDAPSocketFactory; + import netscape.security.util.ObjectIdentifier; + import netscape.security.x509.Extension; + import netscape.security.x509.GeneralName; +@@ -344,6 +345,10 @@ public class CMSEngineDefaultStub implements ICMSEngine { + return null; + } + ++ public LDAPSocketFactory getLDAPSocketFactory(boolean secure) { ++ return null; ++ } ++ + public ILdapAuthInfo getLdapAuthInfo() { + return null; + } diff --git a/SOURCES/pki-core-added-option-to-remove-signing-cert-entry.patch b/SOURCES/pki-core-added-option-to-remove-signing-cert-entry.patch new file mode 100644 index 0000000..dabd033 --- /dev/null +++ b/SOURCES/pki-core-added-option-to-remove-signing-cert-entry.patch @@ -0,0 +1,193 @@ +commit 1dbe79d48ac48d320fb0d2cac0f20329846cdbb1 +Author: Ade Lee +Date: Fri Jan 20 11:01:41 2017 -0500 + + Add option to remove signing cert entry + + In the migration case, it is useful to delete the initially + created signing certificate database record and have that be + imported through the ldif data import instead. + + Therefore, we add an option to remove this entry. The user + also needs to provide the serial number for the entry. + + This resolves the following tickets/BZs: + BZ# 1409949/Trac 2573 - CA Certificate Issuance Date displayed + on CA website incorrect + BZ# 1409946/Trac 2571 - Request ID undefined for CA signing + certificate + + (cherry picked from commit 049a4e3e09328bfcdff62dc189ad95917647fb22) + (cherry picked from commit 42bc6fc8eeef3c8bea036a7fc327696983dcf17c) + +diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java b/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java +index 3c7e483..309f68d 100644 +--- a/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java ++++ b/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java +@@ -24,8 +24,7 @@ import java.net.MalformedURLException; + import java.net.URL; + import java.util.StringTokenizer; + +-import netscape.ldap.LDAPAttribute; +- ++import org.apache.commons.lang.StringUtils; + import org.dogtagpki.server.rest.SystemConfigService; + + import com.netscape.certsrv.apps.CMS; +@@ -41,6 +40,10 @@ import com.netscape.cms.servlet.csadmin.ConfigurationUtils; + import com.netscape.cmscore.base.LDAPConfigStore; + import com.netscape.cmscore.profile.LDAPProfileSubsystem; + ++import netscape.ldap.LDAPAttribute; ++import netscape.ldap.LDAPConnection; ++import netscape.ldap.LDAPException; ++ + /** + * @author alee + * +@@ -93,6 +96,19 @@ public class CAInstallerService extends SystemConfigService { + CMS.debug(e); + throw new PKIException("Error enabling profile subsystem"); + } ++ ++ if (! request.createSigningCertRecord()) { ++ // This is the migration case. In this case, we will delete the ++ // record that was created during the install process. ++ ++ try { ++ String serialNumber = request.getSigningCertSerialNumber(); ++ deleteSigningRecord(serialNumber); ++ } catch (Exception e) { ++ CMS.debug(e); ++ throw new PKIException("Error deleting signing cert record:" + e, e); ++ } ++ } + } + + @Override +@@ -189,9 +205,37 @@ public class CAInstallerService extends SystemConfigService { + configStore.commit(false /* no backup */); + } + ++ private void deleteSigningRecord(String serialNumber) throws EBaseException, LDAPException { ++ ++ if (StringUtils.isEmpty(serialNumber)) { ++ throw new PKIException("signing certificate serial number not specified in configuration request"); ++ } ++ ++ LDAPConnection conn = null; ++ try { ++ IConfigStore dbCfg = cs.getSubStore("internaldb"); ++ ILdapConnFactory dbFactory = CMS.getLdapBoundConnFactory("CAInstallerService"); ++ dbFactory.init(dbCfg); ++ conn = dbFactory.getConn(); ++ ++ String basedn = dbCfg.getString("basedn", ""); ++ String dn = "cn=" + serialNumber + ",ou=certificateRepository,ou=ca," + basedn; ++ ++ conn.delete(dn); ++ } finally { ++ try { ++ if (conn != null) ++ conn.disconnect(); ++ } catch (LDAPException e) { ++ CMS.debug(e); ++ CMS.debug("releaseConnection: " + e); ++ } ++ } ++ } ++ + private void configureStartingCRLNumber(ConfigurationRequest data) { + CMS.debug("CAInstallerService:configureStartingCRLNumber entering."); +- cs.putString("ca.crl.MasterCRL.startingCrlNumber",data.getStartingCRLNumber() ); ++ cs.putString("ca.crl.MasterCRL.startingCrlNumber",data.getStartingCRLNumber()); + + } + private void disableCRLCachingAndGenerationForClone(ConfigurationRequest data) throws MalformedURLException { +diff --git a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java +index cd9d3c8..5d69200 100644 +--- a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java ++++ b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java +@@ -237,6 +237,12 @@ public class ConfigurationRequest { + @XmlElement + protected String startingCRLNumber; + ++ @XmlElement ++ protected Boolean createSigningCertRecord; ++ ++ @XmlElement ++ protected String signingCertSerialNumber; ++ + public ConfigurationRequest() { + // required for JAXB + } +@@ -943,6 +949,30 @@ public class ConfigurationRequest { + this.startingCRLNumber = startingCRLNumber; + } + ++ public String getIsClone() { ++ return isClone; ++ } ++ ++ public void setIsClone(String isClone) { ++ this.isClone = isClone; ++ } ++ ++ public Boolean createSigningCertRecord() { ++ return createSigningCertRecord; ++ } ++ ++ public void setCreateSigningCertRecord(Boolean createSigningCertRecord) { ++ this.createSigningCertRecord = createSigningCertRecord; ++ } ++ ++ public String getSigningCertSerialNumber() { ++ return signingCertSerialNumber; ++ } ++ ++ public void setSigningCertSerialNumber(String signingCertSerialNumber) { ++ this.signingCertSerialNumber = signingCertSerialNumber; ++ } ++ + @Override + public String toString() { + return "ConfigurationRequest [pin=XXXX" + +@@ -1007,6 +1037,8 @@ public class ConfigurationRequest { + ", subordinateSecurityDomainName=" + subordinateSecurityDomainName + + ", reindexData=" + reindexData + + ", startingCrlNumber=" + startingCRLNumber + ++ ", createSigningCertRecord=" + createSigningCertRecord + ++ ", signingCertSerialNumber=" + signingCertSerialNumber + + "]"; + } + +diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg +index e79ff06..cd506cc 100644 +--- a/base/server/etc/default.cfg ++++ b/base/server/etc/default.cfg +@@ -291,6 +291,8 @@ pki_ca_signing_key_algorithm=SHA256withRSA + pki_ca_signing_key_size=2048 + pki_ca_signing_key_type=rsa + pki_ca_signing_nickname=caSigningCert cert-%(pki_instance_name)s CA ++pki_ca_signing_record_create=True ++pki_ca_signing_serial_number=1 + pki_ca_signing_signing_algorithm=SHA256withRSA + pki_ca_signing_subject_dn=cn=CA Signing Certificate,ou=%(pki_instance_name)s,o=%(pki_security_domain_name)s + pki_ca_signing_token= +diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py +index b6eacf1..f77c21a 100644 +--- a/base/server/python/pki/server/deployment/pkihelper.py ++++ b/base/server/python/pki/server/deployment/pkihelper.py +@@ -4095,6 +4095,12 @@ class ConfigClient: + # Misc CA parameters + if self.subsystem == "CA": + data.startingCRLNumber = self.mdict['pki_ca_starting_crl_number'] ++ data.createSigningCertRecord = ( ++ self.mdict['pki_ca_signing_record_create'].lower() ++ ) ++ data.signingCertSerialNumber = ( ++ self.mdict['pki_ca_signing_serial_number'].lower() ++ ) + + return data + diff --git a/SOURCES/pki-core-added-upgrade-script-to-update-AJP-localhost.patch b/SOURCES/pki-core-added-upgrade-script-to-update-AJP-localhost.patch new file mode 100644 index 0000000..9e48d0b --- /dev/null +++ b/SOURCES/pki-core-added-upgrade-script-to-update-AJP-localhost.patch @@ -0,0 +1,83 @@ +commit 219c633d2aae2ae81724d4588e6aaf6969603ebb +Author: Endi S. Dewata +Date: Thu Jan 19 21:43:24 2017 +0100 + + Added upgrade script to update AJP loopback address. + + An upgrade script has been added to replace IPv4- and IPv6-specific + AJP loopback address with a more generic "localhost" in existing + instances. + + https://fedorahosted.org/pki/ticket/2570 + + (cherry picked from commit cb839206d6c1d562e2e4385f6822c7934e9455c6) + (cherry picked from commit 6b8c54d29cfc4f448566f50cb27a40eda07052ca) + +diff --git a/base/server/upgrade/10.3.5/03-UpdateAJPLoopbackAddress b/base/server/upgrade/10.3.5/03-UpdateAJPLoopbackAddress +new file mode 100755 +index 0000000..b7d5c0e +--- /dev/null ++++ b/base/server/upgrade/10.3.5/03-UpdateAJPLoopbackAddress +@@ -0,0 +1,62 @@ ++#!/usr/bin/python ++# Authors: ++# Endi S. Dewata ++# ++# 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. ++# ++# Copyright (C) 2017 Red Hat, Inc. ++# All rights reserved. ++# ++ ++from __future__ import absolute_import ++import os ++from lxml import etree ++ ++import pki ++ ++ ++class UpdateAJPLoopbackAddress( ++ pki.server.upgrade.PKIServerUpgradeScriptlet): ++ ++ def __init__(self): ++ super(UpdateAJPLoopbackAddress, self).__init__() ++ self.message = 'Update AJP loopback address' ++ ++ self.parser = etree.XMLParser(remove_blank_text=True) ++ ++ def upgrade_instance(self, instance): ++ ++ server_xml = os.path.join(instance.conf_dir, 'server.xml') ++ self.backup(server_xml) ++ ++ document = etree.parse(server_xml, self.parser) ++ ++ server = document.getroot() ++ connectors = server.findall('.//Connector') ++ ++ # replace IPv4- or IPv6-specific AJP loopback address with localhost ++ for connector in connectors: ++ ++ protocol = connector.get('protocol') ++ if protocol != 'AJP/1.3': ++ continue ++ ++ address = connector.get('address') ++ if address != '127.0.0.1' and address != '::1': ++ continue ++ ++ connector.set('address', 'localhost') ++ ++ with open(server_xml, 'wb') as f: ++ document.write(f, pretty_print=True, encoding='utf-8') diff --git a/SOURCES/pki-core-fixed-problem-searching-for-latest-cert-req.patch b/SOURCES/pki-core-fixed-problem-searching-for-latest-cert-req.patch new file mode 100644 index 0000000..e546a5f --- /dev/null +++ b/SOURCES/pki-core-fixed-problem-searching-for-latest-cert-req.patch @@ -0,0 +1,35 @@ +commit e1ae89e9f110cf4af75f6ea82a38a9ce085617ac +Author: Endi S. Dewata +Date: Thu Jan 26 23:38:53 2017 +0100 + + Fixed problem searching the latest certificate request. + + Previously if a certificate request page only has one entry the + entry itself will be removed from the page, resulting in a blank + page. + + The QueryReq.trim() has been modified not to remove the marker + entry if it's the only entry in the page. + + https://fedorahosted.org/pki/ticket/2450 + + (cherry picked from commit 755fb2834d22131628ad1929c1bd4b1cd7592203) + (cherry picked from commit 196ae21e55a3210ef9db1ad6b8c84d64d4d1959e) + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/QueryReq.java b/base/server/cms/src/com/netscape/cms/servlet/request/QueryReq.java +index d05da10..376349b 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/request/QueryReq.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/request/QueryReq.java +@@ -503,6 +503,12 @@ public class QueryReq extends CMSServlet { + */ + private void trim(Vector v, RequestId marker) { + int i = v.size() - 1; ++ ++ if (i == 0) { ++ // do not remove the only element in the list ++ return; ++ } ++ + if (v.elementAt(i).getRequestId().toString().equals( + marker.toString())) { + v.remove(i); diff --git a/SOURCES/pki-core-javadoc-special-characters.patch b/SOURCES/pki-core-javadoc-special-characters.patch new file mode 100644 index 0000000..0e43e3e --- /dev/null +++ b/SOURCES/pki-core-javadoc-special-characters.patch @@ -0,0 +1,26 @@ +commit ef0710a1b4f1e49aba7877eb90c8274a25240afd +Author: Endi S. Dewata +Date: Tue Jan 24 22:00:12 2017 +0100 + + Fixed Javadoc failure caused by HTML special characters. + + The CMSTemplate has been fixed to escape HTML special characters + in method documentation. + + Fixes: https://fedorahosted.org/pki/ticket/2579 + (cherry picked from commit 8c6707f1117e56c68d147e0b37c018efa3c81fb2) + (cherry picked from commit 423c986c57a0baacf1dc8d817dc8b356b9cf0d06) + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplate.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplate.java +index ba4e840..fe5a14b 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplate.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMSTemplate.java +@@ -343,7 +343,7 @@ public class CMSTemplate extends CMSFile { + + /** + * Escape the contents of src string in preparation to be enclosed in +- * double quotes as a JavaScript String Literal within an