Workaround for Tomcat failure to flush after exception in unwrap
protected BCSSLConnection connection = null;
protected SSLSession handshakeSession = null;
+ protected SSLException deferredException = null;
+
protected ProvSSLEngine(ProvSSLContextSpi context, ContextData contextData)
{
super();
@@ -336,8 +338,25 @@ public synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts, in
}
catch (IOException e)
{
- // TODO[jsse] Throw a subclass of SSLException?
- throw new SSLException(e);
+ /*
+ * TODO[jsse] 'deferredException' is a workaround for Apache Tomcat's (as of
+ * 8.5.13) SecureNioChannel behaviour when exceptions are thrown from SSLEngine.
+ * In the case of SSLEngine.wrap throwing, Tomcat will call wrap again, allowing
+ * any buffered outbound alert to be flushed. For unwrap, this doesn't happen.
+ * So we pretend this unwrap was OK and ask for NEED_WRAP, then throw in wrap.
+ *
+ * Note that the SSLEngine javadoc clearly describes a process of flushing via
+ * wrap calls after any closure events, to include thrown exceptions.
+ */
+ //throw new SSLException(e);
+ if (this.deferredException == null)
+ {
+ this.deferredException = new SSLException(e);
+ }
+
+ handshakeStatus = HandshakeStatus.NEED_WRAP;
+
+ return new SSLEngineResult(Status.OK, HandshakeStatus.NEED_WRAP, bytesConsumed, bytesProduced);
}
bytesConsumed += count;
@@ -409,6 +428,13 @@ else if (protocol.isClosed())
public synchronized SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst)
throws SSLException
{
+ if (deferredException != null)
+ {
+ SSLException e = deferredException;
+ deferredException = null;
+ throw e;
+ }
+
// TODO[jsse] Argument checks - see javadoc
if (!initialHandshakeBegun)
