Skip to content

Commit 18228cd

Browse files
cpugopherbot
authored andcommitted
acme: return err from deprecated TLS-SNI-[01|02] functions
The TLSSNI01ChallengeCert and TLSSNI02ChallengeCert functions have been marked deprecated since 2022. The package documentation indicates pre-RFC 8555 functionality is retained for compilation success, but will return errors. This commit makes these two deprecated functions match that description. No meaningful support for these draft standard challenge types exists in the ACME ecosystem, and they are insecure for use in shared hosting environments. Change-Id: I1c17980a0630092c70eb971b3453a0f115834be0 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/676835 Auto-Submit: Daniel McCarney <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]> Reviewed-by: Michael Knyszek <[email protected]>
1 parent 73f6362 commit 18228cd

File tree

2 files changed

+44
-144
lines changed

2 files changed

+44
-144
lines changed

acme/acme.go

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
"crypto/x509/pkix"
3232
"encoding/asn1"
3333
"encoding/base64"
34-
"encoding/hex"
3534
"encoding/json"
3635
"errors"
3736
"fmt"
@@ -470,7 +469,7 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
470469
// while waiting for a final authorization status.
471470
d := retryAfter(res.Header.Get("Retry-After"))
472471
if d == 0 {
473-
// Given that the fastest challenges TLS-SNI and HTTP-01
472+
// Given that the fastest challenges TLS-ALPN and HTTP-01
474473
// require a CA to make at least 1 network round trip
475474
// and most likely persist a challenge state,
476475
// this default delay seems reasonable.
@@ -571,44 +570,21 @@ func (c *Client) HTTP01ChallengePath(token string) string {
571570
}
572571

573572
// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
573+
// Always returns an error.
574574
//
575-
// Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec.
576-
func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
577-
ka, err := keyAuth(c.Key.Public(), token)
578-
if err != nil {
579-
return tls.Certificate{}, "", err
580-
}
581-
b := sha256.Sum256([]byte(ka))
582-
h := hex.EncodeToString(b[:])
583-
name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:])
584-
cert, err = tlsChallengeCert([]string{name}, opt)
585-
if err != nil {
586-
return tls.Certificate{}, "", err
587-
}
588-
return cert, name, nil
575+
// Deprecated: This challenge type was only present in pre-standardized ACME
576+
// protocol drafts and is insecure for use in shared hosting environments.
577+
func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (tls.Certificate, string, error) {
578+
return tls.Certificate{}, "", errPreRFC
589579
}
590580

591581
// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
582+
// Always returns an error.
592583
//
593-
// Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec.
594-
func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
595-
b := sha256.Sum256([]byte(token))
596-
h := hex.EncodeToString(b[:])
597-
sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:])
598-
599-
ka, err := keyAuth(c.Key.Public(), token)
600-
if err != nil {
601-
return tls.Certificate{}, "", err
602-
}
603-
b = sha256.Sum256([]byte(ka))
604-
h = hex.EncodeToString(b[:])
605-
sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:])
606-
607-
cert, err = tlsChallengeCert([]string{sanA, sanB}, opt)
608-
if err != nil {
609-
return tls.Certificate{}, "", err
610-
}
611-
return cert, sanA, nil
584+
// Deprecated: This challenge type was only present in pre-standardized ACME
585+
// protocol drafts and is insecure for use in shared hosting environments.
586+
func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (tls.Certificate, string, error) {
587+
return tls.Certificate{}, "", errPreRFC
612588
}
613589

614590
// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response.
@@ -772,7 +748,7 @@ func defaultTLSChallengeCertTemplate() *x509.Certificate {
772748
}
773749
}
774750

775-
// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
751+
// tlsChallengeCert creates a temporary certificate for TLS-ALPN challenges
776752
// with the given SANs and auto-generated public/private key pair.
777753
// The Subject Common Name is set to the first SAN to aid debugging.
778754
// To create a cert with a custom key pair, specify WithKey option.

acme/acme_test.go

