#7653 pki-tomcatd doesn't start when having a wildcard ECDSA for ldaps
Closed: fixed Opened by ptymatt.

Request for enhancement

pki-tomcatd should accept wildcard ECDSA certificates.

Issue

tomcatd tls client can't initiate a connection and fail to start when the ldaps server present a wildcard ECDSA certificate.

Steps to Reproduce

  1. Obtain a wildcard ECDSA certificate for *.domain.com
  2. Install a FreeIPA server at ipa.domain.com
  3. Integrate the certificate and its CA as described here in your ipa server
  4. ipactl restart

Actual behavior

$ sudo ipactl restart
Starting Directory Service
Stopping pki-tomcatd Service
Restarting krb5kdc Service
Restarting kadmin Service
Restarting named Service
Restarting httpd Service
Restarting ipa-custodia Service
Restarting ntpd Service
Restarting pki-tomcatd Service
Failed to restart pki-tomcatd Service
Shutting down
Hint: You can use --ignore-service-failure option for forced start in case that a non-critical service failed
Aborting ipactl
$ echo $?
1

When using the command line ldapsearch -H ldaps://ipa.domain.com:636 ... I don't have certificate issue.

Expected behavior

$ sudo ipactl restart
Restarting Directory Service
Restarting krb5kdc Service
Restarting kadmin Service
Restarting named Service
Restarting httpd Service
Restarting ipa-custodia Service
Restarting ntpd Service
Restarting ipa-otpd Service
Restarting ipa-dnskeysyncd Service
Starting pki-tomcatd Service
ipa: INFO: The ipactl command was successful
$ echo $?
0

Version/Release/Distribution

ipa-server-4.5.4-10.el7.centos.3.x86_64
ipa-client-4.5.4-10.el7.centos.3.x86_64
389-ds-base-1.3.7.5-24.el7_5.x86_64
pki-ca-10.5.1-13.1.el7_5.noarch
krb5-server-1.15.1-19.el7.x86_64

Additional info:

Here is the last log of /var/log/pki/pki-tomcat/ca/debug:

