X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs23_clnt.c;h=47f938981790d6959f7cc13ca01e765dd641e938;hp=3bb5adfa480dba6bfd8da2abdcd8ce8b5c364ce8;hb=5e374d2ee85992523a3eafd7dfa8095e51b1a9a0;hpb=f1fd4544a3747682010ed89ac908713fe90b8304 diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c index 3bb5adfa48..47f9389817 100644 --- a/ssl/s23_clnt.c +++ b/ssl/s23_clnt.c @@ -129,6 +129,8 @@ static const SSL_METHOD *ssl23_get_client_method(int ver) return(SSLv3_client_method()); else if (ver == TLS1_VERSION) return(TLSv1_client_method()); + else if (ver == TLS1_1_VERSION) + return(TLSv1_1_client_method()); else return(NULL); } @@ -250,21 +252,45 @@ end: return(ret); } +static int ssl23_no_ssl2_ciphers(SSL *s) + { + SSL_CIPHER *cipher; + STACK_OF(SSL_CIPHER) *ciphers; + int i; + ciphers = SSL_get_ciphers(s); + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) + { + cipher = sk_SSL_CIPHER_value(ciphers, i); + if (cipher->algorithm_ssl == SSL_SSLV2) + return 0; + } + return 1; + } static int ssl23_client_hello(SSL *s) { unsigned char *buf; unsigned char *p,*d; - int i,j,ch_len; + int i,ch_len; unsigned long Time,l; int ssl2_compat; int version = 0, version_major, version_minor; +#ifndef OPENSSL_NO_COMP + int j; SSL_COMP *comp; +#endif int ret; ssl2_compat = (s->options & SSL_OP_NO_SSLv2) ? 0 : 1; - if (!(s->options & SSL_OP_NO_TLSv1)) + if (ssl2_compat && ssl23_no_ssl2_ciphers(s)) + ssl2_compat = 0; + + if (!(s->options & SSL_OP_NO_TLSv1_1)) + { + version = TLS1_1_VERSION; + } + else if (!(s->options & SSL_OP_NO_TLSv1)) { version = TLS1_VERSION; } @@ -276,6 +302,21 @@ static int ssl23_client_hello(SSL *s) { version = SSL2_VERSION; } +#ifndef OPENSSL_NO_TLSEXT + if (version != SSL2_VERSION) + { + /* have to disable SSL 2.0 compatibility if we need TLS extensions */ + + if (s->tlsext_hostname != NULL) + ssl2_compat = 0; + if (s->tlsext_status_type != -1) + ssl2_compat = 0; +#ifdef TLSEXT_TYPE_opaque_prf_input + if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL) + ssl2_compat = 0; +#endif + } +#endif buf=(unsigned char *)s->init_buf->data; if (s->state == SSL23_ST_CW_CLNT_HELLO_A) @@ -294,7 +335,12 @@ static int ssl23_client_hello(SSL *s) if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) return -1; - if (version == TLS1_VERSION) + if (version == TLS1_1_VERSION) + { + version_major = TLS1_1_VERSION_MAJOR; + version_minor = TLS1_1_VERSION_MINOR; + } + else if (version == TLS1_VERSION) { version_major = TLS1_VERSION_MAJOR; version_minor = TLS1_VERSION_MINOR; @@ -352,6 +398,10 @@ static int ssl23_client_hello(SSL *s) ch_len=SSL2_MAX_CHALLENGE_LENGTH; /* write out sslv2 challenge */ + /* Note that ch_len must be <= SSL3_RANDOM_SIZE (32), + because it is one of SSL2_MAX_CHALLENGE_LENGTH (32) + or SSL2_MAX_CHALLENGE_LENGTH (16), but leave the + check in for futurproofing */ if (SSL3_RANDOM_SIZE < ch_len) i=SSL3_RANDOM_SIZE; else @@ -420,9 +470,15 @@ static int ssl23_client_hello(SSL *s) *(p++)=0; /* Add the NULL method */ #ifndef OPENSSL_NO_TLSEXT + /* TLS extensions*/ + if (ssl_prepare_clienthello_tlsext(s) <= 0) + { + SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); + return -1; + } if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) { - SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); return -1; } #endif @@ -522,6 +578,10 @@ static int ssl23_get_server_hello(SSL *s) ch_len=SSL2_MAX_CHALLENGE_LENGTH; /* write out sslv2 challenge */ + /* Note that ch_len must be <= SSL3_RANDOM_SIZE (32), because + it is one of SSL2_MAX_CHALLENGE_LENGTH (32) or + SSL2_MAX_CHALLENGE_LENGTH (16), but leave the check in for + futurproofing */ i=(SSL3_RANDOM_SIZE < ch_len) ?SSL3_RANDOM_SIZE:ch_len; s->s2->challenge_length=i; @@ -542,7 +602,7 @@ static int ssl23_get_server_hello(SSL *s) /* use special padding (SSL 3.0 draft/RFC 2246, App. E.2) */ s->s2->ssl2_rollback=1; - /* setup the 5 bytes we have read so we get them from + /* setup the 7 bytes we have read so we get them from * the sslv2 buffer */ s->rstate=SSL_ST_READ_HEADER; s->packet_length=n; @@ -558,27 +618,12 @@ static int ssl23_get_server_hello(SSL *s) s->handshake_func=s->method->ssl_connect; #endif } - else if ((p[0] == SSL3_RT_HANDSHAKE) && - (p[1] == SSL3_VERSION_MAJOR) && - ((p[2] == SSL3_VERSION_MINOR) || - (p[2] == TLS1_VERSION_MINOR)) && - (p[5] == SSL3_MT_SERVER_HELLO)) + else if (p[1] == SSL3_VERSION_MAJOR && + p[2] <= TLS1_1_VERSION_MINOR && + ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) || + (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2))) { - /* we have sslv3 or tls1 */ - - if (!ssl_init_wbio_buffer(s,1)) goto err; - - /* we are in this state */ - s->state=SSL3_ST_CR_SRVR_HELLO_A; - - /* put the 5 bytes we have read into the input buffer - * for SSLv3 */ - s->rstate=SSL_ST_READ_HEADER; - s->packet_length=n; - s->packet= &(s->s3->rbuf.buf[0]); - memcpy(s->packet,buf,n); - s->s3->rbuf.left=n; - s->s3->rbuf.offset=0; + /* we have sslv3 or tls1 (server hello or alert) */ if ((p[2] == SSL3_VERSION_MINOR) && !(s->options & SSL_OP_NO_SSLv3)) @@ -592,40 +637,63 @@ static int ssl23_get_server_hello(SSL *s) s->version=TLS1_VERSION; s->method=TLSv1_client_method(); } + else if ((p[2] == TLS1_1_VERSION_MINOR) && + !(s->options & SSL_OP_NO_TLSv1_1)) + { + s->version=TLS1_1_VERSION; + s->method=TLSv1_1_client_method(); + } else { SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); goto err; } - - s->handshake_func=s->method->ssl_connect; - } - else if ((p[0] == SSL3_RT_ALERT) && - (p[1] == SSL3_VERSION_MAJOR) && - ((p[2] == SSL3_VERSION_MINOR) || - (p[2] == TLS1_VERSION_MINOR)) && - (p[3] == 0) && - (p[4] == 2)) - { - void (*cb)(const SSL *ssl,int type,int val)=NULL; - int j; - - /* An alert */ - if (s->info_callback != NULL) - cb=s->info_callback; - else if (s->ctx->info_callback != NULL) - cb=s->ctx->info_callback; - - i=p[5]; - if (cb != NULL) + + if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING) { - j=(i<<8)|p[6]; - cb(s,SSL_CB_READ_ALERT,j); + /* fatal alert */ + + void (*cb)(const SSL *ssl,int type,int val)=NULL; + int j; + + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; + + i=p[5]; + if (cb != NULL) + { + j=(i<<8)|p[6]; + cb(s,SSL_CB_READ_ALERT,j); + } + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_ALERT, p+5, 2, s, s->msg_callback_arg); + + s->rwstate=SSL_NOTHING; + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]); + goto err; } - s->rwstate=SSL_NOTHING; - SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]); - goto err; + if (!ssl_init_wbio_buffer(s,1)) goto err; + + /* we are in this state */ + s->state=SSL3_ST_CR_SRVR_HELLO_A; + + /* put the 7 bytes we have read into the input buffer + * for SSLv3 */ + s->rstate=SSL_ST_READ_HEADER; + s->packet_length=n; + if (s->s3->rbuf.buf == NULL) + if (!ssl3_setup_read_buffer(s)) + goto err; + s->packet= &(s->s3->rbuf.buf[0]); + memcpy(s->packet,buf,n); + s->s3->rbuf.left=n; + s->s3->rbuf.offset=0; + + s->handshake_func=s->method->ssl_connect; } else { @@ -639,9 +707,7 @@ static int ssl23_get_server_hello(SSL *s) if (!ssl_get_new_session(s,0)) goto err; - s->first_packet=1; return(SSL_connect(s)); err: return(-1); } -