DTLSv1_listen rewrite
authorMatt Caswell <matt@openssl.org>
Mon, 14 Sep 2015 21:49:35 +0000 (22:49 +0100)
committerMatt Caswell <matt@openssl.org>
Wed, 23 Sep 2015 12:53:26 +0000 (13:53 +0100)
commite3d0dae7cf8363ca462ac425b72c7bb31c3b4b7a
tree5324d0001be54ed135b4ff8d60fd0a4ea6ccf1ef
parent01b7851aa27aa144372f5484da916be042d9aa4f
DTLSv1_listen rewrite

The existing implementation of DTLSv1_listen() is fundamentally flawed. This
function is used in DTLS solutions to listen for new incoming connections
from DTLS clients. A client will send an initial ClientHello. The server
will respond with a HelloVerifyRequest containing a unique cookie. The
client the responds with a second ClientHello - which this time contains the
cookie.

Once the cookie has been verified then DTLSv1_listen() returns to user code,
which is typically expected to continue the handshake with a call to (for
example) SSL_accept().

Whilst listening for incoming ClientHellos, the underlying BIO is usually in
an unconnected state. Therefore ClientHellos can come in from *any* peer.
The arrival of the first ClientHello without the cookie, and the second one
with it, could be interspersed with other intervening messages from
different clients.

The whole purpose of this mechanism is as a defence against DoS attacks. The
idea is to avoid allocating state on the server until the client has
verified that it is capable of receiving messages at the address it claims
to come from. However the existing DTLSv1_listen() implementation completely
fails to do this. It attempts to super-impose itself on the standard state
machine and reuses all of this code. However the standard state machine
expects to operate in a stateful manner with a single client, and this can
cause various problems.

A second more minor issue is that the return codes from this function are
quite confused, with no distinction made between fatal and non-fatal errors.
Most user code treats all errors as non-fatal, and simply retries the call
to DTLSv1_listen().

This commit completely rewrites the implementation of DTLSv1_listen() and
provides a stand alone implementation that does not rely on the existing
state machine. It also provides more consistent return codes.

Reviewed-by: Andy Polyakov <appro@openssl.org>
include/openssl/ssl.h
ssl/d1_both.c
ssl/d1_lib.c
ssl/d1_srvr.c
ssl/record/rec_layer_d1.c
ssl/record/record.h
ssl/ssl_err.c
ssl/ssl_locl.h