Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto/tls: customized selection of a client cert during handshake with server #16626

Closed
bfix opened this issue Aug 6, 2016 · 7 comments
Closed
Labels
FeatureRequest FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@bfix
Copy link

bfix commented Aug 6, 2016

Please answer these questions before submitting your issue. Thanks!

  1. What version of Go are you using (go version)?
    go version go1.6.3 linux/amd64
  2. What operating system and processor architecture are you using (go env)?
    GOARCH="amd64"
    GOBIN=""
    GOEXE=""
    GOHOSTARCH="amd64"
    GOHOSTOS="linux"
    GOOS="linux"
    GOPATH="/opt/go/ext"
    GORACE=""
    GOROOT="/opt/go/golang"
    GOTOOLDIR="/opt/go/golang/pkg/tool/linux_amd64"
    GO15VENDOREXPERIMENT="1"
    CC="gcc"
    GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
    CXX="g++"
    CGO_ENABLED="1"
  3. Feature request:
    Requirement for a customized selection of a client certificate during TLS handshake with a server. The current implementation in crypto/tls/handshake_client.go uses the first certificate that is signed by an acceptable CA. The application cannot set the client cert in tls.Config.Certificates based on user selection before calling conn.Handshake(), because it has no way to tell which CAs will be accepted by a server in a handshake.

The problem was locally fixed by cloning crypto/tls and applying the following changes. If the requirement is considered legit and usually useful, feel free to use and modify it as you see fit:

crypto/tls/common.go:

// ServerHelloInfo contains information from a ServerHello message in order to
// guide certificate selection in the GetClientCertificate callback.
type ServerHelloInfo struct {
    // CertCAs lists the CA root certificates accepted for successful
    // client authentication.
    CertCAs [][]byte

    // CertTypes lists the supported certificate types for each CA cert.
    CertTypes []byte
}
:
type Config struct {
    :
    // GetClientCertificate returns a Certificate based on the given
    // ServerHelloInfo. It will only be called if the server requests
    // client authentication and if Certificates is empty.
    //
    // If GetClientCertificate is nil or returns nil, no client certificate
    // is send to the server as a response.
    GetClientCertificate func(serverHello *ServerHelloInfo) (*Certificate, error)
    :
}

crypto/tls/handshake_client.go(doFullHandshake):

:
// If no client certs are available in Config and the
// GetClientCertificate callback is defined, get a
// certificate from the callback function.
//
// It is the responsibility of the callback to return
// an appropriate certificate.
if c.config.Certificates == nil && c.config.GetClientCertificate != nil {
    hello := &ServerHelloInfo{
        CertCAs:   certReq.certificateAuthorities,
        CertTypes: certReq.certificateTypes,
    }
    if chainToSend, err = c.config.GetClientCertificate(hello); err != nil {
        return err
    }
} else {
    // We need to search our list of client certs for one
    // where SignatureAlgorithm is acceptable to the server and the
    // Issuer is in certReq.certificateAuthorities
    findCert:
        for i, chain := range c.config.Certificates {
            :
        }
}

crypto/tls/tls_test.go(TestClone):

:
case "Time", "GetCertificate", "GetClientCertificate":
:
@bradfitz
Copy link
Contributor

bradfitz commented Aug 6, 2016

Do you want to send a change? See https://golang.org/doc/contribute.html

@bfix
Copy link
Author

bfix commented Aug 7, 2016

Sure. Will you be a reviewer or should I leave it open?

@bradfitz
Copy link
Contributor

bradfitz commented Aug 7, 2016

It will be routed to reviewers. I will do the early reviews. @agl can give it the crypto blessing.

@bfix
Copy link
Author

bfix commented Aug 7, 2016

OK, thanks for the reply. I will 'git mail' it then.

@quentinmit quentinmit added this to the Go1.8Maybe milestone Aug 8, 2016
@agl agl self-assigned this Aug 19, 2016
@quentinmit quentinmit added the NeedsFix The path to resolution is known, but the work has not been done. label Oct 10, 2016
@rsc
Copy link
Contributor

rsc commented Oct 20, 2016

CL 25570.

@gopherbot
Copy link

CL https://golang.org/cl/25570 mentions this issue.

@gopherbot
Copy link

CL https://golang.org/cl/32115 mentions this issue.

@golang golang locked and limited conversation to collaborators Oct 27, 2017
FiloSottile pushed a commit to FiloSottile/go that referenced this issue Oct 12, 2018
Currently, the selection of a client certificate done internally based
on the limitations given by the server's request and the certifcates in
the Config. This means that it's not possible for an application to
control that selection based on details of the request.

This change adds a callback, GetClientCertificate, that is called by a
Client during the handshake and which allows applications to select the
best certificate at that time.

(Based on https://golang.org/cl/25570/ by Bernd Fix.)

Fixes golang#16626.

Change-Id: Ia4cea03235d2aa3c9fd49c99c227593c8e86ddd9
Reviewed-on: https://go-review.googlesource.com/32115
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
FiloSottile pushed a commit to FiloSottile/go that referenced this issue Oct 12, 2018
Currently, the selection of a client certificate done internally based
on the limitations given by the server's request and the certifcates in
the Config. This means that it's not possible for an application to
control that selection based on details of the request.

This change adds a callback, GetClientCertificate, that is called by a
Client during the handshake and which allows applications to select the
best certificate at that time.

(Based on https://golang.org/cl/25570/ by Bernd Fix.)

Fixes golang#16626.

Change-Id: Ia4cea03235d2aa3c9fd49c99c227593c8e86ddd9
Reviewed-on: https://go-review.googlesource.com/32115
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
@rsc rsc unassigned agl Jun 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FeatureRequest FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

6 participants