PR: 1829
authorDr. Stephen Henson <steve@openssl.org>
Tue, 14 Apr 2009 14:33:12 +0000 (14:33 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 14 Apr 2009 14:33:12 +0000 (14:33 +0000)
Submitted by: Robin Seggelmann <seggelmann@fh-muenster.de>
Approved by: steve@openssl.org

DTLS Timer Bug fix.

crypto/bio/bio.h
crypto/bio/bss_dgram.c
ssl/d1_clnt.c
ssl/d1_srvr.c

index ea5323d20fe91997604eaaebe38f3e0bdc84dd21..3371342fc1956e447258a493b506e7e766bcf44c 100644 (file)
@@ -159,6 +159,7 @@ extern "C" {
 
 #define BIO_CTRL_DGRAM_SET_PEER           44 /* Destination for the data */
 
 
 #define BIO_CTRL_DGRAM_SET_PEER           44 /* Destination for the data */
 
+#define BIO_CTRL_DGRAM_SET_TIMEOUT        45
 
 /* modifiers */
 #define BIO_FP_READ            0x02
 
 /* modifiers */
 #define BIO_FP_READ            0x02
index c3da6dc82fa9e9750249b81b97f609ff8a39f04c..2717d77956f8fe17c5fea5afbf005124f4f1944f 100644 (file)
@@ -104,6 +104,8 @@ typedef struct bio_dgram_data_st
        unsigned int connected;
        unsigned int _errno;
        unsigned int mtu;
        unsigned int connected;
        unsigned int _errno;
        unsigned int mtu;
+       struct timeval hstimeoutdiff;
+       struct timeval hstimeout;
        } bio_dgram_data;
 
 BIO_METHOD *BIO_s_datagram(void)
        } bio_dgram_data;
 
 BIO_METHOD *BIO_s_datagram(void)
@@ -196,6 +198,29 @@ static int dgram_read(BIO *b, char *out, int outl)
                                BIO_set_retry_read(b);
                                data->_errno = get_last_socket_error();
                                }
                                BIO_set_retry_read(b);
                                data->_errno = get_last_socket_error();
                                }
+                       memset(&(data->hstimeout), 0, sizeof(struct timeval));
+                       }
+               else
+                       {
+                       if (data->hstimeout.tv_sec > 0 || data->hstimeout.tv_usec > 0)
+                               {
+#ifdef OPENSSL_SYS_WIN32
+                               struct timeb tb;
+                               ftime(&tb);
+                               curtime.tv_sec = tb.time;
+                               curtime.tv_usec = tb.millitm * 1000;
+#else
+                               gettimeofday(&curtime, NULL);
+#endif
+
+                               if (curtime.tv_sec >= data->hstimeout.tv_sec &&
+                                       curtime.tv_usec >= data->hstimeout.tv_usec)
+                                       {
+                                       data->_errno = EAGAIN;
+                                       ret = -1;
+                                       memset(&(data->hstimeout), 0, sizeof(struct timeval));
+                                       }
+                               }
                        }
                }
        return(ret);
                        }
                }
        return(ret);
@@ -345,6 +370,30 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
 
         memcpy(&(data->peer), to, sizeof(struct sockaddr));
         break;
 
         memcpy(&(data->peer), to, sizeof(struct sockaddr));
         break;
+       case BIO_CTRL_DGRAM_SET_TIMEOUT:
+               if (num > 0)
+                       {
+#ifdef OPENSSL_SYS_WIN32
+                       struct timeb tb;
+                       ftime(&tb);
+                       data->hstimeout.tv_sec = tb.time;
+                       data->hstimeout.tv_usec = tb.millitm * 1000;
+#else
+                       gettimeofday(&(data->hstimeout), NULL);
+#endif
+                       data->hstimeout.tv_sec += data->hstimeoutdiff.tv_sec;
+                       data->hstimeout.tv_usec += data->hstimeoutdiff.tv_usec;
+                       if (data->hstimeout.tv_usec >= 1000000)
+                               {
+                               data->hstimeout.tv_sec++;
+                               data->hstimeout.tv_usec -= 1000000;
+                               }
+                       }
+               else
+                       {
+                       memset(&(data->hstimeout), 0, sizeof(struct timeval));
+                       }
+               break;
 #if defined(SO_RCVTIMEO)
        case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
 #ifdef OPENSSL_SYS_WINDOWS
 #if defined(SO_RCVTIMEO)
        case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
 #ifdef OPENSSL_SYS_WINDOWS
