Additional CVE-2014-0224 protection.
[openssl.git] / ssl / s3_pkt.c
index b9e45c74bc5c8c04cc7c2e023eb484162491e362..34eb2b442331f7cdee5d1fa17f3567bcfb380623 100644 (file)
@@ -658,6 +658,21 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
                        }
                }
 
+       /* ensure that if we end up with a smaller value of data to write 
+        * out than the the original len from a write which didn't complete 
+        * for non-blocking I/O and also somehow ended up avoiding 
+        * the check for this in ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as
+        * it must never be possible to end up with (len-tot) as a large
+        * number that will then promptly send beyond the end of the users
+        * buffer ... so we trap and report the error in a way the user
+        * will notice
+        */
+       if ( len < tot)
+               {
+               SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_BAD_LENGTH);
+               return(-1);
+               }
+
        /* first check if there is a SSL3_BUFFER still being written
         * out.  This will happen with non blocking IO */
        if (wb->left != 0)
@@ -816,6 +831,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
                return tot;
                }
 
+
        n=(len-tot);
        for (;;)
                {
@@ -864,9 +880,6 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
        SSL3_BUFFER *wb=&(s->s3->wbuf);
        SSL_SESSION *sess;
 
-       if (wb->buf == NULL)
-               if (!ssl3_setup_write_buffer(s))
-                       return -1;
 
        /* first check if there is a SSL3_BUFFER still being written
         * out.  This will happen with non blocking IO */
@@ -882,6 +895,10 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
                /* if it went, fall through and send more stuff */
                }
 
+       if (wb->buf == NULL)
+               if (!ssl3_setup_write_buffer(s))
+                       return -1;
+
        if (len == 0 && !create_empty_fragment)
                return 0;
 
@@ -1334,7 +1351,7 @@ start:
                                {
                                s->rstate=SSL_ST_READ_HEADER;
                                rr->off=0;
-                               if (s->mode & SSL_MODE_RELEASE_BUFFERS)
+                               if (s->mode & SSL_MODE_RELEASE_BUFFERS && s->s3->rbuf.left == 0)
                                        ssl3_release_read_buffer(s);
                                }
                        }
@@ -1710,7 +1727,7 @@ int ssl3_do_change_cipher_spec(SSL *s)
 
        if (s->s3->tmp.key_block == NULL)
                {
-               if (s->session == NULL
+               if (s->session == NULL || s->session->master_key_length == 0)
                        {
                        /* might happen if dtls1_read_bytes() calls this */
                        SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY);