Skip to content

Commit a3beeb7

Browse files
author
Alex Vaghin
committed
acme/autocert: support configurable CSR extensions
Package users can now provide extra CSR extensions to serve certificates with desired properties. Fixes golang/go#17801. Change-Id: Iac1010f41391c865f6e318bad2e0dafc2ffef6b1 Reviewed-on: https://go-review.googlesource.com/42470 Reviewed-by: Adam Langley <[email protected]> Run-TryBot: Adam Langley <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 159ae71 commit a3beeb7

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

acme/autocert/autocert.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,15 @@ type Manager struct {
146146
// is EC-based keys using the P-256 curve.
147147
ForceRSA bool
148148

149+
// ExtraExtensions are used when generating a new CSR (Certificate Request),
150+
// thus allowing customization of the resulting certificate.
151+
// For instance, TLS Feature Extension (RFC 7633) can be used
152+
// to prevent an OCSP downgrade attack.
153+
//
154+
// The field value is passed to crypto/x509.CreateCertificateRequest
155+
// in the template's ExtraExtensions field as is.
156+
ExtraExtensions []pkix.Extension
157+
149158
clientMu sync.Mutex
150159
client *acme.Client // initialized by acmeClient method
151160

@@ -527,7 +536,7 @@ func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain
527536
if err := m.verify(ctx, client, domain); err != nil {
528537
return nil, nil, err
529538
}
530-
csr, err := certRequest(key, domain)
539+
csr, err := certRequest(key, domain, m.ExtraExtensions)
531540
if err != nil {
532541
return nil, nil, err
533542
}
@@ -870,12 +879,12 @@ func (s *certState) tlscert() (*tls.Certificate, error) {
870879
}, nil
871880
}
872881

873-
// certRequest creates a certificate request for the given common name cn
874-
// and optional SANs.
875-
func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) {
882+
// certRequest generates a CSR for the given common name cn and optional SANs.
883+
func certRequest(key crypto.Signer, cn string, ext []pkix.Extension, san ...string) ([]byte, error) {
876884
req := &x509.CertificateRequest{
877-
Subject: pkix.Name{CommonName: cn},
878-
DNSNames: san,
885+
Subject: pkix.Name{CommonName: cn},
886+
DNSNames: san,
887+
ExtraExtensions: ext,
879888
}
880889
return x509.CreateCertificateRequest(rand.Reader, req, key)
881890
}

acme/autocert/autocert_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"crypto/tls"
1515
"crypto/x509"
1616
"crypto/x509/pkix"
17+
"encoding/asn1"
1718
"encoding/base64"
1819
"encoding/json"
1920
"fmt"
@@ -854,3 +855,33 @@ func TestManagerGetCertificateBogusSNI(t *testing.T) {
854855
}
855856
}
856857
}
858+
859+
func TestCertRequest(t *testing.T) {
860+
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
861+
if err != nil {
862+
t.Fatal(err)
863+
}
864+
// An extension from RFC7633. Any will do.
865+
ext := pkix.Extension{
866+
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1},
867+
Value: []byte("dummy"),
868+
}
869+
b, err := certRequest(key, "example.org", []pkix.Extension{ext}, "san.example.org")
870+
if err != nil {
871+
t.Fatalf("certRequest: %v", err)
872+
}
873+
r, err := x509.ParseCertificateRequest(b)
874+
if err != nil {
875+
t.Fatalf("ParseCertificateRequest: %v", err)
876+
}
877+
var found bool
878+
for _, v := range r.Extensions {
879+
if v.Id.Equal(ext.Id) {
880+
found = true
881+
break
882+
}
883+
}
884+
if !found {
885+
t.Errorf("want %v in Extensions: %v", ext, r.Extensions)
886+
}
887+
}

0 commit comments

Comments
 (0)