Skip to content

crypto/tls: Missing attribute in tls.ConnectionState struct #11881

Description

@nathanaelle

Hi,

Summary

In some situations, ConnectionState.ServerName is not enough and the access to the certificate used to negociate the connection is needed.
This issue targets any stateless protocol that can use SNI and an field (inside the protocol) to identify a virtual host.
In Case of HTTP with TLS , SNI ServerName and the Host header provide valid strings that may differ.

Solution

Adding a ServerCertificate *x509.Certificate attribute to tls.ConnectionState struct

tls.Conn has access to tls.Config so ServerCertificate can be set when (*tls.Conn)ConnectionState() is called.

Illustrations of the problem

the context is a HTTPS offloader/reverse-proxy that have 2 differents certificates each for a different *.FQDN in CommonName ; precisely, cert-1 has *.FQDN-1 CommonName and cert-2 has *.FQDN-2 CommonName

Good case (easily produced with any browser)

  1. client connects to the server with a SNI header to foo.FQDN-1 and a Host: foo.FQDN-1
  2. server sets request.TLS.ServerName and call ServeHTTP foo.FQDN-1
  3. inside ServeHTTP, request.TLS.ServerName and req.Host have the same value
  4. ServeHTTP answers a redirection to bar.FQDN-1
  5. client reuses the same connection & Session Ticket because the Certificate's CommonName allow it
  6. inside ServerHTTP , request.TLS.ServerName and req.Host have different values because req.TLS.ServerName was set in the first connection

a call to req.TLS.ServerCertificate.VerifyHostname(req.Host) will return nil to confirm that bar.FQDN-1 can be served on the same connection.

Bad case

  1. client connects to the server with a SNI header to foo.FQDN-1 and a Host: foo.FQDN-1
  2. server sets request.TLS.ServerName and call ServeHTTP foo.FQDN-1
  3. client crafts a HTTP request to foo.FQDN-2 and reuse the previous connection
  4. inside ServerHTTP , request.TLS.ServerName and req.Host have different values

Here, a call to req.TLS.ServerCertificate.VerifyHostname(req.Host) will return an error. this call provide an elegant way to mitigate the situation.

There are others way to mitigate this situation but are also more complicated.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions