I came across this bug while i found our SSL server was coring a few times a
day. I used dmalloc (www.dmalloc.com) to help trace it down to a client
using MSIE with SSLv3 off and using SSLv2. I have not tried but i assume
any SSLv2 client will cause the same results. It comes down to calculating
a wrong buffer size and overwriting a buffer limit. Here are the details:

ssl/s2_pkt.c line 453

   453  static int do_ssl_write(SSL *s, const unsigned char *buf, unsigned int l
en)
   454          {
   455          unsigned int j,k,olen,p,mac_size,bs;
   456          register unsigned char *pp;
   457
   458          olen=len;
   459
   460          /* first check if there is data from an encryption waiting to
   461           * be sent - it must be sent because the other end is waiting.
   462           * This will happen with non-blocking IO.  We print it and then
   463           * return.
   464           */
   465          if (s->s2->wpend_len != 0) return(write_pending(s,buf,len));
   466
   467          /* set mac_size to mac size */
   468          if (s->s2->clear_text)
   469                  mac_size=0;
   470          else
   471                  mac_size=EVP_MD_size(s->write_hash);
   472
   473          /* lets set the pad p */
   474          if (s->s2->clear_text)
   475                  {
   476                  if (len > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
   477                          len=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
   478                  p=0;
   479                  s->s2->three_byte_header=0;
   480                  /* len=len; */
   481                  }
   482          else
   483                  {
   484                  bs=EVP_CIPHER_CTX_block_size(s->enc_read_ctx);
   485                  j=len+mac_size;
   486                  if ((j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) &&
   487                          (!s->s2->escape))
   488                          {
   489                          if (j > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
   490                                  j=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
   491                          /* set k to the max number of bytes with 2
   492                           * byte header */
   493                          k=j-(j%bs);
   494                          /* how many data bytes? */
   495                          len=k-mac_size;
   496                          s->s2->three_byte_header=0;
   497                          p=0;
   498                          }
   499                  else if ((bs <= 1) && (!s->s2->escape))
   500                          {
   501                          /* len=len; */
   502                          s->s2->three_byte_header=0;
   503                          p=0;
   504                          }
   505                  else /* 3 byte header */
   506                          {
   507                          /*len=len; */
   508                          p=(j%bs);
   509                          p=(p == 0)?0:(bs-p);
   510                          if (s->s2->escape)
   511                                  s->s2->three_byte_header=1;
   512                          else
   513                                  s->s2->three_byte_header=(p == 0)?0:1;
   514                          }
   515                  }
   516          /* mac_size is the number of MAC bytes
   517           * len is the number of data bytes we are going to send
   518           * p is the number of padding bytes
   519           * if p == 0, it is a 2 byte header */
   520  
   521          s->s2->wlength=len;
   522          s->s2->padding=p;
   523          s->s2->mac_data= &(s->s2->wbuf[3]);
   524          s->s2->wact_data= &(s->s2->wbuf[3+mac_size]);
   525          /* we copy the data into s->s2->wbuf */
   526          memcpy(s->s2->wact_data,buf,len);

...


SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER = 32767
SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER = 16383
s->s2->wbuf allocated with SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2 bytes
    (s2_lib.c)

453: called with len = 32768
465: s->s2->wpend_len = 0, does not meet condition
468: s->s2->clear_text = 0
471: mac_size gets set to 16 (s->write_hash->md_size)
474: s->s2->clear_text = 0
484: bs set to 1 (s->enc_read_ctx->cipher->block_size)
485: j set to 32784 (32768 + 16)
486: j (32784) is > 16383  AND  s->s2->escape = 0
489: j (32784) is > 32767
490: j set to 32767
493: k set to 32767 - (32767 % 1) = 32767
495: len = 32767 - 16 = 32751
...
524: s->s2->wact_data set to s->s2->wbuf[19], this leaves 32769 - 19 as a
     buffer for s->s2->wact_data
526: 32751 bytes are written into s->s2->wact_data, which is 32750 bytes long

someone double check the math here, but i believe this is correct. if not
i'm sorry for whoevers time i wasted =)

i don't know the lib well enough to propose a fix, but i assume its just
adding a byte to the buffer or removing one from the length to copy
somewhere.

-Eric Day
[EMAIL PROTECTED]
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to