Check for alerts while waiting for a dry event
authorMatt Caswell <matt@openssl.org>
Tue, 16 Jan 2018 10:48:01 +0000 (10:48 +0000)
committerMatt Caswell <matt@openssl.org>
Wed, 21 Mar 2018 10:32:15 +0000 (10:32 +0000)
At a couple of points in a DTLS/SCTP handshake we need to wait for a dry
event before continuing. However if an alert has been sent by the peer
then we will never receive that dry event and an infinite loop results.

This commit changes things so that we attempt to read a message if we
are waiting for a dry event but haven't got one yet. This should never
succeed, but any alerts will be processed.

Fixes #4763

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5085)

include/openssl/ssl.h
ssl/ssl_err.c
ssl/statem/statem_dtls.c

index abe4406126463bdc874abf8ee5fa719b06cb6748..d99008d7d9f25d0cb7d272a7d3990f7841386a64 100644 (file)
@@ -2110,6 +2110,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST        385
 # define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE               370
 # define SSL_F_DTLS_PROCESS_HELLO_VERIFY                  386
+# define SSL_F_DTLS_WAIT_FOR_DRY                          592
 # define SSL_F_OPENSSL_INIT_SSL                           342
 # define SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION         417
 # define SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION         418
index 3c2ebe1d180fab85c9f1e0e4e882f1ee3b3c1f56..580861eaed8fd0297334711475200c18eee41e29 100644 (file)
@@ -48,6 +48,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE),
      "dtls_get_reassembled_message"},
     {ERR_FUNC(SSL_F_DTLS_PROCESS_HELLO_VERIFY), "dtls_process_hello_verify"},
+    {ERR_FUNC(SSL_F_DTLS_WAIT_FOR_DRY), "dtls_wait_for_dry"},
     {ERR_FUNC(SSL_F_OPENSSL_INIT_SSL), "OPENSSL_init_ssl"},
     {ERR_FUNC(SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION),
      "ossl_statem_client_read_transition"},
index 22be8711f33a238ddd2c7d8c7dfe6350d6a0691c..ebc95d317b6fc587de8e633dc7122c8afcaa65d6 100644 (file)
@@ -910,9 +910,14 @@ int dtls_construct_change_cipher_spec(SSL *s)
 }
 
 #ifndef OPENSSL_NO_SCTP
+/*
+ * Wait for a dry event. Should only be called at a point in the handshake
+ * where we are not expecting any data from the peer (except possibly an alert).
+ */
 WORK_STATE dtls_wait_for_dry(SSL *s)
 {
     int ret;
+    long len;
 
     /* read app data until dry event */
     ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
@@ -920,6 +925,20 @@ WORK_STATE dtls_wait_for_dry(SSL *s)
         return WORK_ERROR;
 
     if (ret == 0) {
+        /*
+         * We're not expecting any more messages from the peer at this point -
+         * but we could get an alert. If an alert is waiting then we will never
+         * return successfully. Therefore we attempt to read a message. This
+         * should never succeed but will process any waiting alerts.
+         */
+        if (dtls_get_reassembled_message(s, &len)) {
+            /* The call succeeded! This should never happen */
+            SSLerr(SSL_F_DTLS_WAIT_FOR_DRY, SSL_R_UNEXPECTED_MESSAGE);
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+            ossl_statem_set_error(s);
+            return WORK_ERROR;
+        }
+
         s->s3->in_read_app_data = 2;
         s->rwstate = SSL_READING;
         BIO_clear_retry_flags(SSL_get_rbio(s));