Skip to content

crypto/x509: Verify failed on some valid certificates with SubjectAlternateNames #24293

Description

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   }
...

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions