Java Code Examples for javax.net.ssl.SSLEngineResult#bytesProduced()

The following examples show how to use javax.net.ssl.SSLEngineResult#bytesProduced() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AsyncChannelWrapperSecure.java    From Tomcat8-Source-Read with MIT License 6 votes vote down vote up
private void checkResult(SSLEngineResult result, boolean wrap)
        throws SSLException {

    handshakeStatus = result.getHandshakeStatus();
    resultStatus = result.getStatus();

    if (resultStatus != Status.OK &&
            (wrap || resultStatus != Status.BUFFER_UNDERFLOW)) {
        throw new SSLException(
                sm.getString("asyncChannelWrapperSecure.check.notOk", resultStatus));
    }
    if (wrap && result.bytesConsumed() != 0) {
        throw new SSLException(sm.getString("asyncChannelWrapperSecure.check.wrap"));
    }
    if (!wrap && result.bytesProduced() != 0) {
        throw new SSLException(sm.getString("asyncChannelWrapperSecure.check.unwrap"));
    }
}
 
Example 2
Source File: SSLSocket.java    From whiskey with Apache License 2.0 6 votes vote down vote up
private void wrap() throws IOException {

            ArrayList<ByteBuffer> wrapped = new ArrayList<>();

            while (true) {
                // TODO(bgallagher) buffer pooling
                ByteBuffer out = ByteBuffer.allocate(engine.getSession().getPacketBufferSize());

                SSLEngineResult result = engine.wrap(pending(), out);

                if (result.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
                    throw new SSLException("renegotiation not supported");
                }

                if (result.bytesProduced() > 0) {
                    out.flip();
                    wrapped.add(out);
                } else {
                    break;
                }
            }

            setPending(wrapped.toArray(new ByteBuffer[wrapped.size()]));
        }
 
Example 3
Source File: AsyncChannelWrapperSecure.java    From tomcatsrc with Apache License 2.0 6 votes vote down vote up
private void checkResult(SSLEngineResult result, boolean wrap)
        throws SSLException {

    handshakeStatus = result.getHandshakeStatus();
    resultStatus = result.getStatus();

    if (resultStatus != Status.OK &&
            (wrap || resultStatus != Status.BUFFER_UNDERFLOW)) {
        throw new SSLException("TODO");
    }
    if (wrap && result.bytesConsumed() != 0) {
        throw new SSLException("TODO");
    }
    if (!wrap && result.bytesProduced() != 0) {
        throw new SSLException("TODO");
    }
}
 
Example 4
Source File: TlsCryptoSocket.java    From vespa with Apache License 2.0 5 votes vote down vote up
private int applicationDataUnwrap(ByteBuffer dst) throws IOException {
    SSLEngineResult result = sslEngineUnwrap(dst);
    if (result.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) throw new SSLException("Renegotiation detected");
    switch (result.getStatus()) {
        case OK:
            return result.bytesProduced();
        case BUFFER_OVERFLOW:
        case BUFFER_UNDERFLOW:
            return 0;
        default:
            throw unexpectedStatusException(result.getStatus());
    }
}
 
Example 5
Source File: TlsCryptoSocket.java    From vespa with Apache License 2.0 5 votes vote down vote up
private boolean handshakeUnwrap() throws IOException {
    SSLEngineResult result = sslEngineUnwrap(handshakeDummyBuffer);
    switch (result.getStatus()) {
        case OK:
            if (result.bytesProduced() > 0) throw new SSLException("Got application data in handshake unwrap");
            return true;
        case BUFFER_UNDERFLOW:
            return false;
        default:
            throw unexpectedStatusException(result.getStatus());
    }
}
 
Example 6
Source File: Worker.java    From sslfacade with MIT License 5 votes vote down vote up
private void emitPlainData(SSLEngineResult result)
{
  if (result.bytesProduced() > 0) {
    ByteBuffer internalPlainBuffer = _buffers.get(BufferType.IN_PLAIN);
    _sslListener.onPlainData(makeExternalBuffer(internalPlainBuffer));
  }

}
 
Example 7
Source File: Worker.java    From getty with Apache License 2.0 5 votes vote down vote up
private void emitWrappedData(SSLEngineResult result)
{
  if (result.bytesProduced() > 0) {
    ByteBuffer internalCipherBuffer = _buffers.get(BufferType.OUT_CIPHER);
    _sslListener.onWrappedData(makeExternalBuffer(internalCipherBuffer));
  }
}
 
