-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcerts.go
More file actions
141 lines (117 loc) · 2.57 KB
/
Copy pathcerts.go
File metadata and controls
141 lines (117 loc) · 2.57 KB
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package anchor
import (
"crypto/x509"
"encoding/pem"
"errors"
)
var Certs = make(CertSet)
type CertType int
const (
Unknown CertType = iota
AnchorCA
SubCA
Leaf
)
type CertInfo struct {
Algo x509.PublicKeyAlgorithm
Name string
Serial string
Type CertType
}
type CertSet map[CertInfo]*x509.Certificate
func (s CertSet) Append(cert *x509.Certificate) {
info := CertInfo{
Algo: cert.PublicKeyAlgorithm,
Name: cert.Subject.CommonName,
Serial: cert.SerialNumber.Text(16),
Type: Leaf,
}
switch {
case cert.IsCA && cert.MaxPathLenZero:
info.Type = SubCA
case cert.IsCA:
info.Type = AnchorCA
}
s[info] = cert
}
func (s CertSet) AppendPEM(data string) error {
buf := []byte(data)
var block *pem.Block
for len(buf) > 0 {
block, buf = pem.Decode(buf)
if block == nil || block.Type != "CERTIFICATE" {
return errors.New("anchor: invalid certificate PEM data")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return err
}
s.Append(cert)
}
return nil
}
func (s CertSet) AddToPool(pool *x509.CertPool) {
for _, cert := range s {
pool.AddCert(cert)
}
}
func (s CertSet) CertPool() *x509.CertPool {
pool := x509.NewCertPool()
s.AddToPool(pool)
return pool
}
func (s CertSet) Select(fns ...FilterFunc) (CertSet, error) {
ss := make(CertSet)
for info, cert := range s {
ok, err := match(info, cert, fns)
if err != nil {
return nil, err
}
if ok {
ss[info] = cert
}
}
return ss, nil
}
func (s CertSet) Find(fns ...FilterFunc) (CertInfo, *x509.Certificate, error) {
for info, cert := range s {
ok, err := match(info, cert, fns)
if err != nil {
return CertInfo{}, nil, err
}
if ok {
return info, cert, nil
}
}
return CertInfo{}, nil, nil
}
func match(info CertInfo, cert *x509.Certificate, fns []FilterFunc) (bool, error) {
for _, fn := range fns {
ok, err := fn(info, cert)
if !ok || err != nil {
return ok, err
}
}
return true, nil
}
type FilterFunc func(CertInfo, *x509.Certificate) (bool, error)
func ByAlgo(algo x509.PublicKeyAlgorithm) FilterFunc {
return func(info CertInfo, _ *x509.Certificate) (bool, error) {
return info.Algo == algo, nil
}
}
func ByName(name string) FilterFunc {
return func(info CertInfo, _ *x509.Certificate) (bool, error) {
return info.Name == name, nil
}
}
func BySerial(serial string) FilterFunc {
return func(info CertInfo, _ *x509.Certificate) (bool, error) {
return info.Serial == serial, nil
}
}
func ByType(typ CertType) FilterFunc {
return func(info CertInfo, _ *x509.Certificate) (bool, error) {
return info.Type == typ, nil
}
}