diff -up openssl-1.0.1e/ssl/ssl_err.c.ticket-race openssl-1.0.1e/ssl/ssl_err.c
--- openssl-1.0.1e/ssl/ssl_err.c.ticket-race 2015-06-09 15:40:41.000000000 +0200
+++ openssl-1.0.1e/ssl/ssl_err.c 2015-06-09 15:45:06.879198463 +0200
@@ -245,6 +245,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_SSL_READ), "SSL_read"},
{ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT), "SSL_RSA_PRIVATE_DECRYPT"},
{ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT), "SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"},
{ERR_FUNC(SSL_F_SSL_SESSION_NEW), "SSL_SESSION_new"},
{ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP), "SSL_SESSION_print_fp"},
{ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT), "SSL_SESSION_set1_id_context"},
diff -up openssl-1.0.1e/ssl/ssl.h.ticket-race openssl-1.0.1e/ssl/ssl.h
--- openssl-1.0.1e/ssl/ssl.h.ticket-race 2015-06-09 15:40:41.000000000 +0200
+++ openssl-1.0.1e/ssl/ssl.h 2015-06-09 15:44:22.696191291 +0200
@@ -2176,6 +2176,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_READ 223
#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187
#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188
+#define SSL_F_SSL_SESSION_DUP 348
#define SSL_F_SSL_SESSION_NEW 189
#define SSL_F_SSL_SESSION_PRINT_FP 190
#define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 312
diff -up openssl-1.0.1e/ssl/ssl_locl.h.ticket-race openssl-1.0.1e/ssl/ssl_locl.h
--- openssl-1.0.1e/ssl/ssl_locl.h.ticket-race 2015-06-09 15:40:41.000000000 +0200
+++ openssl-1.0.1e/ssl/ssl_locl.h 2015-06-09 16:02:41.105243796 +0200
@@ -822,6 +822,7 @@ void ssl_sess_cert_free(SESS_CERT *sc);
int ssl_set_peer_cert_type(SESS_CERT *c, int type);
int ssl_get_new_session(SSL *s, int session);
int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
ssl_cipher_id);
diff -up openssl-1.0.1e/ssl/ssl_sess.c.ticket-race openssl-1.0.1e/ssl/ssl_sess.c
--- openssl-1.0.1e/ssl/ssl_sess.c.ticket-race 2013-02-11 16:26:04.000000000 +0100
+++ openssl-1.0.1e/ssl/ssl_sess.c 2015-06-11 13:48:26.724348868 +0200
@@ -224,6 +224,146 @@ SSL_SESSION *SSL_SESSION_new(void)
return(ss);
}
+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+ SSL_SESSION *dest;
+
+ dest = OPENSSL_malloc(sizeof(*src));
+ if (dest == NULL)
+ {
+ goto err;
+ }
+ memcpy(dest, src, sizeof(*dest));
+
+ /*
+ * Set the various pointers to NULL so that we can call SSL_SESSION_free in
+ * the case of an error whilst halfway through constructing dest
+ */
+#ifndef OPENSSL_NO_PSK
+ dest->psk_identity_hint = NULL;
+ dest->psk_identity = NULL;
+#endif
+ dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+ dest->tlsext_hostname = NULL;
+# ifndef OPENSSL_NO_EC
+ dest->tlsext_ecpointformatlist = NULL;
+ dest->tlsext_ellipticcurvelist = NULL;
+# endif
+#endif
+ dest->tlsext_tick = NULL;
+#ifndef OPENSSL_NO_SRP
+ dest->srp_username = NULL;
+#endif
+ memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+ /* We deliberately don't copy the prev and next pointers */
+ dest->prev = NULL;
+ dest->next = NULL;
+
+ dest->references = 1;
+
+ if (src->sess_cert != NULL)
+ CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
+
+ if (src->peer != NULL)
+ CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+
+#ifndef OPENSSL_NO_PSK
+ if (src->psk_identity_hint)
+ {
+ dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint);
+ if (dest->psk_identity_hint == NULL)
+ {
+ goto err;
+ }
+ }
+ if (src->psk_identity)
+ {
+ dest->psk_identity = BUF_strdup(src->psk_identity);
+ if (dest->psk_identity == NULL)
+ {
+ goto err;
+ }
+ }
+#endif
+
+ if(src->ciphers != NULL)
+ {
+ dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+ if (dest->ciphers == NULL)
+ goto err;
+ }
+
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+ &dest->ex_data, &src->ex_data))
+ {
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_TLSEXT
+ if (src->tlsext_hostname)
+ {
+ dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+ if (dest->tlsext_hostname == NULL)
+ {
+ goto err;
+ }
+ }
+# ifndef OPENSSL_NO_EC
+ if (src->tlsext_ecpointformatlist)
+ {
+ dest->tlsext_ecpointformatlist =
+ BUF_memdup(src->tlsext_ecpointformatlist,
+ src->tlsext_ecpointformatlist_length);
+ if (dest->tlsext_ecpointformatlist == NULL)
+ goto err;
+ }
+ if (src->tlsext_ellipticcurvelist)
+ {
+ dest->tlsext_ellipticcurvelist =
+ BUF_memdup(src->tlsext_ellipticcurvelist,
+ src->tlsext_ellipticcurvelist_length);
+ if (dest->tlsext_ellipticcurvelist == NULL)
+ goto err;
+ }
+# endif
+#endif
+
+ if (ticket != 0)
+ {
+ dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
+ if(dest->tlsext_tick == NULL)
+ goto err;
+ }
+ else
+ {
+ dest->tlsext_tick_lifetime_hint = 0;
+ dest->tlsext_ticklen = 0;
+ }
+
+#ifndef OPENSSL_NO_SRP
+ if (src->srp_username)
+ {
+ dest->srp_username = BUF_strdup(src->srp_username);
+ if (dest->srp_username == NULL)
+ {
+ goto err;
+ }
+ }
+#endif
+
+ return dest;
+err:
+ SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+ SSL_SESSION_free(dest);
+ return NULL;
+}
+
const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
{
if(len)
diff -up openssl-1.0.1e/ssl/s3_clnt.c.ticket-race openssl-1.0.1e/ssl/s3_clnt.c
--- openssl-1.0.1e/ssl/s3_clnt.c.ticket-race 2015-06-09 15:40:41.000000000 +0200
+++ openssl-1.0.1e/ssl/s3_clnt.c 2015-06-09 15:39:56.315119013 +0200
@@ -2065,24 +2065,13 @@ int ssl3_get_new_session_ticket(SSL *s)
n=s->method->ssl_get_message(s,
SSL3_ST_CR_SESSION_TICKET_A,
SSL3_ST_CR_SESSION_TICKET_B,
- -1,
+ SSL3_MT_NEWSESSION_TICKET,
16384,
&ok);
if (!ok)
return((int)n);
- if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
- {
- s->s3->tmp.reuse_message=1;
- return(1);
- }
- if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET)
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE);
- goto f_err;
- }
if (n < 6)
{
/* need at least ticket_lifetime_hint + ticket length */
@@ -2092,6 +2081,44 @@ int ssl3_get_new_session_ticket(SSL *s)
}
p=d=(unsigned char *)s->init_msg;
+
+ if (s->session->session_id_length > 0)
+ {
+ int i = s->session_ctx->session_cache_mode;
+ SSL_SESSION *new_sess;
+ /*
+ * We reused an existing session, so we need to replace it with a new
+ * one
+ */
+ if (i & SSL_SESS_CACHE_CLIENT)
+ {
+ /*
+ * Remove the old session from the cache
+ */
+ if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE)
+ {
+ if (s->session_ctx->remove_session_cb != NULL)
+ s->session_ctx->remove_session_cb(s->session_ctx,
+ s->session);
+ }
+ else
+ {
+ /* We carry on if this fails */
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+ }
+ }
+
+ if ((new_sess = ssl_session_dup(s->session, 0)) == 0)
+ {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+
+ SSL_SESSION_free(s->session);
+ s->session = new_sess;
+ }
+
n2l(p, s->session->tlsext_tick_lifetime_hint);
n2s(p, ticklen);
/* ticket_lifetime_hint + ticket_length + ticket */