Example 8
Source File: Worker.java    From sslfacade with MIT License 5 votes vote down vote up
private void emitWrappedData(SSLEngineResult result)
{
  if (result.bytesProduced() > 0) {
    ByteBuffer internalCipherBuffer = _buffers.get(BufferType.OUT_CIPHER);
    _sslListener.onWrappedData(makeExternalBuffer(internalCipherBuffer));
  }
}
 
Example 9
Source File: TlsChannelImpl.java    From pgadba with BSD 2-Clause "Simplified" License 5 votes vote down vote up
private UnwrapResult unwrapLoop(Optional<ByteBufferSet> dest, HandshakeStatus statusCondition, boolean closing)
    throws SSLException {
  ByteBufferSet effDest = dest.orElseGet(() -> {
    inPlain.prepare();
    return new ByteBufferSet(inPlain.buffer);
  });
  while (true) {
    Util.assertTrue(inPlain.nullOrEmpty());
    SSLEngineResult result = callEngineUnwrap(effDest);
    /*
     * Note that data can be returned even in case of overflow, in that
     * case, just return the data.
     */
    if (result.bytesProduced() > 0 || result.getStatus() == Status.BUFFER_UNDERFLOW
        || !closing && result.getStatus() == Status.CLOSED
        || result.getHandshakeStatus() != statusCondition) {
      boolean wasClosed = result.getStatus() == Status.CLOSED;
      return new UnwrapResult(result.bytesProduced(), result.getHandshakeStatus(), wasClosed);
    }
    if (result.getStatus() == Status.BUFFER_OVERFLOW) {
      if (dest.isPresent() && effDest == dest.get()) {
        /*
         * The client-supplier buffer is not big enough. Use the
         * internal inPlain buffer, also ensure that it is bigger
         * than the too-small supplied one.
         */
        inPlain.prepare();
        ensureInPlainCapacity(Math.min(((int) dest.get().remaining()) * 2, maxTlsPacketSize));
      } else {
        inPlain.enlarge();
      }
      // inPlain changed, re-create the wrapper
      effDest = new ByteBufferSet(inPlain.buffer);
    }
  }
}
 
Example 10
Source File: Worker.java    From t-io with Apache License 2.0 5 votes vote down vote up
private void emitWrappedData(SslVo sslVo, SSLEngineResult result) {
	if (result.bytesProduced() > 0) {
		ByteBuffer internalCipherBuffer = _buffers.get(BufferType.OUT_CIPHER);
		sslVo.setByteBuffer(makeExternalBuffer(internalCipherBuffer));
		_sslListener.onWrappedData(sslVo);
	}
}
 
Example 11
Source File: SslConnection.java    From IoTgo_Android_App with MIT License 4 votes vote down vote up
private synchronized boolean wrap(final Buffer buffer) throws IOException
{
    ByteBuffer bbuf=extractByteBuffer(buffer);
    final SSLEngineResult result;

    synchronized(bbuf)
    {
        _outbound.compact();
        ByteBuffer out_buffer=_outbound.getByteBuffer();
        synchronized(out_buffer)
        {
            try
            {
                bbuf.position(buffer.getIndex());
                bbuf.limit(buffer.putIndex());
                out_buffer.position(_outbound.putIndex());
                out_buffer.limit(out_buffer.capacity());
                result=_engine.wrap(bbuf,out_buffer);
                if (_logger.isDebugEnabled())
                    _logger.debug("{} wrap {} {} consumed={} produced={}",
                        _session,
                        result.getStatus(),
                        result.getHandshakeStatus(),
                        result.bytesConsumed(),
                        result.bytesProduced());


                buffer.skip(result.bytesConsumed());
                _outbound.setPutIndex(_outbound.putIndex()+result.bytesProduced());
            }
            catch(SSLException e)
            {
                _logger.debug(String.valueOf(_endp), e);
                _endp.close();
                throw e;
            }
            finally
            {
                out_buffer.position(0);
                out_buffer.limit(out_buffer.capacity());
                bbuf.position(0);
                bbuf.limit(bbuf.capacity());
            }
        }
    }

    switch(result.getStatus())
    {
        case BUFFER_UNDERFLOW:
            throw new IllegalStateException();

        case BUFFER_OVERFLOW:
            break;

        case OK:
            if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
                _handshook=true;
            break;

        case CLOSED:
            _logger.debug("wrap CLOSE {} {}",this,result);
            if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
                _endp.close();
            break;

        default:
            _logger.debug("{} wrap default {}",_session,result);
        throw new IOException(result.toString());
    }

    return result.bytesConsumed()>0 || result.bytesProduced()>0;
}
 
