I haven't actually seen this in practice, but I have been reading the code for ssl3_get_record in ssl/s3_pkt.c and I think there might be a bug.

Immediately following the "again" label is this code:

again:
    /* check if we have the header */
    if (    (s->rstate != SSL_ST_READ_BODY) ||
        (s->packet_length < SSL3_RT_HEADER_LENGTH))
        {
        n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
        if (n <= 0) return(n); /* error or non-blocking */
        s->rstate=SSL_ST_READ_BODY;

(This is lines 311-318 in ssl/s3_pkt from OpenSSL 1.0.1e.)

I think the problem occurs because passing zero for the "extend" parameter of ssl3_read_n discards any data already pointed to by s->packet, even if s->packet_length is nonzero.

Suppose, with a non-blocking socket, that a TCP segment containing a full TLS record and (say) the first two bytes of the next record is the most recent data received. When we call ssl3_get_record to read the partial header, ssl3_read_n will read two bytes into s->packet and return -1 (non-blocking I/O). Later, when more data is available, we will again call ssl3_get_record to read the rest of the header. However, doesn't the call to ssl3_read_n actually discard the two bytes already read?

Have I misread this?

                    - Ken

Reply via email to