X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_pkt.c;h=febc2860e1f49defac832249a4d7ce3d0fef1108;hp=3e5ce0c5b9bbb1970a5f92b3a318809b74befb24;hb=3f7c59208270dd4f8acb52649a5e6d349d21859b;hpb=8164032a2e34ac236775cfcf6301d7c74534bbe4 diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index 3e5ce0c5b9..febc2860e1 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c @@ -137,6 +137,10 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) if (n <= 0) return n; rb = &(s->s3->rbuf); + if (rb->buf == NULL) + if (!ssl3_setup_read_buffer(s)) + return -1; + left = rb->left; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (long)rb->buf + SSL3_RT_HEADER_LENGTH; @@ -156,7 +160,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) if (pkt[0] == SSL3_RT_APPLICATION_DATA && (pkt[3]<<8|pkt[4]) >= 128) { - /* Note that even if packet is corrupted + /* Note that even if packet is corrupted * and its length field is insane, we can * only be led to wrong decision about * whether memmove will occur or not. @@ -172,11 +176,12 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) /* ... now we can act as if 'extend' was set */ } - /* extend reads should not span multiple packets for DTLS */ - if ( SSL_version(s) == DTLS1_VERSION && - extend) + /* 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 the buffer). */ + if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) { - if ( left > 0 && n > left) + if (left > 0 && n > left) n = left; } @@ -203,15 +208,22 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) rb->offset = len + align; } - max = rb->len - rb->offset; - if (n > max) /* does not happen */ + if (n > (int)(rb->len - rb->offset)) /* does not happen */ { SSLerr(SSL_F_SSL3_READ_N,ERR_R_INTERNAL_ERROR); return -1; } if (!s->read_ahead) - max=n; + /* ignore max parameter */ + max = n; + else + { + if (max < n) + max = n; + if (max > (int)(rb->len - rb->offset)) + max = rb->len - rb->offset; + } while (left < n) { @@ -234,9 +246,20 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) if (i <= 0) { rb->left = left; + if (s->mode & SSL_MODE_RELEASE_BUFFERS) + if (len+left == 0) + ssl3_release_read_buffer(s); return(i); } left+=i; + /* reads should *never* span multiple packets for DTLS because + * the underlying transport protocol is message oriented as opposed + * to byte oriented as in the TLS case. */ + if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) + { + if (n > left) + n = left; /* makes the while condition false */ + } } /* done reading, now the book-keeping */ @@ -265,7 +288,7 @@ static int ssl3_get_record(SSL *s) unsigned char *p; unsigned char md[EVP_MAX_MD_SIZE]; short version; - unsigned int mac_size; + int mac_size; int clear=0; size_t extra; int decryption_failed_or_bad_record_mac = 0; @@ -405,7 +428,9 @@ printf("\n"); if (!clear) { + /* !clear => s->read_hash != NULL => mac_size != -1 */ mac_size=EVP_MD_CTX_size(s->read_hash); + OPENSSL_assert(mac_size >= 0); if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) { @@ -418,7 +443,7 @@ printf("\n"); #endif } /* check the MAC for rr->input (it's in mac_size bytes at the tail) */ - if (rr->length >= mac_size) + if (rr->length >= (unsigned int)mac_size) { rr->length -= mac_size; mac = &rr->data[rr->length]; @@ -436,7 +461,7 @@ printf("\n"); #endif } i=s->method->ssl3_enc->mac(s,md,0); - if (mac == NULL || memcmp(md, mac, mac_size) != 0) + if (i < 0 || mac == NULL || memcmp(md, mac, (size_t)mac_size) != 0) { decryption_failed_or_bad_record_mac = 1; } @@ -609,6 +634,10 @@ 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 */ if (wb->left != 0) @@ -637,7 +666,11 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, if (clear) mac_size=0; else + { mac_size=EVP_MD_CTX_size(s->write_hash); + if (mac_size < 0) + goto err; + } /* 'create_empty_fragment' is true only when this function calls itself */ if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done) @@ -735,7 +768,8 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, if (mac_size != 0) { - s->method->ssl3_enc->mac(s,&(p[wr->length]),1); + if (s->method->ssl3_enc->mac(s,&(p[wr->length]),1) < 0) + goto err; wr->length+=mac_size; wr->input=p; wr->data=p; @@ -812,11 +846,20 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, { wb->left=0; wb->offset+=i; + if (s->mode & SSL_MODE_RELEASE_BUFFERS) + ssl3_release_write_buffer(s); s->rwstate=SSL_NOTHING; return(s->s3->wpend_ret); } - else if (i <= 0) + else if (i <= 0) { + if (s->version == DTLS1_VERSION || + s->version == DTLS1_BAD_VER) { + /* For DTLS, just drop it. That's kind of the whole + point in using a datagram service */ + wb->left = 0; + } return(i); + } wb->offset+=i; wb->left-=i; } @@ -857,7 +900,7 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) void (*cb)(const SSL *ssl,int type2,int val)=NULL; if (s->s3->rbuf.buf == NULL) /* Not initialized yet */ - if (!ssl3_setup_buffers(s)) + if (!ssl3_setup_read_buffer(s)) return(-1); if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type) || @@ -966,6 +1009,8 @@ start: { s->rstate=SSL_ST_READ_HEADER; rr->off=0; + if (s->mode & SSL_MODE_RELEASE_BUFFERS) + ssl3_release_read_buffer(s); } } return(n); @@ -1287,6 +1332,13 @@ int ssl3_do_change_cipher_spec(SSL *s) if (s->s3->tmp.key_block == NULL) { + if (s->session == NULL) + { + /* might happen if dtls1_read_bytes() calls this */ + SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY); + return (0); + } + s->session->cipher=s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) return(0); } @@ -1314,13 +1366,13 @@ int ssl3_do_change_cipher_spec(SSL *s) return(1); } -void ssl3_send_alert(SSL *s, int level, int desc) +int ssl3_send_alert(SSL *s, int level, int desc) { /* Map tls/ssl alert value to correct one */ desc=s->method->ssl3_enc->alert_value(desc); if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have protocol_version alerts */ - if (desc < 0) return; + if (desc < 0) return -1; /* If a fatal one, remove from cache */ if ((level == 2) && (s->session != NULL)) SSL_CTX_remove_session(s->ctx,s->session); @@ -1329,9 +1381,10 @@ void ssl3_send_alert(SSL *s, int level, int desc) s->s3->send_alert[0]=level; s->s3->send_alert[1]=desc; if (s->s3->wbuf.left == 0) /* data still being written out? */ - s->method->ssl_dispatch_alert(s); + return s->method->ssl_dispatch_alert(s); /* else data is still being written out, we will get written * some time in the future */ + return -1; } int ssl3_dispatch_alert(SSL *s)