autocert_test.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package autocert
  5. import (
  6. "context"
  7. "crypto"
  8. "crypto/ecdsa"
  9. "crypto/elliptic"
  10. "crypto/rand"
  11. "crypto/rsa"
  12. "crypto/tls"
  13. "crypto/x509"
  14. "crypto/x509/pkix"
  15. "encoding/base64"
  16. "encoding/json"
  17. "fmt"
  18. "html/template"
  19. "io"
  20. "io/ioutil"
  21. "math/big"
  22. "net/http"
  23. "net/http/httptest"
  24. "reflect"
  25. "strconv"
  26. "strings"
  27. "sync"
  28. "testing"
  29. "time"
  30. "golang.org/x/crypto/acme"
  31. )
  32. var discoTmpl = template.Must(template.New("disco").Parse(`{
  33. "new-reg": "{{.}}/new-reg",
  34. "new-authz": "{{.}}/new-authz",
  35. "new-cert": "{{.}}/new-cert"
  36. }`))
  37. var authzTmpl = template.Must(template.New("authz").Parse(`{
  38. "status": "pending",
  39. "challenges": [
  40. {
  41. "uri": "{{.}}/challenge/1",
  42. "type": "tls-sni-01",
  43. "token": "token-01"
  44. },
  45. {
  46. "uri": "{{.}}/challenge/2",
  47. "type": "tls-sni-02",
  48. "token": "token-02"
  49. },
  50. {
  51. "uri": "{{.}}/challenge/dns-01",
  52. "type": "dns-01",
  53. "token": "token-dns-01"
  54. },
  55. {
  56. "uri": "{{.}}/challenge/http-01",
  57. "type": "http-01",
  58. "token": "token-http-01"
  59. }
  60. ]
  61. }`))
  62. type memCache struct {
  63. mu sync.Mutex
  64. keyData map[string][]byte
  65. }
  66. func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) {
  67. m.mu.Lock()
  68. defer m.mu.Unlock()
  69. v, ok := m.keyData[key]
  70. if !ok {
  71. return nil, ErrCacheMiss
  72. }
  73. return v, nil
  74. }
  75. func (m *memCache) Put(ctx context.Context, key string, data []byte) error {
  76. m.mu.Lock()
  77. defer m.mu.Unlock()
  78. m.keyData[key] = data
  79. return nil
  80. }
  81. func (m *memCache) Delete(ctx context.Context, key string) error {
  82. m.mu.Lock()
  83. defer m.mu.Unlock()
  84. delete(m.keyData, key)
  85. return nil
  86. }
  87. func newMemCache() *memCache {
  88. return &memCache{
  89. keyData: make(map[string][]byte),
  90. }
  91. }
  92. func dummyCert(pub interface{}, san ...string) ([]byte, error) {
  93. return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...)
  94. }
  95. func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte, error) {
  96. // use EC key to run faster on 386
  97. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  98. if err != nil {
  99. return nil, err
  100. }
  101. t := &x509.Certificate{
  102. SerialNumber: big.NewInt(1),
  103. NotBefore: start,
  104. NotAfter: end,
  105. BasicConstraintsValid: true,
  106. KeyUsage: x509.KeyUsageKeyEncipherment,
  107. DNSNames: san,
  108. }
  109. if pub == nil {
  110. pub = &key.PublicKey
  111. }
  112. return x509.CreateCertificate(rand.Reader, t, t, pub, key)
  113. }
  114. func decodePayload(v interface{}, r io.Reader) error {
  115. var req struct{ Payload string }
  116. if err := json.NewDecoder(r).Decode(&req); err != nil {
  117. return err
  118. }
  119. payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
  120. if err != nil {
  121. return err
  122. }
  123. return json.Unmarshal(payload, v)
  124. }
  125. func TestGetCertificate(t *testing.T) {
  126. man := &Manager{Prompt: AcceptTOS}
  127. defer man.stopRenew()
  128. hello := &tls.ClientHelloInfo{ServerName: "example.org"}
  129. testGetCertificate(t, man, "example.org", hello)
  130. }
  131. func TestGetCertificate_trailingDot(t *testing.T) {
  132. man := &Manager{Prompt: AcceptTOS}
  133. defer man.stopRenew()
  134. hello := &tls.ClientHelloInfo{ServerName: "example.org."}
  135. testGetCertificate(t, man, "example.org", hello)
  136. }
  137. func TestGetCertificate_ForceRSA(t *testing.T) {
  138. man := &Manager{
  139. Prompt: AcceptTOS,
  140. Cache: newMemCache(),
  141. ForceRSA: true,
  142. }
  143. defer man.stopRenew()
  144. hello := &tls.ClientHelloInfo{ServerName: "example.org"}
  145. testGetCertificate(t, man, "example.org", hello)
  146. cert, err := man.cacheGet(context.Background(), "example.org")
  147. if err != nil {
  148. t.Fatalf("man.cacheGet: %v", err)
  149. }
  150. if _, ok := cert.PrivateKey.(*rsa.PrivateKey); !ok {
  151. t.Errorf("cert.PrivateKey is %T; want *rsa.PrivateKey", cert.PrivateKey)
  152. }
  153. }
  154. func TestGetCertificate_nilPrompt(t *testing.T) {
  155. man := &Manager{}
  156. defer man.stopRenew()
  157. url, finish := startACMEServerStub(t, man, "example.org")
  158. defer finish()
  159. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  160. if err != nil {
  161. t.Fatal(err)
  162. }
  163. man.Client = &acme.Client{
  164. Key: key,
  165. DirectoryURL: url,
  166. }
  167. hello := &tls.ClientHelloInfo{ServerName: "example.org"}
  168. if _, err := man.GetCertificate(hello); err == nil {
  169. t.Error("got certificate for example.org; wanted error")
  170. }
  171. }
  172. func TestGetCertificate_expiredCache(t *testing.T) {
  173. // Make an expired cert and cache it.
  174. pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  175. if err != nil {
  176. t.Fatal(err)
  177. }
  178. tmpl := &x509.Certificate{
  179. SerialNumber: big.NewInt(1),
  180. Subject: pkix.Name{CommonName: "example.org"},
  181. NotAfter: time.Now(),
  182. }
  183. pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk)
  184. if err != nil {
  185. t.Fatal(err)
  186. }
  187. tlscert := &tls.Certificate{
  188. Certificate: [][]byte{pub},
  189. PrivateKey: pk,
  190. }
  191. man := &Manager{Prompt: AcceptTOS, Cache: newMemCache()}
  192. defer man.stopRenew()
  193. if err := man.cachePut(context.Background(), "example.org", tlscert); err != nil {
  194. t.Fatalf("man.cachePut: %v", err)
  195. }
  196. // The expired cached cert should trigger a new cert issuance
  197. // and return without an error.
  198. hello := &tls.ClientHelloInfo{ServerName: "example.org"}
  199. testGetCertificate(t, man, "example.org", hello)
  200. }
  201. func TestGetCertificate_failedAttempt(t *testing.T) {
  202. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  203. w.WriteHeader(http.StatusBadRequest)
  204. }))
  205. defer ts.Close()
  206. const example = "example.org"
  207. d := createCertRetryAfter
  208. f := testDidRemoveState
  209. defer func() {
  210. createCertRetryAfter = d
  211. testDidRemoveState = f
  212. }()
  213. createCertRetryAfter = 0
  214. done := make(chan struct{})
  215. testDidRemoveState = func(domain string) {
  216. if domain != example {
  217. t.Errorf("testDidRemoveState: domain = %q; want %q", domain, example)
  218. }
  219. close(done)
  220. }
  221. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  222. if err != nil {
  223. t.Fatal(err)
  224. }
  225. man := &Manager{
  226. Prompt: AcceptTOS,
  227. Client: &acme.Client{
  228. Key: key,
  229. DirectoryURL: ts.URL,
  230. },
  231. }
  232. defer man.stopRenew()
  233. hello := &tls.ClientHelloInfo{ServerName: example}
  234. if _, err := man.GetCertificate(hello); err == nil {
  235. t.Error("GetCertificate: err is nil")
  236. }
  237. select {
  238. case <-time.After(5 * time.Second):
  239. t.Errorf("took too long to remove the %q state", example)
  240. case <-done:
  241. man.stateMu.Lock()
  242. defer man.stateMu.Unlock()
  243. if v, exist := man.state[example]; exist {
  244. t.Errorf("state exists for %q: %+v", example, v)
  245. }
  246. }
  247. }
  248. // startACMEServerStub runs an ACME server
  249. // The domain argument is the expected domain name of a certificate request.
  250. func startACMEServerStub(t *testing.T, man *Manager, domain string) (url string, finish func()) {
  251. // echo token-02 | shasum -a 256
  252. // then divide result in 2 parts separated by dot
  253. tokenCertName := "4e8eb87631187e9ff2153b56b13a4dec.13a35d002e485d60ff37354b32f665d9.token.acme.invalid"
  254. verifyTokenCert := func() {
  255. hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
  256. _, err := man.GetCertificate(hello)
  257. if err != nil {
  258. t.Errorf("verifyTokenCert: GetCertificate(%q): %v", tokenCertName, err)
  259. return
  260. }
  261. }
  262. // ACME CA server stub
  263. var ca *httptest.Server
  264. ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  265. w.Header().Set("Replay-Nonce", "nonce")
  266. if r.Method == "HEAD" {
  267. // a nonce request
  268. return
  269. }
  270. switch r.URL.Path {
  271. // discovery
  272. case "/":
  273. if err := discoTmpl.Execute(w, ca.URL); err != nil {
  274. t.Errorf("discoTmpl: %v", err)
  275. }
  276. // client key registration
  277. case "/new-reg":
  278. w.Write([]byte("{}"))
  279. // domain authorization
  280. case "/new-authz":
  281. w.Header().Set("Location", ca.URL+"/authz/1")
  282. w.WriteHeader(http.StatusCreated)
  283. if err := authzTmpl.Execute(w, ca.URL); err != nil {
  284. t.Errorf("authzTmpl: %v", err)
  285. }
  286. // accept tls-sni-02 challenge
  287. case "/challenge/2":
  288. verifyTokenCert()
  289. w.Write([]byte("{}"))
  290. // authorization status
  291. case "/authz/1":
  292. w.Write([]byte(`{"status": "valid"}`))
  293. // cert request
  294. case "/new-cert":
  295. var req struct {
  296. CSR string `json:"csr"`
  297. }
  298. decodePayload(&req, r.Body)
  299. b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
  300. csr, err := x509.ParseCertificateRequest(b)
  301. if err != nil {
  302. t.Errorf("new-cert: CSR: %v", err)
  303. }
  304. if csr.Subject.CommonName != domain {
  305. t.Errorf("CommonName in CSR = %q; want %q", csr.Subject.CommonName, domain)
  306. }
  307. der, err := dummyCert(csr.PublicKey, domain)
  308. if err != nil {
  309. t.Errorf("new-cert: dummyCert: %v", err)
  310. }
  311. chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
  312. w.Header().Set("Link", chainUp)
  313. w.WriteHeader(http.StatusCreated)
  314. w.Write(der)
  315. // CA chain cert
  316. case "/ca-cert":
  317. der, err := dummyCert(nil, "ca")
  318. if err != nil {
  319. t.Errorf("ca-cert: dummyCert: %v", err)
  320. }
  321. w.Write(der)
  322. default:
  323. t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
  324. }
  325. }))
  326. finish = func() {
  327. ca.Close()
  328. // make sure token cert was removed
  329. cancel := make(chan struct{})
  330. done := make(chan struct{})
  331. go func() {
  332. defer close(done)
  333. tick := time.NewTicker(100 * time.Millisecond)
  334. defer tick.Stop()
  335. for {
  336. hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
  337. if _, err := man.GetCertificate(hello); err != nil {
  338. return
  339. }
  340. select {
  341. case <-tick.C:
  342. case <-cancel:
  343. return
  344. }
  345. }
  346. }()
  347. select {
  348. case <-done:
  349. case <-time.After(5 * time.Second):
  350. close(cancel)
  351. t.Error("token cert was not removed")
  352. <-done
  353. }
  354. }
  355. return ca.URL, finish
  356. }
  357. // tests man.GetCertificate flow using the provided hello argument.
  358. // The domain argument is the expected domain name of a certificate request.
  359. func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.ClientHelloInfo) {
  360. url, finish := startACMEServerStub(t, man, domain)
  361. defer finish()
  362. // use EC key to run faster on 386
  363. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  364. if err != nil {
  365. t.Fatal(err)
  366. }
  367. man.Client = &acme.Client{
  368. Key: key,
  369. DirectoryURL: url,
  370. }
  371. // simulate tls.Config.GetCertificate
  372. var tlscert *tls.Certificate
  373. done := make(chan struct{})
  374. go func() {
  375. tlscert, err = man.GetCertificate(hello)
  376. close(done)
  377. }()
  378. select {
  379. case <-time.After(time.Minute):
  380. t.Fatal("man.GetCertificate took too long to return")
  381. case <-done:
  382. }
  383. if err != nil {
  384. t.Fatalf("man.GetCertificate: %v", err)
  385. }
  386. // verify the tlscert is the same we responded with from the CA stub
  387. if len(tlscert.Certificate) == 0 {
  388. t.Fatal("len(tlscert.Certificate) is 0")
  389. }
  390. cert, err := x509.ParseCertificate(tlscert.Certificate[0])
  391. if err != nil {
  392. t.Fatalf("x509.ParseCertificate: %v", err)
  393. }
  394. if len(cert.DNSNames) == 0 || cert.DNSNames[0] != domain {
  395. t.Errorf("cert.DNSNames = %v; want %q", cert.DNSNames, domain)
  396. }
  397. }
  398. func TestVerifyHTTP01(t *testing.T) {
  399. var (
  400. http01 http.Handler
  401. authzCount int // num. of created authorizations
  402. didAcceptHTTP01 bool
  403. )
  404. verifyHTTPToken := func() {
  405. r := httptest.NewRequest("GET", "/.well-known/acme-challenge/token-http-01", nil)
  406. w := httptest.NewRecorder()
  407. http01.ServeHTTP(w, r)
  408. if w.Code != http.StatusOK {
  409. t.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK)
  410. }
  411. if v := string(w.Body.Bytes()); !strings.HasPrefix(v, "token-http-01.") {
  412. t.Errorf("http token value = %q; want 'token-http-01.' prefix", v)
  413. }
  414. }
  415. // ACME CA server stub, only the needed bits.
  416. // TODO: Merge this with startACMEServerStub, making it a configurable CA for testing.
  417. var ca *httptest.Server
  418. ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  419. w.Header().Set("Replay-Nonce", "nonce")
  420. if r.Method == "HEAD" {
  421. // a nonce request
  422. return
  423. }
  424. switch r.URL.Path {
  425. // Discovery.
  426. case "/":
  427. if err := discoTmpl.Execute(w, ca.URL); err != nil {
  428. t.Errorf("discoTmpl: %v", err)
  429. }
  430. // Client key registration.
  431. case "/new-reg":
  432. w.Write([]byte("{}"))
  433. // New domain authorization.
  434. case "/new-authz":
  435. authzCount++
  436. w.Header().Set("Location", fmt.Sprintf("%s/authz/%d", ca.URL, authzCount))
  437. w.WriteHeader(http.StatusCreated)
  438. if err := authzTmpl.Execute(w, ca.URL); err != nil {
  439. t.Errorf("authzTmpl: %v", err)
  440. }
  441. // Accept tls-sni-02.
  442. case "/challenge/2":
  443. w.Write([]byte("{}"))
  444. // Reject tls-sni-01.
  445. case "/challenge/1":
  446. http.Error(w, "won't accept tls-sni-01", http.StatusBadRequest)
  447. // Should not accept dns-01.
  448. case "/challenge/dns-01":
  449. t.Errorf("dns-01 challenge was accepted")
  450. http.Error(w, "won't accept dns-01", http.StatusBadRequest)
  451. // Accept http-01.
  452. case "/challenge/http-01":
  453. didAcceptHTTP01 = true
  454. verifyHTTPToken()
  455. w.Write([]byte("{}"))
  456. // Authorization statuses.
  457. // Make tls-sni-xxx invalid.
  458. case "/authz/1", "/authz/2":
  459. w.Write([]byte(`{"status": "invalid"}`))
  460. case "/authz/3", "/authz/4":
  461. w.Write([]byte(`{"status": "valid"}`))
  462. default:
  463. http.NotFound(w, r)
  464. t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
  465. }
  466. }))
  467. defer ca.Close()
  468. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  469. if err != nil {
  470. t.Fatal(err)
  471. }
  472. m := &Manager{
  473. Client: &acme.Client{
  474. Key: key,
  475. DirectoryURL: ca.URL,
  476. },
  477. }
  478. http01 = m.HTTPHandler(nil)
  479. if err := m.verify(context.Background(), m.Client, "example.org"); err != nil {
  480. t.Errorf("m.verify: %v", err)
  481. }
  482. // Only tls-sni-01, tls-sni-02 and http-01 must be accepted
  483. // The dns-01 challenge is unsupported.
  484. if authzCount != 3 {
  485. t.Errorf("authzCount = %d; want 3", authzCount)
  486. }
  487. if !didAcceptHTTP01 {
  488. t.Error("did not accept http-01 challenge")
  489. }
  490. }
  491. func TestRevokeFailedAuth(t *testing.T) {
  492. var (
  493. authzCount int // num. of created authorizations
  494. revoked [3]bool // there will be three different authorization attempts; see below
  495. )
  496. // make cleanup revocations synchronous
  497. waitForRevocations = true
  498. // ACME CA server stub, only the needed bits.
  499. // TODO: Merge this with startACMEServerStub, making it a configurable CA for testing.
  500. var ca *httptest.Server
  501. ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  502. w.Header().Set("Replay-Nonce", "nonce")
  503. if r.Method == "HEAD" {
  504. // a nonce request
  505. return
  506. }
  507. switch r.URL.Path {
  508. // Discovery.
  509. case "/":
  510. if err := discoTmpl.Execute(w, ca.URL); err != nil {
  511. t.Errorf("discoTmpl: %v", err)
  512. }
  513. // Client key registration.
  514. case "/new-reg":
  515. w.Write([]byte("{}"))
  516. // New domain authorization.
  517. case "/new-authz":
  518. w.Header().Set("Location", fmt.Sprintf("%s/authz/%d", ca.URL, authzCount))
  519. w.WriteHeader(http.StatusCreated)
  520. if err := authzTmpl.Execute(w, ca.URL); err != nil {
  521. t.Errorf("authzTmpl: %v", err)
  522. }
  523. authzCount++
  524. // force error on Accept()
  525. case "/challenge/2":
  526. http.Error(w, "won't accept tls-sni-02 challenge", http.StatusBadRequest)
  527. // accept; authorization will be expired (404; see /authz/1 below)
  528. case "/challenge/1":
  529. w.Write([]byte("{}"))
  530. // Authorization statuses.
  531. case "/authz/0", "/authz/1", "/authz/2":
  532. if r.Method == "POST" {
  533. body, err := ioutil.ReadAll(r.Body)
  534. if err != nil {
  535. t.Errorf("could not read request body")
  536. }
  537. if reflect.DeepEqual(body, []byte(`{"status": "deactivated"}`)) {
  538. t.Errorf("unexpected POST to authz: '%s'", body)
  539. }
  540. i, err := strconv.ParseInt(r.URL.Path[len(r.URL.Path)-1:], 10, 64)
  541. if err != nil {
  542. t.Errorf("could not convert authz ID to int")
  543. }
  544. revoked[i] = true
  545. w.Write([]byte(`{"status": "invalid"}`))
  546. } else {
  547. switch r.URL.Path {
  548. case "/authz/0":
  549. // ensure we get a spurious validation if error forcing did not work (see above)
  550. w.Write([]byte(`{"status": "valid"}`))
  551. case "/authz/1":
  552. // force error during WaitAuthorization()
  553. w.WriteHeader(http.StatusNotFound)
  554. }
  555. }
  556. default:
  557. http.NotFound(w, r)
  558. t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
  559. }
  560. }))
  561. defer ca.Close()
  562. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  563. if err != nil {
  564. t.Fatal(err)
  565. }
  566. m := &Manager{
  567. Client: &acme.Client{
  568. Key: key,
  569. DirectoryURL: ca.URL,
  570. },
  571. }
  572. // should fail and revoke tsl-sni-02, tls-sni-01 and the third time after not finding any remaining challenges
  573. if err := m.verify(context.Background(), m.Client, "example.org"); err == nil {
  574. t.Errorf("m.verify should have failed!")
  575. }
  576. for i := range revoked {
  577. if !revoked[i] {
  578. t.Errorf("authorization attempt %d not revoked after error", i)
  579. }
  580. }
  581. }
  582. func TestHTTPHandlerDefaultFallback(t *testing.T) {
  583. tt := []struct {
  584. method, url string
  585. wantCode int
  586. wantLocation string
  587. }{
  588. {"GET", "http://example.org", 302, "https://example.org/"},
  589. {"GET", "http://example.org/foo", 302, "https://example.org/foo"},
  590. {"GET", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"},
  591. {"GET", "http://example.org/?a=b", 302, "https://example.org/?a=b"},
  592. {"GET", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"},
  593. {"GET", "http://example.org:80/foo?a=b", 302, "https://example.org:443/foo?a=b"},
  594. {"GET", "http://example.org:80/foo%20bar", 302, "https://example.org:443/foo%20bar"},
  595. {"GET", "http://[2602:d1:xxxx::c60a]:1234", 302, "https://[2602:d1:xxxx::c60a]:443/"},
  596. {"GET", "http://[2602:d1:xxxx::c60a]", 302, "https://[2602:d1:xxxx::c60a]/"},
  597. {"GET", "http://[2602:d1:xxxx::c60a]/foo?a=b", 302, "https://[2602:d1:xxxx::c60a]/foo?a=b"},
  598. {"HEAD", "http://example.org", 302, "https://example.org/"},
  599. {"HEAD", "http://example.org/foo", 302, "https://example.org/foo"},
  600. {"HEAD", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"},
  601. {"HEAD", "http://example.org/?a=b", 302, "https://example.org/?a=b"},
  602. {"HEAD", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"},
  603. {"POST", "http://example.org", 400, ""},
  604. {"PUT", "http://example.org", 400, ""},
  605. {"GET", "http://example.org/.well-known/acme-challenge/x", 404, ""},
  606. }
  607. var m Manager
  608. h := m.HTTPHandler(nil)
  609. for i, test := range tt {
  610. r := httptest.NewRequest(test.method, test.url, nil)
  611. w := httptest.NewRecorder()
  612. h.ServeHTTP(w, r)
  613. if w.Code != test.wantCode {
  614. t.Errorf("%d: w.Code = %d; want %d", i, w.Code, test.wantCode)
  615. t.Errorf("%d: body: %s", i, w.Body.Bytes())
  616. }
  617. if v := w.Header().Get("Location"); v != test.wantLocation {
  618. t.Errorf("%d: Location = %q; want %q", i, v, test.wantLocation)
  619. }
  620. }
  621. }
  622. func TestAccountKeyCache(t *testing.T) {
  623. m := Manager{Cache: newMemCache()}
  624. ctx := context.Background()
  625. k1, err := m.accountKey(ctx)
  626. if err != nil {
  627. t.Fatal(err)
  628. }
  629. k2, err := m.accountKey(ctx)
  630. if err != nil {
  631. t.Fatal(err)
  632. }
  633. if !reflect.DeepEqual(k1, k2) {
  634. t.Errorf("account keys don't match: k1 = %#v; k2 = %#v", k1, k2)
  635. }
  636. }
  637. func TestCache(t *testing.T) {
  638. privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  639. if err != nil {
  640. t.Fatal(err)
  641. }
  642. tmpl := &x509.Certificate{
  643. SerialNumber: big.NewInt(1),
  644. Subject: pkix.Name{CommonName: "example.org"},
  645. NotAfter: time.Now().Add(time.Hour),
  646. }
  647. pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &privKey.PublicKey, privKey)
  648. if err != nil {
  649. t.Fatal(err)
  650. }
  651. tlscert := &tls.Certificate{
  652. Certificate: [][]byte{pub},
  653. PrivateKey: privKey,
  654. }
  655. man := &Manager{Cache: newMemCache()}
  656. defer man.stopRenew()
  657. ctx := context.Background()
  658. if err := man.cachePut(ctx, "example.org", tlscert); err != nil {
  659. t.Fatalf("man.cachePut: %v", err)
  660. }
  661. res, err := man.cacheGet(ctx, "example.org")
  662. if err != nil {
  663. t.Fatalf("man.cacheGet: %v", err)
  664. }
  665. if res == nil {
  666. t.Fatal("res is nil")
  667. }
  668. }
  669. func TestHostWhitelist(t *testing.T) {
  670. policy := HostWhitelist("example.com", "example.org", "*.example.net")
  671. tt := []struct {
  672. host string
  673. allow bool
  674. }{
  675. {"example.com", true},
  676. {"example.org", true},
  677. {"one.example.com", false},
  678. {"two.example.org", false},
  679. {"three.example.net", false},
  680. {"dummy", false},
  681. }
  682. for i, test := range tt {
  683. err := policy(nil, test.host)
  684. if err != nil && test.allow {
  685. t.Errorf("%d: policy(%q): %v; want nil", i, test.host, err)
  686. }
  687. if err == nil && !test.allow {
  688. t.Errorf("%d: policy(%q): nil; want an error", i, test.host)
  689. }
  690. }
  691. }
  692. func TestValidCert(t *testing.T) {
  693. key1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  694. if err != nil {
  695. t.Fatal(err)
  696. }
  697. key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  698. if err != nil {
  699. t.Fatal(err)
  700. }
  701. key3, err := rsa.GenerateKey(rand.Reader, 512)
  702. if err != nil {
  703. t.Fatal(err)
  704. }
  705. cert1, err := dummyCert(key1.Public(), "example.org")
  706. if err != nil {
  707. t.Fatal(err)
  708. }
  709. cert2, err := dummyCert(key2.Public(), "example.org")
  710. if err != nil {
  711. t.Fatal(err)
  712. }
  713. cert3, err := dummyCert(key3.Public(), "example.org")
  714. if err != nil {
  715. t.Fatal(err)
  716. }
  717. now := time.Now()
  718. early, err := dateDummyCert(key1.Public(), now.Add(time.Hour), now.Add(2*time.Hour), "example.org")
  719. if err != nil {
  720. t.Fatal(err)
  721. }
  722. expired, err := dateDummyCert(key1.Public(), now.Add(-2*time.Hour), now.Add(-time.Hour), "example.org")
  723. if err != nil {
  724. t.Fatal(err)
  725. }
  726. tt := []struct {
  727. domain string
  728. key crypto.Signer
  729. cert [][]byte
  730. ok bool
  731. }{
  732. {"example.org", key1, [][]byte{cert1}, true},
  733. {"example.org", key3, [][]byte{cert3}, true},
  734. {"example.org", key1, [][]byte{cert1, cert2, cert3}, true},
  735. {"example.org", key1, [][]byte{cert1, {1}}, false},
  736. {"example.org", key1, [][]byte{{1}}, false},
  737. {"example.org", key1, [][]byte{cert2}, false},
  738. {"example.org", key2, [][]byte{cert1}, false},
  739. {"example.org", key1, [][]byte{cert3}, false},
  740. {"example.org", key3, [][]byte{cert1}, false},
  741. {"example.net", key1, [][]byte{cert1}, false},
  742. {"example.org", key1, [][]byte{early}, false},
  743. {"example.org", key1, [][]byte{expired}, false},
  744. }
  745. for i, test := range tt {
  746. leaf, err := validCert(test.domain, test.cert, test.key)
  747. if err != nil && test.ok {
  748. t.Errorf("%d: err = %v", i, err)
  749. }
  750. if err == nil && !test.ok {
  751. t.Errorf("%d: err is nil", i)
  752. }
  753. if err == nil && test.ok && leaf == nil {
  754. t.Errorf("%d: leaf is nil", i)
  755. }
  756. }
  757. }
  758. type cacheGetFunc func(ctx context.Context, key string) ([]byte, error)
  759. func (f cacheGetFunc) Get(ctx context.Context, key string) ([]byte, error) {
  760. return f(ctx, key)
  761. }
  762. func (f cacheGetFunc) Put(ctx context.Context, key string, data []byte) error {
  763. return fmt.Errorf("unsupported Put of %q = %q", key, data)
  764. }
  765. func (f cacheGetFunc) Delete(ctx context.Context, key string) error {
  766. return fmt.Errorf("unsupported Delete of %q", key)
  767. }
  768. func TestManagerGetCertificateBogusSNI(t *testing.T) {
  769. m := Manager{
  770. Prompt: AcceptTOS,
  771. Cache: cacheGetFunc(func(ctx context.Context, key string) ([]byte, error) {
  772. return nil, fmt.Errorf("cache.Get of %s", key)
  773. }),
  774. }
  775. tests := []struct {
  776. name string
  777. wantErr string
  778. }{
  779. {"foo.com", "cache.Get of foo.com"},
  780. {"foo.com.", "cache.Get of foo.com"},
  781. {`a\b.com`, "acme/autocert: server name contains invalid character"},
  782. {`a/b.com`, "acme/autocert: server name contains invalid character"},
  783. {"", "acme/autocert: missing server name"},
  784. {"foo", "acme/autocert: server name component count invalid"},
  785. {".foo", "acme/autocert: server name component count invalid"},
  786. {"foo.", "acme/autocert: server name component count invalid"},
  787. {"fo.o", "cache.Get of fo.o"},
  788. }
  789. for _, tt := range tests {
  790. _, err := m.GetCertificate(&tls.ClientHelloInfo{ServerName: tt.name})
  791. got := fmt.Sprint(err)
  792. if got != tt.wantErr {
  793. t.Errorf("GetCertificate(SNI = %q) = %q; want %q", tt.name, got, tt.wantErr)
  794. }
  795. }
  796. }