Example 12
Source File: AsyncChannelWrapperSecure.java    From Tomcat8-Source-Read with MIT License 4 votes vote down vote up
@Override
public void run() {
    long written = 0;

    try {
        for (int i = offset; i < offset + length; i++) {
            ByteBuffer src = srcs[i];
            while (src.hasRemaining()) {
                socketWriteBuffer.clear();

                // Encrypt the data
                SSLEngineResult r = sslEngine.wrap(src, socketWriteBuffer);
                written += r.bytesConsumed();
                Status s = r.getStatus();

                if (s == Status.OK || s == Status.BUFFER_OVERFLOW) {
                    // Need to write out the bytes and may need to read from
                    // the source again to empty it
                } else {
                    // Status.BUFFER_UNDERFLOW - only happens on unwrap
                    // Status.CLOSED - unexpected
                    throw new IllegalStateException(sm.getString(
                            "asyncChannelWrapperSecure.statusWrap"));
                }

                // Check for tasks
                if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                    Runnable runnable = sslEngine.getDelegatedTask();
                    while (runnable != null) {
                        runnable.run();
                        runnable = sslEngine.getDelegatedTask();
                    }
                }

                socketWriteBuffer.flip();

                // Do the write
                int toWrite = r.bytesProduced();
                while (toWrite > 0) {
                    Future<Integer> f =
                            socketChannel.write(socketWriteBuffer);
                    Integer socketWrite = f.get();
                    toWrite -= socketWrite.intValue();
                }
            }
        }


        if (writing.compareAndSet(true, false)) {
            future.complete(Long.valueOf(written));
        } else {
            future.fail(new IllegalStateException(sm.getString(
                    "asyncChannelWrapperSecure.wrongStateWrite")));
        }
    } catch (Exception e) {
        writing.set(false);
        future.fail(e);
    }
}
 
Example 13
Source File: AsyncChannelWrapperSecure.java    From tomcatsrc with Apache License 2.0 4 votes vote down vote up
@Override
public void run() {
    int read = 0;

    boolean forceRead = false;

    try {
        while (read == 0) {
            socketReadBuffer.compact();

            if (forceRead) {
                forceRead = false;
                Future<Integer> f = socketChannel.read(socketReadBuffer);
                Integer socketRead = f.get();
                if (socketRead.intValue() == -1) {
                    throw new EOFException(sm.getString(
                            "asyncChannelWrapperSecure.eof"));
                }
            }

            socketReadBuffer.flip();

            if (socketReadBuffer.hasRemaining()) {
                // Decrypt the data in the buffer
                SSLEngineResult r =
                        sslEngine.unwrap(socketReadBuffer, dest);
                read += r.bytesProduced();
                Status s = r.getStatus();

                if (s == Status.OK) {
                    // Bytes available for reading and there may be
                    // sufficient data in the socketReadBuffer to
                    // support further reads without reading from the
                    // socket
                } else if (s == Status.BUFFER_UNDERFLOW) {
                    // There is partial data in the socketReadBuffer
                    if (read == 0) {
                        // Need more data before the partial data can be
                        // processed and some output generated
                        forceRead = true;
                    }
                    // else return the data we have and deal with the
                    // partial data on the next read
                } else if (s == Status.BUFFER_OVERFLOW) {
                    // Not enough space in the destination buffer to
                    // store all of the data. We could use a bytes read
                    // value of -bufferSizeRequired to signal the new
                    // buffer size required but an explicit exception is
                    // clearer.
                    if (reading.compareAndSet(true, false)) {
                        throw new ReadBufferOverflowException(sslEngine.
                                getSession().getApplicationBufferSize());
                    } else {
                        future.fail(new IllegalStateException(sm.getString(
                                "asyncChannelWrapperSecure.wrongStateRead")));
                    }
                } else {
                    // Status.CLOSED - unexpected
                    throw new IllegalStateException(sm.getString(
                            "asyncChannelWrapperSecure.statusUnwrap"));
                }

                // Check for tasks
                if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                    Runnable runnable = sslEngine.getDelegatedTask();
                    while (runnable != null) {
                        runnable.run();
                        runnable = sslEngine.getDelegatedTask();
                    }
                }
            } else {
                forceRead = true;
            }
        }


        if (reading.compareAndSet(true, false)) {
            future.complete(Integer.valueOf(read));
        } else {
            future.fail(new IllegalStateException(sm.getString(
                    "asyncChannelWrapperSecure.wrongStateRead")));
        }
    } catch (Exception e) {
        future.fail(e);
    }
}
 