@@ -360,6 +409,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
                        sizeof(struct timeval)) < 0)
                        { perror("setsockopt"); ret = -1; }
 #endif
                        sizeof(struct timeval)) < 0)
                        { perror("setsockopt"); ret = -1; }
 #endif
+               memcpy(&(data->hstimeoutdiff), ptr, sizeof(struct timeval));
                break;
        case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
 #ifdef OPENSSL_SYS_WINDOWS
                break;
        case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
 #ifdef OPENSSL_SYS_WINDOWS
index 8833547292d50eac51485f0a1d99225112112cae..c151264e56381e9e1f2c578bb6f2fc5a06801e1a 100644 (file)
@@ -229,6 +229,7 @@ int dtls1_connect(SSL *s)
                        /* every DTLS ClientHello resets Finished MAC */
                        ssl3_init_finished_mac(s);
 
                        /* every DTLS ClientHello resets Finished MAC */
                        ssl3_init_finished_mac(s);
 
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret=dtls1_client_hello(s);
                        if (ret <= 0) goto end;
 
                        ret=dtls1_client_hello(s);
                        if (ret <= 0) goto end;
 
@@ -254,6 +255,7 @@ int dtls1_connect(SSL *s)
                        if (ret <= 0) goto end;
                        else
                                {
                        if (ret <= 0) goto end;
                        else
                                {
+                               BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
                                if (s->hit)
                                        s->state=SSL3_ST_CR_FINISHED_A;
                                else
                                if (s->hit)
                                        s->state=SSL3_ST_CR_FINISHED_A;
                                else
@@ -268,6 +270,7 @@ int dtls1_connect(SSL *s)
                        ret = dtls1_get_hello_verify(s);
                        if ( ret <= 0)
                                goto end;
                        ret = dtls1_get_hello_verify(s);
                        if ( ret <= 0)
                                goto end;
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
                        if ( s->d1->send_cookie) /* start again, with a cookie */
                                s->state=SSL3_ST_CW_CLNT_HELLO_A;
                        else
                        if ( s->d1->send_cookie) /* start again, with a cookie */
                                s->state=SSL3_ST_CW_CLNT_HELLO_A;
                        else
@@ -329,6 +332,7 @@ int dtls1_connect(SSL *s)
                case SSL3_ST_CW_CERT_B:
                case SSL3_ST_CW_CERT_C:
                case SSL3_ST_CW_CERT_D:
                case SSL3_ST_CW_CERT_B:
                case SSL3_ST_CW_CERT_C:
                case SSL3_ST_CW_CERT_D:
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret=dtls1_send_client_certificate(s);
                        if (ret <= 0) goto end;
                        s->state=SSL3_ST_CW_KEY_EXCH_A;
                        ret=dtls1_send_client_certificate(s);
                        if (ret <= 0) goto end;
                        s->state=SSL3_ST_CW_KEY_EXCH_A;
@@ -337,6 +341,7 @@ int dtls1_connect(SSL *s)
 
                case SSL3_ST_CW_KEY_EXCH_A:
                case SSL3_ST_CW_KEY_EXCH_B:
 
                case SSL3_ST_CW_KEY_EXCH_A:
                case SSL3_ST_CW_KEY_EXCH_B:
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret=dtls1_send_client_key_exchange(s);
                        if (ret <= 0) goto end;
                        /* EAY EAY EAY need to check for DH fix cert
                        ret=dtls1_send_client_key_exchange(s);
                        if (ret <= 0) goto end;
                        /* EAY EAY EAY need to check for DH fix cert
@@ -358,6 +363,7 @@ int dtls1_connect(SSL *s)
 
                case SSL3_ST_CW_CERT_VRFY_A:
                case SSL3_ST_CW_CERT_VRFY_B:
 
                case SSL3_ST_CW_CERT_VRFY_A:
                case SSL3_ST_CW_CERT_VRFY_B:
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret=dtls1_send_client_verify(s);
                        if (ret <= 0) goto end;
                        s->state=SSL3_ST_CW_CHANGE_A;
                        ret=dtls1_send_client_verify(s);
                        if (ret <= 0) goto end;
                        s->state=SSL3_ST_CW_CHANGE_A;
@@ -367,6 +373,7 @@ int dtls1_connect(SSL *s)
 
                case SSL3_ST_CW_CHANGE_A:
                case SSL3_ST_CW_CHANGE_B:
 
                case SSL3_ST_CW_CHANGE_A:
                case SSL3_ST_CW_CHANGE_B:
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret=dtls1_send_change_cipher_spec(s,
                                SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
                        if (ret <= 0) goto end;
                        ret=dtls1_send_change_cipher_spec(s,
                                SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
                        if (ret <= 0) goto end;
@@ -401,6 +408,7 @@ int dtls1_connect(SSL *s)
 
                case SSL3_ST_CW_FINISHED_A:
                case SSL3_ST_CW_FINISHED_B:
 
                case SSL3_ST_CW_FINISHED_A:
                case SSL3_ST_CW_FINISHED_B:
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret=dtls1_send_finished(s,
                                SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
                                s->method->ssl3_enc->client_finished_label,
                        ret=dtls1_send_finished(s,
                                SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
                                s->method->ssl3_enc->client_finished_label,
@@ -433,6 +441,7 @@ int dtls1_connect(SSL *s)
                        ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
                                SSL3_ST_CR_FINISHED_B);
                        if (ret <= 0) goto end;
                        ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
                                SSL3_ST_CR_FINISHED_B);
                        if (ret <= 0) goto end;
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 
                        if (s->hit)
                                s->state=SSL3_ST_CW_CHANGE_A;
 
                        if (s->hit)
                                s->state=SSL3_ST_CW_CHANGE_A;
index f4c12b226595d8402f58cca42ef0dd2d00b35783..ebd35c71617b46f2c5a470d7d857baf2bdd8fc3f 100644 (file)
@@ -249,6 +249,7 @@ int dtls1_accept(SSL *s)
                case SSL3_ST_SW_HELLO_REQ_B:
 
                        s->shutdown=0;
                case SSL3_ST_SW_HELLO_REQ_B:
 
                        s->shutdown=0;
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret=dtls1_send_hello_request(s);
                        if (ret <= 0) goto end;
                        s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
                        ret=dtls1_send_hello_request(s);
                        if (ret <= 0) goto end;
                        s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
@@ -269,6 +270,7 @@ int dtls1_accept(SSL *s)
                        s->shutdown=0;
                        ret=ssl3_get_client_hello(s);
                        if (ret <= 0) goto end;
                        s->shutdown=0;
                        ret=ssl3_get_client_hello(s);
                        if (ret <= 0) goto end;
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
                        s->new_session = 2;
 
                        if (s->d1->send_cookie)
                        s->new_session = 2;
 
                        if (s->d1->send_cookie)
@@ -282,6 +284,7 @@ int dtls1_accept(SSL *s)
                case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
                case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
 
                case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
                case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
 
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret = dtls1_send_hello_verify_request(s);
                        if ( ret <= 0) goto end;
                        s->d1->send_cookie = 0;
                        ret = dtls1_send_hello_verify_request(s);
                        if ( ret <= 0) goto end;
                        s->d1->send_cookie = 0;
@@ -294,6 +297,7 @@ int dtls1_accept(SSL *s)
                        
                case SSL3_ST_SW_SRVR_HELLO_A:
                case SSL3_ST_SW_SRVR_HELLO_B:
                        
                case SSL3_ST_SW_SRVR_HELLO_A:
                case SSL3_ST_SW_SRVR_HELLO_B:
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret=dtls1_send_server_hello(s);
                        if (ret <= 0) goto end;
 
                        ret=dtls1_send_server_hello(s);
                        if (ret <= 0) goto end;
 
@@ -309,6 +313,7 @@ int dtls1_accept(SSL *s)
                        /* Check if it is anon DH */
                        if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
                                {
                        /* Check if it is anon DH */
                        if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
                                {
+                               BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                                ret=dtls1_send_server_certificate(s);
                                if (ret <= 0) goto end;
                                }
                                ret=dtls1_send_server_certificate(s);
                                if (ret <= 0) goto end;
                                }
@@ -350,6 +355,7 @@ int dtls1_accept(SSL *s)
                                )
                            )
                                {
                                )
                            )
                                {
+                               BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                                ret=dtls1_send_server_key_exchange(s);
                                if (ret <= 0) goto end;
                                }
                                ret=dtls1_send_server_key_exchange(s);
                                if (ret <= 0) goto end;
                                }
