Package tlschannel

Class ServerTlsChannel

java.lang.Object
tlschannel.ServerTlsChannel
All Implemented Interfaces:
java.io.Closeable, java.lang.AutoCloseable, java.nio.channels.ByteChannel, java.nio.channels.Channel, java.nio.channels.GatheringByteChannel, java.nio.channels.ReadableByteChannel, java.nio.channels.ScatteringByteChannel, java.nio.channels.WritableByteChannel, TlsChannel

public class ServerTlsChannel
extends java.lang.Object
implements TlsChannel
A server-side TlsChannel.
  • Nested Class Summary

    Nested Classes 
    Modifier and Type Class Description
    static class  ServerTlsChannel.Builder
    Builder of ServerTlsChannel
  • Field Summary

    Fields inherited from interface tlschannel.TlsChannel

    defaultEncryptedBufferAllocator, defaultPlainBufferAllocator
  • Method Summary

    Modifier and Type Method Description
    void close()
    Closes the underlying channel.
    TrackingAllocator getEncryptedBufferAllocator()
    Return the BufferAllocator to use for encrypted data.
    TrackingAllocator getPlainBufferAllocator()
    Return the BufferAllocator to use for unencrypted data.
    boolean getRunTasks()
    Return whether CPU-intensive tasks are run or not.
    java.util.function.Consumer<javax.net.ssl.SSLSession> getSessionInitCallback()
    Return the callback function to be executed when the TLS session is established (or re-established).
    javax.net.ssl.SSLContext getSslContext()
    Return the used SSLContext.
    javax.net.ssl.SSLEngine getSslEngine()
    Return a reference to the SSLEngine used.
    java.nio.channels.ByteChannel getUnderlying()
    Return a reference to the underlying ByteChannel.
    void handshake()
    Forces the initial TLS handshake.
    boolean isOpen()  
    static ServerTlsChannel.Builder newBuilder​(java.nio.channels.ByteChannel underlying, javax.net.ssl.SSLContext sslContext)
    Create a new ServerTlsChannel.Builder, configured with a underlying Channel and a fixed SSLContext, which will be used to create the SSLEngine.
    static ServerTlsChannel.Builder newBuilder​(java.nio.channels.ByteChannel underlying, SniSslContextFactory sslContextFactory)
    Create a new ServerTlsChannel.Builder, configured with a underlying Channel and a custom SSLContext factory, which will be used to create the context (in turn used to create the SSLEngine, as a function of the SNI received at the TLS connection start.
    int read​(java.nio.ByteBuffer dstBuffer)
    Reads a sequence of bytesProduced from this channel into the given buffer.
    long read​(java.nio.ByteBuffer[] dstBuffers)
    Reads a sequence of bytesProduced from this channel into the given buffers.
    long read​(java.nio.ByteBuffer[] dstBuffers, int offset, int length)
    Reads a sequence of bytesProduced from this channel into a subsequence of the given buffers.
    void renegotiate()
    Initiates a handshake (initial or renegotiation) on this channel.
    boolean shutdown()
    Shuts down the TLS connection.
    boolean shutdownReceived()
    Return whether this side of the connection has already received the close notification.
    boolean shutdownSent()
    Return whether this side of the connection has already sent the close notification.
    int write​(java.nio.ByteBuffer srcBuffer)
    Writes a sequence of bytesProduced to this channel from the given buffer.
    long write​(java.nio.ByteBuffer[] srcs)
    Writes a sequence of bytesProduced to this channel from the given buffers.
    long write​(java.nio.ByteBuffer[] srcs, int offset, int length)
    Writes a sequence of bytesProduced to this channel from a subsequence of the given buffers.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • newBuilder

      public static ServerTlsChannel.Builder newBuilder​(java.nio.channels.ByteChannel underlying, javax.net.ssl.SSLContext sslContext)
      Create a new ServerTlsChannel.Builder, configured with a underlying Channel and a fixed SSLContext, which will be used to create the SSLEngine.
      Parameters:
      underlying - a reference to the underlying ByteChannel
      sslContext - a fixed SSLContext to be used
      Returns:
      the new builder
    • newBuilder

      public static ServerTlsChannel.Builder newBuilder​(java.nio.channels.ByteChannel underlying, SniSslContextFactory sslContextFactory)
      Create a new ServerTlsChannel.Builder, configured with a underlying Channel and a custom SSLContext factory, which will be used to create the context (in turn used to create the SSLEngine, as a function of the SNI received at the TLS connection start.

      Implementation note:
      Due to limitations of SSLEngine, configuring a ServerTlsChannel to select the SSLContext based on the SNI value implies parsing the first TLS frame (ClientHello) independently of the SSLEngine.

      Parameters:
      underlying - a reference to the underlying ByteChannel
      sslContextFactory - a function from an optional SNI to the SSLContext to be used
      Returns:
      the new builder
      See Also:
      Server Name Indication
    • getUnderlying

      public java.nio.channels.ByteChannel getUnderlying()
      Description copied from interface: TlsChannel
      Return a reference to the underlying ByteChannel.
      Specified by:
      getUnderlying in interface TlsChannel
      Returns:
      the underlying channel
    • getSslContext

      public javax.net.ssl.SSLContext getSslContext()
      Return the used SSLContext.
      Returns:
      if context if present, of null if the TLS connection as not been initializer, or the SNI not received yet.
    • getSslEngine

      public javax.net.ssl.SSLEngine getSslEngine()
      Description copied from interface: TlsChannel
      Return a reference to the SSLEngine used.
      Specified by:
      getSslEngine in interface TlsChannel
      Returns:
      the engine reference if present, or null if unknown (that can happen in server-side channels before the SNI is parsed).
    • getSessionInitCallback

      public java.util.function.Consumer<javax.net.ssl.SSLSession> getSessionInitCallback()
      Description copied from interface: TlsChannel
      Return the callback function to be executed when the TLS session is established (or re-established).
      Specified by:
      getSessionInitCallback in interface TlsChannel
      Returns:
      the callback function
      See Also:
      TlsChannelBuilder.withSessionInitCallback(Consumer)
    • getRunTasks

      public boolean getRunTasks()
      Description copied from interface: TlsChannel
      Return whether CPU-intensive tasks are run or not.
      Specified by:
      getRunTasks in interface TlsChannel
      Returns:
      whether tasks are run
      See Also:
      TlsChannelBuilder.withRunTasks(boolean)
    • getPlainBufferAllocator

      public TrackingAllocator getPlainBufferAllocator()
      Description copied from interface: TlsChannel
      Return the BufferAllocator to use for unencrypted data. Actually, a decorating subclass is returned, which contains allocation statistics for this channel.
      Specified by:
      getPlainBufferAllocator in interface TlsChannel
      Returns:
      the buffer allocator
      See Also:
      TlsChannelBuilder.withPlainBufferAllocator(BufferAllocator), TrackingAllocator
    • getEncryptedBufferAllocator

      public TrackingAllocator getEncryptedBufferAllocator()
      Description copied from interface: TlsChannel
      Return the BufferAllocator to use for encrypted data. Actually, a decorating subclass is returned, which contains allocation statistics for this channel.
      Specified by:
      getEncryptedBufferAllocator in interface TlsChannel
      Returns:
      the buffer allocator
      See Also:
      TlsChannelBuilder.withEncryptedBufferAllocator(BufferAllocator), TrackingAllocator
    • read

      public long read​(java.nio.ByteBuffer[] dstBuffers, int offset, int length) throws java.io.IOException
      Description copied from interface: TlsChannel
      Reads a sequence of bytesProduced from this channel into a subsequence of the given buffers.

      See ScatteringByteChannel.read(ByteBuffer[], int, int) for more details of the meaning of this signature.

      This method behaves slightly different than the interface specification, with respect to non-blocking responses, see TlsChannel.read(ByteBuffer) for more details.

      Specified by:
      read in interface java.nio.channels.ScatteringByteChannel
      Specified by:
      read in interface TlsChannel
      Parameters:
      dstBuffers - The buffers into which bytesProduced are to be transferred
      offset - The offset within the buffer array of the first buffer into which bytesProduced are to be transferred; must be non-negative and no larger than dsts.length
      length - The maximum number of buffers to be accessed; must be non-negative and no larger than dsts.length  - offset
      Returns:
      The number of bytesProduced read, or -1 if the channel has reached end-of-stream; contrary to the behavior specified in ByteChannel, this method never returns 0, but throws WouldBlockException
      Throws:
      WouldBlockException - if the channel is in non-blocking mode and the IO operation cannot be completed immediately
      NeedsTaskException - if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operation
      javax.net.ssl.SSLException - if the SSLEngine throws a SSLException
      java.io.IOException - if the underlying channel throws an IOException
    • read

      public long read​(java.nio.ByteBuffer[] dstBuffers) throws java.io.IOException
      Description copied from interface: TlsChannel
      Reads a sequence of bytesProduced from this channel into the given buffers.

      An invocation of this method of the form c.read(dsts) behaves in exactly the same manner as the invocation

       c.read(dsts, 0, dsts.length);
       

      This method behaves slightly different than the interface specification, with respect to non-blocking responses, see TlsChannel.read(ByteBuffer) for more details.

      Specified by:
      read in interface java.nio.channels.ScatteringByteChannel
      Specified by:
      read in interface TlsChannel
      Parameters:
      dstBuffers - The buffers into which bytesProduced are to be transferred
      Returns:
      The number of bytesProduced read, or -1 if the channel has reached end-of-stream; contrary to the behavior specified in ByteChannel, this method never returns 0, but throws WouldBlockException
      Throws:
      WouldBlockException - if the channel is in non-blocking mode and the IO operation cannot be completed immediately
      NeedsTaskException - if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operation
      javax.net.ssl.SSLException - if the SSLEngine throws a SSLException
      java.io.IOException - if the underlying channel throws an IOException
    • read

      public int read​(java.nio.ByteBuffer dstBuffer) throws java.io.IOException
      Description copied from interface: TlsChannel
      Reads a sequence of bytesProduced from this channel into the given buffer.

      An attempt is made to read up to r bytesProduced from the channel, where r is the number of bytesProduced remaining in the buffer, that is, dst.remaining(), at the moment this method is invoked.

      Suppose that a byte sequence of length n is read, where 0   <= n <= r. This byte sequence will be transferred into the buffer so that the first byte in the sequence is at index p and the last byte is at index p + n -  1, where p is the buffer's position at the moment this method is invoked. Upon return the buffer's position will be equal to p  + n; its limit will not have changed.

      A read operation might not fill the buffer, and in fact it might not read any bytesProduced at all. Whether or not it does so depends upon the nature and state of the underlying channel. It is guaranteed, however, that if a channel is in blocking mode and there is at least one byte remaining in the buffer then this method will block until at least one byte is read. On the other hand, if the underlying channel is in non-blocking mode then a WouldBlockException may be thrown. Note that this also includes the possibility of a NeedsWriteException, due to the fact that, during a TLS handshake, bytesProduced need to be written to the underlying channel. In any case, after a WouldBlockException, the operation should be retried when the underlying channel is ready (for reading or writing, depending on the subclass).

      If the channel is configured to not run tasks and one is due to run, a NeedsTaskException will be thrown. In this case the operation should be retried after the task is run.

      This method may be invoked at any time. If another thread has already initiated a read or handshaking operation upon this channel, however, then an invocation of this method will block until the first operation is complete.

      Specified by:
      read in interface java.nio.channels.ReadableByteChannel
      Specified by:
      read in interface TlsChannel
      Parameters:
      dstBuffer - The buffer into which bytesProduced are to be transferred
      Returns:
      The number of bytesProduced read, or -1 if the channel has reached end-of-stream; contrary to the behavior specified in ByteChannel, this method never returns 0, but throws WouldBlockException
      Throws:
      WouldBlockException - if the channel is in non-blocking mode and the IO operation cannot be completed immediately
      NeedsTaskException - if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operation
      javax.net.ssl.SSLException - if the SSLEngine throws a SSLException
      java.io.IOException - if the underlying channel throws an IOException
    • write

      public long write​(java.nio.ByteBuffer[] srcs, int offset, int length) throws java.io.IOException
      Description copied from interface: TlsChannel
      Writes a sequence of bytesProduced to this channel from a subsequence of the given buffers.

      See GatheringByteChannel.write(ByteBuffer[], int, int) for more details of the meaning of this signature.

      This method behaves slightly different than the interface specification, with respect to non-blocking responses, see TlsChannel.write(ByteBuffer) for more details.

      Specified by:
      write in interface java.nio.channels.GatheringByteChannel
      Specified by:
      write in interface TlsChannel
      Parameters:
      srcs - The buffers from which bytesProduced are to be retrieved
      offset - The offset within the buffer array of the first buffer from which bytesProduced are to be retrieved; must be non-negative and no larger than srcs.length
      length - The maximum number of buffers to be accessed; must be non-negative and no larger than srcs.length  - offset
      Returns:
      The number of bytesProduced written, contrary to the behavior specified in ByteChannel, this method never returns 0, but throws WouldBlockException
      Throws:
      WouldBlockException - if the channel is in non-blocking mode and the IO operation cannot be completed immediately
      NeedsTaskException - if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operation
      javax.net.ssl.SSLException - if the SSLEngine throws a SSLException
      java.io.IOException - if the underlying channel throws an IOException
    • write

      public long write​(java.nio.ByteBuffer[] srcs) throws java.io.IOException
      Description copied from interface: TlsChannel
      Writes a sequence of bytesProduced to this channel from the given buffers.

      An invocation of this method of the form c.write(srcs) behaves in exactly the same manner as the invocation

       c.write(srcs, 0, srcs.length);
       
      This method behaves slightly different than the interface specification, with respect to non-blocking responses, see TlsChannel.write(ByteBuffer) for more details.
      Specified by:
      write in interface java.nio.channels.GatheringByteChannel
      Specified by:
      write in interface TlsChannel
      Parameters:
      srcs - The buffers from which bytesProduced are to be retrieved
      Returns:
      The number of bytesProduced written, contrary to the behavior specified in ByteChannel, this method never returns 0, but throws WouldBlockException
      Throws:
      WouldBlockException - if the channel is in non-blocking mode and the IO operation cannot be completed immediately
      NeedsTaskException - if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operation
      javax.net.ssl.SSLException - if the SSLEngine throws a SSLException
      java.io.IOException - if the underlying channel throws an IOExceptions
    • write

      public int write​(java.nio.ByteBuffer srcBuffer) throws java.io.IOException
      Description copied from interface: TlsChannel
      Writes a sequence of bytesProduced to this channel from the given buffer.

      An attempt is made to write up to r bytesProduced to the channel, where r is the number of bytesProduced remaining in the buffer, that is, src.remaining(), at the moment this method is invoked.

      Suppose that a byte sequence of length n is written, where 0  <= n <=  r. This byte sequence will be transferred from the buffer starting at index p, where p is the buffer's position at the moment this method is invoked; the index of the last byte written will be p  + n - 1. Upon return the buffer's position will be equal to p  + n; its limit will not have changed.

      If the underlying channel is in blocking mode, a write operation will return only after writing all of the r requested bytesProduced. On the other hand, if it is in non-blocking mode, this operation may write only some of the bytesProduced or possibly none at all, in this case a WouldBlockException will be thrown. Note that this also includes the possibility of a NeedsReadException, due to the fact that, during a TLS handshake, bytes need to be read from the underlying channel. In any case, after a WouldBlockException, the operation should be retried when the underlying channel is ready (for reading or writing, depending on the subclass).

      If the channel is configured to not run tasks and one is due to run, a NeedsTaskException will be thrown. In this case the operation should be retried after the task is run.

      This method may be invoked at any time. If another thread has already initiated a write or handshaking operation upon this channel, however, then an invocation of this method will block until the first operation is complete.

      Specified by:
      write in interface TlsChannel
      Specified by:
      write in interface java.nio.channels.WritableByteChannel
      Parameters:
      srcBuffer - The buffer from which bytesProduced are to be retrieved
      Returns:
      The number of bytesProduced written, contrary to the behavior specified in ByteChannel, this method never returns 0, but throws WouldBlockException
      Throws:
      WouldBlockException - if the channel is in non-blocking mode and the IO operation cannot be completed immediately
      NeedsTaskException - if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operation
      javax.net.ssl.SSLException - if the SSLEngine throws a SSLException
      java.io.IOException - if the underlying channel throws an IOException
    • renegotiate

      public void renegotiate() throws java.io.IOException
      Description copied from interface: TlsChannel
      Initiates a handshake (initial or renegotiation) on this channel. This method is not needed for the initial handshake, as the read() and write() methods will implicitly do the initial handshake if needed.

      This method may block if the underlying channel if in blocking mode.

      Note that renegotiation is a problematic feature of the TLS protocol, that should only be initiated at quiet point of the protocol.

      This method may block if the underlying channel is in blocking mode, otherwise a WouldBlockException can be thrown. In this case the operation should be retried when the underlying channel is ready (for reading or writing, depending on the subclass).

      If the channel is configured to not run tasks and one is due to run, a NeedsTaskException will be thrown, with a reference to the task. In this case the operation should be retried after the task is run.

      This method may be invoked at any time. If another thread has already initiated a read, write, or handshaking operation upon this channel, however, then an invocation of this method will block until the first operation is complete.

      Specified by:
      renegotiate in interface TlsChannel
      Throws:
      WouldBlockException - if the channel is in non-blocking mode and the IO operation cannot be completed immediately
      NeedsTaskException - if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operation
      javax.net.ssl.SSLException - if the SSLEngine throws a SSLException
      java.io.IOException - if the underlying channel throws an IOException
    • handshake

      public void handshake() throws java.io.IOException
      Description copied from interface: TlsChannel
      Forces the initial TLS handshake. Calling this method is usually not needed, as a handshake will happen automatically when doing the first read() or write() operation. Calling this method after the initial handshake has been done has no effect.

      This method may block if the underlying channel is in blocking mode, otherwise a WouldBlockException can be thrown. In this case the operation should be retried when the underlying channel is ready (for reading or writing, depending on the subclass).

      If the channel is configured to not run tasks and one is due to run, a NeedsTaskException will be thrown, with a reference to the task. In this case the operation should be retried after the task is run.

      This method may be invoked at any time. If another thread has already initiated a read, write, or handshaking operation upon this channel, however, then an invocation of this method will block until the first operation is complete.

      Specified by:
      handshake in interface TlsChannel
      Throws:
      WouldBlockException - if the channel is in non-blocking mode and the IO operation cannot be completed immediately
      NeedsTaskException - if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operation
      javax.net.ssl.SSLException - if the SSLEngine throws a SSLException
      java.io.IOException - if the underlying channel throws an IOException
    • close

      public void close() throws java.io.IOException
      Description copied from interface: TlsChannel
      Closes the underlying channel. This method first does some form of TLS close if not already done. The exact behavior can be configured using the TlsChannelBuilder.withWaitForCloseConfirmation(boolean).

      The default behavior mimics what happens in a normal (that is, non layered) Socket.close().

      For finer control of the TLS close, use TlsChannel.shutdown()

      Specified by:
      close in interface java.lang.AutoCloseable
      Specified by:
      close in interface java.nio.channels.Channel
      Specified by:
      close in interface java.io.Closeable
      Specified by:
      close in interface TlsChannel
      Throws:
      java.io.IOException - if the underlying channel throws an IOException during close. Exceptions thrown during any previous TLS close are not propagated.
    • isOpen

      public boolean isOpen()
      Specified by:
      isOpen in interface java.nio.channels.Channel
    • shutdown

      public boolean shutdown() throws java.io.IOException
      Description copied from interface: TlsChannel
      Shuts down the TLS connection. This method emulates the behavior of OpenSSL's SSL_shutdown().

      The shutdown procedure consists of two steps: the sending of the "close notify" shutdown alert and the reception of the peer's "close notify". According to the TLS standard, it is acceptable for an application to only send its shutdown alert and then close the underlying connection without waiting for the peer's response. When the underlying connection shall be used for more communications, the complete shutdown procedure (bidirectional "close notify" alerts) must be performed, so that the peers stay synchronized.

      This class supports both uni- and bidirectional shutdown by its 2 step behavior, using this method.

      When this is the first party to send the "close notify" alert, this method will only send the alert, set the TlsChannel.shutdownSent() flag and return false. If a unidirectional shutdown is enough, this first call is sufficient. In order to complete the bidirectional shutdown handshake, This method must be called again. The second call will wait for the peer's "close notify" shutdown alert. On success, the second call will return true.

      If the peer already sent the "close notify" alert and it was already processed implicitly inside a read operation, the TlsChannel.shutdownReceived() flag is already set. This method will then send the "close notify" alert, set the TlsChannel.shutdownSent() flag and immediately return true. It is therefore recommended to check the return value of this method and call it again, if the bidirectional shutdown is not yet complete.

      If the underlying channel is blocking, this method will only return once the handshake step has been finished or an error occurred.

      If the underlying channel is non-blocking, this method may throw WouldBlockException if the underlying channel could not support the continuation of the handshake. The calling process then must repeat the call after taking appropriate action (like waiting in a selector in case of a SocketChannel).

      Note that despite not being mandated by the specification, a proper TLS close is important to prevent truncation attacks, which consists, essentially, of an adversary introducing TCP FIN segments to trick on party to ignore the final bytes of a secure stream. For more details, see the original paper.

      Specified by:
      shutdown in interface TlsChannel
      Returns:
      whether the closing is finished.
      Throws:
      java.io.IOException - if the underlying channel throws an IOException
      WouldBlockException - if the channel is in non-blocking mode and the IO operation cannot be completed immediately
      See Also:
      TlsChannelBuilder.withWaitForCloseConfirmation(boolean)
    • shutdownReceived

      public boolean shutdownReceived()
      Description copied from interface: TlsChannel
      Return whether this side of the connection has already received the close notification.
      Specified by:
      shutdownReceived in interface TlsChannel
      Returns:
      true if the close notification was received
      See Also:
      TlsChannel.shutdown()
    • shutdownSent

      public boolean shutdownSent()
      Description copied from interface: TlsChannel
      Return whether this side of the connection has already sent the close notification.
      Specified by:
      shutdownSent in interface TlsChannel
      Returns:
      true if the close notification was sent
      See Also:
      TlsChannel.shutdown()