diff options
Diffstat (limited to 'crypto/openssl/ssl/s3_pkt.c')
-rw-r--r-- | crypto/openssl/ssl/s3_pkt.c | 1041 |
1 files changed, 0 insertions, 1041 deletions
diff --git a/crypto/openssl/ssl/s3_pkt.c b/crypto/openssl/ssl/s3_pkt.c deleted file mode 100644 index 7893d03123df3..0000000000000 --- a/crypto/openssl/ssl/s3_pkt.c +++ /dev/null @@ -1,1041 +0,0 @@ -/* ssl/s3_pkt.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#include <stdio.h> -#include <errno.h> -#define USE_SOCKETS -#include <openssl/evp.h> -#include <openssl/buffer.h> -#include "ssl_locl.h" - -static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, - unsigned int len); -static int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, - unsigned int len); -static int ssl3_get_record(SSL *s); -static int do_compress(SSL *ssl); -static int do_uncompress(SSL *ssl); -static int do_change_cipher_spec(SSL *ssl); -static int ssl3_read_n(SSL *s, int n, int max, int extend) - { - int i,off,newb; - - /* if there is stuff still in the buffer from a previous read, - * and there is more than we want, take some. */ - if (s->s3->rbuf.left >= (int)n) - { - if (extend) - s->packet_length+=n; - else - { - s->packet= &(s->s3->rbuf.buf[s->s3->rbuf.offset]); - s->packet_length=n; - } - s->s3->rbuf.left-=n; - s->s3->rbuf.offset+=n; - return(n); - } - - /* else we need to read more data */ - if (!s->read_ahead) max=n; - if (max > SSL3_RT_MAX_PACKET_SIZE) - max=SSL3_RT_MAX_PACKET_SIZE; - - /* First check if there is some left or we want to extend */ - off=0; - if ( (s->s3->rbuf.left != 0) || - ((s->packet_length != 0) && extend)) - { - newb=s->s3->rbuf.left; - if (extend) - { - /* Copy bytes back to the front of the buffer - * Take the bytes already pointed to by 'packet' - * and take the extra ones on the end. */ - off=s->packet_length; - if (s->packet != s->s3->rbuf.buf) - memcpy(s->s3->rbuf.buf,s->packet,newb+off); - } - else if (s->s3->rbuf.offset != 0) - { /* so the data is not at the start of the buffer */ - memcpy(s->s3->rbuf.buf, - &(s->s3->rbuf.buf[s->s3->rbuf.offset]),newb); - s->s3->rbuf.offset=0; - } - - s->s3->rbuf.left=0; - } - else - newb=0; - - /* So we now have 'newb' bytes at the front of - * s->s3->rbuf.buf and need to read some more in on the end - * We start reading into the buffer at 's->s3->rbuf.offset' - */ - s->packet=s->s3->rbuf.buf; - - while (newb < n) - { - clear_sys_error(); - if (s->rbio != NULL) - { - s->rwstate=SSL_READING; - i=BIO_read(s->rbio, - (char *)&(s->s3->rbuf.buf[off+newb]), - max-newb); - } - else - { - SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET); - i= -1; - } - - if (i <= 0) - { - s->s3->rbuf.left+=newb; - return(i); - } - newb+=i; - } - - /* record used data read */ - if (newb > n) - { - s->s3->rbuf.offset=n+off; - s->s3->rbuf.left=newb-n; - } - else - { - s->s3->rbuf.offset=0; - s->s3->rbuf.left=0; - } - - if (extend) - s->packet_length+=n; - else - s->packet_length+=n; - return(n); - } - -/* Call this to get a new input record. - * It will return <= 0 if more data is needed, normally due to an error - * or non-blocking IO. - * When it finishes, one packet has been decoded and can be found in - * ssl->s3->rrec.type - is the type of record - * ssl->s3->rrec.data, - data - * ssl->s3->rrec.length, - number of bytes - */ -static int ssl3_get_record(SSL *s) - { - int ssl_major,ssl_minor,al; - int n,i,ret= -1; - SSL3_BUFFER *rb; - SSL3_RECORD *rr; - SSL_SESSION *sess; - unsigned char *p; - unsigned char md[EVP_MAX_MD_SIZE]; - short version; - unsigned int mac_size; - int clear=0,extra; - - rr= &(s->s3->rrec); - rb= &(s->s3->rbuf); - sess=s->session; - - if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) - extra=SSL3_RT_MAX_EXTRA; - else - extra=0; - -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, - SSL3_RT_MAX_PACKET_SIZE,0); - if (n <= 0) return(n); /* error or non-blocking */ - s->rstate=SSL_ST_READ_BODY; - - p=s->packet; - - /* Pull apart the header into the SSL3_RECORD */ - rr->type= *(p++); - ssl_major= *(p++); - ssl_minor= *(p++); - version=(ssl_major<<8)|ssl_minor; - n2s(p,rr->length); - - /* Lets check version */ - if (s->first_packet) - { - s->first_packet=0; - } - else - { - if (version != s->version) - { - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); - /* Send back error using their - * version number :-) */ - s->version=version; - al=SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - } - - if ((version>>8) != SSL3_VERSION_MAJOR) - { - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); - goto err; - } - - if (rr->length > - (unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) - { - al=SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG); - goto f_err; - } - - s->rstate=SSL_ST_READ_BODY; - } - - /* get and decode the data */ - if (s->rstate == SSL_ST_READ_BODY) - { - if (rr->length > (s->packet_length-SSL3_RT_HEADER_LENGTH)) - { - i=rr->length; - /*-(s->packet_length-SSL3_RT_HEADER_LENGTH); */ - n=ssl3_read_n(s,i,i,1); - if (n <= 0) return(n); /* error or non-blocking io */ - } - s->rstate=SSL_ST_READ_HEADER; - } - - /* At this point, we have the data in s->packet and there should be - * s->packet_length bytes, we must not 'overrun' this buffer :-) - * One of the following functions will copy the data from the - * s->packet buffer */ - - rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]); - - /* ok, we can now read from 's->packet' data into 'rr' - * rr->input points at rr->length bytes, which - * need to be copied into rr->data by either - * the decryption or by the decompression - * When the data is 'copied' into the rr->data buffer, - * rr->input will be pointed at the new buffer */ - - /* Set the state for the following operations */ - s->rstate=SSL_ST_READ_HEADER; - - /* We now have - encrypted [ MAC [ compressed [ plain ] ] ] - * rr->length bytes of encrypted compressed stuff. */ - - /* check is not needed I belive */ - if (rr->length > (unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) - { - al=SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG); - goto f_err; - } - - /* decrypt in place in 'rr->input' */ - rr->data=rr->input; - - if (!s->method->ssl3_enc->enc(s,0)) - { - al=SSL_AD_DECRYPT_ERROR; - goto f_err; - } -#ifdef TLS_DEBUG -printf("dec %d\n",rr->length); -{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); } -printf("\n"); -#endif - /* r->length is now the compressed data plus mac */ - if ( (sess == NULL) || - (s->enc_read_ctx == NULL) || - (s->read_hash == NULL)) - clear=1; - - if (!clear) - { - mac_size=EVP_MD_size(s->read_hash); - - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) - { - al=SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); - goto f_err; - } - /* check MAC for rr->input' */ - if (rr->length < mac_size) - { - al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - rr->length-=mac_size; - i=s->method->ssl3_enc->mac(s,md,0); - if (memcmp(md,&(rr->data[rr->length]),mac_size) != 0) - { - al=SSL_AD_BAD_RECORD_MAC; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_MAC_DECODE); - ret= -1; - goto f_err; - } - } - - /* r->length is now just compressed */ - if (s->expand != NULL) - { - if (rr->length > - (unsigned int)SSL3_RT_MAX_COMPRESSED_LENGTH+extra) - { - al=SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG); - goto f_err; - } - if (!do_uncompress(s)) - { - al=SSL_AD_DECOMPRESSION_FAILURE; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION); - goto f_err; - } - } - - if (rr->length > (unsigned int)SSL3_RT_MAX_PLAIN_LENGTH+extra) - { - al=SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG); - goto f_err; - } - - rr->off=0; - /* So at this point the following is true - * ssl->s3->rrec.type is the type of record - * ssl->s3->rrec.length == number of bytes in record - * ssl->s3->rrec.off == offset to first valid byte - * ssl->s3->rrec.data == where to take bytes from, increment - * after use :-). - */ - - /* we have pulled in a full packet so zero things */ - s->packet_length=0; - - /* just read a 0 length packet */ - if (rr->length == 0) goto again; - - return(1); -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); -err: - return(ret); - } - -static int do_uncompress(SSL *ssl) - { - int i; - SSL3_RECORD *rr; - - rr= &(ssl->s3->rrec); - i=COMP_expand_block(ssl->expand,rr->comp, - SSL3_RT_MAX_PLAIN_LENGTH,rr->data,(int)rr->length); - if (i < 0) - return(0); - else - rr->length=i; - rr->data=rr->comp; - - return(1); - } - -static int do_compress(SSL *ssl) - { - int i; - SSL3_RECORD *wr; - - wr= &(ssl->s3->wrec); - i=COMP_compress_block(ssl->compress,wr->data, - SSL3_RT_MAX_COMPRESSED_LENGTH, - wr->input,(int)wr->length); - if (i < 0) - return(0); - else - wr->length=i; - - wr->input=wr->data; - return(1); - } - -/* Call this to write data - * It will return <= 0 if not all data has been sent or non-blocking IO. - */ -int ssl3_write_bytes(SSL *s, int type, const void *_buf, int len) - { - const unsigned char *buf=_buf; - unsigned int tot,n,nw; - int i; - - s->rwstate=SSL_NOTHING; - tot=s->s3->wnum; - s->s3->wnum=0; - - if (SSL_in_init(s) && !s->in_handshake) - { - i=s->handshake_func(s); - if (i < 0) return(i); - if (i == 0) - { - SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); - return(-1); - } - } - - n=(len-tot); - for (;;) - { - if (n > SSL3_RT_MAX_PLAIN_LENGTH) - nw=SSL3_RT_MAX_PLAIN_LENGTH; - else - nw=n; - - i=do_ssl3_write(s,type,&(buf[tot]),nw); - if (i <= 0) - { - s->s3->wnum=tot; - return(i); - } - - if (type == SSL3_RT_HANDSHAKE) - ssl3_finish_mac(s,&(buf[tot]),i); - - if ((i == (int)n) || - (type == SSL3_RT_APPLICATION_DATA && - (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) - { - return(tot+i); - } - - n-=i; - tot+=i; - } - } - -static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, - unsigned int len) - { - unsigned char *p,*plen; - int i,mac_size,clear=0; - SSL3_RECORD *wr; - SSL3_BUFFER *wb; - SSL_SESSION *sess; - - /* first check is there is a SSL3_RECORD still being written - * out. This will happen with non blocking IO */ - if (s->s3->wbuf.left != 0) - return(ssl3_write_pending(s,type,buf,len)); - - /* If we have an alert to send, lets send it */ - if (s->s3->alert_dispatch) - { - i=ssl3_dispatch_alert(s); - if (i <= 0) - return(i); - /* if it went, fall through and send more stuff */ - } - - if (len <= 0) return(len); - - wr= &(s->s3->wrec); - wb= &(s->s3->wbuf); - sess=s->session; - - if ( (sess == NULL) || - (s->enc_write_ctx == NULL) || - (s->write_hash == NULL)) - clear=1; - - if (clear) - mac_size=0; - else - mac_size=EVP_MD_size(s->write_hash); - - p=wb->buf; - - /* write the header */ - *(p++)=type&0xff; - wr->type=type; - - *(p++)=(s->version>>8); - *(p++)=s->version&0xff; - - /* record where we are to write out packet length */ - plen=p; - p+=2; - - /* lets setup the record stuff. */ - wr->data=p; - wr->length=(int)len; - wr->input=(unsigned char *)buf; - - /* we now 'read' from wr->input, wr->length bytes into - * wr->data */ - - /* first we compress */ - if (s->compress != NULL) - { - if (!do_compress(s)) - { - SSLerr(SSL_F_DO_SSL3_WRITE,SSL_R_COMPRESSION_FAILURE); - goto err; - } - } - else - { - memcpy(wr->data,wr->input,wr->length); - wr->input=wr->data; - } - - /* we should still have the output to wr->data and the input - * from wr->input. Length should be wr->length. - * wr->data still points in the wb->buf */ - - if (mac_size != 0) - { - s->method->ssl3_enc->mac(s,&(p[wr->length]),1); - wr->length+=mac_size; - wr->input=p; - wr->data=p; - } - - /* ssl3_enc can only have an error on read */ - s->method->ssl3_enc->enc(s,1); - - /* record length after mac and block padding */ - s2n(wr->length,plen); - - /* we should now have - * wr->data pointing to the encrypted data, which is - * wr->length long */ - wr->type=type; /* not needed but helps for debugging */ - wr->length+=SSL3_RT_HEADER_LENGTH; - - /* Now lets setup wb */ - wb->left=wr->length; - wb->offset=0; - - s->s3->wpend_tot=len; - s->s3->wpend_buf=buf; - s->s3->wpend_type=type; - s->s3->wpend_ret=len; - - /* we now just need to write the buffer */ - return(ssl3_write_pending(s,type,buf,len)); -err: - return(-1); - } - -/* if s->s3->wbuf.left != 0, we need to call this */ -static int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, - unsigned int len) - { - int i; - -/* XXXX */ - if ((s->s3->wpend_tot > (int)len) - || ((s->s3->wpend_buf != buf) && - !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) - || (s->s3->wpend_type != type)) - { - SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY); - return(-1); - } - - for (;;) - { - clear_sys_error(); - if (s->wbio != NULL) - { - s->rwstate=SSL_WRITING; - i=BIO_write(s->wbio, - (char *)&(s->s3->wbuf.buf[s->s3->wbuf.offset]), - (unsigned int)s->s3->wbuf.left); - } - else - { - SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BIO_NOT_SET); - i= -1; - } - if (i == s->s3->wbuf.left) - { - s->s3->wbuf.left=0; - s->rwstate=SSL_NOTHING; - return(s->s3->wpend_ret); - } - else if (i <= 0) - return(i); - s->s3->wbuf.offset+=i; - s->s3->wbuf.left-=i; - } - } - -int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len) - { - int al,i,j,n,ret; - SSL3_RECORD *rr; - void (*cb)()=NULL; - BIO *bio; - - if (s->s3->rbuf.buf == NULL) /* Not initialize yet */ - if (!ssl3_setup_buffers(s)) - return(-1); - - if (!s->in_handshake && SSL_in_init(s)) - { - i=s->handshake_func(s); - if (i < 0) return(i); - if (i == 0) - { - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); - return(-1); - } - } -start: - s->rwstate=SSL_NOTHING; - - /* s->s3->rrec.type - is the type of record - * s->s3->rrec.data, - data - * s->s3->rrec.off, - ofset into 'data' for next read - * s->s3->rrec.length, - number of bytes. */ - rr= &(s->s3->rrec); - - /* get new packet */ - if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) - { - ret=ssl3_get_record(s); - if (ret <= 0) return(ret); - } - - /* we now have a packet which can be read and processed */ - - if (s->s3->change_cipher_spec && (rr->type != SSL3_RT_HANDSHAKE)) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); - goto err; - } - - /* If the other end has shutdown, throw anything we read away */ - if (s->shutdown & SSL_RECEIVED_SHUTDOWN) - { - rr->length=0; - s->rwstate=SSL_NOTHING; - return(0); - } - - /* Check for an incoming 'Client Request' message */ - if ((rr->type == SSL3_RT_HANDSHAKE) && (rr->length == 4) && - (rr->data[0] == SSL3_MT_CLIENT_REQUEST) && - (s->session != NULL) && (s->session->cipher != NULL)) - { - if ((rr->data[1] != 0) || (rr->data[2] != 0) || - (rr->data[3] != 0)) - { - al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CLIENT_REQUEST); - goto err; - } - - if (SSL_is_init_finished(s) && - !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && - !s->s3->renegotiate) - { - ssl3_renegotiate(s); - if (ssl3_renegotiate_check(s)) - { - n=s->handshake_func(s); - if (n < 0) return(n); - if (n == 0) - { - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); - return(-1); - } - } - } - rr->length=0; -/* ZZZ */ goto start; - } - - /* if it is not the type we want, or we have shutdown and want - * the peer shutdown */ - if ((rr->type != type) || (s->shutdown & SSL_SENT_SHUTDOWN)) - { - if (rr->type == SSL3_RT_ALERT) - { - if ((rr->length != 2) || (rr->off != 0)) - { - al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_ALERT_RECORD); - goto f_err; - } - - i=rr->data[0]; - n=rr->data[1]; - - /* clear from buffer */ - rr->length=0; - - if (s->info_callback != NULL) - cb=s->info_callback; - else if (s->ctx->info_callback != NULL) - cb=s->ctx->info_callback; - - if (cb != NULL) - { - j=(i<<8)|n; - cb(s,SSL_CB_READ_ALERT,j); - } - - if (i == 1) - { - s->s3->warn_alert=n; - if (n == SSL_AD_CLOSE_NOTIFY) - { - s->shutdown|=SSL_RECEIVED_SHUTDOWN; - return(0); - } - } - else if (i == 2) - { - char tmp[16]; - - s->rwstate=SSL_NOTHING; - s->s3->fatal_alert=n; - SSLerr(SSL_F_SSL3_READ_BYTES, - SSL_AD_REASON_OFFSET+n); - sprintf(tmp,"%d",n); - ERR_add_error_data(2,"SSL alert number ",tmp); - s->shutdown|=SSL_RECEIVED_SHUTDOWN; - SSL_CTX_remove_session(s->ctx,s->session); - return(0); - } - else - { - al=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE); - goto f_err; - } - - rr->length=0; - goto start; - } - - if (s->shutdown & SSL_SENT_SHUTDOWN) - { - s->rwstate=SSL_NOTHING; - rr->length=0; - return(0); - } - - if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) - { - if ( (rr->length != 1) || (rr->off != 0) || - (rr->data[0] != SSL3_MT_CCS)) - { - i=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); - goto err; - } - - rr->length=0; - s->s3->change_cipher_spec=1; - if (!do_change_cipher_spec(s)) - goto err; - else - goto start; - } - - /* else we have a handshake */ - if ((rr->type == SSL3_RT_HANDSHAKE) && - !s->in_handshake) - { - if (((s->state&SSL_ST_MASK) == SSL_ST_OK) && - !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) - { - s->state=SSL_ST_BEFORE|(s->server) - ?SSL_ST_ACCEPT - :SSL_ST_CONNECT; - s->new_session=1; - } - n=s->handshake_func(s); - if (n < 0) return(n); - if (n == 0) - { - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); - return(-1); - } - - /* In the case where we try to read application data - * the first time, but we trigger an SSL handshake, we - * return -1 with the retry option set. I do this - * otherwise renegotiation can cause nasty problems - * in the non-blocking world */ - - s->rwstate=SSL_READING; - bio=SSL_get_rbio(s); - BIO_clear_retry_flags(bio); - BIO_set_retry_read(bio); - return(-1); - } - - switch (rr->type) - { - default: -#ifndef NO_TLS - /* TLS just ignores unknown message types */ - if (s->version == TLS1_VERSION) - { - goto start; - } -#endif - case SSL3_RT_CHANGE_CIPHER_SPEC: - case SSL3_RT_ALERT: - case SSL3_RT_HANDSHAKE: - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD); - goto f_err; - case SSL3_RT_APPLICATION_DATA: - /* At this point, we were expecting something else, - * but have application data. What we do is set the - * error, and return -1. On the way out, if the - * library was running inside ssl3_read() and it makes - * sense to read application data at this point, we - * will indulge it. This will mostly happen during - * session renegotiation. - */ - if (s->s3->in_read_app_data && - (s->s3->total_renegotiations != 0) && - (( - (s->state & SSL_ST_CONNECT) && - (s->state >= SSL3_ST_CW_CLNT_HELLO_A) && - (s->state <= SSL3_ST_CR_SRVR_HELLO_A) - ) || ( - (s->state & SSL_ST_ACCEPT) && - (s->state <= SSL3_ST_SW_HELLO_REQ_A) && - (s->state >= SSL3_ST_SR_CLNT_HELLO_A) - ) - )) - { - s->s3->in_read_app_data=0; - return(-1); - } - else - { - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD); - goto f_err; - } - } - } - - /* make sure that we are not getting application data when we - * are doing a handshake for the first time */ - if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) && - (s->enc_read_ctx == NULL)) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE); - goto f_err; - } - - if (len <= 0) return(len); - - if ((unsigned int)len > rr->length) - n=rr->length; - else - n=len; - - memcpy(buf,&(rr->data[rr->off]),(unsigned int)n); - rr->length-=n; - rr->off+=n; - if (rr->length <= 0) - { - s->rstate=SSL_ST_READ_HEADER; - rr->off=0; - } - - if (type == SSL3_RT_HANDSHAKE) - ssl3_finish_mac(s,buf,n); - return(n); -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); -err: - return(-1); - } - -static int do_change_cipher_spec(SSL *s) - { - int i; - unsigned char *sender; - int slen; - - if (s->state & SSL_ST_ACCEPT) - i=SSL3_CHANGE_CIPHER_SERVER_READ; - else - i=SSL3_CHANGE_CIPHER_CLIENT_READ; - - if (s->s3->tmp.key_block == NULL) - { - s->session->cipher=s->s3->tmp.new_cipher; - if (!s->method->ssl3_enc->setup_key_block(s)) return(0); - } - - if (!s->method->ssl3_enc->change_cipher_state(s,i)) - return(0); - - /* we have to record the message digest at - * this point so we can get it before we read - * the finished message */ - if (s->state & SSL_ST_CONNECT) - { - sender=s->method->ssl3_enc->server_finished; - slen=s->method->ssl3_enc->server_finished_len; - } - else - { - sender=s->method->ssl3_enc->client_finished; - slen=s->method->ssl3_enc->client_finished_len; - } - - s->method->ssl3_enc->final_finish_mac(s, - &(s->s3->finish_dgst1), - &(s->s3->finish_dgst2), - sender,slen,&(s->s3->tmp.finish_md[0])); - - return(1); - } - -int ssl3_do_write(SSL *s, int type) - { - int ret; - - ret=ssl3_write_bytes(s,type,&s->init_buf->data[s->init_off], - s->init_num); - if (ret == s->init_num) - return(1); - if (ret < 0) return(-1); - s->init_off+=ret; - s->init_num-=ret; - return(0); - } - -void 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 (desc < 0) return; - /* If a fatal one, remove from cache */ - if ((level == 2) && (s->session != NULL)) - SSL_CTX_remove_session(s->ctx,s->session); - - s->s3->alert_dispatch=1; - s->s3->send_alert[0]=level; - s->s3->send_alert[1]=desc; - if (s->s3->wbuf.left == 0) /* data still being written out */ - ssl3_dispatch_alert(s); - /* else data is still being written out, we will get written - * some time in the future */ - } - -int ssl3_dispatch_alert(SSL *s) - { - int i,j; - void (*cb)()=NULL; - - s->s3->alert_dispatch=0; - i=do_ssl3_write(s,SSL3_RT_ALERT,&s->s3->send_alert[0],2); - if (i <= 0) - { - s->s3->alert_dispatch=1; - } - else - { - /* If it is important, send it now. If the message - * does not get sent due to non-blocking IO, we will - * not worry too much. */ - if (s->s3->send_alert[0] == SSL3_AL_FATAL) - (void)BIO_flush(s->wbio); - - if (s->info_callback != NULL) - cb=s->info_callback; - else if (s->ctx->info_callback != NULL) - cb=s->ctx->info_callback; - - if (cb != NULL) - { - j=(s->s3->send_alert[0]<<8)|s->s3->send_alert[1]; - cb(s,SSL_CB_WRITE_ALERT,j); - } - } - return(i); - } - |