@@ -386,6 +392,7 @@ int dtls1_accept(SSL *s)
                        else
                                {
                                s->s3->tmp.cert_request=1;
                        else
                                {
                                s->s3->tmp.cert_request=1;
+                               BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                                ret=dtls1_send_certificate_request(s);
                                if (ret <= 0) goto end;
 #ifndef NETSCAPE_HANG_BUG
                                ret=dtls1_send_certificate_request(s);
                                if (ret <= 0) goto end;
 #ifndef NETSCAPE_HANG_BUG
@@ -400,6 +407,7 @@ int dtls1_accept(SSL *s)
 
                case SSL3_ST_SW_SRVR_DONE_A:
                case SSL3_ST_SW_SRVR_DONE_B:
 
                case SSL3_ST_SW_SRVR_DONE_A:
                case SSL3_ST_SW_SRVR_DONE_B:
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
                        ret=dtls1_send_server_done(s);
                        if (ret <= 0) goto end;
                        s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
                        ret=dtls1_send_server_done(s);
                        if (ret <= 0) goto end;
                        s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
@@ -427,6 +435,7 @@ int dtls1_accept(SSL *s)
                        ret = ssl3_check_client_hello(s);
                        if (ret <= 0)
                                goto end;
                        ret = ssl3_check_client_hello(s);
                        if (ret <= 0)
                                goto end;
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
                        if (ret == 2)
                                s->state = SSL3_ST_SR_CLNT_HELLO_C;
                        else {
                        if (ret == 2)
                                s->state = SSL3_ST_SR_CLNT_HELLO_C;
                        else {
@@ -434,6 +443,7 @@ int dtls1_accept(SSL *s)
                                 * have not asked for it :-) */
                                ret=ssl3_get_client_certificate(s);
                                if (ret <= 0) goto end;
                                 * have not asked for it :-) */
                                ret=ssl3_get_client_certificate(s);
                                if (ret <= 0) goto end;
+                               BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
                                s->init_num=0;
                                s->state=SSL3_ST_SR_KEY_EXCH_A;
                        }
                                s->init_num=0;
                                s->state=SSL3_ST_SR_KEY_EXCH_A;
                        }