Example 14
Source File: AsyncChannelWrapperSecure.java    From tomcatsrc with Apache License 2.0 4 votes vote down vote up
@Override
public void run() {
    long written = 0;

    try {
        for (int i = offset; i < offset + length; i++) {
            ByteBuffer src = srcs[i];
            while (src.hasRemaining()) {
                socketWriteBuffer.clear();

                // Encrypt the data
                SSLEngineResult r = sslEngine.wrap(src, socketWriteBuffer);
                written += r.bytesConsumed();
                Status s = r.getStatus();

                if (s == Status.OK || s == Status.BUFFER_OVERFLOW) {
                    // Need to write out the bytes and may need to read from
                    // the source again to empty it
                } else {
                    // Status.BUFFER_UNDERFLOW - only happens on unwrap
                    // Status.CLOSED - unexpected
                    throw new IllegalStateException(sm.getString(
                            "asyncChannelWrapperSecure.statusWrap"));
                }

                // Check for tasks
                if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                    Runnable runnable = sslEngine.getDelegatedTask();
                    while (runnable != null) {
                        runnable.run();
                        runnable = sslEngine.getDelegatedTask();
                    }
                }

                socketWriteBuffer.flip();

                // Do the write
                int toWrite = r.bytesProduced();
                while (toWrite > 0) {
                    Future<Integer> f =
                            socketChannel.write(socketWriteBuffer);
                    Integer socketWrite = f.get();
                    toWrite -= socketWrite.intValue();
                }
            }
        }


        if (writing.compareAndSet(true, false)) {
            future.complete(Long.valueOf(written));
        } else {
            future.fail(new IllegalStateException(sm.getString(
                    "asyncChannelWrapperSecure.wrongStateWrite")));
        }
    } catch (Exception e) {
        future.fail(e);
    }
}
 
Example 15
Source File: TlsChannelImpl.java    From tls-channel with MIT License 4 votes vote down vote up
private void unwrapLoop(HandshakeStatus originalStatus) throws SSLException {

    ByteBufferSet effDest;
    if (suppliedInPlain != null) {
      effDest = suppliedInPlain;
    } else {
      inPlain.prepare();
      effDest = new ByteBufferSet(inPlain.buffer);
    }

    while (true) {
      Util.assertTrue(inPlain.nullOrEmpty());
      SSLEngineResult result = callEngineUnwrap(effDest);
      /*
       * Note that data can be returned even in case of overflow, in that
       * case, just return the data.
       */
      if (result.bytesProduced() > 0
          || result.getStatus() == Status.BUFFER_UNDERFLOW
          || result.getStatus() == Status.CLOSED
          || result.getHandshakeStatus() != originalStatus) {
        bytesToReturn = result.bytesProduced();
        if (result.getStatus() == Status.CLOSED) {
          shutdownReceived = true;
        }
        return;
      }
      if (result.getStatus() == Status.BUFFER_OVERFLOW) {
        if (suppliedInPlain != null && effDest == suppliedInPlain) {
          /*
           * The client-supplier buffer is not big enough. Use the
           * internal inPlain buffer, also ensure that it is bigger
           * than the too-small supplied one.
           */
          inPlain.prepare();
          ensureInPlainCapacity(
              Math.min(((int) suppliedInPlain.remaining()) * 2, maxTlsPacketSize));
        } else {
          inPlain.enlarge();
        }
        // inPlain changed, re-create the wrapper
        effDest = new ByteBufferSet(inPlain.buffer);
      }
    }
  }
 
