X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs23_clnt.c;h=fa20c1c3bd7b4c5f02cfb1a35e97a88580476876;hp=78c39d9af558bf1137a52017f33aad913cc4cccc;hb=4082fea81c150e9f2643819148d275e500f309a3;hpb=67c8e7f41486934b6809673b6d836d38eaf2383b diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c index 78c39d9af5..fa20c1c3bd 100644 --- a/ssl/s23_clnt.c +++ b/ssl/s23_clnt.c @@ -129,6 +129,10 @@ 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 if (ver == TLS1_2_VERSION) + return(TLSv1_2_client_method()); else return(NULL); } @@ -250,33 +254,102 @@ 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; + } + +/* Fill a ClientRandom or ServerRandom field of length len. Returns <= 0 + * on failure, 1 on success. */ +int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len) + { + int send_time = 0; + if (len < 4) + return 0; + if (server) + send_time = (s->mode & SSL_MODE_SEND_SERVERHELLO_TIME) != 0; + else + send_time = (s->mode & SSL_MODE_SEND_CLIENTHELLO_TIME) != 0; + if (send_time) + { + unsigned long Time = time(NULL); + unsigned char *p = result; + l2n(Time, p); + return RAND_pseudo_bytes(p, len-4); + } + else + return RAND_pseudo_bytes(result, len); + } static int ssl23_client_hello(SSL *s) { unsigned char *buf; unsigned char *p,*d; - int i,j,ch_len; - unsigned long Time,l; + int i,ch_len; + unsigned long l; int ssl2_compat; int version = 0, version_major, version_minor; +#ifndef OPENSSL_NO_COMP + int j; SSL_COMP *comp; +#endif int ret; + unsigned long mask, options = s->options; + + ssl2_compat = (options & SSL_OP_NO_SSLv2) ? 0 : 1; + + if (ssl2_compat && ssl23_no_ssl2_ciphers(s)) + ssl2_compat = 0; + + /* + * SSL_OP_NO_X disables all protocols above X *if* there are + * some protocols below X enabled. This is required in order + * to maintain "version capability" vector contiguous. So + * that if application wants to disable TLS1.0 in favour of + * TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the + * answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2. + */ + mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1 +#if !defined(OPENSSL_NO_SSL3) + |SSL_OP_NO_SSLv3 +#endif +#if !defined(OPENSSL_NO_SSL2) + |(ssl2_compat?SSL_OP_NO_SSLv2:0) +#endif + ; +#if !defined(OPENSSL_NO_TLS1_2_CLIENT) + version = TLS1_2_VERSION; - ssl2_compat = (s->options & SSL_OP_NO_SSLv2) ? 0 : 1; - - if (!(s->options & SSL_OP_NO_TLSv1)) - { + if ((options & SSL_OP_NO_TLSv1_2) && (options & mask) != mask) + version = TLS1_1_VERSION; +#else + version = TLS1_1_VERSION; +#endif + mask &= ~SSL_OP_NO_TLSv1_1; + if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask) version = TLS1_VERSION; - } - else if (!(s->options & SSL_OP_NO_SSLv3)) - { + mask &= ~SSL_OP_NO_TLSv1; +#if !defined(OPENSSL_NO_SSL3) + if ((options & SSL_OP_NO_TLSv1) && (options & mask) != mask) version = SSL3_VERSION; - } - else if (!(s->options & SSL_OP_NO_SSLv2)) - { + mask &= ~SSL_OP_NO_SSLv3; +#endif +#if !defined(OPENSSL_NO_SSL2) + if ((options & SSL_OP_NO_SSLv3) && (options & mask) != mask) version = SSL2_VERSION; - } +#endif +#ifndef OPENSSL_NO_TLSEXT if (version != SSL2_VERSION) { /* have to disable SSL 2.0 compatibility if we need TLS extensions */ @@ -285,12 +358,16 @@ static int ssl23_client_hello(SSL *s) 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 + if (s->ctx->custom_cli_ext_records_count != 0) + ssl2_compat = 0; + if (s->ctx->cli_supp_data_records_count != 0) + ssl2_compat = 0; } +#endif buf=(unsigned char *)s->init_buf->data; if (s->state == SSL23_ST_CW_CLNT_HELLO_A) @@ -304,16 +381,38 @@ static int ssl23_client_hello(SSL *s) #endif p=s->s3->client_random; - Time=(unsigned long)time(NULL); /* Time */ - l2n(Time,p); - if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) + if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0) return -1; - if (version == TLS1_VERSION) + if (version == TLS1_2_VERSION) + { + version_major = TLS1_2_VERSION_MAJOR; + version_minor = TLS1_2_VERSION_MINOR; + } + else if (tls1_suiteb(s)) + { + SSLerr(SSL_F_SSL23_CLIENT_HELLO, + SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE); + return -1; + } + else 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; } +#ifdef OPENSSL_FIPS + else if(FIPS_mode()) + { + SSLerr(SSL_F_SSL23_CLIENT_HELLO, + SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); + return -1; + } +#endif else if (version == SSL3_VERSION) { version_major = SSL3_VERSION_MAJOR; @@ -367,6 +466,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 @@ -413,6 +516,15 @@ static int ssl23_client_hello(SSL *s) SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE); return -1; } +#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH + /* Some servers hang if client hello > 256 bytes + * as hack workaround chop number of supported ciphers + * to keep it well below this if we use TLS v1.2 + */ + if (TLS1_get_version(s) >= TLS1_2_VERSION + && i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH) + i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1; +#endif s2n(i,p); p+=i; @@ -467,8 +579,13 @@ static int ssl23_client_hello(SSL *s) d=buf; *(d++) = SSL3_RT_HANDSHAKE; *(d++) = version_major; - *(d++) = version_minor; /* arguably we should send the *lowest* suported version here - * (indicating, e.g., TLS 1.0 in "SSL 3.0 format") */ + /* Some servers hang if we use long client hellos + * and a record number > TLS 1.0. + */ + if (TLS1_get_client_version(s) > TLS1_VERSION) + *(d++) = 1; + else + *(d++) = version_minor; s2n((int)l,d); /* number of bytes to write */ @@ -492,7 +609,10 @@ static int ssl23_client_hello(SSL *s) if (ssl2_compat) s->msg_callback(1, SSL2_VERSION, 0, s->init_buf->data+2, ret-2, s, s->msg_callback_arg); else + { + s->msg_callback(1, version, SSL3_RT_HEADER, s->init_buf->data, 5, s, s->msg_callback_arg); s->msg_callback(1, version, SSL3_RT_HANDSHAKE, s->init_buf->data+5, ret-5, s, s->msg_callback_arg); + } } return ret; @@ -543,6 +663,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; @@ -580,7 +704,7 @@ static int ssl23_get_server_hello(SSL *s) #endif } else if (p[1] == SSL3_VERSION_MAJOR && - (p[2] == SSL3_VERSION_MINOR || p[2] == TLS1_VERSION_MINOR) && + p[2] <= TLS1_2_VERSION_MINOR && ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) || (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2))) { @@ -589,6 +713,14 @@ static int ssl23_get_server_hello(SSL *s) if ((p[2] == SSL3_VERSION_MINOR) && !(s->options & SSL_OP_NO_SSLv3)) { +#ifdef OPENSSL_FIPS + if(FIPS_mode()) + { + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, + SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); + goto err; + } +#endif s->version=SSL3_VERSION; s->method=SSLv3_client_method(); } @@ -598,6 +730,18 @@ 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 if ((p[2] == TLS1_2_VERSION_MINOR) && + !(s->options & SSL_OP_NO_TLSv1_2)) + { + s->version=TLS1_2_VERSION; + s->method=TLSv1_2_client_method(); + } else { SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); @@ -624,7 +768,10 @@ static int ssl23_get_server_hello(SSL *s) } if (s->msg_callback) + { + s->msg_callback(0, s->version, SSL3_RT_HEADER, p, 5, s, s->msg_callback_arg); 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]); @@ -640,6 +787,9 @@ static int ssl23_get_server_hello(SSL *s) * 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;