[26/juil./2018:10:05:00][localhost-startStop-1]: Creating LdapBoundConnFactor(DBSubsystem)
[26/juil./2018:10:05:00][localhost-startStop-1]: LdapBoundConnFactory: init 
[26/juil./2018:10:05:00][localhost-startStop-1]: LdapBoundConnFactory:doCloning true
[26/juil./2018:10:05:00][localhost-startStop-1]: LdapAuthInfo: init()
[26/juil./2018:10:05:00][localhost-startStop-1]: LdapAuthInfo: init begins
[26/juil./2018:10:05:00][localhost-startStop-1]: LdapAuthInfo: init ends
[26/juil./2018:10:05:00][localhost-startStop-1]: init: before makeConnection errorIfDown is true
[26/juil./2018:10:05:00][localhost-startStop-1]: makeConnection: errorIfDown true
[26/juil./2018:10:05:00][localhost-startStop-1]: TCP Keep-Alive: true
[26/juil./2018:10:05:00][localhost-startStop-1]: SSLClientCertificateSelectionCB: Setting desired cert nickname to: subsystemCert cert-pki-ca
[26/juil./2018:10:05:00][localhost-startStop-1]: LdapJssSSLSocket: set client auth cert nickname subsystemCert cert-pki-ca
org.mozilla.jss.ssl.SSLSocketException: org.mozilla.jss.ssl.SSLSocketException: SSL_ForceHandshake failed: (-12286) Cannot communicate securely with peer: no common encryption algorithm(s).
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.mozilla.jss.ssl.SocketBase.processExceptions(SocketBase.java:439)
    at org.mozilla.jss.ssl.SSLSocket.forceHandshake(Native Method)
    at com.netscape.cmscore.ldapconn.PKISocketFactory.makeSSLSocket(PKISocketFactory.java:116)
    at com.netscape.cmscore.ldapconn.PKISocketFactory.makeSocket(PKISocketFactory.java:130)
    at netscape.ldap.LDAPConnSetupMgr.connectServer(Unknown Source)
    at netscape.ldap.LDAPConnSetupMgr.openSerial(Unknown Source)
    at netscape.ldap.LDAPConnSetupMgr.connect(Unknown Source)
    at netscape.ldap.LDAPConnSetupMgr.openConnection(Unknown Source)
    at netscape.ldap.LDAPConnThread.connect(Unknown Source)
    at netscape.ldap.LDAPConnection.connect(Unknown Source)
    at netscape.ldap.LDAPConnection.connect(Unknown Source)
    at netscape.ldap.LDAPConnection.connect(Unknown Source)
    at com.netscape.cmscore.ldapconn.LdapBoundConnection.<init>(LdapBoundConnection.java:82)
    at com.netscape.cmscore.ldapconn.LdapBoundConnFactory$BoundConnection.<init>(LdapBoundConnFactory.java:531)
    at com.netscape.cmscore.ldapconn.LdapBoundConnFactory.makeConnection(LdapBoundConnFactory.java:187)
    at com.netscape.cmscore.ldapconn.LdapBoundConnFactory.init(LdapBoundConnFactory.java:166)
    at com.netscape.cmscore.ldapconn.LdapBoundConnFactory.init(LdapBoundConnFactory.java:130)
    at com.netscape.cmscore.dbs.DBSubsystem.init(DBSubsystem.java:667)
    at com.netscape.cmscore.apps.CMSEngine.initSubsystem(CMSEngine.java:1056)
    at com.netscape.cmscore.apps.CMSEngine.initSubsystems(CMSEngine.java:962)
    at com.netscape.cmscore.apps.CMSEngine.init(CMSEngine.java:568)
    at com.netscape.certsrv.apps.CMS.init(CMS.java:187)
    at com.netscape.certsrv.apps.CMS.start(CMS.java:1602)
    at com.netscape.cms.servlet.base.CMSStartServlet.init(CMSStartServlet.java:117)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:288)
    at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:285)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
    at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:320)
    at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:175)
    at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:124)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1257)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1182)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1072)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5368)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5660)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:899)
    at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:133)
    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:156)
    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:145)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:873)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:679)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1966)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Could not connect to LDAP server host ipa.domain.com port 636 Error netscape.ldap.LDAPException: Unable to create socket: org.mozilla.jss.ssl.SSLSocketException: org.mozilla.jss.ssl.SSLSocketException: SSL_ForceHandshake failed: (-12286) Cannot communicate securely with peer: no common encryption algorithm(s). (-1)
    at com.netscape.cmscore.ldapconn.LdapBoundConnFactory.makeConnection(LdapBoundConnFactory.java:205)
    at com.netscape.cmscore.ldapconn.LdapBoundConnFactory.init(LdapBoundConnFactory.java:166)
    at com.netscape.cmscore.ldapconn.LdapBoundConnFactory.init(LdapBoundConnFactory.java:130)
    at com.netscape.cmscore.dbs.DBSubsystem.init(DBSubsystem.java:667)
    at com.netscape.cmscore.apps.CMSEngine.initSubsystem(CMSEngine.java:1056)
    at com.netscape.cmscore.apps.CMSEngine.initSubsystems(CMSEngine.java:962)
    at com.netscape.cmscore.apps.CMSEngine.init(CMSEngine.java:568)
    at com.netscape.certsrv.apps.CMS.init(CMS.java:187)
    at com.netscape.certsrv.apps.CMS.start(CMS.java:1602)
    at com.netscape.cms.servlet.base.CMSStartServlet.init(CMSStartServlet.java:117)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:288)
    at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:285)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
    at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:320)
    at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:175)
    at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:124)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1257)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1182)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1072)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5368)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5660)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:899)
    at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:133)
    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:156)
    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:145)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:873)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:679)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1966)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Internal Database Error encountered: Could not connect to LDAP server host ipa.domain.com port 636 Error netscape.ldap.LDAPException: Unable to create socket: org.mozilla.jss.ssl.SSLSocketException: org.mozilla.jss.ssl.SSLSocketException: SSL_ForceHandshake failed: (-12286) Cannot communicate securely with peer: no common encryption algorithm(s). (-1)
    at com.netscape.cmscore.dbs.DBSubsystem.init(DBSubsystem.java:689)
    at com.netscape.cmscore.apps.CMSEngine.initSubsystem(CMSEngine.java:1056)
    at com.netscape.cmscore.apps.CMSEngine.initSubsystems(CMSEngine.java:962)
    at com.netscape.cmscore.apps.CMSEngine.init(CMSEngine.java:568)
    at com.netscape.certsrv.apps.CMS.init(CMS.java:187)
    at com.netscape.certsrv.apps.CMS.start(CMS.java:1602)
    at com.netscape.cms.servlet.base.CMSStartServlet.init(CMSStartServlet.java:117)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:288)
    at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:285)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
    at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:320)
    at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:175)
    at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:124)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1257)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1182)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1072)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5368)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5660)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:899)
    at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:133)
    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:156)
    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:145)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:873)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:679)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1966)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