Example 16
Source File: SslConnection.java    From IoTgo_Android_App with MIT License 4 votes vote down vote up
private synchronized boolean wrap(final Buffer buffer) throws IOException
{
    ByteBuffer bbuf=extractByteBuffer(buffer);
    final SSLEngineResult result;

    synchronized(bbuf)
    {
        _outbound.compact();
        ByteBuffer out_buffer=_outbound.getByteBuffer();
        synchronized(out_buffer)
        {
            try
            {
                bbuf.position(buffer.getIndex());
                bbuf.limit(buffer.putIndex());
                out_buffer.position(_outbound.putIndex());
                out_buffer.limit(out_buffer.capacity());
                result=_engine.wrap(bbuf,out_buffer);
                if (_logger.isDebugEnabled())
                    _logger.debug("{} wrap {} {} consumed={} produced={}",
                        _session,
                        result.getStatus(),
                        result.getHandshakeStatus(),
                        result.bytesConsumed(),
                        result.bytesProduced());


                buffer.skip(result.bytesConsumed());
                _outbound.setPutIndex(_outbound.putIndex()+result.bytesProduced());
            }
            catch(SSLException e)
            {
                _logger.debug(String.valueOf(_endp), e);
                _endp.close();
                throw e;
            }
            finally
            {
                out_buffer.position(0);
                out_buffer.limit(out_buffer.capacity());
                bbuf.position(0);
                bbuf.limit(bbuf.capacity());
            }
        }
    }

    switch(result.getStatus())
    {
        case BUFFER_UNDERFLOW:
            throw new IllegalStateException();

        case BUFFER_OVERFLOW:
            break;

        case OK:
            if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
                _handshook=true;
            break;

        case CLOSED:
            _logger.debug("wrap CLOSE {} {}",this,result);
            if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
                _endp.close();
            break;

        default:
            _logger.debug("{} wrap default {}",_session,result);
        throw new IOException(result.toString());
    }

    return result.bytesConsumed()>0 || result.bytesProduced()>0;
}
 
Example 17
Source File: AsyncChannelWrapperSecure.java    From Tomcat7.0.67 with Apache License 2.0 4 votes vote down vote up
@Override
public void run() {
    long written = 0;

    try {
        for (int i = offset; i < offset + length; i++) {
            ByteBuffer src = srcs[i];
            while (src.hasRemaining()) {
                socketWriteBuffer.clear();

                // Encrypt the data
                SSLEngineResult r = sslEngine.wrap(src, socketWriteBuffer);
                written += r.bytesConsumed();
                Status s = r.getStatus();

                if (s == Status.OK || s == Status.BUFFER_OVERFLOW) {
                    // Need to write out the bytes and may need to read from
                    // the source again to empty it
                } else {
                    // Status.BUFFER_UNDERFLOW - only happens on unwrap
                    // Status.CLOSED - unexpected
                    throw new IllegalStateException(sm.getString(
                            "asyncChannelWrapperSecure.statusWrap"));
                }

                // Check for tasks
                if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                    Runnable runnable = sslEngine.getDelegatedTask();
                    while (runnable != null) {
                        runnable.run();
                        runnable = sslEngine.getDelegatedTask();
                    }
                }

                socketWriteBuffer.flip();

                // Do the write
                int toWrite = r.bytesProduced();
                while (toWrite > 0) {
                    Future<Integer> f =
                            socketChannel.write(socketWriteBuffer);
                    Integer socketWrite = f.get();
                    toWrite -= socketWrite.intValue();
                }
            }
        }


        if (writing.compareAndSet(true, false)) {
            future.complete(Long.valueOf(written));
        } else {
            future.fail(new IllegalStateException(sm.getString(
                    "asyncChannelWrapperSecure.wrongStateWrite")));
        }
    } catch (Exception e) {
        future.fail(e);
    }
}
 
