Bug 62054 - exception on OpenSSLEngine lead to websocket session closure
Summary: exception on OpenSSLEngine lead to websocket session closure
Status: RESOLVED INVALID
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Util (show other bugs)
Version: 8.5.23
Hardware: PC All
: P2 major (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-01-29 17:37 UTC by Leandro Gaspar Scanavini
Modified: 2018-01-29 21:03 UTC (History)
0 users



Attachments
Source for reproducing the issue (6.50 KB, application/x-tar)
2018-01-29 17:37 UTC, Leandro Gaspar Scanavini
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Leandro Gaspar Scanavini 2018-01-29 17:37:15 UTC
Created attachment 35703 [details]
Source for reproducing the issue

On windows, SSL_shutdown is called when connection is in init state and the WebSocket session is closed as consequence. The browser receives CloseEvent with reason "error:140E0197:SSL routines:SSL_shutdown:shutdown while in init".

The problem doesn't seen to happen in Google Chrome but when using Microsoft Edge, Internet Explorer or Firefox the issue is easily reproducible.

This user in stackoverflow was reporting the same issue and using the tomcat in linux solved the problem too.

https://stackoverflow.com/questions/47729007/secured-websocket-connections-wss-abort-in-tomcat-spring-while-https-is-wo

---------------------------------------------------------------------------
Exception stack trace:
onError... sessionId=3
javax.net.ssl.SSLException: error:140E0197:SSL routines:SSL_shutdown:shutdown wh
ile in init
        at org.apache.tomcat.util.net.openssl.OpenSSLEngine.checkLastError(OpenS
SLEngine.java:905)
        at org.apache.tomcat.util.net.openssl.OpenSSLEngine.pendingReadableBytes
InSSL(OpenSSLEngine.java:616)
        at org.apache.tomcat.util.net.openssl.OpenSSLEngine.unwrap(OpenSSLEngine
.java:544)
        at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
        at org.apache.tomcat.util.net.SecureNioChannel.read(SecureNioChannel.jav
a:563)
        at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffe
r(NioEndpoint.java:1242)
        at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffe
r(NioEndpoint.java:1215)
        at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpo
int.java:1188)
        at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFr
ameServer.java:72)
        at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(Ws
FrameServer.java:171)
        at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(
WsFrameServer.java:151)
        at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispat
ch(WsHttpUpgradeHandler.java:148)
        at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(Up
gradeProcessorInternal.java:54)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLig
ht.java:53)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(Abstract
Protocol.java:868)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpo
int.java:1457)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBas
e.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.
java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor
.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskTh
read.java:61)
        at java.lang.Thread.run(Thread.java:748)
Close Connection... sessionId=3
Session Closed. sessionId=3

---------------------------------------------------------------------------
Possible fix:
As a simple test, I did a build changing the OpenSSLEngine#shutdown method to check if the SSL is init state before releasing it:

    public synchronized void shutdown() {
        if (!destroyed && SSL.isInInit(ssl) != 0) {
            destroyed = true;
            SSL.freeBIO(networkBIO);
            SSL.freeSSL(ssl);
            ssl = networkBIO = 0;

            // internal errors can cause shutdown without marking the engine closed
            isInboundDone = isOutboundDone = engineClosed = true;
        }
    }

That solved the issue, however I would like some feedback for the effects of this change.

---------------------------------------------------------------------------
Product: Tomcat 8.5.x and Tomcat 9.0.x
Version: apache-tomcat-8.5.23 or apache-tomcat-9.0.4
Component: Util
OS: Windows 10 Pro and Windows 2012 R2 Datacenter 

Configuration details:
Java version – Java(TM) SE Runtime Environment (build 1.8.0_144-b01) and Java(TM) SE Runtime Environment (build 1.8.0_161-b12).
Tomcat Connector Configuration: 
    <Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
               keystoreFile="${catalina.base}\conf\keystore.jks"/>

---------------------------------------------------------------------------
Reproducing the issue:
I'm attaching the source for a really simple app that reproduces the issue.

The web page starts a WebSocket and waits for messages and echo it back to the server.
On the server side, once a new connection arrives a thread is started and every 100ms if the session is open a message is sent to the client.

For testing open the page on the Internet Explorer or Microsoft Edge and wait for the exception.
Comment 1 Leandro Gaspar Scanavini 2018-01-29 20:36:55 UTC
I'm sorry, I confused my tomcat versions while testing. The issue does not happens on Tomcat 9.0.x as originally reported.
Comment 2 Leandro Gaspar Scanavini 2018-01-29 21:03:27 UTC
On 8.5.27 the issue was not reproducible with my test application. Sorry about the spam.