diff options
Diffstat (limited to 'src/crypto/tls/handshake_server.go')
-rw-r--r-- | src/crypto/tls/handshake_server.go | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index b231981e09..43f30e2fef 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -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 { |