static int ssl23_get_server_hello(SSL *s);
static const SSL_METHOD *ssl23_get_client_method(int ver)
{
- if (ver == SSL3_VERSION)
- 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);
+ /* When SSL_set_session is called, do NOT switch to the version-specific
+ * method table. The server may still negotiate a different version when
+ * rejecting the session.
+ *
+ * TODO(davidben): Clean this up. This duplicates logic from the
+ * version-specific tables. https://crbug.com/403378 */
+ return SSLv23_client_method();
}
IMPLEMENT_ssl23_meth_func(SSLv23_client_method,
case SSL_ST_BEFORE|SSL_ST_CONNECT:
case SSL_ST_OK|SSL_ST_CONNECT:
- if (s->session != NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl23_connect, SSL_R_SSL23_DOING_SESSION_ID_REUSE);
- ret= -1;
- goto end;
- }
s->server=0;
if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
* 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_TLS1_2_CLIENT)
+ mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3;
version = TLS1_2_VERSION;
-
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;
mask &= ~SSL_OP_NO_TLSv1;
-#if !defined(OPENSSL_NO_SSL3)
if ((options & SSL_OP_NO_TLSv1) && (options & mask) != mask)
version = SSL3_VERSION;
mask &= ~SSL_OP_NO_SSLv3;
-#endif
buf=(unsigned char *)s->init_buf->data;
if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
{
-#if 0
- /* don't reuse session-id's */
- if (!ssl_get_new_session(s,0))
+ /* Check if the session is resumable. If not, drop it. */
+ if (s->session != NULL)
{
- return(-1);
+ if (s->session->ssl_version > version ||
+ s->session->session_id_length == 0 ||
+ s->session->not_resumable)
+ {
+ SSL_SESSION_free(s->session);
+ s->session = NULL;
+ }
}
-#endif
p=s->s3->client_random;
if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0)
version_major = TLS1_2_VERSION_MAJOR;
version_minor = TLS1_2_VERSION_MINOR;
}
- else if (tls1_suiteb(s))
- {
- OPENSSL_PUT_ERROR(SSL, 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;
memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
p += SSL3_RANDOM_SIZE;
- /* Session ID (zero since there is no reuse) */
- *(p++) = 0;
+ /* Session ID */
+ if (s->new_session || s->session == NULL)
+ i=0;
+ else
+ i=s->session->session_id_length;
+ *(p++)=i;
+ if (i != 0)
+ {
+ if (i > (int)sizeof(s->session->session_id))
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl23_client_hello, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ memcpy(p,s->session->session_id,i);
+ p+=i;
+ }
/* Ciphers supported (using SSL 3.0/TLS 1.0 format) */
i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2]);
}
s->init_num=0;
- /* Since, if we are sending a ssl23 client hello, we are not
- * reusing a session-id */
- if (!ssl_get_new_session(s,0))
+ /* If there was no session to resume, now that the final version is
+ * determined, insert a fresh one. */
+ if (s->session == NULL && !ssl_get_new_session(s,0))
goto err;
return(SSL_connect(s));