public class SslHandler extends FrameDecoder implements ChannelDownstreamHandler
Channel
. Please refer
to the "SecureChat" example in the distribution or the web
site for the detailed usage.
You must make sure not to write a message while the
handshake is in progress unless you are
renegotiating. You will be notified by the ChannelFuture
which is
returned by the handshake()
method when the handshake
process succeeds or fails.
If isIssueHandshake()
is false
(default) you will need to take care of calling handshake()
by your own. In most
situations were SslHandler
is used in 'client mode' you want to issue a handshake once
the connection was established. if setIssueHandshake(boolean)
is set to true
you don't need to worry about this as the SslHandler
will take care of it.
If enableRenegotiation
is true
(default) and the initial handshake has been done successfully, you can call
handshake()
to trigger the renegotiation.
If enableRenegotiation
is false
,
an attempt to trigger renegotiation will result in the connection closure.
Please note that TLS renegotiation had a security issue before. If your
runtime environment did not fix it, please make sure to disable TLS
renegotiation by calling setEnableRenegotiation(boolean)
with
false
. For more information, please refer to the following documents:
To close the SSL session, the close()
method should be
called to send the close_notify
message to the remote peer. One
exception is when you close the Channel
- SslHandler
intercepts the close request and send the close_notify
message
before the channel closure automatically. Once the SSL session is closed,
it is not reusable, and consequently you should create a new
SslHandler
with a new SSLEngine
as explained in the
following section.
To restart the SSL session, you must remove the existing closed
SslHandler
from the ChannelPipeline
, insert a new
SslHandler
with a new SSLEngine
into the pipeline,
and start the handshake process as described in the first section.
StartTLS is the communication pattern that secures the wire in the middle of the plaintext connection. Please note that it is different from SSL · TLS, that secures the wire from the beginning of the connection. Typically, StartTLS is composed of three steps:
SslHandler
instance with startTls
flag set
to true
,SslHandler
to the ChannelPipeline
, andSslHandler
before sending
the StartTLS response. Otherwise the client can send begin SSL handshake
before SslHandler
is inserted to the ChannelPipeline
, causing
data corruption.
The client-side implementation is much simpler.
SslHandler
instance with startTls
flag set
to false
,SslHandler
to the ChannelPipeline
, andhandshake()
.Because of a known issue with the current implementation of the SslEngine that comes with Java it may be possible that you see blocked IO-Threads while a full GC is done.
So if you are affected you can workaround this problem by adjust the cache settings like shown below:
SslContext context = ...; context.getServerSessionContext().setSessionCacheSize(someSaneSize); context.getServerSessionContext().setSessionTime(someSameTimeout);
What values to use here depends on the nature of your application and should be set based on monitoring and debugging of it. For more details see #832 in our issue tracker.
ChannelHandler.Sharable
cumulation, DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS
Constructor and Description |
---|
SslHandler(SSLEngine engine)
Creates a new instance.
|
SslHandler(SSLEngine engine,
boolean startTls)
Creates a new instance.
|
SslHandler(SSLEngine engine,
SslBufferPool bufferPool)
Creates a new instance.
|
SslHandler(SSLEngine engine,
SslBufferPool bufferPool,
boolean startTls)
Creates a new instance.
|
SslHandler(SSLEngine engine,
SslBufferPool bufferPool,
boolean startTls,
Timer timer,
long handshakeTimeoutInMillis)
Creates a new instance.
|
Modifier and Type | Method and Description |
---|---|
void |
afterRemove(ChannelHandlerContext ctx)
Fail all pending writes which we were not able to flush out
|
void |
beforeAdd(ChannelHandlerContext ctx) |
void |
channelClosed(ChannelHandlerContext ctx,
ChannelStateEvent e)
Loop over all the pending writes and fail them.
|
void |
channelConnected(ChannelHandlerContext ctx,
ChannelStateEvent e)
Calls
handshake() once the Channel is connected |
void |
channelDisconnected(ChannelHandlerContext ctx,
ChannelStateEvent e)
Invoked when a
Channel was disconnected from its remote peer. |
ChannelFuture |
close()
Sends an SSL
close_notify message to the specified channel and
destroys the underlying SSLEngine . |
protected Object |
decode(ChannelHandlerContext ctx,
Channel channel,
ChannelBuffer in)
Decodes the received packets so far into a frame.
|
void |
exceptionCaught(ChannelHandlerContext ctx,
ExceptionEvent e)
Invoked when an exception was raised by an I/O thread or a
ChannelHandler . |
boolean |
getCloseOnSSLException() |
static SslBufferPool |
getDefaultBufferPool()
Returns the default
SslBufferPool used when no pool is
specified in the constructor. |
SSLEngine |
getEngine()
Returns the
SSLEngine which is used by this handler. |
long |
getHandshakeTimeout()
Return the timeout (in ms) after which the
ChannelFuture of handshake() will be failed, while
a handshake is in progress |
ChannelFuture |
getSSLEngineInboundCloseFuture()
Return the
ChannelFuture that will get notified if the inbound of the SSLEngine will get closed. |
void |
handleDownstream(ChannelHandlerContext context,
ChannelEvent evt)
Handles the specified downstream event.
|
ChannelFuture |
handshake()
Starts an SSL / TLS handshake for the specified channel.
|
boolean |
isEnableRenegotiation()
Returns
true if and only if TLS renegotiation is enabled. |
static boolean |
isEncrypted(ChannelBuffer buffer)
Returns
true if the given ChannelBuffer is encrypted. |
boolean |
isIssueHandshake()
Returns
true if the automatic handshake is enabled |
void |
setCloseOnSSLException(boolean closeOnSslException)
|
void |
setEnableRenegotiation(boolean enableRenegotiation)
Enables or disables TLS renegotiation.
|
void |
setIssueHandshake(boolean issueHandshake)
Enables or disables the automatic handshake once the
Channel is
connected. |
actualReadableBytes, afterAdd, appendToCumulation, beforeRemove, cleanup, decodeLast, extractFrame, getMaxCumulationBufferCapacity, getMaxCumulationBufferComponents, internalBuffer, isUnfold, messageReceived, newCumulationBuffer, replace, setMaxCumulationBufferCapacity, setMaxCumulationBufferComponents, setUnfold, unfoldAndFireMessageReceived, updateCumulation
channelBound, channelInterestChanged, channelOpen, channelUnbound, childChannelClosed, childChannelOpen, handleUpstream, writeComplete
public SslHandler(SSLEngine engine)
engine
- the SSLEngine
this handler will usepublic SslHandler(SSLEngine engine, SslBufferPool bufferPool)
engine
- the SSLEngine
this handler will usebufferPool
- the SslBufferPool
where this handler will
acquire the buffers required by the SSLEngine
public SslHandler(SSLEngine engine, boolean startTls)
public SslHandler(SSLEngine engine, SslBufferPool bufferPool, boolean startTls)
engine
- the SSLEngine
this handler will usebufferPool
- the SslBufferPool
where this handler will
acquire the buffers required by the SSLEngine
startTls
- true
if the first write request shouldn't be
encrypted by the SSLEngine
public SslHandler(SSLEngine engine, SslBufferPool bufferPool, boolean startTls, Timer timer, long handshakeTimeoutInMillis)
engine
- the SSLEngine
this handler will usebufferPool
- the SslBufferPool
where this handler will acquire
the buffers required by the SSLEngine
startTls
- true
if the first write request shouldn't be encrypted
by the SSLEngine
timer
- the Timer
which will be used to process the timeout of the handshake()
.
Be aware that the given Timer
will not get stopped automaticly, so it is up to you to cleanup
once you not need it anymorehandshakeTimeoutInMillis
- the time in milliseconds after whic the handshake()
will be failed, and so the future notifiedpublic static SslBufferPool getDefaultBufferPool()
SslBufferPool
used when no pool is
specified in the constructor.public ChannelFuture handshake()
ChannelFuture
which is notified when the handshake
succeeds or fails.public ChannelFuture close()
close_notify
message to the specified channel and
destroys the underlying SSLEngine
.public boolean isEnableRenegotiation()
true
if and only if TLS renegotiation is enabled.public void setEnableRenegotiation(boolean enableRenegotiation)
public void setIssueHandshake(boolean issueHandshake)
public boolean isIssueHandshake()
true
if the automatic handshake is enabledpublic ChannelFuture getSSLEngineInboundCloseFuture()
ChannelFuture
that will get notified if the inbound of the SSLEngine
will get closed.
This method will return the same ChannelFuture
all the time.
For more informations see the apidocs of SSLEngine
public long getHandshakeTimeout()
ChannelFuture
of handshake()
will be failed, while
a handshake is in progresspublic void setCloseOnSSLException(boolean closeOnSslException)
true
, the Channel
will automatically get closed
one a SSLException
was caught. This is most times what you want, as after this
its almost impossible to recover.
Anyway the default is false
to not break compatibility with older releases. This
will be changed to true
in the next major release.public boolean getCloseOnSSLException()
public void handleDownstream(ChannelHandlerContext context, ChannelEvent evt) throws Exception
ChannelDownstreamHandler
handleDownstream
in interface ChannelDownstreamHandler
context
- the context object for this handlerevt
- the downstream event to process or interceptException
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception
SimpleChannelUpstreamHandler
Channel
was disconnected from its remote peer.channelDisconnected
in class FrameDecoder
Exception
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception
SimpleChannelUpstreamHandler
ChannelHandler
.exceptionCaught
in class FrameDecoder
Exception
public static boolean isEncrypted(ChannelBuffer buffer)
true
if the given ChannelBuffer
is encrypted. Be aware that this method
will not increase the readerIndex of the given ChannelBuffer
.buffer
- The ChannelBuffer
to read from. Be aware that it must have at least 5 bytes to read,
otherwise it will throw an IllegalArgumentException
.true
if the ChannelBuffer
is encrypted, false
otherwise.IllegalArgumentException
- Is thrown if the given ChannelBuffer
has not at least 5 bytes to read.protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer in) throws Exception
FrameDecoder
FrameDecoder.extractFrame(ChannelBuffer, int, int)
method,
to make optimizations easier later.decode
in class FrameDecoder
ctx
- the context of this handlerchannel
- the current channelin
- the cumulative buffer of received packets so far.
Note that the buffer might be empty, which means you
should not make an assumption that the buffer contains
at least one byte in your decoder implementation.null
if there's not enough data in the buffer to decode a frame.Exception
public void beforeAdd(ChannelHandlerContext ctx) throws Exception
beforeAdd
in interface LifeCycleAwareChannelHandler
beforeAdd
in class FrameDecoder
Exception
public void afterRemove(ChannelHandlerContext ctx) throws Exception
afterRemove
in interface LifeCycleAwareChannelHandler
afterRemove
in class FrameDecoder
Exception
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception
handshake()
once the Channel
is connectedchannelConnected
in class SimpleChannelUpstreamHandler
Exception
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception
channelClosed
in class FrameDecoder
Exception
Copyright © 2008-2016 The Netty Project. All Rights Reserved.