Lines changed: 32 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"context"
1010
"crypto/rand"
1111
"crypto/rsa"
12-
"crypto/tls"
1312
"crypto/x509"
1413
"crypto/x509/pkix"
1514
"encoding/base64"
@@ -22,8 +21,6 @@ import (
2221
"net/http"
2322
"net/http/httptest"
2423
"reflect"
25-
"sort"
26-
"strings"
2724
"testing"
2825
"time"
2926
)
@@ -692,71 +689,6 @@ func TestLinkHeader(t *testing.T) {
692689
}
693690
}
694691

695-
func TestTLSSNI01ChallengeCert(t *testing.T) {
696-
const (
697-
token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
698-
// echo -n <token.testKeyECThumbprint> | shasum -a 256
699-
san = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.acme.invalid"
700-
)
701-
702-
tlscert, name, err := newTestClient().TLSSNI01ChallengeCert(token)
703-
if err != nil {
704-
t.Fatal(err)
705-
}
706-
707-
if n := len(tlscert.Certificate); n != 1 {
708-
t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
709-
}
710-
cert, err := x509.ParseCertificate(tlscert.Certificate[0])
711-
if err != nil {
712-
t.Fatal(err)
713-
}
714-
if len(cert.DNSNames) != 1 || cert.DNSNames[0] != san {
715-
t.Fatalf("cert.DNSNames = %v; want %q", cert.DNSNames, san)
716-
}
717-
if cert.DNSNames[0] != name {
718-
t.Errorf("cert.DNSNames[0] != name: %q vs %q", cert.DNSNames[0], name)
719-
}
720-
if cn := cert.Subject.CommonName; cn != san {
721-
t.Errorf("cert.Subject.CommonName = %q; want %q", cn, san)
722-
}
723-
}
724-
725-
func TestTLSSNI02ChallengeCert(t *testing.T) {
726-
const (
727-
token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
728-
// echo -n evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA | shasum -a 256
729-
sanA = "7ea0aaa69214e71e02cebb18bb867736.09b730209baabf60e43d4999979ff139.token.acme.invalid"
730-
// echo -n <token.testKeyECThumbprint> | shasum -a 256
731-
sanB = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.ka.acme.invalid"
732-
)
733-
734-
tlscert, name, err := newTestClient().TLSSNI02ChallengeCert(token)
735-
if err != nil {
736-
t.Fatal(err)
737-
}
738-
739-
if n := len(tlscert.Certificate); n != 1 {
740-
t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
741-
}
742-
cert, err := x509.ParseCertificate(tlscert.Certificate[0])
743-
if err != nil {
744-
t.Fatal(err)
745-
}
746-
names := []string{sanA, sanB}
747-
if !reflect.DeepEqual(cert.DNSNames, names) {
748-
t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names)
749-
}
750-
sort.Strings(cert.DNSNames)
751-
i := sort.SearchStrings(cert.DNSNames, name)
752-
if i >= len(cert.DNSNames) || cert.DNSNames[i] != name {
753-
t.Errorf("%v doesn't have %q", cert.DNSNames, name)
754-
}
755-
if cn := cert.Subject.CommonName; cn != sanA {
756-
t.Errorf("CommonName = %q; want %q", cn, sanA)
757-
}
758-
}
759-
760692
func TestTLSALPN01ChallengeCert(t *testing.T) {
761693
const (
762694
token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
@@ -813,6 +745,7 @@ func TestTLSChallengeCertOpt(t *testing.T) {
813745
if err != nil {
814746
t.Fatal(err)
815747
}
748+
domain := "example.com"
816749
tmpl := &x509.Certificate{
817750
SerialNumber: big.NewInt(2),
818751
Subject: pkix.Name{Organization: []string{"Test"}},
@@ -821,52 +754,43 @@ func TestTLSChallengeCertOpt(t *testing.T) {
821754
opts := []CertOption{WithKey(key), WithTemplate(tmpl)}
822755

823756
client := newTestClient()
824-
cert1, _, err := client.TLSSNI01ChallengeCert("token", opts...)
757+
cert, err := client.TLSALPN01ChallengeCert("token", domain, opts...)
825758
if err != nil {
826759
t.Fatal(err)
827760
}
828-
cert2, _, err := client.TLSSNI02ChallengeCert("token", opts...)
761+
762+
// verify generated cert private key
763+
tlskey, ok := cert.PrivateKey.(*rsa.PrivateKey)
764+
if !ok {
765+
t.Fatalf("tlscert.PrivateKey is %T; want *rsa.PrivateKey", cert.PrivateKey)
766+
}
767+
if tlskey.D.Cmp(key.D) != 0 {
768+
t.Errorf("tlskey.D = %v; want %v", tlskey.D, key.D)
769+
}
770+
// verify generated cert public key
771+
x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
829772
if err != nil {
830773
t.Fatal(err)
831774
}
832-
833-
for i, tlscert := range []tls.Certificate{cert1, cert2} {
834-
// verify generated cert private key
835-
tlskey, ok := tlscert.PrivateKey.(*rsa.PrivateKey)
836-
if !ok {
837-
t.Errorf("%d: tlscert.PrivateKey is %T; want *rsa.PrivateKey", i, tlscert.PrivateKey)
838-
continue
839-
}
840-
if tlskey.D.Cmp(key.D) != 0 {
841-
t.Errorf("%d: tlskey.D = %v; want %v", i, tlskey.D, key.D)
842-
}
843-
// verify generated cert public key
844-
x509Cert, err := x509.ParseCertificate(tlscert.Certificate[0])
845-
if err != nil {
846-
t.Errorf("%d: %v", i, err)
847-
continue
848-
}
849-
tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey)
850-
if !ok {
851-
t.Errorf("%d: x509Cert.PublicKey is %T; want *rsa.PublicKey", i, x509Cert.PublicKey)
852-
continue
853-
}
854-
if tlspub.N.Cmp(key.N) != 0 {
855-
t.Errorf("%d: tlspub.N = %v; want %v", i, tlspub.N, key.N)
856-
}
857-
// verify template option
858-
sn := big.NewInt(2)
859-
if x509Cert.SerialNumber.Cmp(sn) != 0 {
860-
t.Errorf("%d: SerialNumber = %v; want %v", i, x509Cert.SerialNumber, sn)
861-
}
862-
org := []string{"Test"}
863-
if !reflect.DeepEqual(x509Cert.Subject.Organization, org) {
864-
t.Errorf("%d: Subject.Organization = %+v; want %+v", i, x509Cert.Subject.Organization, org)
865-
}
866-
for _, v := range x509Cert.DNSNames {
867-
if !strings.HasSuffix(v, ".acme.invalid") {
868-
t.Errorf("%d: invalid DNSNames element: %q", i, v)
869-
}
775+
tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey)
776+
if !ok {
777+
t.Fatalf("x509Cert.PublicKey is %T; want *rsa.PublicKey", x509Cert.PublicKey)
778+
}
779+
if tlspub.N.Cmp(key.N) != 0 {
780+
t.Errorf("tlspub.N = %v; want %v", tlspub.N, key.N)
781+
}
782+
// verify template option
783+
sn := big.NewInt(2)
784+
if x509Cert.SerialNumber.Cmp(sn) != 0 {
785+
t.Errorf("SerialNumber = %v; want %v", x509Cert.SerialNumber, sn)
786+
}
787+
org := []string{"Test"}
788+
if !reflect.DeepEqual(x509Cert.Subject.Organization, org) {
789+
t.Errorf("Subject.Organization = %+v; want %+v", x509Cert.Subject.Organization, org)
790+
}
791+
for _, v := range x509Cert.DNSNames {
792+
if v != domain {
793+
t.Errorf("invalid DNSNames element: %q", v)
870794
}
871795
}
872796
}

0 commit comments

Comments
 (0)