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

Comments

@bfix
Copy link

@bfix 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

This comment has been minimized.

Copy link
Contributor

@bradfitz bradfitz commented Aug 6, 2016

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

@bfix

This comment has been minimized.

Copy link
Author

@bfix bfix commented Aug 7, 2016

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

@bradfitz

This comment has been minimized.

Copy link
Contributor

@bradfitz 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

This comment has been minimized.

Copy link
Author

@bfix 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 label Oct 10, 2016
@rsc

This comment has been minimized.

Copy link
Contributor

@rsc rsc commented Oct 20, 2016

CL 25570.

@gopherbot

This comment has been minimized.

Copy link

@gopherbot gopherbot commented Oct 21, 2016

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

@gopherbot

This comment has been minimized.

Copy link

@gopherbot gopherbot commented Oct 26, 2016

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

@gopherbot gopherbot closed this in 81038d2 Oct 27, 2016
@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>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants
You can’t perform that action at this time.