X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs23_srvr.c;h=484a1a6e262fb98a60bcfb307227ca4329fb3779;hp=49320647e7033e93ec4da90f34f6a91866c4307f;hb=280b1f1ad12131defcd986676a8fc9717aaa601b;hpb=b35e9050f282c5ea2164bd5b08ed34d03accf45f diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c index 49320647e7..484a1a6e26 100644 --- a/ssl/s23_srvr.c +++ b/ssl/s23_srvr.c @@ -55,19 +55,75 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2006 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 + * are met: + * + * 1. Redistributions of source code must retain the above 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 acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ #include +#include "ssl_locl.h" #include #include #include #include -#include "ssl_locl.h" +#ifdef OPENSSL_FIPS +#include +#endif -static SSL_METHOD *ssl23_get_server_method(int ver); +static const SSL_METHOD *ssl23_get_server_method(int ver); int ssl23_get_client_hello(SSL *s); -static SSL_METHOD *ssl23_get_server_method(int ver) +static const SSL_METHOD *ssl23_get_server_method(int ver) { -#ifndef NO_SSL2 +#ifndef OPENSSL_NO_SSL2 if (ver == SSL2_VERSION) return(SSLv2_server_method()); #endif @@ -75,31 +131,24 @@ static SSL_METHOD *ssl23_get_server_method(int ver) return(SSLv3_server_method()); else if (ver == TLS1_VERSION) return(TLSv1_server_method()); + else if (ver == TLS1_1_VERSION) + return(TLSv1_1_server_method()); + else if (ver == TLS1_2_VERSION) + return(TLSv1_2_server_method()); else return(NULL); } -SSL_METHOD *SSLv23_server_method(void) - { - static int init=1; - static SSL_METHOD SSLv23_server_data; - - if (init) - { - memcpy((char *)&SSLv23_server_data, - (char *)sslv23_base_method(),sizeof(SSL_METHOD)); - SSLv23_server_data.ssl_accept=ssl23_accept; - SSLv23_server_data.get_ssl_method=ssl23_get_server_method; - init=0; - } - return(&SSLv23_server_data); - } +IMPLEMENT_ssl23_meth_func(SSLv23_server_method, + ssl23_accept, + ssl_undefined_function, + ssl23_get_server_method) int ssl23_accept(SSL *s) { BUF_MEM *buf; - unsigned long Time=time(NULL); - void (*cb)()=NULL; + unsigned long Time=(unsigned long)time(NULL); + void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; int new_state,state; @@ -112,8 +161,8 @@ int ssl23_accept(SSL *s) else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; - if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->in_handshake++; + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); for (;;) { @@ -179,9 +228,9 @@ int ssl23_accept(SSL *s) } } end: + s->in_handshake--; if (cb != NULL) cb(s,SSL_CB_ACCEPT_EXIT,ret); - s->in_handshake--; return(ret); } @@ -189,9 +238,10 @@ end: int ssl23_get_client_hello(SSL *s) { char buf_space[11]; /* Request this many bytes in initial read. - * We can detect SSL 3.0/TLS 1.0 Client Hellos only - * when the following is in a single record - * (not guaranteed by protocol specs): + * We can detect SSL 3.0/TLS 1.0 Client Hellos + * ('type == 3') correctly only when the following + * is in a single record, which is not guaranteed by + * the protocol specification: * Byte Content * 0 type \ * 1/2 version > record header @@ -200,13 +250,12 @@ int ssl23_get_client_hello(SSL *s) * 6-8 length > Client Hello message * 9/10 client_version / */ -/* XXX */ char *buf= &(buf_space[0]); - unsigned char *p,*d,*dd; + unsigned char *p,*d,*d_len,*dd; unsigned int i; unsigned int csl,sil,cl; int n=0,j; - int type=0,use_sslv2_strong=0; + int type=0; int v[2]; if (s->state == SSL23_ST_SR_CLNT_HELLO_A) @@ -241,7 +290,20 @@ int ssl23_get_client_hello(SSL *s) /* SSLv3/TLSv1 */ if (p[4] >= TLS1_VERSION_MINOR) { - if (!(s->options & SSL_OP_NO_TLSv1)) + if (p[4] >= TLS1_2_VERSION_MINOR && + !(s->options & SSL_OP_NO_TLSv1_2)) + { + s->version=TLS1_2_VERSION; + s->state=SSL23_ST_SR_CLNT_HELLO_B; + } + else if (p[4] >= TLS1_1_VERSION_MINOR && + !(s->options & SSL_OP_NO_TLSv1_1)) + { + s->version=TLS1_1_VERSION; + /* type=2; */ /* done later to survive restarts */ + s->state=SSL23_ST_SR_CLNT_HELLO_B; + } + else if (!(s->options & SSL_OP_NO_TLSv1)) { s->version=TLS1_VERSION; /* type=2; */ /* done later to survive restarts */ @@ -267,88 +329,56 @@ int ssl23_get_client_hello(SSL *s) else if (!(s->options & SSL_OP_NO_SSLv2)) type=1; - if (s->options & SSL_OP_NON_EXPORT_FIRST) - /* Not only utterly confusing, but broken - * ('fractured programming'?) -- the details - * of this block nearly make it work - * as intended in this environment, but on one - * of the fine points (w.r.t. restarts) it fails. - * The obvious fix would be even more devastating - * to program structure; if you want the functionality, - * throw this away and implement it in a way - * that makes sense */ - { -#if 0 - STACK_OF(SSL_CIPHER) *sk; - SSL_CIPHER *c; - int ne2,ne3; - - j=((p[0]&0x7f)<<8)|p[1]; - if (j > (1024*4)) - { - SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE); - goto err; - } - - n=ssl23_read_bytes(s,j+2); - if (n <= 0) return(n); - p=s->packet; - - if ((buf=Malloc(n)) == NULL) - { - SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE); - goto err; - } - memcpy(buf,p,n); - - p+=5; - n2s(p,csl); - p+=4; - - sk=ssl_bytes_to_cipher_list( - s,p,csl,NULL); - if (sk != NULL) - { - ne2=ne3=0; - for (j=0; jid>>24L) == 2L) - ne2=1; - else - ne3=1; - } - } - if (ne2 && !ne3) - { - type=1; - use_sslv2_strong=1; - goto next_bit; - } - } -#else - SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNSUPPORTED_OPTION); - goto err; -#endif - } } } else if ((p[0] == SSL3_RT_HANDSHAKE) && (p[1] == SSL3_VERSION_MAJOR) && (p[5] == SSL3_MT_CLIENT_HELLO) && - (p[9] == p[1])) + ((p[3] == 0 && p[4] < 5 /* silly record length? */) + || (p[9] >= p[1]))) { /* * SSLv3 or tls1 header */ - /* we must look at client_version inside the client hello: */ - v[0]=p[9]; v[1]=p[10]; + v[0]=p[1]; /* major version (= SSL3_VERSION_MAJOR) */ + /* We must look at client_version inside the Client Hello message + * to get the correct minor version. + * However if we have only a pathologically small fragment of the + * Client Hello message, this would be difficult, and we'd have + * to read more records to find out. + * No known SSL 3.0 client fragments ClientHello like this, + * so we simply reject such connections to avoid + * protocol version downgrade attacks. */ + if (p[3] == 0 && p[4] < 6) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL); + goto err; + } + /* if major version number > 3 set minor to a value + * which will use the highest version 3 we support. + * If TLS 2.0 ever appears we will need to revise + * this.... + */ + if (p[9] > SSL3_VERSION_MAJOR) + v[1]=0xff; + else + v[1]=p[10]; /* minor version according to client_version */ if (v[1] >= TLS1_VERSION_MINOR) { - if (!(s->options & SSL_OP_NO_TLSv1)) + if (v[1] >= TLS1_2_VERSION_MINOR && + !(s->options & SSL_OP_NO_TLSv1_2)) + { + s->version=TLS1_2_VERSION; + type=3; + } + else if (v[1] >= TLS1_1_VERSION_MINOR && + !(s->options & SSL_OP_NO_TLSv1_1)) + { + s->version=TLS1_1_VERSION; + type=3; + } + else if (!(s->options & SSL_OP_NO_TLSv1)) { s->version=TLS1_VERSION; type=3; @@ -359,10 +389,21 @@ int ssl23_get_client_hello(SSL *s) type=3; } } - else if (!(s->options & SSL_OP_NO_SSLv3)) + else { - s->version=SSL3_VERSION; - type=3; + /* client requests SSL 3.0 */ + if (!(s->options & SSL_OP_NO_SSLv3)) + { + s->version=SSL3_VERSION; + type=3; + } + else if (!(s->options & SSL_OP_NO_TLSv1)) + { + /* we won't be able to use TLS of course, + * but this will send an appropriate alert */ + s->version=TLS1_VERSION; + type=3; + } } } else if ((strncmp("GET ", (char *)p,4) == 0) || @@ -380,7 +421,28 @@ int ssl23_get_client_hello(SSL *s) } } -next_bit: + if (s->version < TLS1_2_VERSION && tls1_suiteb(s)) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, + SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE); + goto err; + } + +#ifdef OPENSSL_FIPS + if (FIPS_mode() && (s->version < TLS1_VERSION)) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, + SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); + goto err; + } +#endif + + if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_VERSION_TOO_LOW); + goto err; + } + if (s->state == SSL23_ST_SR_CLNT_HELLO_B) { /* we have SSLv3/TLSv1 in an SSLv2 header @@ -391,17 +453,39 @@ next_bit: v[0] = p[3]; /* == SSL3_VERSION_MAJOR */ v[1] = p[4]; + /* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2 + * header is sent directly on the wire, not wrapped as a TLS + * record. It's format is: + * Byte Content + * 0-1 msg_length + * 2 msg_type + * 3-4 version + * 5-6 cipher_spec_length + * 7-8 session_id_length + * 9-10 challenge_length + * ... ... + */ n=((p[0]&0x7f)<<8)|p[1]; if (n > (1024*4)) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE); goto err; } + if (n < 9) + { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH); + goto err; + } j=ssl23_read_bytes(s,n+2); + /* We previously read 11 bytes, so if j > 0, we must have + * j == n+2 == s->packet_length. We have at least 11 valid + * packet bytes. */ if (j <= 0) return(j); - ssl3_finish_mac(s,&(s->packet[2]),s->packet_length-2); + ssl3_finish_mac(s, s->packet+2, s->packet_length-2); + if (s->msg_callback) + s->msg_callback(0, SSL2_VERSION, 0, s->packet+2, s->packet_length-2, s, s->msg_callback_arg); /* CLIENT-HELLO */ p=s->packet; p+=5; @@ -409,12 +493,21 @@ next_bit: n2s(p,sil); n2s(p,cl); d=(unsigned char *)s->init_buf->data; - if ((csl+sil+cl+11) != s->packet_length) + if ((csl+sil+cl+11) != s->packet_length) /* We can't have TLS extensions in SSL 2.0 format + * Client Hello, can we? Error condition should be + * '>' otherweise */ { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH); goto err; } + /* record header: msg_type ... */ + *(d++) = SSL3_MT_CLIENT_HELLO; + /* ... and length (actual value will be written later) */ + d_len = d; + d += 3; + + /* client_version */ *(d++) = SSL3_VERSION_MAJOR; /* == v[0] */ *(d++) = v[1]; @@ -445,7 +538,17 @@ next_bit: *(d++)=1; *(d++)=0; - i=(d-(unsigned char *)s->init_buf->data); +#if 0 + /* copy any remaining data with may be extensions */ + p = p+csl+sil+cl; + while (p < s->packet+s->packet_length) + { + *(d++)=*(p++); + } +#endif + + i = (d-(unsigned char *)s->init_buf->data) - 4; + l2n3((long)i, d_len); /* get the data reused from the init_buf */ s->s3->tmp.reuse_message=1; @@ -458,7 +561,7 @@ next_bit: if (type == 1) { -#ifdef NO_SSL2 +#ifdef OPENSSL_NO_SSL2 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); goto err; #else @@ -476,17 +579,18 @@ next_bit: if (s->s3 != NULL) ssl3_free(s); - if (!BUF_MEM_grow(s->init_buf, + if (!BUF_MEM_grow_clean(s->init_buf, SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) { goto err; } s->state=SSL2_ST_GET_CLIENT_HELLO_A; - if ((s->options & SSL_OP_MSIE_SSLV2_RSA_PADDING) || - use_sslv2_strong) + if (s->options & SSL_OP_NO_TLSv1 && s->options & SSL_OP_NO_SSLv3) s->s2->ssl2_rollback=0; else + /* reject SSL 2.0 session if client supports SSL 3.0 or TLS 1.0 + * (SSL 3.0 draft/RFC 2246, App. E.2) */ s->s2->ssl2_rollback=1; /* setup the n bytes we have read so we get them from @@ -518,6 +622,10 @@ next_bit: * 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; @@ -529,8 +637,11 @@ next_bit: s->s3->rbuf.left=0; s->s3->rbuf.offset=0; } - - if (s->version == TLS1_VERSION) + if (s->version == TLS1_2_VERSION) + s->method = TLSv1_2_server_method(); + else if (s->version == TLS1_1_VERSION) + s->method = TLSv1_1_server_method(); + else if (s->version == TLS1_VERSION) s->method = TLSv1_server_method(); else s->method = SSLv3_server_method(); @@ -548,10 +659,9 @@ next_bit: } s->init_num=0; - if (buf != buf_space) Free(buf); - s->first_packet=1; + if (buf != buf_space) OPENSSL_free(buf); return(SSL_accept(s)); err: - if (buf != buf_space) Free(buf); + if (buf != buf_space) OPENSSL_free(buf); return(-1); }