Duplicate SSL_SESSIONs when renewing them.

See also upstream's 27c76b9b8010b536687318739c6f631ce4194688, CVE-2015-1791.
Rather than write a dup function, serializing and deserializing the object is
simpler. It also fixes a bug in the original fix where it never calls
new_session_cb to store the new session (for clients which use that callback;
how clients should handle the session cache is much less clear).

The old session isn't pruned as we haven't processed the Finished message yet.
RFC 5077 says:

   The server MUST NOT assume that the client actually received the updated
   ticket until it successfully verifies the client's Finished message.

Moreover, because network messages are asynchronous, a new SSL connection may
have began just before the client received the new ticket, so any such servers
are broken regardless.

Change-Id: I13b3dc986dc58ea2ce66659dbb29e14cd02a641b
Reviewed-on: https://boringssl-review.googlesource.com/5122
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index c9e7fcd..90b59c5 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1501,6 +1501,27 @@
     return n;
+  if (s->hit) {
+    /* The server is sending a new ticket for an existing session. Sessions are
+     * immutable once established, so duplicate all but the ticket of the
+     * existing session. */
+    uint8_t *bytes;
+    size_t bytes_len;
+    if (!SSL_SESSION_to_bytes_for_ticket(s->session, &bytes, &bytes_len)) {
+      goto err;
+    }
+    SSL_SESSION *new_session = SSL_SESSION_from_bytes(bytes, bytes_len);
+    OPENSSL_free(bytes);
+    if (new_session == NULL) {
+      /* This should never happen. */
+      OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, ERR_R_INTERNAL_ERROR);
+      goto err;
+    }
+    SSL_SESSION_free(s->session);
+    s->session = new_session;
+  }
   CBS_init(&new_session_ticket, s->init_msg, n);
   if (!CBS_get_u32(&new_session_ticket,