certificates.go raw

   1  package certificate
   2  
   3  import (
   4  	"bytes"
   5  	"crypto"
   6  	"crypto/x509"
   7  	"encoding/base64"
   8  	"errors"
   9  	"fmt"
  10  	"io"
  11  	"net/http"
  12  	"strings"
  13  	"time"
  14  
  15  	"github.com/go-acme/lego/v4/acme"
  16  	"github.com/go-acme/lego/v4/acme/api"
  17  	"github.com/go-acme/lego/v4/certcrypto"
  18  	"github.com/go-acme/lego/v4/challenge"
  19  	"github.com/go-acme/lego/v4/log"
  20  	"github.com/go-acme/lego/v4/platform/wait"
  21  	"golang.org/x/crypto/ocsp"
  22  	"golang.org/x/net/idna"
  23  )
  24  
  25  const (
  26  	// DefaultOverallRequestLimit is the overall number of request per second
  27  	// limited on the "new-reg", "new-authz" and "new-cert" endpoints.
  28  	// From the documentation the limitation is 20 requests per second,
  29  	// but using 20 as value doesn't work but 18 do.
  30  	// https://letsencrypt.org/docs/rate-limits/
  31  	// ZeroSSL has a limit of 7.
  32  	// https://help.zerossl.com/hc/en-us/articles/17864245480093-Advantages-over-Using-Let-s-Encrypt#h_01HT4Z1JCJFJQFJ1M3P7S085Q9
  33  	DefaultOverallRequestLimit = 18
  34  )
  35  
  36  // maxBodySize is the maximum size of body that we will read.
  37  const maxBodySize = 1024 * 1024
  38  
  39  // Resource represents a CA issued certificate.
  40  // PrivateKey, Certificate and IssuerCertificate are all
  41  // already PEM encoded and can be directly written to disk.
  42  // Certificate may be a certificate bundle,
  43  // depending on the options supplied to create it.
  44  type Resource struct {
  45  	Domain            string `json:"domain"`
  46  	CertURL           string `json:"certUrl"`
  47  	CertStableURL     string `json:"certStableUrl"`
  48  	PrivateKey        []byte `json:"-"`
  49  	Certificate       []byte `json:"-"`
  50  	IssuerCertificate []byte `json:"-"`
  51  	CSR               []byte `json:"-"`
  52  }
  53  
  54  // ObtainRequest The request to obtain certificate.
  55  //
  56  // The first domain in domains is used for the CommonName field of the certificate,
  57  // all other domains are added using the Subject Alternate Names extension.
  58  //
  59  // A new private key is generated for every invocation of the function Obtain.
  60  // If you do not want that you can supply your own private key in the privateKey parameter.
  61  // If this parameter is non-nil it will be used instead of generating a new one.
  62  //
  63  // If `Bundle` is true, the `[]byte` contains both the issuer certificate and your issued certificate as a bundle.
  64  //
  65  // If `AlwaysDeactivateAuthorizations` is true, the authorizations are also relinquished if the obtain request was successful.
  66  // See https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2.
  67  type ObtainRequest struct {
  68  	Domains        []string
  69  	PrivateKey     crypto.PrivateKey
  70  	MustStaple     bool
  71  	EmailAddresses []string
  72  
  73  	NotBefore      time.Time
  74  	NotAfter       time.Time
  75  	Bundle         bool
  76  	PreferredChain string
  77  
  78  	// A string uniquely identifying the profile
  79  	// which will be used to affect issuance of the certificate requested by this Order.
  80  	// - https://www.ietf.org/id/draft-ietf-acme-profiles-00.html#section-4
  81  	Profile string
  82  
  83  	AlwaysDeactivateAuthorizations bool
  84  
  85  	// A string uniquely identifying a previously-issued certificate which this
  86  	// order is intended to replace.
  87  	// - https://www.rfc-editor.org/rfc/rfc9773.html#section-5
  88  	ReplacesCertID string
  89  }
  90  
  91  // ObtainForCSRRequest The request to obtain a certificate matching the CSR passed into it.
  92  //
  93  // If `Bundle` is true, the `[]byte` contains both the issuer certificate and your issued certificate as a bundle.
  94  //
  95  // If `AlwaysDeactivateAuthorizations` is true, the authorizations are also relinquished if the obtain request was successful.
  96  // See https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2.
  97  type ObtainForCSRRequest struct {
  98  	CSR *x509.CertificateRequest
  99  
 100  	PrivateKey crypto.PrivateKey
 101  
 102  	NotBefore      time.Time
 103  	NotAfter       time.Time
 104  	Bundle         bool
 105  	PreferredChain string
 106  
 107  	// A string uniquely identifying the profile
 108  	// which will be used to affect issuance of the certificate requested by this Order.
 109  	// - https://www.ietf.org/id/draft-ietf-acme-profiles-00.html#section-4
 110  	Profile string
 111  
 112  	AlwaysDeactivateAuthorizations bool
 113  
 114  	// A string uniquely identifying a previously-issued certificate which this
 115  	// order is intended to replace.
 116  	// - https://www.rfc-editor.org/rfc/rfc9773.html#section-5
 117  	ReplacesCertID string
 118  }
 119  
 120  type resolver interface {
 121  	Solve(authorizations []acme.Authorization) error
 122  }
 123  
 124  type CertifierOptions struct {
 125  	KeyType             certcrypto.KeyType
 126  	Timeout             time.Duration
 127  	OverallRequestLimit int
 128  	DisableCommonName   bool
 129  }
 130  
 131  // Certifier A service to obtain/renew/revoke certificates.
 132  type Certifier struct {
 133  	core                *api.Core
 134  	resolver            resolver
 135  	options             CertifierOptions
 136  	overallRequestLimit int
 137  }
 138  
 139  // NewCertifier creates a Certifier.
 140  func NewCertifier(core *api.Core, resolver resolver, options CertifierOptions) *Certifier {
 141  	c := &Certifier{
 142  		core:     core,
 143  		resolver: resolver,
 144  		options:  options,
 145  	}
 146  
 147  	c.overallRequestLimit = options.OverallRequestLimit
 148  	if c.overallRequestLimit <= 0 {
 149  		c.overallRequestLimit = DefaultOverallRequestLimit
 150  	}
 151  
 152  	return c
 153  }
 154  
 155  // Obtain tries to obtain a single certificate using all domains passed into it.
 156  //
 157  // This function will never return a partial certificate.
 158  // If one domain in the list fails, the whole certificate will fail.
 159  func (c *Certifier) Obtain(request ObtainRequest) (*Resource, error) {
 160  	if len(request.Domains) == 0 {
 161  		return nil, errors.New("no domains to obtain a certificate for")
 162  	}
 163  
 164  	domains := sanitizeDomain(request.Domains)
 165  
 166  	if request.Bundle {
 167  		log.Infof("[%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
 168  	} else {
 169  		log.Infof("[%s] acme: Obtaining SAN certificate", strings.Join(domains, ", "))
 170  	}
 171  
 172  	orderOpts := &api.OrderOptions{
 173  		NotBefore:      request.NotBefore,
 174  		NotAfter:       request.NotAfter,
 175  		Profile:        request.Profile,
 176  		ReplacesCertID: request.ReplacesCertID,
 177  	}
 178  
 179  	order, err := c.core.Orders.NewWithOptions(domains, orderOpts)
 180  	if err != nil {
 181  		return nil, err
 182  	}
 183  
 184  	authz, err := c.getAuthorizations(order)
 185  	if err != nil {
 186  		// If any challenge fails, return. Do not generate partial SAN certificates.
 187  		c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
 188  		return nil, err
 189  	}
 190  
 191  	err = c.resolver.Solve(authz)
 192  	if err != nil {
 193  		// If any challenge fails, return. Do not generate partial SAN certificates.
 194  		c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
 195  		return nil, err
 196  	}
 197  
 198  	log.Infof("[%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
 199  
 200  	failures := newObtainError()
 201  
 202  	cert, err := c.getForOrder(domains, order, request)
 203  	if err != nil {
 204  		for _, auth := range authz {
 205  			failures.Add(challenge.GetTargetedDomain(auth), err)
 206  		}
 207  	}
 208  
 209  	if request.AlwaysDeactivateAuthorizations {
 210  		c.deactivateAuthorizations(order, true)
 211  	}
 212  
 213  	return cert, failures.Join()
 214  }
 215  
 216  // ObtainForCSR tries to obtain a certificate matching the CSR passed into it.
 217  //
 218  // The domains are inferred from the CommonName and SubjectAltNames, if any.
 219  // The private key for this CSR is not required.
 220  //
 221  // If bundle is true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
 222  //
 223  // This function will never return a partial certificate.
 224  // If one domain in the list fails, the whole certificate will fail.
 225  func (c *Certifier) ObtainForCSR(request ObtainForCSRRequest) (*Resource, error) {
 226  	if request.CSR == nil {
 227  		return nil, errors.New("cannot obtain resource for CSR: CSR is missing")
 228  	}
 229  
 230  	// figure out what domains it concerns
 231  	// start with the common name
 232  	domains := certcrypto.ExtractDomainsCSR(request.CSR)
 233  
 234  	if request.Bundle {
 235  		log.Infof("[%s] acme: Obtaining bundled SAN certificate given a CSR", strings.Join(domains, ", "))
 236  	} else {
 237  		log.Infof("[%s] acme: Obtaining SAN certificate given a CSR", strings.Join(domains, ", "))
 238  	}
 239  
 240  	orderOpts := &api.OrderOptions{
 241  		NotBefore:      request.NotBefore,
 242  		NotAfter:       request.NotAfter,
 243  		Profile:        request.Profile,
 244  		ReplacesCertID: request.ReplacesCertID,
 245  	}
 246  
 247  	order, err := c.core.Orders.NewWithOptions(domains, orderOpts)
 248  	if err != nil {
 249  		return nil, err
 250  	}
 251  
 252  	authz, err := c.getAuthorizations(order)
 253  	if err != nil {
 254  		// If any challenge fails, return. Do not generate partial SAN certificates.
 255  		c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
 256  		return nil, err
 257  	}
 258  
 259  	err = c.resolver.Solve(authz)
 260  	if err != nil {
 261  		// If any challenge fails, return. Do not generate partial SAN certificates.
 262  		c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
 263  		return nil, err
 264  	}
 265  
 266  	log.Infof("[%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
 267  
 268  	failures := newObtainError()
 269  
 270  	var privateKey []byte
 271  	if request.PrivateKey != nil {
 272  		privateKey = certcrypto.PEMEncode(request.PrivateKey)
 273  	}
 274  
 275  	cert, err := c.getForCSR(domains, order, request.Bundle, request.CSR.Raw, privateKey, request.PreferredChain)
 276  	if err != nil {
 277  		for _, auth := range authz {
 278  			failures.Add(challenge.GetTargetedDomain(auth), err)
 279  		}
 280  	}
 281  
 282  	if request.AlwaysDeactivateAuthorizations {
 283  		c.deactivateAuthorizations(order, true)
 284  	}
 285  
 286  	if cert != nil {
 287  		// Add the CSR to the certificate so that it can be used for renewals.
 288  		cert.CSR = certcrypto.PEMEncode(request.CSR)
 289  	}
 290  
 291  	return cert, failures.Join()
 292  }
 293  
 294  func (c *Certifier) getForOrder(domains []string, order acme.ExtendedOrder, request ObtainRequest) (*Resource, error) {
 295  	privateKey := request.PrivateKey
 296  
 297  	if privateKey == nil {
 298  		var err error
 299  
 300  		privateKey, err = certcrypto.GeneratePrivateKey(c.options.KeyType)
 301  		if err != nil {
 302  			return nil, err
 303  		}
 304  	}
 305  
 306  	commonName := ""
 307  	if len(domains[0]) <= 64 && !c.options.DisableCommonName {
 308  		commonName = domains[0]
 309  	}
 310  
 311  	// RFC8555 Section 7.4 "Applying for Certificate Issuance"
 312  	// https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4
 313  	// says:
 314  	//   Clients SHOULD NOT make any assumptions about the sort order of
 315  	//   "identifiers" or "authorizations" elements in the returned order
 316  	//   object.
 317  
 318  	var san []string
 319  	if commonName != "" {
 320  		san = append(san, commonName)
 321  	}
 322  
 323  	for _, auth := range order.Identifiers {
 324  		if auth.Value != commonName {
 325  			san = append(san, auth.Value)
 326  		}
 327  	}
 328  
 329  	csrOptions := certcrypto.CSROptions{
 330  		Domain:         commonName,
 331  		SAN:            san,
 332  		MustStaple:     request.MustStaple,
 333  		EmailAddresses: request.EmailAddresses,
 334  	}
 335  
 336  	csr, err := certcrypto.CreateCSR(privateKey, csrOptions)
 337  	if err != nil {
 338  		return nil, err
 339  	}
 340  
 341  	return c.getForCSR(domains, order, request.Bundle, csr, certcrypto.PEMEncode(privateKey), request.PreferredChain)
 342  }
 343  
 344  func (c *Certifier) getForCSR(domains []string, order acme.ExtendedOrder, bundle bool, csr, privateKeyPem []byte, preferredChain string) (*Resource, error) {
 345  	respOrder, err := c.core.Orders.UpdateForCSR(order.Finalize, csr)
 346  	if err != nil {
 347  		return nil, err
 348  	}
 349  
 350  	certRes := &Resource{
 351  		Domain:     domains[0],
 352  		CertURL:    respOrder.Certificate,
 353  		PrivateKey: privateKeyPem,
 354  	}
 355  
 356  	if respOrder.Status == acme.StatusValid {
 357  		// if the certificate is available right away, shortcut!
 358  		ok, errR := c.checkResponse(respOrder, certRes, bundle, preferredChain)
 359  		if errR != nil {
 360  			return nil, errR
 361  		}
 362  
 363  		if ok {
 364  			return certRes, nil
 365  		}
 366  	}
 367  
 368  	timeout := c.options.Timeout
 369  	if c.options.Timeout <= 0 {
 370  		timeout = 30 * time.Second
 371  	}
 372  
 373  	err = wait.For("certificate", timeout, timeout/60, func() (bool, error) {
 374  		ord, errW := c.core.Orders.Get(order.Location)
 375  		if errW != nil {
 376  			return false, errW
 377  		}
 378  
 379  		done, errW := c.checkResponse(ord, certRes, bundle, preferredChain)
 380  		if errW != nil {
 381  			return false, errW
 382  		}
 383  
 384  		return done, nil
 385  	})
 386  
 387  	return certRes, err
 388  }
 389  
 390  // checkResponse checks to see if the certificate is ready and a link is contained in the response.
 391  //
 392  // If so, loads it into certRes and returns true.
 393  // If the cert is not yet ready, it returns false.
 394  //
 395  // The certRes input should already have the Domain (common name) field populated.
 396  //
 397  // If bundle is true, the certificate will be bundled with the issuer's cert.
 398  func (c *Certifier) checkResponse(order acme.ExtendedOrder, certRes *Resource, bundle bool, preferredChain string) (bool, error) {
 399  	valid, err := checkOrderStatus(order)
 400  	if err != nil || !valid {
 401  		return valid, err
 402  	}
 403  
 404  	certs, err := c.core.Certificates.GetAll(order.Certificate, bundle)
 405  	if err != nil {
 406  		return false, err
 407  	}
 408  
 409  	// Set the default certificate
 410  	certRes.IssuerCertificate = certs[order.Certificate].Issuer
 411  	certRes.Certificate = certs[order.Certificate].Cert
 412  	certRes.CertURL = order.Certificate
 413  	certRes.CertStableURL = order.Certificate
 414  
 415  	if preferredChain == "" {
 416  		log.Infof("[%s] Server responded with a certificate.", certRes.Domain)
 417  
 418  		return true, nil
 419  	}
 420  
 421  	for link, cert := range certs {
 422  		ok, err := hasPreferredChain(cert.Issuer, preferredChain)
 423  		if err != nil {
 424  			return false, err
 425  		}
 426  
 427  		if ok {
 428  			log.Infof("[%s] Server responded with a certificate for the preferred certificate chains %q.", certRes.Domain, preferredChain)
 429  
 430  			certRes.IssuerCertificate = cert.Issuer
 431  			certRes.Certificate = cert.Cert
 432  			certRes.CertURL = link
 433  			certRes.CertStableURL = link
 434  
 435  			return true, nil
 436  		}
 437  	}
 438  
 439  	log.Infof("lego has been configured to prefer certificate chains with issuer %q, but no chain from the CA matched this issuer. Using the default certificate chain instead.", preferredChain)
 440  
 441  	return true, nil
 442  }
 443  
 444  // Revoke takes a PEM encoded certificate or bundle and tries to revoke it at the CA.
 445  func (c *Certifier) Revoke(cert []byte) error {
 446  	return c.RevokeWithReason(cert, nil)
 447  }
 448  
 449  // RevokeWithReason takes a PEM encoded certificate or bundle and tries to revoke it at the CA.
 450  func (c *Certifier) RevokeWithReason(cert []byte, reason *uint) error {
 451  	certificates, err := certcrypto.ParsePEMBundle(cert)
 452  	if err != nil {
 453  		return err
 454  	}
 455  
 456  	x509Cert := certificates[0]
 457  	if x509Cert.IsCA {
 458  		return errors.New("certificate bundle starts with a CA certificate")
 459  	}
 460  
 461  	revokeMsg := acme.RevokeCertMessage{
 462  		Certificate: base64.RawURLEncoding.EncodeToString(x509Cert.Raw),
 463  		Reason:      reason,
 464  	}
 465  
 466  	return c.core.Certificates.Revoke(revokeMsg)
 467  }
 468  
 469  // RenewOptions options used by Certifier.RenewWithOptions.
 470  type RenewOptions struct {
 471  	NotBefore time.Time
 472  	NotAfter  time.Time
 473  	// If true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
 474  	Bundle         bool
 475  	PreferredChain string
 476  
 477  	Profile string
 478  
 479  	AlwaysDeactivateAuthorizations bool
 480  	// Not supported for CSR request.
 481  	MustStaple     bool
 482  	EmailAddresses []string
 483  }
 484  
 485  // Renew takes a Resource and tries to renew the certificate.
 486  //
 487  // If the renewal process succeeds, the new certificate will be returned in a new CertResource.
 488  // Please be aware that this function will return a new certificate in ANY case that is not an error.
 489  // If the server does not provide us with a new cert on a GET request to the CertURL
 490  // this function will start a new-cert flow where a new certificate gets generated.
 491  //
 492  // If bundle is true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
 493  //
 494  // For private key reuse the PrivateKey property of the passed in Resource should be non-nil.
 495  //
 496  // Deprecated: use RenewWithOptions instead.
 497  func (c *Certifier) Renew(certRes Resource, bundle, mustStaple bool, preferredChain string) (*Resource, error) {
 498  	return c.RenewWithOptions(certRes, &RenewOptions{
 499  		Bundle:         bundle,
 500  		PreferredChain: preferredChain,
 501  		MustStaple:     mustStaple,
 502  	})
 503  }
 504  
 505  // RenewWithOptions takes a Resource and tries to renew the certificate.
 506  //
 507  // If the renewal process succeeds, the new certificate will be returned in a new CertResource.
 508  // Please be aware that this function will return a new certificate in ANY case that is not an error.
 509  // If the server does not provide us with a new cert on a GET request to the CertURL
 510  // this function will start a new-cert flow where a new certificate gets generated.
 511  //
 512  // If bundle is true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
 513  //
 514  // For private key reuse the PrivateKey property of the passed in Resource should be non-nil.
 515  func (c *Certifier) RenewWithOptions(certRes Resource, options *RenewOptions) (*Resource, error) {
 516  	// Input certificate is PEM encoded.
 517  	// Decode it here as we may need the decoded cert later on in the renewal process.
 518  	// The input may be a bundle or a single certificate.
 519  	certificates, err := certcrypto.ParsePEMBundle(certRes.Certificate)
 520  	if err != nil {
 521  		return nil, err
 522  	}
 523  
 524  	x509Cert := certificates[0]
 525  	if x509Cert.IsCA {
 526  		return nil, fmt.Errorf("[%s] Certificate bundle starts with a CA certificate", certRes.Domain)
 527  	}
 528  
 529  	// This is just meant to be informal for the user.
 530  	timeLeft := x509Cert.NotAfter.Sub(time.Now().UTC())
 531  	log.Infof("[%s] acme: Trying renewal with %d hours remaining", certRes.Domain, int(timeLeft.Hours()))
 532  
 533  	// We always need to request a new certificate to renew.
 534  	// Start by checking to see if the certificate was based off a CSR,
 535  	// and use that if it's defined.
 536  	if len(certRes.CSR) > 0 {
 537  		csr, errP := certcrypto.PemDecodeTox509CSR(certRes.CSR)
 538  		if errP != nil {
 539  			return nil, errP
 540  		}
 541  
 542  		request := ObtainForCSRRequest{CSR: csr}
 543  
 544  		if options != nil {
 545  			request.NotBefore = options.NotBefore
 546  			request.NotAfter = options.NotAfter
 547  			request.Bundle = options.Bundle
 548  			request.PreferredChain = options.PreferredChain
 549  			request.Profile = options.Profile
 550  			request.AlwaysDeactivateAuthorizations = options.AlwaysDeactivateAuthorizations
 551  		}
 552  
 553  		return c.ObtainForCSR(request)
 554  	}
 555  
 556  	var privateKey crypto.PrivateKey
 557  	if certRes.PrivateKey != nil {
 558  		privateKey, err = certcrypto.ParsePEMPrivateKey(certRes.PrivateKey)
 559  		if err != nil {
 560  			return nil, err
 561  		}
 562  	}
 563  
 564  	request := ObtainRequest{
 565  		Domains:    certcrypto.ExtractDomains(x509Cert),
 566  		PrivateKey: privateKey,
 567  	}
 568  
 569  	if options != nil {
 570  		request.MustStaple = options.MustStaple
 571  		request.NotBefore = options.NotBefore
 572  		request.NotAfter = options.NotAfter
 573  		request.Bundle = options.Bundle
 574  		request.PreferredChain = options.PreferredChain
 575  		request.EmailAddresses = options.EmailAddresses
 576  		request.Profile = options.Profile
 577  		request.AlwaysDeactivateAuthorizations = options.AlwaysDeactivateAuthorizations
 578  	}
 579  
 580  	return c.Obtain(request)
 581  }
 582  
 583  // GetOCSP takes a PEM encoded cert or cert bundle returning the raw OCSP response,
 584  // the parsed response, and an error, if any.
 585  //
 586  // The returned []byte can be passed directly into the OCSPStaple property of a tls.Certificate.
 587  // If the bundle only contains the issued certificate,
 588  // this function will try to get the issuer certificate from the IssuingCertificateURL in the certificate.
 589  //
 590  // If the []byte and/or ocsp.Response return values are nil, the OCSP status may be assumed OCSPUnknown.
 591  func (c *Certifier) GetOCSP(bundle []byte) ([]byte, *ocsp.Response, error) {
 592  	certificates, err := certcrypto.ParsePEMBundle(bundle)
 593  	if err != nil {
 594  		return nil, nil, err
 595  	}
 596  
 597  	// We expect the certificate slice to be ordered downwards the chain.
 598  	// SRV CRT -> CA. We need to pull the leaf and issuer certs out of it,
 599  	// which should always be the first two certificates.
 600  	// If there's no OCSP server listed in the leaf cert, there's nothing to do.
 601  	// And if we have only one certificate so far, we need to get the issuer cert.
 602  
 603  	issuedCert := certificates[0]
 604  
 605  	if len(issuedCert.OCSPServer) == 0 {
 606  		return nil, nil, errors.New("no OCSP server specified in cert")
 607  	}
 608  
 609  	if len(certificates) == 1 {
 610  		// TODO: build fallback. If this fails, check the remaining array entries.
 611  		if len(issuedCert.IssuingCertificateURL) == 0 {
 612  			return nil, nil, errors.New("no issuing certificate URL")
 613  		}
 614  
 615  		resp, errC := c.core.HTTPClient.Get(issuedCert.IssuingCertificateURL[0])
 616  		if errC != nil {
 617  			return nil, nil, errC
 618  		}
 619  		defer resp.Body.Close()
 620  
 621  		issuerBytes, errC := io.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
 622  		if errC != nil {
 623  			return nil, nil, errC
 624  		}
 625  
 626  		issuerCert, errC := x509.ParseCertificate(issuerBytes)
 627  		if errC != nil {
 628  			return nil, nil, errC
 629  		}
 630  
 631  		// Insert it into the slice on position 0
 632  		// We want it ordered right SRV CRT -> CA
 633  		certificates = append(certificates, issuerCert)
 634  	}
 635  
 636  	issuerCert := certificates[1]
 637  
 638  	// Finally kick off the OCSP request.
 639  	ocspReq, err := ocsp.CreateRequest(issuedCert, issuerCert, nil)
 640  	if err != nil {
 641  		return nil, nil, err
 642  	}
 643  
 644  	resp, err := c.core.HTTPClient.Post(issuedCert.OCSPServer[0], "application/ocsp-request", bytes.NewReader(ocspReq))
 645  	if err != nil {
 646  		return nil, nil, err
 647  	}
 648  	defer resp.Body.Close()
 649  
 650  	ocspResBytes, err := io.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
 651  	if err != nil {
 652  		return nil, nil, err
 653  	}
 654  
 655  	ocspRes, err := ocsp.ParseResponse(ocspResBytes, issuerCert)
 656  	if err != nil {
 657  		return nil, nil, err
 658  	}
 659  
 660  	return ocspResBytes, ocspRes, nil
 661  }
 662  
 663  // Get attempts to fetch the certificate at the supplied URL.
 664  // The URL is the same as what would normally be supplied at the Resource's CertURL.
 665  //
 666  // The returned Resource will not have the PrivateKey and CSR fields populated as these will not be available.
 667  //
 668  // If bundle is true, the Certificate field in the returned Resource includes the issuer certificate.
 669  func (c *Certifier) Get(url string, bundle bool) (*Resource, error) {
 670  	cert, issuer, err := c.core.Certificates.Get(url, bundle)
 671  	if err != nil {
 672  		return nil, err
 673  	}
 674  
 675  	// Parse the returned cert bundle so that we can grab the domain from the common name.
 676  	x509Certs, err := certcrypto.ParsePEMBundle(cert)
 677  	if err != nil {
 678  		return nil, err
 679  	}
 680  
 681  	domain, err := certcrypto.GetCertificateMainDomain(x509Certs[0])
 682  	if err != nil {
 683  		return nil, err
 684  	}
 685  
 686  	return &Resource{
 687  		Domain:            domain,
 688  		Certificate:       cert,
 689  		IssuerCertificate: issuer,
 690  		CertURL:           url,
 691  		CertStableURL:     url,
 692  	}, nil
 693  }
 694  
 695  func hasPreferredChain(issuer []byte, preferredChain string) (bool, error) {
 696  	certs, err := certcrypto.ParsePEMBundle(issuer)
 697  	if err != nil {
 698  		return false, err
 699  	}
 700  
 701  	topCert := certs[len(certs)-1]
 702  
 703  	if topCert.Issuer.CommonName == preferredChain {
 704  		return true, nil
 705  	}
 706  
 707  	return false, nil
 708  }
 709  
 710  func checkOrderStatus(order acme.ExtendedOrder) (bool, error) {
 711  	switch order.Status {
 712  	case acme.StatusValid:
 713  		return true, nil
 714  	case acme.StatusInvalid:
 715  		return false, fmt.Errorf("invalid order: %w", order.Err())
 716  	default:
 717  		return false, nil
 718  	}
 719  }
 720  
 721  // https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.4
 722  // The domain name MUST be encoded in the form in which it would appear in a certificate.
 723  // That is, it MUST be encoded according to the rules in Section 7 of [RFC5280].
 724  //
 725  // https://www.rfc-editor.org/rfc/rfc5280.html#section-7
 726  func sanitizeDomain(domains []string) []string {
 727  	var sanitizedDomains []string
 728  
 729  	for _, domain := range domains {
 730  		sanitizedDomain, err := idna.ToASCII(domain)
 731  		if err != nil {
 732  			log.Infof("skip domain %q: unable to sanitize (punnycode): %v", domain, err)
 733  		} else {
 734  			sanitizedDomains = append(sanitizedDomains, sanitizedDomain)
 735  		}
 736  	}
 737  
 738  	return sanitizedDomains
 739  }
 740