546bf97
diff -up openssl-1.0.1k/ssl/ssl_err.c.ticket-race openssl-1.0.1k/ssl/ssl_err.c
546bf97
--- openssl-1.0.1k/ssl/ssl_err.c.ticket-race	2015-06-15 17:06:22.699702477 +0200
546bf97
+++ openssl-1.0.1k/ssl/ssl_err.c	2015-06-15 17:06:22.704702592 +0200
546bf97
@@ -245,6 +245,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
546bf97
 {ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
546bf97
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
546bf97
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
546bf97
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP),	"ssl_session_dup"},
546bf97
 {ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"},
546bf97
 {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"},
546bf97
 {ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT),	"SSL_SESSION_set1_id_context"},
546bf97
diff -up openssl-1.0.1k/ssl/ssl.h.ticket-race openssl-1.0.1k/ssl/ssl.h
546bf97
--- openssl-1.0.1k/ssl/ssl.h.ticket-race	2015-06-15 17:06:22.700702500 +0200
546bf97
+++ openssl-1.0.1k/ssl/ssl.h	2015-06-15 17:06:22.704702592 +0200
546bf97
@@ -2203,6 +2203,7 @@ void ERR_load_SSL_strings(void);
546bf97
 #define SSL_F_SSL_READ					 223
546bf97
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
546bf97
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
546bf97
+#define SSL_F_SSL_SESSION_DUP				 348
546bf97
 #define SSL_F_SSL_SESSION_NEW				 189
546bf97
 #define SSL_F_SSL_SESSION_PRINT_FP			 190
546bf97
 #define SSL_F_SSL_SESSION_SET1_ID_CONTEXT		 312
546bf97
diff -up openssl-1.0.1k/ssl/ssl_locl.h.ticket-race openssl-1.0.1k/ssl/ssl_locl.h
546bf97
--- openssl-1.0.1k/ssl/ssl_locl.h.ticket-race	2015-06-15 17:06:22.543698865 +0200
546bf97
+++ openssl-1.0.1k/ssl/ssl_locl.h	2015-06-15 17:06:22.705702616 +0200
546bf97
@@ -831,6 +831,7 @@ void ssl_sess_cert_free(SESS_CERT *sc);
546bf97
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
546bf97
 int ssl_get_new_session(SSL *s, int session);
546bf97
 int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
546bf97
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
546bf97
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
546bf97
 DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
546bf97
 				  ssl_cipher_id);
546bf97
diff -up openssl-1.0.1k/ssl/ssl_sess.c.ticket-race openssl-1.0.1k/ssl/ssl_sess.c
546bf97
--- openssl-1.0.1k/ssl/ssl_sess.c.ticket-race	2015-01-08 15:00:56.000000000 +0100
546bf97
+++ openssl-1.0.1k/ssl/ssl_sess.c	2015-06-15 17:06:22.705702616 +0200
546bf97
@@ -224,6 +224,146 @@ SSL_SESSION *SSL_SESSION_new(void)
546bf97
 	return(ss);
546bf97
 	}
546bf97
 
