aboutsummaryrefslogtreecommitdiff
path: root/crypto/tls/ocsp_manager.go
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/tls/ocsp_manager.go')
-rw-r--r--crypto/tls/ocsp_manager.go134
1 files changed, 0 insertions, 134 deletions
diff --git a/crypto/tls/ocsp_manager.go b/crypto/tls/ocsp_manager.go
deleted file mode 100644
index dac4c5e..0000000
--- a/crypto/tls/ocsp_manager.go
+++ /dev/null
@@ -1,134 +0,0 @@
1package tls
2
3import (
4 "context"
5 "crypto/tls"
6 "errors"
7 "fmt"
8 "sync"
9 "time"
10
11 "golang.org/x/crypto/ocsp"
12)
13
14type OcspError struct {
15 Err error
16 AtBoot bool
17}
18
19func (e OcspError) Error() string {
20 return e.Err.Error()
21}
22
23func (e OcspError) Unwrap() error {
24 return e.Err
25}
26
27type OcspLogger interface {
28 Info(...interface{})
29 Errorf(string, ...interface{})
30}
31
32func OcspErrorLogger(l OcspLogger, c <-chan OcspError) func(context.Context, *sync.WaitGroup) error {
33 return func(ctx context.Context, wg *sync.WaitGroup) error {
34 wg.Add(1)
35 defer wg.Done()
36
37 for {
38 select {
39 case err := <-c:
40 l.Errorf("Error in OCSP stapling: %w", errors.Unwrap(err))
41 case <-ctx.Done():
42 l.Info("Shutting down OCSP logger")
43 return nil
44 }
45 }
46 }
47}
48
49type OcspManager struct {
50 CertPath, KeyPath string
51 Errors chan<- OcspError
52 cert *tls.Certificate
53 ocspRes *ocsp.Response
54 sync.RWMutex
55}
56
57func (m *OcspManager) loadCert() error {
58 cert, err := tls.LoadX509KeyPair(m.CertPath, m.KeyPath)
59 if err != nil {
60 return err
61 }
62 m.Lock()
63 m.cert = &cert
64 m.Unlock()
65
66 return nil
67}
68
69func (m *OcspManager) stapleCert() error {
70 // This makes a network request to an unknown server so don't hold the full
71 // lock while this is happening
72 m.RLock()
73 raw, ocspRes, err := GetOcspResponse(m.cert)
74 if err != nil {
75 return err
76 }
77 m.RUnlock()
78
79 m.Lock()
80 m.cert.OCSPStaple = raw
81 m.ocspRes = ocspRes
82 m.Unlock()
83
84 return nil
85}
86
87func (m *OcspManager) Init() error {
88 // All functions called here will handle locking themselves
89 if err := m.loadCert(); err != nil {
90 return err
91 }
92
93 if err := m.stapleCert(); err != nil {
94 return err
95 }
96
97 return nil
98}
99
100func (m *OcspManager) Run(ctx context.Context, wg *sync.WaitGroup) error {
101 wg.Add(1)
102 defer wg.Done()
103
104 t := time.NewTimer(m.ocspRes.NextUpdate.Sub(time.Now()) - time.Hour)
105
106 for {
107 select {
108 case <-t.C:
109 if err := m.stapleCert(); err != nil {
110 if m.Errors != nil {
111 m.Errors <- OcspError{err, false}
112 }
113 t.Reset(time.Hour)
114 continue
115 }
116 // We own this object and only we write it, no need to lock
117 t.Reset(m.ocspRes.NextUpdate.Sub(time.Now()) - time.Hour)
118 case <-ctx.Done():
119 return nil
120 }
121 }
122}
123
124// TODO: TLS.GetCertificate for dyanmic certs for LE (cache these)
125func (m *OcspManager) GetCertificate(h *tls.ClientHelloInfo) (*tls.Certificate, error) {
126 m.RLock()
127 defer m.RUnlock()
128
129 if m.cert != nil {
130 return m.cert, nil
131 }
132
133 return nil, fmt.Errorf("OCSP manager has no certificate stored")
134}