/
poolbuffer.go
142 lines (111 loc) · 2.68 KB
/
poolbuffer.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
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
142
package certpool
import (
"crypto/x509"
"encoding/pem"
"sync"
"sync/atomic"
"darvaza.org/darvaza/shared/x509utils"
)
// PoolBuffer is a CertPool in the making
type PoolBuffer struct {
mu sync.Mutex
logger atomic.Value
index map[Hash]*pbCertData
roots CertPool
inter CertPool
certs CertPool
keys pbKeys
}
// Reset makes the PoolBuffer go back to its initial state, empty
func (pb *PoolBuffer) Reset() {
pb.mu.Lock()
defer pb.mu.Unlock()
pb.index = nil
pb.roots.Reset()
pb.inter.Reset()
pb.certs.Reset()
pb.keys.Reset()
}
// AddKey adds a PrivateKey to the PoolBuffer
func (pb *PoolBuffer) AddKey(fn string, pk x509utils.PrivateKey) error {
var err error
if pk != nil {
pb.mu.Lock()
defer pb.mu.Unlock()
err = pb.addKeyUnlocked(fn, pk)
}
return err
}
// AddCert adds a Certificate to the PoolBuffer
func (pb *PoolBuffer) AddCert(fn string, cert *x509.Certificate) error {
var err error
if cert != nil {
pb.mu.Lock()
defer pb.mu.Unlock()
err = pb.addCertUnlocked(fn, cert)
}
return err
}
// Add loads private keys and certificates from PEM files, directories, and direct text
func (pb *PoolBuffer) Add(data ...string) error {
pb.mu.Lock()
defer pb.mu.Unlock()
for _, s := range data {
var addErr error
readErr := x509utils.ReadStringPEM(s, func(fn string, block *pem.Block) bool {
if err := pb.addBlock(fn, block); err != nil {
addErr = err
}
return addErr != nil
})
switch {
case addErr != nil:
return addErr
case readErr != nil:
return readErr
}
}
return nil
}
func (pb *PoolBuffer) addBlock(fn string, block *pem.Block) error {
if pk, err := x509utils.BlockToPrivateKey(block); pk != nil {
// PrivateKey
return pb.addKeyUnlocked(fn, pk)
} else if err != x509utils.ErrIgnored {
// Bad PrivateKey
return err
}
if cert, err := x509utils.BlockToCertificate(block); cert != nil {
// Certificate
return pb.addCertUnlocked(fn, cert)
} else if err != x509utils.ErrIgnored {
// Bad Certificate
return err
}
// Ignore other blocks
return nil
}
// Count returns how many certificates are in the buffer
func (pb *PoolBuffer) Count() int {
pb.mu.Lock()
defer pb.mu.Unlock()
return len(pb.index)
}
// Export returns a new x509.CertPool with the CA certificates
func (pb *PoolBuffer) Export() *x509.CertPool {
pb.mu.Lock()
defer pb.mu.Unlock()
return pb.inter.Export()
}
// Pool returns a new CertPool with the CA certificates
func (pb *PoolBuffer) Pool() *CertPool {
pb.mu.Lock()
defer pb.mu.Unlock()
return pb.inter.Copy(nil)
}
// CopyPool copies the CA certificates into the given CertPool
func (pb *PoolBuffer) CopyPool(out *CertPool) *CertPool {
pb.mu.Lock()
defer pb.mu.Unlock()
return pb.inter.Copy(out)
}