}
}
-int ssl3_read_n(SSL *s, int n, int max, int extend, int clearold)
+/*
+ * Return values are as per SSL_read(), i.e.
+ * 1 Success
+ * 0 Failure (not retryable)
+ * <0 Failure (may be retryable)
+ */
+int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
+ size_t *read)
{
/*
* If extend == 0, obtain new n-byte packet; if extend == 1, increase
* if clearold == 1, move the packet to the start of the buffer; if
* clearold == 0 then leave any old packets where they were
*/
- int i, len, left;
- size_t align = 0;
+ size_t len, left, align = 0;
unsigned char *pkt;
SSL3_BUFFER *rb;
- if (n <= 0)
- return n;
+ if (n == 0)
+ return 0;
rb = &s->rlayer.rbuf;
if (rb->buf == NULL)
/* ... now we can act as if 'extend' was set */
}
+ len = s->rlayer.packet_length;
+ pkt = rb->buf + align;
+ /*
+ * Move any available bytes to front of buffer: 'len' bytes already
+ * pointed to by 'packet', 'left' extra ones at the end
+ */
+ if (s->rlayer.packet != pkt && clearold == 1) {
+ memmove(pkt, s->rlayer.packet, len + left);
+ s->rlayer.packet = pkt;
+ rb->offset = len + align;
+ }
+
/*
* For DTLS/UDP reads should not span multiple packets because the read
* operation returns the whole packet at once (as long as it fits into
s->rlayer.packet_length += n;
rb->left = left - n;
rb->offset += n;
- return (n);
+ *read = n;
+ return 1;
}
/* else we need to read more data */
- len = s->rlayer.packet_length;
- pkt = rb->buf + align;
- /*
- * Move any available bytes to front of buffer: 'len' bytes already
- * pointed to by 'packet', 'left' extra ones at the end
- */
- if (s->rlayer.packet != pkt && clearold == 1) { /* len > 0 */
- memmove(pkt, s->rlayer.packet, len + left);
- s->rlayer.packet = pkt;
- rb->offset = len + align;
- }
-
- if (n > (int)(rb->len - rb->offset)) { /* does not happen */
+ if (n > (rb->len - rb->offset)) { /* does not happen */
SSLerr(SSL_F_SSL3_READ_N, ERR_R_INTERNAL_ERROR);
return -1;
}
else {
if (max < n)
max = n;
- if (max > (int)(rb->len - rb->offset))
+ if (max > (rb->len - rb->offset))
max = rb->len - rb->offset;
}
while (left < n) {
+ size_t bioread;
+ int ret;
+
/*
* Now we have len+left bytes at the front of s->s3->rbuf.buf and
* need to read in more until we have len+n (up to len+max if
clear_sys_error();
if (s->rbio != NULL) {
s->rwstate = SSL_READING;
- i = BIO_read(s->rbio, pkt + len + left, max - left);
+ /* TODO(size_t): Convert this function */
+ ret = BIO_read(s->rbio, pkt + len + left, max - left);
+ if (ret >= 0)
+ bioread = ret;
} else {
SSLerr(SSL_F_SSL3_READ_N, SSL_R_READ_BIO_NOT_SET);
- i = -1;
+ ret = -1;
}
- if (i <= 0) {
+ if (ret <= 0) {
rb->left = left;
if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
if (len + left == 0)
ssl3_release_read_buffer(s);
- return (i);
+ return -1;
}
- left += i;
+ left += bioread;
/*
* reads should *never* span multiple packets for DTLS because the
* underlying transport protocol is message oriented as opposed to
rb->left = left - n;
s->rlayer.packet_length += n;
s->rwstate = SSL_NOTHING;
- return (n);
+ *read = n;
+ return 1;
}
/*
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) {
unsigned char aad[13];
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
- int packlen;
+ size_t packlen;
/* minimize address aliasing conflicts */
if ((max_send_fragment & 0xfff) == 0)
mb_param.inp = aad;
mb_param.len = nw;
+ /* TODO: CHECK ME - CAN THIS EVER BE NEGATIVE???? */
packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
sizeof(mb_param), &mb_param);
- if (packlen <= 0 || packlen > (int)wb->len) { /* never happens */
+ if (packlen <= 0 || packlen > wb->len) { /* never happens */
/* free jumbo buffer */
ssl3_release_write_buffer(s);
break;
return -1;
}
-/* if s->s3->wbuf.left != 0, we need to call this */
+/* if s->s3->wbuf.left != 0, we need to call this
+ *
+ * Return values are as per SSL_read(), i.e.
+ * >0 The number of read bytes
+ * 0 Failure (not retryable)
+ * <0 Failure (may be retryable)
+ */
int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
unsigned int len)
{
SSLerr(SSL_F_SSL3_WRITE_PENDING, SSL_R_BIO_NOT_SET);
i = -1;
}
- if (i == SSL3_BUFFER_get_left(&wb[currbuf])) {
+ if (i == (int)SSL3_BUFFER_get_left(&wb[currbuf])) {
SSL3_BUFFER_set_left(&wb[currbuf], 0);
SSL3_BUFFER_add_offset(&wb[currbuf], i);
if (currbuf + 1 < s->rlayer.numwpipes)
*/
SSL3_BUFFER_set_left(&wb[currbuf], 0);
}
- return (i);
+ return -1;
}
SSL3_BUFFER_add_offset(&wb[currbuf], i);
SSL3_BUFFER_add_left(&wb[currbuf], -i);
} while (num_recs == 0);
rr = &rr[curr_rec];
+ /*
+ * Reset the count of consecutive warning alerts if we've got a non-empty
+ * record that isn't an alert.
+ */
+ if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT
+ && SSL3_RECORD_get_length(rr) != 0)
+ s->rlayer.alert_count = 0;
+
/* we now have a packet which can be read and processed */
if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
memcpy(buf, &(rr->data[rr->off]), n);
buf += n;
- if (!peek) {
+ if (peek) {
+ /* Mark any zero length record as consumed CVE-2016-6305 */
+ if (SSL3_RECORD_get_length(rr) == 0)
+ SSL3_RECORD_set_read(rr);
+ } else {
SSL3_RECORD_sub_length(rr, n);
SSL3_RECORD_add_off(rr, n);
if (SSL3_RECORD_get_length(rr) == 0) {
if (alert_level == SSL3_AL_WARNING) {
s->s3->warn_alert = alert_descr;
SSL3_RECORD_set_read(rr);
+
+ s->rlayer.alert_count++;
+ if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS);
+ goto f_err;
+ }
+
if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return (0);
goto f_err;
}
#ifdef SSL_AD_MISSING_SRP_USERNAME
- else if (alert_descr == SSL_AD_MISSING_SRP_USERNAME) {
- return 0;
- }
+ else if (alert_descr == SSL_AD_MISSING_SRP_USERNAME)
+ return (0);
#endif
- else {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE);
- goto f_err;
- }
} else if (alert_level == SSL3_AL_FATAL) {
char tmp[16];
switch (SSL3_RECORD_get_type(rr)) {
default:
/*
- * TLS up to v1.1 just ignores unknown message types: TLS v1.2 give
- * an unexpected message alert.
+ * TLS 1.0 and 1.1 say you SHOULD ignore unrecognised record types, but
+ * TLS 1.2 says you MUST send an unexpected message alert. We use the
+ * TLS 1.2 behaviour for all protocol versions to prevent issues where
+ * no progress is being made and the peer continually sends unrecognised
+ * record types, using up resources processing them.
*/
- if (s->version >= TLS1_VERSION && s->version <= TLS1_1_VERSION) {
- SSL3_RECORD_set_length(rr, 0);
- SSL3_RECORD_set_read(rr);
- goto start;
- }
al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
goto f_err;