Make DTLSv1_listen a first class function and change its type

The DTLSv1_listen function exposed details of the underlying BIO
abstraction and did not properly allow for IPv6. This commit changes the
"peer" argument to be a BIO_ADDR and makes it a first class function
(rather than a ctrl) to ensure proper type checking.

Reviewed-by: Richard Levitte <levitte@openssl.org>
This commit is contained in:
Matt Caswell 2016-02-05 10:59:42 +00:00
parent 0dc225577c
commit 3edeb622ba
7 changed files with 39 additions and 43 deletions

View File

@ -4,6 +4,9 @@
Changes between 1.0.2f and 1.1.0 [xx XXX xxxx]
*) The arguments to the DTLSv1_listen function have changed. Specifically the
"peer" argument is now expected to be a BIO_ADDR object.
*) Rewrite of BIO networking library. The BIO library lacked consistent
support of IPv6, and adding it required some more extensive
modifications. This introduces the BIO_ADDR and BIO_ADDRINFO types,

View File

@ -2496,7 +2496,7 @@ static int init_ssl_connection(SSL *con)
BIO_printf(bio_err, "ERROR - memory\n");
return 0;
}
i = DTLSv1_listen(con, &client);
i = DTLSv1_listen(con, client);
if (i > 0) {
BIO *wbio;
int fd = -1;

View File

@ -8,7 +8,7 @@ DTLSv1_listen - listen for incoming DTLS connections.
#include <openssl/ssl.h>
int DTLSv1_listen(SSL *ssl, struct sockaddr *peer);
int DTLSv1_listen(SSL *ssl, BIO_ADDR *peer);
=head1 DESCRIPTION
@ -43,14 +43,10 @@ messages from any peer.
When a ClientHello is received that contains a cookie that has been verified,
then DTLSv1_listen() will return with the B<ssl> parameter updated into a state
where the handshake can be continued by a call to (for example) SSL_accept().
Additionally the B<struct sockaddr> location pointed to by B<peer> will be
filled in with details of the peer that sent the ClientHello. It is the calling
code's responsibility to ensure that the B<peer> location is sufficiently large
to accommodate the addressing scheme in use. For example this might be done by
allocating space for a struct sockaddr_storage and casting the pointer to it to
a struct sockaddr * for the call to DTLSv1_listen(). Typically user code is
expected to "connect" the underlying socket to the peer and continue the
handshake in a connected state.
Additionally the B<BIO_ADDR> pointed to by B<peer> will be filled in with
details of the peer that sent the ClientHello. Typically user code is expected
to "connect" the underlying socket to the peer and continue the handshake in a
connected state.
Prior to calling DTLSv1_listen() user code must ensure that cookie generation
and verification callbacks have been set up using
@ -89,6 +85,7 @@ L<ssl(3)>, L<bio(3)>
=head1 HISTORY
DTLSv1_listen() return codes were clarified in OpenSSL 1.1.0.
DTLSv1_listen() return codes were clarified in OpenSSL 1.1.0. The type of "peer"
also changed in OpenSSL 1.1.0.
=cut

View File

@ -1184,7 +1184,6 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# endif
# define DTLS_CTRL_GET_TIMEOUT 73
# define DTLS_CTRL_HANDLE_TIMEOUT 74
# define DTLS_CTRL_LISTEN 75
# define SSL_CTRL_GET_RI_SUPPORT 76
# define SSL_CTRL_CLEAR_MODE 78
# define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB 79
@ -1227,8 +1226,6 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
# define DTLSv1_handle_timeout(ssl) \
SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
# define DTLSv1_listen(ssl, peer) \
SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer)
# define SSL_session_reused(ssl) \
SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
# define SSL_num_renegotiations(ssl) \
@ -1842,6 +1839,8 @@ void SSL_trace(int write_p, int version, int content_type,
__owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c);
# endif
int DTLSv1_listen(SSL *s, BIO_ADDR *client);
/* What the "other" parameter contains in security callback */
/* Mask for type */
# define SSL_SECOP_OTHER_TYPE 0xffff0000
@ -1958,7 +1957,6 @@ void ERR_load_SSL_strings(void);
# define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT 253
# define SSL_F_DTLS1_HANDLE_TIMEOUT 297
# define SSL_F_DTLS1_HEARTBEAT 305
# define SSL_F_DTLS1_LISTEN 350
# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288
# define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256
# define SSL_F_DTLS1_PROCESS_RECORD 257
@ -1967,6 +1965,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST 260
# define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST 264
# define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268
# define SSL_F_DTLSV1_LISTEN 350
# define SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC 371
# define SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST 385
# define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE 370

View File