@@ -443,6 +453,7 @@ int dtls1_accept(SSL *s)
                case SSL3_ST_SR_KEY_EXCH_B:
                        ret=ssl3_get_client_key_exchange(s);
                        if (ret <= 0) goto end;
                case SSL3_ST_SR_KEY_EXCH_B:
                        ret=ssl3_get_client_key_exchange(s);
                        if (ret <= 0) goto end;
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
                        s->state=SSL3_ST_SR_CERT_VRFY_A;
                        s->init_num=0;
 
                        s->state=SSL3_ST_SR_CERT_VRFY_A;
                        s->init_num=0;
 
@@ -463,6 +474,7 @@ int dtls1_accept(SSL *s)
                        /* we should decide if we expected this one */
                        ret=ssl3_get_cert_verify(s);
                        if (ret <= 0) goto end;
                        /* we should decide if we expected this one */
                        ret=ssl3_get_cert_verify(s);
                        if (ret <= 0) goto end;
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 
                        s->state=SSL3_ST_SR_FINISHED_A;
                        s->init_num=0;
 
                        s->state=SSL3_ST_SR_FINISHED_A;
                        s->init_num=0;
@@ -473,6 +485,7 @@ int dtls1_accept(SSL *s)
                        ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
                                SSL3_ST_SR_FINISHED_B);
                        if (ret <= 0) goto end;
                        ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
                                SSL3_ST_SR_FINISHED_B);
                        if (ret <= 0) goto end;
+                       BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
                        if (s->hit)
                                s->state=SSL_ST_OK;
                        else
                        if (s->hit)
                                s->state=SSL_ST_OK;
                        else