I don't know why the cert would be an issue. You can try adding -d 255 to your ldapsearch (or use openssl s_client) to determine which cipher is being negotiated.

Then if you ipactl stop, replace the four occurances of 636 in CS.cfg with 1924, you can insert an SSL proxy in between to decode parts of the handshake (it doesn't decode the encrypted content). I'd be sure to backup CS.cfg prior to making any changes.

ssltap -slx -p 1924 hostname:636 2>&1 | tee /tmp/log

This will show you which ciphers the client offered and will confirm that the server has no overlap.

A tool like cipherscan (https://github.com/mozilla/cipherscan) can be used to see what ciphers the server supports.

With cipherscan I have the following:

$  ./cipherscan ipa.domain.com:636
............
Target: ipa.domain.com:636
prio  ciphersuite                    protocols              pfs                 curves
1     ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2                ECDH,P-384,384bits  secp384r1
2     ECDHE-ECDSA-AES256-SHA         TLSv1,TLSv1.1,TLSv1.2  ECDH,P-384,384bits  secp384r1
3     ECDHE-ECDSA-AES128-GCM-SHA256  TLSv1.2                ECDH,P-256,256bits  prime256v1,secp384r1
4     ECDHE-ECDSA-AES128-SHA         TLSv1,TLSv1.1,TLSv1.2  ECDH,P-256,256bits  prime256v1,secp384r1
Certificate: trusted, 384 bits, sha256WithRSAEncryption signature
TLS ticket lifetime hint: None
NPN protocols: None
OCSP stapling: not supported
Cipher ordering: server
Curves ordering: server - fallback: no
Server supports secure renegotiation
Server supported compression methods: NONE
TLS Tolerance: yes
Intolerance to:
 SSL 3.254           : absent
 TLS 1.0             : absent
 TLS 1.1             : absent
 TLS 1.2             : absent
 TLS 1.3             : absent
 TLS 1.4             : absent

With the ssltap trick I have, in the ClientHelloV3 block, the following when doing ipactl restart (at the pki step):

            cipher_suites[13] = {
                (0xc014) TLS/ECDHE-RSA/AES256-CBC/SHA
                (0xc02f) TLS/ECDHE-RSA/AES128-GCM/SHA256
                (0xc013) TLS/ECDHE-RSA/AES128-CBC/SHA
                (0xc027) TLS/ECDHE-RSA/AES128-CBC/SHA256
                (0x0039) TLS/DHE-RSA/AES256-CBC/SHA
                (0x006b) TLS/DHE-RSA/AES256-CBC/SHA256
                (0x009e) TLS/DHE-RSA/AES128-GCM/SHA256
                (0x0033) TLS/DHE-RSA/AES128-CBC/SHA
                (0x0067) TLS/DHE-RSA/AES128-CBC/SHA256
                (0x0035) TLS/RSA/AES256-CBC/SHA
                (0x003d) TLS/RSA/AES256-CBC/SHA256
                (0x002f) TLS/RSA/AES128-CBC/SHA
                (0x003c) TLS/RSA/AES128-CBC/SHA256
            }

Then as expected a nice fatal: handshake_failure as the tomcat client doesn't support ECDSA certificates :'(

Maybe it "just" has to be enabled in the conf? Or the java/tomcat version is involved?

I don't know how to configure the TLS client that dogtag uses, maybe @edewata can help.

Metadata Update from @rcritten:
- Custom field cc adjusted to ededata@redhat.com

I'm not familiar with ECDSA specifically, but here are some docs about TLS/SSL configuration in PKI:

  • http://www.dogtagpki.org/wiki/SSL
  • http://www.dogtagpki.org/wiki/TomcatJSS_Configuration

From the TomcatJSS_Configuration.

I've edited the /var/lib/pki/pki-tomcat/conf/server.xml file, searched for a sslRangeCiphers tag and found that the TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 cipher suite was present, but ... with a minus (-) before. It is disabled!

By changing to a (+) (and also adding "+ECDHE-ECDSA-AES256-GCM-SHA384" to the list), the pki-tomcatd service started, and The ipactl command was successful. Great! Thanks!

Shouldn't these ciphers be present and enabled by default?

Thanks again for the links and your time.

You might want to check with @cfu or @jmagne on #dogtag-pki. They should be more familiar about that.

I'm going to mark this as closed given you found a fix.

Metadata Update from @rcritten:
- Issue close_status updated to: fixed
- Issue status updated to: Closed (was: Open)

Metadata