jetty.project icon indicating copy to clipboard operation
jetty.project copied to clipboard

Client certificate error results in EofException instead of SSLHandshakeException

Open YutaHiguchi-bsn opened this issue 5 years ago • 2 comments

Jetty version 9.4.28.v20200408 9.4.27.v20200227 9.4.26.v20200117 9.4.24.v20191120 9.4.22.v20191022

Note: above are versions I've tested and had the issue. I've skipped couple versions in the middle (e.g., 9.4.25) It is not that version not listed did not have the problem.

Java version $ java -version openjdk version "11.0.7" 2020-04-14 OpenJDK Runtime Environment (build 11.0.7+10) OpenJDK 64-Bit Server VM (build 11.0.7+10, mixed mode)

OS type/version macOS Catalina 10.15.4

Description Client certificate error sometimes results in EofException instead of SSLHandshakeException, when using Jetty as https client.

Symptom is similar to #3787, which was about server certificate validation failure does not reach http client's event handler, which was fixed in #4126

This new issue is showing similar symptom, but the cause of SslException was client certificate validation error instead of the server.

Like #3787 it seems to be caused by some kind of race condition, our unit test sporadically fails.

From the log, Jetty internally I see SSL related Exception:

19:28:52.772 DEBUG [o.e.j.i.s.SslConnection:HttpClient@4ec27c4c-2289] wrap Status = OK HandshakeStatus = FINISHED bytesConsumed = 0 bytesProduced = 82 sequenceNumber = 0 [p=0,l=82,c=18432,r=82] ioDone=false/false
19:28:52.772 DEBUG [o.e.j.i.ChannelEndPoint:HttpClient@4ec27c4c-2289] flushed 82 SocketChannelEndPoint@69de7471{/127.0.0.1:6656<->/127.0.0.1:63872,OPEN,fill=-,flush=-,to=1/53000}{io=0/0,kio=0,kro=1}->SslConnection@9f18b3e{NOT_HANDSHAKING,eio=0/0,di=0,fill=IDLE,flush=IDLE}~>DecryptedEndPoint@139608c1{/127.0.0.1:6656<->/127.0.0.1:63872,OPEN,fill=-,flush=P,to=1/53000}=>HttpConnectionOverHTTP@587d3cdf(l:/127.0.0.1:63872 <-> r:/127.0.0.1:6656,closed=false)=>HttpChannelOverHTTP@1acbbdde(exchange=HttpExchange@5c0bc8c req=PENDING/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@2be1e19c(req=HEADERS,snd=SENDING,failure=null)[HttpGenerator@8922421{s=COMPLETING}],recv=HttpReceiverOverHTTP@dbff676(rsp=IDLE,failure=null)[HttpParser{s=START,0 of -1}]]
19:28:52.772 DEBUG [o.e.j.i.s.SslConnection:HttpClient@4ec27c4c-2289] net flushed=true, ac=true
19:28:52.772 DEBUG [o.e.j.i.s.SslConnection:HttpClient@4ec27c4c-2289] handshake succeeded SslConnection@9f18b3e::SocketChannelEndPoint@69de7471{/127.0.0.1:6656<->/127.0.0.1:63872,OPEN,fill=-,flush=-,to=0/53000}{io=0/0,kio=0,kro=1}->SslConnection@9f18b3e{NOT_HANDSHAKING,eio=0/0,di=0,fill=IDLE,flush=IDLE}~>DecryptedEndPoint@139608c1{/127.0.0.1:6656<->/127.0.0.1:63872,OPEN,fill=-,flush=P,to=2/53000}=>HttpConnectionOverHTTP@587d3cdf(l:/127.0.0.1:63872 <-> r:/127.0.0.1:6656,closed=false)=>HttpChannelOverHTTP@1acbbdde(exchange=HttpExchange@5c0bc8c req=PENDING/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@2be1e19c(req=HEADERS,snd=SENDING,failure=null)[HttpGenerator@8922421{s=COMPLETING}],recv=HttpReceiverOverHTTP@dbff676(rsp=IDLE,failure=null)[HttpParser{s=START,0 of -1}]] client TLSv1.3/TLS_AES_128_GCM_SHA256
19:28:52.772 DEBUG [o.e.j.i.s.SslConnection:HttpClient@4ec27c4c-2289] <flush true SslConnection@9f18b3e::SocketChannelEndPoint@69de7471{/127.0.0.1:6656<->/127.0.0.1:63872,OPEN,fill=-,flush=-,to=0/53000}{io=0/0,kio=0,kro=1}->SslConnection@9f18b3e{NOT_HANDSHAKING,eio=0/-1,di=0,fill=IDLE,flush=IDLE}~>DecryptedEndPoint@139608c1{/127.0.0.1:6656<->/127.0.0.1:63872,OPEN,fill=-,flush=P,to=2/53000}=>HttpConnectionOverHTTP@587d3cdf(l:/127.0.0.1:63872 <-> r:/127.0.0.1:6656,closed=false)=>HttpChannelOverHTTP@1acbbdde(exchange=HttpExchange@5c0bc8c req=PENDING/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@2be1e19c(req=HEADERS,snd=SENDING,failure=null)[HttpGenerator@8922421{s=COMPLETING}],recv=HttpReceiverOverHTTP@dbff676(rsp=IDLE,failure=null)[HttpParser{s=START,0 of -1}]]
19:28:52.772 DEBUG [o.e.j.i.s.SslConnection:HttpClient@4ec27c4c-2289] fill NOT_HANDSHAKING
19:28:52.772 DEBUG [o.e.j.i.ChannelEndPoint:HttpClient@4ec27c4c-2289] filled 40 DirectByteBuffer@1c304e5f[p=0,l=40,c=18432,r=40]={<<<\x17\x03\x03\x00#\xD8u\xC5D\x04\xFfU\xDd\xB1\xAc\x02I\n56\xFaZ\xDe\x91\xF4\xBaVA\xDb\xB4\xB2@\x12\xFa\xE4\xE3\x13\xD6n\xC5>>>\xBb\x16\x00\x00\x00\x00\x00\x00\x00...\x00\x00\x00\x00\x00\x00\x00}
19:28:52.772 DEBUG [o.e.j.i.s.SslConnection:HttpClient@4ec27c4c-2289] net filled=40
19:28:52.773 DEBUG [o.e.j.i.s.SslConnection:HttpClient@4ec27c4c-2289] DecryptedEndPoint@139608c1{/127.0.0.1:6656<->/127.0.0.1:63872,OPEN,fill=-,flush=P,to=2/53000} stored fill exception
javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:313)
	at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
	at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:186)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
	at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:668)
	at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:623)
	at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:441)
	at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:420)
	at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:634)
	at org.eclipse.jetty.io.ssl.SslConnection.unwrap(SslConnection.java:417)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:705)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:159)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:75)
	at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133)
	at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:156)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint$IncompleteWriteCallback.succeeded(SslConnection.java:1531)
	at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:293)
	at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:381)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.needsFillInterest(SslConnection.java:894)
	at org.eclipse.jetty.io.AbstractEndPoint$1.needsFillInterest(AbstractEndPoint.java:45)
	at org.eclipse.jetty.io.FillInterest.tryRegister(FillInterest.java:83)
	at org.eclipse.jetty.io.FillInterest.register(FillInterest.java:55)
	at org.eclipse.jetty.io.AbstractEndPoint.fillInterested(AbstractEndPoint.java:362)
	at org.eclipse.jetty.io.AbstractConnection.fillInterested(AbstractConnection.java:134)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.fillInterested(HttpReceiverOverHTTP.java:221)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:170)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:75)
	at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133)
	at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:156)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint$IncompleteWriteCallback.succeeded(SslConnection.java:1531)
	at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:293)
	at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:381)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.needsFillInterest(SslConnection.java:894)
	at org.eclipse.jetty.io.AbstractEndPoint$1.needsFillInterest(AbstractEndPoint.java:45)
	at org.eclipse.jetty.io.FillInterest.tryRegister(FillInterest.java:83)
	at org.eclipse.jetty.io.FillInterest.register(FillInterest.java:55)
	at org.eclipse.jetty.io.AbstractEndPoint.fillInterested(AbstractEndPoint.java:362)
	at org.eclipse.jetty.io.AbstractConnection.fillInterested(AbstractConnection.java:134)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.fillInterested(HttpReceiverOverHTTP.java:221)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:170)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:75)
	at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133)
	at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:156)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint$IncompleteWriteCallback.succeeded(SslConnection.java:1531)
	at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:293)
	at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:381)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.needsFillInterest(SslConnection.java:894)
	at org.eclipse.jetty.io.AbstractEndPoint$1.needsFillInterest(AbstractEndPoint.java:45)
	at org.eclipse.jetty.io.FillInterest.tryRegister(FillInterest.java:83)
	at org.eclipse.jetty.io.FillInterest.register(FillInterest.java:55)
	at org.eclipse.jetty.io.AbstractEndPoint.fillInterested(AbstractEndPoint.java:362)
	at org.eclipse.jetty.io.AbstractConnection.fillInterested(AbstractConnection.java:134)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.fillInterested(HttpReceiverOverHTTP.java:221)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:170)
	at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:75)
	at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133)
	at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:156)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:543)
	at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:398)
	at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:161)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
	at java.base/java.lang.Thread.run(Thread.java:834)

