summaryrefslogtreecommitdiff
path: root/vendor/github.com/pion/dtls/v2/certificate.go
blob: c99e1c93d790d7b41136c1163250a9ebc1228ab0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package dtls

import (
	"crypto/tls"
	"crypto/x509"
	"strings"
)

func (c *handshakeConfig) getCertificate(serverName string) (*tls.Certificate, error) {
	c.mu.Lock()
	defer c.mu.Unlock()

	if c.nameToCertificate == nil {
		nameToCertificate := make(map[string]*tls.Certificate)
		for i := range c.localCertificates {
			cert := &c.localCertificates[i]
			x509Cert := cert.Leaf
			if x509Cert == nil {
				var parseErr error
				x509Cert, parseErr = x509.ParseCertificate(cert.Certificate[0])
				if parseErr != nil {
					continue
				}
			}
			if len(x509Cert.Subject.CommonName) > 0 {
				nameToCertificate[strings.ToLower(x509Cert.Subject.CommonName)] = cert
			}
			for _, san := range x509Cert.DNSNames {
				nameToCertificate[strings.ToLower(san)] = cert
			}
		}
		c.nameToCertificate = nameToCertificate
	}

	if len(c.localCertificates) == 0 {
		return nil, errNoCertificates
	}

	if len(c.localCertificates) == 1 {
		// There's only one choice, so no point doing any work.
		return &c.localCertificates[0], nil
	}

	if len(serverName) == 0 {
		return &c.localCertificates[0], nil
	}

	name := strings.TrimRight(strings.ToLower(serverName), ".")

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

	// If nothing matches, return the first certificate.
	return &c.localCertificates[0], nil
}