]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/crypto/tls/handshake_server.go
[dev.boringcrypto] all: merge commit 57c115e1 into dev.boringcrypto
[gostls13.git] / src / crypto / tls / handshake_server.go
index 85afad067158e4cd9d1405628dae6f6ad7fd33ed..497e196a856dcef64a610cb75c1ea1e1ef24ce91 100644 (file)
@@ -217,15 +217,13 @@ func (hs *serverHandshakeState) processClientHello() error {
                c.serverName = hs.clientHello.serverName
        }
 
-       if len(c.config.NextProtos) > 0 && len(hs.clientHello.alpnProtocols) > 0 {
-               selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos)
-               if selectedProto == "" {
-                       c.sendAlert(alertNoApplicationProtocol)
-                       return fmt.Errorf("tls: client requested unsupported application protocols (%s)", hs.clientHello.alpnProtocols)
-               }
-               hs.hello.alpnProtocol = selectedProto
-               c.clientProtocol = selectedProto
+       selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols)
+       if err != nil {
+               c.sendAlert(alertNoApplicationProtocol)
+               return err
        }
+       hs.hello.alpnProtocol = selectedProto
+       c.clientProtocol = selectedProto
 
        hs.cert, err = c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello))
        if err != nil {
@@ -277,6 +275,34 @@ func (hs *serverHandshakeState) processClientHello() error {
        return nil
 }
 
+// negotiateALPN picks a shared ALPN protocol that both sides support in server
+// preference order. If ALPN is not configured or the peer doesn't support it,
+// it returns "" and no error.
+func negotiateALPN(serverProtos, clientProtos []string) (string, error) {
+       if len(serverProtos) == 0 || len(clientProtos) == 0 {
+               return "", nil
+       }
+       var http11fallback bool
+       for _, s := range serverProtos {
+               for _, c := range clientProtos {
+                       if s == c {
+                               return s, nil
+                       }
+                       if s == "h2" && c == "http/1.1" {
+                               http11fallback = true
+                       }
+               }
+       }
+       // As a special case, let http/1.1 clients connect to h2 servers as if they
+       // didn't support ALPN. We used not to enforce protocol overlap, so over
+       // time a number of HTTP servers were configured with only "h2", but
+       // expected to accept connections from "http/1.1" clients. See Issue 46310.
+       if http11fallback {
+               return "", nil
+       }
+       return "", fmt.Errorf("tls: client requested unsupported application protocols (%s)", clientProtos)
+}
+
 // supportsECDHE returns whether ECDHE key exchanges can be used with this
 // pre-TLS 1.3 client.
 func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8) bool {