acme_test.go 38 KB

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