1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package acme
21
22 import (
23 "context"
24 "crypto"
25 "crypto/ecdsa"
26 "crypto/elliptic"
27 "crypto/rand"
28 "crypto/sha256"
29 "crypto/tls"
30 "crypto/x509"
31 "crypto/x509/pkix"
32 "encoding/asn1"
33 "encoding/base64"
34 "encoding/hex"
35 "encoding/json"
36 "encoding/pem"
37 "errors"
38 "fmt"
39 "math/big"
40 "net/http"
41 "strings"
42 "sync"
43 "time"
44 )
45
46 const (
47
48 LetsEncryptURL = "https://acme-v02.api.letsencrypt.org/directory"
49
50
51
52
53
54
55
56 ALPNProto = "acme-tls/1"
57 )
58
59
60
61 var idPeACMEIdentifier = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31}
62
63 const (
64 maxChainLen = 5
65 maxCertSize = 1 << 20
66
67
68 maxCertChainSize = maxCertSize * maxChainLen
69
70
71
72 maxNonces = 100
73 )
74
75
76
77
78
79
80
81
82
83
84
85 type Client struct {
86
87
88
89
90
91
92 Key crypto.Signer
93
94
95
96 HTTPClient *http.Client
97
98
99
100
101
102 DirectoryURL string
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration
119
120
121
122
123
124
125 UserAgent string
126
127 cacheMu sync.Mutex
128 dir *Directory
129
130
131 KID KeyID
132
133 noncesMu sync.Mutex
134 nonces map[string]struct{}
135 }
136
137
138
139
140
141
142
143
144
145
146 func (c *Client) accountKID(ctx context.Context) KeyID {
147 c.cacheMu.Lock()
148 defer c.cacheMu.Unlock()
149 if c.KID != noKeyID {
150 return c.KID
151 }
152 a, err := c.getRegRFC(ctx)
153 if err != nil {
154 return noKeyID
155 }
156 c.KID = KeyID(a.URI)
157 return c.KID
158 }
159
160 var errPreRFC = errors.New("acme: server does not support the RFC 8555 version of ACME")
161
162
163
164
165
166
167 func (c *Client) Discover(ctx context.Context) (Directory, error) {
168 c.cacheMu.Lock()
169 defer c.cacheMu.Unlock()
170 if c.dir != nil {
171 return *c.dir, nil
172 }
173
174 res, err := c.get(ctx, c.directoryURL(), wantStatus(http.StatusOK))
175 if err != nil {
176 return Directory{}, err
177 }
178 defer res.Body.Close()
179 c.addNonce(res.Header)
180
181 var v struct {
182 Reg string `json:"newAccount"`
183 Authz string `json:"newAuthz"`
184 Order string `json:"newOrder"`
185 Revoke string `json:"revokeCert"`
186 Nonce string `json:"newNonce"`
187 KeyChange string `json:"keyChange"`
188 Meta struct {
189 Terms string `json:"termsOfService"`
190 Website string `json:"website"`
191 CAA []string `json:"caaIdentities"`
192 ExternalAcct bool `json:"externalAccountRequired"`
193 }
194 }
195 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
196 return Directory{}, err
197 }
198 if v.Order == "" {
199 return Directory{}, errPreRFC
200 }
201 c.dir = &Directory{
202 RegURL: v.Reg,
203 AuthzURL: v.Authz,
204 OrderURL: v.Order,
205 RevokeURL: v.Revoke,
206 NonceURL: v.Nonce,
207 KeyChangeURL: v.KeyChange,
208 Terms: v.Meta.Terms,
209 Website: v.Meta.Website,
210 CAA: v.Meta.CAA,
211 ExternalAccountRequired: v.Meta.ExternalAcct,
212 }
213 return *c.dir, nil
214 }
215
216 func (c *Client) directoryURL() string {
217 if c.DirectoryURL != "" {
218 return c.DirectoryURL
219 }
220 return LetsEncryptURL
221 }
222
223
224
225
226 func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) {
227 return nil, "", errPreRFC
228 }
229
230
231
232
233
234
235
236
237
238
239
240 func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
241 if _, err := c.Discover(ctx); err != nil {
242 return nil, err
243 }
244 return c.fetchCertRFC(ctx, url, bundle)
245 }
246
247
248
249
250
251
252
253 func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
254 if _, err := c.Discover(ctx); err != nil {
255 return err
256 }
257 return c.revokeCertRFC(ctx, key, cert, reason)
258 }
259
260
261
262 func AcceptTOS(tosURL string) bool { return true }
263
264
265
266
267
268
269
270
271
272
273
274
275
276 func (c *Client) Register(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) {
277 if c.Key == nil {
278 return nil, errors.New("acme: client.Key must be set to Register")
279 }
280 if _, err := c.Discover(ctx); err != nil {
281 return nil, err
282 }
283 return c.registerRFC(ctx, acct, prompt)
284 }
285
286
287
288
289
290 func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
291 if _, err := c.Discover(ctx); err != nil {
292 return nil, err
293 }
294 return c.getRegRFC(ctx)
295 }
296
297
298
299
300
301
302 func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error) {
303 if _, err := c.Discover(ctx); err != nil {
304 return nil, err
305 }
306 return c.updateRegRFC(ctx, acct)
307 }
308
309
310
311
312
313
314
315
316
317
318
319 func (c *Client) AccountKeyRollover(ctx context.Context, newKey crypto.Signer) error {
320 return c.accountKeyRollover(ctx, newKey)
321 }
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338 func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
339 return c.authorize(ctx, "dns", domain)
340 }
341
342
343
344
345
346
347
348 func (c *Client) AuthorizeIP(ctx context.Context, ipaddr string) (*Authorization, error) {
349 return c.authorize(ctx, "ip", ipaddr)
350 }
351
352 func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization, error) {
353 if _, err := c.Discover(ctx); err != nil {
354 return nil, err
355 }
356
357 type authzID struct {
358 Type string `json:"type"`
359 Value string `json:"value"`
360 }
361 req := struct {
362 Resource string `json:"resource"`
363 Identifier authzID `json:"identifier"`
364 }{
365 Resource: "new-authz",
366 Identifier: authzID{Type: typ, Value: val},
367 }
368 res, err := c.post(ctx, nil, c.dir.AuthzURL, req, wantStatus(http.StatusCreated))
369 if err != nil {
370 return nil, err
371 }
372 defer res.Body.Close()
373
374 var v wireAuthz
375 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
376 return nil, fmt.Errorf("acme: invalid response: %v", err)
377 }
378 if v.Status != StatusPending && v.Status != StatusValid {
379 return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
380 }
381 return v.authorization(res.Header.Get("Location")), nil
382 }
383
384
385
386
387
388 func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
389 if _, err := c.Discover(ctx); err != nil {
390 return nil, err
391 }
392
393 res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
394 if err != nil {
395 return nil, err
396 }
397 defer res.Body.Close()
398 var v wireAuthz
399 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
400 return nil, fmt.Errorf("acme: invalid response: %v", err)
401 }
402 return v.authorization(url), nil
403 }
404
405
406
407
408
409
410
411
412
413
414 func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
415 if _, err := c.Discover(ctx); err != nil {
416 return err
417 }
418
419 req := struct {
420 Resource string `json:"resource"`
421 Status string `json:"status"`
422 Delete bool `json:"delete"`
423 }{
424 Resource: "authz",
425 Status: "deactivated",
426 Delete: true,
427 }
428 res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
429 if err != nil {
430 return err
431 }
432 defer res.Body.Close()
433 return nil
434 }
435
436
437
438
439
440
441
442
443 func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
444 if _, err := c.Discover(ctx); err != nil {
445 return nil, err
446 }
447 for {
448 res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
449 if err != nil {
450 return nil, err
451 }
452
453 var raw wireAuthz
454 err = json.NewDecoder(res.Body).Decode(&raw)
455 res.Body.Close()
456 switch {
457 case err != nil:
458
459 case raw.Status == StatusValid:
460 return raw.authorization(url), nil
461 case raw.Status == StatusInvalid:
462 return nil, raw.error(url)
463 }
464
465
466
467
468 d := retryAfter(res.Header.Get("Retry-After"))
469 if d == 0 {
470
471
472
473
474 d = time.Second
475 }
476 t := time.NewTimer(d)
477 select {
478 case <-ctx.Done():
479 t.Stop()
480 return nil, ctx.Err()
481 case <-t.C:
482
483 }
484 }
485 }
486
487
488
489
490 func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
491 if _, err := c.Discover(ctx); err != nil {
492 return nil, err
493 }
494
495 res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
496 if err != nil {
497 return nil, err
498 }
499
500 defer res.Body.Close()
501 v := wireChallenge{URI: url}
502 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
503 return nil, fmt.Errorf("acme: invalid response: %v", err)
504 }
505 return v.challenge(), nil
506 }
507
508
509
510
511
512 func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
513 if _, err := c.Discover(ctx); err != nil {
514 return nil, err
515 }
516
517 res, err := c.post(ctx, nil, chal.URI, json.RawMessage("{}"), wantStatus(
518 http.StatusOK,
519 http.StatusAccepted,
520 ))
521 if err != nil {
522 return nil, err
523 }
524 defer res.Body.Close()
525
526 var v wireChallenge
527 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
528 return nil, fmt.Errorf("acme: invalid response: %v", err)
529 }
530 return v.challenge(), nil
531 }
532
533
534
535
536
537
538 func (c *Client) DNS01ChallengeRecord(token string) (string, error) {
539 ka, err := keyAuth(c.Key.Public(), token)
540 if err != nil {
541 return "", err
542 }
543 b := sha256.Sum256([]byte(ka))
544 return base64.RawURLEncoding.EncodeToString(b[:]), nil
545 }
546
547
548
549
550
551
552
553 func (c *Client) HTTP01ChallengeResponse(token string) (string, error) {
554 return keyAuth(c.Key.Public(), token)
555 }
556
557
558
559
560
561
562 func (c *Client) HTTP01ChallengePath(token string) string {
563 return "/.well-known/acme-challenge/" + token
564 }
565
566
567
568
569 func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
570 ka, err := keyAuth(c.Key.Public(), token)
571 if err != nil {
572 return tls.Certificate{}, "", err
573 }
574 b := sha256.Sum256([]byte(ka))
575 h := hex.EncodeToString(b[:])
576 name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:])
577 cert, err = tlsChallengeCert([]string{name}, opt)
578 if err != nil {
579 return tls.Certificate{}, "", err
580 }
581 return cert, name, nil
582 }
583
584
585
586
587 func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
588 b := sha256.Sum256([]byte(token))
589 h := hex.EncodeToString(b[:])
590 sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:])
591
592 ka, err := keyAuth(c.Key.Public(), token)
593 if err != nil {
594 return tls.Certificate{}, "", err
595 }
596 b = sha256.Sum256([]byte(ka))
597 h = hex.EncodeToString(b[:])
598 sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:])
599
600 cert, err = tlsChallengeCert([]string{sanA, sanB}, opt)
601 if err != nil {
602 return tls.Certificate{}, "", err
603 }
604 return cert, sanA, nil
605 }
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620 func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error) {
621 ka, err := keyAuth(c.Key.Public(), token)
622 if err != nil {
623 return tls.Certificate{}, err
624 }
625 shasum := sha256.Sum256([]byte(ka))
626 extValue, err := asn1.Marshal(shasum[:])
627 if err != nil {
628 return tls.Certificate{}, err
629 }
630 acmeExtension := pkix.Extension{
631 Id: idPeACMEIdentifier,
632 Critical: true,
633 Value: extValue,
634 }
635
636 tmpl := defaultTLSChallengeCertTemplate()
637
638 var newOpt []CertOption
639 for _, o := range opt {
640 switch o := o.(type) {
641 case *certOptTemplate:
642 t := *(*x509.Certificate)(o)
643 tmpl = &t
644 default:
645 newOpt = append(newOpt, o)
646 }
647 }
648 tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension)
649 newOpt = append(newOpt, WithTemplate(tmpl))
650 return tlsChallengeCert([]string{domain}, newOpt)
651 }
652
653
654
655
656
657 func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
658 c.noncesMu.Lock()
659 defer c.noncesMu.Unlock()
660 if len(c.nonces) == 0 {
661 if c.dir != nil && c.dir.NonceURL != "" {
662 return c.fetchNonce(ctx, c.dir.NonceURL)
663 }
664 dirURL := c.directoryURL()
665 v, err := c.fetchNonce(ctx, dirURL)
666 if err != nil && url != dirURL {
667 v, err = c.fetchNonce(ctx, url)
668 }
669 return v, err
670 }
671 var nonce string
672 for nonce = range c.nonces {
673 delete(c.nonces, nonce)
674 break
675 }
676 return nonce, nil
677 }
678
679
680 func (c *Client) clearNonces() {
681 c.noncesMu.Lock()
682 defer c.noncesMu.Unlock()
683 c.nonces = make(map[string]struct{})
684 }
685
686
687 func (c *Client) addNonce(h http.Header) {
688 v := nonceFromHeader(h)
689 if v == "" {
690 return
691 }
692 c.noncesMu.Lock()
693 defer c.noncesMu.Unlock()
694 if len(c.nonces) >= maxNonces {
695 return
696 }
697 if c.nonces == nil {
698 c.nonces = make(map[string]struct{})
699 }
700 c.nonces[v] = struct{}{}
701 }
702
703 func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
704 r, err := http.NewRequest("HEAD", url, nil)
705 if err != nil {
706 return "", err
707 }
708 resp, err := c.doNoRetry(ctx, r)
709 if err != nil {
710 return "", err
711 }
712 defer resp.Body.Close()
713 nonce := nonceFromHeader(resp.Header)
714 if nonce == "" {
715 if resp.StatusCode > 299 {
716 return "", responseError(resp)
717 }
718 return "", errors.New("acme: nonce not found")
719 }
720 return nonce, nil
721 }
722
723 func nonceFromHeader(h http.Header) string {
724 return h.Get("Replay-Nonce")
725 }
726
727
728
729
730 func linkHeader(h http.Header, rel string) []string {
731 var links []string
732 for _, v := range h["Link"] {
733 parts := strings.Split(v, ";")
734 for _, p := range parts {
735 p = strings.TrimSpace(p)
736 if !strings.HasPrefix(p, "rel=") {
737 continue
738 }
739 if v := strings.Trim(p[4:], `"`); v == rel {
740 links = append(links, strings.Trim(parts[0], "<>"))
741 }
742 }
743 }
744 return links
745 }
746
747
748 func keyAuth(pub crypto.PublicKey, token string) (string, error) {
749 th, err := JWKThumbprint(pub)
750 if err != nil {
751 return "", err
752 }
753 return fmt.Sprintf("%s.%s", token, th), nil
754 }
755
756
757 func defaultTLSChallengeCertTemplate() *x509.Certificate {
758 return &x509.Certificate{
759 SerialNumber: big.NewInt(1),
760 NotBefore: time.Now(),
761 NotAfter: time.Now().Add(24 * time.Hour),
762 BasicConstraintsValid: true,
763 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
764 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
765 }
766 }
767
768
769
770
771
772 func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
773 var key crypto.Signer
774 tmpl := defaultTLSChallengeCertTemplate()
775 for _, o := range opt {
776 switch o := o.(type) {
777 case *certOptKey:
778 if key != nil {
779 return tls.Certificate{}, errors.New("acme: duplicate key option")
780 }
781 key = o.key
782 case *certOptTemplate:
783 t := *(*x509.Certificate)(o)
784 tmpl = &t
785 default:
786
787 panic(fmt.Sprintf("unsupported option type %T", o))
788 }
789 }
790 if key == nil {
791 var err error
792 if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
793 return tls.Certificate{}, err
794 }
795 }
796 tmpl.DNSNames = san
797 if len(san) > 0 {
798 tmpl.Subject.CommonName = san[0]
799 }
800
801 der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
802 if err != nil {
803 return tls.Certificate{}, err
804 }
805 return tls.Certificate{
806 Certificate: [][]byte{der},
807 PrivateKey: key,
808 }, nil
809 }
810
811
812 func encodePEM(typ string, b []byte) []byte {
813 pb := &pem.Block{Type: typ, Bytes: b}
814 return pem.EncodeToMemory(pb)
815 }
816
817
818 var timeNow = time.Now
819
View as plain text