X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs23_clnt.c;h=42c3d6861f9a4eeb285fc402cd3c74d3e3254066;hp=47f938981790d6959f7cc13ca01e765dd641e938;hb=62f45cc27d07187b59551e4fad3db4e52ea73f2c;hpb=5e374d2ee85992523a3eafd7dfa8095e51b1a9a0 diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c index 47f9389817..42c3d6861f 100644 --- a/ssl/s23_clnt.c +++ b/ssl/s23_clnt.c @@ -125,12 +125,16 @@ static const SSL_METHOD *ssl23_get_client_method(int ver) if (ver == SSL2_VERSION) return(SSLv2_client_method()); #endif +#ifndef OPENSSL_NO_SSL3 if (ver == SSL3_VERSION) return(SSLv3_client_method()); - else if (ver == TLS1_VERSION) +#endif + 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); } @@ -257,51 +261,102 @@ static int ssl23_no_ssl2_ciphers(SSL *s) SSL_CIPHER *cipher; STACK_OF(SSL_CIPHER) *ciphers; int i; + ssl_set_client_disabled(s); ciphers = SSL_get_ciphers(s); for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { cipher = sk_SSL_CIPHER_value(ciphers, i); + if (ssl_cipher_disabled(s, cipher, SSL_SECOP_CIPHER_SUPPORTED)) + continue; 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 = (unsigned long)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,ch_len; - unsigned long Time,l; + unsigned long l; int ssl2_compat; int version = 0, version_major, version_minor; + int al = 0; #ifndef OPENSSL_NO_COMP int j; SSL_COMP *comp; #endif int ret; + unsigned long mask, options = s->options; - ssl2_compat = (s->options & SSL_OP_NO_SSLv2) ? 0 : 1; + ssl2_compat = (options & SSL_OP_NO_SSLv2) ? 0 : 1; + if (ssl2_compat && !ssl_security(s, SSL_SECOP_SSL2_COMPAT, 0, 0, NULL)) + ssl2_compat = 0; if (ssl2_compat && ssl23_no_ssl2_ciphers(s)) ssl2_compat = 0; - if (!(s->options & SSL_OP_NO_TLSv1_1)) - { + /* + * 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; + + if ((options & SSL_OP_NO_TLSv1_2) && (options & mask) != mask) version = TLS1_1_VERSION; - } - else if (!(s->options & SSL_OP_NO_TLSv1)) - { +#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) { @@ -315,6 +370,8 @@ static int ssl23_client_hello(SSL *s) if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL) ssl2_compat = 0; #endif + if (s->cert->cli_ext.meths_count != 0) + ssl2_compat = 0; } #endif @@ -330,12 +387,21 @@ 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_1_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; @@ -345,6 +411,14 @@ static int ssl23_client_hello(SSL *s) 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; @@ -448,6 +522,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; @@ -455,8 +538,7 @@ static int ssl23_client_hello(SSL *s) #ifdef OPENSSL_NO_COMP *(p++)=1; #else - if ((s->options & SSL_OP_NO_COMPRESSION) - || !s->ctx->comp_methods) + if (!ssl_allow_compression(s) || !s->ctx->comp_methods) j=0; else j=sk_SSL_COMP_num(s->ctx->comp_methods); @@ -476,8 +558,9 @@ static int ssl23_client_hello(SSL *s) 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) + if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, &al)) == NULL) { + ssl3_send_alert(s,SSL3_AL_FATAL,al); SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); return -1; } @@ -502,8 +585,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 */ @@ -527,7 +615,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; @@ -619,19 +710,30 @@ static int ssl23_get_server_hello(SSL *s) #endif } else if (p[1] == SSL3_VERSION_MAJOR && - p[2] <= TLS1_1_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))) { /* we have sslv3 or tls1 (server hello or alert) */ +#ifndef OPENSSL_NO_SSL3 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(); } - else if ((p[2] == TLS1_VERSION_MINOR) && + else +#endif + if ((p[2] == TLS1_VERSION_MINOR) && !(s->options & SSL_OP_NO_TLSv1)) { s->version=TLS1_VERSION; @@ -643,12 +745,27 @@ static int ssl23_get_server_hello(SSL *s) 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); goto err; } + /* ensure that TLS_MAX_VERSION is up-to-date */ + OPENSSL_assert(s->version <= TLS_MAX_VERSION); + + if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) + { + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_VERSION_TOO_LOW); + goto err; + } + if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING) { /* fatal alert */ @@ -669,7 +786,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]);