357240 safer SSL close
This commit is contained in:
parent
ba0ee9f216
commit
b28a53ad52
|
@ -206,6 +206,141 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int process() throws IOException
|
||||||
|
{
|
||||||
|
ByteBuffer bbuf = null; // TODO ???
|
||||||
|
|
||||||
|
int wraps=0;
|
||||||
|
|
||||||
|
HandshakeStatus initialStatus = _engine.getHandshakeStatus();
|
||||||
|
loop: while (true)
|
||||||
|
{
|
||||||
|
// If we have encrypted data in output buffer
|
||||||
|
if (isBufferingOutput())
|
||||||
|
{
|
||||||
|
// we must flush it, as the other end might be
|
||||||
|
// waiting for that outgoing data before sending
|
||||||
|
// more incoming data
|
||||||
|
flush();
|
||||||
|
|
||||||
|
// If we were unable to flush all the data, then
|
||||||
|
// we should break the loop and wait for the call
|
||||||
|
// back to handle when the SelectSet detects that
|
||||||
|
// the channel is writable again.
|
||||||
|
if (isBufferingOutput())
|
||||||
|
{
|
||||||
|
scheduleWrite();
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle the current hand share status
|
||||||
|
switch(_engine.getHandshakeStatus())
|
||||||
|
{
|
||||||
|
case FINISHED:
|
||||||
|
case NOT_HANDSHAKING:
|
||||||
|
// If we are closing, then unwrap must have CLOSED result,
|
||||||
|
// so return -1 to signal upwards
|
||||||
|
if (_closing)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// otherwise we break loop with the data we have unwrapped.
|
||||||
|
break loop;
|
||||||
|
|
||||||
|
case NEED_UNWRAP:
|
||||||
|
checkRenegotiate();
|
||||||
|
// Need more data to be unwrapped so try another call to unwrap
|
||||||
|
if (!unwrap(bbuf) && _engine.getHandshakeStatus()==HandshakeStatus.NEED_UNWRAP)
|
||||||
|
{
|
||||||
|
// If the unwrap call did not make any progress and we are still in
|
||||||
|
// NEED_UNWRAP, then we should break the loop and wait for more data to
|
||||||
|
// arrive.
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
// progress was made so continue the loop.
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NEED_TASK:
|
||||||
|
{
|
||||||
|
// A task needs to be run, so run it!
|
||||||
|
|
||||||
|
Runnable task;
|
||||||
|
while ((task=_engine.getDelegatedTask())!=null)
|
||||||
|
{
|
||||||
|
task.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect SUN JVM Bug!!!
|
||||||
|
if(initialStatus==HandshakeStatus.NOT_HANDSHAKING &&
|
||||||
|
_engine.getHandshakeStatus()==HandshakeStatus.NEED_UNWRAP && wraps==0)
|
||||||
|
{
|
||||||
|
// This should be NEED_WRAP
|
||||||
|
// The fix simply detects the signature of the bug and then close the connection (fail-fast) so that ff3 will delegate to using SSL instead of TLS.
|
||||||
|
// This is a jvm bug on java1.6 where the SSLEngine expects more data from the initial handshake when the client(ff3-tls) already had given it.
|
||||||
|
// See http://jira.codehaus.org/browse/JETTY-567 for more details
|
||||||
|
if (_debug) __log.warn(_session+" JETTY-567");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NEED_WRAP:
|
||||||
|
{
|
||||||
|
checkRenegotiate();
|
||||||
|
// The SSL needs to send some handshake data to the other side,
|
||||||
|
// so let fill become a flush for a little bit.
|
||||||
|
wraps++;
|
||||||
|
needOutBuffer();
|
||||||
|
ByteBuffer out_buffer=_outNIOBuffer.getByteBuffer();
|
||||||
|
synchronized(out_buffer)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// call wrap with empty application buffers, so it can
|
||||||
|
// generate required handshake messages into _outNIOBuffer
|
||||||
|
_outNIOBuffer.compact();
|
||||||
|
int put=_outNIOBuffer.putIndex();
|
||||||
|
out_buffer.position();
|
||||||
|
_result=null;
|
||||||
|
_result=_engine.wrap(__NO_BUFFERS,out_buffer);
|
||||||
|
if (_debug) __log.debug(_session+" fill wrap "+_result);
|
||||||
|
switch(_result.getStatus())
|
||||||
|
{
|
||||||
|
case BUFFER_OVERFLOW:
|
||||||
|
case BUFFER_UNDERFLOW:
|
||||||
|
LOG.warn("wrap {}",_result);
|
||||||
|
_closing=true;
|
||||||
|
break;
|
||||||
|
case CLOSED:
|
||||||
|
_closing=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_outNIOBuffer.setPutIndex(put+_result.bytesProduced());
|
||||||
|
}
|
||||||
|
catch(SSLException e)
|
||||||
|
{
|
||||||
|
super.close();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
out_buffer.position(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush the encrypted outNIOBuffer
|
||||||
|
flush();
|
||||||
|
freeOutBuffer();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
protected void sslClose() throws IOException
|
protected void sslClose() throws IOException
|
||||||
{
|
{
|
||||||
|
@ -651,23 +786,24 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
||||||
@Override
|
@Override
|
||||||
public void flush() throws IOException
|
public void flush() throws IOException
|
||||||
{
|
{
|
||||||
if (_outNIOBuffer==null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int len=_outNIOBuffer.length();
|
|
||||||
if (isBufferingOutput())
|
if (isBufferingOutput())
|
||||||
{
|
{
|
||||||
int flushed=super.flush(_outNIOBuffer);
|
int flushed=super.flush(_outNIOBuffer);
|
||||||
if (_debug) __log.debug(_session+" Flushed "+flushed+"/"+len);
|
if (_debug)
|
||||||
if (isBufferingOutput())
|
__log.debug(_session+" Flushed "+flushed+" left="+_outNIOBuffer.length());
|
||||||
{
|
|
||||||
// Try again after yield.... cheaper than a reschedule.
|
|
||||||
Thread.yield();
|
|
||||||
flushed=super.flush(_outNIOBuffer);
|
|
||||||
if (_debug) __log.debug(_session+" flushed "+flushed+"/"+len);
|
|
||||||
}
|
}
|
||||||
else if (_closing && !_engine.isOutboundDone())
|
else if (_closing)
|
||||||
{
|
{
|
||||||
|
if (_engine.isOutboundDone())
|
||||||
|
{
|
||||||
|
if (_debug)
|
||||||
|
__log.debug(_session+" close");
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_debug)
|
||||||
|
__log.debug(_session+" closeOutbound");
|
||||||
_engine.closeOutbound();
|
_engine.closeOutbound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue