* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
+ * 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
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#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 OPENSSL_NO_SSL2
if (ver == SSL2_VERSION)
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)
- {
- CRYPTO_w_lock(CRYPTO_LOCK_SSL_METHOD);
-
- 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;
-
- CRYPTO_w_unlock(CRYPTO_LOCK_SSL_METHOD);
- }
- 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);
+ unsigned long Time=(unsigned long)time(NULL);
void (*cb)(const SSL *ssl,int type,int val)=NULL;
int ret= -1;
int new_state,state;
int n=0,j;
int type=0;
int v[2];
-#ifndef OPENSSL_NO_RSA
- int use_sslv2_strong=0;
-#endif
if (s->state == SSL23_ST_SR_CLNT_HELLO_A)
{
/* 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 */
(p[1] == SSL3_VERSION_MAJOR) &&
(p[5] == SSL3_MT_CLIENT_HELLO) &&
((p[3] == 0 && p[4] < 5 /* silly record length? */)
- || (p[9] == p[1])))
+ || (p[9] >= p[1])))
{
/*
* SSLv3 or tls1 header
v[1] = TLS1_VERSION_MINOR;
#endif
}
+ /* 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....
+ */
+ else 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;
}
}
+#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 (s->state == SSL23_ST_SR_CLNT_HELLO_B)
{
/* we have SSLv3/TLSv1 in an SSLv2 header
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;
*(d++)=1;
*(d++)=0;
+#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);
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 ||
- (s->options & SSL_OP_NO_TLSv1 && s->options & SSL_OP_NO_SSLv3))
+ 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
* 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.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();
s->init_num=0;
if (buf != buf_space) OPENSSL_free(buf);
- s->first_packet=1;
return(SSL_accept(s));
err:
if (buf != buf_space) OPENSSL_free(buf);