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 */