@ -75,7 +75,6 @@
static void get_current_time(struct timeval *t);
static int dtls1_set_handshake_header(SSL *s, int type, unsigned long len);
static int dtls1_handshake_write(SSL *s);
int dtls1_listen(SSL *s, BIO_ADDR *client);
static unsigned int dtls1_link_min_mtu(void);
/* XDTLS: figure out the right values */
@ -252,9 +251,6 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
case DTLS_CTRL_HANDLE_TIMEOUT:
ret = dtls1_handle_timeout(s);
break;
case DTLS_CTRL_LISTEN:
ret = dtls1_listen(s, parg);
break;
case DTLS_CTRL_SET_LINK_MTU:
if (larg < (long)dtls1_link_min_mtu())
return 0;
@ -484,7 +480,7 @@ static void get_current_time(struct timeval *t)
#define LISTEN_SEND_VERIFY_REQUEST 1
int dtls1_listen(SSL *s, BIO_ADDR *client)
int DTLSv1_listen(SSL *s, BIO_ADDR *client)
{
int next, n, ret = 0, clearpkt = 0;
unsigned char cookie[DTLS1_COOKIE_LENGTH];
@ -508,7 +504,7 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
wbio = SSL_get_wbio(s);
if(!rbio || !wbio) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_BIO_NOT_SET);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET);
return -1;
}
@ -527,19 +523,19 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
* SSL_accept)
*/
if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION);
return -1;
}
if (s->init_buf == NULL) {
if ((bufm = BUF_MEM_new()) == NULL) {
SSLerr(SSL_F_DTLS1_LISTEN, ERR_R_MALLOC_FAILURE);
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
return -1;
}
if (!BUF_MEM_grow(bufm, SSL3_RT_MAX_PLAIN_LENGTH)) {
BUF_MEM_free(bufm);
SSLerr(SSL_F_DTLS1_LISTEN, ERR_R_MALLOC_FAILURE);
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
return -1;
}
s->init_buf = bufm;
@ -572,7 +568,7 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
clearpkt = 1;
if (!PACKET_buf_init(&pkt, buf, n)) {
SSLerr(SSL_F_DTLS1_LISTEN, ERR_R_INTERNAL_ERROR);
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
return -1;
}
@ -587,7 +583,7 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
/* this packet contained a partial record, dump it */
if (n < DTLS1_RT_HEADER_LENGTH) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_RECORD_TOO_SMALL);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL);
goto end;
}
@ -598,12 +594,12 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
/* Get the record header */
if (!PACKET_get_1(&pkt, &rectype)
|| !PACKET_get_1(&pkt, &versmajor)) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_LENGTH_MISMATCH);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
if (rectype != SSL3_RT_HANDSHAKE) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
goto end;
}
@ -612,7 +608,7 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
* the same.
*/
if (versmajor != DTLS1_VERSION_MAJOR) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
goto end;
}
@ -621,13 +617,13 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
|| !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE)
|| !PACKET_get_length_prefixed_2(&pkt, &msgpkt)
|| PACKET_remaining(&pkt) != 0) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_LENGTH_MISMATCH);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
/* This is an initial ClientHello so the epoch has to be 0 */
if (seq[0] != 0 || seq[1] != 0) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
goto end;
}
@ -642,24 +638,24 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
|| !PACKET_get_net_3(&msgpkt, &fraglen)
|| !PACKET_get_sub_packet(&msgpkt, &msgpayload, msglen)
|| PACKET_remaining(&msgpkt) != 0) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_LENGTH_MISMATCH);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
if (msgtype != SSL3_MT_CLIENT_HELLO) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
goto end;
}
/* Message sequence number can only be 0 or 1 */
if(msgseq > 2) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER);
goto end;
}
/* We don't support a fragmented ClientHello whilst listening */
if (fragoff != 0 || fraglen != msglen) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO);
goto end;
}
@ -669,7 +665,7 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
s->msg_callback_arg);
if (!PACKET_get_net_2(&msgpayload, &clientvers)) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_LENGTH_MISMATCH);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
@ -678,14 +674,14 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
*/
if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) &&
s->method->version != DTLS_ANY_VERSION) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_WRONG_VERSION_NUMBER);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER);
goto end;
}
if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE)
|| !PACKET_get_length_prefixed_1(&msgpayload, &session)
|| !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_LENGTH_MISMATCH);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
@ -700,7 +696,7 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
* We have a cookie, so lets check it.
*/
if (s->ctx->app_verify_cookie_cb == NULL) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK);
/* This is fatal */
return -1;
}
@ -737,7 +733,7 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
if (s->ctx->app_gen_cookie_cb == NULL ||
s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 ||
cookielen > 255) {
SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
/* This is fatal */
return -1;
}
@ -808,7 +804,7 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
if ((tmpclient = BIO_ADDR_new()) == NULL
|| BIO_dgram_get_peer(rbio, tmpclient) <= 0
|| BIO_dgram_set_peer(wbio, tmpclient) <= 0) {
SSLerr(SSL_F_DTLS1_LISTEN, ERR_R_INTERNAL_ERROR);
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
goto end;
}
BIO_ADDR_free(tmpclient);
@ -859,7 +855,7 @@ int dtls1_listen(SSL *s, BIO_ADDR *client)
ossl_statem_set_hello_verify_done(s);
if(BIO_dgram_get_peer(rbio, client) <= 0) {
SSLerr(SSL_F_DTLS1_LISTEN, ERR_R_INTERNAL_ERROR);
SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
return -1;
}

View File

@ -84,7 +84,6 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT), "DTLS1_GET_MESSAGE_FRAGMENT"},
{ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT), "dtls1_handle_timeout"},
{ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "dtls1_heartbeat"},
{ERR_FUNC(SSL_F_DTLS1_LISTEN), "dtls1_listen"},
{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "dtls1_preprocess_fragment"},
{ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),
"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
@ -96,6 +95,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST),
"DTLS1_SEND_HELLO_VERIFY_REQUEST"},
{ERR_FUNC(SSL_F_DTLS1_WRITE_APP_DATA_BYTES), "dtls1_write_app_data_bytes"},
{ERR_FUNC(SSL_F_DTLSV1_LISTEN), "dtlsv1_listen"},
{ERR_FUNC(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC),
"dtls_construct_change_cipher_spec"},
{ERR_FUNC(SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST),

View File

@ -435,3 +435,4 @@ SSL_set_options 469 1_1_0 EXIST::FUNCTION:
SSL_get_options 470 1_1_0 EXIST::FUNCTION:
SSL_up_ref 471 1_1_0 EXIST::FUNCTION:
SSL_CTX_up_ref 472 1_1_0 EXIST::FUNCTION:
DTLSv1_listen 473 1_1_0 EXIST::FUNCTION: