I think Go is making a mistake in assuming that client certificates
without the extended usage attributes (ie most client certificates)
should be denied use as a client authentication.
What steps will reproduce the problem?
Here are a couple of programs and a script to demonstrate the problem
https://gist.github.com/ncw/9253562
What is the expected output?
Working SSL connection
What do you see instead?
tls: client's certificate's extended key usage doesn't permit it to be used for client
authentication
Which operating system are you using?
Linux Ubuntu 13.10
Which version are you using? (run 'go version' or 'gccgo --version')
(latest head)
go version devel +abd51e52924a Thu Feb 27 01:45:22 2014 -0800 linux/amd64
Please provide any additional information below.
Here is the README from the gist
This demonstrates a bug in Go
First generate the certificates with
./makecert.sh test@test.com
Run the server in one terminal
go run server.go
Run the client in the other
go run client.go
You'll see an SSL negotiation failure
The Server says
2014/02/27 16:33:51 server: listening
2014/02/27 16:33:53 server: accepted from 127.0.0.1:43700
2014/02/27 16:33:53 server: conn: type assert to TLS succeedded
2014/02/27 16:33:53 server: handshake failed: tls: client's certificate's extended key
usage doesn't permit it to be used for client authentication
exit status 1
And the Client says
2014/02/27 16:33:53 client: dial: remote error: handshake failure
exit status 1
If you then try to add the extended usage to the certificate with the -addtrust
clientAuth (uncomment in makecert.sh) you get this from the Client
2014/02/27 16:36:58 server: loadkeys: crypto/tls: failed to parse certificate PEM data
exit status 1
Because the client can no longer read the certificate which now starts with
-----BEGIN TRUSTED CERTIFICATE-----
MIIDizCCAnMCAQEwDQYJKoZIhvcNAQEFBQAwgZExCzAJBgNVBAYTAkRFMQwwCgYD
The relevant code is in crypo/tls/handshake_server.go
ok := false
for _, ku := range certs[0].ExtKeyUsage {
if ku == x509.ExtKeyUsageClientAuth {
ok = true
break
}
}
if !ok {
c.sendAlert(alertHandshakeFailure)
return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
}
I think Go is making a mistake in assuming that client certificates
without the extended usage attributes (ie most client certificates)
should be denied use as a client authentication.
So removing this code would fix the problem or possibly Go should
assume certificates without the extended trust attributes should be
allowed rather than rejected.
From the OpenSSL docs
http://www.openssl.org/docs/apps/x509.html
> Trust settings currently are only used with a root CA. They allow a
> finer control over the purposes the root CA can be used for. For
> example a CA may be trusted for SSL client but not SSL server use.
>
> See the description of the verify utility for more information on
> the meaning of trust settings.
>
> Future versions of OpenSSL will recognize trust settings on any
> certificate: not just root CAs.
Indicating that OpenSSL doesn't use these trust settings at all
(confirmed with my experiments with Apache).