https://bz.apache.org/bugzilla/show_bug.cgi?id=57833
Bug ID: 57833 Summary: NIO connector fails SSL handshake due to uppercase letters in keyAlias name Product: Tomcat 7 Version: 7.0.59 Hardware: PC Status: NEW Severity: critical Priority: P2 Component: Connectors Assignee: dev@tomcat.apache.org Reporter: bluesan...@gmail.com Created attachment 32664 --> https://bz.apache.org/bugzilla/attachment.cgi?id=32664&action=edit Patch for fixing NIO connector SSL handshake exception due to uppercase letters in keyAlias If we create a SSL enabled NIO connector with keyAlias name containing mixed case of letters i.e. uppercase and lowercase, for instance, "externalCA" and try to connect to that port using SSL, then the handshake fails with following exception: ==================================================== FINE: Error during SSL handshake javax.net.ssl.SSLHandshakeException: no cipher suites in common at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1336) at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:519) at sun.security.ssl.SSLEngineImpl.writeAppRecord(SSLEngineImpl.java:1197) at sun.security.ssl.SSLEngineImpl.wrap(SSLEngineImpl.java:1169) at javax.net.ssl.SSLEngine.wrap(SSLEngine.java:469) at org.apache.tomcat.util.net.SecureNioChannel.handshakeWrap(SecureNioChannel.java:301) at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:175) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1715) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1698) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Caused by: javax.net.ssl.SSLHandshakeException: no cipher suites in common at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1639) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:281) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:269) at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:901) at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:629) at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:167) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:901) at sun.security.ssl.Handshaker$1.run(Handshaker.java:841) at sun.security.ssl.Handshaker$1.run(Handshaker.java:839) at java.security.AccessController.doPrivileged(Native Method) at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1273) at org.apache.tomcat.util.net.SecureNioChannel.tasks(SecureNioChannel.java:285) at org.apache.tomcat.util.net.SecureNioChannel.handshakeUnwrap(SecureNioChannel.java:343) at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:193) ... 6 more Apr 16, 2015 8:55:00 PM org.apache.tomcat.util.net.NioEndpoint$Poller cancelledKey FINE: Failed to close socket java.nio.channels.ClosedChannelException at sun.nio.ch.SocketChannelImpl.ensureWriteOpen(SocketChannelImpl.java:265) at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:474) at org.apache.tomcat.util.net.SecureNioChannel.flush(SecureNioChannel.java:135) at org.apache.tomcat.util.net.SecureNioChannel.close(SecureNioChannel.java:370) at org.apache.tomcat.util.net.SecureNioChannel.close(SecureNioChannel.java:398) at org.apache.tomcat.util.net.NioEndpoint$Poller.cancelledKey(NioEndpoint.java:1115) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1767) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1698) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) ====================================================== Found out that the actual issue is not due to the mentioned exception message "no cipher suites in common" but instead the issue is due to the way X509KeyManager stores the private key. It uses map with keyAlias as key (converted to lowercase). And the calling code has to take care of passing keyAlias in lowercase while retrieving. This is correctly handled in JSSESocketFactory.getKeyManagers() method @line 594 if the key store type is default (JKS). But in case of NioEndpoint, the conversion of keyAlias to lowercase is missed and due to that, the private key is returned null causing the handshake to fail. Please find attached the patch to fix the issue. It would be good if we can throw exception with relevant message which would help us locate the issue faster. Steps to reproduce: ------------------ 1. Create a SSL enabled NIO connector with keyAlias name containing uppercase letters. 2. Try to connect to the NIO port over https. Then above exception can be seen if juli logging is enabled. -- You are receiving this mail because: You are the assignee for the bug. --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org