Example 18
Source File: OpenSslEngineTest.java    From netty-4.1.22 with Apache License 2.0 4 votes vote down vote up
@Test
public void testPartialPacketUnwrapJDKCompatabilityModeOff() throws Exception {
    SelfSignedCertificate cert = new SelfSignedCertificate();

    clientSslCtx = SslContextBuilder
            .forClient()
            .trustManager(cert.cert())
            .sslProvider(sslClientProvider())
            .build();
    SSLEngine client = clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine();

    serverSslCtx = SslContextBuilder
            .forServer(cert.certificate(), cert.privateKey())
            .sslProvider(sslServerProvider())
            .build();
    SSLEngine server = serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine();

    try {
        ByteBuffer plainClient = allocateBuffer(1024);
        ByteBuffer plainClient2 = allocateBuffer(512);
        ByteBuffer plainClientTotal = allocateBuffer(plainClient.capacity() + plainClient2.capacity());
        plainClientTotal.put(plainClient);
        plainClientTotal.put(plainClient2);
        plainClient.clear();
        plainClient2.clear();
        plainClientTotal.flip();

        ByteBuffer encClientToServer = allocateBuffer(client.getSession().getPacketBufferSize());
        ByteBuffer plainServer = allocateBuffer(server.getSession().getApplicationBufferSize());

        handshake(client, server);

        SSLEngineResult result = client.wrap(plainClient, encClientToServer);
        assertEquals(SSLEngineResult.Status.OK, result.getStatus());
        assertEquals(result.bytesConsumed(), plainClient.capacity());
        final int encClientLen = result.bytesProduced();

        result = client.wrap(plainClient2, encClientToServer);
        assertEquals(SSLEngineResult.Status.OK, result.getStatus());
        assertEquals(result.bytesConsumed(), plainClient2.capacity());
        final int encClientLen2 = result.bytesProduced();

        // Flip so we can read it.
        encClientToServer.flip();

        // Consume a partial TLS packet.
        ByteBuffer encClientFirstHalf = encClientToServer.duplicate();
        encClientFirstHalf.limit(encClientLen / 2);
        result = server.unwrap(encClientFirstHalf, plainServer);
        assertEquals(SSLEngineResult.Status.OK, result.getStatus());
        assertEquals(result.bytesConsumed(), encClientLen / 2);
        encClientToServer.position(result.bytesConsumed());

        // We now have half of the first packet and the whole second packet, so lets decode all but the last byte.
        ByteBuffer encClientAllButLastByte = encClientToServer.duplicate();
        final int encClientAllButLastByteLen = encClientAllButLastByte.remaining() - 1;
        encClientAllButLastByte.limit(encClientAllButLastByte.limit() - 1);
        result = server.unwrap(encClientAllButLastByte, plainServer);
        assertEquals(SSLEngineResult.Status.OK, result.getStatus());
        assertEquals(result.bytesConsumed(), encClientAllButLastByteLen);
        encClientToServer.position(encClientToServer.position() + result.bytesConsumed());

        // Read the last byte and verify the original content has been decrypted.
        result = server.unwrap(encClientToServer, plainServer);
        assertEquals(SSLEngineResult.Status.OK, result.getStatus());
        assertEquals(result.bytesConsumed(), 1);
        plainServer.flip();
        assertEquals(plainClientTotal, plainServer);
    } finally {
        cert.delete();
        cleanupClientSslEngine(client);
        cleanupServerSslEngine(server);
    }
}
 
Example 19
Source File: SslHandler.java    From netty-4.1.22 with Apache License 2.0 4 votes vote down vote up
/**
 * This method will not call
 * {@link #setHandshakeFailure(ChannelHandlerContext, Throwable, boolean, boolean, boolean)} or
 * {@link #setHandshakeFailure(ChannelHandlerContext, Throwable)}.
 * @return {@code true} if this method ends on {@link SSLEngineResult.HandshakeStatus#NOT_HANDSHAKING}.
 */
