PR: 2755
[openssl.git] / ssl / d1_lib.c
index 96b220e87ce0f52a21f60f1486c0dae6f7e33c7c..f4bfd29afd5b18892a2852fba362d24d339f2ebc 100644 (file)
@@ -82,6 +82,7 @@ SSL3_ENC_METHOD DTLSv1_enc_data={
        TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
        TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
        tls1_alert_code,
        TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
        TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
        tls1_alert_code,
+       tls1_export_keying_material,
        };
 
 long dtls1_default_timeout(void)
        };
 
 long dtls1_default_timeout(void)
@@ -129,26 +130,33 @@ int dtls1_new(SSL *s)
        return(1);
        }
 
        return(1);
        }
 
-void dtls1_free(SSL *s)
+static void dtls1_clear_queues(SSL *s)
        {
     pitem *item = NULL;
     hm_fragment *frag = NULL;
        {
     pitem *item = NULL;
     hm_fragment *frag = NULL;
-
-       ssl3_free(s);
+       DTLS1_RECORD_DATA *rdata;
 
     while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
         {
 
     while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
         {
+               rdata = (DTLS1_RECORD_DATA *) item->data;
+               if (rdata->rbuf.buf)
+                       {
+                       OPENSSL_free(rdata->rbuf.buf);
+                       }
         OPENSSL_free(item->data);
         pitem_free(item);
         }
         OPENSSL_free(item->data);
         pitem_free(item);
         }
-    pqueue_free(s->d1->unprocessed_rcds.q);
 
     while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
         {
 
     while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
         {
+               rdata = (DTLS1_RECORD_DATA *) item->data;
+               if (rdata->rbuf.buf)
+                       {
+                       OPENSSL_free(rdata->rbuf.buf);
+                       }
         OPENSSL_free(item->data);
         pitem_free(item);
         }
         OPENSSL_free(item->data);
         pitem_free(item);
         }
-    pqueue_free(s->d1->processed_rcds.q);
 
     while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
         {
 
     while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
         {
@@ -157,7 +165,6 @@ void dtls1_free(SSL *s)
         OPENSSL_free(frag);
         pitem_free(item);
         }
         OPENSSL_free(frag);
         pitem_free(item);
         }
-    pqueue_free(s->d1->buffered_messages);
 
     while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
         {
 
     while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
         {
@@ -166,7 +173,6 @@ void dtls1_free(SSL *s)
         OPENSSL_free(frag);
         pitem_free(item);
         }
         OPENSSL_free(frag);
         pitem_free(item);
         }
-       pqueue_free(s->d1->sent_messages);
 
        while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
                {
 
        while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
                {
@@ -175,6 +181,18 @@ void dtls1_free(SSL *s)
                OPENSSL_free(frag);
                pitem_free(item);
                }
                OPENSSL_free(frag);
                pitem_free(item);
                }
+       }
+
+void dtls1_free(SSL *s)
+       {
+       ssl3_free(s);
+
+       dtls1_clear_queues(s);
+
+    pqueue_free(s->d1->unprocessed_rcds.q);
+    pqueue_free(s->d1->processed_rcds.q);
+    pqueue_free(s->d1->buffered_messages);
+       pqueue_free(s->d1->sent_messages);
        pqueue_free(s->d1->buffered_app_data.q);
 
        OPENSSL_free(s->d1);
        pqueue_free(s->d1->buffered_app_data.q);
 
        OPENSSL_free(s->d1);
@@ -182,6 +200,43 @@ void dtls1_free(SSL *s)
 
 void dtls1_clear(SSL *s)
        {
 
 void dtls1_clear(SSL *s)
        {
+    pqueue unprocessed_rcds;
+    pqueue processed_rcds;
+    pqueue buffered_messages;
+       pqueue sent_messages;
+       pqueue buffered_app_data;
+       unsigned int mtu;
+
+       if (s->d1)
+               {
+               unprocessed_rcds = s->d1->unprocessed_rcds.q;
+               processed_rcds = s->d1->processed_rcds.q;
+               buffered_messages = s->d1->buffered_messages;
+               sent_messages = s->d1->sent_messages;
+               buffered_app_data = s->d1->buffered_app_data.q;
+               mtu = s->d1->mtu;
+
+               dtls1_clear_queues(s);
+
+               memset(s->d1, 0, sizeof(*(s->d1)));
+
+               if (s->server)
+                       {
+                       s->d1->cookie_len = sizeof(s->d1->cookie);
+                       }
+
+               if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)
+                       {
+                       s->d1->mtu = mtu;
+                       }
+
+               s->d1->unprocessed_rcds.q = unprocessed_rcds;
+               s->d1->processed_rcds.q = processed_rcds;
+               s->d1->buffered_messages = buffered_messages;
+               s->d1->sent_messages = sent_messages;
+               s->d1->buffered_app_data.q = buffered_app_data;
+               }
+
        ssl3_clear(s);
        if (s->options & SSL_OP_CISCO_ANYCONNECT)
                s->version=DTLS1_BAD_VER;
        ssl3_clear(s);
        if (s->options & SSL_OP_CISCO_ANYCONNECT)
                s->version=DTLS1_BAD_VER;
@@ -237,6 +292,15 @@ const SSL_CIPHER *dtls1_get_cipher(unsigned int u)
 
 void dtls1_start_timer(SSL *s)
        {
 
 void dtls1_start_timer(SSL *s)
        {
+#ifndef OPENSSL_NO_SCTP
+       /* Disable timer for SCTP */
+       if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
+               {
+               memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
+               return;
+               }
+#endif
+
        /* If timer is not set, initialize duration with 1 second */
        if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
                {
        /* If timer is not set, initialize duration with 1 second */
        if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
                {
@@ -330,6 +394,8 @@ void dtls1_stop_timer(SSL *s)
        memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
        s->d1->timeout_duration = 1;
        BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
        memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
        s->d1->timeout_duration = 1;
        BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
+       /* Clear retransmission buffer */
+       dtls1_clear_record_buffer(s);
        }
 
 int dtls1_handle_timeout(SSL *s)
        }
 
 int dtls1_handle_timeout(SSL *s)
@@ -349,7 +415,7 @@ int dtls1_handle_timeout(SSL *s)
                {
                /* fail the connection, enough alerts have been sent */
                SSLerr(SSL_F_DTLS1_HANDLE_TIMEOUT,SSL_R_READ_TIMEOUT_EXPIRED);
                {
                /* fail the connection, enough alerts have been sent */
                SSLerr(SSL_F_DTLS1_HANDLE_TIMEOUT,SSL_R_READ_TIMEOUT_EXPIRED);
-               return 0;
+               return -1;
                }
 
        state->timeout.read_timeouts++;
                }
 
        state->timeout.read_timeouts++;
@@ -358,6 +424,19 @@ int dtls1_handle_timeout(SSL *s)
                state->timeout.read_timeouts = 1;
                }
 
                state->timeout.read_timeouts = 1;
                }
 
+       if (state->timeout_duration > 2)
+               {
+               s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);               
+               }
+
+#ifndef OPENSSL_NO_HEARTBEATS
+       if (s->tlsext_hb_pending)
+               {
+               s->tlsext_hb_pending = 0;
+               return dtls1_heartbeat(s);
+               }
+#endif
+
        dtls1_start_timer(s);
        return dtls1_retransmit_buffered_messages(s);
        }
        dtls1_start_timer(s);
        return dtls1_retransmit_buffered_messages(s);
        }