acme_test.go 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380
  1. // Copyright 2015 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 acme
  5. import (
  6. "bytes"
  7. "context"
  8. "crypto/rand"
  9. "crypto/rsa"
  10. "crypto/tls"
  11. "crypto/x509"
  12. "crypto/x509/pkix"
  13. "encoding/base64"
  14. "encoding/json"
  15. "fmt"
  16. "io/ioutil"
  17. "math/big"
  18. "net/http"
  19. "net/http/httptest"
  20. "reflect"
  21. "sort"
  22. "strings"
  23. "testing"
  24. "time"
  25. )
  26. // Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided
  27. // interface.
  28. func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) {
  29. // Decode request
  30. var req struct{ Payload string }
  31. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  32. t.Fatal(err)
  33. }
  34. payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
  35. if err != nil {
  36. t.Fatal(err)
  37. }
  38. err = json.Unmarshal(payload, v)
  39. if err != nil {
  40. t.Fatal(err)
  41. }
  42. }
  43. type jwsHead struct {
  44. Alg string
  45. Nonce string
  46. JWK map[string]string `json:"jwk"`
  47. }
  48. func decodeJWSHead(r *http.Request) (*jwsHead, error) {
  49. var req struct{ Protected string }
  50. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  51. return nil, err
  52. }
  53. b, err := base64.RawURLEncoding.DecodeString(req.Protected)
  54. if err != nil {
  55. return nil, err
  56. }
  57. var head jwsHead
  58. if err := json.Unmarshal(b, &head); err != nil {
  59. return nil, err
  60. }
  61. return &head, nil
  62. }
  63. func TestDiscover(t *testing.T) {
  64. const (
  65. reg = "https://example.com/acme/new-reg"
  66. authz = "https://example.com/acme/new-authz"
  67. cert = "https://example.com/acme/new-cert"
  68. revoke = "https://example.com/acme/revoke-cert"
  69. )
  70. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  71. w.Header().Set("Content-Type", "application/json")
  72. fmt.Fprintf(w, `{
  73. "new-reg": %q,
  74. "new-authz": %q,
  75. "new-cert": %q,
  76. "revoke-cert": %q
  77. }`, reg, authz, cert, revoke)
  78. }))
  79. defer ts.Close()
  80. c := Client{DirectoryURL: ts.URL}
  81. dir, err := c.Discover(context.Background())
  82. if err != nil {
  83. t.Fatal(err)
  84. }
  85. if dir.RegURL != reg {
  86. t.Errorf("dir.RegURL = %q; want %q", dir.RegURL, reg)
  87. }
  88. if dir.AuthzURL != authz {
  89. t.Errorf("dir.AuthzURL = %q; want %q", dir.AuthzURL, authz)
  90. }
  91. if dir.CertURL != cert {
  92. t.Errorf("dir.CertURL = %q; want %q", dir.CertURL, cert)
  93. }
  94. if dir.RevokeURL != revoke {
  95. t.Errorf("dir.RevokeURL = %q; want %q", dir.RevokeURL, revoke)
  96. }
  97. }
  98. func TestRegister(t *testing.T) {
  99. contacts := []string{"mailto:admin@example.com"}
  100. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  101. if r.Method == "HEAD" {
  102. w.Header().Set("Replay-Nonce", "test-nonce")
  103. return
  104. }
  105. if r.Method != "POST" {
  106. t.Errorf("r.Method = %q; want POST", r.Method)
  107. }
  108. var j struct {
  109. Resource string
  110. Contact []string
  111. Agreement string
  112. }
  113. decodeJWSRequest(t, &j, r)
  114. // Test request
  115. if j.Resource != "new-reg" {
  116. t.Errorf("j.Resource = %q; want new-reg", j.Resource)
  117. }
  118. if !reflect.DeepEqual(j.Contact, contacts) {
  119. t.Errorf("j.Contact = %v; want %v", j.Contact, contacts)
  120. }
  121. w.Header().Set("Location", "https://ca.tld/acme/reg/1")
  122. w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
  123. w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
  124. w.Header().Add("Link", `<https://ca.tld/acme/terms>;rel="terms-of-service"`)
  125. w.WriteHeader(http.StatusCreated)
  126. b, _ := json.Marshal(contacts)
  127. fmt.Fprintf(w, `{"contact": %s}`, b)
  128. }))
  129. defer ts.Close()
  130. prompt := func(url string) bool {
  131. const terms = "https://ca.tld/acme/terms"
  132. if url != terms {
  133. t.Errorf("prompt url = %q; want %q", url, terms)
  134. }
  135. return false
  136. }
  137. c := Client{Key: testKeyEC, dir: &Directory{RegURL: ts.URL}}
  138. a := &Account{Contact: contacts}
  139. var err error
  140. if a, err = c.Register(context.Background(), a, prompt); err != nil {
  141. t.Fatal(err)
  142. }
  143. if a.URI != "https://ca.tld/acme/reg/1" {
  144. t.Errorf("a.URI = %q; want https://ca.tld/acme/reg/1", a.URI)
  145. }
  146. if a.Authz != "https://ca.tld/acme/new-authz" {
  147. t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz)
  148. }
  149. if a.CurrentTerms != "https://ca.tld/acme/terms" {
  150. t.Errorf("a.CurrentTerms = %q; want https://ca.tld/acme/terms", a.CurrentTerms)
  151. }
  152. if !reflect.DeepEqual(a.Contact, contacts) {
  153. t.Errorf("a.Contact = %v; want %v", a.Contact, contacts)
  154. }
  155. }
  156. func TestUpdateReg(t *testing.T) {
  157. const terms = "https://ca.tld/acme/terms"
  158. contacts := []string{"mailto:admin@example.com"}
  159. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  160. if r.Method == "HEAD" {
  161. w.Header().Set("Replay-Nonce", "test-nonce")
  162. return
  163. }
  164. if r.Method != "POST" {
  165. t.Errorf("r.Method = %q; want POST", r.Method)
  166. }
  167. var j struct {
  168. Resource string
  169. Contact []string
  170. Agreement string
  171. }
  172. decodeJWSRequest(t, &j, r)
  173. // Test request
  174. if j.Resource != "reg" {
  175. t.Errorf("j.Resource = %q; want reg", j.Resource)
  176. }
  177. if j.Agreement != terms {
  178. t.Errorf("j.Agreement = %q; want %q", j.Agreement, terms)
  179. }
  180. if !reflect.DeepEqual(j.Contact, contacts) {
  181. t.Errorf("j.Contact = %v; want %v", j.Contact, contacts)
  182. }
  183. w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
  184. w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
  185. w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, terms))
  186. w.WriteHeader(http.StatusOK)
  187. b, _ := json.Marshal(contacts)
  188. fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms)
  189. }))
  190. defer ts.Close()
  191. c := Client{Key: testKeyEC}
  192. a := &Account{URI: ts.URL, Contact: contacts, AgreedTerms: terms}
  193. var err error
  194. if a, err = c.UpdateReg(context.Background(), a); err != nil {
  195. t.Fatal(err)
  196. }
  197. if a.Authz != "https://ca.tld/acme/new-authz" {
  198. t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz)
  199. }
  200. if a.AgreedTerms != terms {
  201. t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms)
  202. }
  203. if a.CurrentTerms != terms {
  204. t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, terms)
  205. }
  206. if a.URI != ts.URL {
  207. t.Errorf("a.URI = %q; want %q", a.URI, ts.URL)
  208. }
  209. }
  210. func TestGetReg(t *testing.T) {
  211. const terms = "https://ca.tld/acme/terms"
  212. const newTerms = "https://ca.tld/acme/new-terms"
  213. contacts := []string{"mailto:admin@example.com"}
  214. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  215. if r.Method == "HEAD" {
  216. w.Header().Set("Replay-Nonce", "test-nonce")
  217. return
  218. }
  219. if r.Method != "POST" {
  220. t.Errorf("r.Method = %q; want POST", r.Method)
  221. }
  222. var j struct {
  223. Resource string
  224. Contact []string
  225. Agreement string
  226. }
  227. decodeJWSRequest(t, &j, r)
  228. // Test request
  229. if j.Resource != "reg" {
  230. t.Errorf("j.Resource = %q; want reg", j.Resource)
  231. }
  232. if len(j.Contact) != 0 {
  233. t.Errorf("j.Contact = %v", j.Contact)
  234. }
  235. if j.Agreement != "" {
  236. t.Errorf("j.Agreement = %q", j.Agreement)
  237. }
  238. w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
  239. w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
  240. w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, newTerms))
  241. w.WriteHeader(http.StatusOK)
  242. b, _ := json.Marshal(contacts)
  243. fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms)
  244. }))
  245. defer ts.Close()
  246. c := Client{Key: testKeyEC}
  247. a, err := c.GetReg(context.Background(), ts.URL)
  248. if err != nil {
  249. t.Fatal(err)
  250. }
  251. if a.Authz != "https://ca.tld/acme/new-authz" {
  252. t.Errorf("a.AuthzURL = %q; want https://ca.tld/acme/new-authz", a.Authz)
  253. }
  254. if a.AgreedTerms != terms {
  255. t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms)
  256. }
  257. if a.CurrentTerms != newTerms {
  258. t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, newTerms)
  259. }
  260. if a.URI != ts.URL {
  261. t.Errorf("a.URI = %q; want %q", a.URI, ts.URL)
  262. }
  263. }
  264. func TestAuthorize(t *testing.T) {
  265. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  266. if r.Method == "HEAD" {
  267. w.Header().Set("Replay-Nonce", "test-nonce")
  268. return
  269. }
  270. if r.Method != "POST" {
  271. t.Errorf("r.Method = %q; want POST", r.Method)
  272. }
  273. var j struct {
  274. Resource string
  275. Identifier struct {
  276. Type string
  277. Value string
  278. }
  279. }
  280. decodeJWSRequest(t, &j, r)
  281. // Test request
  282. if j.Resource != "new-authz" {
  283. t.Errorf("j.Resource = %q; want new-authz", j.Resource)
  284. }
  285. if j.Identifier.Type != "dns" {
  286. t.Errorf("j.Identifier.Type = %q; want dns", j.Identifier.Type)
  287. }
  288. if j.Identifier.Value != "example.com" {
  289. t.Errorf("j.Identifier.Value = %q; want example.com", j.Identifier.Value)
  290. }
  291. w.Header().Set("Location", "https://ca.tld/acme/auth/1")
  292. w.WriteHeader(http.StatusCreated)
  293. fmt.Fprintf(w, `{
  294. "identifier": {"type":"dns","value":"example.com"},
  295. "status":"pending",
  296. "challenges":[
  297. {
  298. "type":"http-01",
  299. "status":"pending",
  300. "uri":"https://ca.tld/acme/challenge/publickey/id1",
  301. "token":"token1"
  302. },
  303. {
  304. "type":"tls-sni-01",
  305. "status":"pending",
  306. "uri":"https://ca.tld/acme/challenge/publickey/id2",
  307. "token":"token2"
  308. }
  309. ],
  310. "combinations":[[0],[1]]}`)
  311. }))
  312. defer ts.Close()
  313. cl := Client{Key: testKeyEC, dir: &Directory{AuthzURL: ts.URL}}
  314. auth, err := cl.Authorize(context.Background(), "example.com")
  315. if err != nil {
  316. t.Fatal(err)
  317. }
  318. if auth.URI != "https://ca.tld/acme/auth/1" {
  319. t.Errorf("URI = %q; want https://ca.tld/acme/auth/1", auth.URI)
  320. }
  321. if auth.Status != "pending" {
  322. t.Errorf("Status = %q; want pending", auth.Status)
  323. }
  324. if auth.Identifier.Type != "dns" {
  325. t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type)
  326. }
  327. if auth.Identifier.Value != "example.com" {
  328. t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value)
  329. }
  330. if n := len(auth.Challenges); n != 2 {
  331. t.Fatalf("len(auth.Challenges) = %d; want 2", n)
  332. }
  333. c := auth.Challenges[0]
  334. if c.Type != "http-01" {
  335. t.Errorf("c.Type = %q; want http-01", c.Type)
  336. }
  337. if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
  338. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
  339. }
  340. if c.Token != "token1" {
  341. t.Errorf("c.Token = %q; want token1", c.Token)
  342. }
  343. c = auth.Challenges[1]
  344. if c.Type != "tls-sni-01" {
  345. t.Errorf("c.Type = %q; want tls-sni-01", c.Type)
  346. }
  347. if c.URI != "https://ca.tld/acme/challenge/publickey/id2" {
  348. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI)
  349. }
  350. if c.Token != "token2" {
  351. t.Errorf("c.Token = %q; want token2", c.Token)
  352. }
  353. combs := [][]int{{0}, {1}}
  354. if !reflect.DeepEqual(auth.Combinations, combs) {
  355. t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs)
  356. }
  357. }
  358. func TestAuthorizeValid(t *testing.T) {
  359. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  360. if r.Method == "HEAD" {
  361. w.Header().Set("Replay-Nonce", "nonce")
  362. return
  363. }
  364. w.WriteHeader(http.StatusCreated)
  365. w.Write([]byte(`{"status":"valid"}`))
  366. }))
  367. defer ts.Close()
  368. client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
  369. _, err := client.Authorize(context.Background(), "example.com")
  370. if err != nil {
  371. t.Errorf("err = %v", err)
  372. }
  373. }
  374. func TestGetAuthorization(t *testing.T) {
  375. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  376. if r.Method != "GET" {
  377. t.Errorf("r.Method = %q; want GET", r.Method)
  378. }
  379. w.WriteHeader(http.StatusOK)
  380. fmt.Fprintf(w, `{
  381. "identifier": {"type":"dns","value":"example.com"},
  382. "status":"pending",
  383. "challenges":[
  384. {
  385. "type":"http-01",
  386. "status":"pending",
  387. "uri":"https://ca.tld/acme/challenge/publickey/id1",
  388. "token":"token1"
  389. },
  390. {
  391. "type":"tls-sni-01",
  392. "status":"pending",
  393. "uri":"https://ca.tld/acme/challenge/publickey/id2",
  394. "token":"token2"
  395. }
  396. ],
  397. "combinations":[[0],[1]]}`)
  398. }))
  399. defer ts.Close()
  400. cl := Client{Key: testKeyEC}
  401. auth, err := cl.GetAuthorization(context.Background(), ts.URL)
  402. if err != nil {
  403. t.Fatal(err)
  404. }
  405. if auth.Status != "pending" {
  406. t.Errorf("Status = %q; want pending", auth.Status)
  407. }
  408. if auth.Identifier.Type != "dns" {
  409. t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type)
  410. }
  411. if auth.Identifier.Value != "example.com" {
  412. t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value)
  413. }
  414. if n := len(auth.Challenges); n != 2 {
  415. t.Fatalf("len(set.Challenges) = %d; want 2", n)
  416. }
  417. c := auth.Challenges[0]
  418. if c.Type != "http-01" {
  419. t.Errorf("c.Type = %q; want http-01", c.Type)
  420. }
  421. if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
  422. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
  423. }
  424. if c.Token != "token1" {
  425. t.Errorf("c.Token = %q; want token1", c.Token)
  426. }
  427. c = auth.Challenges[1]
  428. if c.Type != "tls-sni-01" {
  429. t.Errorf("c.Type = %q; want tls-sni-01", c.Type)
  430. }
  431. if c.URI != "https://ca.tld/acme/challenge/publickey/id2" {
  432. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI)
  433. }
  434. if c.Token != "token2" {
  435. t.Errorf("c.Token = %q; want token2", c.Token)
  436. }
  437. combs := [][]int{{0}, {1}}
  438. if !reflect.DeepEqual(auth.Combinations, combs) {
  439. t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs)
  440. }
  441. }
  442. func TestWaitAuthorization(t *testing.T) {
  443. var count int
  444. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  445. count++
  446. w.Header().Set("Retry-After", "0")
  447. if count > 1 {
  448. fmt.Fprintf(w, `{"status":"valid"}`)
  449. return
  450. }
  451. fmt.Fprintf(w, `{"status":"pending"}`)
  452. }))
  453. defer ts.Close()
  454. type res struct {
  455. authz *Authorization
  456. err error
  457. }
  458. done := make(chan res)
  459. defer close(done)
  460. go func() {
  461. var client Client
  462. a, err := client.WaitAuthorization(context.Background(), ts.URL)
  463. done <- res{a, err}
  464. }()
  465. select {
  466. case <-time.After(5 * time.Second):
  467. t.Fatal("WaitAuthz took too long to return")
  468. case res := <-done:
  469. if res.err != nil {
  470. t.Fatalf("res.err = %v", res.err)
  471. }
  472. if res.authz == nil {
  473. t.Fatal("res.authz is nil")
  474. }
  475. }
  476. }
  477. func TestWaitAuthorizationInvalid(t *testing.T) {
  478. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  479. fmt.Fprintf(w, `{"status":"invalid"}`)
  480. }))
  481. defer ts.Close()
  482. res := make(chan error)
  483. defer close(res)
  484. go func() {
  485. var client Client
  486. _, err := client.WaitAuthorization(context.Background(), ts.URL)
  487. res <- err
  488. }()
  489. select {
  490. case <-time.After(3 * time.Second):
  491. t.Fatal("WaitAuthz took too long to return")
  492. case err := <-res:
  493. if err == nil {
  494. t.Error("err is nil")
  495. }
  496. if _, ok := err.(*AuthorizationError); !ok {
  497. t.Errorf("err is %T; want *AuthorizationError", err)
  498. }
  499. }
  500. }
  501. func TestWaitAuthorizationClientError(t *testing.T) {
  502. const code = http.StatusBadRequest
  503. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  504. w.WriteHeader(code)
  505. }))
  506. defer ts.Close()
  507. ch := make(chan error, 1)
  508. go func() {
  509. var client Client
  510. _, err := client.WaitAuthorization(context.Background(), ts.URL)
  511. ch <- err
  512. }()
  513. select {
  514. case <-time.After(3 * time.Second):
  515. t.Fatal("WaitAuthz took too long to return")
  516. case err := <-ch:
  517. res, ok := err.(*Error)
  518. if !ok {
  519. t.Fatalf("err is %v (%T); want a non-nil *Error", err, err)
  520. }
  521. if res.StatusCode != code {
  522. t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, code)
  523. }
  524. }
  525. }
  526. func TestWaitAuthorizationCancel(t *testing.T) {
  527. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  528. w.Header().Set("Retry-After", "60")
  529. fmt.Fprintf(w, `{"status":"pending"}`)
  530. }))
  531. defer ts.Close()
  532. res := make(chan error)
  533. defer close(res)
  534. go func() {
  535. var client Client
  536. ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
  537. defer cancel()
  538. _, err := client.WaitAuthorization(ctx, ts.URL)
  539. res <- err
  540. }()
  541. select {
  542. case <-time.After(time.Second):
  543. t.Fatal("WaitAuthz took too long to return")
  544. case err := <-res:
  545. if err == nil {
  546. t.Error("err is nil")
  547. }
  548. }
  549. }
  550. func TestRevokeAuthorization(t *testing.T) {
  551. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  552. if r.Method == "HEAD" {
  553. w.Header().Set("Replay-Nonce", "nonce")
  554. return
  555. }
  556. switch r.URL.Path {
  557. case "/1":
  558. var req struct {
  559. Resource string
  560. Status string
  561. Delete bool
  562. }
  563. decodeJWSRequest(t, &req, r)
  564. if req.Resource != "authz" {
  565. t.Errorf("req.Resource = %q; want authz", req.Resource)
  566. }
  567. if req.Status != "deactivated" {
  568. t.Errorf("req.Status = %q; want deactivated", req.Status)
  569. }
  570. if !req.Delete {
  571. t.Errorf("req.Delete is false")
  572. }
  573. case "/2":
  574. w.WriteHeader(http.StatusInternalServerError)
  575. }
  576. }))
  577. defer ts.Close()
  578. client := &Client{Key: testKey}
  579. ctx := context.Background()
  580. if err := client.RevokeAuthorization(ctx, ts.URL+"/1"); err != nil {
  581. t.Errorf("err = %v", err)
  582. }
  583. if client.RevokeAuthorization(ctx, ts.URL+"/2") == nil {
  584. t.Error("nil error")
  585. }
  586. }
  587. func TestPollChallenge(t *testing.T) {
  588. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  589. if r.Method != "GET" {
  590. t.Errorf("r.Method = %q; want GET", r.Method)
  591. }
  592. w.WriteHeader(http.StatusOK)
  593. fmt.Fprintf(w, `{
  594. "type":"http-01",
  595. "status":"pending",
  596. "uri":"https://ca.tld/acme/challenge/publickey/id1",
  597. "token":"token1"}`)
  598. }))
  599. defer ts.Close()
  600. cl := Client{Key: testKeyEC}
  601. chall, err := cl.GetChallenge(context.Background(), ts.URL)
  602. if err != nil {
  603. t.Fatal(err)
  604. }
  605. if chall.Status != "pending" {
  606. t.Errorf("Status = %q; want pending", chall.Status)
  607. }
  608. if chall.Type != "http-01" {
  609. t.Errorf("c.Type = %q; want http-01", chall.Type)
  610. }
  611. if chall.URI != "https://ca.tld/acme/challenge/publickey/id1" {
  612. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", chall.URI)
  613. }
  614. if chall.Token != "token1" {
  615. t.Errorf("c.Token = %q; want token1", chall.Token)
  616. }
  617. }
  618. func TestAcceptChallenge(t *testing.T) {
  619. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  620. if r.Method == "HEAD" {
  621. w.Header().Set("Replay-Nonce", "test-nonce")
  622. return
  623. }
  624. if r.Method != "POST" {
  625. t.Errorf("r.Method = %q; want POST", r.Method)
  626. }
  627. var j struct {
  628. Resource string
  629. Type string
  630. Auth string `json:"keyAuthorization"`
  631. }
  632. decodeJWSRequest(t, &j, r)
  633. // Test request
  634. if j.Resource != "challenge" {
  635. t.Errorf(`resource = %q; want "challenge"`, j.Resource)
  636. }
  637. if j.Type != "http-01" {
  638. t.Errorf(`type = %q; want "http-01"`, j.Type)
  639. }
  640. keyAuth := "token1." + testKeyECThumbprint
  641. if j.Auth != keyAuth {
  642. t.Errorf(`keyAuthorization = %q; want %q`, j.Auth, keyAuth)
  643. }
  644. // Respond to request
  645. w.WriteHeader(http.StatusAccepted)
  646. fmt.Fprintf(w, `{
  647. "type":"http-01",
  648. "status":"pending",
  649. "uri":"https://ca.tld/acme/challenge/publickey/id1",
  650. "token":"token1",
  651. "keyAuthorization":%q
  652. }`, keyAuth)
  653. }))
  654. defer ts.Close()
  655. cl := Client{Key: testKeyEC}
  656. c, err := cl.Accept(context.Background(), &Challenge{
  657. URI: ts.URL,
  658. Token: "token1",
  659. Type: "http-01",
  660. })
  661. if err != nil {
  662. t.Fatal(err)
  663. }
  664. if c.Type != "http-01" {
  665. t.Errorf("c.Type = %q; want http-01", c.Type)
  666. }
  667. if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
  668. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
  669. }
  670. if c.Token != "token1" {
  671. t.Errorf("c.Token = %q; want token1", c.Token)
  672. }
  673. }
  674. func TestNewCert(t *testing.T) {
  675. notBefore := time.Now()
  676. notAfter := notBefore.AddDate(0, 2, 0)
  677. timeNow = func() time.Time { return notBefore }
  678. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  679. if r.Method == "HEAD" {
  680. w.Header().Set("Replay-Nonce", "test-nonce")
  681. return
  682. }
  683. if r.Method != "POST" {
  684. t.Errorf("r.Method = %q; want POST", r.Method)
  685. }
  686. var j struct {
  687. Resource string `json:"resource"`
  688. CSR string `json:"csr"`
  689. NotBefore string `json:"notBefore,omitempty"`
  690. NotAfter string `json:"notAfter,omitempty"`
  691. }
  692. decodeJWSRequest(t, &j, r)
  693. // Test request
  694. if j.Resource != "new-cert" {
  695. t.Errorf(`resource = %q; want "new-cert"`, j.Resource)
  696. }
  697. if j.NotBefore != notBefore.Format(time.RFC3339) {
  698. t.Errorf(`notBefore = %q; wanted %q`, j.NotBefore, notBefore.Format(time.RFC3339))
  699. }
  700. if j.NotAfter != notAfter.Format(time.RFC3339) {
  701. t.Errorf(`notAfter = %q; wanted %q`, j.NotAfter, notAfter.Format(time.RFC3339))
  702. }
  703. // Respond to request
  704. template := x509.Certificate{
  705. SerialNumber: big.NewInt(int64(1)),
  706. Subject: pkix.Name{
  707. Organization: []string{"goacme"},
  708. },
  709. NotBefore: notBefore,
  710. NotAfter: notAfter,
  711. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  712. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  713. BasicConstraintsValid: true,
  714. }
  715. sampleCert, err := x509.CreateCertificate(rand.Reader, &template, &template, &testKeyEC.PublicKey, testKeyEC)
  716. if err != nil {
  717. t.Fatalf("Error creating certificate: %v", err)
  718. }
  719. w.Header().Set("Location", "https://ca.tld/acme/cert/1")
  720. w.WriteHeader(http.StatusCreated)
  721. w.Write(sampleCert)
  722. }))
  723. defer ts.Close()
  724. csr := x509.CertificateRequest{
  725. Version: 0,
  726. Subject: pkix.Name{
  727. CommonName: "example.com",
  728. Organization: []string{"goacme"},
  729. },
  730. }
  731. csrb, err := x509.CreateCertificateRequest(rand.Reader, &csr, testKeyEC)
  732. if err != nil {
  733. t.Fatal(err)
  734. }
  735. c := Client{Key: testKeyEC, dir: &Directory{CertURL: ts.URL}}
  736. cert, certURL, err := c.CreateCert(context.Background(), csrb, notAfter.Sub(notBefore), false)
  737. if err != nil {
  738. t.Fatal(err)
  739. }
  740. if cert == nil {
  741. t.Errorf("cert is nil")
  742. }
  743. if certURL != "https://ca.tld/acme/cert/1" {
  744. t.Errorf("certURL = %q; want https://ca.tld/acme/cert/1", certURL)
  745. }
  746. }
  747. func TestFetchCert(t *testing.T) {
  748. var count byte
  749. var ts *httptest.Server
  750. ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  751. count++
  752. if count < 3 {
  753. up := fmt.Sprintf("<%s>;rel=up", ts.URL)
  754. w.Header().Set("Link", up)
  755. }
  756. w.Write([]byte{count})
  757. }))
  758. defer ts.Close()
  759. res, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
  760. if err != nil {
  761. t.Fatalf("FetchCert: %v", err)
  762. }
  763. cert := [][]byte{{1}, {2}, {3}}
  764. if !reflect.DeepEqual(res, cert) {
  765. t.Errorf("res = %v; want %v", res, cert)
  766. }
  767. }
  768. func TestFetchCertRetry(t *testing.T) {
  769. var count int
  770. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  771. if count < 1 {
  772. w.Header().Set("Retry-After", "0")
  773. w.WriteHeader(http.StatusAccepted)
  774. count++
  775. return
  776. }
  777. w.Write([]byte{1})
  778. }))
  779. defer ts.Close()
  780. res, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
  781. if err != nil {
  782. t.Fatalf("FetchCert: %v", err)
  783. }
  784. cert := [][]byte{{1}}
  785. if !reflect.DeepEqual(res, cert) {
  786. t.Errorf("res = %v; want %v", res, cert)
  787. }
  788. }
  789. func TestFetchCertCancel(t *testing.T) {
  790. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  791. w.Header().Set("Retry-After", "0")
  792. w.WriteHeader(http.StatusAccepted)
  793. }))
  794. defer ts.Close()
  795. ctx, cancel := context.WithCancel(context.Background())
  796. done := make(chan struct{})
  797. var err error
  798. go func() {
  799. _, err = (&Client{}).FetchCert(ctx, ts.URL, false)
  800. close(done)
  801. }()
  802. cancel()
  803. <-done
  804. if err != context.Canceled {
  805. t.Errorf("err = %v; want %v", err, context.Canceled)
  806. }
  807. }
  808. func TestFetchCertDepth(t *testing.T) {
  809. var count byte
  810. var ts *httptest.Server
  811. ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  812. count++
  813. if count > maxChainLen+1 {
  814. t.Errorf("count = %d; want at most %d", count, maxChainLen+1)
  815. w.WriteHeader(http.StatusInternalServerError)
  816. }
  817. w.Header().Set("Link", fmt.Sprintf("<%s>;rel=up", ts.URL))
  818. w.Write([]byte{count})
  819. }))
  820. defer ts.Close()
  821. _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
  822. if err == nil {
  823. t.Errorf("err is nil")
  824. }
  825. }
  826. func TestFetchCertBreadth(t *testing.T) {
  827. var ts *httptest.Server
  828. ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  829. for i := 0; i < maxChainLen+1; i++ {
  830. w.Header().Add("Link", fmt.Sprintf("<%s>;rel=up", ts.URL))
  831. }
  832. w.Write([]byte{1})
  833. }))
  834. defer ts.Close()
  835. _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
  836. if err == nil {
  837. t.Errorf("err is nil")
  838. }
  839. }
  840. func TestFetchCertSize(t *testing.T) {
  841. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  842. b := bytes.Repeat([]byte{1}, maxCertSize+1)
  843. w.Write(b)
  844. }))
  845. defer ts.Close()
  846. _, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
  847. if err == nil {
  848. t.Errorf("err is nil")
  849. }
  850. }
  851. func TestRevokeCert(t *testing.T) {
  852. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  853. if r.Method == "HEAD" {
  854. w.Header().Set("Replay-Nonce", "nonce")
  855. return
  856. }
  857. var req struct {
  858. Resource string
  859. Certificate string
  860. Reason int
  861. }
  862. decodeJWSRequest(t, &req, r)
  863. if req.Resource != "revoke-cert" {
  864. t.Errorf("req.Resource = %q; want revoke-cert", req.Resource)
  865. }
  866. if req.Reason != 1 {
  867. t.Errorf("req.Reason = %d; want 1", req.Reason)
  868. }
  869. // echo -n cert | base64 | tr -d '=' | tr '/+' '_-'
  870. cert := "Y2VydA"
  871. if req.Certificate != cert {
  872. t.Errorf("req.Certificate = %q; want %q", req.Certificate, cert)
  873. }
  874. }))
  875. defer ts.Close()
  876. client := &Client{
  877. Key: testKeyEC,
  878. dir: &Directory{RevokeURL: ts.URL},
  879. }
  880. ctx := context.Background()
  881. if err := client.RevokeCert(ctx, nil, []byte("cert"), CRLReasonKeyCompromise); err != nil {
  882. t.Fatal(err)
  883. }
  884. }
  885. func TestNonce_add(t *testing.T) {
  886. var c Client
  887. c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
  888. c.addNonce(http.Header{"Replay-Nonce": {}})
  889. c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
  890. nonces := map[string]struct{}{"nonce": {}}
  891. if !reflect.DeepEqual(c.nonces, nonces) {
  892. t.Errorf("c.nonces = %q; want %q", c.nonces, nonces)
  893. }
  894. }
  895. func TestNonce_addMax(t *testing.T) {
  896. c := &Client{nonces: make(map[string]struct{})}
  897. for i := 0; i < maxNonces; i++ {
  898. c.nonces[fmt.Sprintf("%d", i)] = struct{}{}
  899. }
  900. c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
  901. if n := len(c.nonces); n != maxNonces {
  902. t.Errorf("len(c.nonces) = %d; want %d", n, maxNonces)
  903. }
  904. }
  905. func TestNonce_fetch(t *testing.T) {
  906. tests := []struct {
  907. code int
  908. nonce string
  909. }{
  910. {http.StatusOK, "nonce1"},
  911. {http.StatusBadRequest, "nonce2"},
  912. {http.StatusOK, ""},
  913. }
  914. var i int
  915. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  916. if r.Method != "HEAD" {
  917. t.Errorf("%d: r.Method = %q; want HEAD", i, r.Method)
  918. }
  919. w.Header().Set("Replay-Nonce", tests[i].nonce)
  920. w.WriteHeader(tests[i].code)
  921. }))
  922. defer ts.Close()
  923. for ; i < len(tests); i++ {
  924. test := tests[i]
  925. c := &Client{}
  926. n, err := c.fetchNonce(context.Background(), ts.URL)
  927. if n != test.nonce {
  928. t.Errorf("%d: n=%q; want %q", i, n, test.nonce)
  929. }
  930. switch {
  931. case err == nil && test.nonce == "":
  932. t.Errorf("%d: n=%q, err=%v; want non-nil error", i, n, err)
  933. case err != nil && test.nonce != "":
  934. t.Errorf("%d: n=%q, err=%v; want %q", i, n, err, test.nonce)
  935. }
  936. }
  937. }
  938. func TestNonce_fetchError(t *testing.T) {
  939. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  940. w.WriteHeader(http.StatusTooManyRequests)
  941. }))
  942. defer ts.Close()
  943. c := &Client{}
  944. _, err := c.fetchNonce(context.Background(), ts.URL)
  945. e, ok := err.(*Error)
  946. if !ok {
  947. t.Fatalf("err is %T; want *Error", err)
  948. }
  949. if e.StatusCode != http.StatusTooManyRequests {
  950. t.Errorf("e.StatusCode = %d; want %d", e.StatusCode, http.StatusTooManyRequests)
  951. }
  952. }
  953. func TestNonce_postJWS(t *testing.T) {
  954. var count int
  955. seen := make(map[string]bool)
  956. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  957. count++
  958. w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count))
  959. if r.Method == "HEAD" {
  960. // We expect the client do a HEAD request
  961. // but only to fetch the first nonce.
  962. return
  963. }
  964. // Make client.Authorize happy; we're not testing its result.
  965. defer func() {
  966. w.WriteHeader(http.StatusCreated)
  967. w.Write([]byte(`{"status":"valid"}`))
  968. }()
  969. head, err := decodeJWSHead(r)
  970. if err != nil {
  971. t.Errorf("decodeJWSHead: %v", err)
  972. return
  973. }
  974. if head.Nonce == "" {
  975. t.Error("head.Nonce is empty")
  976. return
  977. }
  978. if seen[head.Nonce] {
  979. t.Errorf("nonce is already used: %q", head.Nonce)
  980. }
  981. seen[head.Nonce] = true
  982. }))
  983. defer ts.Close()
  984. client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
  985. if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
  986. t.Errorf("client.Authorize 1: %v", err)
  987. }
  988. // The second call should not generate another extra HEAD request.
  989. if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
  990. t.Errorf("client.Authorize 2: %v", err)
  991. }
  992. if count != 3 {
  993. t.Errorf("total requests count: %d; want 3", count)
  994. }
  995. if n := len(client.nonces); n != 1 {
  996. t.Errorf("len(client.nonces) = %d; want 1", n)
  997. }
  998. for k := range seen {
  999. if _, exist := client.nonces[k]; exist {
  1000. t.Errorf("used nonce %q in client.nonces", k)
  1001. }
  1002. }
  1003. }
  1004. func TestRetryPostJWS(t *testing.T) {
  1005. var count int
  1006. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1007. count++
  1008. w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count))
  1009. if r.Method == "HEAD" {
  1010. // We expect the client to do 2 head requests to fetch
  1011. // nonces, one to start and another after getting badNonce
  1012. return
  1013. }
  1014. head, err := decodeJWSHead(r)
  1015. if err != nil {
  1016. t.Errorf("decodeJWSHead: %v", err)
  1017. } else if head.Nonce == "" {
  1018. t.Error("head.Nonce is empty")
  1019. } else if head.Nonce == "nonce1" {
  1020. // return a badNonce error to force the call to retry
  1021. w.WriteHeader(http.StatusBadRequest)
  1022. w.Write([]byte(`{"type":"urn:ietf:params:acme:error:badNonce"}`))
  1023. return
  1024. }
  1025. // Make client.Authorize happy; we're not testing its result.
  1026. w.WriteHeader(http.StatusCreated)
  1027. w.Write([]byte(`{"status":"valid"}`))
  1028. }))
  1029. defer ts.Close()
  1030. client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
  1031. // This call will fail with badNonce, causing a retry
  1032. if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
  1033. t.Errorf("client.Authorize 1: %v", err)
  1034. }
  1035. if count != 4 {
  1036. t.Errorf("total requests count: %d; want 4", count)
  1037. }
  1038. }
  1039. func TestLinkHeader(t *testing.T) {
  1040. h := http.Header{"Link": {
  1041. `<https://example.com/acme/new-authz>;rel="next"`,
  1042. `<https://example.com/acme/recover-reg>; rel=recover`,
  1043. `<https://example.com/acme/terms>; foo=bar; rel="terms-of-service"`,
  1044. `<dup>;rel="next"`,
  1045. }}
  1046. tests := []struct {
  1047. rel string
  1048. out []string
  1049. }{
  1050. {"next", []string{"https://example.com/acme/new-authz", "dup"}},
  1051. {"recover", []string{"https://example.com/acme/recover-reg"}},
  1052. {"terms-of-service", []string{"https://example.com/acme/terms"}},
  1053. {"empty", nil},
  1054. }
  1055. for i, test := range tests {
  1056. if v := linkHeader(h, test.rel); !reflect.DeepEqual(v, test.out) {
  1057. t.Errorf("%d: linkHeader(%q): %v; want %v", i, test.rel, v, test.out)
  1058. }
  1059. }
  1060. }
  1061. func TestErrorResponse(t *testing.T) {
  1062. s := `{
  1063. "status": 400,
  1064. "type": "urn:acme:error:xxx",
  1065. "detail": "text"
  1066. }`
  1067. res := &http.Response{
  1068. StatusCode: 400,
  1069. Status: "400 Bad Request",
  1070. Body: ioutil.NopCloser(strings.NewReader(s)),
  1071. Header: http.Header{"X-Foo": {"bar"}},
  1072. }
  1073. err := responseError(res)
  1074. v, ok := err.(*Error)
  1075. if !ok {
  1076. t.Fatalf("err = %+v (%T); want *Error type", err, err)
  1077. }
  1078. if v.StatusCode != 400 {
  1079. t.Errorf("v.StatusCode = %v; want 400", v.StatusCode)
  1080. }
  1081. if v.ProblemType != "urn:acme:error:xxx" {
  1082. t.Errorf("v.ProblemType = %q; want urn:acme:error:xxx", v.ProblemType)
  1083. }
  1084. if v.Detail != "text" {
  1085. t.Errorf("v.Detail = %q; want text", v.Detail)
  1086. }
  1087. if !reflect.DeepEqual(v.Header, res.Header) {
  1088. t.Errorf("v.Header = %+v; want %+v", v.Header, res.Header)
  1089. }
  1090. }
  1091. func TestTLSSNI01ChallengeCert(t *testing.T) {
  1092. const (
  1093. token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
  1094. // echo -n <token.testKeyECThumbprint> | shasum -a 256
  1095. san = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.acme.invalid"
  1096. )
  1097. client := &Client{Key: testKeyEC}
  1098. tlscert, name, err := client.TLSSNI01ChallengeCert(token)
  1099. if err != nil {
  1100. t.Fatal(err)
  1101. }
  1102. if n := len(tlscert.Certificate); n != 1 {
  1103. t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
  1104. }
  1105. cert, err := x509.ParseCertificate(tlscert.Certificate[0])
  1106. if err != nil {
  1107. t.Fatal(err)
  1108. }
  1109. if len(cert.DNSNames) != 1 || cert.DNSNames[0] != san {
  1110. t.Fatalf("cert.DNSNames = %v; want %q", cert.DNSNames, san)
  1111. }
  1112. if cert.DNSNames[0] != name {
  1113. t.Errorf("cert.DNSNames[0] != name: %q vs %q", cert.DNSNames[0], name)
  1114. }
  1115. if cn := cert.Subject.CommonName; cn != san {
  1116. t.Errorf("cert.Subject.CommonName = %q; want %q", cn, san)
  1117. }
  1118. }
  1119. func TestTLSSNI02ChallengeCert(t *testing.T) {
  1120. const (
  1121. token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
  1122. // echo -n evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA | shasum -a 256
  1123. sanA = "7ea0aaa69214e71e02cebb18bb867736.09b730209baabf60e43d4999979ff139.token.acme.invalid"
  1124. // echo -n <token.testKeyECThumbprint> | shasum -a 256
  1125. sanB = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.ka.acme.invalid"
  1126. )
  1127. client := &Client{Key: testKeyEC}
  1128. tlscert, name, err := client.TLSSNI02ChallengeCert(token)
  1129. if err != nil {
  1130. t.Fatal(err)
  1131. }
  1132. if n := len(tlscert.Certificate); n != 1 {
  1133. t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
  1134. }
  1135. cert, err := x509.ParseCertificate(tlscert.Certificate[0])
  1136. if err != nil {
  1137. t.Fatal(err)
  1138. }
  1139. names := []string{sanA, sanB}
  1140. if !reflect.DeepEqual(cert.DNSNames, names) {
  1141. t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names)
  1142. }
  1143. sort.Strings(cert.DNSNames)
  1144. i := sort.SearchStrings(cert.DNSNames, name)
  1145. if i >= len(cert.DNSNames) || cert.DNSNames[i] != name {
  1146. t.Errorf("%v doesn't have %q", cert.DNSNames, name)
  1147. }
  1148. if cn := cert.Subject.CommonName; cn != sanA {
  1149. t.Errorf("CommonName = %q; want %q", cn, sanA)
  1150. }
  1151. }
  1152. func TestTLSChallengeCertOpt(t *testing.T) {
  1153. key, err := rsa.GenerateKey(rand.Reader, 512)
  1154. if err != nil {
  1155. t.Fatal(err)
  1156. }
  1157. tmpl := &x509.Certificate{
  1158. SerialNumber: big.NewInt(2),
  1159. Subject: pkix.Name{Organization: []string{"Test"}},
  1160. DNSNames: []string{"should-be-overwritten"},
  1161. }
  1162. opts := []CertOption{WithKey(key), WithTemplate(tmpl)}
  1163. client := &Client{Key: testKeyEC}
  1164. cert1, _, err := client.TLSSNI01ChallengeCert("token", opts...)
  1165. if err != nil {
  1166. t.Fatal(err)
  1167. }
  1168. cert2, _, err := client.TLSSNI02ChallengeCert("token", opts...)
  1169. if err != nil {
  1170. t.Fatal(err)
  1171. }
  1172. for i, tlscert := range []tls.Certificate{cert1, cert2} {
  1173. // verify generated cert private key
  1174. tlskey, ok := tlscert.PrivateKey.(*rsa.PrivateKey)
  1175. if !ok {
  1176. t.Errorf("%d: tlscert.PrivateKey is %T; want *rsa.PrivateKey", i, tlscert.PrivateKey)
  1177. continue
  1178. }
  1179. if tlskey.D.Cmp(key.D) != 0 {
  1180. t.Errorf("%d: tlskey.D = %v; want %v", i, tlskey.D, key.D)
  1181. }
  1182. // verify generated cert public key
  1183. x509Cert, err := x509.ParseCertificate(tlscert.Certificate[0])
  1184. if err != nil {
  1185. t.Errorf("%d: %v", i, err)
  1186. continue
  1187. }
  1188. tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey)
  1189. if !ok {
  1190. t.Errorf("%d: x509Cert.PublicKey is %T; want *rsa.PublicKey", i, x509Cert.PublicKey)
  1191. continue
  1192. }
  1193. if tlspub.N.Cmp(key.N) != 0 {
  1194. t.Errorf("%d: tlspub.N = %v; want %v", i, tlspub.N, key.N)
  1195. }
  1196. // verify template option
  1197. sn := big.NewInt(2)
  1198. if x509Cert.SerialNumber.Cmp(sn) != 0 {
  1199. t.Errorf("%d: SerialNumber = %v; want %v", i, x509Cert.SerialNumber, sn)
  1200. }
  1201. org := []string{"Test"}
  1202. if !reflect.DeepEqual(x509Cert.Subject.Organization, org) {
  1203. t.Errorf("%d: Subject.Organization = %+v; want %+v", i, x509Cert.Subject.Organization, org)
  1204. }
  1205. for _, v := range x509Cert.DNSNames {
  1206. if !strings.HasSuffix(v, ".acme.invalid") {
  1207. t.Errorf("%d: invalid DNSNames element: %q", i, v)
  1208. }
  1209. }
  1210. }
  1211. }
  1212. func TestHTTP01Challenge(t *testing.T) {
  1213. const (
  1214. token = "xxx"
  1215. // thumbprint is precomputed for testKeyEC in jws_test.go
  1216. value = token + "." + testKeyECThumbprint
  1217. urlpath = "/.well-known/acme-challenge/" + token
  1218. )
  1219. client := &Client{Key: testKeyEC}
  1220. val, err := client.HTTP01ChallengeResponse(token)
  1221. if err != nil {
  1222. t.Fatal(err)
  1223. }
  1224. if val != value {
  1225. t.Errorf("val = %q; want %q", val, value)
  1226. }
  1227. if path := client.HTTP01ChallengePath(token); path != urlpath {
  1228. t.Errorf("path = %q; want %q", path, urlpath)
  1229. }
  1230. }
  1231. func TestDNS01ChallengeRecord(t *testing.T) {
  1232. // echo -n xxx.<testKeyECThumbprint> | \
  1233. // openssl dgst -binary -sha256 | \
  1234. // base64 | tr -d '=' | tr '/+' '_-'
  1235. const value = "8DERMexQ5VcdJ_prpPiA0mVdp7imgbCgjsG4SqqNMIo"
  1236. client := &Client{Key: testKeyEC}
  1237. val, err := client.DNS01ChallengeRecord("xxx")
  1238. if err != nil {
  1239. t.Fatal(err)
  1240. }
  1241. if val != value {
  1242. t.Errorf("val = %q; want %q", val, value)
  1243. }
  1244. }
  1245. func TestBackoff(t *testing.T) {
  1246. tt := []struct{ min, max time.Duration }{
  1247. {time.Second, 2 * time.Second},
  1248. {2 * time.Second, 3 * time.Second},
  1249. {4 * time.Second, 5 * time.Second},
  1250. {8 * time.Second, 9 * time.Second},
  1251. }
  1252. for i, test := range tt {
  1253. d := backoff(i, time.Minute)
  1254. if d < test.min || test.max < d {
  1255. t.Errorf("%d: d = %v; want between %v and %v", i, d, test.min, test.max)
  1256. }
  1257. }
  1258. min, max := time.Second, 2*time.Second
  1259. if d := backoff(-1, time.Minute); d < min || max < d {
  1260. t.Errorf("d = %v; want between %v and %v", d, min, max)
  1261. }
  1262. bound := 10 * time.Second
  1263. if d := backoff(100, bound); d != bound {
  1264. t.Errorf("d = %v; want %v", d, bound)
  1265. }
  1266. }