github.com/letsencrypt/boulder@v0.20251208.0/ra/ra.go (about)

     1  package ra
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"crypto"
     7  	"crypto/x509"
     8  	"crypto/x509/pkix"
     9  	"encoding/asn1"
    10  	"encoding/json"
    11  	"errors"
    12  	"fmt"
    13  	"net/url"
    14  	"os"
    15  	"slices"
    16  	"strconv"
    17  	"strings"
    18  	"sync"
    19  	"time"
    20  
    21  	"github.com/go-jose/go-jose/v4"
    22  	"github.com/jmhodges/clock"
    23  	"github.com/prometheus/client_golang/prometheus"
    24  	"github.com/prometheus/client_golang/prometheus/promauto"
    25  	"google.golang.org/protobuf/proto"
    26  	"google.golang.org/protobuf/types/known/durationpb"
    27  	"google.golang.org/protobuf/types/known/emptypb"
    28  	"google.golang.org/protobuf/types/known/timestamppb"
    29  
    30  	"github.com/letsencrypt/boulder/allowlist"
    31  	capb "github.com/letsencrypt/boulder/ca/proto"
    32  	"github.com/letsencrypt/boulder/config"
    33  	"github.com/letsencrypt/boulder/core"
    34  	corepb "github.com/letsencrypt/boulder/core/proto"
    35  	csrlib "github.com/letsencrypt/boulder/csr"
    36  	"github.com/letsencrypt/boulder/ctpolicy"
    37  	berrors "github.com/letsencrypt/boulder/errors"
    38  	"github.com/letsencrypt/boulder/features"
    39  	"github.com/letsencrypt/boulder/goodkey"
    40  	bgrpc "github.com/letsencrypt/boulder/grpc"
    41  	"github.com/letsencrypt/boulder/identifier"
    42  	"github.com/letsencrypt/boulder/issuance"
    43  	blog "github.com/letsencrypt/boulder/log"
    44  	"github.com/letsencrypt/boulder/metrics"
    45  	"github.com/letsencrypt/boulder/policy"
    46  	"github.com/letsencrypt/boulder/probs"
    47  	pubpb "github.com/letsencrypt/boulder/publisher/proto"
    48  	rapb "github.com/letsencrypt/boulder/ra/proto"
    49  	"github.com/letsencrypt/boulder/ratelimits"
    50  	"github.com/letsencrypt/boulder/revocation"
    51  	sapb "github.com/letsencrypt/boulder/sa/proto"
    52  	"github.com/letsencrypt/boulder/va"
    53  	vapb "github.com/letsencrypt/boulder/va/proto"
    54  
    55  	"github.com/letsencrypt/boulder/web"
    56  )
    57  
    58  var (
    59  	errIncompleteGRPCRequest  = errors.New("incomplete gRPC request message")
    60  	errIncompleteGRPCResponse = errors.New("incomplete gRPC response message")
    61  
    62  	// caaRecheckDuration is the amount of time after a CAA check that we will
    63  	// recheck the CAA records for a domain. Per Baseline Requirements, we must
    64  	// recheck CAA records within 8 hours of issuance. We set this to 7 hours to
    65  	// stay on the safe side.
    66  	caaRecheckDuration = -7 * time.Hour
    67  )
    68  
    69  // RegistrationAuthorityImpl defines an RA.
    70  //
    71  // NOTE: All of the fields in RegistrationAuthorityImpl need to be
    72  // populated, or there is a risk of panic.
    73  type RegistrationAuthorityImpl struct {
    74  	rapb.UnsafeRegistrationAuthorityServer
    75  	rapb.UnsafeSCTProviderServer
    76  	CA        capb.CertificateAuthorityClient
    77  	VA        va.RemoteClients
    78  	SA        sapb.StorageAuthorityClient
    79  	PA        core.PolicyAuthority
    80  	publisher pubpb.PublisherClient
    81  
    82  	clk               clock.Clock
    83  	log               blog.Logger
    84  	keyPolicy         goodkey.KeyPolicy
    85  	profiles          *validationProfiles
    86  	maxContactsPerReg int
    87  	limiter           *ratelimits.Limiter
    88  	txnBuilder        *ratelimits.TransactionBuilder
    89  	finalizeTimeout   time.Duration
    90  	drainWG           sync.WaitGroup
    91  
    92  	issuersByNameID map[issuance.NameID]*issuance.Certificate
    93  
    94  	ctpolicy *ctpolicy.CTPolicy
    95  
    96  	ctpolicyResults         *prometheus.HistogramVec
    97  	revocationReasonCounter *prometheus.CounterVec
    98  	namesPerCert            *prometheus.HistogramVec
    99  	newRegCounter           prometheus.Counter
   100  	recheckCAACounter       prometheus.Counter
   101  	newCertCounter          prometheus.Counter
   102  	authzAges               *prometheus.HistogramVec
   103  	orderAges               *prometheus.HistogramVec
   104  	inflightFinalizes       prometheus.Gauge
   105  	certCSRMismatch         prometheus.Counter
   106  	pauseCounter            *prometheus.CounterVec
   107  }
   108  
   109  var _ rapb.RegistrationAuthorityServer = (*RegistrationAuthorityImpl)(nil)
   110  
   111  // Health implements our grpc.checker interface. This method will be called
   112  // periodically to set the gRPC service's healthpb.Health.Check() status.
   113  func (ra *RegistrationAuthorityImpl) Health(ctx context.Context) error {
   114  	if ra.txnBuilder.Ready() {
   115  		return nil
   116  	}
   117  	return errors.New("waiting for overrides")
   118  }
   119  
   120  // NewRegistrationAuthorityImpl constructs a new RA object.
   121  func NewRegistrationAuthorityImpl(
   122  	clk clock.Clock,
   123  	logger blog.Logger,
   124  	stats prometheus.Registerer,
   125  	maxContactsPerReg int,
   126  	keyPolicy goodkey.KeyPolicy,
   127  	limiter *ratelimits.Limiter,
   128  	txnBuilder *ratelimits.TransactionBuilder,
   129  	maxNames int,
   130  	profiles *validationProfiles,
   131  	pubc pubpb.PublisherClient,
   132  	finalizeTimeout time.Duration,
   133  	ctp *ctpolicy.CTPolicy,
   134  	issuers []*issuance.Certificate,
   135  ) *RegistrationAuthorityImpl {
   136  	ctpolicyResults := promauto.With(stats).NewHistogramVec(
   137  		prometheus.HistogramOpts{
   138  			Name:    "ctpolicy_results",
   139  			Help:    "Histogram of latencies of ctpolicy.GetSCTs calls with success/failure/deadlineExceeded labels",
   140  			Buckets: metrics.InternetFacingBuckets,
   141  		},
   142  		[]string{"result"},
   143  	)
   144  
   145  	namesPerCert := promauto.With(stats).NewHistogramVec(prometheus.HistogramOpts{
   146  		Name: "names_per_cert",
   147  		Help: "Histogram of the number of SANs in requested and issued certificates",
   148  		// The namesPerCert buckets are chosen based on the current Let's Encrypt
   149  		// limit of 100 SANs per certificate.
   150  		Buckets: []float64{1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100},
   151  	}, []string{"type"})
   152  
   153  	newRegCounter := promauto.With(stats).NewCounter(prometheus.CounterOpts{
   154  		Name: "new_registrations",
   155  		Help: "A counter of new registrations",
   156  	})
   157  
   158  	recheckCAACounter := promauto.With(stats).NewCounter(prometheus.CounterOpts{
   159  		Name: "recheck_caa",
   160  		Help: "A counter of CAA rechecks",
   161  	})
   162  
   163  	newCertCounter := promauto.With(stats).NewCounter(prometheus.CounterOpts{
   164  		Name: "new_certificates",
   165  		Help: "A counter of issued certificates",
   166  	})
   167  
   168  	revocationReasonCounter := promauto.With(stats).NewCounterVec(prometheus.CounterOpts{
   169  		Name: "revocation_reason",
   170  		Help: "A counter of certificate revocation reasons",
   171  	}, []string{"reason"})
   172  
   173  	authzAges := promauto.With(stats).NewHistogramVec(prometheus.HistogramOpts{
   174  		Name: "authz_ages",
   175  		Help: "Histogram of ages, in seconds, of Authorization objects, labelled by method and type",
   176  		// authzAges keeps track of how old, in seconds, authorizations are when
   177  		// we attach them to a new order and again when we finalize that order.
   178  		// We give it a non-standard bucket distribution so that the leftmost
   179  		// (closest to zero) bucket can be used exclusively for brand-new (i.e.
   180  		// not reused) authzs. Our buckets are: one nanosecond, one second, one
   181  		// minute, one hour, 7 hours (our CAA reuse time), 1 day, 2 days, 7
   182  		// days, 30 days, +inf (should be empty).
   183  		Buckets: []float64{0.000000001, 1, 60, 3600, 25200, 86400, 172800, 604800, 2592000, 7776000},
   184  	}, []string{"method", "type"})
   185  
   186  	orderAges := promauto.With(stats).NewHistogramVec(prometheus.HistogramOpts{
   187  		Name: "order_ages",
   188  		Help: "Histogram of ages, in seconds, of Order objects when they're reused and finalized, labelled by method",
   189  		// Orders currently have a max age of 7 days (168hrs), so our buckets
   190  		// are: one nanosecond (new), 1 second, 10 seconds, 1 minute, 10
   191  		// minutes, 1 hour, 7 hours (our CAA reuse time), 1 day, 2 days, 7 days, +inf.
   192  		Buckets: []float64{0.000000001, 1, 10, 60, 600, 3600, 25200, 86400, 172800, 604800},
   193  	}, []string{"method"})
   194  
   195  	inflightFinalizes := promauto.With(stats).NewGauge(prometheus.GaugeOpts{
   196  		Name: "inflight_finalizes",
   197  		Help: "Gauge of the number of current asynchronous finalize goroutines",
   198  	})
   199  
   200  	certCSRMismatch := promauto.With(stats).NewCounter(prometheus.CounterOpts{
   201  		Name: "cert_csr_mismatch",
   202  		Help: "Number of issued certificates that have failed ra.matchesCSR for any reason. This is _real bad_ and should be alerted upon.",
   203  	})
   204  
   205  	pauseCounter := promauto.With(stats).NewCounterVec(prometheus.CounterOpts{
   206  		Name: "paused_pairs",
   207  		Help: "Number of times a pause operation is performed, labeled by paused=[bool], repaused=[bool], grace=[bool]",
   208  	}, []string{"paused", "repaused", "grace"})
   209  
   210  	issuersByNameID := make(map[issuance.NameID]*issuance.Certificate)
   211  	for _, issuer := range issuers {
   212  		issuersByNameID[issuer.NameID()] = issuer
   213  	}
   214  
   215  	ra := &RegistrationAuthorityImpl{
   216  		clk:                     clk,
   217  		log:                     logger,
   218  		profiles:                profiles,
   219  		maxContactsPerReg:       maxContactsPerReg,
   220  		keyPolicy:               keyPolicy,
   221  		limiter:                 limiter,
   222  		txnBuilder:              txnBuilder,
   223  		publisher:               pubc,
   224  		finalizeTimeout:         finalizeTimeout,
   225  		ctpolicy:                ctp,
   226  		ctpolicyResults:         ctpolicyResults,
   227  		issuersByNameID:         issuersByNameID,
   228  		namesPerCert:            namesPerCert,
   229  		newRegCounter:           newRegCounter,
   230  		recheckCAACounter:       recheckCAACounter,
   231  		newCertCounter:          newCertCounter,
   232  		revocationReasonCounter: revocationReasonCounter,
   233  		authzAges:               authzAges,
   234  		orderAges:               orderAges,
   235  		inflightFinalizes:       inflightFinalizes,
   236  		certCSRMismatch:         certCSRMismatch,
   237  		pauseCounter:            pauseCounter,
   238  	}
   239  	return ra
   240  }
   241  
   242  // ValidationProfileConfig is a config struct which can be used to create a
   243  // ValidationProfile.
   244  type ValidationProfileConfig struct {
   245  	// PendingAuthzLifetime defines how far in the future an authorization's
   246  	// "expires" timestamp is set when it is first created, i.e. how much
   247  	// time the applicant has to attempt the challenge.
   248  	PendingAuthzLifetime config.Duration `validate:"required"`
   249  	// ValidAuthzLifetime defines how far in the future an authorization's
   250  	// "expires" timestamp is set when one of its challenges is fulfilled,
   251  	// i.e. how long a validated authorization may be reused.
   252  	ValidAuthzLifetime config.Duration `validate:"required"`
   253  	// OrderLifetime defines how far in the future an order's "expires"
   254  	// timestamp is set when it is first created, i.e. how much time the
   255  	// applicant has to fulfill all challenges and finalize the order. This is
   256  	// a maximum time: if the order reuses an authorization and that authz
   257  	// expires earlier than this OrderLifetime would otherwise set, then the
   258  	// order's expiration is brought in to match that authorization.
   259  	OrderLifetime config.Duration `validate:"required"`
   260  	// MaxNames is the maximum number of subjectAltNames in a single cert.
   261  	// The value supplied MUST be greater than 0 and no more than 100. These
   262  	// limits are per section 7.1 of our combined CP/CPS, under "DV-SSL
   263  	// Subscriber Certificate". The value must be less than or equal to the
   264  	// global (i.e. not per-profile) value configured in the CA.
   265  	MaxNames int `validate:"omitempty,min=1,max=100"`
   266  	// AllowList specifies the path to a YAML file containing a list of
   267  	// account IDs permitted to use this profile. If no path is
   268  	// specified, the profile is open to all accounts. If the file
   269  	// exists but is empty, the profile is closed to all accounts.
   270  	AllowList string `validate:"omitempty"`
   271  	// IdentifierTypes is a list of identifier types that may be issued under
   272  	// this profile.
   273  	IdentifierTypes []identifier.IdentifierType `validate:"required,dive,oneof=dns ip"`
   274  }
   275  
   276  // validationProfile holds the attributes of a given validation profile.
   277  type validationProfile struct {
   278  	// pendingAuthzLifetime defines how far in the future an authorization's
   279  	// "expires" timestamp is set when it is first created, i.e. how much
   280  	// time the applicant has to attempt the challenge.
   281  	pendingAuthzLifetime time.Duration
   282  	// validAuthzLifetime defines how far in the future an authorization's
   283  	// "expires" timestamp is set when one of its challenges is fulfilled,
   284  	// i.e. how long a validated authorization may be reused.
   285  	validAuthzLifetime time.Duration
   286  	// orderLifetime defines how far in the future an order's "expires"
   287  	// timestamp is set when it is first created, i.e. how much time the
   288  	// applicant has to fulfill all challenges and finalize the order. This is
   289  	// a maximum time: if the order reuses an authorization and that authz
   290  	// expires earlier than this OrderLifetime would otherwise set, then the
   291  	// order's expiration is brought in to match that authorization.
   292  	orderLifetime time.Duration
   293  	// maxNames is the maximum number of subjectAltNames in a single cert.
   294  	maxNames int
   295  	// allowList holds the set of account IDs allowed to use this profile. If
   296  	// nil, the profile is open to all accounts (everyone is allowed).
   297  	allowList *allowlist.List[int64]
   298  	// identifierTypes is a list of identifier types that may be issued under
   299  	// this profile.
   300  	identifierTypes []identifier.IdentifierType
   301  }
   302  
   303  // validationProfiles provides access to the set of configured profiles,
   304  // including the default profile for orders/authzs which do not specify one.
   305  type validationProfiles struct {
   306  	defaultName string
   307  	byName      map[string]*validationProfile
   308  }
   309  
   310  // NewValidationProfiles builds a new validationProfiles struct from the given
   311  // configs and default name. It enforces that the given authorization lifetimes
   312  // are within the bounds mandated by the Baseline Requirements.
   313  func NewValidationProfiles(defaultName string, configs map[string]*ValidationProfileConfig) (*validationProfiles, error) {
   314  	if defaultName == "" {
   315  		return nil, errors.New("default profile name must be configured")
   316  	}
   317  
   318  	profiles := make(map[string]*validationProfile, len(configs))
   319  
   320  	for name, config := range configs {
   321  		// The Baseline Requirements v1.8.1 state that validation tokens "MUST
   322  		// NOT be used for more than 30 days from its creation". If unconfigured
   323  		// or the configured value pendingAuthorizationLifetimeDays is greater
   324  		// than 29 days, bail out.
   325  		if config.PendingAuthzLifetime.Duration <= 0 || config.PendingAuthzLifetime.Duration > 29*(24*time.Hour) {
   326  			return nil, fmt.Errorf("PendingAuthzLifetime value must be greater than 0 and less than 30d, but got %q", config.PendingAuthzLifetime.Duration)
   327  		}
   328  
   329  		// Baseline Requirements v1.8.1 section 4.2.1: "any reused data, document,
   330  		// or completed validation MUST be obtained no more than 398 days prior
   331  		// to issuing the Certificate". If unconfigured or the configured value is
   332  		// greater than 397 days, bail out.
   333  		if config.ValidAuthzLifetime.Duration <= 0 || config.ValidAuthzLifetime.Duration > 397*(24*time.Hour) {
   334  			return nil, fmt.Errorf("ValidAuthzLifetime value must be greater than 0 and less than 398d, but got %q", config.ValidAuthzLifetime.Duration)
   335  		}
   336  
   337  		if config.MaxNames <= 0 || config.MaxNames > 100 {
   338  			return nil, fmt.Errorf("MaxNames must be greater than 0 and at most 100")
   339  		}
   340  
   341  		var allowList *allowlist.List[int64]
   342  		if config.AllowList != "" {
   343  			data, err := os.ReadFile(config.AllowList)
   344  			if err != nil {
   345  				return nil, fmt.Errorf("reading allowlist: %w", err)
   346  			}
   347  			allowList, err = allowlist.NewFromYAML[int64](data)
   348  			if err != nil {
   349  				return nil, fmt.Errorf("parsing allowlist: %w", err)
   350  			}
   351  		}
   352  
   353  		profiles[name] = &validationProfile{
   354  			pendingAuthzLifetime: config.PendingAuthzLifetime.Duration,
   355  			validAuthzLifetime:   config.ValidAuthzLifetime.Duration,
   356  			orderLifetime:        config.OrderLifetime.Duration,
   357  			maxNames:             config.MaxNames,
   358  			allowList:            allowList,
   359  			identifierTypes:      config.IdentifierTypes,
   360  		}
   361  	}
   362  
   363  	_, ok := profiles[defaultName]
   364  	if !ok {
   365  		return nil, fmt.Errorf("no profile configured matching default profile name %q", defaultName)
   366  	}
   367  
   368  	return &validationProfiles{
   369  		defaultName: defaultName,
   370  		byName:      profiles,
   371  	}, nil
   372  }
   373  
   374  func (vp *validationProfiles) get(name string) (*validationProfile, error) {
   375  	if name == "" {
   376  		name = vp.defaultName
   377  	}
   378  	profile, ok := vp.byName[name]
   379  	if !ok {
   380  		return nil, berrors.InvalidProfileError("unrecognized profile name %q", name)
   381  	}
   382  	return profile, nil
   383  }
   384  
   385  // certificateRequestAuthz is a struct for holding information about a valid
   386  // authz referenced during a certificateRequestEvent. It holds both the
   387  // authorization ID and the challenge type that made the authorization valid. We
   388  // specifically include the challenge type that solved the authorization to make
   389  // some common analysis easier.
   390  type certificateRequestAuthz struct {
   391  	ID            string
   392  	ChallengeType core.AcmeChallenge
   393  }
   394  
   395  // certificateRequestEvent is a struct for holding information that is logged as
   396  // JSON to the audit log as the result of an issuance event.
   397  type certificateRequestEvent struct {
   398  	ID string `json:",omitempty"`
   399  	// Requester is the associated account ID
   400  	Requester int64 `json:",omitempty"`
   401  	// OrderID is the associated order ID (may be empty for an ACME v1 issuance)
   402  	OrderID int64 `json:",omitempty"`
   403  	// SerialNumber is the string representation of the issued certificate's
   404  	// serial number
   405  	SerialNumber string `json:",omitempty"`
   406  	// VerifiedFields are required by the baseline requirements and are always
   407  	// a static value for Boulder.
   408  	VerifiedFields []string `json:",omitempty"`
   409  	// CommonName is the subject common name from the issued cert
   410  	CommonName string `json:",omitempty"`
   411  	// Identifiers are the identifiers from the issued cert
   412  	Identifiers identifier.ACMEIdentifiers `json:",omitempty"`
   413  	// NotBefore is the starting timestamp of the issued cert's validity period
   414  	NotBefore time.Time
   415  	// NotAfter is the ending timestamp of the issued cert's validity period
   416  	NotAfter time.Time
   417  	// RequestTime and ResponseTime are for tracking elapsed time during issuance
   418  	RequestTime  time.Time
   419  	ResponseTime time.Time
   420  	// Error contains any encountered errors
   421  	Error string `json:",omitempty"`
   422  	// Authorizations is a map of identifier names to certificateRequestAuthz
   423  	// objects. It can be used to understand how the names in a certificate
   424  	// request were authorized.
   425  	Authorizations map[string]certificateRequestAuthz
   426  	// CertProfileName is a human readable name used to refer to the certificate
   427  	// profile.
   428  	CertProfileName string `json:",omitempty"`
   429  	// CertProfileHash is SHA256 sum over every exported field of an
   430  	// issuance.ProfileConfig, represented here as a hexadecimal string.
   431  	CertProfileHash string `json:",omitempty"`
   432  	// PreviousCertificateIssued is present when this certificate uses the same set
   433  	// of FQDNs as a previous certificate (from any account) and contains the
   434  	// notBefore of the most recent such certificate.
   435  	PreviousCertificateIssued time.Time
   436  	// UserAgent is the User-Agent header from the ACME client (provided to the
   437  	// RA via gRPC metadata).
   438  	UserAgent string
   439  }
   440  
   441  // certificateRevocationEvent is a struct for holding information that is logged
   442  // as JSON to the audit log as the result of a revocation event.
   443  type certificateRevocationEvent struct {
   444  	ID string `json:",omitempty"`
   445  	// SerialNumber is the string representation of the revoked certificate's
   446  	// serial number.
   447  	SerialNumber string `json:",omitempty"`
   448  	// Reason is the integer representing the revocation reason used.
   449  	Reason revocation.Reason `json:"reason"`
   450  	// Method is the way in which revocation was requested.
   451  	// It will be one of the strings: "applicant", "subscriber", "control", "key", or "admin".
   452  	Method string `json:",omitempty"`
   453  	// RequesterID is the account ID of the requester.
   454  	// Will be zero for admin revocations.
   455  	RequesterID int64 `json:",omitempty"`
   456  	CRLShard    int64
   457  	// AdminName is the name of the admin requester.
   458  	// Will be zero for subscriber revocations.
   459  	AdminName string `json:",omitempty"`
   460  	// Error contains any error encountered during revocation.
   461  	Error string `json:",omitempty"`
   462  }
   463  
   464  // finalizationCAACheckEvent is a struct for holding information logged as JSON
   465  // to the info log as the result of an issuance event. It is logged when the RA
   466  // performs the final CAA check of a certificate finalization request.
   467  type finalizationCAACheckEvent struct {
   468  	// Requester is the associated account ID.
   469  	Requester int64 `json:",omitempty"`
   470  	// Reused is a count of Authz where the original CAA check was performed in
   471  	// the last 7 hours.
   472  	Reused int `json:",omitempty"`
   473  	// Rechecked is a count of Authz where a new CAA check was performed because
   474  	// the original check was older than 7 hours.
   475  	Rechecked int `json:",omitempty"`
   476  }
   477  
   478  // NewRegistration constructs a new Registration from a request.
   479  func (ra *RegistrationAuthorityImpl) NewRegistration(ctx context.Context, request *corepb.Registration) (*corepb.Registration, error) {
   480  	// Error if the request is nil, there is no account key or IP address
   481  	if request == nil || len(request.Key) == 0 {
   482  		return nil, errIncompleteGRPCRequest
   483  	}
   484  
   485  	// Check if account key is acceptable for use.
   486  	var key jose.JSONWebKey
   487  	err := key.UnmarshalJSON(request.Key)
   488  	if err != nil {
   489  		return nil, berrors.InternalServerError("failed to unmarshal account key: %s", err.Error())
   490  	}
   491  	err = ra.keyPolicy.GoodKey(ctx, key.Key)
   492  	if err != nil {
   493  		return nil, berrors.MalformedError("invalid public key: %s", err.Error())
   494  	}
   495  
   496  	// Don't populate ID or CreatedAt because those will be set by the SA.
   497  	req := &corepb.Registration{
   498  		Key:       request.Key,
   499  		Agreement: request.Agreement,
   500  		Status:    string(core.StatusValid),
   501  	}
   502  
   503  	// Store the registration object, then return the version that got stored.
   504  	res, err := ra.SA.NewRegistration(ctx, req)
   505  	if err != nil {
   506  		return nil, err
   507  	}
   508  
   509  	ra.newRegCounter.Inc()
   510  	return res, nil
   511  }
   512  
   513  // validateContacts checks the provided list of contacts, returning an error if
   514  // any are not acceptable. Unacceptable contacts lists include:
   515  // * An empty list
   516  // * A list has more than maxContactsPerReg contacts
   517  // * A list containing an empty contact
   518  // * A list containing a contact that does not parse as a URL
   519  // * A list containing a contact that has a URL scheme other than mailto
   520  // * A list containing a mailto contact that contains hfields
   521  // * A list containing a contact that has non-ascii characters
   522  // * A list containing a contact that doesn't pass `policy.ValidEmail`
   523  func (ra *RegistrationAuthorityImpl) validateContacts(contacts []string) error {
   524  	if len(contacts) == 0 {
   525  		return nil // Nothing to validate
   526  	}
   527  	if ra.maxContactsPerReg > 0 && len(contacts) > ra.maxContactsPerReg {
   528  		return berrors.MalformedError(
   529  			"too many contacts provided: %d > %d",
   530  			len(contacts),
   531  			ra.maxContactsPerReg,
   532  		)
   533  	}
   534  
   535  	for _, contact := range contacts {
   536  		if contact == "" {
   537  			return berrors.InvalidEmailError("empty contact")
   538  		}
   539  		parsed, err := url.Parse(contact)
   540  		if err != nil {
   541  			return berrors.InvalidEmailError("unparsable contact")
   542  		}
   543  		if parsed.Scheme != "mailto" {
   544  			return berrors.UnsupportedContactError("only contact scheme 'mailto:' is supported")
   545  		}
   546  		if parsed.RawQuery != "" || contact[len(contact)-1] == '?' {
   547  			return berrors.InvalidEmailError("contact email contains a question mark")
   548  		}
   549  		if parsed.Fragment != "" || contact[len(contact)-1] == '#' {
   550  			return berrors.InvalidEmailError("contact email contains a '#'")
   551  		}
   552  		if !core.IsASCII(contact) {
   553  			return berrors.InvalidEmailError("contact email contains non-ASCII characters")
   554  		}
   555  		err = policy.ValidEmail(parsed.Opaque)
   556  		if err != nil {
   557  			return err
   558  		}
   559  	}
   560  
   561  	// NOTE(@cpu): For historical reasons (</3) we store ACME account contact
   562  	// information de-normalized in a fixed size `contact` field on the
   563  	// `registrations` table. At the time of writing this field is VARCHAR(191)
   564  	// That means the largest marshalled JSON value we can store is 191 bytes.
   565  	const maxContactBytes = 191
   566  	if jsonBytes, err := json.Marshal(contacts); err != nil {
   567  		return fmt.Errorf("failed to marshal reg.Contact to JSON: %w", err)
   568  	} else if len(jsonBytes) >= maxContactBytes {
   569  		return berrors.InvalidEmailError(
   570  			"too many/too long contact(s). Please use shorter or fewer email addresses")
   571  	}
   572  
   573  	return nil
   574  }
   575  
   576  // matchesCSR tests the contents of a generated certificate to make sure
   577  // that the PublicKey, CommonName, and identifiers match those provided in
   578  // the CSR that was used to generate the certificate. It also checks the
   579  // following fields for:
   580  //   - notBefore is not more than 24 hours ago
   581  //   - BasicConstraintsValid is true
   582  //   - IsCA is false
   583  //   - ExtKeyUsage only contains ExtKeyUsageServerAuth & ExtKeyUsageClientAuth
   584  //   - Subject only contains CommonName & Names
   585  func (ra *RegistrationAuthorityImpl) matchesCSR(parsedCertificate *x509.Certificate, csr *x509.CertificateRequest) error {
   586  	if !core.KeyDigestEquals(parsedCertificate.PublicKey, csr.PublicKey) {
   587  		return berrors.InternalServerError("generated certificate public key doesn't match CSR public key")
   588  	}
   589  
   590  	csrIdents := identifier.FromCSR(csr)
   591  	if parsedCertificate.Subject.CommonName != "" {
   592  		// Only check that the issued common name matches one of the SANs if there
   593  		// is an issued CN at all: this allows flexibility on whether we include
   594  		// the CN.
   595  		if !slices.Contains(csrIdents, identifier.NewDNS(parsedCertificate.Subject.CommonName)) {
   596  			return berrors.InternalServerError("generated certificate CommonName doesn't match any CSR name")
   597  		}
   598  	}
   599  
   600  	parsedIdents := identifier.FromCert(parsedCertificate)
   601  	if !slices.Equal(csrIdents, parsedIdents) {
   602  		return berrors.InternalServerError("generated certificate identifiers don't match CSR identifiers")
   603  	}
   604  
   605  	if !slices.Equal(parsedCertificate.EmailAddresses, csr.EmailAddresses) {
   606  		return berrors.InternalServerError("generated certificate EmailAddresses don't match CSR EmailAddresses")
   607  	}
   608  
   609  	if !slices.Equal(parsedCertificate.URIs, csr.URIs) {
   610  		return berrors.InternalServerError("generated certificate URIs don't match CSR URIs")
   611  	}
   612  
   613  	if len(parsedCertificate.Subject.Country) > 0 || len(parsedCertificate.Subject.Organization) > 0 ||
   614  		len(parsedCertificate.Subject.OrganizationalUnit) > 0 || len(parsedCertificate.Subject.Locality) > 0 ||
   615  		len(parsedCertificate.Subject.Province) > 0 || len(parsedCertificate.Subject.StreetAddress) > 0 ||
   616  		len(parsedCertificate.Subject.PostalCode) > 0 {
   617  		return berrors.InternalServerError("generated certificate Subject contains fields other than CommonName, or SerialNumber")
   618  	}
   619  	now := ra.clk.Now()
   620  	if now.Sub(parsedCertificate.NotBefore) > time.Hour*24 {
   621  		return berrors.InternalServerError("generated certificate is back dated %s", now.Sub(parsedCertificate.NotBefore))
   622  	}
   623  	if !parsedCertificate.BasicConstraintsValid {
   624  		return berrors.InternalServerError("generated certificate doesn't have basic constraints set")
   625  	}
   626  	if parsedCertificate.IsCA {
   627  		return berrors.InternalServerError("generated certificate can sign other certificates")
   628  	}
   629  	for _, eku := range parsedCertificate.ExtKeyUsage {
   630  		if eku != x509.ExtKeyUsageServerAuth && eku != x509.ExtKeyUsageClientAuth {
   631  			return berrors.InternalServerError("generated certificate has unacceptable EKU")
   632  		}
   633  	}
   634  	if !slices.Contains(parsedCertificate.ExtKeyUsage, x509.ExtKeyUsageServerAuth) {
   635  		return berrors.InternalServerError("generated certificate doesn't have serverAuth EKU")
   636  	}
   637  
   638  	return nil
   639  }
   640  
   641  // checkOrderAuthorizations verifies that a provided set of names associated
   642  // with a specific order and account has all of the required valid, unexpired
   643  // authorizations to proceed with issuance. It returns the authorizations that
   644  // satisfied the set of names or it returns an error. If it returns an error, it
   645  // will be of type BoulderError.
   646  func (ra *RegistrationAuthorityImpl) checkOrderAuthorizations(
   647  	ctx context.Context,
   648  	orderID orderID,
   649  	acctID accountID,
   650  	idents identifier.ACMEIdentifiers,
   651  	now time.Time) (map[identifier.ACMEIdentifier]*core.Authorization, error) {
   652  	// Get all of the valid authorizations for this account/order
   653  	req := &sapb.GetValidOrderAuthorizationsRequest{
   654  		Id:     int64(orderID),
   655  		AcctID: int64(acctID),
   656  	}
   657  	authzMapPB, err := ra.SA.GetValidOrderAuthorizations2(ctx, req)
   658  	if err != nil {
   659  		return nil, berrors.InternalServerError("error in GetValidOrderAuthorizations: %s", err)
   660  	}
   661  	authzs, err := bgrpc.PBToAuthzMap(authzMapPB)
   662  	if err != nil {
   663  		return nil, err
   664  	}
   665  
   666  	// Ensure that every identifier has a matching authz, and vice-versa.
   667  	var missing []string
   668  	var invalid []string
   669  	var expired []string
   670  	for _, ident := range idents {
   671  		authz, ok := authzs[ident]
   672  		if !ok || authz == nil {
   673  			missing = append(missing, ident.Value)
   674  			continue
   675  		}
   676  		if authz.Status != core.StatusValid {
   677  			invalid = append(invalid, ident.Value)
   678  			continue
   679  		}
   680  		if authz.Expires.Before(now) {
   681  			expired = append(expired, ident.Value)
   682  			continue
   683  		}
   684  		err = ra.PA.CheckAuthzChallenges(authz)
   685  		if err != nil {
   686  			invalid = append(invalid, ident.Value)
   687  			continue
   688  		}
   689  	}
   690  
   691  	if len(missing) > 0 {
   692  		return nil, berrors.UnauthorizedError(
   693  			"authorizations for these identifiers not found: %s",
   694  			strings.Join(missing, ", "),
   695  		)
   696  	}
   697  
   698  	if len(invalid) > 0 {
   699  		return nil, berrors.UnauthorizedError(
   700  			"authorizations for these identifiers not valid: %s",
   701  			strings.Join(invalid, ", "),
   702  		)
   703  	}
   704  	if len(expired) > 0 {
   705  		return nil, berrors.UnauthorizedError(
   706  			"authorizations for these identifiers expired: %s",
   707  			strings.Join(expired, ", "),
   708  		)
   709  	}
   710  
   711  	// Even though this check is cheap, we do it after the more specific checks
   712  	// so that we can return more specific error messages.
   713  	if len(idents) != len(authzs) {
   714  		return nil, berrors.UnauthorizedError("incorrect number of identifiers requested for finalization")
   715  	}
   716  
   717  	// Check that the authzs either don't need CAA rechecking, or do the
   718  	// necessary CAA rechecks right now.
   719  	err = ra.checkAuthorizationsCAA(ctx, int64(acctID), authzs, now)
   720  	if err != nil {
   721  		return nil, err
   722  	}
   723  
   724  	return authzs, nil
   725  }
   726  
   727  // validatedBefore checks if a given authorization's challenge was
   728  // validated before a given time. Returns a bool.
   729  func validatedBefore(authz *core.Authorization, caaRecheckTime time.Time) (bool, error) {
   730  	numChallenges := len(authz.Challenges)
   731  	if numChallenges != 1 {
   732  		return false, berrors.InternalServerError("authorization has incorrect number of challenges. 1 expected, %d found for: id %s", numChallenges, authz.ID)
   733  	}
   734  	if authz.Challenges[0].Validated == nil {
   735  		return false, berrors.InternalServerError("authorization's challenge has no validated timestamp for: id %s", authz.ID)
   736  	}
   737  	return authz.Challenges[0].Validated.Before(caaRecheckTime), nil
   738  }
   739  
   740  // checkAuthorizationsCAA ensures that we have sufficiently-recent CAA checks
   741  // for every input identifier/authz. If any authz was validated too long ago, it
   742  // kicks off a CAA recheck for that identifier If it returns an error, it will
   743  // be of type BoulderError.
   744  func (ra *RegistrationAuthorityImpl) checkAuthorizationsCAA(
   745  	ctx context.Context,
   746  	acctID int64,
   747  	authzs map[identifier.ACMEIdentifier]*core.Authorization,
   748  	now time.Time) error {
   749  	// recheckAuthzs is a list of authorizations that must have their CAA records rechecked
   750  	var recheckAuthzs []*core.Authorization
   751  
   752  	// Per Baseline Requirements, CAA must be checked within 8 hours of
   753  	// issuance. CAA is checked when an authorization is validated, so as
   754  	// long as that was less than 8 hours ago, we're fine. We recheck if
   755  	// that was more than 7 hours ago, to be on the safe side. We can
   756  	// check to see if the authorized challenge `AttemptedAt`
   757  	// (`Validated`) value from the database is before our caaRecheckTime.
   758  	// Set the recheck time to 7 hours ago.
   759  	caaRecheckAfter := now.Add(caaRecheckDuration)
   760  
   761  	for _, authz := range authzs {
   762  		if staleCAA, err := validatedBefore(authz, caaRecheckAfter); err != nil {
   763  			return err
   764  		} else if staleCAA {
   765  			switch authz.Identifier.Type {
   766  			case identifier.TypeDNS:
   767  				// Ensure that CAA is rechecked for this name
   768  				recheckAuthzs = append(recheckAuthzs, authz)
   769  			case identifier.TypeIP:
   770  			default:
   771  				return berrors.MalformedError("invalid identifier type: %s", authz.Identifier.Type)
   772  			}
   773  		}
   774  	}
   775  
   776  	if len(recheckAuthzs) > 0 {
   777  		err := ra.recheckCAA(ctx, recheckAuthzs)
   778  		if err != nil {
   779  			return err
   780  		}
   781  	}
   782  
   783  	caaEvent := &finalizationCAACheckEvent{
   784  		Requester: acctID,
   785  		Reused:    len(authzs) - len(recheckAuthzs),
   786  		Rechecked: len(recheckAuthzs),
   787  	}
   788  	ra.log.InfoObject("FinalizationCaaCheck", caaEvent)
   789  
   790  	return nil
   791  }
   792  
   793  // recheckCAA accepts a list of names that need to have their CAA records
   794  // rechecked because their associated authorizations are sufficiently old and
   795  // performs the CAA checks required for each. If any of the rechecks fail an
   796  // error is returned.
   797  func (ra *RegistrationAuthorityImpl) recheckCAA(ctx context.Context, authzs []*core.Authorization) error {
   798  	ra.recheckCAACounter.Add(float64(len(authzs)))
   799  
   800  	type authzCAAResult struct {
   801  		authz *core.Authorization
   802  		err   error
   803  	}
   804  	ch := make(chan authzCAAResult, len(authzs))
   805  	for _, authz := range authzs {
   806  		go func(authz *core.Authorization) {
   807  			// If an authorization has multiple valid challenges,
   808  			// the type of the first valid challenge is used for
   809  			// the purposes of CAA rechecking.
   810  			var method string
   811  			for _, challenge := range authz.Challenges {
   812  				if challenge.Status == core.StatusValid {
   813  					method = string(challenge.Type)
   814  					break
   815  				}
   816  			}
   817  			if method == "" {
   818  				ch <- authzCAAResult{
   819  					authz: authz,
   820  					err: berrors.InternalServerError(
   821  						"Internal error determining validation method for authorization ID %v (%v)",
   822  						authz.ID, authz.Identifier.Value),
   823  				}
   824  				return
   825  			}
   826  			var resp *vapb.IsCAAValidResponse
   827  			var err error
   828  			resp, err = ra.VA.DoCAA(ctx, &vapb.IsCAAValidRequest{
   829  				Identifier:       authz.Identifier.ToProto(),
   830  				ValidationMethod: method,
   831  				AccountURIID:     authz.RegistrationID,
   832  			})
   833  			if err != nil {
   834  				ra.log.AuditErrf("Rechecking CAA: %s", err)
   835  				err = berrors.InternalServerError(
   836  					"Internal error rechecking CAA for authorization ID %v (%v)",
   837  					authz.ID, authz.Identifier.Value,
   838  				)
   839  			} else if resp.Problem != nil {
   840  				err = berrors.CAAError("rechecking caa: %s", resp.Problem.Detail)
   841  			}
   842  			ch <- authzCAAResult{
   843  				authz: authz,
   844  				err:   err,
   845  			}
   846  		}(authz)
   847  	}
   848  	var subErrors []berrors.SubBoulderError
   849  	// Read a recheckResult for each authz from the results channel
   850  	for range len(authzs) {
   851  		recheckResult := <-ch
   852  		// If the result had a CAA boulder error, construct a suberror with the
   853  		// identifier from the authorization that was checked.
   854  		err := recheckResult.err
   855  		if err != nil {
   856  			var bErr *berrors.BoulderError
   857  			if errors.As(err, &bErr) && bErr.Type == berrors.CAA {
   858  				subErrors = append(subErrors, berrors.SubBoulderError{
   859  					Identifier:   recheckResult.authz.Identifier,
   860  					BoulderError: bErr})
   861  			} else {
   862  				return err
   863  			}
   864  		}
   865  	}
   866  	if len(subErrors) > 0 {
   867  		var detail string
   868  		// If there was only one error, then use it as the top level error that is
   869  		// returned.
   870  		if len(subErrors) == 1 {
   871  			return subErrors[0].BoulderError
   872  		}
   873  		detail = fmt.Sprintf(
   874  			"Rechecking CAA for %q and %d more identifiers failed. "+
   875  				"Refer to sub-problems for more information",
   876  			subErrors[0].Identifier.Value,
   877  			len(subErrors)-1)
   878  		return (&berrors.BoulderError{
   879  			Type:   berrors.CAA,
   880  			Detail: detail,
   881  		}).WithSubErrors(subErrors)
   882  	}
   883  	return nil
   884  }
   885  
   886  // failOrder marks an order as failed by setting the problem details field of
   887  // the order & persisting it through the SA. If an error occurs doing this we
   888  // log it and don't modify the input order. There aren't any alternatives if we
   889  // can't add the error to the order. This function MUST only be called when we
   890  // are already returning an error for another reason.
   891  func (ra *RegistrationAuthorityImpl) failOrder(
   892  	ctx context.Context,
   893  	order *corepb.Order,
   894  	prob *probs.ProblemDetails) {
   895  	// Use a separate context with its own timeout, since the error we encountered
   896  	// may have been a context cancellation or timeout, and these operations still
   897  	// need to succeed.
   898  	ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 1*time.Second)
   899  	defer cancel()
   900  
   901  	// Convert the problem to a protobuf problem for the *corepb.Order field
   902  	pbProb, err := bgrpc.ProblemDetailsToPB(prob)
   903  	if err != nil {
   904  		ra.log.AuditErrf("Could not convert order error problem to PB: %q", err)
   905  		return
   906  	}
   907  
   908  	// Assign the protobuf problem to the field and save it via the SA
   909  	order.Error = pbProb
   910  	_, err = ra.SA.SetOrderError(ctx, &sapb.SetOrderErrorRequest{
   911  		Id:    order.Id,
   912  		Error: order.Error,
   913  	})
   914  	if err != nil {
   915  		ra.log.AuditErrf("Could not persist order error: %q", err)
   916  	}
   917  }
   918  
   919  // To help minimize the chance that an accountID would be used as an order ID
   920  // (or vice versa) when calling functions that use both we define internal
   921  // `accountID` and `orderID` types so that callers must explicitly cast.
   922  type accountID int64
   923  type orderID int64
   924  
   925  // FinalizeOrder accepts a request to finalize an order object and, if possible,
   926  // issues a certificate to satisfy the order. If an order does not have valid,
   927  // unexpired authorizations for all of its associated names an error is
   928  // returned. Similarly we vet that all of the names in the order are acceptable
   929  // based on current policy and return an error if the order can't be fulfilled.
   930  // If successful the order will be returned in processing status for the client
   931  // to poll while awaiting finalization to occur.
   932  func (ra *RegistrationAuthorityImpl) FinalizeOrder(ctx context.Context, req *rapb.FinalizeOrderRequest) (*corepb.Order, error) {
   933  	// Step 1: Set up logging/tracing and validate the Order
   934  	if req == nil || req.Order == nil || len(req.Csr) == 0 {
   935  		return nil, errIncompleteGRPCRequest
   936  	}
   937  
   938  	logEvent := certificateRequestEvent{
   939  		ID:          core.NewToken(),
   940  		OrderID:     req.Order.Id,
   941  		Requester:   req.Order.RegistrationID,
   942  		RequestTime: ra.clk.Now(),
   943  		UserAgent:   web.UserAgent(ctx),
   944  	}
   945  	csr, err := ra.validateFinalizeRequest(ctx, req, &logEvent)
   946  	if err != nil {
   947  		return nil, err
   948  	}
   949  
   950  	// Observe the age of this order, so we know how quickly most clients complete
   951  	// issuance flows.
   952  	ra.orderAges.WithLabelValues("FinalizeOrder").Observe(ra.clk.Since(req.Order.Created.AsTime()).Seconds())
   953  
   954  	// Step 2: Set the Order to Processing status
   955  	//
   956  	// We do this separately from the issuance process itself so that, when we
   957  	// switch to doing issuance asynchronously, we aren't lying to the client
   958  	// when we say that their order is already Processing.
   959  	//
   960  	// NOTE(@cpu): After this point any errors that are encountered must update
   961  	// the state of the order to invalid by setting the order's error field.
   962  	// Otherwise the order will be "stuck" in processing state. It can not be
   963  	// finalized because it isn't pending, but we aren't going to process it
   964  	// further because we already did and encountered an error.
   965  	_, err = ra.SA.SetOrderProcessing(ctx, &sapb.OrderRequest{Id: req.Order.Id})
   966  	if err != nil {
   967  		// Fail the order with a server internal error - we weren't able to set the
   968  		// status to processing and that's unexpected & weird.
   969  		ra.failOrder(ctx, req.Order, probs.ServerInternal("Error setting order processing"))
   970  		return nil, err
   971  	}
   972  
   973  	// Update the order status locally since the SA doesn't return the updated
   974  	// order itself after setting the status
   975  	order := req.Order
   976  	order.Status = string(core.StatusProcessing)
   977  
   978  	// Steps 3 (issuance) and 4 (cleanup) are done inside a helper function so
   979  	// that we can control whether or not that work happens asynchronously.
   980  	if features.Get().AsyncFinalize {
   981  		// We do this work in a goroutine so that we can better handle latency from
   982  		// getting SCTs and writing the (pre)certificate to the database. This lets
   983  		// us return the order in the Processing state to the client immediately,
   984  		// prompting them to poll the Order object and wait for it to be put into
   985  		// its final state.
   986  		//
   987  		// We track this goroutine's lifetime in a waitgroup global to this RA, so
   988  		// that it can wait for all goroutines to drain during shutdown.
   989  		ra.drainWG.Go(func() {
   990  			// The original context will be canceled in the RPC layer when FinalizeOrder returns,
   991  			// so split off a context that won't be canceled (and has its own timeout).
   992  			ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), ra.finalizeTimeout)
   993  			defer cancel()
   994  			_, err := ra.issueCertificateOuter(ctx, proto.Clone(order).(*corepb.Order), csr, logEvent)
   995  			if err != nil {
   996  				// We only log here, because this is in a background goroutine with
   997  				// no parent goroutine waiting for it to receive the error.
   998  				ra.log.AuditErrf("Asynchronous finalization failed: %s", err.Error())
   999  			}
  1000  		})
  1001  		return order, nil
  1002  	} else {
  1003  		return ra.issueCertificateOuter(ctx, order, csr, logEvent)
  1004  	}
  1005  }
  1006  
  1007  // containsMustStaple returns true if the provided set of extensions includes
  1008  // an entry whose OID and value both match the expected values for the OCSP
  1009  // Must-Staple (a.k.a. id-pe-tlsFeature) extension.
  1010  func containsMustStaple(extensions []pkix.Extension) bool {
  1011  	// RFC 7633: id-pe-tlsfeature OBJECT IDENTIFIER ::=  { id-pe 24 }
  1012  	var mustStapleExtId = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 24}
  1013  	// ASN.1 encoding of:
  1014  	// SEQUENCE
  1015  	//   INTEGER 5
  1016  	// where "5" is the status_request feature (RFC 6066)
  1017  	var mustStapleExtValue = []byte{0x30, 0x03, 0x02, 0x01, 0x05}
  1018  
  1019  	for _, ext := range extensions {
  1020  		if ext.Id.Equal(mustStapleExtId) && bytes.Equal(ext.Value, mustStapleExtValue) {
  1021  			return true
  1022  		}
  1023  	}
  1024  	return false
  1025  }
  1026  
  1027  // validateFinalizeRequest checks that a FinalizeOrder request is fully correct
  1028  // and ready for issuance.
  1029  func (ra *RegistrationAuthorityImpl) validateFinalizeRequest(
  1030  	ctx context.Context,
  1031  	req *rapb.FinalizeOrderRequest,
  1032  	logEvent *certificateRequestEvent) (*x509.CertificateRequest, error) {
  1033  	if req.Order.Id <= 0 {
  1034  		return nil, berrors.MalformedError("invalid order ID: %d", req.Order.Id)
  1035  	}
  1036  
  1037  	if req.Order.RegistrationID <= 0 {
  1038  		return nil, berrors.MalformedError("invalid account ID: %d", req.Order.RegistrationID)
  1039  	}
  1040  
  1041  	if core.AcmeStatus(req.Order.Status) != core.StatusReady {
  1042  		return nil, berrors.OrderNotReadyError(
  1043  			"Order's status (%q) is not acceptable for finalization",
  1044  			req.Order.Status)
  1045  	}
  1046  
  1047  	profile, err := ra.profiles.get(req.Order.CertificateProfileName)
  1048  	if err != nil {
  1049  		return nil, err
  1050  	}
  1051  
  1052  	orderIdents := identifier.Normalize(identifier.FromProtoSlice(req.Order.Identifiers))
  1053  
  1054  	// There should never be an order with 0 identifiers at the stage, but we check to
  1055  	// be on the safe side, throwing an internal server error if this assumption
  1056  	// is ever violated.
  1057  	if len(orderIdents) == 0 {
  1058  		return nil, berrors.InternalServerError("Order has no associated identifiers")
  1059  	}
  1060  
  1061  	// Parse the CSR from the request
  1062  	csr, err := x509.ParseCertificateRequest(req.Csr)
  1063  	if err != nil {
  1064  		return nil, berrors.BadCSRError("unable to parse CSR: %s", err.Error())
  1065  	}
  1066  
  1067  	if containsMustStaple(csr.Extensions) {
  1068  		return nil, berrors.UnauthorizedError(
  1069  			"OCSP must-staple extension is no longer available: see https://letsencrypt.org/2024/12/05/ending-ocsp",
  1070  		)
  1071  	}
  1072  
  1073  	err = csrlib.VerifyCSR(ctx, csr, profile.maxNames, &ra.keyPolicy, ra.PA)
  1074  	if err != nil {
  1075  		// VerifyCSR returns berror instances that can be passed through as-is
  1076  		// without wrapping.
  1077  		return nil, err
  1078  	}
  1079  
  1080  	// Dedupe, lowercase and sort both the names from the CSR and the names in the
  1081  	// order.
  1082  	csrIdents := identifier.FromCSR(csr)
  1083  	// Check that the order names and the CSR names are an exact match
  1084  	if !slices.Equal(csrIdents, orderIdents) {
  1085  		return nil, berrors.UnauthorizedError("CSR does not specify same identifiers as Order")
  1086  	}
  1087  
  1088  	// Get the originating account for use in the next check.
  1089  	regPB, err := ra.SA.GetRegistration(ctx, &sapb.RegistrationID{Id: req.Order.RegistrationID})
  1090  	if err != nil {
  1091  		return nil, err
  1092  	}
  1093  
  1094  	account, err := bgrpc.PbToRegistration(regPB)
  1095  	if err != nil {
  1096  		return nil, err
  1097  	}
  1098  
  1099  	// Make sure they're not using their account key as the certificate key too.
  1100  	if core.KeyDigestEquals(csr.PublicKey, account.Key) {
  1101  		return nil, berrors.MalformedError("certificate public key must be different than account key")
  1102  	}
  1103  
  1104  	// Double-check that all authorizations on this order are valid, are also
  1105  	// associated with the same account as the order itself, and have recent CAA.
  1106  	authzs, err := ra.checkOrderAuthorizations(
  1107  		ctx, orderID(req.Order.Id), accountID(req.Order.RegistrationID), csrIdents, ra.clk.Now())
  1108  	if err != nil {
  1109  		// Pass through the error without wrapping it because the called functions
  1110  		// return BoulderError and we don't want to lose the type.
  1111  		return nil, err
  1112  	}
  1113  
  1114  	// Collect up a certificateRequestAuthz that stores the ID and challenge type
  1115  	// of each of the valid authorizations we used for this issuance.
  1116  	logEventAuthzs := make(map[string]certificateRequestAuthz, len(csrIdents))
  1117  	for _, authz := range authzs {
  1118  		// No need to check for error here because we know this same call just
  1119  		// succeeded inside ra.checkOrderAuthorizations
  1120  		solvedByChallengeType, _ := authz.SolvedBy()
  1121  		logEventAuthzs[authz.Identifier.Value] = certificateRequestAuthz{
  1122  			ID:            authz.ID,
  1123  			ChallengeType: solvedByChallengeType,
  1124  		}
  1125  		authzAge := (profile.validAuthzLifetime - authz.Expires.Sub(ra.clk.Now())).Seconds()
  1126  		ra.authzAges.WithLabelValues("FinalizeOrder", string(authz.Status)).Observe(authzAge)
  1127  	}
  1128  	logEvent.Authorizations = logEventAuthzs
  1129  
  1130  	// Mark that we verified the CN and SANs
  1131  	logEvent.VerifiedFields = []string{"subject.commonName", "subjectAltName"}
  1132  
  1133  	return csr, nil
  1134  }
  1135  
  1136  func (ra *RegistrationAuthorityImpl) GetSCTs(ctx context.Context, sctRequest *rapb.SCTRequest) (*rapb.SCTResponse, error) {
  1137  	scts, err := ra.getSCTs(ctx, sctRequest.PrecertDER)
  1138  	if err != nil {
  1139  		return nil, err
  1140  	}
  1141  	return &rapb.SCTResponse{
  1142  		SctDER: scts,
  1143  	}, nil
  1144  }
  1145  
  1146  // issueCertificateOuter exists solely to ensure that all calls to
  1147  // issueCertificateInner have their result handled uniformly, no matter what
  1148  // return path that inner function takes. It takes ownership of the logEvent,
  1149  // mutates it, and is responsible for outputting its final state.
  1150  func (ra *RegistrationAuthorityImpl) issueCertificateOuter(
  1151  	ctx context.Context,
  1152  	order *corepb.Order,
  1153  	csr *x509.CertificateRequest,
  1154  	logEvent certificateRequestEvent,
  1155  ) (*corepb.Order, error) {
  1156  	ra.inflightFinalizes.Inc()
  1157  	defer ra.inflightFinalizes.Dec()
  1158  
  1159  	idents := identifier.FromProtoSlice(order.Identifiers)
  1160  
  1161  	isRenewal := false
  1162  	timestamps, err := ra.SA.FQDNSetTimestampsForWindow(ctx, &sapb.CountFQDNSetsRequest{
  1163  		Identifiers: idents.ToProtoSlice(),
  1164  		Window:      durationpb.New(120 * 24 * time.Hour),
  1165  		Limit:       1,
  1166  	})
  1167  	if err != nil {
  1168  		return nil, fmt.Errorf("checking if certificate is a renewal: %w", err)
  1169  	}
  1170  	if len(timestamps.Timestamps) > 0 {
  1171  		isRenewal = true
  1172  		logEvent.PreviousCertificateIssued = timestamps.Timestamps[0].AsTime()
  1173  	}
  1174  
  1175  	profileName := order.CertificateProfileName
  1176  	if profileName == "" {
  1177  		profileName = ra.profiles.defaultName
  1178  	}
  1179  
  1180  	// Step 3: Issue the Certificate
  1181  	cert, err := ra.issueCertificateInner(
  1182  		ctx, csr, isRenewal, profileName, accountID(order.RegistrationID), orderID(order.Id))
  1183  
  1184  	// Step 4: Fail the order if necessary, and update metrics and log fields
  1185  	var result string
  1186  	if err != nil {
  1187  		// The problem is computed using `web.ProblemDetailsForError`, the same
  1188  		// function the WFE uses to convert between `berrors` and problems. This
  1189  		// will turn normal expected berrors like berrors.UnauthorizedError into the
  1190  		// correct `urn:ietf:params:acme:error:unauthorized` problem while not
  1191  		// letting anything like a server internal error through with sensitive
  1192  		// info.
  1193  		ra.failOrder(ctx, order, web.ProblemDetailsForError(err, "Error finalizing order"))
  1194  		order.Status = string(core.StatusInvalid)
  1195  
  1196  		logEvent.Error = err.Error()
  1197  		result = "error"
  1198  	} else {
  1199  		order.CertificateSerial = core.SerialToString(cert.SerialNumber)
  1200  		order.Status = string(core.StatusValid)
  1201  
  1202  		ra.namesPerCert.With(
  1203  			prometheus.Labels{"type": "issued"},
  1204  		).Observe(float64(len(idents)))
  1205  
  1206  		ra.newCertCounter.Inc()
  1207  
  1208  		logEvent.SerialNumber = core.SerialToString(cert.SerialNumber)
  1209  		logEvent.CommonName = cert.Subject.CommonName
  1210  		logEvent.Identifiers = identifier.FromCert(cert)
  1211  		logEvent.NotBefore = cert.NotBefore
  1212  		logEvent.NotAfter = cert.NotAfter
  1213  		logEvent.CertProfileName = profileName
  1214  
  1215  		result = "successful"
  1216  	}
  1217  
  1218  	logEvent.ResponseTime = ra.clk.Now()
  1219  	ra.log.AuditObject(fmt.Sprintf("Certificate request - %s", result), logEvent)
  1220  
  1221  	return order, err
  1222  }
  1223  
  1224  // countCertificateIssued increments the certificates (per domain and per
  1225  // account) and duplicate certificate rate limits. There is no reason to surface
  1226  // errors from this function to the Subscriber, spends against these limit are
  1227  // best effort.
  1228  func (ra *RegistrationAuthorityImpl) countCertificateIssued(ctx context.Context, regId int64, orderIdents identifier.ACMEIdentifiers, isRenewal bool) {
  1229  	var transactions []ratelimits.Transaction
  1230  	if !isRenewal {
  1231  		txns, err := ra.txnBuilder.CertificatesPerDomainSpendOnlyTransactions(regId, orderIdents)
  1232  		if err != nil {
  1233  			ra.log.Warningf("building rate limit transactions at finalize: %s", err)
  1234  		}
  1235  		transactions = append(transactions, txns...)
  1236  	}
  1237  
  1238  	txn, err := ra.txnBuilder.CertificatesPerFQDNSetSpendOnlyTransaction(orderIdents)
  1239  	if err != nil {
  1240  		ra.log.Warningf("building rate limit transaction at finalize: %s", err)
  1241  	}
  1242  	transactions = append(transactions, txn)
  1243  
  1244  	_, err = ra.limiter.BatchSpend(ctx, transactions)
  1245  	if err != nil {
  1246  		if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
  1247  			return
  1248  		}
  1249  		ra.log.Warningf("spending against rate limits at finalize: %s", err)
  1250  	}
  1251  }
  1252  
  1253  // issueCertificateInner is part of the [issuance cycle].
  1254  //
  1255  // It gets a precertificate from the CA, submits it to CT logs to get SCTs,
  1256  // then sends the precertificate and the SCTs to the CA to get a final certificate.
  1257  //
  1258  // This function is responsible for ensuring that we never try to issue a final
  1259  // certificate twice for the same precertificate, because that has the potential
  1260  // to create certificates with duplicate serials. For instance, this could
  1261  // happen if final certificates were created with different sets of SCTs. This
  1262  // function accomplishes that by bailing on issuance if there is any error in
  1263  // IssueCertificateForPrecertificate; there are no retries, and serials are
  1264  // generated in IssuePrecertificate, so serials with errors are dropped and
  1265  // never have final certificates issued for them (because there is a possibility
  1266  // that the certificate was actually issued but there was an error returning
  1267  // it).
  1268  //
  1269  // [issuance cycle]: https://github.com/letsencrypt/boulder/blob/main/docs/ISSUANCE-CYCLE.md
  1270  func (ra *RegistrationAuthorityImpl) issueCertificateInner(
  1271  	ctx context.Context,
  1272  	csr *x509.CertificateRequest,
  1273  	isRenewal bool,
  1274  	profileName string,
  1275  	acctID accountID,
  1276  	oID orderID) (*x509.Certificate, error) {
  1277  	// wrapError adds a prefix to an error. If the error is a boulder error then
  1278  	// the problem detail is updated with the prefix. Otherwise a new error is
  1279  	// returned with the message prefixed using `fmt.Errorf`
  1280  	wrapError := func(e error, prefix string) error {
  1281  		if berr, ok := e.(*berrors.BoulderError); ok {
  1282  			berr.Detail = fmt.Sprintf("%s: %s", prefix, berr.Detail)
  1283  			return berr
  1284  		}
  1285  		return fmt.Errorf("%s: %s", prefix, e)
  1286  	}
  1287  
  1288  	issueReq := &capb.IssueCertificateRequest{
  1289  		Csr:             csr.Raw,
  1290  		RegistrationID:  int64(acctID),
  1291  		OrderID:         int64(oID),
  1292  		CertProfileName: profileName,
  1293  	}
  1294  
  1295  	resp, err := ra.CA.IssueCertificate(ctx, issueReq)
  1296  	if err != nil {
  1297  		return nil, err
  1298  	}
  1299  
  1300  	parsedCertificate, err := x509.ParseCertificate(resp.DER)
  1301  	if err != nil {
  1302  		return nil, wrapError(err, "parsing final certificate")
  1303  	}
  1304  
  1305  	ra.countCertificateIssued(ctx, int64(acctID), identifier.FromCert(parsedCertificate), isRenewal)
  1306  
  1307  	// Asynchronously submit the final certificate to any configured logs
  1308  	go ra.ctpolicy.SubmitFinalCert(resp.DER, parsedCertificate.NotAfter)
  1309  
  1310  	err = ra.matchesCSR(parsedCertificate, csr)
  1311  	if err != nil {
  1312  		ra.certCSRMismatch.Inc()
  1313  		return nil, err
  1314  	}
  1315  
  1316  	_, err = ra.SA.FinalizeOrder(ctx, &sapb.FinalizeOrderRequest{
  1317  		Id:                int64(oID),
  1318  		CertificateSerial: core.SerialToString(parsedCertificate.SerialNumber),
  1319  	})
  1320  	if err != nil {
  1321  		return nil, wrapError(err, "persisting finalized order")
  1322  	}
  1323  
  1324  	return parsedCertificate, nil
  1325  }
  1326  
  1327  func (ra *RegistrationAuthorityImpl) getSCTs(ctx context.Context, precertDER []byte) (core.SCTDERs, error) {
  1328  	started := ra.clk.Now()
  1329  	precert, err := x509.ParseCertificate(precertDER)
  1330  	if err != nil {
  1331  		return nil, fmt.Errorf("parsing precertificate: %w", err)
  1332  	}
  1333  
  1334  	scts, err := ra.ctpolicy.GetSCTs(ctx, precertDER, precert.NotAfter)
  1335  	took := ra.clk.Since(started)
  1336  	if err != nil {
  1337  		state := "failure"
  1338  		if err == context.DeadlineExceeded {
  1339  			state = "deadlineExceeded"
  1340  			// Convert the error to a missingSCTsError to communicate the timeout,
  1341  			// otherwise it will be a generic serverInternalError
  1342  			err = berrors.MissingSCTsError("failed to get SCTs: %s", err.Error())
  1343  		}
  1344  		ra.log.Warningf("ctpolicy.GetSCTs failed: %s", err)
  1345  		ra.ctpolicyResults.With(prometheus.Labels{"result": state}).Observe(took.Seconds())
  1346  		return nil, err
  1347  	}
  1348  	ra.ctpolicyResults.With(prometheus.Labels{"result": "success"}).Observe(took.Seconds())
  1349  	return scts, nil
  1350  }
  1351  
  1352  // UpdateRegistrationKey updates an existing Registration's key.
  1353  func (ra *RegistrationAuthorityImpl) UpdateRegistrationKey(ctx context.Context, req *rapb.UpdateRegistrationKeyRequest) (*corepb.Registration, error) {
  1354  	if core.IsAnyNilOrZero(req.RegistrationID, req.Jwk) {
  1355  		return nil, errIncompleteGRPCRequest
  1356  	}
  1357  
  1358  	update, err := ra.SA.UpdateRegistrationKey(ctx, &sapb.UpdateRegistrationKeyRequest{
  1359  		RegistrationID: req.RegistrationID,
  1360  		Jwk:            req.Jwk,
  1361  	})
  1362  	if err != nil {
  1363  		return nil, fmt.Errorf("failed to update registration key: %w", err)
  1364  	}
  1365  
  1366  	return update, nil
  1367  }
  1368  
  1369  // recordValidation records an authorization validation event,
  1370  // it should only be used on v2 style authorizations.
  1371  func (ra *RegistrationAuthorityImpl) recordValidation(ctx context.Context, authID string, authExpires time.Time, challenge *core.Challenge) error {
  1372  	authzID, err := strconv.ParseInt(authID, 10, 64)
  1373  	if err != nil {
  1374  		return err
  1375  	}
  1376  	vr, err := bgrpc.ValidationResultToPB(challenge.ValidationRecord, challenge.Error, "", "")
  1377  	if err != nil {
  1378  		return err
  1379  	}
  1380  	var validated *timestamppb.Timestamp
  1381  	if challenge.Validated != nil {
  1382  		validated = timestamppb.New(*challenge.Validated)
  1383  	}
  1384  	_, err = ra.SA.FinalizeAuthorization2(ctx, &sapb.FinalizeAuthorizationRequest{
  1385  		Id:                authzID,
  1386  		Status:            string(challenge.Status),
  1387  		Expires:           timestamppb.New(authExpires),
  1388  		Attempted:         string(challenge.Type),
  1389  		AttemptedAt:       validated,
  1390  		ValidationRecords: vr.Records,
  1391  		ValidationError:   vr.Problem,
  1392  	})
  1393  	return err
  1394  }
  1395  
  1396  // countFailedValidations increments the FailedAuthorizationsPerDomainPerAccount limit.
  1397  // and the FailedAuthorizationsForPausingPerDomainPerAccountTransaction limit.
  1398  func (ra *RegistrationAuthorityImpl) countFailedValidations(ctx context.Context, regId int64, ident identifier.ACMEIdentifier) error {
  1399  	txn, err := ra.txnBuilder.FailedAuthorizationsPerDomainPerAccountSpendOnlyTransaction(regId, ident)
  1400  	if err != nil {
  1401  		return fmt.Errorf("building rate limit transaction for the %s rate limit: %w", ratelimits.FailedAuthorizationsPerDomainPerAccount, err)
  1402  	}
  1403  
  1404  	_, err = ra.limiter.Spend(ctx, txn)
  1405  	if err != nil {
  1406  		return fmt.Errorf("spending against the %s rate limit: %w", ratelimits.FailedAuthorizationsPerDomainPerAccount, err)
  1407  	}
  1408  
  1409  	if features.Get().AutomaticallyPauseZombieClients {
  1410  		txn, err = ra.txnBuilder.FailedAuthorizationsForPausingPerDomainPerAccountTransaction(regId, ident)
  1411  		if err != nil {
  1412  			return fmt.Errorf("building rate limit transaction for the %s rate limit: %w", ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount, err)
  1413  		}
  1414  
  1415  		decision, err := ra.limiter.Spend(ctx, txn)
  1416  		if err != nil {
  1417  			return fmt.Errorf("spending against the %s rate limit: %s", ratelimits.FailedAuthorizationsForPausingPerDomainPerAccount, err)
  1418  		}
  1419  
  1420  		if decision.Result(ra.clk.Now()) != nil {
  1421  			resp, err := ra.SA.PauseIdentifiers(ctx, &sapb.PauseRequest{
  1422  				RegistrationID: regId,
  1423  				Identifiers:    []*corepb.Identifier{ident.ToProto()},
  1424  			})
  1425  			if err != nil {
  1426  				return fmt.Errorf("failed to pause %d/%q: %w", regId, ident.Value, err)
  1427  			}
  1428  			ra.pauseCounter.With(prometheus.Labels{
  1429  				"paused":   strconv.FormatBool(resp.Paused > 0),
  1430  				"repaused": strconv.FormatBool(resp.Repaused > 0),
  1431  				"grace":    strconv.FormatBool(resp.Paused <= 0 && resp.Repaused <= 0),
  1432  			}).Inc()
  1433  		}
  1434  	}
  1435  	return nil
  1436  }
  1437  
  1438  // resetAccountPausingLimit resets bucket to maximum capacity for given account.
  1439  // There is no reason to surface errors from this function to the Subscriber.
  1440  func (ra *RegistrationAuthorityImpl) resetAccountPausingLimit(ctx context.Context, regId int64, ident identifier.ACMEIdentifier) {
  1441  	txns, err := ra.txnBuilder.NewPausingResetTransactions(regId, ident)
  1442  	if err != nil {
  1443  		ra.log.Warningf("building reset transaction for regID=[%d] identifier=[%s]: %s", regId, ident.Value, err)
  1444  		return
  1445  	}
  1446  
  1447  	err = ra.limiter.BatchReset(ctx, txns)
  1448  	if err != nil {
  1449  		ra.log.Warningf("resetting bucket for regID=[%d] identifier=[%s]: %s", regId, ident.Value, err)
  1450  	}
  1451  }
  1452  
  1453  // doDCVAndCAA performs DCV and CAA checks sequentially: DCV is performed first
  1454  // and CAA is only checked if DCV is successful. Validation records from the DCV
  1455  // check are returned even if the CAA check fails.
  1456  func (ra *RegistrationAuthorityImpl) checkDCVAndCAA(ctx context.Context, dcvReq *vapb.PerformValidationRequest, caaReq *vapb.IsCAAValidRequest) (*corepb.ProblemDetails, []*corepb.ValidationRecord, error) {
  1457  	doDCVRes, err := ra.VA.DoDCV(ctx, dcvReq)
  1458  	if err != nil {
  1459  		return nil, nil, err
  1460  	}
  1461  	if doDCVRes.Problem != nil {
  1462  		return doDCVRes.Problem, doDCVRes.Records, nil
  1463  	}
  1464  
  1465  	switch identifier.FromProto(dcvReq.Identifier).Type {
  1466  	case identifier.TypeDNS:
  1467  		doCAAResp, err := ra.VA.DoCAA(ctx, caaReq)
  1468  		if err != nil {
  1469  			return nil, nil, err
  1470  		}
  1471  		return doCAAResp.Problem, doDCVRes.Records, nil
  1472  	case identifier.TypeIP:
  1473  		return nil, doDCVRes.Records, nil
  1474  	default:
  1475  		return nil, nil, berrors.MalformedError("invalid identifier type: %s", dcvReq.Identifier.Type)
  1476  	}
  1477  }
  1478  
  1479  // PerformValidation initiates validation for a specific challenge associated
  1480  // with the given base authorization. The authorization and challenge are
  1481  // updated based on the results.
  1482  func (ra *RegistrationAuthorityImpl) PerformValidation(
  1483  	ctx context.Context,
  1484  	req *rapb.PerformValidationRequest) (*corepb.Authorization, error) {
  1485  	// Clock for start of PerformValidation.
  1486  	vStart := ra.clk.Now()
  1487  
  1488  	if core.IsAnyNilOrZero(req.Authz, req.Authz.Id, req.Authz.Identifier, req.Authz.Status, req.Authz.Expires) {
  1489  		return nil, errIncompleteGRPCRequest
  1490  	}
  1491  
  1492  	authz, err := bgrpc.PBToAuthz(req.Authz)
  1493  	if err != nil {
  1494  		return nil, err
  1495  	}
  1496  
  1497  	// Refuse to update expired authorizations
  1498  	if authz.Expires == nil || authz.Expires.Before(ra.clk.Now()) {
  1499  		return nil, berrors.MalformedError("expired authorization")
  1500  	}
  1501  
  1502  	profile, err := ra.profiles.get(authz.CertificateProfileName)
  1503  	if err != nil {
  1504  		return nil, err
  1505  	}
  1506  
  1507  	challIndex := int(req.ChallengeIndex)
  1508  	if challIndex >= len(authz.Challenges) {
  1509  		return nil,
  1510  			berrors.MalformedError("invalid challenge index '%d'", challIndex)
  1511  	}
  1512  
  1513  	ch := &authz.Challenges[challIndex]
  1514  
  1515  	// This challenge type may have been disabled since the challenge was created.
  1516  	if !ra.PA.ChallengeTypeEnabled(ch.Type) {
  1517  		return nil, berrors.MalformedError("challenge type %q no longer allowed", ch.Type)
  1518  	}
  1519  
  1520  	// We expect some clients to try and update a challenge for an authorization
  1521  	// that is already valid. In this case we don't need to process the
  1522  	// challenge update. It wouldn't be helpful, the overall authorization is
  1523  	// already good! We return early for the valid authz reuse case.
  1524  	if authz.Status == core.StatusValid {
  1525  		return req.Authz, nil
  1526  	}
  1527  
  1528  	if authz.Status != core.StatusPending {
  1529  		return nil, berrors.MalformedError("authorization must be pending")
  1530  	}
  1531  
  1532  	// Look up the account key for this authorization
  1533  	regPB, err := ra.SA.GetRegistration(ctx, &sapb.RegistrationID{Id: authz.RegistrationID})
  1534  	if err != nil {
  1535  		return nil, berrors.InternalServerError("getting acct for authorization: %s", err.Error())
  1536  	}
  1537  	reg, err := bgrpc.PbToRegistration(regPB)
  1538  	if err != nil {
  1539  		return nil, berrors.InternalServerError("getting acct for authorization: %s", err.Error())
  1540  	}
  1541  
  1542  	// Compute the key authorization field based on the registration key
  1543  	expectedKeyAuthorization, err := ch.ExpectedKeyAuthorization(reg.Key)
  1544  	if err != nil {
  1545  		return nil, berrors.InternalServerError("could not compute expected key authorization value")
  1546  	}
  1547  
  1548  	// Double check before sending to VA
  1549  	if cErr := ch.CheckPending(); cErr != nil {
  1550  		return nil, berrors.MalformedError("cannot validate challenge: %s", cErr.Error())
  1551  	}
  1552  
  1553  	// Dispatch to the VA for service
  1554  	ra.drainWG.Add(1)
  1555  	vaCtx := context.Background()
  1556  	go func(authz core.Authorization) {
  1557  		defer ra.drainWG.Done()
  1558  
  1559  		// We will mutate challenges later in this goroutine to change status and
  1560  		// add error, but we also return a copy of authz immediately. To avoid a
  1561  		// data race, make a copy of the challenges slice here for mutation.
  1562  		challenges := make([]core.Challenge, len(authz.Challenges))
  1563  		copy(challenges, authz.Challenges)
  1564  		authz.Challenges = challenges
  1565  		chall, _ := bgrpc.ChallengeToPB(authz.Challenges[challIndex])
  1566  		checkProb, checkRecords, err := ra.checkDCVAndCAA(
  1567  			vaCtx,
  1568  			&vapb.PerformValidationRequest{
  1569  				Identifier:               authz.Identifier.ToProto(),
  1570  				Challenge:                chall,
  1571  				Authz:                    &vapb.AuthzMeta{Id: authz.ID, RegID: authz.RegistrationID},
  1572  				ExpectedKeyAuthorization: expectedKeyAuthorization,
  1573  			},
  1574  			&vapb.IsCAAValidRequest{
  1575  				Identifier:       authz.Identifier.ToProto(),
  1576  				ValidationMethod: chall.Type,
  1577  				AccountURIID:     authz.RegistrationID,
  1578  				AuthzID:          authz.ID,
  1579  			},
  1580  		)
  1581  		challenge := &authz.Challenges[challIndex]
  1582  		var prob *probs.ProblemDetails
  1583  		if err != nil {
  1584  			prob = probs.ServerInternal("Could not communicate with VA")
  1585  			ra.log.AuditErrf("Could not communicate with VA: %s", err)
  1586  		} else {
  1587  			if checkProb != nil {
  1588  				prob, err = bgrpc.PBToProblemDetails(checkProb)
  1589  				if err != nil {
  1590  					prob = probs.ServerInternal("Could not communicate with VA")
  1591  					ra.log.AuditErrf("Could not communicate with VA: %s", err)
  1592  				}
  1593  			}
  1594  			// Save the updated records
  1595  			records := make([]core.ValidationRecord, len(checkRecords))
  1596  			for i, r := range checkRecords {
  1597  				records[i], err = bgrpc.PBToValidationRecord(r)
  1598  				if err != nil {
  1599  					prob = probs.ServerInternal("Records for validation corrupt")
  1600  				}
  1601  			}
  1602  			challenge.ValidationRecord = records
  1603  		}
  1604  		if !challenge.RecordsSane() && prob == nil {
  1605  			prob = probs.ServerInternal("Records for validation failed sanity check")
  1606  		}
  1607  
  1608  		expires := *authz.Expires
  1609  		if prob != nil {
  1610  			challenge.Status = core.StatusInvalid
  1611  			challenge.Error = prob
  1612  			err := ra.countFailedValidations(vaCtx, authz.RegistrationID, authz.Identifier)
  1613  			if err != nil {
  1614  				ra.log.Warningf("incrementing failed validations: %s", err)
  1615  			}
  1616  		} else {
  1617  			challenge.Status = core.StatusValid
  1618  			expires = ra.clk.Now().Add(profile.validAuthzLifetime)
  1619  			if features.Get().AutomaticallyPauseZombieClients {
  1620  				ra.resetAccountPausingLimit(vaCtx, authz.RegistrationID, authz.Identifier)
  1621  			}
  1622  		}
  1623  		challenge.Validated = &vStart
  1624  		authz.Challenges[challIndex] = *challenge
  1625  
  1626  		err = ra.recordValidation(vaCtx, authz.ID, expires, challenge)
  1627  		if err != nil {
  1628  			if errors.Is(err, berrors.NotFound) {
  1629  				// We log NotFound at a lower level because this is largely due to a
  1630  				// parallel-validation race: a different validation attempt has already
  1631  				// updated this authz, so we failed to find a *pending* authz with the
  1632  				// given ID to update.
  1633  				ra.log.Infof("Failed to record validation (likely parallel validation race): regID=[%d] authzID=[%s] err=[%s]",
  1634  					authz.RegistrationID, authz.ID, err)
  1635  			} else {
  1636  				ra.log.AuditErrf("Failed to record validation: regID=[%d] authzID=[%s] err=[%s]",
  1637  					authz.RegistrationID, authz.ID, err)
  1638  			}
  1639  		}
  1640  	}(authz)
  1641  	return bgrpc.AuthzToPB(authz)
  1642  }
  1643  
  1644  // revokeCertificate updates the database to mark the certificate as revoked,
  1645  // with the given reason and current timestamp.
  1646  func (ra *RegistrationAuthorityImpl) revokeCertificate(ctx context.Context, cert *x509.Certificate, reason revocation.Reason) error {
  1647  	serialString := core.SerialToString(cert.SerialNumber)
  1648  	issuerID := issuance.IssuerNameID(cert)
  1649  	shardIdx, err := crlShard(cert)
  1650  	if err != nil {
  1651  		return err
  1652  	}
  1653  
  1654  	_, err = ra.SA.RevokeCertificate(ctx, &sapb.RevokeCertificateRequest{
  1655  		Serial:   serialString,
  1656  		Reason:   int64(reason),
  1657  		Date:     timestamppb.New(ra.clk.Now()),
  1658  		IssuerID: int64(issuerID),
  1659  		ShardIdx: shardIdx,
  1660  	})
  1661  	if err != nil {
  1662  		return err
  1663  	}
  1664  
  1665  	ra.revocationReasonCounter.WithLabelValues(reason.String()).Inc()
  1666  	return nil
  1667  }
  1668  
  1669  // updateRevocationForKeyCompromise updates the database to mark the certificate
  1670  // as revoked, with the given reason and current timestamp. This only works for
  1671  // certificates that were previously revoked for a reason other than
  1672  // keyCompromise, and which are now being updated to keyCompromise instead.
  1673  func (ra *RegistrationAuthorityImpl) updateRevocationForKeyCompromise(ctx context.Context, serialString string, issuerID issuance.NameID) error {
  1674  	status, err := ra.SA.GetCertificateStatus(ctx, &sapb.Serial{Serial: serialString})
  1675  	if err != nil {
  1676  		return berrors.NotFoundError("unable to confirm that serial %q was ever issued: %s", serialString, err)
  1677  	}
  1678  
  1679  	if status.Status != string(core.OCSPStatusRevoked) {
  1680  		// Internal server error, because we shouldn't be in the function at all
  1681  		// unless the cert was already revoked.
  1682  		return fmt.Errorf("unable to re-revoke serial %q which is not currently revoked", serialString)
  1683  	}
  1684  	if revocation.Reason(status.RevokedReason) == revocation.KeyCompromise {
  1685  		return berrors.AlreadyRevokedError("unable to re-revoke serial %q which is already revoked for keyCompromise", serialString)
  1686  	}
  1687  
  1688  	cert, err := ra.SA.GetCertificate(ctx, &sapb.Serial{Serial: serialString})
  1689  	if err != nil {
  1690  		return berrors.NotFoundError("unable to confirm that serial %q was ever issued: %s", serialString, err)
  1691  	}
  1692  	x509Cert, err := x509.ParseCertificate(cert.Der)
  1693  	if err != nil {
  1694  		return err
  1695  	}
  1696  
  1697  	shardIdx, err := crlShard(x509Cert)
  1698  	if err != nil {
  1699  		return err
  1700  	}
  1701  
  1702  	_, err = ra.SA.UpdateRevokedCertificate(ctx, &sapb.RevokeCertificateRequest{
  1703  		Serial:   serialString,
  1704  		Reason:   int64(revocation.KeyCompromise),
  1705  		Date:     timestamppb.New(ra.clk.Now()),
  1706  		Backdate: status.RevokedDate,
  1707  		IssuerID: int64(issuerID),
  1708  		ShardIdx: shardIdx,
  1709  	})
  1710  	if err != nil {
  1711  		return err
  1712  	}
  1713  
  1714  	ra.revocationReasonCounter.WithLabelValues(revocation.KeyCompromise.String()).Inc()
  1715  	return nil
  1716  }
  1717  
  1718  // RevokeCertByApplicant revokes the certificate in question. It allows any
  1719  // revocation reason from (0, 1, 3, 4, 5, 9), because Subscribers are allowed to
  1720  // request any revocation reason for their own certificates. However, if the
  1721  // requesting RegID is an account which has authorizations for all names in the
  1722  // cert but is *not* the original subscriber, it overrides the revocation reason
  1723  // to be 5 (cessationOfOperation), because that code is used to cover instances
  1724  // where "the certificate subscriber no longer owns the domain names in the
  1725  // certificate". It does not add the key to the blocked keys list, even if
  1726  // reason 1 (keyCompromise) is requested, as it does not demonstrate said
  1727  // compromise.
  1728  func (ra *RegistrationAuthorityImpl) RevokeCertByApplicant(ctx context.Context, req *rapb.RevokeCertByApplicantRequest) (*emptypb.Empty, error) {
  1729  	if req == nil || req.Cert == nil || req.RegID == 0 {
  1730  		return nil, errIncompleteGRPCRequest
  1731  	}
  1732  
  1733  	reasonCode := revocation.Reason(req.Code)
  1734  	if !revocation.UserAllowedReason(reasonCode) {
  1735  		return nil, berrors.BadRevocationReasonError(req.Code)
  1736  	}
  1737  
  1738  	cert, err := x509.ParseCertificate(req.Cert)
  1739  	if err != nil {
  1740  		return nil, err
  1741  	}
  1742  
  1743  	serialString := core.SerialToString(cert.SerialNumber)
  1744  
  1745  	logEvent := certificateRevocationEvent{
  1746  		ID:           core.NewToken(),
  1747  		SerialNumber: serialString,
  1748  		Reason:       reasonCode,
  1749  		Method:       "applicant",
  1750  		RequesterID:  req.RegID,
  1751  	}
  1752  
  1753  	// Below this point, do not re-declare `err` (i.e. type `err :=`) in a
  1754  	// nested scope. Doing so will create a new `err` variable that is not
  1755  	// captured by this closure.
  1756  	defer func() {
  1757  		if err != nil {
  1758  			logEvent.Error = err.Error()
  1759  		}
  1760  		ra.log.AuditObject("Revocation request:", logEvent)
  1761  	}()
  1762  
  1763  	metadata, err := ra.SA.GetSerialMetadata(ctx, &sapb.Serial{Serial: serialString})
  1764  	if err != nil {
  1765  		return nil, err
  1766  	}
  1767  
  1768  	if req.RegID == metadata.RegistrationID {
  1769  		// The requester is the original subscriber. They can revoke for any reason.
  1770  		logEvent.Method = "subscriber"
  1771  	} else {
  1772  		// The requester is a different account. We need to confirm that they have
  1773  		// authorizations for all names in the cert.
  1774  		logEvent.Method = "control"
  1775  
  1776  		idents := identifier.FromCert(cert)
  1777  		var authzPB *sapb.Authorizations
  1778  		authzPB, err = ra.SA.GetValidAuthorizations2(ctx, &sapb.GetValidAuthorizationsRequest{
  1779  			RegistrationID: req.RegID,
  1780  			Identifiers:    idents.ToProtoSlice(),
  1781  			ValidUntil:     timestamppb.New(ra.clk.Now()),
  1782  		})
  1783  		if err != nil {
  1784  			return nil, err
  1785  		}
  1786  
  1787  		var authzMap map[identifier.ACMEIdentifier]*core.Authorization
  1788  		authzMap, err = bgrpc.PBToAuthzMap(authzPB)
  1789  		if err != nil {
  1790  			return nil, err
  1791  		}
  1792  
  1793  		for _, ident := range idents {
  1794  			if _, present := authzMap[ident]; !present {
  1795  				return nil, berrors.UnauthorizedError("requester does not control all identifiers in cert with serial %q", serialString)
  1796  			}
  1797  		}
  1798  
  1799  		// Applicants who are not the original Subscriber are not allowed to
  1800  		// revoke for any reason other than cessationOfOperation, which covers
  1801  		// circumstances where "the certificate subscriber no longer owns the
  1802  		// domain names in the certificate". Override the reason code to match.
  1803  		reasonCode = revocation.CessationOfOperation
  1804  		logEvent.Reason = reasonCode
  1805  	}
  1806  
  1807  	err = ra.revokeCertificate(ctx, cert, reasonCode)
  1808  	if err != nil {
  1809  		return nil, err
  1810  	}
  1811  
  1812  	return &emptypb.Empty{}, nil
  1813  }
  1814  
  1815  // crlShard extracts the CRL shard from a certificate's CRLDistributionPoint.
  1816  //
  1817  // If there is no CRLDistributionPoint, returns 0.
  1818  //
  1819  // If there is more than one CRLDistributionPoint, returns an error.
  1820  //
  1821  // Assumes the shard number is represented in the URL as an integer that
  1822  // occurs in the last path component, optionally followed by ".crl".
  1823  //
  1824  // Note: This assumes (a) the CA is generating well-formed, correct
  1825  // CRLDistributionPoints and (b) an earlier component has verified the signature
  1826  // on this certificate comes from one of our issuers.
  1827  func crlShard(cert *x509.Certificate) (int64, error) {
  1828  	if len(cert.CRLDistributionPoints) == 0 {
  1829  		return 0, errors.New("no crlDistributionPoints in certificate")
  1830  	}
  1831  	if len(cert.CRLDistributionPoints) > 1 {
  1832  		return 0, errors.New("too many crlDistributionPoints in certificate")
  1833  	}
  1834  
  1835  	url := strings.TrimSuffix(cert.CRLDistributionPoints[0], ".crl")
  1836  	lastIndex := strings.LastIndex(url, "/")
  1837  	if lastIndex == -1 {
  1838  		return 0, fmt.Errorf("malformed CRLDistributionPoint %q", url)
  1839  	}
  1840  	shardStr := url[lastIndex+1:]
  1841  	shardIdx, err := strconv.Atoi(shardStr)
  1842  	if err != nil {
  1843  		return 0, fmt.Errorf("parsing CRLDistributionPoint: %s", err)
  1844  	}
  1845  
  1846  	if shardIdx <= 0 {
  1847  		return 0, fmt.Errorf("invalid shard in CRLDistributionPoint: %d", shardIdx)
  1848  	}
  1849  
  1850  	return int64(shardIdx), nil
  1851  }
  1852  
  1853  // addToBlockedKeys initiates a GRPC call to have the Base64-encoded SHA256
  1854  // digest of a provided public key added to the blockedKeys table.
  1855  func (ra *RegistrationAuthorityImpl) addToBlockedKeys(ctx context.Context, key crypto.PublicKey, src string, comment string) error {
  1856  	var digest core.Sha256Digest
  1857  	digest, err := core.KeyDigest(key)
  1858  	if err != nil {
  1859  		return err
  1860  	}
  1861  
  1862  	// Add the public key to the blocked keys list.
  1863  	_, err = ra.SA.AddBlockedKey(ctx, &sapb.AddBlockedKeyRequest{
  1864  		KeyHash: digest[:],
  1865  		Added:   timestamppb.New(ra.clk.Now()),
  1866  		Source:  src,
  1867  		Comment: comment,
  1868  	})
  1869  	if err != nil {
  1870  		return err
  1871  	}
  1872  
  1873  	return nil
  1874  }
  1875  
  1876  // RevokeCertByKey revokes the certificate in question. It always uses
  1877  // reason code 1 (keyCompromise). It ensures that they public key is added to
  1878  // the blocked keys list, even if revocation otherwise fails.
  1879  func (ra *RegistrationAuthorityImpl) RevokeCertByKey(ctx context.Context, req *rapb.RevokeCertByKeyRequest) (*emptypb.Empty, error) {
  1880  	if req == nil || req.Cert == nil {
  1881  		return nil, errIncompleteGRPCRequest
  1882  	}
  1883  
  1884  	cert, err := x509.ParseCertificate(req.Cert)
  1885  	if err != nil {
  1886  		return nil, err
  1887  	}
  1888  
  1889  	logEvent := certificateRevocationEvent{
  1890  		ID:           core.NewToken(),
  1891  		SerialNumber: core.SerialToString(cert.SerialNumber),
  1892  		Reason:       revocation.KeyCompromise,
  1893  		Method:       "key",
  1894  		RequesterID:  0,
  1895  	}
  1896  
  1897  	// Below this point, do not re-declare `err` (i.e. type `err :=`) in a
  1898  	// nested scope. Doing so will create a new `err` variable that is not
  1899  	// captured by this closure.
  1900  	defer func() {
  1901  		if err != nil {
  1902  			logEvent.Error = err.Error()
  1903  		}
  1904  		ra.log.AuditObject("Revocation request:", logEvent)
  1905  	}()
  1906  
  1907  	// We revoke the cert before adding it to the blocked keys list, to avoid a
  1908  	// race between this and the bad-key-revoker. But we don't check the error
  1909  	// from this operation until after we add the key to the blocked keys list,
  1910  	// since that addition needs to happen no matter what.
  1911  	revokeErr := ra.revokeCertificate(
  1912  		ctx,
  1913  		cert,
  1914  		revocation.KeyCompromise,
  1915  	)
  1916  
  1917  	// Failing to add the key to the blocked keys list is a worse failure than
  1918  	// failing to revoke in the first place, because it means that
  1919  	// bad-key-revoker won't revoke the cert anyway.
  1920  	err = ra.addToBlockedKeys(ctx, cert.PublicKey, "API", "")
  1921  	if err != nil {
  1922  		return nil, err
  1923  	}
  1924  
  1925  	issuerID := issuance.IssuerNameID(cert)
  1926  
  1927  	// Check the error returned from revokeCertificate itself.
  1928  	err = revokeErr
  1929  	if errors.Is(err, berrors.AlreadyRevoked) {
  1930  		// If it was an AlreadyRevoked error, try to re-revoke the cert in case
  1931  		// it was revoked for a reason other than keyCompromise.
  1932  		err = ra.updateRevocationForKeyCompromise(ctx, core.SerialToString(cert.SerialNumber), issuerID)
  1933  		if err != nil {
  1934  			return nil, err
  1935  		}
  1936  		return &emptypb.Empty{}, nil
  1937  	} else if err != nil {
  1938  		// Error out if the error was anything other than AlreadyRevoked.
  1939  		return nil, err
  1940  	}
  1941  
  1942  	return &emptypb.Empty{}, nil
  1943  }
  1944  
  1945  // AdministrativelyRevokeCertificate terminates trust in the certificate
  1946  // provided and does not require the registration ID of the requester since this
  1947  // method is only called from the `admin` tool. It trusts that the admin
  1948  // is doing the right thing, so if the requested reason is keyCompromise, it
  1949  // blocks the key from future issuance even though compromise has not been
  1950  // demonstrated here.
  1951  func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx context.Context, req *rapb.AdministrativelyRevokeCertificateRequest) (*emptypb.Empty, error) {
  1952  	if req == nil || req.AdminName == "" {
  1953  		return nil, errIncompleteGRPCRequest
  1954  	}
  1955  	if req.Serial == "" {
  1956  		return nil, errIncompleteGRPCRequest
  1957  	}
  1958  	if req.CrlShard != 0 && !req.Malformed {
  1959  		return nil, errors.New("non-zero CRLShard is only allowed for malformed certificates (shard is automatic for well formed certificates)")
  1960  	}
  1961  	if req.Malformed && req.CrlShard == 0 {
  1962  		return nil, errors.New("CRLShard is required for malformed certificates")
  1963  	}
  1964  
  1965  	reasonCode := revocation.Reason(req.Code)
  1966  	if !revocation.AdminAllowedReason(reasonCode) {
  1967  		return nil, fmt.Errorf("cannot revoke for reason %d", reasonCode)
  1968  	}
  1969  	if req.SkipBlockKey && reasonCode != revocation.KeyCompromise {
  1970  		return nil, fmt.Errorf("cannot skip key blocking for reasons other than KeyCompromise")
  1971  	}
  1972  	if reasonCode == revocation.KeyCompromise && req.Malformed {
  1973  		return nil, fmt.Errorf("cannot revoke malformed certificate for KeyCompromise")
  1974  	}
  1975  
  1976  	logEvent := certificateRevocationEvent{
  1977  		ID:           core.NewToken(),
  1978  		SerialNumber: req.Serial,
  1979  		Reason:       reasonCode,
  1980  		CRLShard:     req.CrlShard,
  1981  		Method:       "admin",
  1982  		AdminName:    req.AdminName,
  1983  	}
  1984  
  1985  	// Below this point, do not re-declare `err` (i.e. type `err :=`) in a
  1986  	// nested scope. Doing so will create a new `err` variable that is not
  1987  	// captured by this closure.
  1988  	var err error
  1989  	defer func() {
  1990  		if err != nil {
  1991  			logEvent.Error = err.Error()
  1992  		}
  1993  		ra.log.AuditObject("Revocation request:", logEvent)
  1994  	}()
  1995  
  1996  	var cert *x509.Certificate
  1997  	var issuerID issuance.NameID
  1998  	var shard int64
  1999  	if req.Cert != nil {
  2000  		// If the incoming request includes a certificate body, just use that and
  2001  		// avoid doing any database queries. This code path is deprecated and will
  2002  		// be removed when req.Cert is removed.
  2003  		cert, err = x509.ParseCertificate(req.Cert)
  2004  		if err != nil {
  2005  			return nil, err
  2006  		}
  2007  		issuerID = issuance.IssuerNameID(cert)
  2008  		shard, err = crlShard(cert)
  2009  		if err != nil {
  2010  			return nil, err
  2011  		}
  2012  	} else if !req.Malformed {
  2013  		// As long as we don't believe the cert will be malformed, we should
  2014  		// get the precertificate so we can block its pubkey if necessary.
  2015  		var certPB *corepb.Certificate
  2016  		certPB, err = ra.SA.GetLintPrecertificate(ctx, &sapb.Serial{Serial: req.Serial})
  2017  		if err != nil {
  2018  			return nil, err
  2019  		}
  2020  		// Note that, although the thing we're parsing here is actually a linting
  2021  		// precertificate, it has identical issuer info (and therefore an identical
  2022  		// issuer NameID) to the real thing.
  2023  		cert, err = x509.ParseCertificate(certPB.Der)
  2024  		if err != nil {
  2025  			return nil, err
  2026  		}
  2027  		issuerID = issuance.IssuerNameID(cert)
  2028  		shard, err = crlShard(cert)
  2029  		if err != nil {
  2030  			return nil, err
  2031  		}
  2032  	} else {
  2033  		// But if the cert is malformed, we at least still need its IssuerID.
  2034  		var status *corepb.CertificateStatus
  2035  		status, err = ra.SA.GetCertificateStatus(ctx, &sapb.Serial{Serial: req.Serial})
  2036  		if err != nil {
  2037  			return nil, fmt.Errorf("unable to confirm that serial %q was ever issued: %w", req.Serial, err)
  2038  		}
  2039  		issuerID = issuance.NameID(status.IssuerID)
  2040  		shard = req.CrlShard
  2041  	}
  2042  
  2043  	_, err = ra.SA.RevokeCertificate(ctx, &sapb.RevokeCertificateRequest{
  2044  		Serial:   req.Serial,
  2045  		Reason:   int64(reasonCode),
  2046  		Date:     timestamppb.New(ra.clk.Now()),
  2047  		IssuerID: int64(issuerID),
  2048  		ShardIdx: shard,
  2049  	})
  2050  	if err != nil {
  2051  		if reasonCode == revocation.KeyCompromise && errors.Is(err, berrors.AlreadyRevoked) {
  2052  			err = ra.updateRevocationForKeyCompromise(ctx, req.Serial, issuerID)
  2053  			if err != nil {
  2054  				return nil, err
  2055  			}
  2056  		}
  2057  		return nil, err
  2058  	}
  2059  
  2060  	if reasonCode == revocation.KeyCompromise && !req.SkipBlockKey {
  2061  		if cert == nil {
  2062  			return nil, errors.New("revoking for key compromise requires providing the certificate's DER")
  2063  		}
  2064  		err = ra.addToBlockedKeys(ctx, cert.PublicKey, "admin-revoker", fmt.Sprintf("revoked by %s", req.AdminName))
  2065  		if err != nil {
  2066  			return nil, err
  2067  		}
  2068  	}
  2069  
  2070  	return &emptypb.Empty{}, nil
  2071  }
  2072  
  2073  // DeactivateRegistration deactivates a valid registration
  2074  func (ra *RegistrationAuthorityImpl) DeactivateRegistration(ctx context.Context, req *rapb.DeactivateRegistrationRequest) (*corepb.Registration, error) {
  2075  	if req == nil || req.RegistrationID == 0 {
  2076  		return nil, errIncompleteGRPCRequest
  2077  	}
  2078  
  2079  	updatedAcct, err := ra.SA.DeactivateRegistration(ctx, &sapb.RegistrationID{Id: req.RegistrationID})
  2080  	if err != nil {
  2081  		return nil, err
  2082  	}
  2083  
  2084  	return updatedAcct, nil
  2085  }
  2086  
  2087  // DeactivateAuthorization deactivates a currently valid authorization
  2088  func (ra *RegistrationAuthorityImpl) DeactivateAuthorization(ctx context.Context, req *corepb.Authorization) (*emptypb.Empty, error) {
  2089  	ident := identifier.FromProto(req.Identifier)
  2090  
  2091  	if core.IsAnyNilOrZero(req, req.Id, ident, req.Status, req.RegistrationID) {
  2092  		return nil, errIncompleteGRPCRequest
  2093  	}
  2094  	authzID, err := strconv.ParseInt(req.Id, 10, 64)
  2095  	if err != nil {
  2096  		return nil, err
  2097  	}
  2098  	if _, err := ra.SA.DeactivateAuthorization2(ctx, &sapb.AuthorizationID2{Id: authzID}); err != nil {
  2099  		return nil, err
  2100  	}
  2101  	if req.Status == string(core.StatusPending) {
  2102  		// Some clients deactivate pending authorizations without attempting them.
  2103  		// We're not sure exactly when this happens but it's most likely due to
  2104  		// internal errors in the client. From our perspective this uses storage
  2105  		// resources similar to how failed authorizations do, so we increment the
  2106  		// failed authorizations limit.
  2107  		err = ra.countFailedValidations(ctx, req.RegistrationID, ident)
  2108  		if err != nil {
  2109  			return nil, fmt.Errorf("failed to update rate limits: %w", err)
  2110  		}
  2111  	}
  2112  	return &emptypb.Empty{}, nil
  2113  }
  2114  
  2115  // NewOrder creates a new order object
  2116  func (ra *RegistrationAuthorityImpl) NewOrder(ctx context.Context, req *rapb.NewOrderRequest) (*corepb.Order, error) {
  2117  	if req == nil || req.RegistrationID == 0 {
  2118  		return nil, errIncompleteGRPCRequest
  2119  	}
  2120  
  2121  	idents := identifier.Normalize(identifier.FromProtoSlice(req.Identifiers))
  2122  
  2123  	profile, err := ra.profiles.get(req.CertificateProfileName)
  2124  	if err != nil {
  2125  		return nil, err
  2126  	}
  2127  
  2128  	if profile.allowList != nil && !profile.allowList.Contains(req.RegistrationID) {
  2129  		return nil, berrors.UnauthorizedError("account ID %d is not permitted to use certificate profile %q",
  2130  			req.RegistrationID,
  2131  			req.CertificateProfileName,
  2132  		)
  2133  	}
  2134  
  2135  	if len(idents) > profile.maxNames {
  2136  		return nil, berrors.MalformedError(
  2137  			"Order cannot contain more than %d identifiers", profile.maxNames)
  2138  	}
  2139  
  2140  	for _, ident := range idents {
  2141  		if !slices.Contains(profile.identifierTypes, ident.Type) {
  2142  			return nil, berrors.RejectedIdentifierError("Profile %q does not permit %s type identifiers", req.CertificateProfileName, ident.Type)
  2143  		}
  2144  	}
  2145  
  2146  	// Validate that our policy allows issuing for each of the identifiers in
  2147  	// the order
  2148  	err = ra.PA.WillingToIssue(idents)
  2149  	if err != nil {
  2150  		return nil, err
  2151  	}
  2152  
  2153  	err = wildcardOverlap(idents)
  2154  	if err != nil {
  2155  		return nil, err
  2156  	}
  2157  
  2158  	// See if there is an existing unexpired pending (or ready) order that can be reused
  2159  	// for this account
  2160  	existingOrder, err := ra.SA.GetOrderForNames(ctx, &sapb.GetOrderForNamesRequest{
  2161  		AcctID:      req.RegistrationID,
  2162  		Identifiers: idents.ToProtoSlice(),
  2163  	})
  2164  	// If there was an error and it wasn't an acceptable "NotFound" error, return
  2165  	// immediately
  2166  	if err != nil && !errors.Is(err, berrors.NotFound) {
  2167  		return nil, err
  2168  	}
  2169  
  2170  	// If there was an order, make sure it has expected fields and return it
  2171  	// Error if an incomplete order is returned.
  2172  	if existingOrder != nil {
  2173  		// Check to see if the expected fields of the existing order are set.
  2174  		if core.IsAnyNilOrZero(existingOrder.Id, existingOrder.Status, existingOrder.RegistrationID, existingOrder.Identifiers, existingOrder.Created, existingOrder.Expires) {
  2175  			return nil, errIncompleteGRPCResponse
  2176  		}
  2177  
  2178  		// Only re-use the order if the profile (even if it is just the empty
  2179  		// string, leaving us to choose a default profile) matches.
  2180  		if existingOrder.CertificateProfileName == req.CertificateProfileName {
  2181  			// Track how often we reuse an existing order and how old that order is.
  2182  			ra.orderAges.WithLabelValues("NewOrder").Observe(ra.clk.Since(existingOrder.Created.AsTime()).Seconds())
  2183  			return existingOrder, nil
  2184  		}
  2185  	}
  2186  
  2187  	// An order's lifetime is effectively bound by the shortest remaining lifetime
  2188  	// of its associated authorizations. For that reason it would be Uncool if
  2189  	// `sa.GetAuthorizations` returned an authorization that was very close to
  2190  	// expiry. The resulting pending order that references it would itself end up
  2191  	// expiring very soon.
  2192  	// What is considered "very soon" scales with the associated order's lifetime,
  2193  	// up to a point.
  2194  	minTimeToExpiry := profile.orderLifetime / 8
  2195  	if minTimeToExpiry < time.Hour {
  2196  		minTimeToExpiry = time.Hour
  2197  	} else if minTimeToExpiry > 24*time.Hour {
  2198  		minTimeToExpiry = 24 * time.Hour
  2199  	}
  2200  	authzExpiryCutoff := ra.clk.Now().Add(minTimeToExpiry)
  2201  
  2202  	existingAuthz, err := ra.SA.GetValidAuthorizations2(ctx, &sapb.GetValidAuthorizationsRequest{
  2203  		RegistrationID: req.RegistrationID,
  2204  		ValidUntil:     timestamppb.New(authzExpiryCutoff),
  2205  		Identifiers:    idents.ToProtoSlice(),
  2206  		Profile:        req.CertificateProfileName,
  2207  	})
  2208  	if err != nil {
  2209  		return nil, err
  2210  	}
  2211  
  2212  	identToExistingAuthz, err := bgrpc.PBToAuthzMap(existingAuthz)
  2213  	if err != nil {
  2214  		return nil, err
  2215  	}
  2216  
  2217  	// For each of the identifiers in the order, if there is an acceptable
  2218  	// existing authz, append it to the order to reuse it. Otherwise track that
  2219  	// there is a missing authz for that identifier.
  2220  	var newOrderAuthzs []int64
  2221  	var missingAuthzIdents identifier.ACMEIdentifiers
  2222  	for _, ident := range idents {
  2223  		// If there isn't an existing authz, note that its missing and continue
  2224  		authz, exists := identToExistingAuthz[ident]
  2225  		if !exists {
  2226  			// The existing authz was not acceptable for reuse, and we need to
  2227  			// mark the name as requiring a new pending authz.
  2228  			missingAuthzIdents = append(missingAuthzIdents, ident)
  2229  			continue
  2230  		}
  2231  
  2232  		// If the authz is associated with the wrong profile, don't reuse it.
  2233  		if authz.CertificateProfileName != req.CertificateProfileName {
  2234  			missingAuthzIdents = append(missingAuthzIdents, ident)
  2235  			// Delete the authz from the identToExistingAuthz map since we are not reusing it.
  2236  			delete(identToExistingAuthz, ident)
  2237  			continue
  2238  		}
  2239  
  2240  		// This is only used for our metrics.
  2241  		authzAge := (profile.validAuthzLifetime - authz.Expires.Sub(ra.clk.Now())).Seconds()
  2242  		if authz.Status == core.StatusPending {
  2243  			authzAge = (profile.pendingAuthzLifetime - authz.Expires.Sub(ra.clk.Now())).Seconds()
  2244  		}
  2245  
  2246  		// If the identifier is a wildcard DNS name, it must have exactly one
  2247  		// DNS-01 type challenge. The PA guarantees this at order creation time,
  2248  		// but we verify again to be safe.
  2249  		if ident.Type == identifier.TypeDNS && strings.HasPrefix(ident.Value, "*.") &&
  2250  			(len(authz.Challenges) != 1 || authz.Challenges[0].Type != core.ChallengeTypeDNS01) {
  2251  			return nil, berrors.InternalServerError(
  2252  				"SA.GetAuthorizations returned a DNS wildcard authz (%s) with invalid challenge(s)",
  2253  				authz.ID)
  2254  		}
  2255  
  2256  		// If we reached this point then the existing authz was acceptable for
  2257  		// reuse.
  2258  		authzID, err := strconv.ParseInt(authz.ID, 10, 64)
  2259  		if err != nil {
  2260  			return nil, err
  2261  		}
  2262  		newOrderAuthzs = append(newOrderAuthzs, authzID)
  2263  		ra.authzAges.WithLabelValues("NewOrder", string(authz.Status)).Observe(authzAge)
  2264  	}
  2265  
  2266  	// Loop through each of the identifiers missing authzs and create a new
  2267  	// pending authorization for each.
  2268  	var newAuthzs []*sapb.NewAuthzRequest
  2269  	for _, ident := range missingAuthzIdents {
  2270  		challTypes, err := ra.PA.ChallengeTypesFor(ident)
  2271  		if err != nil {
  2272  			return nil, err
  2273  		}
  2274  
  2275  		var challStrs []string
  2276  		for _, t := range challTypes {
  2277  			challStrs = append(challStrs, string(t))
  2278  		}
  2279  
  2280  		newAuthzs = append(newAuthzs, &sapb.NewAuthzRequest{
  2281  			Identifier:     ident.ToProto(),
  2282  			RegistrationID: req.RegistrationID,
  2283  			Expires:        timestamppb.New(ra.clk.Now().Add(profile.pendingAuthzLifetime).Truncate(time.Second)),
  2284  			ChallengeTypes: challStrs,
  2285  			Token:          core.NewToken(),
  2286  		})
  2287  
  2288  		ra.authzAges.WithLabelValues("NewOrder", string(core.StatusPending)).Observe(0)
  2289  	}
  2290  
  2291  	// Start with the order's own expiry as the minExpiry. We only care
  2292  	// about authz expiries that are sooner than the order's expiry
  2293  	minExpiry := ra.clk.Now().Add(profile.orderLifetime)
  2294  
  2295  	// Check the reused authorizations to see if any have an expiry before the
  2296  	// minExpiry (the order's lifetime)
  2297  	for _, authz := range identToExistingAuthz {
  2298  		// An authz without an expiry is an unexpected internal server event
  2299  		if core.IsAnyNilOrZero(authz.Expires) {
  2300  			return nil, berrors.InternalServerError(
  2301  				"SA.GetAuthorizations returned an authz (%s) with zero expiry",
  2302  				authz.ID)
  2303  		}
  2304  		// If the reused authorization expires before the minExpiry, it's expiry
  2305  		// is the new minExpiry.
  2306  		if authz.Expires.Before(minExpiry) {
  2307  			minExpiry = *authz.Expires
  2308  		}
  2309  	}
  2310  	// If the newly created pending authz's have an expiry closer than the
  2311  	// minExpiry the minExpiry is the pending authz expiry.
  2312  	if len(newAuthzs) > 0 {
  2313  		newPendingAuthzExpires := ra.clk.Now().Add(profile.pendingAuthzLifetime)
  2314  		if newPendingAuthzExpires.Before(minExpiry) {
  2315  			minExpiry = newPendingAuthzExpires
  2316  		}
  2317  	}
  2318  
  2319  	newOrder := &sapb.NewOrderRequest{
  2320  		RegistrationID:         req.RegistrationID,
  2321  		Identifiers:            idents.ToProtoSlice(),
  2322  		CertificateProfileName: req.CertificateProfileName,
  2323  		Replaces:               req.Replaces,
  2324  		ReplacesSerial:         req.ReplacesSerial,
  2325  		// Set the order's expiry to the minimum expiry. The db doesn't store
  2326  		// sub-second values, so truncate here.
  2327  		Expires:          timestamppb.New(minExpiry.Truncate(time.Second)),
  2328  		V2Authorizations: newOrderAuthzs,
  2329  	}
  2330  	newOrderAndAuthzsReq := &sapb.NewOrderAndAuthzsRequest{
  2331  		NewOrder:  newOrder,
  2332  		NewAuthzs: newAuthzs,
  2333  	}
  2334  	storedOrder, err := ra.SA.NewOrderAndAuthzs(ctx, newOrderAndAuthzsReq)
  2335  	if err != nil {
  2336  		return nil, err
  2337  	}
  2338  
  2339  	if core.IsAnyNilOrZero(storedOrder.Id, storedOrder.Status, storedOrder.RegistrationID, storedOrder.Identifiers, storedOrder.Created, storedOrder.Expires) {
  2340  		return nil, errIncompleteGRPCResponse
  2341  	}
  2342  	ra.orderAges.WithLabelValues("NewOrder").Observe(0)
  2343  
  2344  	// Note how many identifiers are being requested in this certificate order.
  2345  	ra.namesPerCert.With(prometheus.Labels{"type": "requested"}).Observe(float64(len(storedOrder.Identifiers)))
  2346  
  2347  	return storedOrder, nil
  2348  }
  2349  
  2350  // wildcardOverlap takes a slice of identifiers and returns an error if any of
  2351  // them is a non-wildcard FQDN that overlaps with a wildcard domain in the map.
  2352  func wildcardOverlap(idents identifier.ACMEIdentifiers) error {
  2353  	nameMap := make(map[string]bool, len(idents))
  2354  	for _, v := range idents {
  2355  		if v.Type == identifier.TypeDNS {
  2356  			nameMap[v.Value] = true
  2357  		}
  2358  	}
  2359  	for name := range nameMap {
  2360  		if name[0] == '*' {
  2361  			continue
  2362  		}
  2363  		labels := strings.Split(name, ".")
  2364  		labels[0] = "*"
  2365  		if nameMap[strings.Join(labels, ".")] {
  2366  			return berrors.MalformedError(
  2367  				"Domain name %q is redundant with a wildcard domain in the same request. Remove one or the other from the certificate request.", name)
  2368  		}
  2369  	}
  2370  	return nil
  2371  }
  2372  
  2373  // UnpauseAccount receives a validated account unpause request from the SFE and
  2374  // instructs the SA to unpause that account. If the account cannot be unpaused,
  2375  // an error is returned.
  2376  func (ra *RegistrationAuthorityImpl) UnpauseAccount(ctx context.Context, request *rapb.UnpauseAccountRequest) (*rapb.UnpauseAccountResponse, error) {
  2377  	if core.IsAnyNilOrZero(request.RegistrationID) {
  2378  		return nil, errIncompleteGRPCRequest
  2379  	}
  2380  
  2381  	count, err := ra.SA.UnpauseAccount(ctx, &sapb.RegistrationID{
  2382  		Id: request.RegistrationID,
  2383  	})
  2384  	if err != nil {
  2385  		return nil, berrors.InternalServerError("failed to unpause account ID %d", request.RegistrationID)
  2386  	}
  2387  
  2388  	return &rapb.UnpauseAccountResponse{Count: count.Count}, nil
  2389  }
  2390  
  2391  func (ra *RegistrationAuthorityImpl) GetAuthorization(ctx context.Context, req *rapb.GetAuthorizationRequest) (*corepb.Authorization, error) {
  2392  	if core.IsAnyNilOrZero(req, req.Id) {
  2393  		return nil, errIncompleteGRPCRequest
  2394  	}
  2395  
  2396  	authz, err := ra.SA.GetAuthorization2(ctx, &sapb.AuthorizationID2{Id: req.Id})
  2397  	if err != nil {
  2398  		return nil, fmt.Errorf("getting authz from SA: %w", err)
  2399  	}
  2400  
  2401  	// Filter out any challenges which are currently disabled, so that the client
  2402  	// doesn't attempt them.
  2403  	challs := []*corepb.Challenge{}
  2404  	for _, chall := range authz.Challenges {
  2405  		if ra.PA.ChallengeTypeEnabled(core.AcmeChallenge(chall.Type)) {
  2406  			challs = append(challs, chall)
  2407  		}
  2408  	}
  2409  
  2410  	authz.Challenges = challs
  2411  	return authz, nil
  2412  }
  2413  
  2414  // AddRateLimitOverride dispatches an SA RPC to add a rate limit override to the
  2415  // database. If the override already exists, it will be updated. If the override
  2416  // does not exist, it will be inserted and enabled. If the override exists but
  2417  // has been disabled, it will be updated but not be re-enabled. The status of
  2418  // the override is returned in Enabled field of the response. To re-enable an
  2419  // override, use sa.EnableRateLimitOverride.
  2420  func (ra *RegistrationAuthorityImpl) AddRateLimitOverride(ctx context.Context, req *rapb.AddRateLimitOverrideRequest) (*rapb.AddRateLimitOverrideResponse, error) {
  2421  	if core.IsAnyNilOrZero(req, req.LimitEnum, req.BucketKey, req.Count, req.Burst, req.Period, req.Comment) {
  2422  		return nil, errIncompleteGRPCRequest
  2423  	}
  2424  
  2425  	resp, err := ra.SA.AddRateLimitOverride(ctx, &sapb.AddRateLimitOverrideRequest{
  2426  		Override: &sapb.RateLimitOverride{
  2427  			LimitEnum: req.LimitEnum,
  2428  			BucketKey: req.BucketKey,
  2429  			Comment:   req.Comment,
  2430  			Period:    req.Period,
  2431  			Count:     req.Count,
  2432  			Burst:     req.Burst,
  2433  		},
  2434  	})
  2435  	if err != nil {
  2436  		return nil, fmt.Errorf("adding rate limit override: %w", err)
  2437  	}
  2438  
  2439  	return &rapb.AddRateLimitOverrideResponse{
  2440  		Inserted: resp.Inserted,
  2441  		Enabled:  resp.Enabled,
  2442  	}, nil
  2443  }
  2444  
  2445  // Drain blocks until all detached goroutines are done.
  2446  //
  2447  // The RA runs detached goroutines for challenge validation and finalization,
  2448  // so that ACME responses can be returned to the user promptly while work continues.
  2449  //
  2450  // The main goroutine should call this before exiting to avoid canceling the work
  2451  // being done in detached goroutines.
  2452  func (ra *RegistrationAuthorityImpl) Drain() {
  2453  	ra.drainWG.Wait()
  2454  }