Allow different protocol version when trying to reuse a session

We now send the highest supported version by the client, even if the session
uses an older version.

This fixes 2 problems:
- When you try to reuse a session but the other side doesn't reuse it and
  uses a different protocol version the connection will fail.
- When you're trying to reuse a session with an old version you might be
  stuck trying to reuse the old version while both sides support a newer
  version

Signed-off-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>

GH: #852, MR: #2452
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index bafb90a..73f54bc 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -817,7 +817,8 @@
         goto err;
     }
 
-    if ((sess == NULL) || (sess->ssl_version != s->version) ||
+    if ((sess == NULL) ||
+        !ssl_version_supported(s, sess->ssl_version) ||
         /*
          * In the case of EAP-FAST, we can have a pre-shared
          * "ticket" without a session ID.
@@ -1126,12 +1127,22 @@
             }
         }
 
+        s->session->ssl_version = s->version;
         s->session->session_id_length = session_id_len;
         /* session_id_len could be 0 */
         memcpy(s->session->session_id, PACKET_data(&session_id),
                session_id_len);
     }
 
+    /* Session version and negotiated protocol version should match */
+    if (s->version != s->session->ssl_version) {
+        al = SSL_AD_PROTOCOL_VERSION;
+
+        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
+               SSL_R_SSL_SESSION_VERSION_MISMATCH);
+        goto f_err;
+    }
+
     c = ssl_get_cipher_by_char(s, cipherchars);
     if (c == NULL) {
         /* unknown cipher */