X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=ssl%2Fs3_pkt.c;h=9ab76604a64534192a45569a6f90257487b2135a;hb=9a22ce66c94294ee56d99870a47022ae0e067203;hp=d76c5f9e597b47b03bfd3a9d3173848091e41a33;hpb=745c70e5658d176a87965526d8839a7da79a6240;p=oweals%2Fopenssl.git diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index d76c5f9e59..9ab76604a6 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -704,18 +704,19 @@ static int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, * Application data protocol * none of our business */ -int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len) +int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) { - int al,i,j,n,ret; + int al,i,j,ret; + unsigned int n; SSL3_RECORD *rr; void (*cb)()=NULL; - BIO *bio; if (s->s3->rbuf.buf == NULL) /* Not initialized yet */ if (!ssl3_setup_buffers(s)) return(-1); - if ((type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type) + if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type) || + (peek && (type != SSL3_RT_APPLICATION_DATA))) { SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_INTERNAL_ERROR); return -1; @@ -726,7 +727,9 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len) { unsigned char *src = s->s3->handshake_fragment; unsigned char *dst = buf; + unsigned int k; + /* peek == 0 */ n = 0; while ((len > 0) && (s->s3->handshake_fragment_len > 0)) { @@ -735,8 +738,8 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len) n++; } /* move any remaining fragment bytes: */ - for (i = 0; i < s->s3->handshake_fragment_len; i++) - s->s3->handshake_fragment[i] = *src++; + for (k = 0; k < s->s3->handshake_fragment_len; k++) + s->s3->handshake_fragment[k] = *src++; return n; } @@ -762,7 +765,7 @@ start: * s->s3->rrec.length, - number of bytes. */ rr = &(s->s3->rrec); - /* get new packet */ + /* get new packet if necessary */ if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) { ret=ssl3_get_record(s); @@ -780,7 +783,8 @@ start: goto err; } - /* If the other end has shutdown, throw anything we read away */ + /* If the other end has shut down, throw anything we read away + * (even in 'peek' mode) */ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { rr->length=0; @@ -804,17 +808,20 @@ start: if (len <= 0) return(len); if ((unsigned int)len > rr->length) - n=rr->length; + n = rr->length; else - n=len; + n = (unsigned int)len; - memcpy(buf,&(rr->data[rr->off]),(unsigned int)n); - rr->length-=n; - rr->off+=n; - if (rr->length == 0) + memcpy(buf,&(rr->data[rr->off]),n); + if (!peek) { - s->rstate=SSL_ST_READ_HEADER; - rr->off=0; + rr->length-=n; + rr->off+=n; + if (rr->length == 0) + { + s->rstate=SSL_ST_READ_HEADER; + rr->off=0; + } } return(n); } @@ -827,9 +834,9 @@ start: * fill that so that we can process the data at a fixed place. */ { - int dest_maxlen = 0; - unsigned char *dest; - int *dest_len; + unsigned int dest_maxlen = 0; + unsigned char *dest = NULL; + unsigned int *dest_len = NULL; if (rr->type == SSL3_RT_HANDSHAKE) { @@ -890,13 +897,30 @@ start: ssl3_renegotiate(s); if (ssl3_renegotiate_check(s)) { - n=s->handshake_func(s); - if (n < 0) return(n); - if (n == 0) + 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); } + + if (!(s->mode & SSL_MODE_AUTO_RETRY)) + { + if (s->s3->rbuf.left == 0) /* no read-ahead left? */ + { + BIO *bio; + /* In the case where we try to read application data, + * but we trigger an SSL handshake, we return -1 with + * the retry option set. Otherwise renegotiation may + * cause nasty problems in the blocking world */ + s->rwstate=SSL_READING; + bio=SSL_get_rbio(s); + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); + return(-1); + } + } } } /* we either finished a handshake or ignored the request, @@ -906,8 +930,8 @@ start: if (s->s3->alert_fragment_len >= 2) { - i = s->s3->alert_fragment[0]; - n = s->s3->alert_fragment[1]; + int alert_level = s->s3->alert_fragment[0]; + int alert_descr = s->s3->alert_fragment[1]; s->s3->alert_fragment_len = 0; @@ -918,28 +942,27 @@ start: if (cb != NULL) { - j=(i<<8)|n; - cb(s,SSL_CB_READ_ALERT,j); + j = (alert_level << 8) | alert_descr; + cb(s, SSL_CB_READ_ALERT, j); } - if (i == 1) /* warning */ + if (alert_level == 1) /* warning */ { - s->s3->warn_alert=n; - if (n == SSL_AD_CLOSE_NOTIFY) + s->s3->warn_alert = alert_descr; + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { - s->shutdown|=SSL_RECEIVED_SHUTDOWN; + s->shutdown |= SSL_RECEIVED_SHUTDOWN; return(0); } } - else if (i == 2) /* fatal */ + else if (alert_level == 2) /* fatal */ { 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); + s->s3->fatal_alert = alert_descr; + SSLerr(SSL_F_SSL3_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr); + BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr); ERR_add_error_data(2,"SSL alert number ",tmp); s->shutdown|=SSL_RECEIVED_SHUTDOWN; SSL_CTX_remove_session(s->ctx,s->session); @@ -988,30 +1011,42 @@ start: if (((s->state&SSL_ST_MASK) == SSL_ST_OK) && !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { +#if 0 /* worked only because C operator preferences are not as expected (and + * because this is not really needed for clients except for detecting + * protocol violations): */ s->state=SSL_ST_BEFORE|(s->server) ?SSL_ST_ACCEPT :SSL_ST_CONNECT; +#else + s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; +#endif s->new_session=1; } - n=s->handshake_func(s); - if (n < 0) return(n); - if (n == 0) + 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); } - /* 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); + if (!(s->mode & SSL_MODE_AUTO_RETRY)) + { + if (s->s3->rbuf.left == 0) /* no read-ahead left? */ + { + BIO *bio; + /* In the case where we try to read application data, + * but we trigger an SSL handshake, we return -1 with + * the retry option set. Otherwise renegotiation may + * cause nasty problems in the blocking world */ + s->rwstate=SSL_READING; + bio=SSL_get_rbio(s); + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); + return(-1); + } + } + goto start; } switch (rr->type) @@ -1041,7 +1076,7 @@ start: * but have application data. If the library was * running inside ssl3_read() (i.e. in_read_app_data * is set) and it makes sense to read application data - * at this point (session renegotation not yet started), + * at this point (session renegotiation not yet started), * we will indulge it. */ if (s->s3->in_read_app_data && @@ -1117,26 +1152,6 @@ static int do_change_cipher_spec(SSL *s) return(1); } -/* send s->init_buf in records of type 'type' */ -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 < 0) return(-1); - if (type == SSL3_RT_HANDSHAKE) - /* should not be done for 'Hello Request's, but in that case - * we'll ignore the result anyway */ - ssl3_finish_mac(s,&s->init_buf->data[s->init_off],ret); - - if (ret == s->init_num) - 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 */