A memory leak can occur in dtls1_buffer_record if either of the calls to
[openssl.git] / ssl / d1_pkt.c
index 009a434943c95f0cf8162862adcb1df8f7b5f2f1..082b3fbf8b48ae804def01d843604427d0dcfe8c 100644 (file)
@@ -212,7 +212,7 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
        /* Limit the size of the queue to prevent DOS attacks */
        if (pqueue_size(queue->q) >= 100)
                return 0;
-               
+
        rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA));
        item = pitem_new(priority, rdata);
        if (rdata == NULL || item == NULL)
@@ -239,14 +239,6 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
        }
 #endif
 
-       /* insert should not fail, since duplicates are dropped */
-       if (pqueue_insert(queue->q, item) == NULL)
-               {
-               OPENSSL_free(rdata);
-               pitem_free(item);
-               return(0);
-               }
-
        s->packet = NULL;
        s->packet_length = 0;
        memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
@@ -255,11 +247,24 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
        if (!ssl3_setup_buffers(s))
                {
                SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+               if (rdata->rbuf.buf != NULL)
+                       OPENSSL_free(rdata->rbuf.buf);
                OPENSSL_free(rdata);
                pitem_free(item);
-               return(0);
+               return(-1);
                }
-       
+
+       /* insert should not fail, since duplicates are dropped */
+       if (pqueue_insert(queue->q, item) == NULL)
+               {
+               SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+               if (rdata->rbuf.buf != NULL)
+                       OPENSSL_free(rdata->rbuf.buf);
+               OPENSSL_free(rdata);
+               pitem_free(item);
+               return(-1);
+               }
+
        return(1);
        }
 
@@ -313,8 +318,9 @@ dtls1_process_buffered_records(SSL *s)
             dtls1_get_unprocessed_record(s);
             if ( ! dtls1_process_record(s))
                 return(0);
-            dtls1_buffer_record(s, &(s->d1->processed_rcds), 
-                s->s3->rrec.seq_num);
+            if(dtls1_buffer_record(s, &(s->d1->processed_rcds),
+                s->s3->rrec.seq_num)<0)
+                return -1;
             }
         }
 
@@ -529,7 +535,6 @@ printf("\n");
 
        /* we have pulled in a full packet so zero things */
        s->packet_length=0;
-       dtls1_record_bitmap_update(s, &(s->d1->bitmap));/* Mark receipt of record. */
        return(1);
 
 f_err:
@@ -562,7 +567,8 @@ int dtls1_get_record(SSL *s)
 
        /* The epoch may have changed.  If so, process all the
         * pending records.  This is a non-blocking operation. */
-       dtls1_process_buffered_records(s);
+       if(dtls1_process_buffered_records(s)<0)
+               return -1;
 
        /* if we're renegotiating, then there may be buffered records */
        if (dtls1_get_processed_record(s))
@@ -589,6 +595,9 @@ again:
 
                p=s->packet;
 
+               if (s->msg_callback)
+                       s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
+
                /* Pull apart the header into the DTLS1_RECORD */
                rr->type= *(p++);
                ssl_major= *(p++);
@@ -641,8 +650,6 @@ again:
                /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
                i=rr->length;
                n=ssl3_read_n(s,i,i,1);
-               if (n <= 0) return(n); /* error or non-blocking io */
-
                /* this packet contained a partial record, dump it */
                if ( n != i)
                        {
@@ -677,7 +684,8 @@ again:
                 * would be dropped unnecessarily.
                 */
                if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
-                   *p == SSL3_MT_CLIENT_HELLO) &&
+                   s->packet_length > DTLS1_RT_HEADER_LENGTH &&
+                   s->packet[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO) &&
                    !dtls1_record_replay_check(s, bitmap))
                        {
                        rr->length = 0;
@@ -700,7 +708,9 @@ again:
                {
                if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen)
                        {
-                       dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num);
+                       if(dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num)<0)
+                               return -1;
+                       dtls1_record_bitmap_update(s, bitmap);/* Mark receipt of record. */
                        }
                rr->length = 0;
                s->packet_length = 0;
@@ -713,6 +723,7 @@ again:
                s->packet_length = 0;  /* dump this record */
                goto again;   /* get another record */
                }
+       dtls1_record_bitmap_update(s, bitmap);/* Mark receipt of record. */
 
        return(1);
 
@@ -864,7 +875,11 @@ start:
                 * buffer the application data for later processing rather
                 * than dropping the connection.
                 */
-               dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num);
+               if(dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num)<0)
+                       {
+                       SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
+                       return -1;
+                       }
                rr->length = 0;
                goto start;
                }
@@ -1556,9 +1571,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len,
         * we haven't decided which version to use yet send back using 
         * version 1.0 header: otherwise some clients will ignore it.
         */
-       if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B
-                       && s->method->version == DTLS_ANY_VERSION
-                       && s->client_version == DTLS1_VERSION)
+       if (s->method->version == DTLS_ANY_VERSION)
                {
                *(p++)=DTLS1_VERSION>>8;
                *(p++)=DTLS1_VERSION&0xff;
@@ -1633,7 +1646,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len,
        if (eivlen)
                wr->length += eivlen;
 
-       s->method->ssl3_enc->enc(s,1);
+       if(s->method->ssl3_enc->enc(s,1) < 1) goto err;
 
        /* record length after mac and block padding */
 /*     if (type == SSL3_RT_APPLICATION_DATA ||
@@ -1651,6 +1664,9 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len,
        pseq+=6;
        s2n(wr->length,pseq);
 
+       if (s->msg_callback)
+               s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH, DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
+
        /* we should now have
         * wr->data pointing to the encrypted data, which is
         * wr->length long */