autocert_test.go 24 KB

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