-
Notifications
You must be signed in to change notification settings - Fork 432
/
errors.go
439 lines (402 loc) · 10.7 KB
/
errors.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
package acme
import (
"github.com/pkg/errors"
)
// AccountDoesNotExistErr returns a new acme error.
func AccountDoesNotExistErr(err error) *Error {
return &Error{
Type: accountDoesNotExistErr,
Detail: "Account does not exist",
Status: 400,
Err: err,
}
}
// AlreadyRevokedErr returns a new acme error.
func AlreadyRevokedErr(err error) *Error {
return &Error{
Type: alreadyRevokedErr,
Detail: "Certificate already revoked",
Status: 400,
Err: err,
}
}
// BadCSRErr returns a new acme error.
func BadCSRErr(err error) *Error {
return &Error{
Type: badCSRErr,
Detail: "The CSR is unacceptable",
Status: 400,
Err: err,
}
}
// BadNonceErr returns a new acme error.
func BadNonceErr(err error) *Error {
return &Error{
Type: badNonceErr,
Detail: "Unacceptable anti-replay nonce",
Status: 400,
Err: err,
}
}
// BadPublicKeyErr returns a new acme error.
func BadPublicKeyErr(err error) *Error {
return &Error{
Type: badPublicKeyErr,
Detail: "The jws was signed by a public key the server does not support",
Status: 400,
Err: err,
}
}
// BadRevocationReasonErr returns a new acme error.
func BadRevocationReasonErr(err error) *Error {
return &Error{
Type: badRevocationReasonErr,
Detail: "The revocation reason provided is not allowed by the server",
Status: 400,
Err: err,
}
}
// BadSignatureAlgorithmErr returns a new acme error.
func BadSignatureAlgorithmErr(err error) *Error {
return &Error{
Type: badSignatureAlgorithmErr,
Detail: "The JWS was signed with an algorithm the server does not support",
Status: 400,
Err: err,
}
}
// CaaErr returns a new acme error.
func CaaErr(err error) *Error {
return &Error{
Type: caaErr,
Detail: "Certification Authority Authorization (CAA) records forbid the CA from issuing a certificate",
Status: 400,
Err: err,
}
}
// CompoundErr returns a new acme error.
func CompoundErr(err error) *Error {
return &Error{
Type: compoundErr,
Detail: "Specific error conditions are indicated in the “subproblems” array",
Status: 400,
Err: err,
}
}
// ConnectionErr returns a new acme error.
func ConnectionErr(err error) *Error {
return &Error{
Type: connectionErr,
Detail: "The server could not connect to validation target",
Status: 400,
Err: err,
}
}
// DNSErr returns a new acme error.
func DNSErr(err error) *Error {
return &Error{
Type: dnsErr,
Detail: "There was a problem with a DNS query during identifier validation",
Status: 400,
Err: err,
}
}
// ExternalAccountRequiredErr returns a new acme error.
func ExternalAccountRequiredErr(err error) *Error {
return &Error{
Type: externalAccountRequiredErr,
Detail: "The request must include a value for the \"externalAccountBinding\" field",
Status: 400,
Err: err,
}
}
// IncorrectResponseErr returns a new acme error.
func IncorrectResponseErr(err error) *Error {
return &Error{
Type: incorrectResponseErr,
Detail: "Response received didn't match the challenge's requirements",
Status: 400,
Err: err,
}
}
// InvalidContactErr returns a new acme error.
func InvalidContactErr(err error) *Error {
return &Error{
Type: invalidContactErr,
Detail: "A contact URL for an account was invalid",
Status: 400,
Err: err,
}
}
// MalformedErr returns a new acme error.
func MalformedErr(err error) *Error {
return &Error{
Type: malformedErr,
Detail: "The request message was malformed",
Status: 400,
Err: err,
}
}
// OrderNotReadyErr returns a new acme error.
func OrderNotReadyErr(err error) *Error {
return &Error{
Type: orderNotReadyErr,
Detail: "The request attempted to finalize an order that is not ready to be finalized",
Status: 400,
Err: err,
}
}
// RateLimitedErr returns a new acme error.
func RateLimitedErr(err error) *Error {
return &Error{
Type: rateLimitedErr,
Detail: "The request exceeds a rate limit",
Status: 400,
Err: err,
}
}
// RejectedIdentifierErr returns a new acme error.
func RejectedIdentifierErr(err error) *Error {
return &Error{
Type: rejectedIdentifierErr,
Detail: "The server will not issue certificates for the identifier",
Status: 400,
Err: err,
}
}
// ServerInternalErr returns a new acme error.
func ServerInternalErr(err error) *Error {
return &Error{
Type: serverInternalErr,
Detail: "The server experienced an internal error",
Status: 500,
Err: err,
}
}
// TLSErr returns a new acme error.
func TLSErr(err error) *Error {
return &Error{
Type: tlsErr,
Detail: "The server received a TLS error during validation",
Status: 400,
Err: err,
}
}
// UnauthorizedErr returns a new acme error.
func UnauthorizedErr(err error) *Error {
return &Error{
Type: unauthorizedErr,
Detail: "The client lacks sufficient authorization",
Status: 401,
Err: err,
}
}
// UnsupportedContactErr returns a new acme error.
func UnsupportedContactErr(err error) *Error {
return &Error{
Type: unsupportedContactErr,
Detail: "A contact URL for an account used an unsupported protocol scheme",
Status: 400,
Err: err,
}
}
// UnsupportedIdentifierErr returns a new acme error.
func UnsupportedIdentifierErr(err error) *Error {
return &Error{
Type: unsupportedIdentifierErr,
Detail: "An identifier is of an unsupported type",
Status: 400,
Err: err,
}
}
// UserActionRequiredErr returns a new acme error.
func UserActionRequiredErr(err error) *Error {
return &Error{
Type: userActionRequiredErr,
Detail: "Visit the “instance” URL and take actions specified there",
Status: 400,
Err: err,
}
}
// ProbType is the type of the ACME problem.
type ProbType int
const (
// The request specified an account that does not exist
accountDoesNotExistErr ProbType = iota
// The request specified a certificate to be revoked that has already been revoked
alreadyRevokedErr
// The CSR is unacceptable (e.g., due to a short key)
badCSRErr
// The client sent an unacceptable anti-replay nonce
badNonceErr
// The JWS was signed by a public key the server does not support
badPublicKeyErr
// The revocation reason provided is not allowed by the server
badRevocationReasonErr
// The JWS was signed with an algorithm the server does not support
badSignatureAlgorithmErr
// Certification Authority Authorization (CAA) records forbid the CA from issuing a certificate
caaErr
// Specific error conditions are indicated in the “subproblems” array.
compoundErr
// The server could not connect to validation target
connectionErr
// There was a problem with a DNS query during identifier validation
dnsErr
// The request must include a value for the “externalAccountBinding” field
externalAccountRequiredErr
// Response received didn’t match the challenge’s requirements
incorrectResponseErr
// A contact URL for an account was invalid
invalidContactErr
// The request message was malformed
malformedErr
// The request attempted to finalize an order that is not ready to be finalized
orderNotReadyErr
// The request exceeds a rate limit
rateLimitedErr
// The server will not issue certificates for the identifier
rejectedIdentifierErr
// The server experienced an internal error
serverInternalErr
// The server received a TLS error during validation
tlsErr
// The client lacks sufficient authorization
unauthorizedErr
// A contact URL for an account used an unsupported protocol scheme
unsupportedContactErr
// An identifier is of an unsupported type
unsupportedIdentifierErr
// Visit the “instance” URL and take actions specified there
userActionRequiredErr
)
// String returns the string representation of the acme problem type,
// fulfilling the Stringer interface.
func (ap ProbType) String() string {
switch ap {
case accountDoesNotExistErr:
return "accountDoesNotExist"
case alreadyRevokedErr:
return "alreadyRevoked"
case badCSRErr:
return "badCSR"
case badNonceErr:
return "badNonce"
case badPublicKeyErr:
return "badPublicKey"
case badRevocationReasonErr:
return "badRevocationReason"
case badSignatureAlgorithmErr:
return "badSignatureAlgorithm"
case caaErr:
return "caa"
case compoundErr:
return "compound"
case connectionErr:
return "connection"
case dnsErr:
return "dns"
case externalAccountRequiredErr:
return "externalAccountRequired"
case incorrectResponseErr:
return "incorrectResponse"
case invalidContactErr:
return "invalidContact"
case malformedErr:
return "malformed"
case orderNotReadyErr:
return "orderNotReady"
case rateLimitedErr:
return "rateLimited"
case rejectedIdentifierErr:
return "rejectedIdentifier"
case serverInternalErr:
return "serverInternal"
case tlsErr:
return "tls"
case unauthorizedErr:
return "unauthorized"
case unsupportedContactErr:
return "unsupportedContact"
case unsupportedIdentifierErr:
return "unsupportedIdentifier"
case userActionRequiredErr:
return "userActionRequired"
default:
return "unsupported type"
}
}
// Error is an ACME error type complete with problem document.
type Error struct {
Type ProbType
Detail string
Err error
Status int
Sub []*Error
Identifier *Identifier
}
// Wrap attempts to wrap the internal error.
func Wrap(err error, wrap string) *Error {
switch e := err.(type) {
case nil:
return nil
case *Error:
if e.Err == nil {
e.Err = errors.New(wrap + "; " + e.Detail)
} else {
e.Err = errors.Wrap(e.Err, wrap)
}
return e
default:
return ServerInternalErr(errors.Wrap(err, wrap))
}
}
// Error implements the error interface.
func (e *Error) Error() string {
if e.Err == nil {
return e.Detail
}
return e.Err.Error()
}
// Cause returns the internal error and implements the Causer interface.
func (e *Error) Cause() error {
if e.Err == nil {
return errors.New(e.Detail)
}
return e.Err
}
// ToACME returns an acme representation of the problem type.
func (e *Error) ToACME() *AError {
ae := &AError{
Type: "urn:ietf:params:acme:error:" + e.Type.String(),
Detail: e.Error(),
Status: e.Status,
}
if e.Identifier != nil {
ae.Identifier = *e.Identifier
}
for _, p := range e.Sub {
ae.Subproblems = append(ae.Subproblems, p.ToACME())
}
return ae
}
// StatusCode returns the status code and implements the StatusCode interface.
func (e *Error) StatusCode() int {
return e.Status
}
// AError is the error type as seen in acme request/responses.
type AError struct {
Type string `json:"type"`
Detail string `json:"detail"`
Identifier interface{} `json:"identifier,omitempty"`
Subproblems []interface{} `json:"subproblems,omitempty"`
Status int `json:"-"`
}
// Error allows AError to implement the error interface.
func (ae *AError) Error() string {
return ae.Detail
}
// StatusCode returns the status code and implements the StatusCode interface.
func (ae *AError) StatusCode() int {
return ae.Status
}