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

The following examples show how to use javax.net.ssl.SSLEngineResult#bytesConsumed() . 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: SecureNio2Channel.java    From Tomcat8-Source-Read with MIT License 6 votes vote down vote up
protected void wrap() {
    try {
        if (!netOutBuffer.hasRemaining()) {
            netOutBuffer.clear();
            SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
            written = result.bytesConsumed();
            netOutBuffer.flip();
            if (result.getStatus() == Status.OK) {
                if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
                    tasks();
            } else {
                t = new IOException(sm.getString("channel.nio.ssl.wrapFail", result.getStatus()));
            }
        }
        integer = sc.write(netOutBuffer);
    } catch (SSLException e) {
        t = e;
    }
}
 
Example 3
Source File: TlsChannelImpl.java    From pgadba with BSD 2-Clause "Simplified" License 6 votes vote down vote up
private WrapResult wrapLoop(ByteBufferSet source) throws SSLException {
  while (true) {
    SSLEngineResult result = callEngineWrap(source);
    switch (result.getStatus()) {
      case OK:
      case CLOSED:
        return new WrapResult(result.bytesConsumed(), result.getHandshakeStatus());
      case BUFFER_OVERFLOW:
        Util.assertTrue(result.bytesConsumed() == 0);
        outEncrypted.enlarge();
        break;
      case BUFFER_UNDERFLOW:
        throw new IllegalStateException();
      default:
        throw new RuntimeException("reached default clause in switch");
    }
  }
}
 
Example 4
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 5
Source File: SslReadWriteSelectorHandler.java    From simplewebserver with Apache License 2.0 5 votes vote down vote up
/**
 * Try to flush out any existing outbound data, then try to wrap
 * anything new contained in the src buffer.
 * <p>
 * Return the number of bytes actually consumed from the buffer,
 * but the data may actually be still sitting in the output buffer,
 * waiting to be flushed.
 */
private int doWrite(ByteBuffer src) throws IOException {
    int retValue = 0;

    if (outNetBB.hasRemaining() && !tryFlush(outNetBB)) {
        return retValue;
    }

    /*
     * The data buffer is empty, we can reuse the entire buffer.
     */
    outNetBB.clear();

    SSLEngineResult result = sslEngine.wrap(src, outNetBB);
    retValue = result.bytesConsumed();

    outNetBB.flip();

    if (result.getStatus() == Status.OK) {
        if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
            doTasks();
        }
    } else {
        throw new IOException("sslEngine error during data write: " +
                result.getStatus());
    }

    /*
     * Try to flush the data, regardless of whether or not
     * it's been selected.  Odds of a write buffer being full
     * is less than a read buffer being empty.
     */
    tryFlush(src);
    if (outNetBB.hasRemaining()) {
        tryFlush(outNetBB);
    }

    return retValue;
}
 
