forked from quic-go/quic-go
Fix reading of tls.Config certificates
This commit mostly copies the getCertificate function from crypto/tls to align our certificate reading with the standard library. Should fix #458.
This commit is contained in:
@@ -55,30 +55,46 @@ func (c *certChain) GetLeafCert(sni string) ([]byte, error) {
|
|||||||
return cert.Certificate[0], nil
|
return cert.Certificate[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *certChain) getCertForSNI(sni string) (*tls.Certificate, error) {
|
func (cc *certChain) getCertForSNI(sni string) (*tls.Certificate, error) {
|
||||||
if c.config.GetCertificate != nil {
|
c := cc.config
|
||||||
cert, err := c.config.GetCertificate(&tls.ClientHelloInfo{ServerName: sni})
|
// The rest of this function is mostly copied from crypto/tls.getCertificate
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
if c.GetCertificate != nil {
|
||||||
|
cert, err := c.GetCertificate(&tls.ClientHelloInfo{ServerName: sni})
|
||||||
|
if cert != nil || err != nil {
|
||||||
|
return cert, err
|
||||||
}
|
}
|
||||||
if cert != nil {
|
}
|
||||||
|
|
||||||
|
if len(c.Certificates) == 0 {
|
||||||
|
return nil, errNoMatchingCertificate
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c.Certificates) == 1 || c.NameToCertificate == nil {
|
||||||
|
// There's only one choice, so no point doing any work.
|
||||||
|
return &c.Certificates[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
name := strings.ToLower(sni)
|
||||||
|
for len(name) > 0 && name[len(name)-1] == '.' {
|
||||||
|
name = name[:len(name)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if cert, ok := c.NameToCertificate[name]; ok {
|
||||||
|
return cert, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// try replacing labels in the name with wildcards until we get a
|
||||||
|
// match.
|
||||||
|
labels := strings.Split(name, ".")
|
||||||
|
for i := range labels {
|
||||||
|
labels[i] = "*"
|
||||||
|
candidate := strings.Join(labels, ".")
|
||||||
|
if cert, ok := c.NameToCertificate[candidate]; ok {
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.config.NameToCertificate) != 0 {
|
// If nothing matches, return the first certificate.
|
||||||
if cert, ok := c.config.NameToCertificate[sni]; ok {
|
return &c.Certificates[0], nil
|
||||||
return cert, nil
|
|
||||||
}
|
|
||||||
wildcardSNI := "*" + strings.TrimLeftFunc(sni, func(r rune) bool { return r != '.' })
|
|
||||||
if cert, ok := c.config.NameToCertificate[wildcardSNI]; ok {
|
|
||||||
return cert, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.config.Certificates) != 0 {
|
|
||||||
return &c.config.Certificates[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errNoMatchingCertificate
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ var _ = Describe("Proof", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("uses NameToCertificate entries", func() {
|
It("uses NameToCertificate entries", func() {
|
||||||
|
config.Certificates = []tls.Certificate{cert, cert} // two entries so the long path is used
|
||||||
config.NameToCertificate = map[string]*tls.Certificate{
|
config.NameToCertificate = map[string]*tls.Certificate{
|
||||||
"quic.clemente.io": &cert,
|
"quic.clemente.io": &cert,
|
||||||
}
|
}
|
||||||
@@ -94,6 +95,7 @@ var _ = Describe("Proof", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("uses NameToCertificate entries with wildcard", func() {
|
It("uses NameToCertificate entries with wildcard", func() {
|
||||||
|
config.Certificates = []tls.Certificate{cert, cert} // two entries so the long path is used
|
||||||
config.NameToCertificate = map[string]*tls.Certificate{
|
config.NameToCertificate = map[string]*tls.Certificate{
|
||||||
"*.clemente.io": &cert,
|
"*.clemente.io": &cert,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user