Test that the early callback can affect max_version.

The early callback needs to run before even version negotiation has been
resolved.

Change-Id: Ibb449ccec07dedef19b7827400ef318fa2f422c0
Reviewed-on: https://boringssl-review.googlesource.com/10722
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index 5c68f26..3f9c898 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -2096,6 +2096,43 @@
   return true;
 }
 
+static int SetMaxVersion(const struct ssl_early_callback_ctx *ctx) {
+  SSL_set_max_version(ctx->ssl, TLS1_2_VERSION);
+  return 1;
+}
+
+// TestEarlyCallbackVersionSwitch tests that the early callback can swap the
+// maximum version.
+static bool TestEarlyCallbackVersionSwitch() {
+  ScopedX509 cert = GetTestCertificate();
+  ScopedEVP_PKEY key = GetTestKey();
+  ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
+  ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
+  if (!cert || !key || !server_ctx || !client_ctx ||
+      !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
+    return false;
+  }
+
+  SSL_CTX_set_max_version(client_ctx.get(), TLS1_3_VERSION);
+  SSL_CTX_set_max_version(server_ctx.get(), TLS1_3_VERSION);
+
+  SSL_CTX_set_select_certificate_cb(server_ctx.get(), SetMaxVersion);
+
+  ScopedSSL client, server;
+  if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
+                              server_ctx.get(), nullptr)) {
+    return false;
+  }
+
+  if (SSL_version(client.get()) != TLS1_2_VERSION) {
+    fprintf(stderr, "Early callback failed to switch the maximum version.\n");
+    return false;
+  }
+
+  return true;
+}
+
 int main() {
   CRYPTO_library_init();
 
@@ -2130,7 +2167,8 @@
       !TestClientHello() ||
       !TestSessionIDContext() ||
       !TestSessionTimeout() ||
-      !TestSNICallback()) {
+      !TestSNICallback() ||
+      !TestEarlyCallbackVersionSwitch()) {
     ERR_print_errors_fp(stderr);
     return 1;
   }