Index: openssl/ssl/s23_clnt.c |
=================================================================== |
--- openssl/ssl/s23_clnt.c (revision 105093) |
+++ openssl/ssl/s23_clnt.c (working copy) |
@@ -55,6 +55,59 @@ |
* 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 <stdio.h> |
#include "ssl_locl.h" |
@@ -63,10 +116,10 @@ |
#include <openssl/objects.h> |
#include <openssl/evp.h> |
-static SSL_METHOD *ssl23_get_client_method(int ver); |
+static const SSL_METHOD *ssl23_get_client_method(int ver); |
static int ssl23_client_hello(SSL *s); |
static int ssl23_get_server_hello(SSL *s); |
-static SSL_METHOD *ssl23_get_client_method(int ver) |
+static const SSL_METHOD *ssl23_get_client_method(int ver) |
{ |
#ifndef OPENSSL_NO_SSL2 |
if (ver == SSL2_VERSION) |
@@ -197,6 +250,20 @@ |
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) |
{ |
@@ -214,6 +281,9 @@ |
ssl2_compat = (s->options & SSL_OP_NO_SSLv2) ? 0 : 1; |
+ if (ssl2_compat && ssl23_no_ssl2_ciphers(s)) |
+ ssl2_compat = 0; |
+ |
if (!(s->options & SSL_OP_NO_TLSv1)) |
{ |
version = TLS1_VERSION; |
@@ -226,7 +296,7 @@ |
{ |
version = SSL2_VERSION; |
} |
-#ifndef OPENSSL_NO_TLSEXT |
+#ifndef OPENSSL_NO_TLSEXT |
if (version != SSL2_VERSION) |
{ |
/* have to disable SSL 2.0 compatibility if we need TLS extensions */ |
@@ -235,6 +305,10 @@ |
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 |
@@ -260,14 +334,6 @@ |
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; |
@@ -321,6 +387,10 @@ |
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 |
@@ -369,11 +439,13 @@ |
} |
s2n(i,p); |
p+=i; |
+ |
+ /* COMPRESSION */ |
#ifdef OPENSSL_NO_COMP |
*(p++)=1; |
#else |
- /* COMPRESSION */ |
- if (s->ctx->comp_methods == NULL) |
+ if ((s->options & SSL_OP_NO_COMPRESSION) |
+ || !s->ctx->comp_methods) |
j=0; |
else |
j=sk_SSL_COMP_num(s->ctx->comp_methods); |
@@ -385,7 +457,14 @@ |
} |
#endif |
*(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_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); |
@@ -394,7 +473,6 @@ |
#endif |
l = p-d; |
- *p = 42; |
/* fill in 4-byte handshake header */ |
d=&(buf[5]); |
@@ -489,6 +567,10 @@ |
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; |
@@ -509,7 +591,7 @@ |
/* 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; |
@@ -525,39 +607,16 @@ |
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] == SSL3_VERSION_MINOR || p[2] == TLS1_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 */ |
+ /* we have sslv3 or tls1 (server hello or alert) */ |
- 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; |
- |
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(); |
} |
@@ -572,35 +631,52 @@ |
SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); |
goto err; |
} |
+ |
+ if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING) |
+ { |
+ /* 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); |
+ } |
- 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; |
+ if (s->msg_callback) |
+ s->msg_callback(0, s->version, SSL3_RT_ALERT, p+5, 2, s, s->msg_callback_arg); |
- /* 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) |
- { |
- j=(i<<8)|p[6]; |
- cb(s,SSL_CB_READ_ALERT,j); |
+ 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 |
{ |
@@ -611,6 +687,13 @@ |
/* Since, if we are sending a ssl23 client hello, we are not |
* reusing a session-id */ |
+ if (!s->session_creation_enabled) |
+ { |
+ if (!(s->client_version == SSL2_VERSION)) |
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); |
+ SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED); |
+ goto err; |
+ } |
if (!ssl_get_new_session(s,0)) |
goto err; |
@@ -618,4 +701,3 @@ |
err: |
return(-1); |
} |
- |