| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- package acme
- import (
- "crypto"
- "crypto/x509"
- "encoding/base64"
- "encoding/pem"
- "fmt"
- "net/http"
- )
- func (c Client) decodeCertificateChain(body []byte, resp *http.Response, account Account) ([]*x509.Certificate, error) {
- var certs []*x509.Certificate
- for {
- var p *pem.Block
- p, body = pem.Decode(body)
- if p == nil {
- break
- }
- cert, err := x509.ParseCertificate(p.Bytes)
- if err != nil {
- return certs, fmt.Errorf("acme: error parsing certificate: %v", err)
- }
- certs = append(certs, cert)
- }
- up := fetchLink(resp, "up")
- if up != "" {
- upCerts, err := c.FetchCertificates(account, up)
- if err != nil {
- return certs, fmt.Errorf("acme: error fetching up cert: %v", err)
- }
- if len(upCerts) != 0 {
- certs = append(certs, upCerts...)
- }
- }
- return certs, nil
- }
- // FetchCertificates downloads a certificate chain from a url given in an order certificate.
- func (c Client) FetchCertificates(account Account, certificateURL string) ([]*x509.Certificate, error) {
- resp, body, err := c.postRaw(0, certificateURL, account.URL, account.PrivateKey, "", []int{http.StatusOK})
- if err != nil {
- return nil, err
- }
- return c.decodeCertificateChain(body, resp, account)
- }
- // FetchAllCertificates downloads a certificate chain from a url given in an order certificate, as well as any alternate certificates if provided.
- // Returns a mapping of certificate urls to the certificate chain.
- func (c Client) FetchAllCertificates(account Account, certificateURL string) (map[string][]*x509.Certificate, error) {
- resp, body, err := c.postRaw(0, certificateURL, account.URL, account.PrivateKey, "", []int{http.StatusOK})
- if err != nil {
- return nil, err
- }
- certChain, err := c.decodeCertificateChain(body, resp, account)
- if err != nil {
- return nil, err
- }
- certs := map[string][]*x509.Certificate{
- certificateURL: certChain,
- }
- alternates := fetchLinks(resp, "alternate")
- for _, altURL := range alternates {
- altResp, altBody, err := c.postRaw(0, altURL, account.URL, account.PrivateKey, "", []int{http.StatusOK})
- if err != nil {
- return certs, fmt.Errorf("acme: error fetching alt cert chain at %q - %v", altURL, err)
- }
- altCertChain, err := c.decodeCertificateChain(altBody, altResp, account)
- if err != nil {
- return certs, fmt.Errorf("acme: error decoding alt cert chain at %q - %v", altURL, err)
- }
- certs[altURL] = altCertChain
- }
- return certs, nil
- }
- // RevokeCertificate revokes a given certificate given the certificate key or account key, and a reason.
- func (c Client) RevokeCertificate(account Account, cert *x509.Certificate, key crypto.Signer, reason int) error {
- revokeReq := struct {
- Certificate string `json:"certificate"`
- Reason int `json:"reason"`
- }{
- Certificate: base64.RawURLEncoding.EncodeToString(cert.Raw),
- Reason: reason,
- }
- kid := ""
- if key == account.PrivateKey {
- kid = account.URL
- }
- if _, err := c.post(c.dir.RevokeCert, kid, key, revokeReq, nil, http.StatusOK); err != nil {
- return err
- }
- return nil
- }
|