forked from globalsign/certlint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
type.go
115 lines (100 loc) · 2.8 KB
/
type.go
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package certdata
import (
"crypto/x509"
"encoding/asn1"
"fmt"
"strings"
psl "golang.org/x/net/publicsuffix"
)
// setCertificateType set the base on how we check for other requirements of the
// certificate. It's important that we reliably identify the purpose to apply
// the right checks for that certificate type.
func (d *Data) setCertificateType() error {
// We want to be able to detect 'false' CA certificates, classify as CA
// certificate is basic contains and key usage certsign are set.
if d.Cert.IsCA && d.Cert.KeyUsage&x509.KeyUsageCertSign != 0 {
d.Type = "CA"
return nil
}
// The fallback type is used when a certificate could be any of a range
// but further checks need to define the exact type. When these checks fail
// the fallback type is used.
var fallbackType string
// Based on ExtKeyUsage
for _, ku := range d.Cert.ExtKeyUsage {
switch ku {
case x509.ExtKeyUsageServerAuth:
// Try to determine certificate type via policy oid
d.Type = getType(d.Cert.PolicyIdentifiers)
fallbackType = "DV"
case x509.ExtKeyUsageClientAuth:
fallbackType = "PS"
case x509.ExtKeyUsageEmailProtection:
d.Type = "PS"
case x509.ExtKeyUsageCodeSigning:
d.Type = "CS"
case x509.ExtKeyUsageTimeStamping:
d.Type = "TS"
case x509.ExtKeyUsageOCSPSigning:
d.Type = "OCSP"
}
}
// If we have no known key usage, try the policy list again
if d.Type == "" {
d.Type = getType(d.Cert.PolicyIdentifiers)
}
// When determined by Policy Identifier we can stop
if d.Type != "" {
return nil
}
// Based on UnknownExtKeyUsage
for _, ku := range d.Cert.UnknownExtKeyUsage {
switch {
case ku.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 21, 19}):
// dsEmailReplication
d.Type = "PS"
return nil
case ku.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 8, 2, 2}):
// IPSEC Protection
d.Type = "IPSEC"
return nil
}
}
// Check if the e-mailAddress is set in the DN
for _, n := range d.Cert.Subject.Names {
switch {
case n.Type.Equal(asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}): // e-mailAddress
d.Type = "PS"
return nil
}
}
// An @ sing in the common name is often used in PS.
if strings.Contains(d.Cert.Subject.CommonName, "@") {
d.Type = "PS"
return nil
} else if strings.Contains(d.Cert.Subject.CommonName, " ") {
d.Type = "PS"
return nil
}
// If it's a fqdn, it's a EV, OV or DV
if suffix, _ := psl.PublicSuffix(strings.ToLower(d.Cert.Subject.CommonName)); len(suffix) > 0 {
if len(d.Cert.Subject.Organization) > 0 {
if len(d.Cert.Subject.SerialNumber) > 0 {
d.Type = "EV"
return nil
}
d.Type = "OV"
return nil
}
d.Type = "DV"
return nil
}
if len(fallbackType) > 0 {
d.Type = fallbackType
return nil
}
if d.Type == "" {
return fmt.Errorf("Could not determine certificate type")
}
return nil
}