use of javax.net.ssl.SSLEngineResult.HandshakeStatus in project netty by netty.
the class SslHandler method unwrap.
/**
* Unwraps inbound SSL records.
*/
private boolean unwrap(ChannelHandlerContext ctx, ByteBuf packet, int offset, int length) throws SSLException {
boolean decoded = false;
boolean wrapLater = false;
boolean notifyClosure = false;
ByteBuf decodeOut = allocate(ctx, length);
try {
// See https://github.com/netty/netty/issues/5860
unwrapLoop: while (!ctx.isRemoved()) {
final SSLEngineResult result = engineType.unwrap(this, packet, offset, length, decodeOut);
final Status status = result.getStatus();
final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
final int produced = result.bytesProduced();
final int consumed = result.bytesConsumed();
// Update indexes for the next iteration
offset += consumed;
length -= consumed;
switch(status) {
case BUFFER_OVERFLOW:
int readableBytes = decodeOut.readableBytes();
int bufferSize = engine.getSession().getApplicationBufferSize() - readableBytes;
if (readableBytes > 0) {
decoded = true;
ctx.fireChannelRead(decodeOut);
// This buffer was handled, null it out.
decodeOut = null;
if (bufferSize <= 0) {
// It may happen that readableBytes >= engine.getSession().getApplicationBufferSize()
// while there is still more to unwrap, in this case we will just allocate a new buffer
// with the capacity of engine.getSession().getApplicationBufferSize() and call unwrap
// again.
bufferSize = engine.getSession().getApplicationBufferSize();
}
} else {
// This buffer was handled, null it out.
decodeOut.release();
decodeOut = null;
}
// Allocate a new buffer which can hold all the rest data and loop again.
// TODO: We may want to reconsider how we calculate the length here as we may
// have more then one ssl message to decode.
decodeOut = allocate(ctx, bufferSize);
continue;
case CLOSED:
// notify about the CLOSED state of the SSLEngine. See #137
notifyClosure = true;
break;
default:
break;
}
switch(handshakeStatus) {
case NEED_UNWRAP:
break;
case NEED_WRAP:
// costly unwrap operation and break out of the loop.
if (wrapNonAppData(ctx, true) && length == 0) {
break unwrapLoop;
}
break;
case NEED_TASK:
runDelegatedTasks();
break;
case FINISHED:
setHandshakeSuccess();
wrapLater = true;
// - https://code.google.com/p/android/issues/detail?id=198639&thanks=198639&ts=1452501203
break;
case NOT_HANDSHAKING:
if (setHandshakeSuccessIfStillHandshaking()) {
wrapLater = true;
continue;
}
if (flushedBeforeHandshake) {
// We need to call wrap(...) in case there was a flush done before the handshake completed.
//
// See https://github.com/netty/netty/pull/2437
flushedBeforeHandshake = false;
wrapLater = true;
}
// out of the loop.
if (length == 0) {
break unwrapLoop;
}
break;
default:
throw new IllegalStateException("unknown handshake status: " + handshakeStatus);
}
if (status == Status.BUFFER_UNDERFLOW || consumed == 0 && produced == 0) {
if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) {
// The underlying engine is starving so we need to feed it with more data.
// See https://github.com/netty/netty/pull/5039
readIfNeeded(ctx);
}
break;
}
}
if (wrapLater) {
wrap(ctx, true);
}
if (notifyClosure) {
notifyClosePromise(null);
}
} finally {
if (decodeOut != null) {
if (decodeOut.isReadable()) {
decoded = true;
ctx.fireChannelRead(decodeOut);
} else {
decodeOut.release();
}
}
}
return decoded;
}
use of javax.net.ssl.SSLEngineResult.HandshakeStatus in project robovm by robovm.
the class TestSSLEnginePair method handshakeCompleted.
private static boolean handshakeCompleted(SSLEngine engine, ByteBuffer output, ByteBuffer input, ByteBuffer scratch) throws IOException {
try {
// make the other side's output into our input
input.flip();
HandshakeStatus status = engine.getHandshakeStatus();
switch(status) {
case NEED_TASK:
boolean progress = false;
while (true) {
Runnable runnable = engine.getDelegatedTask();
if (runnable == null) {
return progress;
}
runnable.run();
progress = true;
}
case NEED_UNWRAP:
// avoid underflow
if (input.remaining() == 0) {
return false;
}
SSLEngineResult unwrapResult = engine.unwrap(input, scratch);
assertEquals(SSLEngineResult.Status.OK, unwrapResult.getStatus());
assertEquals(0, scratch.position());
return true;
case NEED_WRAP:
// avoid possible overflow
if (output.remaining() != output.capacity()) {
return false;
}
SSLEngineResult wrapResult = engine.wrap(EMPTY_BYTE_BUFFER, output);
assertEquals(SSLEngineResult.Status.OK, wrapResult.getStatus());
return true;
case NOT_HANDSHAKING:
// should have been checked by caller before calling
case FINISHED:
// only returned by wrap/unrap status, not getHandshakeStatus
throw new IllegalStateException("Unexpected HandshakeStatus = " + status);
default:
throw new IllegalStateException("Unknown HandshakeStatus = " + status);
}
} finally {
// shift consumed input, restore to output mode
input.compact();
}
}
use of javax.net.ssl.SSLEngineResult.HandshakeStatus in project CloudStack-archive by CloudStack-extras.
the class Link method doHandshake.
public static void doHandshake(SocketChannel ch, SSLEngine sslEngine, boolean isClient) throws IOException {
if (s_logger.isTraceEnabled()) {
s_logger.trace("SSL: begin Handshake, isClient: " + isClient);
}
SSLEngineResult engResult;
SSLSession sslSession = sslEngine.getSession();
HandshakeStatus hsStatus;
ByteBuffer in_pkgBuf = ByteBuffer.allocate(sslSession.getPacketBufferSize() + 40);
ByteBuffer in_appBuf = ByteBuffer.allocate(sslSession.getApplicationBufferSize() + 40);
ByteBuffer out_pkgBuf = ByteBuffer.allocate(sslSession.getPacketBufferSize() + 40);
ByteBuffer out_appBuf = ByteBuffer.allocate(sslSession.getApplicationBufferSize() + 40);
int count;
if (isClient) {
hsStatus = SSLEngineResult.HandshakeStatus.NEED_WRAP;
} else {
hsStatus = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
}
while (hsStatus != SSLEngineResult.HandshakeStatus.FINISHED) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("SSL: Handshake status " + hsStatus);
}
engResult = null;
if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
out_pkgBuf.clear();
out_appBuf.clear();
out_appBuf.put("Hello".getBytes());
engResult = sslEngine.wrap(out_appBuf, out_pkgBuf);
out_pkgBuf.flip();
int remain = out_pkgBuf.limit();
while (remain != 0) {
remain -= ch.write(out_pkgBuf);
if (remain < 0) {
throw new IOException("Too much bytes sent?");
}
}
} else if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
in_appBuf.clear();
// One packet may contained multiply operation
if (in_pkgBuf.position() == 0 || !in_pkgBuf.hasRemaining()) {
in_pkgBuf.clear();
count = ch.read(in_pkgBuf);
if (count == -1) {
throw new IOException("Connection closed with -1 on reading size.");
}
in_pkgBuf.flip();
}
engResult = sslEngine.unwrap(in_pkgBuf, in_appBuf);
ByteBuffer tmp_pkgBuf = ByteBuffer.allocate(sslSession.getPacketBufferSize() + 40);
int loop_count = 0;
while (engResult.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
// The client is too slow? Cut it and let it reconnect
if (loop_count > 10) {
throw new IOException("Too many times in SSL BUFFER_UNDERFLOW, disconnect guest.");
}
// We need more packets to complete this operation
if (s_logger.isTraceEnabled()) {
s_logger.trace("SSL: Buffer underflowed, getting more packets");
}
tmp_pkgBuf.clear();
count = ch.read(tmp_pkgBuf);
if (count == -1) {
throw new IOException("Connection closed with -1 on reading size.");
}
tmp_pkgBuf.flip();
in_pkgBuf.mark();
in_pkgBuf.position(in_pkgBuf.limit());
in_pkgBuf.limit(in_pkgBuf.limit() + tmp_pkgBuf.limit());
in_pkgBuf.put(tmp_pkgBuf);
in_pkgBuf.reset();
in_appBuf.clear();
engResult = sslEngine.unwrap(in_pkgBuf, in_appBuf);
loop_count++;
}
} else if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_TASK) {
Runnable run;
while ((run = sslEngine.getDelegatedTask()) != null) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("SSL: Running delegated task!");
}
run.run();
}
} else if (hsStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
throw new IOException("NOT a handshaking!");
}
if (engResult != null && engResult.getStatus() != SSLEngineResult.Status.OK) {
throw new IOException("Fail to handshake! " + engResult.getStatus());
}
if (engResult != null)
hsStatus = engResult.getHandshakeStatus();
else
hsStatus = sslEngine.getHandshakeStatus();
}
}
use of javax.net.ssl.SSLEngineResult.HandshakeStatus in project cloudstack by apache.
the class Link method doHandshake.
public static boolean doHandshake(final SocketChannel socketChannel, final SSLEngine sslEngine, final boolean isClient) throws IOException {
if (socketChannel == null || sslEngine == null) {
return false;
}
final int appBufferSize = sslEngine.getSession().getApplicationBufferSize();
final int netBufferSize = sslEngine.getSession().getPacketBufferSize();
ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);
ByteBuffer myNetData = ByteBuffer.allocate(netBufferSize);
ByteBuffer peerNetData = ByteBuffer.allocate(netBufferSize);
final long startTimeMills = System.currentTimeMillis();
HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
while (handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED && handshakeStatus != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
final long timeTaken = System.currentTimeMillis() - startTimeMills;
if (timeTaken > 15000L) {
s_logger.warn("SSL Handshake has taken more than 15s to connect to: " + socketChannel.getRemoteAddress() + ". Please investigate this connection.");
return false;
}
switch(handshakeStatus) {
case NEED_UNWRAP:
if (!doHandshakeUnwrap(socketChannel, sslEngine, peerAppData, peerNetData, appBufferSize)) {
return false;
}
break;
case NEED_WRAP:
if (!doHandshakeWrap(socketChannel, sslEngine, myAppData, myNetData, peerNetData, netBufferSize)) {
return false;
}
break;
case NEED_TASK:
Runnable task;
while ((task = sslEngine.getDelegatedTask()) != null) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("SSL: Running delegated task!");
}
task.run();
}
break;
case FINISHED:
break;
case NOT_HANDSHAKING:
break;
default:
throw new IllegalStateException("Invalid SSL status: " + handshakeStatus);
}
handshakeStatus = sslEngine.getHandshakeStatus();
}
return true;
}
use of javax.net.ssl.SSLEngineResult.HandshakeStatus in project webpieces by deanhiller.
the class AsyncSSLEngine2Impl method close.
@Override
public void close() {
clientInitiated = true;
if (mem.getConnectionState() == ConnectionState.NOT_STARTED) {
listener.closed(true);
return;
}
mem.compareSet(ConnectionState.CONNECTED, ConnectionState.DISCONNECTING);
SSLEngine engine = mem.getEngine();
engine.closeOutbound();
HandshakeStatus status = engine.getHandshakeStatus();
switch(status) {
case NEED_WRAP:
sendHandshakeMessage();
break;
case NOT_HANDSHAKING:
if (ConnectionState.DISCONNECTED != mem.getConnectionState())
throw new IllegalStateException("state=" + mem.getConnectionState() + " hsStatus=" + status + " should not be able to occur");
break;
default:
//we WILL hit this and need to fix if other end closes...try closing both ends!!!
throw new RuntimeException(mem + "bug, status not handled in close=" + status);
}
}
Aggregations