From 21853a76e0cca35cf785c34dceee499a3d5a7168 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 30 Nov 2016 16:39:40 +0000 Subject: [PATCH] acme/autocert: remove trailing dot from domain before requesting cert Browsers can send an SNI name of "example.com." for https://example.com./ but LetsEncrypt rejects the trailing dot. Fixes golang/go#18114 Change-Id: Ie38e355e5b5566a7eb18f77a2449660e22e21b4c Reviewed-on: https://go-review.googlesource.com/33711 Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot Reviewed-by: Emmanuel Odeke Reviewed-by: Brad Fitzpatrick --- acme/autocert/autocert.go | 1 + acme/autocert/autocert_test.go | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/acme/autocert/autocert.go b/acme/autocert/autocert.go index 12c9010d..877bfba1 100644 --- a/acme/autocert/autocert.go +++ b/acme/autocert/autocert.go @@ -187,6 +187,7 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, } // regular domain + name = strings.TrimSuffix(name, ".") // golang.org/issue/18114 cert, err := m.cert(name) if err == nil { return cert, nil diff --git a/acme/autocert/autocert_test.go b/acme/autocert/autocert_test.go index 3a9daa10..295f702d 100644 --- a/acme/autocert/autocert_test.go +++ b/acme/autocert/autocert_test.go @@ -108,6 +108,14 @@ func decodePayload(v interface{}, r io.Reader) error { } func TestGetCertificate(t *testing.T) { + testGetCertificate(t, false) +} + +func TestGetCertificate_trailingDot(t *testing.T) { + testGetCertificate(t, true) +} + +func testGetCertificate(t *testing.T, trailingDot bool) { const domain = "example.org" man := &Manager{Prompt: AcceptTOS} defer man.stopRenew() @@ -167,6 +175,9 @@ func TestGetCertificate(t *testing.T) { if err != nil { t.Fatalf("new-cert: CSR: %v", err) } + if csr.Subject.CommonName != domain { + t.Errorf("CommonName in CSR = %q; want %q", csr.Subject.CommonName, domain) + } der, err := dummyCert(csr.PublicKey, domain) if err != nil { t.Fatalf("new-cert: dummyCert: %v", err) @@ -201,11 +212,14 @@ func TestGetCertificate(t *testing.T) { // simulate tls.Config.GetCertificate var tlscert *tls.Certificate done := make(chan struct{}) - go func() { - hello := &tls.ClientHelloInfo{ServerName: domain} + go func(serverName string) { + if trailingDot { + serverName += "." + } + hello := &tls.ClientHelloInfo{ServerName: serverName} tlscert, err = man.GetCertificate(hello) close(done) - }() + }(domain) select { case <-time.After(time.Minute): t.Fatal("man.GetCertificate took too long to return")