int appBufferSize = engine.getSession().getApplicationBufferSize(); myAppData = ByteBuffer.allocate( appBufferSize ); peerAppData = ByteBuffer.allocate( appBufferSize ); peerNetData.clear(); handshakeStatus = result.getHandshakeStatus(); break; switch(result.getStatus()) { case OK: break; throw new IllegalStateException( "Invalid SSL status: " + result.getStatus() ); handshakeStatus = result.getHandshakeStatus(); break; switch(result.getStatus()) { case OK: myNetData.flip(); while( myNetData.hasRemaining() ) { socketChannel.write( myNetData ); throw new IllegalStateException( "Invalid SSL status: " + result.getStatus() );
protected int secureRead(ByteBuffer plain) throws Exception { int bytesRead = channel.read(inputBuffer); if (bytesRead == 0 && !(sslEngine.getHandshakeStatus().equals(SSLEngineResult.HandshakeStatus.NEED_UNWRAP))) { return 0; sslEngine.closeInbound(); if (inputBuffer.position() == 0 || status == SSLEngineResult.Status.BUFFER_UNDERFLOW) { return -1; SSLEngineResult res; do { res = sslEngine.unwrap(inputBuffer, plain); } while (res.getStatus() == SSLEngineResult.Status.OK && res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP && res.bytesProduced() == 0); if (res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED) { finishHandshake(); status = res.getStatus(); handshakeStatus = res.getHandshakeStatus();
SSLEngineResult wrapResult = sslEngine.wrap(src, netWriteBuffer); netWriteBuffer.flip(); if (wrapResult.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING && wrapResult.getStatus() == Status.OK) throw renegotiationException(); if (wrapResult.getStatus() == Status.OK) { written = wrapResult.bytesConsumed(); flush(netWriteBuffer); } else if (wrapResult.getStatus() == Status.BUFFER_OVERFLOW) { int currentNetWriteBufferSize = netWriteBufferSize(); netWriteBuffer.compact(); if (netWriteBuffer.limit() >= currentNetWriteBufferSize) throw new IllegalStateException("SSL BUFFER_OVERFLOW when available data size (" + netWriteBuffer.limit() + ") >= network buffer size (" + currentNetWriteBufferSize + ")"); } else if (wrapResult.getStatus() == Status.BUFFER_UNDERFLOW) { throw new IllegalStateException("SSL BUFFER_UNDERFLOW during write"); } else if (wrapResult.getStatus() == Status.CLOSED) { throw new EOFException();
/** * Convert a {@link SSLEngineResult} into a {@link String}, this is needed * because the supplied method includes a log-breaking newline. */ public static String resultToString(final SSLEngineResult result) { return String.format("status=%s,handshakeStatus=%s,bytesConsumed=%d,bytesConsumed=%d", result.getStatus(), result.getHandshakeStatus(), result.bytesProduced(), result.bytesConsumed()); }
@Override SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int readerIndex, int len, ByteBuf out) throws SSLException { int writerIndex = out.writerIndex(); ByteBuffer inNioBuffer = toByteBuffer(in, readerIndex, len); int position = inNioBuffer.position(); final SSLEngineResult result = handler.engine.unwrap(inNioBuffer, toByteBuffer(out, writerIndex, out.writableBytes())); out.writerIndex(writerIndex + result.bytesProduced()); // This is a workaround for a bug in Android 5.0. Android 5.0 does not correctly update the // SSLEngineResult.bytesConsumed() in some cases and just return 0. // // See: // - https://android-review.googlesource.com/c/platform/external/conscrypt/+/122080 // - https://github.com/netty/netty/issues/7758 if (result.bytesConsumed() == 0) { int consumed = inNioBuffer.position() - position; if (consumed != result.bytesConsumed()) { // Create a new SSLEngineResult with the correct bytesConsumed(). return new SSLEngineResult( result.getStatus(), result.getHandshakeStatus(), consumed, result.bytesProduced()); } } return result; }
/** * Performs the WRAP function * @param doWrite boolean * @return SSLEngineResult * @throws IOException */ private SSLEngineResult handshakeWrap(boolean doWrite) throws IOException { log.trace("SSLHandshake handshakeWrap {}", channelId); if (netWriteBuffer.hasRemaining()) throw new IllegalStateException("handshakeWrap called with netWriteBuffer not empty"); //this should never be called with a network buffer that contains data //so we can clear it here. netWriteBuffer.clear(); SSLEngineResult result = sslEngine.wrap(emptyBuf, netWriteBuffer); //prepare the results to be written netWriteBuffer.flip(); handshakeStatus = result.getHandshakeStatus(); if (result.getStatus() == SSLEngineResult.Status.OK && result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { handshakeStatus = runDelegatedTasks(); } if (doWrite) flush(netWriteBuffer); return result; }
@Test public void handshakeUsesBufferParameter() throws Exception { SocketChannel mockChannel = mock(SocketChannel.class); when(mockChannel.read(any(ByteBuffer.class))).thenReturn(100, 100, 100, 0); Socket mockSocket = mock(Socket.class); when(mockChannel.socket()).thenReturn(mockSocket); when(mockSocket.isClosed()).thenReturn(false); // initial read of handshake status followed by read of handshake status after task execution when(mockEngine.getHandshakeStatus()).thenReturn(NEED_UNWRAP, NEED_WRAP); // interleaved wraps/unwraps/task-execution when(mockEngine.unwrap(any(ByteBuffer.class), any(ByteBuffer.class))).thenReturn( new SSLEngineResult(OK, NEED_WRAP, 100, 100), new SSLEngineResult(BUFFER_OVERFLOW, NEED_UNWRAP, 0, 0), new SSLEngineResult(OK, NEED_TASK, 100, 0)); when(mockEngine.getDelegatedTask()).thenReturn(() -> { }, (Runnable) null); when(mockEngine.wrap(any(ByteBuffer.class), any(ByteBuffer.class))).thenReturn( new SSLEngineResult(OK, NEED_UNWRAP, 100, 100), new SSLEngineResult(BUFFER_OVERFLOW, NEED_WRAP, 0, 0), new SSLEngineResult(CLOSED, FINISHED, 100, 0)); ByteBuffer byteBuffer = ByteBuffer.allocate(netBufferSize); spyNioSslEngine.handshake(mockChannel, 10000, byteBuffer); assertThat(spyNioSslEngine.handshakeBuffer).isSameAs(byteBuffer); }
void handshake(SSLConfigValidatorEngine peerEngine) throws SSLException { SSLEngineResult.HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus(); while (true) { switch (handshakeStatus) { case NEED_WRAP: handshakeResult = sslEngine.wrap(EMPTY_BUF, netBuffer); switch (handshakeResult.getStatus()) { case OK: break; case BUFFER_OVERFLOW: netBuffer.compact(); netBuffer = Utils.ensureCapacity(netBuffer, sslEngine.getSession().getPacketBufferSize()); netBuffer.flip(); break; case CLOSED: default: throw new SSLException("Unexpected handshake status: " + handshakeResult.getStatus()); handshakeStatus = handshakeResult.getHandshakeStatus(); switch (handshakeResult.getStatus()) { case OK: break; case BUFFER_OVERFLOW: appBuffer = Utils.ensureCapacity(appBuffer, sslEngine.getSession().getApplicationBufferSize()); break; case BUFFER_UNDERFLOW: netBuffer = Utils.ensureCapacity(netBuffer, sslEngine.getSession().getPacketBufferSize()); break; case CLOSED: default: throw new SSLException("Unexpected handshake status: " + handshakeResult.getStatus());
final ByteBuffer writableInBuffer = streamInManager.prepareForWrite(engine.getSession().getPacketBufferSize()); int readCount = 0; try { readCount = channel.read(writableInBuffer); } catch (IOException e) { logger.error("{} Failed to readData due to {}", new Object[]{this, e}); final ByteBuffer appDataBuffer = appDataManager.prepareForWrite(engine.getSession().getApplicationBufferSize()); try { SSLEngineResult unwrapResponse = engine.unwrap(streamInBuffer, appDataBuffer); logger.trace("{} When checking if closed, (handshake={}) Unwrap response: {}", this, handshaking, unwrapResponse); if (unwrapResponse.getStatus().equals(Status.CLOSED)) { int bytesDiscarded = channel.read(discardBuffer); while (bytesDiscarded > 0) { discardBuffer.clear(); bytesDiscarded = channel.read(discardBuffer); engine.closeInbound();
final int inPos = input.position(); final int outPos = output.position(); final ByteBuffer outputByteBuffer = output.toByteBuffer(); final SSLEngineResult sslEngineResult; sslEngineResult = sslEngineWrap(sslEngine, inputArray, 0, inputArraySize, outputByteBuffer); final Status status = sslEngineResult.getStatus(); return new SslResult(output, new SSLException("SSLEngine is CLOSED")); return wrap(input, inputArray, inputArraySize, output, null); } else if (isOverflow || status == Status.BUFFER_UNDERFLOW) { return new SslResult(output, new SSLException("SSL wrap error: " + status)); input.position(inPos + sslEngineResult.bytesConsumed()); output.position(outPos + sslEngineResult.bytesProduced());
engine.closeOutbound(); final ByteBuffer outboundBuffer = streamOutManager.prepareForWrite(engine.getSession().getApplicationBufferSize()); final SSLEngineResult handshakeResult = engine.wrap(appDataOut, outboundBuffer); if (handshakeResult.getStatus() != Status.CLOSED) { throw new IOException("Invalid close state - will not send network data"); int bytesDiscarded = channel.read(discardBuffer); while (bytesDiscarded > 0) { discardBuffer.clear(); bytesDiscarded = channel.read(discardBuffer); closeQuietly(channel.socket()); closeQuietly(channel); closed = true;
@Test public void closeWhenUnwrapError() throws Exception { SocketChannel mockChannel = mock(SocketChannel.class); Socket mockSocket = mock(Socket.class); when(mockChannel.socket()).thenReturn(mockSocket); when(mockSocket.isClosed()).thenReturn(true); when(mockEngine.isOutboundDone()).thenReturn(Boolean.FALSE); when(mockEngine.wrap(any(ByteBuffer.class), any(ByteBuffer.class))).thenReturn( new SSLEngineResult(BUFFER_OVERFLOW, FINISHED, 0, 0)); assertThatThrownBy(() -> nioSslEngine.close(mockChannel)).isInstanceOf(GemFireIOException.class) .hasMessageContaining("exception closing SSL session") .hasCauseInstanceOf(SSLException.class); }
if( sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING ) return; // since this may be called either from a reading or a writing thread and because this method is synchronized it is necessary to double check if we are still handshaking. if( !tasks.isEmpty() ) { if( sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ) { if( !isBlocking() || readEngineResult.getStatus() == Status.BUFFER_UNDERFLOW ) { inCrypt.compact(); int read = socketChannel.read( inCrypt ); if( read == -1 ) { throw new IOException( "connection closed unexpectedly by peer" ); if( readEngineResult.getHandshakeStatus() == HandshakeStatus.FINISHED ) { createBuffers( sslEngine.getSession() ); return; if( tasks.isEmpty() || sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP ) { socketChannel.write( wrap( emptybuffer ) ); if( writeEngineResult.getHandshakeStatus() == HandshakeStatus.FINISHED ) { createBuffers( sslEngine.getSession() ); return;
if (state == State.CLOSING) return; state = State.CLOSING; sslEngine.closeOutbound(); try { if (prevState != State.NOT_INITALIZED && isConnected()) { SSLEngineResult wrapResult = sslEngine.wrap(emptyBuf, netWriteBuffer); if (wrapResult.getStatus() != SSLEngineResult.Status.CLOSED) { throw new IOException("Unexpected status returned by SSLEngine.wrap, expected CLOSED, received " + wrapResult.getStatus() + ". Will not send close message to peer."); log.debug("Failed to send SSL Close message", ie); } finally { socketChannel.socket().close(); socketChannel.close(); netReadBuffer = null; netWriteBuffer = null;
SSLEngineResult r = sslEngine.wrap(src, socketWriteBuffer); written += r.bytesConsumed(); Status s = r.getStatus(); throw new IllegalStateException(sm.getString( "asyncChannelWrapperSecure.statusWrap")); if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable = sslEngine.getDelegatedTask(); while (runnable != null) { runnable.run(); runnable = sslEngine.getDelegatedTask(); int toWrite = r.bytesProduced(); while (toWrite > 0) { Future<Integer> f = future.complete(Long.valueOf(written)); } else { future.fail(new IllegalStateException(sm.getString( "asyncChannelWrapperSecure.wrongStateWrite")));
if (wrap) { if (TRACE_SSL) msg.tracef("TLS wrap from %s to %s", Buffers.debugString(srcs, srcOff, srcLen), Buffers.debugString(sendBuffer)); result = engine.wrap(srcs, srcOff, srcLen, sendBuffer); WRAP_RESULT: switch (result.getStatus()) { case BUFFER_UNDERFLOW: { assert result.bytesConsumed() == 0; assert result.bytesProduced() == 0; assert result.bytesConsumed() == 0; assert result.bytesProduced() == 0; if (TRACE_SSL) msg.trace("TLS wrap operation OVERFLOW"); if (sendBuffer.position() == 0) { if (allAreClear(state, WRITE_FLAG_SHUTDOWN) && result.bytesProduced() == 0) { if (goal == IO_GOAL_FLUSH) { if (TRACE_SSL) msg.tracef("TLS wrap operation OK consumed: %d produced: %d", result.bytesConsumed(), result.bytesProduced()); state &= ~(WRITE_FLAG_NEEDS_READ | READ_FLAG_NEEDS_WRITE); final int consumed = result.bytesConsumed(); if (goal == IO_GOAL_READ) { if (result.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) { throw msg.unexpectedWrapResult(result.getStatus()); result = engine.unwrap(receiveBuffer, realDsts, 0, dstLen + 1); final long userProduced = preRem - Buffers.remaining(dsts, dstOff, dstLen); switch (result.getStatus()) { case BUFFER_OVERFLOW: {
SSLEngineResult res = sslEngine.wrap(src, outNetBuf); log.debug("Encrypted data [status=" + res.getStatus() + ", handshakeStaus=" + res.getHandshakeStatus() + ']'); if (res.getStatus() == OK) { if (res.getHandshakeStatus() == NEED_TASK) runTasks(); throw new SSLException("Failed to encrypt data (SSL engine error) [status=" + res.getStatus() + ", handshakeStatus=" + res.getHandshakeStatus() + ']');
switch (engine.getHandshakeStatus()) { case FINISHED: return; final ByteBuffer appDataOut = ByteBuffer.wrap(emptyMessage); final ByteBuffer outboundBuffer = streamOutManager.prepareForWrite(engine.getSession().getApplicationBufferSize()); final SSLEngineResult wrapHelloResult = engine.wrap(appDataOut, outboundBuffer); if (wrapHelloResult.getStatus() == Status.BUFFER_OVERFLOW) { streamOutManager.prepareForWrite(engine.getSession().getApplicationBufferSize()); continue; if (wrapHelloResult.getStatus() != Status.OK) { throw new SSLHandshakeException("Could not generate SSL Handshake information: SSLEngineResult: " + wrapHelloResult.toString()); logger.trace("{} Handshake response after unwrapping: {}", this, handshakeResponseResult); if (handshakeResponseResult.getStatus() == Status.BUFFER_UNDERFLOW) { final ByteBuffer writableDataIn = streamInManager.prepareForWrite(engine.getSession().getPacketBufferSize()); final int bytesRead = readData(writableDataIn); throw new SSLHandshakeException("Reached End-of-File marker while performing handshake"); } else if (handshakeResponseResult.getStatus() == Status.CLOSED) { throw new IOException("Channel was closed by peer during handshake"); } else {
throw new IllegalArgumentException(sm.getString("channel.nio.ssl.invalidBuffer")); if (!handshakeComplete) throw new IllegalStateException(sm.getString("channel.nio.ssl.incompleteHandshake")); int netread = sc.read(netInBuffer); unwrap = sslEngine.unwrap(netInBuffer, dst); if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { read += unwrap.bytesProduced(); if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { tasks(); if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { break; } else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW) { if (read > 0) { sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus())); throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()));
SSLEngineResult result = engine.wrap(in0, out0); in.skipBytes(result.bytesConsumed()); out.writerIndex(out.writerIndex() + result.bytesProduced()); switch (result.getStatus()) { case BUFFER_OVERFLOW: out.ensureWritable(engine.getSession().getPacketBufferSize()); break; default: