Add an option to disable NPN on a per-SSL basis.

Right whether NPN is advertised can only be configured globally on the SSL_CTX.
Rather than adding two pointers to each SSL*, add an options bit to disable it
so we may plumb in a field trial to disable NPN.

Chromium wants to be able to route a bit in to disable NPN, but it uses SSL_CTX
incorrectly and has a global one, so it can't disconnect the callback. (That
really needs to get fixed. Although it's not clear this necessarily wants to be
lifted up to SSL_CTX as far as Chromium's SSLClientSocket is concerned since
NPN doesn't interact with the session cache.)

BUG=526713

Change-Id: I49c86828b963eb341c6ea6a442557b7dfa190ed3
Reviewed-on: https://boringssl-review.googlesource.com/6351
Reviewed-by: Adam Langley <alangley@gmail.com>
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index a133d09..17a91ad 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -1124,6 +1124,9 @@
   if (!config->check_close_notify) {
     SSL_set_quiet_shutdown(ssl.get(), 1);
   }
+  if (config->disable_npn) {
+    SSL_set_options(ssl.get(), SSL_OP_DISABLE_NPN);
+  }
 
   int sock = Connect(config->port);
   if (sock == -1) {
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 01813f9..fb1e46f 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -3366,6 +3366,18 @@
 		shouldFail:    true,
 		expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
 	})
+	// Test that NPN can be disabled with SSL_OP_DISABLE_NPN.
+	testCases = append(testCases, testCase{
+		name: "DisableNPN",
+		config: Config{
+			NextProtos: []string{"foo"},
+		},
+		flags: []string{
+			"-select-next-proto", "foo",
+			"-disable-npn",
+		},
+		expectNoNextProto: true,
+	})
 	// Resume with a corrupt ticket.
 	testCases = append(testCases, testCase{
 		testType: serverTest,
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 4e19be6..54492df 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -97,6 +97,7 @@
   { "-expect-verify-result", &TestConfig::expect_verify_result },
   { "-renegotiate-once", &TestConfig::renegotiate_once },
   { "-renegotiate-freely", &TestConfig::renegotiate_freely },
+  { "-disable-npn", &TestConfig::disable_npn },
 };
 
 const Flag<std::string> kStringFlags[] = {
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 4601851..af1dd80 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -99,6 +99,7 @@
   int expect_total_renegotiations = 0;
   bool renegotiate_once = false;
   bool renegotiate_freely = false;
+  bool disable_npn = false;
 };
 
 bool ParseConfig(int argc, char **argv, TestConfig *out_config);