But what client code sees is EofException

org.eclipse.jetty.io.EofException: null
	at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:283)
	at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:422)
	at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:277)
	at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:381)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onIncompleteFlush(SslConnection.java:1241)
	at org.eclipse.jetty.io.AbstractEndPoint$2.onIncompleteFlush(AbstractEndPoint.java:54)
	at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:387)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint$IncompleteWriteCallback.succeeded(SslConnection.java:1533)
	at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:293)
	at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:381)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onIncompleteFlush(SslConnection.java:1241)
	at org.eclipse.jetty.io.AbstractEndPoint$2.onIncompleteFlush(AbstractEndPoint.java:54)
	at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:387)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint$IncompleteWriteCallback.succeeded(SslConnection.java:1533)
	at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:293)
	at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:381)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onIncompleteFlush(SslConnection.java:1241)
	at org.eclipse.jetty.io.AbstractEndPoint$2.onIncompleteFlush(AbstractEndPoint.java:54)
	at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:387)
	at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.lambda$fill$1(SslConnection.java:809)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.nio.channels.AsynchronousCloseException: null
	at java.base/sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
	at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:261)
	... 22 common frames omitted

I do not have a minimum reproducer yet, but I can provide a log with org.eclipse.jetty set to DEBUG.

full log

YutaHiguchi-bsn avatar May 06 '20 02:05 YutaHiguchi-bsn

This issue has been automatically marked as stale because it has been a full year without activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 09 '21 02:06 stale[bot]

This issue has been automatically marked as stale because it has been a full year without activity. It will be closed if no further activity occurs. Thank you for your contributions.

github-actions[bot] avatar Jun 11 '22 00:06 github-actions[bot]

This issue has been automatically marked as stale because it has been a full year without activity. It will be closed if no further activity occurs. Thank you for your contributions.

github-actions[bot] avatar Jun 14 '23 00:06 github-actions[bot]