@@ -31,12 +31,11 @@ import (
3131 "crypto/x509/pkix"
3232 "encoding/asn1"
3333 "encoding/base64"
34- "encoding/hex"
3534 "encoding/json"
36- "encoding/pem"
3735 "errors"
3836 "fmt"
3937 "math/big"
38+ "net"
4039 "net/http"
4140 "strings"
4241 "sync"
@@ -353,6 +352,10 @@ func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization
353352 if _ , err := c .Discover (ctx ); err != nil {
354353 return nil , err
355354 }
355+ if c .dir .AuthzURL == "" {
356+ // Pre-Authorization is unsupported
357+ return nil , errPreAuthorizationNotSupported
358+ }
356359
357360 type authzID struct {
358361 Type string `json:"type"`
@@ -467,7 +470,7 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
467470 // while waiting for a final authorization status.
468471 d := retryAfter (res .Header .Get ("Retry-After" ))
469472 if d == 0 {
470- // Given that the fastest challenges TLS-SNI and HTTP-01
473+ // Given that the fastest challenges TLS-ALPN and HTTP-01
471474 // require a CA to make at least 1 network round trip
472475 // and most likely persist a challenge state,
473476 // this default delay seems reasonable.
@@ -514,7 +517,11 @@ func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error
514517 return nil , err
515518 }
516519
517- res , err := c .post (ctx , nil , chal .URI , json .RawMessage ("{}" ), wantStatus (
520+ payload := json .RawMessage ("{}" )
521+ if len (chal .Payload ) != 0 {
522+ payload = chal .Payload
523+ }
524+ res , err := c .post (ctx , nil , chal .URI , payload , wantStatus (
518525 http .StatusOK , // according to the spec
519526 http .StatusAccepted , // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md)
520527 ))
@@ -564,60 +571,42 @@ func (c *Client) HTTP01ChallengePath(token string) string {
564571}
565572
566573// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
574+ // Always returns an error.
567575//
568- // Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec.
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
576+ // Deprecated: This challenge type was only present in pre-standardized ACME
577+ // protocol drafts and is insecure for use in shared hosting environments.
578+ func (c * Client ) TLSSNI01ChallengeCert (token string , opt ... CertOption ) (tls.Certificate , string , error ) {
579+ return tls.Certificate {}, "" , errPreRFC
582580}
583581
584582// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
583+ // Always returns an error.
585584//
586- // Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec.
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
585+ // Deprecated: This challenge type was only present in pre-standardized ACME
586+ // protocol drafts and is insecure for use in shared hosting environments.
587+ func (c * Client ) TLSSNI02ChallengeCert (token string , opt ... CertOption ) (tls.Certificate , string , error ) {
588+ return tls.Certificate {}, "" , errPreRFC
605589}
606590
607591// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response.
608592// Servers can present the certificate to validate the challenge and prove control
609- // over a domain name. For more details on TLS-ALPN-01 see
610- // https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-3
593+ // over an identifier (either a DNS name or the textual form of an IPv4 or IPv6
594+ // address). For more details on TLS-ALPN-01 see
595+ // https://www.rfc-editor.org/rfc/rfc8737 and https://www.rfc-editor.org/rfc/rfc8738
611596//
612597// The token argument is a Challenge.Token value.
613598// If a WithKey option is provided, its private part signs the returned cert,
614599// and the public part is used to specify the signee.
615600// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
616601//
617602// The returned certificate is valid for the next 24 hours and must be presented only when
618- // the server name in the TLS ClientHello matches the domain , and the special acme-tls/1 ALPN protocol
603+ // the server name in the TLS ClientHello matches the identifier , and the special acme-tls/1 ALPN protocol
619604// has been specified.
620- func (c * Client ) TLSALPN01ChallengeCert (token , domain string , opt ... CertOption ) (cert tls.Certificate , err error ) {
605+ //
606+ // Validation requests for IP address identifiers will use the reverse DNS form in the server name
607+ // in the TLS ClientHello since the SNI extension is not supported for IP addresses.
608+ // See RFC 8738 Section 6 for more information.
609+ func (c * Client ) TLSALPN01ChallengeCert (token , identifier string , opt ... CertOption ) (cert tls.Certificate , err error ) {
621610 ka , err := keyAuth (c .Key .Public (), token )
622611 if err != nil {
623612 return tls.Certificate {}, err
@@ -647,7 +636,7 @@ func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption)
647636 }
648637 tmpl .ExtraExtensions = append (tmpl .ExtraExtensions , acmeExtension )
649638 newOpt = append (newOpt , WithTemplate (tmpl ))
650- return tlsChallengeCert ([] string { domain } , newOpt )
639+ return tlsChallengeCert (identifier , newOpt )
651640}
652641
653642// popNonce returns a nonce value previously stored with c.addNonce
@@ -701,7 +690,7 @@ func (c *Client) addNonce(h http.Header) {
701690}
702691
703692func (c * Client ) fetchNonce (ctx context.Context , url string ) (string , error ) {
704- r , err := http .NewRequest ( "HEAD" , url , nil )
693+ r , err := http .NewRequestWithContext ( ctx , "HEAD" , url , nil )
705694 if err != nil {
706695 return "" , err
707696 }
@@ -765,11 +754,15 @@ func defaultTLSChallengeCertTemplate() *x509.Certificate {
765754 }
766755}
767756
768- // tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
769- // with the given SANs and auto-generated public/private key pair.
770- // The Subject Common Name is set to the first SAN to aid debugging.
757+ // tlsChallengeCert creates a temporary certificate for TLS-ALPN challenges
758+ // for the given identifier, using an auto-generated public/private key pair.
759+ //
760+ // If the provided identifier is a domain name, it will be used as a DNS type SAN and for the
761+ // subject common name. If the provided identifier is an IP address it will be used as an IP type
762+ // SAN.
763+ //
771764// To create a cert with a custom key pair, specify WithKey option.
772- func tlsChallengeCert (san [] string , opt []CertOption ) (tls.Certificate , error ) {
765+ func tlsChallengeCert (identifier string , opt []CertOption ) (tls.Certificate , error ) {
773766 var key crypto.Signer
774767 tmpl := defaultTLSChallengeCertTemplate ()
775768 for _ , o := range opt {
@@ -793,9 +786,12 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
793786 return tls.Certificate {}, err
794787 }
795788 }
796- tmpl .DNSNames = san
797- if len (san ) > 0 {
798- tmpl .Subject .CommonName = san [0 ]
789+
790+ if ip := net .ParseIP (identifier ); ip != nil {
791+ tmpl .IPAddresses = []net.IP {ip }
792+ } else {
793+ tmpl .DNSNames = []string {identifier }
794+ tmpl .Subject .CommonName = identifier
799795 }
800796
801797 der , err := x509 .CreateCertificate (rand .Reader , tmpl , tmpl , key .Public (), key )
@@ -808,11 +804,5 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
808804 }, nil
809805}
810806
811- // encodePEM returns b encoded as PEM with block of type typ.
812- func encodePEM (typ string , b []byte ) []byte {
813- pb := & pem.Block {Type : typ , Bytes : b }
814- return pem .EncodeToMemory (pb )
815- }
816-
817807// timeNow is time.Now, except in tests which can mess with it.
818808var timeNow = time .Now
0 commit comments