private boolean wrapNonAppData(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException {
    ByteBuf out = null;
    ByteBufAllocator alloc = ctx.alloc();
    try {
        // Only continue to loop if the handler was not removed in the meantime.
        // See https://github.com/netty/netty/issues/5860
        while (!ctx.isRemoved()) {
            if (out == null) {
                // As this is called for the handshake we have no real idea how big the buffer needs to be.
                // That said 2048 should give us enough room to include everything like ALPN / NPN data.
                // If this is not enough we will increase the buffer in wrap(...).
                out = allocateOutNetBuf(ctx, 2048, 1);
            }
            SSLEngineResult result = wrap(alloc, engine, Unpooled.EMPTY_BUFFER, out);

            if (result.bytesProduced() > 0) {
                ctx.write(out);
                if (inUnwrap) {
                    needsFlush = true;
                }
                out = null;
            }

            switch (result.getHandshakeStatus()) {
                case FINISHED:
                    setHandshakeSuccess();
                    return false;
                case NEED_TASK:
                    runDelegatedTasks();
                    break;
                case NEED_UNWRAP:
                    if (inUnwrap) {
                        // If we asked for a wrap, the engine requested an unwrap, and we are in unwrap there is
                        // no use in trying to call wrap again because we have already attempted (or will after we
                        // return) to feed more data to the engine.
                        return false;
                    }

                    unwrapNonAppData(ctx);
                    break;
                case NEED_WRAP:
                    break;
                case NOT_HANDSHAKING:
                    setHandshakeSuccessIfStillHandshaking();
                    // Workaround for TLS False Start problem reported at:
                    // https://github.com/netty/netty/issues/1108#issuecomment-14266970
                    if (!inUnwrap) {
                        unwrapNonAppData(ctx);
                    }
                    return true;
                default:
                    throw new IllegalStateException("Unknown handshake status: " + result.getHandshakeStatus());
            }

            if (result.bytesProduced() == 0) {
                break;
            }

            // It should not consume empty buffers when it is not handshaking
            // Fix for Android, where it was encrypting empty buffers even when not handshaking
            if (result.bytesConsumed() == 0 && result.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) {
                break;
            }
        }
    }  finally {
        if (out != null) {
            out.release();
        }
    }
    return false;
}
 
Example 20
Source File: AsyncChannelWrapperSecure.java    From Tomcat8-Source-Read with MIT License 4 votes vote down vote up
@Override
public void run() {
    int read = 0;

    boolean forceRead = false;

    try {
        while (read == 0) {
            socketReadBuffer.compact();

            if (forceRead) {
                forceRead = false;
                Future<Integer> f = socketChannel.read(socketReadBuffer);
                Integer socketRead = f.get();
                if (socketRead.intValue() == -1) {
                    throw new EOFException(sm.getString("asyncChannelWrapperSecure.eof"));
                }
            }

            socketReadBuffer.flip();

            if (socketReadBuffer.hasRemaining()) {
                // Decrypt the data in the buffer
                SSLEngineResult r = sslEngine.unwrap(socketReadBuffer, dest);
                read += r.bytesProduced();
                Status s = r.getStatus();

                if (s == Status.OK) {
                    // Bytes available for reading and there may be
                    // sufficient data in the socketReadBuffer to
                    // support further reads without reading from the
                    // socket
                } else if (s == Status.BUFFER_UNDERFLOW) {
                    // There is partial data in the socketReadBuffer
                    if (read == 0) {
                        // Need more data before the partial data can be
                        // processed and some output generated
                        forceRead = true;
                    }
                    // else return the data we have and deal with the
                    // partial data on the next read
                } else if (s == Status.BUFFER_OVERFLOW) {
                    // Not enough space in the destination buffer to
                    // store all of the data. We could use a bytes read
                    // value of -bufferSizeRequired to signal the new
                    // buffer size required but an explicit exception is
                    // clearer.
                    if (reading.compareAndSet(true, false)) {
                        throw new ReadBufferOverflowException(sslEngine.
                                getSession().getApplicationBufferSize());
                    } else {
                        future.fail(new IllegalStateException(sm.getString(
                                "asyncChannelWrapperSecure.wrongStateRead")));
                    }
                } else {
                    // Status.CLOSED - unexpected
                    throw new IllegalStateException(sm.getString(
                            "asyncChannelWrapperSecure.statusUnwrap"));
                }

                // Check for tasks
                if (r.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                    Runnable runnable = sslEngine.getDelegatedTask();
                    while (runnable != null) {
                        runnable.run();
                        runnable = sslEngine.getDelegatedTask();
                    }
                }
            } else {
                forceRead = true;
            }
        }


        if (reading.compareAndSet(true, false)) {
            future.complete(Integer.valueOf(read));
        } else {
            future.fail(new IllegalStateException(sm.getString(
                    "asyncChannelWrapperSecure.wrongStateRead")));
        }
    } catch (RuntimeException | ReadBufferOverflowException | SSLException | EOFException |
            ExecutionException | InterruptedException e) {
        reading.set(false);
        future.fail(e);
    }
}