546bf97
+/*
546bf97
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
546bf97
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
546bf97
+ */
546bf97
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
546bf97
+{
546bf97
+	SSL_SESSION *dest;
546bf97
+
546bf97
+	dest = OPENSSL_malloc(sizeof(*src));
546bf97
+	if (dest == NULL)
546bf97
+		{
546bf97
+		goto err;
546bf97
+		}
546bf97
+	memcpy(dest, src, sizeof(*dest));
546bf97
+
546bf97
+	/*
546bf97
+	 * Set the various pointers to NULL so that we can call SSL_SESSION_free in
546bf97
+	 * the case of an error whilst halfway through constructing dest
546bf97
+	 */
546bf97
+#ifndef OPENSSL_NO_PSK
546bf97
+	dest->psk_identity_hint = NULL;
546bf97
+	dest->psk_identity = NULL;
546bf97
+#endif
546bf97
+	dest->ciphers = NULL;
546bf97
+#ifndef OPENSSL_NO_TLSEXT
546bf97
+	dest->tlsext_hostname = NULL;
546bf97
+# ifndef OPENSSL_NO_EC
546bf97
+	dest->tlsext_ecpointformatlist = NULL;
546bf97
+	dest->tlsext_ellipticcurvelist = NULL;
546bf97
+# endif
546bf97
+#endif
546bf97
+	dest->tlsext_tick = NULL;
546bf97
+#ifndef OPENSSL_NO_SRP
546bf97
+	dest->srp_username = NULL;
546bf97
+#endif
546bf97
+	memset(&dest->ex_data, 0, sizeof(dest->ex_data));
546bf97
+
546bf97
+	/* We deliberately don't copy the prev and next pointers */
546bf97
+	dest->prev = NULL;
546bf97
+	dest->next = NULL;
546bf97
+
546bf97
+	dest->references = 1;
546bf97
+
546bf97
+	if (src->sess_cert != NULL)
546bf97
+		CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
546bf97
+
546bf97
+	if (src->peer != NULL)
546bf97
+		CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
546bf97
+
546bf97
+#ifndef OPENSSL_NO_PSK
546bf97
+	if (src->psk_identity_hint)
546bf97
+		{
546bf97
+		dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint);
546bf97
+		if (dest->psk_identity_hint == NULL)
546bf97
+			{
546bf97
+			goto err;
546bf97
+			}
546bf97
+		}
546bf97
+	if (src->psk_identity)
546bf97
+		{
546bf97
+		dest->psk_identity = BUF_strdup(src->psk_identity);
546bf97
+		if (dest->psk_identity == NULL)
546bf97
+			{
546bf97
+			goto err;
546bf97
+			}
546bf97
+		}
546bf97
+#endif
546bf97
+
546bf97
+	if(src->ciphers != NULL)
546bf97
+		{
546bf97
+		dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
546bf97
+		if (dest->ciphers == NULL)
546bf97
+			goto err;
546bf97
+		}
546bf97
+
546bf97
+	if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
546bf97
+				&dest->ex_data, &src->ex_data))
546bf97
+		{
546bf97
+		goto err;
546bf97
+		}
546bf97
+
546bf97
+#ifndef OPENSSL_NO_TLSEXT
546bf97
+	if (src->tlsext_hostname)
546bf97
+		{
546bf97
+		dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
546bf97
+		if (dest->tlsext_hostname == NULL)
546bf97
+			{
546bf97
+			goto err;
546bf97
+			}
546bf97
+		}
546bf97
+# ifndef OPENSSL_NO_EC
546bf97
+	if (src->tlsext_ecpointformatlist)
546bf97
+		{
546bf97
+		dest->tlsext_ecpointformatlist =
546bf97
+			BUF_memdup(src->tlsext_ecpointformatlist,
546bf97
+				src->tlsext_ecpointformatlist_length);
546bf97
+		if (dest->tlsext_ecpointformatlist == NULL)
546bf97
+			goto err;
546bf97
+		}
546bf97
+	if (src->tlsext_ellipticcurvelist)
546bf97
+		{
546bf97
+		dest->tlsext_ellipticcurvelist =
546bf97
+			BUF_memdup(src->tlsext_ellipticcurvelist,
546bf97
+				src->tlsext_ellipticcurvelist_length);
546bf97
+		if (dest->tlsext_ellipticcurvelist == NULL)
546bf97
+			goto err;
546bf97
+		}
546bf97
+# endif
546bf97
+#endif
546bf97
+
546bf97
+	if (ticket != 0)
546bf97
+		{
546bf97
+		dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
546bf97
+        	if(dest->tlsext_tick == NULL)
546bf97
+			goto err;
546bf97
+		}
546bf97
+	else
546bf97
+		{
546bf97
+		dest->tlsext_tick_lifetime_hint = 0;
546bf97
+		dest->tlsext_ticklen = 0;
546bf97
+		}
546bf97
+
546bf97
+#ifndef OPENSSL_NO_SRP
546bf97
+	if (src->srp_username)
546bf97
+		{
546bf97
+		dest->srp_username = BUF_strdup(src->srp_username);
546bf97
+		if (dest->srp_username == NULL)
546bf97
+			{
546bf97
+			goto err;
546bf97
+			}
546bf97
+		}
546bf97
+#endif
546bf97
+
546bf97
+	return dest;
546bf97
+err:
546bf97
+	SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
546bf97
+	SSL_SESSION_free(dest);
546bf97
+	return NULL;
546bf97
+}
546bf97
+
546bf97
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
546bf97
 	{
546bf97
 	if(len)
546bf97
diff -up openssl-1.0.1k/ssl/s3_clnt.c.ticket-race openssl-1.0.1k/ssl/s3_clnt.c
546bf97
--- openssl-1.0.1k/ssl/s3_clnt.c.ticket-race	2015-06-15 17:06:22.700702500 +0200
546bf97
+++ openssl-1.0.1k/ssl/s3_clnt.c	2015-06-15 17:06:37.434043557 +0200
546bf97
@@ -2191,6 +2191,44 @@ int ssl3_get_new_session_ticket(SSL *s)
546bf97
 		}
546bf97
 
546bf97
 	p=d=(unsigned char *)s->init_msg;
546bf97
+
546bf97
+	if (s->session->session_id_length > 0)
546bf97
+		{
546bf97
+		int i = s->session_ctx->session_cache_mode;
546bf97
+		SSL_SESSION *new_sess;
546bf97
+		/*
546bf97
+		 * We reused an existing session, so we need to replace it with a new
546bf97
+		 * one
546bf97
+		 */
546bf97
+		if (i & SSL_SESS_CACHE_CLIENT)
546bf97
+			{
546bf97
+			/*
546bf97
+			 * Remove the old session from the cache
546bf97
+			 */
546bf97
+			if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE)
546bf97
+				{
546bf97
+				if (s->session_ctx->remove_session_cb != NULL)
546bf97
+					s->session_ctx->remove_session_cb(s->session_ctx,
546bf97
+						s->session);
546bf97
+				}
546bf97
+			else
546bf97
+				{
546bf97
+				/* We carry on if this fails */
546bf97
+				SSL_CTX_remove_session(s->session_ctx, s->session);
546bf97
+				}
546bf97
+			}
546bf97
+
546bf97
+		if ((new_sess = ssl_session_dup(s->session, 0)) == 0)
546bf97
+			{
546bf97
+			al = SSL_AD_INTERNAL_ERROR;
546bf97
+			SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
546bf97
+			goto f_err;
546bf97
+			}
546bf97
+
546bf97
+		SSL_SESSION_free(s->session);
546bf97
+		s->session = new_sess;
546bf97
+		}
546bf97
+
546bf97
 	n2l(p, s->session->tlsext_tick_lifetime_hint);
546bf97
 	n2s(p, ticklen);
546bf97
 	/* ticket_lifetime_hint + ticket_length + ticket */