What version of Go are you using (go version)?
Using Docker 17.12. compiled with golang 1.9.4.
Does this issue reproduce with the latest release?
The causative lines of code are still present in the master branch. So i think yes.
What operating system and processor architecture are you using (go env)?
x86 Centos 7 (as VM in VirtualBox on Windows 7)
What did you do?
I want to connect to a docker registry which has an server certificate. The certificate should be validated.
Our certificate has the following attributes:
Subject:
CommonName: our.company.registry
SubjectAlternateNamens:
IP-Address: 1.2.3.4
IP-Address: 1.2.3.5
I don't know if this is a valid combination, but every other tool says this certificate is valid.
According to http://www.alvestrand.no/objectid/2.5.29.17.html SubjectAlternateNamens can have different types of items (e.g. IP-Addresses and DNS-Names)
What did you expect to see?
golang should verify this certificate as valid.
What did you see instead?
golang throws an error: "x509: certificate is not valid for any names, but wanted to match our.company.registry"
What is the cause?
Checking the hostname against the certificate causes the Problem:
(https://github.com/golang/go/blob/release-branch.go1.9/src/crypto/x509/verify.go)
...
90 if c.hasSANExtension() {
91 valid = strings.Join(c.DNSNames, ", ")
92 } else {
93 valid = c.Subject.CommonName
94 }
...
97 if len(valid) == 0 {
98 return "x509: certificate is not valid for any names, but wanted to match " + h.Host
99 }
...
Line 90 checks for presence of SubjectAlternateNamens extension (which is present). Line 91 will join all DNSNames, even if they are not present. So valid will be empty and the error will be thrown.
These lines of code have actually changed between golang 1.8 and golang 1.9. In golang 1.8, the following was executed:
(https://github.com/golang/go/blob/release-branch.go1.8/src/crypto/x509/verify.go)
...
90 if len(c.DNSNames) > 0 {
91 valid = strings.Join(c.DNSNames, ", ")
92 } else {
93 valid = c.Subject.CommonName
94 }
...
97 if len(valid) == 0 {
98 return "x509: certificate is not valid for any names, but wanted to match " + h.Host
99 }
...
Here, the if clause does not match, and the c.Subject.CommonName is used. (and is valid).
So we dont have problems using docker 17.09, wich was compiled against go1.8.3.
What could be the solution?
I can not imagine why the if clause has changed in that way. But in my opinion, before using c.DNSNames it should be checked if they are present.
...
90 if c.hasSANExtension() && len(c.DNSNames) > 0 {
91 valid = strings.Join(c.DNSNames, ", ")
92 } else {
93 valid = c.Subject.CommonName
94 }
...
What version of Go are you using (
go version)?Using Docker 17.12. compiled with golang 1.9.4.
Does this issue reproduce with the latest release?
The causative lines of code are still present in the master branch. So i think yes.
What operating system and processor architecture are you using (
go env)?x86 Centos 7 (as VM in VirtualBox on Windows 7)
What did you do?
I want to connect to a docker registry which has an server certificate. The certificate should be validated.
Our certificate has the following attributes:
I don't know if this is a valid combination, but every other tool says this certificate is valid.
According to http://www.alvestrand.no/objectid/2.5.29.17.html SubjectAlternateNamens can have different types of items (e.g. IP-Addresses and DNS-Names)
What did you expect to see?
golang should verify this certificate as valid.
What did you see instead?
golang throws an error: "x509: certificate is not valid for any names, but wanted to match our.company.registry"
What is the cause?
Checking the hostname against the certificate causes the Problem:
(https://github.com/golang/go/blob/release-branch.go1.9/src/crypto/x509/verify.go)
Line 90 checks for presence of SubjectAlternateNamens extension (which is present). Line 91 will join all DNSNames, even if they are not present. So valid will be empty and the error will be thrown.
These lines of code have actually changed between golang 1.8 and golang 1.9. In golang 1.8, the following was executed:
(https://github.com/golang/go/blob/release-branch.go1.8/src/crypto/x509/verify.go)
Here, the if clause does not match, and the c.Subject.CommonName is used. (and is valid).
So we dont have problems using docker 17.09, wich was compiled against go1.8.3.
What could be the solution?
I can not imagine why the if clause has changed in that way. But in my opinion, before using c.DNSNames it should be checked if they are present.