Example 6
Source File: SslConnection.java    From IoTgo_Android_App with MIT License 4 votes vote down vote up
private synchronized boolean unwrap(final Buffer buffer) throws IOException
{
    if (!_inbound.hasContent())
        return false;

    ByteBuffer bbuf=extractByteBuffer(buffer);
    final SSLEngineResult result;

    synchronized(bbuf)
    {
        ByteBuffer in_buffer=_inbound.getByteBuffer();
        synchronized(in_buffer)
        {
            try
            {
                bbuf.position(buffer.putIndex());
                bbuf.limit(buffer.capacity());
                in_buffer.position(_inbound.getIndex());
                in_buffer.limit(_inbound.putIndex());

                result=_engine.unwrap(in_buffer,bbuf);
                if (_logger.isDebugEnabled())
                    _logger.debug("{} unwrap {} {} consumed={} produced={}",
                        _session,
                        result.getStatus(),
                        result.getHandshakeStatus(),
                        result.bytesConsumed(),
                        result.bytesProduced());

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

    switch(result.getStatus())
    {
        case BUFFER_UNDERFLOW:
            if (_endp.isInputShutdown())
                _inbound.clear();
            break;

        case BUFFER_OVERFLOW:
            if (_logger.isDebugEnabled()) _logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString());
            break;

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

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

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

    //if (LOG.isDebugEnabled() && result.bytesProduced()>0)
    //    LOG.debug("{} unwrapped '{}'",_session,buffer);

    return result.bytesConsumed()>0 || result.bytesProduced()>0;
}
 
Example 7
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 8
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 9
Source File: SslHandler.java    From netty4.0.27Learn with Apache License 2.0 4 votes vote down vote up
/**
 * Unwraps inbound SSL records.
 */
private void unwrap(
        ChannelHandlerContext ctx, ByteBuf packet, int offset, int length) throws SSLException {

    boolean wrapLater = false;
    boolean notifyClosure = false;
    ByteBuf decodeOut = allocate(ctx, length);
    try {
        for (;;) {
            final SSLEngineResult result = unwrap(engine, 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;

            if (status == Status.CLOSED) {
                // notify about the CLOSED state of the SSLEngine. See #137
                notifyClosure = true;
            }

            switch (handshakeStatus) {
                case NEED_UNWRAP:
                    break;
                case NEED_WRAP:
                    wrapNonAppData(ctx, true);
                    break;
                case NEED_TASK:
                    runDelegatedTasks();
                    break;
                case FINISHED:
                    setHandshakeSuccess();
                    wrapLater = true;
                    continue;
                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;
                    }

                    break;
                default:
                    throw new IllegalStateException("unknown handshake status: " + handshakeStatus);
            }

            if (status == Status.BUFFER_UNDERFLOW || consumed == 0 && produced == 0) {
                break;
            }
        }

        if (wrapLater) {
            wrap(ctx, true);
        }

        if (notifyClosure) {
            sslCloseFuture.trySuccess(ctx.channel());
        }
    } catch (SSLException e) {
        setHandshakeFailure(ctx, e);
        throw e;
    } finally {
        if (decodeOut.isReadable()) {
            ctx.fireChannelRead(decodeOut);
        } else {
            decodeOut.release();
        }
    }
}
 
Example 10
Source File: SimpleSslTransportWrapper.java    From qpid-proton-j with Apache License 2.0 4 votes vote down vote up
/**
 * Wrap the underlying transport's output, passing it to the output buffer.
 *
 * {@link #_outputBuffer} is assumed to be writeable on entry and is guaranteed to
 * be still writeable on exit.
 */
private void wrapOutput() throws SSLException
{
    while (true) {
        int pending = _underlyingOutput.pending();
        if (pending < 0) {
            _head_closed = true;
        }

        ByteBuffer clearOutputBuffer = _underlyingOutput.head();
        SSLEngineResult result = _sslEngine.wrap(clearOutputBuffer, _outputBuffer);
        logEngineClientModeAndResult(result, "output");

        int written = result.bytesConsumed();
        _underlyingOutput.pop(written);
        pending = _underlyingOutput.pending();

        Status status = result.getStatus();
        switch (status) {
        case CLOSED:
            _head_closed = true;
            break;
        case OK:
            break;
        case BUFFER_OVERFLOW:
            ByteBuffer old = _outputBuffer;
            _outputBuffer = newWriteableBuffer(_outputBuffer.capacity()*2);
            _head = _outputBuffer.asReadOnlyBuffer();
            old.flip();
            _outputBuffer.put(old);
            continue;
        case BUFFER_UNDERFLOW:
            throw new IllegalStateException("app buffer underflow");
        }

        HandshakeStatus hstatus = result.getHandshakeStatus();
        switch (hstatus) {
        case NEED_UNWRAP:
            // wait for input data
            if (_inputBuffer.position() == 0 && _tail_closed) {
                _head_closed = true;
            }
            break;
        case NEED_WRAP:
            // keep looping
            continue;
        case NEED_TASK:
            runDelegatedTasks(result);
            continue;
        case FINISHED:
            updateCipherAndProtocolName(result);
            // intentionally fall through
        case NOT_HANDSHAKING:
            if (pending > 0 && status == Status.OK) {
                continue;
            } else {
                break;
            }
        }

        break;
    }
}
 
Example 11
Source File: SSLTransmission.java    From ambry with Apache License 2.0 4 votes vote down vote up
/**
 * Writes a sequence of bytes to this channel from the given buffer.
 *
 * @param src The buffer from which bytes are to be retrieved
 * @return The number of bytes decrypted and written to netWriteBuffer. No guarantee that data in the temporary
 * buffer will be completely written to the underlying channel right away. So the caller has to make sure to check
 * the remaining bytes in the netWriteBuffer apart from checking the remaining bytes in src bytebuffer. This method
 * is called from write() in the same class
 * @throws IOException If some other I/O error occurs
 */
@Override
public int write(ByteBuffer src) throws IOException {
  if (closing) {
    throw new IllegalStateException("Channel is in closing state");
  } else if (!handshakeComplete) {
    return 0;
  } else if (!flush(netWriteBuffer)) {
    return 0;
  }

  int written = 0;
  while (src.remaining() != 0) {
    netWriteBuffer.clear();
    long startTimeNs = SystemTime.getInstance().nanoseconds();
    SSLEngineResult wrapResult = sslEngine.wrap(src, netWriteBuffer);
    long encryptionTimeNs = SystemTime.getInstance().nanoseconds() - startTimeNs;
    logger.trace("SSL encryption time: {} ns for {} bytes", encryptionTimeNs, wrapResult.bytesConsumed());
    if (wrapResult.bytesConsumed() > 0) {
      metrics.sslEncryptionTimeInUsPerKB.mark(encryptionTimeNs / wrapResult.bytesConsumed());
    }
    netWriteBuffer.flip();
    //handle ssl renegotiation
    if (wrapResult.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING && wrapResult.getStatus() == Status.OK) {
      handshake();
      metrics.sslRenegotiationCount.inc();
      break;
    }

    if (wrapResult.getStatus() == SSLEngineResult.Status.OK) {
      written += wrapResult.bytesConsumed();
      if (!flush(netWriteBuffer)) {
        // break if socketChannel can't accept all data in netWriteBuffer
        break;
      }
      // otherwise, we are safe to clear the buffer for next iteration.
    } else if (wrapResult.getStatus() == Status.BUFFER_OVERFLOW) {
      handleWrapOverflow();
    } else if (wrapResult.getStatus() == Status.BUFFER_UNDERFLOW) {
      throw new IllegalStateException("SSL BUFFER_UNDERFLOW during write");
    } else if (wrapResult.getStatus() == Status.CLOSED) {
      throw new EOFException();
    }
  }
  return written;
}
 
Example 12
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 13
Source File: SslConduit.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Wraps the user data and attempts to send it to the remote client. If data has already been buffered then
 * this is attempted to be sent first.
 *
 * If the supplied buffers are null then a wrap operation is still attempted, which will happen during the
 * handshaking process.
 * @param userBuffers The buffers
 * @param off         The offset
 * @param len         The length
 * @return The amount of data consumed
 * @throws IOException
 */
private long doWrap(ByteBuffer[] userBuffers, int off, int len) throws IOException {
    if(anyAreSet(state, FLAG_CLOSED)) {
        throw new ClosedChannelException();
    }
    if(outstandingTasks > 0) {
        return 0;
    }
    if(anyAreSet(state, FLAG_WRITE_REQUIRES_READ)) {
        doUnwrap(null, 0, 0);
        if(allAreClear(state, FLAG_READ_REQUIRES_WRITE)) { //unless a wrap is immediatly required we just return
            return 0;
        }
    }
    if(wrappedData != null) {
        int res = sink.write(wrappedData.getBuffer());
        if(res == 0 || wrappedData.getBuffer().hasRemaining()) {
            return 0;
        }
        wrappedData.getBuffer().clear();
    } else {
        wrappedData = bufferPool.allocate();
    }
    try {
        SSLEngineResult result = null;
        while (result == null || (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP && result.getStatus() != SSLEngineResult.Status.BUFFER_OVERFLOW)) {
            if (userBuffers == null) {
                result = engine.wrap(EMPTY_BUFFER, wrappedData.getBuffer());
            } else {
                result = engine.wrap(userBuffers, off, len, wrappedData.getBuffer());
            }
        }
        wrappedData.getBuffer().flip();

        if (result.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
            throw new IOException("underflow"); //todo: can this happen?
        } else if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
            if (!wrappedData.getBuffer().hasRemaining()) { //if an earlier wrap suceeded we ignore this
                throw new IOException("overflow"); //todo: handle properly
            }
        }
        //attempt to write it out, if we fail we just return
        //we ignore the handshake status, as wrap will get called again
        if (wrappedData.getBuffer().hasRemaining()) {
            sink.write(wrappedData.getBuffer());
        }
        //if it was not a complete write we just return
        if (wrappedData.getBuffer().hasRemaining()) {
            return result.bytesConsumed();
        }

        if (!handleHandshakeResult(result)) {
            return 0;
        }
        if (result.getStatus() == SSLEngineResult.Status.CLOSED && userBuffers != null) {
            notifyWriteClosed();
            throw new ClosedChannelException();
        }

        return result.bytesConsumed();
    } catch (RuntimeException|IOException|Error e) {
        try {
            close();
        } catch (Throwable ex) {
            UndertowLogger.REQUEST_LOGGER.debug("Exception closing SSLConduit after exception in doWrap()", ex);
        }
        throw e;
    } finally {
        //this can be cleared if the channel is fully closed
        if(wrappedData != null) {
            if (!wrappedData.getBuffer().hasRemaining()) {
                wrappedData.close();
                wrappedData = null;
            }
        }
    }
}
 
Example 14
Source File: SslConnection.java    From IoTgo_Android_App with MIT License 4 votes vote down vote up
private synchronized boolean unwrap(final Buffer buffer) throws IOException
{
    if (!_inbound.hasContent())
        return false;

    ByteBuffer bbuf=extractByteBuffer(buffer);
    final SSLEngineResult result;

    synchronized(bbuf)
    {
        ByteBuffer in_buffer=_inbound.getByteBuffer();
        synchronized(in_buffer)
        {
            try
            {
                bbuf.position(buffer.putIndex());
                bbuf.limit(buffer.capacity());
                in_buffer.position(_inbound.getIndex());
                in_buffer.limit(_inbound.putIndex());

                result=_engine.unwrap(in_buffer,bbuf);
                if (_logger.isDebugEnabled())
                    _logger.debug("{} unwrap {} {} consumed={} produced={}",
                        _session,
                        result.getStatus(),
                        result.getHandshakeStatus(),
                        result.bytesConsumed(),
                        result.bytesProduced());

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

    switch(result.getStatus())
    {
        case BUFFER_UNDERFLOW:
            if (_endp.isInputShutdown())
                _inbound.clear();
            break;

        case BUFFER_OVERFLOW:
            if (_logger.isDebugEnabled()) _logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString());
            break;

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

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

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

    //if (LOG.isDebugEnabled() && result.bytesProduced()>0)
    //    LOG.debug("{} unwrapped '{}'",_session,buffer);

    return result.bytesConsumed()>0 || result.bytesProduced()>0;
}
 
Example 15
Source File: Worker.java    From sslfacade with MIT License 4 votes vote down vote up
SSLEngineResult unwrap(ByteBuffer encryptedData) throws SSLException
{
  ByteBuffer allEncryptedData = _buffers.prependCached(encryptedData);
  _buffers.prepareForUnwrap(allEncryptedData);
  SSLEngineResult result = doUnwrap();
  debug("unwrap: doUnwrap result: " + result);
  allEncryptedData.position(result.bytesConsumed());
  ByteBuffer unprocessedEncryptedData = BufferUtils.slice(allEncryptedData);

  emitPlainData(result);

  switch (result.getStatus()) {
    case BUFFER_UNDERFLOW:
      _buffers.cache(unprocessedEncryptedData);
      break;
    case BUFFER_OVERFLOW:
      _buffers.grow(BufferType.IN_PLAIN);
      if (unprocessedEncryptedData == null) {
        throw new RuntimeException("Worker.unwrap had "
                + "buffer_overflow but all data was consumed!!");
      } else {
        unwrap(unprocessedEncryptedData);
      }
      break;
    case OK:
      if (unprocessedEncryptedData == null) {
        _buffers.clearCache();
      } else {
        _buffers.cache(unprocessedEncryptedData);
      }
      break;
    case CLOSED:

      break;
  }
  if (_buffers.isCacheEmpty() == false 
          && result.getStatus() == SSLEngineResult.Status.OK
          && result.bytesConsumed() > 0) {
    debug("Still data in cahce");
    result = unwrap(ByteBuffer.allocate(0));
  }
  return result;
}
 
Example 16
Source File: SSLSocketChannel.java    From mts with GNU General Public License v3.0 4 votes vote down vote up
public synchronized int write(ByteBuffer src) throws IOException
{
    if (socketChannel.socket().isOutputShutdown())
    {
        throw new ClosedChannelException();
    }
    else if (initialized != 0)
    {
        handshake(SelectionKey.OP_WRITE);
        return 0;
    }
    else if (shutdown)
    {
        shutdown();
        return 0;
    }

    // Check how much to write.
    int t = src.remaining();
    int n = 0;

    // Write as much as we can.
    SSLEngineResult result;
    Status status;
    do
    {
        if (!prepare(outputBuffer, minBufferSize))
        {
            // Overflow!
            break;
        }

        inputBuffer[0].flip();
        try
        {
            result = sslEngine.wrap(src, outputBuffer[0]);
        }
        finally
        {
            outputBuffer[0].flip();
        }
        n += result.bytesConsumed();
        status = result.getStatus();
        if (status == Status.OK)
        {
            if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
            {
                runTasks();
            }
        }
        else
        {
            if (status == Status.CLOSED)
            {
                shutdown();
            }

            throw new IOException("Write error '" + result.getStatus() + '\'');
        }
    } while (n < t);

    // Try to flush what we got.
    flush();

    return n;
}
 
Example 17
Source File: Worker.java    From getty with Apache License 2.0 4 votes vote down vote up
SSLEngineResult unwrap(ByteBuffer encryptedData) throws SSLException
{
  ByteBuffer allEncryptedData = _buffers.prependCached(encryptedData);
  _buffers.prepareForUnwrap(allEncryptedData);
  SSLEngineResult result = doUnwrap();
  debug("unwrap: doUnwrap result: " + result);
  allEncryptedData.position(result.bytesConsumed());
  ByteBuffer unprocessedEncryptedData = BufferUtils.slice(allEncryptedData);

  emitPlainData(result);

  switch (result.getStatus()) {
    case BUFFER_UNDERFLOW:
      _buffers.cache(unprocessedEncryptedData);
      break;
    case BUFFER_OVERFLOW:
      _buffers.grow(BufferType.IN_PLAIN);
      if (unprocessedEncryptedData == null) {
        throw new RuntimeException("Worker.unwrap had "
                + "buffer_overflow but all data was consumed!!");
      } else {
        unwrap(unprocessedEncryptedData);
      }
      break;
    case OK:
      if (unprocessedEncryptedData == null) {
        _buffers.clearCache();
      } else {
        _buffers.cache(unprocessedEncryptedData);
      }
      break;
    case CLOSED:

      break;
  }
  if (_buffers.isCacheEmpty() == false 
          && result.getStatus() == SSLEngineResult.Status.OK
          && result.bytesConsumed() > 0) {
    debug("Still data in cahce");
    result = unwrap(ByteBuffer.allocate(0));
  }
  return result;
}
 
Example 18
Source File: XmppTcpTransportModule.java    From Smack with Apache License 2.0 4 votes vote down vote up
@Override
public OutputResult output(ByteBuffer outputData, boolean isFinalDataOfElement, boolean destinationAddressChanged,
        boolean moreDataAvailable) throws SSLException {
    if (outputData != null) {
        pendingOutputData.add(outputData);
        pendingOutputBytes += outputData.remaining();
        if (moreDataAvailable && pendingOutputBytes < MAX_PENDING_OUTPUT_BYTES) {
            return OutputResult.NO_OUTPUT;
        }
    }

    ByteBuffer[] outputDataArray = pendingOutputData.toArray(new ByteBuffer[pendingOutputData.size()]);

    myNetData.clear();

    while (true) {
        SSLEngineResult result;
        try {
            result = engine.wrap(outputDataArray, myNetData);
        } catch (SSLException e) {
            handleSslException(e);
            throw e;
        }

        debugLogSslEngineResult("wrap", result);

        SSLEngineResult.Status engineResultStatus = result.getStatus();

        pendingOutputBytes -= result.bytesConsumed();

        if (engineResultStatus == SSLEngineResult.Status.OK) {
            wrapInBytes += result.bytesConsumed();
            wrapOutBytes += result.bytesProduced();

            SSLEngineResult.HandshakeStatus handshakeStatus = handleHandshakeStatus(result);
            switch (handshakeStatus) {
                case NEED_UNWRAP:
                    // NEED_UNWRAP means that we need to receive something in order to continue the handshake. The
                    // standard channelSelectedCallback logic will take care of this, as there is eventually always
                    // a interest to read from the socket.
                    break;
                case NEED_WRAP:
                    // Same as need task: Cycle the reactor.
                case NEED_TASK:
                    // Note that we also set pendingOutputFilterData in the OutputResult in the NEED_TASK case, as
                    // we also want to retry the wrap() operation above in this case.
                    return new OutputResult(true, myNetData);
                default:
                    break;
            }
        }

        switch (engineResultStatus) {
        case OK:
            // No need to outputData.compact() here, since we do not reuse the buffer.
            // Clean up the pending output data.
            pruneBufferList(pendingOutputData);
            return new OutputResult(!pendingOutputData.isEmpty(), myNetData);
        case CLOSED:
            pendingOutputData.clear();
            return OutputResult.NO_OUTPUT;
        case BUFFER_OVERFLOW:
            LOGGER.warning("SSLEngine status BUFFER_OVERFLOW, this is hopefully uncommon");
            int outputDataRemaining = outputData != null ? outputData.remaining() : 0;
            int newCapacity = (int) (1.3 * outputDataRemaining);
            // If newCapacity would not increase myNetData, then double it.
            if (newCapacity <= myNetData.capacity()) {
                newCapacity = 2 * myNetData.capacity();
            }
            ByteBuffer newMyNetData = ByteBuffer.allocateDirect(newCapacity);
            myNetData.flip();
            newMyNetData.put(myNetData);
            myNetData = newMyNetData;
            continue;
        case BUFFER_UNDERFLOW:
            throw new IllegalStateException(
                    "Buffer underflow as result of SSLEngine.wrap() should never happen");
        }
    }
}
 
Example 19
Source File: OpenSslEngineTest.java    From netty-4.1.22 with Apache License 2.0 4 votes vote down vote up
@Test
public void testBufferUnderFlowAvoidedIfJDKCompatabilityModeOff() 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);
        plainClient.limit(plainClient.capacity());

        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());

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

        // We limit the buffer so we have less then the header to read, this should result in an BUFFER_UNDERFLOW.
        encClientToServer.limit(SslUtils.SSL_RECORD_HEADER_LENGTH - 1);
        result = server.unwrap(encClientToServer, plainServer);
        assertEquals(SSLEngineResult.Status.OK, result.getStatus());
        assertEquals(SslUtils.SSL_RECORD_HEADER_LENGTH - 1, result.bytesConsumed());
        assertEquals(0, result.bytesProduced());
        remaining -= result.bytesConsumed();

        // We limit the buffer so we can read the header but not the rest, this should result in an
        // BUFFER_UNDERFLOW.
        encClientToServer.limit(SslUtils.SSL_RECORD_HEADER_LENGTH);
        result = server.unwrap(encClientToServer, plainServer);
        assertEquals(SSLEngineResult.Status.OK, result.getStatus());
        assertEquals(1, result.bytesConsumed());
        assertEquals(0, result.bytesProduced());
        remaining -= result.bytesConsumed();

        // We limit the buffer so we can read the header and partly the rest, this should result in an
        // BUFFER_UNDERFLOW.
        encClientToServer.limit(
                SslUtils.SSL_RECORD_HEADER_LENGTH  + remaining - 1 - SslUtils.SSL_RECORD_HEADER_LENGTH);
        result = server.unwrap(encClientToServer, plainServer);
        assertEquals(SSLEngineResult.Status.OK, result.getStatus());
        assertEquals(encClientToServer.limit() - SslUtils.SSL_RECORD_HEADER_LENGTH, result.bytesConsumed());
        assertEquals(0, result.bytesProduced());
        remaining -= result.bytesConsumed();

        // Reset limit so we can read the full record.
        encClientToServer.limit(remaining);
        assertEquals(0, encClientToServer.remaining());
        result = server.unwrap(encClientToServer, plainServer);
        assertEquals(SSLEngineResult.Status.BUFFER_UNDERFLOW, result.getStatus());
        assertEquals(0, result.bytesConsumed());
        assertEquals(0, result.bytesProduced());

        encClientToServer.position(0);
        result = server.unwrap(encClientToServer, plainServer);
        assertEquals(SSLEngineResult.Status.OK, result.getStatus());
        assertEquals(remaining, result.bytesConsumed());
        assertEquals(0, result.bytesProduced());
    } finally {
        cert.delete();
        cleanupClientSslEngine(client);
        cleanupServerSslEngine(server);
    }
}
 
Example 20
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;
}