diff options
Diffstat (limited to 'crypto/tls/ocsp_manager.go')
-rw-r--r-- | crypto/tls/ocsp_manager.go | 134 |
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 @@ | |||
1 | package tls | ||
2 | |||
3 | import ( | ||
4 | "context" | ||
5 | "crypto/tls" | ||
6 | "errors" | ||
7 | "fmt" | ||
8 | "sync" | ||
9 | "time" | ||
10 | |||
11 | "golang.org/x/crypto/ocsp" | ||
12 | ) | ||
13 | |||
14 | type OcspError struct { | ||
15 | Err error | ||
16 | AtBoot bool | ||
17 | } | ||
18 | |||
19 | func (e OcspError) Error() string { | ||
20 | return e.Err.Error() | ||
21 | } | ||
22 | |||
23 | func (e OcspError) Unwrap() error { | ||
24 | return e.Err | ||
25 | } | ||
26 | |||
27 | type OcspLogger interface { | ||
28 | Info(...interface{}) | ||
29 | Errorf(string, ...interface{}) | ||
30 | } | ||
31 | |||
32 | func 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 | |||
49 | type OcspManager struct { | ||
50 | CertPath, KeyPath string | ||
51 | Errors chan<- OcspError | ||
52 | cert *tls.Certificate | ||
53 | ocspRes *ocsp.Response | ||
54 | sync.RWMutex | ||
55 | } | ||
56 | |||
57 | func (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 | |||
69 | func (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 | |||
87 | func (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 | |||
100 | func (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) | ||
125 | func (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 | } | ||