autocert_test.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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. "crypto"
  7. "crypto/ecdsa"
  8. "crypto/elliptic"
  9. "crypto/rand"
  10. "crypto/rsa"
  11. "crypto/tls"
  12. "crypto/x509"
  13. "crypto/x509/pkix"
  14. "encoding/base64"
  15. "encoding/json"
  16. "fmt"
  17. "html/template"
  18. "io"
  19. "math/big"
  20. "net/http"
  21. "net/http/httptest"
  22. "testing"
  23. "time"
  24. "golang.org/x/crypto/acme"
  25. "golang.org/x/net/context"
  26. )
  27. var discoTmpl = template.Must(template.New("disco").Parse(`{
  28. "new-reg": "{{.}}/new-reg",
  29. "new-authz": "{{.}}/new-authz",
  30. "new-cert": "{{.}}/new-cert"
  31. }`))
  32. var authzTmpl = template.Must(template.New("authz").Parse(`{
  33. "status": "pending",
  34. "challenges": [
  35. {
  36. "uri": "{{.}}/challenge/1",
  37. "type": "tls-sni-01",
  38. "token": "token-01"
  39. },
  40. {
  41. "uri": "{{.}}/challenge/2",
  42. "type": "tls-sni-02",
  43. "token": "token-02"
  44. }
  45. ]
  46. }`))
  47. type memCache map[string][]byte
  48. func (m memCache) Get(ctx context.Context, key string) ([]byte, error) {
  49. v, ok := m[key]
  50. if !ok {
  51. return nil, ErrCacheMiss
  52. }
  53. return v, nil
  54. }
  55. func (m memCache) Put(ctx context.Context, key string, data []byte) error {
  56. m[key] = data
  57. return nil
  58. }
  59. func (m memCache) Delete(ctx context.Context, key string) error {
  60. delete(m, key)
  61. return nil
  62. }
  63. func dummyCert(pub interface{}, san ...string) ([]byte, error) {
  64. return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...)
  65. }
  66. func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte, error) {
  67. // use EC key to run faster on 386
  68. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  69. if err != nil {
  70. return nil, err
  71. }
  72. t := &x509.Certificate{
  73. SerialNumber: big.NewInt(1),
  74. NotBefore: start,
  75. NotAfter: end,
  76. BasicConstraintsValid: true,
  77. KeyUsage: x509.KeyUsageKeyEncipherment,
  78. DNSNames: san,
  79. }
  80. if pub == nil {
  81. pub = &key.PublicKey
  82. }
  83. return x509.CreateCertificate(rand.Reader, t, t, pub, key)
  84. }
  85. func decodePayload(v interface{}, r io.Reader) error {
  86. var req struct{ Payload string }
  87. if err := json.NewDecoder(r).Decode(&req); err != nil {
  88. return err
  89. }
  90. payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
  91. if err != nil {
  92. return err
  93. }
  94. return json.Unmarshal(payload, v)
  95. }
  96. func TestGetCertificate(t *testing.T) {
  97. const domain = "example.org"
  98. man := &Manager{Prompt: AcceptTOS}
  99. defer man.stopRenew()
  100. // echo token-02 | shasum -a 256
  101. // then divide result in 2 parts separated by dot
  102. tokenCertName := "4e8eb87631187e9ff2153b56b13a4dec.13a35d002e485d60ff37354b32f665d9.token.acme.invalid"
  103. verifyTokenCert := func() {
  104. hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
  105. _, err := man.GetCertificate(hello)
  106. if err != nil {
  107. t.Errorf("verifyTokenCert: GetCertificate(%q): %v", tokenCertName, err)
  108. return
  109. }
  110. }
  111. // ACME CA server stub
  112. var ca *httptest.Server
  113. ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  114. w.Header().Set("replay-nonce", "nonce")
  115. if r.Method == "HEAD" {
  116. // a nonce request
  117. return
  118. }
  119. switch r.URL.Path {
  120. // discovery
  121. case "/":
  122. if err := discoTmpl.Execute(w, ca.URL); err != nil {
  123. t.Fatalf("discoTmpl: %v", err)
  124. }
  125. // client key registration
  126. case "/new-reg":
  127. w.Write([]byte("{}"))
  128. // domain authorization
  129. case "/new-authz":
  130. w.Header().Set("location", ca.URL+"/authz/1")
  131. w.WriteHeader(http.StatusCreated)
  132. if err := authzTmpl.Execute(w, ca.URL); err != nil {
  133. t.Fatalf("authzTmpl: %v", err)
  134. }
  135. // accept tls-sni-02 challenge
  136. case "/challenge/2":
  137. verifyTokenCert()
  138. w.Write([]byte("{}"))
  139. // authorization status
  140. case "/authz/1":
  141. w.Write([]byte(`{"status": "valid"}`))
  142. // cert request
  143. case "/new-cert":
  144. var req struct {
  145. CSR string `json:"csr"`
  146. }
  147. decodePayload(&req, r.Body)
  148. b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
  149. csr, err := x509.ParseCertificateRequest(b)
  150. if err != nil {
  151. t.Fatalf("new-cert: CSR: %v", err)
  152. }
  153. der, err := dummyCert(csr.PublicKey, domain)
  154. if err != nil {
  155. t.Fatalf("new-cert: dummyCert: %v", err)
  156. }
  157. chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
  158. w.Header().Set("link", chainUp)
  159. w.WriteHeader(http.StatusCreated)
  160. w.Write(der)
  161. // CA chain cert
  162. case "/ca-cert":
  163. der, err := dummyCert(nil, "ca")
  164. if err != nil {
  165. t.Fatalf("ca-cert: dummyCert: %v", err)
  166. }
  167. w.Write(der)
  168. default:
  169. t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
  170. }
  171. }))
  172. defer ca.Close()
  173. // use EC key to run faster on 386
  174. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  175. if err != nil {
  176. t.Fatal(err)
  177. }
  178. man.Client = &acme.Client{
  179. Key: key,
  180. DirectoryURL: ca.URL,
  181. }
  182. // simulate tls.Config.GetCertificate
  183. var tlscert *tls.Certificate
  184. done := make(chan struct{})
  185. go func() {
  186. hello := &tls.ClientHelloInfo{ServerName: domain}
  187. tlscert, err = man.GetCertificate(hello)
  188. close(done)
  189. }()
  190. select {
  191. case <-time.After(time.Minute):
  192. t.Fatal("man.GetCertificate took too long to return")
  193. case <-done:
  194. }
  195. if err != nil {
  196. t.Fatalf("man.GetCertificate: %v", err)
  197. }
  198. // verify the tlscert is the same we responded with from the CA stub
  199. if len(tlscert.Certificate) == 0 {
  200. t.Fatal("len(tlscert.Certificate) is 0")
  201. }
  202. cert, err := x509.ParseCertificate(tlscert.Certificate[0])
  203. if err != nil {
  204. t.Fatalf("x509.ParseCertificate: %v", err)
  205. }
  206. if len(cert.DNSNames) == 0 || cert.DNSNames[0] != domain {
  207. t.Errorf("cert.DNSNames = %v; want %q", cert.DNSNames, domain)
  208. }
  209. // make sure token cert was removed
  210. done = make(chan struct{})
  211. go func() {
  212. for {
  213. hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
  214. if _, err := man.GetCertificate(hello); err != nil {
  215. break
  216. }
  217. time.Sleep(100 * time.Millisecond)
  218. }
  219. close(done)
  220. }()
  221. select {
  222. case <-time.After(5 * time.Second):
  223. t.Error("token cert was not removed")
  224. case <-done:
  225. }
  226. }
  227. func TestCache(t *testing.T) {
  228. privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  229. if err != nil {
  230. t.Fatal(err)
  231. }
  232. tmpl := &x509.Certificate{
  233. SerialNumber: big.NewInt(1),
  234. Subject: pkix.Name{CommonName: "example.org"},
  235. NotAfter: time.Now().Add(time.Hour),
  236. }
  237. pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &privKey.PublicKey, privKey)
  238. if err != nil {
  239. t.Fatal(err)
  240. }
  241. tlscert := &tls.Certificate{
  242. Certificate: [][]byte{pub},
  243. PrivateKey: privKey,
  244. }
  245. cache := make(memCache)
  246. man := &Manager{Cache: cache}
  247. defer man.stopRenew()
  248. if err := man.cachePut("example.org", tlscert); err != nil {
  249. t.Fatalf("man.cachePut: %v", err)
  250. }
  251. res, err := man.cacheGet("example.org")
  252. if err != nil {
  253. t.Fatalf("man.cacheGet: %v", err)
  254. }
  255. if res == nil {
  256. t.Fatal("res is nil")
  257. }
  258. }
  259. func TestHostWhitelist(t *testing.T) {
  260. policy := HostWhitelist("example.com", "example.org", "*.example.net")
  261. tt := []struct {
  262. host string
  263. allow bool
  264. }{
  265. {"example.com", true},
  266. {"example.org", true},
  267. {"one.example.com", false},
  268. {"two.example.org", false},
  269. {"three.example.net", false},
  270. {"dummy", false},
  271. }
  272. for i, test := range tt {
  273. err := policy(nil, test.host)
  274. if err != nil && test.allow {
  275. t.Errorf("%d: policy(%q): %v; want nil", i, test.host, err)
  276. }
  277. if err == nil && !test.allow {
  278. t.Errorf("%d: policy(%q): nil; want an error", i, test.host)
  279. }
  280. }
  281. }
  282. func TestValidCert(t *testing.T) {
  283. key1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  284. if err != nil {
  285. t.Fatal(err)
  286. }
  287. key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  288. if err != nil {
  289. t.Fatal(err)
  290. }
  291. key3, err := rsa.GenerateKey(rand.Reader, 512)
  292. if err != nil {
  293. t.Fatal(err)
  294. }
  295. cert1, err := dummyCert(key1.Public(), "example.org")
  296. if err != nil {
  297. t.Fatal(err)
  298. }
  299. cert2, err := dummyCert(key2.Public(), "example.org")
  300. if err != nil {
  301. t.Fatal(err)
  302. }
  303. cert3, err := dummyCert(key3.Public(), "example.org")
  304. if err != nil {
  305. t.Fatal(err)
  306. }
  307. now := time.Now()
  308. early, err := dateDummyCert(key1.Public(), now.Add(time.Hour), now.Add(2*time.Hour), "example.org")
  309. if err != nil {
  310. t.Fatal(err)
  311. }
  312. expired, err := dateDummyCert(key1.Public(), now.Add(-2*time.Hour), now.Add(-time.Hour), "example.org")
  313. if err != nil {
  314. t.Fatal(err)
  315. }
  316. tt := []struct {
  317. domain string
  318. key crypto.Signer
  319. cert [][]byte
  320. ok bool
  321. }{
  322. {"example.org", key1, [][]byte{cert1}, true},
  323. {"example.org", key3, [][]byte{cert3}, true},
  324. {"example.org", key1, [][]byte{cert1, cert2, cert3}, true},
  325. {"example.org", key1, [][]byte{cert1, {1}}, false},
  326. {"example.org", key1, [][]byte{{1}}, false},
  327. {"example.org", key1, [][]byte{cert2}, false},
  328. {"example.org", key2, [][]byte{cert1}, false},
  329. {"example.org", key1, [][]byte{cert3}, false},
  330. {"example.org", key3, [][]byte{cert1}, false},
  331. {"example.net", key1, [][]byte{cert1}, false},
  332. {"example.org", key1, [][]byte{early}, false},
  333. {"example.org", key1, [][]byte{expired}, false},
  334. }
  335. for i, test := range tt {
  336. leaf, err := validCert(test.domain, test.cert, test.key)
  337. if err != nil && test.ok {
  338. t.Errorf("%d: err = %v", i, err)
  339. }
  340. if err == nil && !test.ok {
  341. t.Errorf("%d: err is nil", i)
  342. }
  343. if err == nil && test.ok && leaf == nil {
  344. t.Errorf("%d: leaf is nil", i)
  345. }
  346. }
  347. }