CA/SA: Store issuer info in certificateStatus, use for OCSP generation (#4546)
This avoids needing to send the entire certificate in OCSP generation RPCs. Ended up including a few cleanups that made the implementation easier. Initially I was struggling with how to derive the issuer identification info. We could just stick the full SPKI hash in certificateStatus, but that takes a significant amount of space, we could configure unique issuer IDs in the CA config, but that would require being very careful about keeping the IDs constant, and never reusing an ID, or we could store issuers in a table in the database and use that as a lookup table, but that requires figuring out how to get that info into the table etc. Instead I've just gone with what I found to be the easiest solution, deriving a stable ID from the cert hash. This means we don't need to remember to configure anything special and the CA config stays the same as it is now. Fixes #4469.
This commit is contained in:
parent
6ed4ce23a8
commit
b557d870c7
91
ca/ca.go
91
ca/ca.go
|
@ -7,6 +7,7 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/hex"
|
||||
|
@ -36,6 +37,7 @@ import (
|
|||
corepb "github.com/letsencrypt/boulder/core/proto"
|
||||
csrlib "github.com/letsencrypt/boulder/csr"
|
||||
berrors "github.com/letsencrypt/boulder/errors"
|
||||
"github.com/letsencrypt/boulder/features"
|
||||
"github.com/letsencrypt/boulder/goodkey"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
|
@ -103,6 +105,7 @@ type certificateStorage interface {
|
|||
AddCertificate(context.Context, []byte, int64, []byte, *time.Time) (string, error)
|
||||
AddPrecertificate(ctx context.Context, req *sapb.AddCertificateRequest) (*corepb.Empty, error)
|
||||
AddSerial(ctx context.Context, req *sapb.AddSerialRequest) (*corepb.Empty, error)
|
||||
SerialExists(ctx context.Context, req *sapb.Serial) (*sapb.Exists, error)
|
||||
}
|
||||
|
||||
type certificateType string
|
||||
|
@ -119,6 +122,8 @@ type CertificateAuthorityImpl struct {
|
|||
ecdsaProfile string
|
||||
// A map from issuer cert common name to an internalIssuer struct
|
||||
issuers map[string]*internalIssuer
|
||||
// A map from issuer ID to internalIssuer
|
||||
idToIssuer map[int64]*internalIssuer
|
||||
// The common name of the default issuer cert
|
||||
defaultIssuer *internalIssuer
|
||||
sa certificateStorage
|
||||
|
@ -190,6 +195,14 @@ func makeInternalIssuers(
|
|||
return internalIssuers, nil
|
||||
}
|
||||
|
||||
// idForIssuer generates a stable ID for an issuer certificate. This
|
||||
// is used for identifying which issuer issued a certificate in the
|
||||
// certificateStatus table.
|
||||
func idForIssuer(cert *x509.Certificate) int64 {
|
||||
h := sha256.Sum256(cert.Raw)
|
||||
return big.NewInt(0).SetBytes(h[:4]).Int64()
|
||||
}
|
||||
|
||||
// NewCertificateAuthorityImpl creates a CA instance that can sign certificates
|
||||
// from a single issuer (the first first in the issuers slice), and can sign OCSP
|
||||
// for any of the issuer certificates provided.
|
||||
|
@ -284,6 +297,12 @@ func NewCertificateAuthorityImpl(
|
|||
ocspLifetime: config.LifespanOCSP.Duration,
|
||||
}
|
||||
|
||||
ca.idToIssuer = make(map[int64]*internalIssuer)
|
||||
for _, ii := range ca.issuers {
|
||||
id := idForIssuer(ii.cert)
|
||||
ca.idToIssuer[id] = ii
|
||||
}
|
||||
|
||||
if config.Expiry == "" {
|
||||
return nil, errors.New("Config must specify an expiry period.")
|
||||
}
|
||||
|
@ -393,29 +412,56 @@ var ocspStatusToCode = map[string]int{
|
|||
|
||||
// GenerateOCSP produces a new OCSP response and returns it
|
||||
func (ca *CertificateAuthorityImpl) GenerateOCSP(ctx context.Context, req *caPB.GenerateOCSPRequest) (*caPB.OCSPResponse, error) {
|
||||
cert, err := x509.ParseCertificate(req.CertDER)
|
||||
if err != nil {
|
||||
ca.log.AuditErr(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
var issuer *internalIssuer
|
||||
var serial *big.Int
|
||||
// Once the feature is enabled we need to support both RPCs that include
|
||||
// IssuerID and those that don't as we still need to be able to update rows
|
||||
// that didn't have an IssuerID set when they were created. Once this featue
|
||||
// has been enabled for a full OCSP lifetime cycle we can remove this
|
||||
// functionality.
|
||||
if features.Enabled(features.StoreIssuerInfo) && req.IssuerID != nil {
|
||||
serialInt, err := core.StringToSerial(*req.Serial)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serial = serialInt
|
||||
var ok bool
|
||||
issuer, ok = ca.idToIssuer[*req.IssuerID]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("This CA doesn't have an issuer cert with ID %d", *req.IssuerID)
|
||||
}
|
||||
exists, err := ca.sa.SerialExists(ctx, &sapb.Serial{Serial: req.Serial})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !*exists.Exists {
|
||||
return nil, fmt.Errorf("GenerateOCSP was asked to sign OCSP for certification with unknown serial %q", *req.Serial)
|
||||
}
|
||||
} else {
|
||||
cert, err := x509.ParseCertificate(req.CertDER)
|
||||
if err != nil {
|
||||
ca.log.AuditErr(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cn := cert.Issuer.CommonName
|
||||
issuer := ca.issuers[cn]
|
||||
if issuer == nil {
|
||||
return nil, fmt.Errorf("This CA doesn't have an issuer cert with CommonName %q", cn)
|
||||
}
|
||||
|
||||
err = cert.CheckSignatureFrom(issuer.cert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GenerateOCSP was asked to sign OCSP for cert "+
|
||||
"%s from %q, but the cert's signature was not valid: %s.",
|
||||
core.SerialToString(cert.SerialNumber), cn, err)
|
||||
serial = cert.SerialNumber
|
||||
cn := cert.Issuer.CommonName
|
||||
issuer = ca.issuers[cn]
|
||||
if issuer == nil {
|
||||
return nil, fmt.Errorf("This CA doesn't have an issuer cert with CommonName %q", cn)
|
||||
}
|
||||
err = cert.CheckSignatureFrom(issuer.cert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GenerateOCSP was asked to sign OCSP for cert "+
|
||||
"%s from %q, but the cert's signature was not valid: %s.",
|
||||
core.SerialToString(cert.SerialNumber), cn, err)
|
||||
}
|
||||
}
|
||||
|
||||
now := ca.clk.Now().Truncate(time.Hour)
|
||||
tbsResponse := ocsp.Response{
|
||||
Status: ocspStatusToCode[*req.Status],
|
||||
SerialNumber: cert.SerialNumber,
|
||||
SerialNumber: serial,
|
||||
ThisUpdate: now,
|
||||
NextUpdate: now.Add(ca.ocspLifetime),
|
||||
}
|
||||
|
@ -469,12 +515,19 @@ func (ca *CertificateAuthorityImpl) IssuePrecertificate(ctx context.Context, iss
|
|||
return nil, err
|
||||
}
|
||||
|
||||
_, err = ca.sa.AddPrecertificate(ctx, &sapb.AddCertificateRequest{
|
||||
req := &sapb.AddCertificateRequest{
|
||||
Der: precertDER,
|
||||
RegID: ®ID,
|
||||
Ocsp: ocspResp.Response,
|
||||
Issued: &nowNanos,
|
||||
})
|
||||
}
|
||||
|
||||
// we currently only use one issuer, in the future when we support multiple
|
||||
// the issuer will need to be derived from issueReq
|
||||
issuerID := idForIssuer(ca.defaultIssuer.cert)
|
||||
req.IssuerID = &issuerID
|
||||
|
||||
_, err = ca.sa.AddPrecertificate(ctx, req)
|
||||
if err != nil {
|
||||
err = berrors.InternalServerError(err.Error())
|
||||
ca.log.AuditErrf("Failed RPC to store at SA, orphaning precertificate: serial=[%s] cert=[%s] err=[%v], regID=[%d], orderID=[%d]",
|
||||
|
|
|
@ -187,6 +187,11 @@ func (m *mockSA) AddSerial(ctx context.Context, req *sapb.AddSerialRequest) (*co
|
|||
return &corepb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (m *mockSA) SerialExists(ctx context.Context, req *sapb.Serial) (*sapb.Exists, error) {
|
||||
e := true
|
||||
return &sapb.Exists{Exists: &e}, nil
|
||||
}
|
||||
|
||||
var caKey crypto.Signer
|
||||
var caCert *x509.Certificate
|
||||
var ctx = context.Background()
|
||||
|
@ -932,6 +937,11 @@ func (qsa *queueSA) AddSerial(ctx context.Context, req *sapb.AddSerialRequest) (
|
|||
return &corepb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (qsa *queueSA) SerialExists(ctx context.Context, req *sapb.Serial) (*sapb.Exists, error) {
|
||||
e := true
|
||||
return &sapb.Exists{Exists: &e}, nil
|
||||
}
|
||||
|
||||
// TestPrecertOrphanQueue tests that IssuePrecertificate writes precertificates
|
||||
// to the orphan queue if storage fails, and that `integrateOrphan` later
|
||||
// successfully writes those precertificates to the database. To do this, it
|
||||
|
@ -1165,3 +1175,50 @@ func TestIssuePrecertificateLinting(t *testing.T) {
|
|||
matches := testCtx.logger.GetAllMatching(regex)
|
||||
test.AssertEquals(t, len(matches), 1)
|
||||
}
|
||||
|
||||
func TestGenerateOCSPWithIssuerID(t *testing.T) {
|
||||
testCtx := setup(t)
|
||||
sa := &mockSA{}
|
||||
_ = features.Set(map[string]bool{"StoreIssuerInfo": true})
|
||||
ca, err := NewCertificateAuthorityImpl(
|
||||
testCtx.caConfig,
|
||||
sa,
|
||||
testCtx.pa,
|
||||
testCtx.fc,
|
||||
testCtx.stats,
|
||||
testCtx.issuers,
|
||||
testCtx.keyPolicy,
|
||||
testCtx.logger,
|
||||
nil)
|
||||
test.AssertNotError(t, err, "Failed to create CA")
|
||||
|
||||
// GenerateOCSP with feature enabled + req contains bad IssuerID
|
||||
issuerID := int64(666)
|
||||
serial := "DEADDEADDEADDEADDEADDEADDEADDEADDEAD"
|
||||
status := string(core.OCSPStatusGood)
|
||||
_, err = ca.GenerateOCSP(context.Background(), &caPB.GenerateOCSPRequest{
|
||||
IssuerID: &issuerID,
|
||||
Serial: &serial,
|
||||
Status: &status,
|
||||
})
|
||||
test.AssertError(t, err, "GenerateOCSP didn't fail with invalid IssuerID")
|
||||
|
||||
// GenerateOCSP with feature enabled + req contains good IssuerID
|
||||
issuerID = idForIssuer(ca.defaultIssuer.cert)
|
||||
_, err = ca.GenerateOCSP(context.Background(), &caPB.GenerateOCSPRequest{
|
||||
IssuerID: &issuerID,
|
||||
Serial: &serial,
|
||||
Status: &status,
|
||||
})
|
||||
test.AssertNotError(t, err, "GenerateOCSP failed")
|
||||
|
||||
// GenerateOCSP with feature enabled + req doesn't contain IssuerID
|
||||
issueReq := caPB.IssueCertificateRequest{Csr: CNandSANCSR, RegistrationID: &arbitraryRegID}
|
||||
cert, err := ca.IssuePrecertificate(ctx, &issueReq)
|
||||
test.AssertNotError(t, err, "Failed to issue")
|
||||
_, err = ca.GenerateOCSP(context.Background(), &caPB.GenerateOCSPRequest{
|
||||
CertDER: cert.DER,
|
||||
Status: &status,
|
||||
})
|
||||
test.AssertNotError(t, err, "GenerateOCSP failed")
|
||||
}
|
||||
|
|
|
@ -184,11 +184,14 @@ func (m *IssueCertificateForPrecertificateRequest) GetOrderID() int64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
// Exactly one of certDER or [serial and issuerID] must be set.
|
||||
type GenerateOCSPRequest struct {
|
||||
CertDER []byte `protobuf:"bytes,1,opt,name=certDER" json:"certDER,omitempty"`
|
||||
Status *string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
|
||||
Reason *int32 `protobuf:"varint,3,opt,name=reason" json:"reason,omitempty"`
|
||||
RevokedAt *int64 `protobuf:"varint,4,opt,name=revokedAt" json:"revokedAt,omitempty"`
|
||||
Serial *string `protobuf:"bytes,5,opt,name=serial" json:"serial,omitempty"`
|
||||
IssuerID *int64 `protobuf:"varint,6,opt,name=issuerID" json:"issuerID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
@ -247,6 +250,20 @@ func (m *GenerateOCSPRequest) GetRevokedAt() int64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (m *GenerateOCSPRequest) GetSerial() string {
|
||||
if m != nil && m.Serial != nil {
|
||||
return *m.Serial
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GenerateOCSPRequest) GetIssuerID() int64 {
|
||||
if m != nil && m.IssuerID != nil {
|
||||
return *m.IssuerID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type OCSPResponse struct {
|
||||
Response []byte `protobuf:"bytes,1,opt,name=response" json:"response,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
|
@ -297,32 +314,33 @@ func init() {
|
|||
func init() { proto.RegisterFile("ca/proto/ca.proto", fileDescriptor_8f9fdc2529716820) }
|
||||
|
||||
var fileDescriptor_8f9fdc2529716820 = []byte{
|
||||
// 389 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x41, 0xaf, 0xd2, 0x40,
|
||||
0x10, 0xa6, 0xed, 0x7b, 0xe2, 0x9b, 0x54, 0xf3, 0x58, 0x54, 0x9a, 0x62, 0x22, 0xf6, 0x60, 0x1a,
|
||||
0x63, 0x4a, 0xc2, 0xd5, 0x13, 0x52, 0x34, 0x24, 0x26, 0x92, 0x45, 0x2f, 0xde, 0x36, 0xcb, 0xa0,
|
||||
0x8d, 0xb1, 0x8b, 0xb3, 0x5b, 0x13, 0x0f, 0xfe, 0x09, 0x7e, 0xb1, 0xe9, 0xd2, 0x42, 0x21, 0x25,
|
||||
0x1c, 0xbc, 0xcd, 0x37, 0x33, 0xbb, 0xdf, 0x37, 0xf3, 0xed, 0x42, 0x4f, 0x8a, 0xf1, 0x96, 0x94,
|
||||
0x51, 0x63, 0x29, 0x12, 0x1b, 0x30, 0x57, 0x8a, 0xf0, 0xa9, 0x54, 0x84, 0x75, 0x41, 0x11, 0xee,
|
||||
0x4b, 0xd1, 0x4f, 0x18, 0x2c, 0xb4, 0x2e, 0x70, 0x86, 0x64, 0xb2, 0x4d, 0x26, 0x85, 0x41, 0x8e,
|
||||
0xbf, 0x0a, 0xd4, 0x86, 0xdd, 0x83, 0x27, 0x35, 0x05, 0xce, 0xc8, 0x89, 0x7d, 0x5e, 0x86, 0xec,
|
||||
0x15, 0x3c, 0x26, 0xfc, 0x96, 0x69, 0x43, 0xc2, 0x64, 0x2a, 0x5f, 0xa4, 0x81, 0x3b, 0x72, 0x62,
|
||||
0x8f, 0x9f, 0x65, 0x59, 0x00, 0x5d, 0x45, 0x6b, 0xa4, 0x45, 0x1a, 0x78, 0xb6, 0xa1, 0x86, 0xd1,
|
||||
0x18, 0x86, 0x96, 0x6e, 0x49, 0x28, 0x9b, 0x8c, 0x7a, 0xab, 0x72, 0x8d, 0x25, 0x65, 0x3a, 0xe7,
|
||||
0x35, 0x65, 0x3a, 0xe7, 0xd1, 0xce, 0x81, 0xf8, 0x5c, 0xe0, 0x7b, 0x45, 0xe7, 0xe7, 0x0f, 0x8a,
|
||||
0x4f, 0x8f, 0x33, 0x06, 0x37, 0xab, 0xd9, 0x67, 0x1d, 0xb8, 0x23, 0x2f, 0xf6, 0xb9, 0x8d, 0x5b,
|
||||
0xa6, 0xf0, 0xae, 0x4d, 0x71, 0x73, 0x3a, 0xc5, 0x5f, 0xe8, 0x7f, 0xc0, 0x1c, 0x49, 0x18, 0xfc,
|
||||
0x34, 0x5b, 0x2d, 0x6b, 0xfa, 0x00, 0xba, 0xa5, 0xa8, 0xa3, 0x84, 0x1a, 0xb2, 0x67, 0xf0, 0x40,
|
||||
0x1b, 0x61, 0x0a, 0x6d, 0x17, 0x76, 0xc7, 0x2b, 0x54, 0xe6, 0x09, 0x85, 0x56, 0xb9, 0x95, 0x70,
|
||||
0xcb, 0x2b, 0xc4, 0x9e, 0xc3, 0x1d, 0xe1, 0x6f, 0xf5, 0x03, 0xd7, 0x53, 0x53, 0x91, 0x1f, 0x13,
|
||||
0xd1, 0x6b, 0xf0, 0xf7, 0xb4, 0xd5, 0xd6, 0x42, 0x78, 0x48, 0x55, 0x5c, 0x11, 0x1f, 0xf0, 0x64,
|
||||
0xe7, 0xc2, 0x93, 0xc6, 0xea, 0xa6, 0x85, 0xf9, 0xae, 0x28, 0x33, 0x7f, 0xd8, 0x17, 0xe8, 0xb7,
|
||||
0x38, 0xc1, 0x86, 0x89, 0x14, 0xc9, 0x85, 0x17, 0x11, 0xbe, 0x38, 0x14, 0xdb, 0xfd, 0x8b, 0x3a,
|
||||
0x6c, 0x03, 0x2f, 0xaf, 0xda, 0xc5, 0xde, 0xb4, 0x91, 0x5c, 0x72, 0x35, 0xec, 0x25, 0xf6, 0xbd,
|
||||
0x36, 0x5a, 0xa3, 0x0e, 0x7b, 0x0b, 0x7e, 0xd3, 0x02, 0x36, 0x28, 0xaf, 0x6c, 0x31, 0x25, 0xbc,
|
||||
0x2f, 0x0b, 0xcd, 0x75, 0x45, 0x9d, 0xc9, 0x47, 0x78, 0x54, 0x66, 0xaa, 0x76, 0x45, 0xff, 0x75,
|
||||
0xdb, 0xbb, 0xee, 0xd7, 0x5b, 0xfb, 0x97, 0xfe, 0x05, 0x00, 0x00, 0xff, 0xff, 0xf9, 0x16, 0x85,
|
||||
0x42, 0x7a, 0x03, 0x00, 0x00,
|
||||
// 415 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0xcd, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0x8e, 0xed, 0xa6, 0x69, 0x47, 0x06, 0xb5, 0x5b, 0xa0, 0x96, 0x8b, 0x44, 0xf0, 0x01, 0x59,
|
||||
0x08, 0x39, 0x52, 0xaf, 0x9c, 0x4a, 0x5c, 0x50, 0x24, 0x24, 0xaa, 0x2d, 0x5c, 0xb8, 0xad, 0xb6,
|
||||
0x53, 0xb0, 0x00, 0x6f, 0x99, 0x5d, 0x23, 0xf1, 0x1a, 0x7d, 0x13, 0xde, 0x10, 0xed, 0x66, 0xed,
|
||||
0x38, 0x91, 0xa3, 0x1c, 0x7a, 0x9b, 0x6f, 0x66, 0x67, 0xbe, 0x6f, 0x7e, 0x16, 0x8e, 0xa5, 0x98,
|
||||
0xdd, 0x91, 0x32, 0x6a, 0x26, 0x45, 0xe1, 0x0c, 0x16, 0x4a, 0x91, 0x3e, 0x95, 0x8a, 0xb0, 0x0d,
|
||||
0x28, 0xc2, 0x65, 0x28, 0xfb, 0x05, 0xa7, 0x0b, 0xad, 0x1b, 0x9c, 0x23, 0x99, 0xea, 0xb6, 0x92,
|
||||
0xc2, 0x20, 0xc7, 0xdf, 0x0d, 0x6a, 0xc3, 0x8e, 0x20, 0x92, 0x9a, 0x92, 0x60, 0x1a, 0xe4, 0x31,
|
||||
0xb7, 0x26, 0x7b, 0x05, 0x8f, 0x09, 0xbf, 0x55, 0xda, 0x90, 0x30, 0x95, 0xaa, 0x17, 0x65, 0x12,
|
||||
0x4e, 0x83, 0x3c, 0xe2, 0x1b, 0x5e, 0x96, 0xc0, 0x44, 0xd1, 0x0d, 0xd2, 0xa2, 0x4c, 0x22, 0xf7,
|
||||
0xa0, 0x85, 0xd9, 0x0c, 0xce, 0x1c, 0xdd, 0x15, 0xa1, 0xec, 0x33, 0xea, 0x3b, 0x55, 0x6b, 0xb4,
|
||||
0x94, 0xe5, 0x25, 0x6f, 0x29, 0xcb, 0x4b, 0x9e, 0xdd, 0x07, 0x90, 0x6f, 0x0a, 0x7c, 0xaf, 0x68,
|
||||
0x33, 0xbf, 0x53, 0xbc, 0x9e, 0xce, 0x18, 0xec, 0x5d, 0xcf, 0x3f, 0xeb, 0x24, 0x9c, 0x46, 0x79,
|
||||
0xcc, 0x9d, 0x3d, 0xd0, 0x45, 0xb4, 0xab, 0x8b, 0xbd, 0xf5, 0x2e, 0xfe, 0x05, 0x70, 0xf2, 0x01,
|
||||
0x6b, 0x24, 0x61, 0xf0, 0xd3, 0xfc, 0xfa, 0xaa, 0xe5, 0x4f, 0x60, 0x62, 0x55, 0xad, 0x34, 0xb4,
|
||||
0x90, 0x3d, 0x83, 0x7d, 0x6d, 0x84, 0x69, 0xb4, 0x9b, 0xd8, 0x21, 0xf7, 0xc8, 0xfa, 0x09, 0x85,
|
||||
0x56, 0xb5, 0xd3, 0x30, 0xe6, 0x1e, 0xb1, 0xe7, 0x70, 0x48, 0xf8, 0x47, 0xfd, 0xc0, 0x9b, 0x0b,
|
||||
0xe3, 0xd9, 0x57, 0x0e, 0x57, 0x0d, 0xa9, 0x12, 0x3f, 0x93, 0xb1, 0xaf, 0xe6, 0x10, 0x4b, 0xe1,
|
||||
0xa0, 0xb2, 0xb3, 0xb2, 0x92, 0xf7, 0x5d, 0x52, 0x87, 0xb3, 0xd7, 0x10, 0x2f, 0xa5, 0xfa, 0x51,
|
||||
0xa7, 0x70, 0x40, 0xde, 0xf6, 0x62, 0x3b, 0x7c, 0x7e, 0x1f, 0xc2, 0x93, 0xde, 0xbc, 0x2f, 0x1a,
|
||||
0xf3, 0x5d, 0x51, 0x65, 0xfe, 0xb2, 0x2f, 0x70, 0x32, 0xb0, 0x3e, 0x76, 0x56, 0x48, 0x51, 0x6c,
|
||||
0x39, 0xa3, 0xf4, 0x45, 0x17, 0x1c, 0x5e, 0x7a, 0x36, 0x62, 0xb7, 0xf0, 0x72, 0xe7, 0x8e, 0xd9,
|
||||
0x9b, 0x21, 0x92, 0x6d, 0xa7, 0x90, 0x1e, 0x17, 0xee, 0xc8, 0x7b, 0x4f, 0xb3, 0x11, 0x7b, 0x0b,
|
||||
0x71, 0x7f, 0x6d, 0xec, 0xd4, 0x96, 0x1c, 0x58, 0x64, 0x7a, 0x64, 0x03, 0xfd, 0x71, 0x65, 0xa3,
|
||||
0xf3, 0x8f, 0xf0, 0xc8, 0x7a, 0xfc, 0x73, 0x45, 0x0f, 0xaa, 0xf6, 0x6e, 0xf2, 0x75, 0xec, 0x3e,
|
||||
0xe0, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa3, 0xb6, 0x36, 0xac, 0xaf, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -37,11 +37,14 @@ message IssueCertificateForPrecertificateRequest {
|
|||
optional int64 orderID = 4;
|
||||
}
|
||||
|
||||
// Exactly one of certDER or [serial and issuerID] must be set.
|
||||
message GenerateOCSPRequest {
|
||||
optional bytes certDER = 1;
|
||||
optional string status = 2;
|
||||
optional int32 reason = 3;
|
||||
optional int64 revokedAt = 4;
|
||||
optional string serial = 5;
|
||||
optional int64 issuerID = 6;
|
||||
}
|
||||
|
||||
message OCSPResponse {
|
||||
|
|
|
@ -129,19 +129,20 @@ func (updater *OCSPUpdater) findStaleOCSPResponses(oldestLastUpdatedTime time.Ti
|
|||
now := updater.clk.Now()
|
||||
maxAgeCutoff := now.Add(-updater.ocspStaleMaxAge)
|
||||
|
||||
certStatusFields := "cs.serial, cs.status, cs.revokedDate, cs.notAfter"
|
||||
if features.Enabled(features.StoreIssuerInfo) {
|
||||
certStatusFields += ", cs.issuerID"
|
||||
}
|
||||
_, err := updater.dbMap.Select(
|
||||
&statuses,
|
||||
`SELECT
|
||||
cs.serial,
|
||||
cs.status,
|
||||
cs.revokedDate,
|
||||
cs.notAfter
|
||||
fmt.Sprintf(`SELECT
|
||||
%s
|
||||
FROM certificateStatus AS cs
|
||||
WHERE cs.ocspLastUpdated > :maxAge
|
||||
AND cs.ocspLastUpdated < :lastUpdate
|
||||
AND NOT cs.isExpired
|
||||
ORDER BY cs.ocspLastUpdated ASC
|
||||
LIMIT :limit`,
|
||||
LIMIT :limit`, certStatusFields),
|
||||
map[string]interface{}{
|
||||
"lastUpdate": oldestLastUpdatedTime,
|
||||
"maxAge": maxAgeCutoff,
|
||||
|
@ -154,15 +155,15 @@ func (updater *OCSPUpdater) findStaleOCSPResponses(oldestLastUpdatedTime time.Ti
|
|||
return statuses, err
|
||||
}
|
||||
|
||||
func (updater *OCSPUpdater) generateResponse(ctx context.Context, status core.CertificateStatus) (*core.CertificateStatus, error) {
|
||||
func getCertDER(selector ocspDB, serial string) ([]byte, error) {
|
||||
cert, err := sa.SelectCertificate(
|
||||
updater.dbMap,
|
||||
selector,
|
||||
"WHERE serial = ?",
|
||||
status.Serial,
|
||||
serial,
|
||||
)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
cert, err = sa.SelectPrecertificate(updater.dbMap, status.Serial)
|
||||
cert, err = sa.SelectPrecertificate(selector, serial)
|
||||
// If there was still a non-nil error return it. If we can't find
|
||||
// a precert row something is amiss, we have a certificateStatus row with
|
||||
// no matching certificate or precertificate.
|
||||
|
@ -173,16 +174,30 @@ func (updater *OCSPUpdater) generateResponse(ctx context.Context, status core.Ce
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
return cert.DER, nil
|
||||
}
|
||||
|
||||
func (updater *OCSPUpdater) generateResponse(ctx context.Context, status core.CertificateStatus) (*core.CertificateStatus, error) {
|
||||
reason := int32(status.RevokedReason)
|
||||
statusStr := string(status.Status)
|
||||
revokedAt := status.RevokedDate.UnixNano()
|
||||
ocspResponse, err := updater.ogc.GenerateOCSP(ctx, &capb.GenerateOCSPRequest{
|
||||
CertDER: cert.DER,
|
||||
ocspReq := capb.GenerateOCSPRequest{
|
||||
Reason: &reason,
|
||||
Status: &statusStr,
|
||||
RevokedAt: &revokedAt,
|
||||
})
|
||||
}
|
||||
if status.IssuerID != nil {
|
||||
ocspReq.Serial = &status.Serial
|
||||
ocspReq.IssuerID = status.IssuerID
|
||||
} else {
|
||||
certDER, err := getCertDER(updater.dbMap, status.Serial)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ocspReq.CertDER = certDER
|
||||
}
|
||||
|
||||
ocspResponse, err := updater.ogc.GenerateOCSP(ctx, &ocspReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -399,10 +414,7 @@ func setupClients(c OCSPUpdaterConfig, stats metrics.Scope, clk clock.Clock) (
|
|||
clientMetrics := bgrpc.NewClientMetrics(stats)
|
||||
caConn, err := bgrpc.ClientSetup(c.OCSPGeneratorService, tls, clientMetrics, clk)
|
||||
cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to CA")
|
||||
// Make a CA client that is only capable of signing OCSP.
|
||||
// TODO(jsha): Once we've fully moved to gRPC, replace this
|
||||
// with a plain caPB.NewOCSPGeneratorClient.
|
||||
ogc := capb.NewOCSPGeneratorClient(caConn)
|
||||
ogc := bgrpc.NewOCSPGeneratorClient(capb.NewOCSPGeneratorClient(caConn))
|
||||
|
||||
saConn, err := bgrpc.ClientSetup(c.SAService, tls, clientMetrics, clk)
|
||||
cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA")
|
||||
|
|
|
@ -2,9 +2,15 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -13,6 +19,7 @@ import (
|
|||
caPB "github.com/letsencrypt/boulder/ca/proto"
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
"github.com/letsencrypt/boulder/features"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
"github.com/letsencrypt/boulder/sa"
|
||||
|
@ -481,3 +488,68 @@ func TestGenerateOCSPResponsePrecert(t *testing.T) {
|
|||
_, err = updater.generateResponse(ctx, certs[0])
|
||||
test.AssertNotError(t, err, "generateResponse for precert errored")
|
||||
}
|
||||
|
||||
type mockOCSPRecordIssuer struct {
|
||||
gotIssuer bool
|
||||
}
|
||||
|
||||
func (ca *mockOCSPRecordIssuer) GenerateOCSP(_ context.Context, req *caPB.GenerateOCSPRequest, _ ...grpc.CallOption) (*caPB.OCSPResponse, error) {
|
||||
ca.gotIssuer = req.IssuerID != nil && req.Serial != nil
|
||||
return &caPB.OCSPResponse{Response: []byte{1, 2, 3}}, nil
|
||||
}
|
||||
|
||||
func TestIssuerInfo(t *testing.T) {
|
||||
if !strings.HasSuffix(os.Getenv("BOULDER_CONFIG_DIR"), "config-next") {
|
||||
return
|
||||
}
|
||||
|
||||
updater, sa, _, fc, cleanUp := setup(t)
|
||||
defer cleanUp()
|
||||
m := mockOCSPRecordIssuer{}
|
||||
updater.ogc = &m
|
||||
reg := satest.CreateWorkingRegistration(t, sa)
|
||||
_ = features.Set(map[string]bool{"StoreIssuerInfo": true})
|
||||
|
||||
k, err := rsa.GenerateKey(rand.Reader, 512)
|
||||
test.AssertNotError(t, err, "rsa.GenerateKey failed")
|
||||
template := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
}
|
||||
certA, err := x509.CreateCertificate(rand.Reader, template, template, &k.PublicKey, k)
|
||||
test.AssertNotError(t, err, "x509.CreateCertificate failed")
|
||||
template.SerialNumber = big.NewInt(2)
|
||||
certB, err := x509.CreateCertificate(rand.Reader, template, template, &k.PublicKey, k)
|
||||
test.AssertNotError(t, err, "x509.CreateCertificate failed")
|
||||
|
||||
now := fc.Now().UnixNano()
|
||||
id := int64(1234)
|
||||
_, err = sa.AddPrecertificate(context.Background(), &sapb.AddCertificateRequest{
|
||||
Der: certA,
|
||||
RegID: ®.ID,
|
||||
Ocsp: []byte{1, 2, 3},
|
||||
Issued: &now,
|
||||
IssuerID: &id,
|
||||
})
|
||||
test.AssertNotError(t, err, "sa.AddPrecertificate failed")
|
||||
_, err = sa.AddPrecertificate(context.Background(), &sapb.AddCertificateRequest{
|
||||
Der: certB,
|
||||
RegID: ®.ID,
|
||||
Ocsp: []byte{1, 2, 3},
|
||||
Issued: &now,
|
||||
})
|
||||
test.AssertNotError(t, err, "sa.AddPrecertificate failed")
|
||||
|
||||
fc.Add(time.Hour * 24 * 4)
|
||||
statuses, err := updater.findStaleOCSPResponses(fc.Now().Add(-time.Hour), 10)
|
||||
test.AssertNotError(t, err, "findStaleOCSPResponses failed")
|
||||
test.AssertEquals(t, len(statuses), 2)
|
||||
test.AssertEquals(t, *statuses[0].IssuerID, id)
|
||||
test.Assert(t, statuses[1].IssuerID == nil, "second status doesn't have nil IssuerID")
|
||||
|
||||
_, err = updater.generateResponse(context.Background(), statuses[0])
|
||||
test.AssertNotError(t, err, "generateResponse failed")
|
||||
test.Assert(t, m.gotIssuer, "generateResponse didn't send issuer information and serial")
|
||||
_, err = updater.generateResponse(context.Background(), statuses[1])
|
||||
test.AssertNotError(t, err, "generateResponse failed")
|
||||
test.Assert(t, !m.gotIssuer, "generateResponse did send issuer information and serial when it shouldn't")
|
||||
}
|
||||
|
|
|
@ -134,6 +134,7 @@ type StorageGetter interface {
|
|||
GetValidOrderAuthorizations2(ctx context.Context, req *sapb.GetValidOrderAuthorizationsRequest) (*sapb.Authorizations, error)
|
||||
CountInvalidAuthorizations2(ctx context.Context, req *sapb.CountInvalidAuthorizationsRequest) (*sapb.Count, error)
|
||||
GetValidAuthorizations2(ctx context.Context, req *sapb.GetValidAuthorizationsRequest) (*sapb.Authorizations, error)
|
||||
SerialExists(ctx context.Context, req *sapb.Serial) (*sapb.Exists, error)
|
||||
}
|
||||
|
||||
// StorageAdder are the Boulder SA's write/update methods
|
||||
|
|
|
@ -490,6 +490,8 @@ type CertificateStatus struct {
|
|||
// [0]: https://github.com/letsencrypt/boulder/issues/1864
|
||||
NotAfter time.Time `db:"notAfter"`
|
||||
IsExpired bool `db:"isExpired"`
|
||||
|
||||
IssuerID *int64
|
||||
}
|
||||
|
||||
// OCSPResponse is a (large) table of OCSP responses. This contains all
|
||||
|
|
|
@ -38,11 +38,12 @@ func _() {
|
|||
_ = x[PrecertificateRevocation-27]
|
||||
_ = x[StripDefaultSchemePort-28]
|
||||
_ = x[GetAuthorizationsPerf-29]
|
||||
_ = x[StoreIssuerInfo-30]
|
||||
}
|
||||
|
||||
const _FeatureFlag_name = "unusedPerformValidationRPCACME13KeyRolloverSimplifiedVAHTTPTLSSNIRevalidationAllowRenewalFirstRLSetIssuedNamesRenewalBitFasterRateLimitProbeCTLogsRevokeAtRANewAuthorizationSchemaDisableAuthz2OrdersEarlyOrderRateLimitFasterGetOrderForNamesPrecertificateOCSPCAAValidationMethodsCAAAccountURIHeadNonceStatusOKEnforceMultiVAMultiVAFullResultsRemoveWFE2AccountIDCheckRenewalFirstMandatoryPOSTAsGETAllowV1RegistrationParallelCheckFailedValidationDeleteUnusedChallengesV1DisableNewValidationsPrecertificateRevocationStripDefaultSchemePortGetAuthorizationsPerf"
|
||||
const _FeatureFlag_name = "unusedPerformValidationRPCACME13KeyRolloverSimplifiedVAHTTPTLSSNIRevalidationAllowRenewalFirstRLSetIssuedNamesRenewalBitFasterRateLimitProbeCTLogsRevokeAtRANewAuthorizationSchemaDisableAuthz2OrdersEarlyOrderRateLimitFasterGetOrderForNamesPrecertificateOCSPCAAValidationMethodsCAAAccountURIHeadNonceStatusOKEnforceMultiVAMultiVAFullResultsRemoveWFE2AccountIDCheckRenewalFirstMandatoryPOSTAsGETAllowV1RegistrationParallelCheckFailedValidationDeleteUnusedChallengesV1DisableNewValidationsPrecertificateRevocationStripDefaultSchemePortGetAuthorizationsPerfStoreIssuerInfo"
|
||||
|
||||
var _FeatureFlag_index = [...]uint16{0, 6, 26, 43, 59, 77, 96, 120, 135, 146, 156, 178, 197, 216, 238, 256, 276, 289, 306, 320, 338, 357, 374, 392, 411, 440, 462, 485, 509, 531, 552}
|
||||
var _FeatureFlag_index = [...]uint16{0, 6, 26, 43, 59, 77, 96, 120, 135, 146, 156, 178, 197, 216, 238, 256, 276, 289, 306, 320, 338, 357, 374, 392, 411, 440, 462, 485, 509, 531, 552, 567}
|
||||
|
||||
func (i FeatureFlag) String() string {
|
||||
if i < 0 || i >= FeatureFlag(len(_FeatureFlag_index)-1) {
|
||||
|
|
|
@ -68,6 +68,9 @@ const (
|
|||
// GetAuthorizationsPerf enables a more performant GetAuthorizations2 query
|
||||
// at the SA.
|
||||
GetAuthorizationsPerf
|
||||
// StoreIssuerInfo enables storage of information identifying the issuer of
|
||||
// a certificate in the certificateStatus table.
|
||||
StoreIssuerInfo
|
||||
)
|
||||
|
||||
// List of features and their default value, protected by fMu
|
||||
|
@ -102,6 +105,7 @@ var features = map[FeatureFlag]bool{
|
|||
PrecertificateRevocation: false,
|
||||
StripDefaultSchemePort: false,
|
||||
GetAuthorizationsPerf: false,
|
||||
StoreIssuerInfo: false,
|
||||
}
|
||||
|
||||
var fMu = new(sync.RWMutex)
|
||||
|
|
|
@ -100,7 +100,7 @@ func (cas *CertificateAuthorityServerWrapper) IssueCertificateForPrecertificate(
|
|||
}
|
||||
|
||||
func (cas *CertificateAuthorityServerWrapper) GenerateOCSP(ctx context.Context, req *capb.GenerateOCSPRequest) (*capb.OCSPResponse, error) {
|
||||
if req.CertDER == nil || req.Status == nil || req.Reason == nil || req.RevokedAt == nil {
|
||||
if (req.CertDER == nil && (req.Serial == nil || req.IssuerID == nil)) || req.Status == nil || req.Reason == nil || req.RevokedAt == nil {
|
||||
return nil, errIncompleteRequest
|
||||
}
|
||||
return cas.inner.GenerateOCSP(ctx, req)
|
||||
|
|
|
@ -489,6 +489,17 @@ func (sas StorageAuthorityClientWrapper) DeactivateAuthorization2(ctx context.Co
|
|||
return nil, err
|
||||
}
|
||||
|
||||
func (sas StorageAuthorityClientWrapper) SerialExists(ctx context.Context, req *sapb.Serial) (*sapb.Exists, error) {
|
||||
res, err := sas.inner.SerialExists(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res == nil || res.Exists == nil {
|
||||
return nil, errIncompleteResponse
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// StorageAuthorityServerWrapper is the gRPC version of a core.ServerAuthority server
|
||||
type StorageAuthorityServerWrapper struct {
|
||||
// TODO(#3119): Don't use core.StorageAuthority
|
||||
|
@ -898,3 +909,10 @@ func (sas StorageAuthorityServerWrapper) DeactivateAuthorization2(ctx context.Co
|
|||
|
||||
return sas.inner.DeactivateAuthorization2(ctx, req)
|
||||
}
|
||||
|
||||
func (sas StorageAuthorityServerWrapper) SerialExists(ctx context.Context, req *sapb.Serial) (*sapb.Exists, error) {
|
||||
if req == nil || req.Serial == nil {
|
||||
return nil, errIncompleteRequest
|
||||
}
|
||||
return sas.inner.SerialExists(ctx, req)
|
||||
}
|
||||
|
|
|
@ -619,6 +619,10 @@ func (sa *StorageAuthority) GetPendingAuthorization2(ctx context.Context, req *s
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (sa *StorageAuthority) SerialExists(ctx context.Context, req *sapb.Serial) (*sapb.Exists, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
authzIdValid = int64(1)
|
||||
authzIdPending = int64(2)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
-- +goose Up
|
||||
-- SQL in section 'Up' is executed when this migration is applied
|
||||
|
||||
ALTER TABLE certificateStatus ADD `issuerID` BIGINT(20) DEFAULT NULL;
|
||||
|
||||
-- +goose Down
|
||||
-- SQL section 'Down' is executed when this migration is rolled back
|
||||
|
||||
ALTER TABLE certificateStatus DROP `issuerID`;
|
18
sa/model.go
18
sa/model.go
|
@ -137,26 +137,19 @@ const certStatusFields = "serial, status, ocspLastUpdated, revokedDate, revokedR
|
|||
|
||||
// SelectCertificateStatus selects all fields of one certificate status model
|
||||
func SelectCertificateStatus(s db.OneSelector, q string, args ...interface{}) (certStatusModel, error) {
|
||||
fields := certStatusFields
|
||||
if features.Enabled(features.StoreIssuerInfo) {
|
||||
fields += ", issuerID"
|
||||
}
|
||||
var model certStatusModel
|
||||
err := s.SelectOne(
|
||||
&model,
|
||||
"SELECT "+certStatusFields+" FROM certificateStatus "+q,
|
||||
"SELECT "+fields+" FROM certificateStatus "+q,
|
||||
args...,
|
||||
)
|
||||
return model, err
|
||||
}
|
||||
|
||||
// SelectCertificateStatuses selects all fields of multiple certificate status objects
|
||||
func SelectCertificateStatuses(s db.Selector, q string, args ...interface{}) ([]core.CertificateStatus, error) {
|
||||
var models []core.CertificateStatus
|
||||
_, err := s.Select(
|
||||
&models,
|
||||
"SELECT "+certStatusFields+" FROM certificateStatus "+q,
|
||||
args...,
|
||||
)
|
||||
return models, err
|
||||
}
|
||||
|
||||
var mediumBlobSize = int(math.Pow(2, 24))
|
||||
|
||||
type issuedNameModel struct {
|
||||
|
@ -191,6 +184,7 @@ type certStatusModel struct {
|
|||
OCSPResponse []byte `db:"ocspResponse"`
|
||||
NotAfter time.Time `db:"notAfter"`
|
||||
IsExpired bool `db:"isExpired"`
|
||||
IssuerID *int64 `db:"issuerID"`
|
||||
}
|
||||
|
||||
// challModel is the description of a core.Challenge in the database
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/letsencrypt/boulder/core"
|
||||
corepb "github.com/letsencrypt/boulder/core/proto"
|
||||
berrors "github.com/letsencrypt/boulder/errors"
|
||||
"github.com/letsencrypt/boulder/features"
|
||||
bgrpc "github.com/letsencrypt/boulder/grpc"
|
||||
sapb "github.com/letsencrypt/boulder/sa/proto"
|
||||
)
|
||||
|
@ -62,15 +63,40 @@ func (ssa *SQLStorageAuthority) AddPrecertificate(ctx context.Context, req *sapb
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = ssa.dbMap.WithContext(ctx).Insert(&certStatusModel{
|
||||
Status: core.OCSPStatusGood,
|
||||
OCSPLastUpdated: ssa.clk.Now(),
|
||||
OCSPResponse: req.Ocsp,
|
||||
Serial: serialHex,
|
||||
RevokedDate: time.Time{},
|
||||
RevokedReason: 0,
|
||||
NotAfter: parsed.NotAfter,
|
||||
})
|
||||
// With feature.StoreIssuerInfo we've added a new field to certStatusModel
|
||||
// so when we try and use dbMap.Insert it will always try to insert that field.
|
||||
// That will break when the relevant migration hasn't been applied so we need
|
||||
// to use an explicit INSERT statement that we can manipulate to include the
|
||||
// field only when the feature is enabled (and as such the migration has been
|
||||
// applied).
|
||||
csFields := certStatusFields
|
||||
if features.Enabled(features.StoreIssuerInfo) && req.IssuerID != nil {
|
||||
csFields += ", issuerID"
|
||||
}
|
||||
qmarks := []string{}
|
||||
for range strings.Split(csFields, ",") {
|
||||
qmarks = append(qmarks, "?")
|
||||
}
|
||||
args := []interface{}{
|
||||
serialHex, // serial
|
||||
string(core.OCSPStatusGood), // stauts
|
||||
ssa.clk.Now(), // ocspLastUpdated
|
||||
time.Time{}, // revokedDate
|
||||
0, // revokedReason
|
||||
time.Time{}, // lastExpirationNagSent
|
||||
req.Ocsp, // ocspResponse
|
||||
parsed.NotAfter, // notAfter
|
||||
false, // isExpired
|
||||
}
|
||||
if features.Enabled(features.StoreIssuerInfo) && req.IssuerID != nil {
|
||||
args = append(args, req.IssuerID)
|
||||
}
|
||||
|
||||
_, err = ssa.dbMap.WithContext(ctx).Exec(fmt.Sprintf(
|
||||
"INSERT INTO certificateStatus (%s) VALUES (%s)",
|
||||
csFields,
|
||||
strings.Join(qmarks, ","),
|
||||
), args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1103,6 +1103,7 @@ type AddCertificateRequest struct {
|
|||
// the current time. The orphan-finder uses this parameter to add
|
||||
// certificates with the correct historic issued date
|
||||
Issued *int64 `protobuf:"varint,4,opt,name=issued" json:"issued,omitempty"`
|
||||
IssuerID *int64 `protobuf:"varint,5,opt,name=issuerID" json:"issuerID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
@ -1161,6 +1162,13 @@ func (m *AddCertificateRequest) GetIssued() int64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (m *AddCertificateRequest) GetIssuerID() int64 {
|
||||
if m != nil && m.IssuerID != nil {
|
||||
return *m.IssuerID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type AddCertificateResponse struct {
|
||||
Digest *string `protobuf:"bytes,1,opt,name=digest" json:"digest,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
|
@ -1838,115 +1846,116 @@ func init() {
|
|||
func init() { proto.RegisterFile("sa/proto/sa.proto", fileDescriptor_099fb35e782a48a6) }
|
||||
|
||||
var fileDescriptor_099fb35e782a48a6 = []byte{
|
||||
// 1717 bytes of a gzipped FileDescriptorProto
|
||||
// 1739 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xdd, 0x6e, 0xdb, 0xc8,
|
||||
0x15, 0xd6, 0x8f, 0x65, 0x4b, 0xc7, 0x7f, 0xd2, 0xc4, 0x56, 0xb9, 0x8a, 0x9d, 0xc8, 0xb3, 0xd9,
|
||||
0xc0, 0x8b, 0x02, 0x5e, 0x97, 0x5d, 0xec, 0x16, 0x70, 0x9b, 0xc4, 0x8e, 0x1c, 0xc7, 0x69, 0x62,
|
||||
0x2b, 0x54, 0xe3, 0x16, 0x45, 0x6f, 0x18, 0x71, 0xa2, 0xb0, 0x91, 0x49, 0x65, 0x66, 0x64, 0x47,
|
||||
0xbe, 0x2e, 0xd0, 0x3e, 0x41, 0xd1, 0xcb, 0x3e, 0x47, 0x5f, 0xa2, 0xcf, 0xd2, 0x37, 0x28, 0xe6,
|
||||
0x70, 0x48, 0x91, 0x14, 0x29, 0xd7, 0x68, 0xd1, 0xbb, 0x39, 0x67, 0xce, 0xdf, 0xcc, 0x9c, 0x9f,
|
||||
0x8f, 0x84, 0x86, 0xb0, 0xbf, 0x1b, 0x71, 0x5f, 0xfa, 0xdf, 0x09, 0x7b, 0x0f, 0x17, 0xa4, 0x24,
|
||||
0xec, 0xd6, 0x66, 0xdf, 0xe7, 0x4c, 0x6f, 0xa8, 0x65, 0xb0, 0x45, 0xdb, 0xb0, 0x66, 0xb1, 0x81,
|
||||
0x2b, 0x24, 0xb7, 0xa5, 0xeb, 0x7b, 0xa7, 0x1d, 0xb2, 0x06, 0x25, 0xd7, 0x31, 0x8a, 0xed, 0xe2,
|
||||
0x6e, 0xd9, 0x2a, 0xb9, 0x0e, 0x7d, 0x00, 0xf0, 0xaa, 0x77, 0x7e, 0xf6, 0x5b, 0xf6, 0xfe, 0xd7,
|
||||
0x6c, 0x42, 0xea, 0x50, 0xfe, 0xe3, 0xf5, 0x27, 0xdc, 0x5e, 0xb1, 0xd4, 0x92, 0xee, 0xc0, 0xfa,
|
||||
0xe1, 0x58, 0x7e, 0xf4, 0xb9, 0x7b, 0x33, 0x6b, 0xa2, 0x86, 0x26, 0xfe, 0x51, 0x84, 0x07, 0x27,
|
||||
0x4c, 0x76, 0x99, 0xe7, 0xb8, 0xde, 0x20, 0x21, 0x6d, 0xb1, 0xcf, 0x63, 0x26, 0x24, 0x79, 0x0c,
|
||||
0x6b, 0x3c, 0x11, 0x87, 0x8e, 0x20, 0xc5, 0x55, 0x72, 0xae, 0xc3, 0x3c, 0xe9, 0x7e, 0x70, 0x19,
|
||||
0xff, 0xcd, 0x64, 0xc4, 0x8c, 0x12, 0xba, 0x49, 0x71, 0xc9, 0x2e, 0xac, 0x4f, 0x39, 0x17, 0xf6,
|
||||
0x70, 0xcc, 0x8c, 0x32, 0x0a, 0xa6, 0xd9, 0xe4, 0x01, 0xc0, 0x95, 0x3d, 0x74, 0x9d, 0x77, 0x9e,
|
||||
0x74, 0x87, 0xc6, 0x02, 0x7a, 0x8d, 0x71, 0xa8, 0x80, 0xed, 0x13, 0x26, 0x2f, 0x14, 0x23, 0x11,
|
||||
0xb9, 0xb8, 0x6b, 0xe8, 0x06, 0x2c, 0x39, 0xfe, 0xa5, 0xed, 0x7a, 0xc2, 0x28, 0xb5, 0xcb, 0xbb,
|
||||
0x35, 0x2b, 0x24, 0xd5, 0xa5, 0x7a, 0xfe, 0x35, 0x06, 0x58, 0xb6, 0xd4, 0x92, 0xfe, 0xbd, 0x08,
|
||||
0xf7, 0x32, 0x5c, 0x92, 0x5f, 0x40, 0x05, 0x43, 0x33, 0x8a, 0xed, 0xf2, 0xee, 0xb2, 0x49, 0xf7,
|
||||
0x84, 0xbd, 0x97, 0x21, 0xb7, 0xf7, 0xc6, 0x1e, 0x1d, 0x0f, 0xd9, 0x25, 0xf3, 0xa4, 0x15, 0x28,
|
||||
0xb4, 0xce, 0x01, 0xa6, 0x4c, 0xd2, 0x84, 0xc5, 0xc0, 0xb9, 0x7e, 0x25, 0x4d, 0x91, 0x6f, 0xa1,
|
||||
0x62, 0x8f, 0xe5, 0xc7, 0x1b, 0xbc, 0xd5, 0x65, 0xf3, 0xde, 0x1e, 0xa6, 0x4a, 0xf2, 0xc5, 0x02,
|
||||
0x09, 0xfa, 0xcf, 0x12, 0x34, 0x9e, 0x33, 0xae, 0xae, 0xb2, 0x6f, 0x4b, 0xd6, 0x93, 0xb6, 0x1c,
|
||||
0x0b, 0x65, 0x58, 0x30, 0xee, 0xda, 0xc3, 0xd0, 0x70, 0x40, 0x21, 0x1f, 0x25, 0xf4, 0x33, 0x68,
|
||||
0x4a, 0xbd, 0x93, 0xdf, 0x17, 0xa3, 0xd7, 0xb6, 0x90, 0xef, 0x46, 0x8e, 0x2d, 0x99, 0xa3, 0x9f,
|
||||
0x20, 0xcd, 0x26, 0x6d, 0x58, 0xe6, 0xec, 0xca, 0xff, 0xc4, 0x9c, 0x8e, 0x2d, 0x99, 0x51, 0x41,
|
||||
0xa9, 0x38, 0x8b, 0x3c, 0x82, 0x55, 0x4d, 0x5a, 0xcc, 0x16, 0xbe, 0x67, 0x2c, 0xa2, 0x4c, 0x92,
|
||||
0x49, 0xbe, 0x87, 0xcd, 0xa1, 0x2d, 0xe4, 0xf1, 0x97, 0x91, 0x1b, 0x3c, 0xcd, 0x99, 0x3d, 0xe8,
|
||||
0x31, 0x4f, 0x1a, 0x4b, 0x28, 0x9d, 0xbd, 0x49, 0x28, 0xac, 0xa8, 0x80, 0x2c, 0x26, 0x46, 0xbe,
|
||||
0x27, 0x98, 0x51, 0xc5, 0x02, 0x48, 0xf0, 0x48, 0x0b, 0xaa, 0x9e, 0x2f, 0x0f, 0x3f, 0x48, 0xc6,
|
||||
0x8d, 0x1a, 0x1a, 0x8b, 0x68, 0xb2, 0x05, 0x35, 0x57, 0xa0, 0x59, 0xe6, 0x18, 0xd0, 0x2e, 0xee,
|
||||
0x56, 0xad, 0x29, 0xe3, 0xd5, 0x42, 0xb5, 0x54, 0x2f, 0xd3, 0x36, 0x2c, 0xf6, 0xa6, 0xb7, 0x95,
|
||||
0x71, 0x8b, 0xf4, 0x00, 0x2a, 0x96, 0xed, 0x0d, 0xd0, 0x15, 0xb3, 0xf9, 0xd0, 0x65, 0x42, 0xea,
|
||||
0x6c, 0x8b, 0x68, 0xa5, 0x3c, 0xb4, 0xa5, 0xda, 0x29, 0xe1, 0x8e, 0xa6, 0xe8, 0x36, 0x54, 0x9e,
|
||||
0xfb, 0x63, 0x4f, 0x92, 0x0d, 0xa8, 0xf4, 0xd5, 0x42, 0x6b, 0x06, 0x04, 0xfd, 0x1d, 0x3c, 0xc4,
|
||||
0xed, 0xd8, 0x9b, 0x8a, 0xa3, 0xc9, 0x99, 0x7d, 0xc9, 0xa2, 0x4c, 0x7f, 0x08, 0x15, 0xae, 0xdc,
|
||||
0xa3, 0xe2, 0xb2, 0x59, 0x53, 0xd9, 0x87, 0xf1, 0x58, 0x01, 0x5f, 0x59, 0xf6, 0x94, 0x82, 0x4e,
|
||||
0xf0, 0x80, 0xa0, 0x7f, 0x2e, 0xc2, 0x0a, 0x9a, 0xd6, 0xe6, 0xc8, 0x53, 0x58, 0xe9, 0xc7, 0x68,
|
||||
0x9d, 0xcc, 0xf7, 0x95, 0xb9, 0xb8, 0x5c, 0x3c, 0x8b, 0x13, 0x0a, 0xad, 0x1f, 0x12, 0xc9, 0x4c,
|
||||
0x60, 0x41, 0x39, 0xd2, 0x77, 0x85, 0xeb, 0xe9, 0x19, 0x4b, 0xf1, 0x33, 0x76, 0x61, 0x1b, 0x1d,
|
||||
0xc4, 0x5b, 0x9e, 0x38, 0x9a, 0x9c, 0x76, 0xc3, 0x13, 0xaa, 0xce, 0x35, 0xd2, 0xdd, 0xad, 0xe4,
|
||||
0x8e, 0xa6, 0x27, 0x2e, 0x65, 0x9f, 0x98, 0xfe, 0xa5, 0x08, 0x3b, 0x68, 0xf2, 0xd4, 0xbb, 0xfa,
|
||||
0xef, 0x5b, 0x44, 0x0b, 0xaa, 0x1f, 0x7d, 0x21, 0xf1, 0x34, 0x41, 0x5f, 0x8b, 0xe8, 0x69, 0x28,
|
||||
0xe5, 0x9c, 0x50, 0x7a, 0x40, 0x30, 0x92, 0x73, 0xee, 0x30, 0x1e, 0xb9, 0xde, 0x82, 0x9a, 0xdd,
|
||||
0xc7, 0xd3, 0x47, 0x5e, 0xa7, 0x8c, 0xdb, 0xcf, 0xf7, 0x12, 0x36, 0xd0, 0xe8, 0x8b, 0xb7, 0x9d,
|
||||
0xb3, 0x1e, 0x93, 0x91, 0xd9, 0x26, 0x2c, 0x5e, 0xbb, 0x9e, 0xe3, 0x5f, 0x6b, 0x9b, 0x9a, 0xca,
|
||||
0x6f, 0x72, 0x74, 0x1f, 0x36, 0xb4, 0x91, 0xe3, 0x2f, 0xae, 0x98, 0x5a, 0x8a, 0x69, 0x14, 0x93,
|
||||
0x1a, 0x5d, 0x68, 0x77, 0x39, 0xbb, 0x72, 0xfd, 0xb1, 0x88, 0x25, 0x65, 0x52, 0x3b, 0xaf, 0x91,
|
||||
0x6d, 0x40, 0x85, 0xb3, 0xc1, 0x69, 0x27, 0x7c, 0x7f, 0x24, 0x54, 0x85, 0x05, 0xea, 0x4a, 0x8f,
|
||||
0xe1, 0x0a, 0xf5, 0xaa, 0x96, 0xa6, 0xa8, 0x84, 0xfa, 0xa1, 0xe3, 0x04, 0x65, 0x18, 0xfa, 0x88,
|
||||
0x6c, 0x15, 0x63, 0xb6, 0x62, 0x35, 0x5a, 0x4a, 0x74, 0x3a, 0x03, 0x96, 0xfa, 0x9c, 0x61, 0x27,
|
||||
0x0b, 0x1a, 0x7a, 0x48, 0xaa, 0x1d, 0x86, 0x05, 0x2f, 0x74, 0x8f, 0x0b, 0x49, 0xfa, 0x09, 0x36,
|
||||
0x0f, 0x1d, 0x27, 0x76, 0xc8, 0xd0, 0x75, 0x1d, 0xca, 0x0e, 0xe3, 0xe1, 0xb8, 0x75, 0x18, 0xcf,
|
||||
0x3e, 0x98, 0x2a, 0x01, 0xd5, 0x8a, 0xd0, 0xe3, 0x8a, 0x85, 0x6b, 0x15, 0xa0, 0x2b, 0xc4, 0x38,
|
||||
0xea, 0xa8, 0x9a, 0xa2, 0xfb, 0xd0, 0x4c, 0x3b, 0xd3, 0x0d, 0x4c, 0x5d, 0xa6, 0x3b, 0x08, 0x7b,
|
||||
0x8a, 0xba, 0x4c, 0xa4, 0x68, 0x17, 0x56, 0x30, 0xa9, 0xe2, 0x55, 0x12, 0x83, 0x08, 0x64, 0x1f,
|
||||
0xee, 0x8d, 0x05, 0xbb, 0x30, 0x93, 0xc9, 0x8f, 0x11, 0x56, 0xad, 0xac, 0x2d, 0xfa, 0x1a, 0x68,
|
||||
0x38, 0x54, 0xd1, 0x72, 0x76, 0xd9, 0xa4, 0xfd, 0x34, 0x61, 0xd1, 0xee, 0xf7, 0x65, 0x74, 0x78,
|
||||
0x4d, 0xd1, 0x09, 0xfc, 0xe4, 0x84, 0x05, 0x79, 0xff, 0xc2, 0xe7, 0x89, 0x96, 0x35, 0x55, 0x29,
|
||||
0xc6, 0x55, 0xb2, 0x3b, 0x55, 0xde, 0x41, 0xca, 0xf9, 0x07, 0xf9, 0x5b, 0x11, 0x8c, 0x13, 0x26,
|
||||
0xff, 0x6f, 0xc8, 0x40, 0x0d, 0x4c, 0xce, 0x3e, 0x8f, 0x5d, 0xae, 0x63, 0xb9, 0x09, 0x92, 0xa9,
|
||||
0x6a, 0xa5, 0xd9, 0xf4, 0xaf, 0x45, 0x58, 0x4b, 0xc1, 0x87, 0x9f, 0x87, 0xe3, 0x3d, 0xe8, 0xb8,
|
||||
0xdb, 0xaa, 0xdc, 0xe7, 0x20, 0x07, 0x94, 0xfd, 0xdf, 0x23, 0x87, 0xd7, 0xf0, 0xf0, 0xd0, 0x71,
|
||||
0xb2, 0xd0, 0x60, 0x74, 0x73, 0xdf, 0x26, 0x03, 0x9d, 0x67, 0xed, 0x11, 0xd4, 0x53, 0xf8, 0x13,
|
||||
0xaf, 0xcd, 0x75, 0xc2, 0x7e, 0xa2, 0x96, 0x94, 0xce, 0x48, 0x99, 0x33, 0x48, 0xf7, 0x1b, 0x68,
|
||||
0x24, 0x64, 0xcc, 0x94, 0xa9, 0x72, 0x60, 0xea, 0x06, 0x0c, 0x0b, 0x11, 0x45, 0x46, 0xbd, 0xce,
|
||||
0x81, 0x3f, 0x3c, 0xc0, 0x24, 0x3a, 0x73, 0x03, 0x4a, 0xd5, 0xad, 0x42, 0x37, 0xfa, 0x81, 0x71,
|
||||
0xad, 0x86, 0x00, 0x0f, 0x61, 0xc6, 0x02, 0xd6, 0x73, 0x44, 0xd3, 0x3f, 0x95, 0x60, 0xeb, 0x85,
|
||||
0xeb, 0xd9, 0x43, 0xf7, 0x86, 0x65, 0xe2, 0xe8, 0x8c, 0x92, 0xd1, 0xb8, 0xab, 0x94, 0xc0, 0x5d,
|
||||
0xb1, 0x5e, 0x54, 0x4e, 0xf4, 0x22, 0x1c, 0x18, 0x52, 0xb2, 0xcb, 0x51, 0x88, 0xc5, 0x6a, 0xd6,
|
||||
0x94, 0x41, 0x3a, 0xd0, 0xc0, 0x39, 0xa7, 0x9d, 0xf6, 0x7d, 0xee, 0x08, 0xa3, 0x82, 0x8f, 0xd4,
|
||||
0x0c, 0x1e, 0xe9, 0x22, 0xb5, 0x6d, 0xcd, 0x2a, 0x90, 0x27, 0xb0, 0x3e, 0x65, 0x1e, 0x73, 0xee,
|
||||
0x73, 0xc4, 0x6a, 0xcb, 0xe6, 0x46, 0x60, 0xa3, 0xcb, 0xfd, 0xf7, 0x43, 0x76, 0xd9, 0x61, 0xd2,
|
||||
0x76, 0x87, 0xc2, 0x4a, 0x0b, 0x9b, 0xff, 0x6a, 0x40, 0xbd, 0x27, 0x7d, 0x6e, 0x0f, 0xc2, 0x5b,
|
||||
0x90, 0x13, 0x72, 0x00, 0xeb, 0x27, 0x2c, 0x31, 0xda, 0x09, 0xc1, 0x79, 0x96, 0x28, 0xb6, 0x16,
|
||||
0x09, 0x5c, 0xc4, 0xb9, 0xb4, 0x40, 0x7e, 0x09, 0x1b, 0x29, 0xe5, 0xa3, 0x89, 0xfa, 0xde, 0x59,
|
||||
0x53, 0x16, 0xa6, 0xdf, 0x3f, 0x39, 0xda, 0x3f, 0x83, 0xb5, 0x13, 0x16, 0x47, 0x4e, 0x04, 0x94,
|
||||
0x5e, 0x30, 0x46, 0x5a, 0x8d, 0x40, 0x27, 0xb6, 0x4d, 0x0b, 0xe4, 0x7b, 0x68, 0xa8, 0x4f, 0x22,
|
||||
0xce, 0xfa, 0x77, 0xd1, 0x3a, 0xc0, 0x30, 0x67, 0x61, 0x77, 0x5c, 0x71, 0x13, 0x71, 0x54, 0x5a,
|
||||
0x84, 0x16, 0x48, 0x0f, 0x8c, 0x3c, 0x84, 0x47, 0xbe, 0x8e, 0xc0, 0x57, 0x3e, 0xfe, 0x6b, 0xd5,
|
||||
0xd3, 0x08, 0x8d, 0x16, 0xc8, 0x4b, 0x68, 0x66, 0x43, 0x2a, 0xb2, 0x13, 0x49, 0xe7, 0xc1, 0xad,
|
||||
0x56, 0x2d, 0x12, 0xa1, 0x05, 0xf2, 0x06, 0xee, 0xe7, 0x48, 0x23, 0xb6, 0xbc, 0xab, 0x39, 0x13,
|
||||
0x96, 0x63, 0x70, 0x88, 0x34, 0xa3, 0xbd, 0x04, 0x3e, 0x4a, 0xea, 0xfc, 0x00, 0xab, 0x09, 0xb4,
|
||||
0x43, 0x8c, 0x68, 0x37, 0x05, 0x80, 0x92, 0x7a, 0x3f, 0xc2, 0x6a, 0x02, 0xdb, 0x04, 0x7a, 0x59,
|
||||
0x70, 0xa7, 0x85, 0x2f, 0x15, 0xb0, 0x68, 0x81, 0x9c, 0xc3, 0x57, 0xb9, 0x10, 0x87, 0x3c, 0x52,
|
||||
0xa2, 0xb7, 0x21, 0xa0, 0x94, 0xc1, 0x67, 0x98, 0x56, 0xc9, 0x36, 0x46, 0x36, 0x66, 0xfa, 0xfc,
|
||||
0x69, 0xc7, 0x6c, 0x65, 0x35, 0x55, 0x7c, 0x50, 0x32, 0x33, 0xd0, 0x4c, 0xb2, 0xa5, 0x4c, 0xe4,
|
||||
0x0d, 0xba, 0x16, 0x99, 0x1d, 0x24, 0xb4, 0x40, 0xde, 0xe1, 0x68, 0xcc, 0xea, 0xf3, 0x26, 0xa1,
|
||||
0xda, 0xde, 0x9c, 0x7f, 0x02, 0x79, 0x01, 0x3e, 0xd1, 0x79, 0x92, 0x39, 0x40, 0xcc, 0xcc, 0x9a,
|
||||
0x4f, 0x3c, 0xd6, 0x1f, 0x60, 0x6b, 0x0e, 0xf6, 0x30, 0xc9, 0x63, 0x1d, 0xda, 0x2d, 0xe8, 0x24,
|
||||
0xe7, 0xd0, 0x6f, 0x75, 0x74, 0x99, 0xdf, 0x03, 0x26, 0xf9, 0x26, 0x8a, 0x64, 0xde, 0x07, 0x43,
|
||||
0x32, 0x60, 0x0b, 0xe1, 0xcd, 0x45, 0x96, 0xb9, 0x9d, 0x78, 0xac, 0x77, 0x09, 0xf3, 0x00, 0xd6,
|
||||
0xcf, 0xd8, 0x75, 0xaa, 0x59, 0xce, 0xb4, 0xb6, 0x9c, 0x76, 0xf7, 0x23, 0x90, 0xe0, 0xab, 0xfc,
|
||||
0x56, 0xfd, 0xe5, 0x80, 0x77, 0x7c, 0x39, 0x92, 0x13, 0x5a, 0x20, 0xa7, 0xb0, 0x96, 0x84, 0x9e,
|
||||
0xe4, 0x2b, 0x8c, 0x2e, 0x0b, 0xfb, 0xb6, 0x5a, 0x59, 0x5b, 0x7a, 0x0e, 0x16, 0xc8, 0xaf, 0xa0,
|
||||
0xa1, 0x40, 0x44, 0xb2, 0x7f, 0xce, 0xb1, 0x96, 0x8a, 0x64, 0x1f, 0x6a, 0x11, 0xce, 0xd7, 0xf5,
|
||||
0x91, 0x82, 0xfd, 0x69, 0x8d, 0x03, 0x68, 0x76, 0x98, 0xdd, 0x97, 0xee, 0xd5, 0xec, 0xc1, 0x67,
|
||||
0x33, 0x2e, 0xa5, 0xfc, 0x18, 0xaa, 0x67, 0xec, 0x1a, 0x93, 0x89, 0xe8, 0x2d, 0x24, 0x5a, 0x71,
|
||||
0x02, 0xc3, 0x22, 0x3d, 0x8d, 0x64, 0xbb, 0xdc, 0xef, 0x33, 0x21, 0x5c, 0x6f, 0x90, 0xa9, 0x11,
|
||||
0x5a, 0xfe, 0x29, 0xac, 0x86, 0x1a, 0x38, 0x1b, 0x6f, 0x13, 0x0e, 0xd1, 0x43, 0x7e, 0x2c, 0x53,
|
||||
0xe1, 0x6a, 0x88, 0xaa, 0x09, 0x76, 0xfe, 0xf8, 0x37, 0x40, 0x3a, 0xf0, 0x27, 0x50, 0x4f, 0x43,
|
||||
0x70, 0x72, 0x5f, 0x27, 0x67, 0x16, 0x30, 0x4f, 0xeb, 0x3f, 0x83, 0xc6, 0x0c, 0xa8, 0x0a, 0x9a,
|
||||
0x4e, 0x1e, 0xd6, 0x4a, 0x87, 0x6b, 0x01, 0x39, 0x63, 0xd7, 0xe9, 0x02, 0xf9, 0x5a, 0x3f, 0xed,
|
||||
0x3c, 0xb4, 0x19, 0x4c, 0xcc, 0x19, 0xe8, 0x87, 0xf9, 0xda, 0xcc, 0x44, 0x5b, 0x26, 0x69, 0x63,
|
||||
0x83, 0x9f, 0x83, 0xc4, 0xd2, 0xe1, 0x3d, 0x05, 0x63, 0x9a, 0x3e, 0xff, 0x51, 0x7f, 0x4e, 0x1a,
|
||||
0x38, 0x5a, 0xfa, 0x7d, 0x05, 0x7f, 0xd9, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xd6, 0x49,
|
||||
0xb0, 0xe1, 0x15, 0x00, 0x00,
|
||||
0xbe, 0x2e, 0xd0, 0x3e, 0x41, 0x51, 0xa0, 0x37, 0x7d, 0x8e, 0xbe, 0x44, 0x5f, 0xa9, 0x98, 0xc3,
|
||||
0x21, 0x45, 0x52, 0xa4, 0x5c, 0xa3, 0x45, 0xef, 0xe6, 0x9c, 0x39, 0x7f, 0x33, 0x73, 0x7e, 0x3e,
|
||||
0x12, 0x1a, 0xc2, 0xfe, 0x6e, 0xc4, 0x7d, 0xe9, 0x7f, 0x27, 0xec, 0x3d, 0x5c, 0x90, 0x92, 0xb0,
|
||||
0x5b, 0x9b, 0x7d, 0x9f, 0x33, 0xbd, 0xa1, 0x96, 0xc1, 0x16, 0x6d, 0xc3, 0x9a, 0xc5, 0x06, 0xae,
|
||||
0x90, 0xdc, 0x96, 0xae, 0xef, 0x9d, 0x76, 0xc8, 0x1a, 0x94, 0x5c, 0xc7, 0x28, 0xb6, 0x8b, 0xbb,
|
||||
0x65, 0xab, 0xe4, 0x3a, 0xf4, 0x01, 0xc0, 0xab, 0xde, 0xf9, 0xd9, 0x6f, 0xd9, 0xfb, 0x5f, 0xb3,
|
||||
0x09, 0xa9, 0x43, 0xf9, 0x8f, 0xd7, 0x9f, 0x70, 0x7b, 0xc5, 0x52, 0x4b, 0xba, 0x03, 0xeb, 0x87,
|
||||
0x63, 0xf9, 0xd1, 0xe7, 0xee, 0xcd, 0xac, 0x89, 0x1a, 0x9a, 0xf8, 0x67, 0x11, 0x1e, 0x9c, 0x30,
|
||||
0xd9, 0x65, 0x9e, 0xe3, 0x7a, 0x83, 0x84, 0xb4, 0xc5, 0x3e, 0x8f, 0x99, 0x90, 0xe4, 0x31, 0xac,
|
||||
0xf1, 0x44, 0x1c, 0x3a, 0x82, 0x14, 0x57, 0xc9, 0xb9, 0x0e, 0xf3, 0xa4, 0xfb, 0xc1, 0x65, 0xfc,
|
||||
0x37, 0x93, 0x11, 0x33, 0x4a, 0xe8, 0x26, 0xc5, 0x25, 0xbb, 0xb0, 0x3e, 0xe5, 0x5c, 0xd8, 0xc3,
|
||||
0x31, 0x33, 0xca, 0x28, 0x98, 0x66, 0x93, 0x07, 0x00, 0x57, 0xf6, 0xd0, 0x75, 0xde, 0x79, 0xd2,
|
||||
0x1d, 0x1a, 0x0b, 0xe8, 0x35, 0xc6, 0xa1, 0x02, 0xb6, 0x4f, 0x98, 0xbc, 0x50, 0x8c, 0x44, 0xe4,
|
||||
0xe2, 0xae, 0xa1, 0x1b, 0xb0, 0xe4, 0xf8, 0x97, 0xb6, 0xeb, 0x09, 0xa3, 0xd4, 0x2e, 0xef, 0xd6,
|
||||
0xac, 0x90, 0x54, 0x97, 0xea, 0xf9, 0xd7, 0x18, 0x60, 0xd9, 0x52, 0x4b, 0xfa, 0x8f, 0x22, 0xdc,
|
||||
0xcb, 0x70, 0x49, 0x7e, 0x01, 0x15, 0x0c, 0xcd, 0x28, 0xb6, 0xcb, 0xbb, 0xcb, 0x26, 0xdd, 0x13,
|
||||
0xf6, 0x5e, 0x86, 0xdc, 0xde, 0x1b, 0x7b, 0x74, 0x3c, 0x64, 0x97, 0xcc, 0x93, 0x56, 0xa0, 0xd0,
|
||||
0x3a, 0x07, 0x98, 0x32, 0x49, 0x13, 0x16, 0x03, 0xe7, 0xfa, 0x95, 0x34, 0x45, 0xbe, 0x85, 0x8a,
|
||||
0x3d, 0x96, 0x1f, 0x6f, 0xf0, 0x56, 0x97, 0xcd, 0x7b, 0x7b, 0x98, 0x2a, 0xc9, 0x17, 0x0b, 0x24,
|
||||
0xe8, 0xbf, 0x4a, 0xd0, 0x78, 0xce, 0xb8, 0xba, 0xca, 0xbe, 0x2d, 0x59, 0x4f, 0xda, 0x72, 0x2c,
|
||||
0x94, 0x61, 0xc1, 0xb8, 0x6b, 0x0f, 0x43, 0xc3, 0x01, 0x85, 0x7c, 0x94, 0xd0, 0xcf, 0xa0, 0x29,
|
||||
0xf5, 0x4e, 0x7e, 0x5f, 0x8c, 0x5e, 0xdb, 0x42, 0xbe, 0x1b, 0x39, 0xb6, 0x64, 0x8e, 0x7e, 0x82,
|
||||
0x34, 0x9b, 0xb4, 0x61, 0x99, 0xb3, 0x2b, 0xff, 0x13, 0x73, 0x3a, 0xb6, 0x64, 0x46, 0x05, 0xa5,
|
||||
0xe2, 0x2c, 0xf2, 0x08, 0x56, 0x35, 0x69, 0x31, 0x5b, 0xf8, 0x9e, 0xb1, 0x88, 0x32, 0x49, 0x26,
|
||||
0xf9, 0x1e, 0x36, 0x87, 0xb6, 0x90, 0xc7, 0x5f, 0x46, 0x6e, 0xf0, 0x34, 0x67, 0xf6, 0xa0, 0xc7,
|
||||
0x3c, 0x69, 0x2c, 0xa1, 0x74, 0xf6, 0x26, 0xa1, 0xb0, 0xa2, 0x02, 0xb2, 0x98, 0x18, 0xf9, 0x9e,
|
||||
0x60, 0x46, 0x15, 0x0b, 0x20, 0xc1, 0x23, 0x2d, 0xa8, 0x7a, 0xbe, 0x3c, 0xfc, 0x20, 0x19, 0x37,
|
||||
0x6a, 0x68, 0x2c, 0xa2, 0xc9, 0x16, 0xd4, 0x5c, 0x81, 0x66, 0x99, 0x63, 0x40, 0xbb, 0xb8, 0x5b,
|
||||
0xb5, 0xa6, 0x8c, 0x57, 0x0b, 0xd5, 0x52, 0xbd, 0x4c, 0xdb, 0xb0, 0xd8, 0x9b, 0xde, 0x56, 0xc6,
|
||||
0x2d, 0xd2, 0x03, 0xa8, 0x58, 0xb6, 0x37, 0x40, 0x57, 0xcc, 0xe6, 0x43, 0x97, 0x09, 0xa9, 0xb3,
|
||||
0x2d, 0xa2, 0x95, 0xf2, 0xd0, 0x96, 0x6a, 0xa7, 0x84, 0x3b, 0x9a, 0xa2, 0xdb, 0x50, 0x79, 0xee,
|
||||
0x8f, 0x3d, 0x49, 0x36, 0xa0, 0xd2, 0x57, 0x0b, 0xad, 0x19, 0x10, 0xf4, 0x77, 0xf0, 0x10, 0xb7,
|
||||
0x63, 0x6f, 0x2a, 0x8e, 0x26, 0x67, 0xf6, 0x25, 0x8b, 0x32, 0xfd, 0x21, 0x54, 0xb8, 0x72, 0x8f,
|
||||
0x8a, 0xcb, 0x66, 0x4d, 0x65, 0x1f, 0xc6, 0x63, 0x05, 0x7c, 0x65, 0xd9, 0x53, 0x0a, 0x3a, 0xc1,
|
||||
0x03, 0x82, 0xfe, 0xb9, 0x08, 0x2b, 0x68, 0x5a, 0x9b, 0x23, 0x4f, 0x61, 0xa5, 0x1f, 0xa3, 0x75,
|
||||
0x32, 0xdf, 0x57, 0xe6, 0xe2, 0x72, 0xf1, 0x2c, 0x4e, 0x28, 0xb4, 0x7e, 0x48, 0x24, 0x33, 0x81,
|
||||
0x05, 0xe5, 0x48, 0xdf, 0x15, 0xae, 0xa7, 0x67, 0x2c, 0xc5, 0xcf, 0xd8, 0x85, 0x6d, 0x74, 0x10,
|
||||
0x6f, 0x79, 0xe2, 0x68, 0x72, 0xda, 0x0d, 0x4f, 0xa8, 0x3a, 0xd7, 0x48, 0x77, 0xb7, 0x92, 0x3b,
|
||||
0x9a, 0x9e, 0xb8, 0x94, 0x7d, 0x62, 0xfa, 0x97, 0x22, 0xec, 0xa0, 0xc9, 0x53, 0xef, 0xea, 0xbf,
|
||||
0x6f, 0x11, 0x2d, 0xa8, 0x7e, 0xf4, 0x85, 0xc4, 0xd3, 0x04, 0x7d, 0x2d, 0xa2, 0xa7, 0xa1, 0x94,
|
||||
0x73, 0x42, 0xe9, 0x01, 0xc1, 0x48, 0xce, 0xb9, 0xc3, 0x78, 0xe4, 0x7a, 0x0b, 0x6a, 0x76, 0x1f,
|
||||
0x4f, 0x1f, 0x79, 0x9d, 0x32, 0x6e, 0x3f, 0xdf, 0x4b, 0xd8, 0x40, 0xa3, 0x2f, 0xde, 0x76, 0xce,
|
||||
0x7a, 0x4c, 0x46, 0x66, 0x9b, 0xb0, 0x78, 0xed, 0x7a, 0x8e, 0x7f, 0xad, 0x6d, 0x6a, 0x2a, 0xbf,
|
||||
0xc9, 0xd1, 0x7d, 0xd8, 0xd0, 0x46, 0x8e, 0xbf, 0xb8, 0x62, 0x6a, 0x29, 0xa6, 0x51, 0x4c, 0x6a,
|
||||
0x74, 0xa1, 0xdd, 0xe5, 0xec, 0xca, 0xf5, 0xc7, 0x22, 0x96, 0x94, 0x49, 0xed, 0xbc, 0x46, 0xb6,
|
||||
0x01, 0x15, 0xce, 0x06, 0xa7, 0x9d, 0xf0, 0xfd, 0x91, 0x50, 0x15, 0x16, 0xa8, 0x2b, 0x3d, 0x86,
|
||||
0x2b, 0xd4, 0xab, 0x5a, 0x9a, 0xa2, 0x12, 0xea, 0x87, 0x8e, 0x13, 0x94, 0x61, 0xe8, 0x23, 0xb2,
|
||||
0x55, 0x8c, 0xd9, 0x8a, 0xd5, 0x68, 0x29, 0xd1, 0xe9, 0x0c, 0x58, 0xea, 0x73, 0x86, 0x9d, 0x2c,
|
||||
0x68, 0xe8, 0x21, 0xa9, 0x76, 0x18, 0x16, 0xbc, 0xd0, 0x3d, 0x2e, 0x24, 0x55, 0x85, 0x6c, 0x1e,
|
||||
0x3a, 0x4e, 0xec, 0x94, 0xa1, 0xef, 0x3a, 0x94, 0x1d, 0xc6, 0xc3, 0x79, 0xeb, 0x30, 0x9e, 0x7d,
|
||||
0x32, 0x55, 0x03, 0xaa, 0x17, 0xa1, 0xcb, 0x15, 0x0b, 0xd7, 0x2a, 0x42, 0x57, 0x88, 0x71, 0xd4,
|
||||
0x52, 0x35, 0xa5, 0xb2, 0x0c, 0x57, 0xfc, 0xb4, 0xa3, 0xdb, 0x68, 0x44, 0xd3, 0x7d, 0x68, 0xa6,
|
||||
0x03, 0xd1, 0xdd, 0x4d, 0xdd, 0xb4, 0x3b, 0x08, 0x1b, 0x8e, 0xba, 0x69, 0xa4, 0x68, 0x17, 0x56,
|
||||
0x30, 0xe3, 0xe2, 0x25, 0x14, 0xc3, 0x0f, 0x64, 0x1f, 0xee, 0x8d, 0x05, 0xbb, 0x30, 0x93, 0x95,
|
||||
0x81, 0xd1, 0x57, 0xad, 0xac, 0x2d, 0xfa, 0x1a, 0x68, 0x38, 0x71, 0xd1, 0x72, 0x76, 0x4d, 0xa5,
|
||||
0xfd, 0x34, 0x61, 0xd1, 0xee, 0xf7, 0x65, 0x74, 0x31, 0x9a, 0xa2, 0x13, 0xf8, 0xc9, 0x09, 0x0b,
|
||||
0x8a, 0xe2, 0x85, 0xcf, 0x13, 0xfd, 0x6c, 0xaa, 0x52, 0x8c, 0xab, 0x64, 0xb7, 0xb1, 0xbc, 0x83,
|
||||
0x94, 0xf3, 0x0f, 0xf2, 0xb7, 0x22, 0x18, 0x27, 0x4c, 0xfe, 0xdf, 0x60, 0x83, 0x9a, 0xa6, 0x9c,
|
||||
0x7d, 0x1e, 0xbb, 0x5c, 0xc7, 0x72, 0x13, 0x64, 0x5a, 0xd5, 0x4a, 0xb3, 0xe9, 0x5f, 0x8b, 0xb0,
|
||||
0x96, 0xc2, 0x16, 0x3f, 0x0f, 0x67, 0x7f, 0xd0, 0x8e, 0xb7, 0x55, 0x2f, 0x98, 0x03, 0x2b, 0x50,
|
||||
0xf6, 0x7f, 0x0f, 0x2b, 0x5e, 0xc3, 0xc3, 0x43, 0xc7, 0xc9, 0x82, 0x8a, 0xd1, 0xcd, 0x7d, 0x9b,
|
||||
0x0c, 0x74, 0x9e, 0xb5, 0x47, 0x50, 0x4f, 0x81, 0x53, 0xbc, 0x36, 0xd7, 0x09, 0x9b, 0x8d, 0x5a,
|
||||
0x52, 0x3a, 0x23, 0x65, 0xce, 0xc0, 0xe0, 0x6f, 0xa0, 0x91, 0x90, 0x31, 0x53, 0xa6, 0xca, 0x81,
|
||||
0xa9, 0x1b, 0x30, 0x2c, 0x84, 0x1b, 0x19, 0xb5, 0x3c, 0x07, 0x1b, 0xf1, 0x00, 0xb0, 0xe8, 0xcc,
|
||||
0x0d, 0x28, 0x55, 0xd3, 0x0a, 0xfa, 0xe8, 0x07, 0xc6, 0xb5, 0xaa, 0x5d, 0x1e, 0x62, 0x90, 0x05,
|
||||
0xac, 0xf5, 0x88, 0xa6, 0x7f, 0x2a, 0xc1, 0xd6, 0x0b, 0xd7, 0xb3, 0x87, 0xee, 0x0d, 0xcb, 0x04,
|
||||
0xd9, 0x19, 0x25, 0xa3, 0x41, 0x59, 0x29, 0x01, 0xca, 0x62, 0x8d, 0xaa, 0x9c, 0x68, 0x54, 0x38,
|
||||
0x4d, 0xa4, 0x64, 0x97, 0xa3, 0x10, 0xa8, 0xd5, 0xac, 0x29, 0x83, 0x74, 0xa0, 0x81, 0x43, 0x50,
|
||||
0x3b, 0xed, 0xfb, 0xdc, 0x11, 0x46, 0x05, 0x1f, 0xa9, 0x19, 0x3c, 0xd2, 0x45, 0x6a, 0xdb, 0x9a,
|
||||
0x55, 0x20, 0x4f, 0x60, 0x7d, 0xca, 0x3c, 0xe6, 0xdc, 0xe7, 0x08, 0xe4, 0x96, 0xcd, 0x8d, 0xc0,
|
||||
0x46, 0x97, 0xfb, 0xef, 0x87, 0xec, 0xb2, 0xc3, 0xa4, 0xed, 0x0e, 0x85, 0x95, 0x16, 0x36, 0xff,
|
||||
0x4e, 0xa0, 0xde, 0x93, 0x3e, 0xb7, 0x07, 0xe1, 0x2d, 0xc8, 0x09, 0x39, 0x80, 0xf5, 0x13, 0x96,
|
||||
0x98, 0xfb, 0x84, 0xe0, 0xb0, 0x4b, 0x14, 0x5b, 0x8b, 0x04, 0x2e, 0xe2, 0x5c, 0x5a, 0x20, 0xbf,
|
||||
0x84, 0x8d, 0x94, 0xf2, 0xd1, 0x44, 0x7d, 0x0c, 0xad, 0x29, 0x0b, 0xd3, 0x8f, 0xa3, 0x1c, 0xed,
|
||||
0x9f, 0xc1, 0xda, 0x09, 0x8b, 0xc3, 0x2a, 0x02, 0x4a, 0x2f, 0x98, 0x31, 0xad, 0x46, 0xa0, 0x13,
|
||||
0xdb, 0xa6, 0x05, 0xf2, 0x3d, 0x34, 0xd4, 0xf7, 0x12, 0x67, 0xfd, 0xbb, 0x68, 0x1d, 0x60, 0x98,
|
||||
0xb3, 0x98, 0x3c, 0xae, 0xb8, 0x89, 0x20, 0x2b, 0x2d, 0x42, 0x0b, 0xa4, 0x07, 0x46, 0x1e, 0xfc,
|
||||
0x23, 0x5f, 0x47, 0xc8, 0x2c, 0x1f, 0x1c, 0xb6, 0xea, 0x69, 0xf8, 0x46, 0x0b, 0xe4, 0x25, 0x34,
|
||||
0xb3, 0xf1, 0x16, 0xd9, 0x89, 0xa4, 0xf3, 0xb0, 0x58, 0xab, 0x16, 0x89, 0xd0, 0x02, 0x79, 0x03,
|
||||
0xf7, 0x73, 0xa4, 0x11, 0x78, 0xde, 0xd5, 0x9c, 0x09, 0xcb, 0x31, 0xac, 0x44, 0x9a, 0xd1, 0x5e,
|
||||
0x02, 0x3c, 0x25, 0x75, 0x7e, 0x80, 0xd5, 0x04, 0x14, 0x22, 0x46, 0xb4, 0x9b, 0x42, 0x47, 0x49,
|
||||
0xbd, 0x1f, 0x61, 0x35, 0x01, 0x7c, 0x02, 0xbd, 0x2c, 0x2c, 0xd4, 0xc2, 0x97, 0x0a, 0x58, 0xb4,
|
||||
0x40, 0xce, 0xe1, 0xab, 0x5c, 0xfc, 0x43, 0x1e, 0x29, 0xd1, 0xdb, 0xe0, 0x51, 0xca, 0xe0, 0x33,
|
||||
0x4c, 0xab, 0x64, 0x1b, 0x23, 0x1b, 0x33, 0x7d, 0xfe, 0xb4, 0x63, 0xb6, 0xb2, 0x9a, 0x2a, 0x3e,
|
||||
0x28, 0x99, 0x19, 0x68, 0x26, 0xd9, 0x52, 0x26, 0xf2, 0x06, 0x5d, 0x8b, 0xcc, 0x0e, 0x12, 0x5a,
|
||||
0x20, 0xef, 0x70, 0x34, 0x66, 0xf5, 0x79, 0x93, 0x50, 0x6d, 0x6f, 0xce, 0x0f, 0x83, 0xbc, 0x00,
|
||||
0x9f, 0xe8, 0x3c, 0xc9, 0x1c, 0x20, 0x66, 0x66, 0xcd, 0x27, 0x1e, 0xeb, 0x0f, 0xb0, 0x35, 0x07,
|
||||
0x7b, 0x98, 0xe4, 0xb1, 0x0e, 0xed, 0x16, 0x74, 0x92, 0x73, 0xe8, 0xb7, 0x3a, 0xba, 0xcc, 0x8f,
|
||||
0x05, 0x93, 0x7c, 0x13, 0x45, 0x32, 0xef, 0x6b, 0x22, 0x19, 0xb0, 0x85, 0xf0, 0xe6, 0x22, 0xcb,
|
||||
0xdc, 0x4e, 0x3c, 0xd6, 0xbb, 0x84, 0x79, 0x00, 0xeb, 0x67, 0xec, 0x3a, 0xd5, 0x2c, 0x67, 0x5a,
|
||||
0x5b, 0x4e, 0xbb, 0xfb, 0x11, 0x48, 0xf0, 0xc9, 0x7e, 0xab, 0xfe, 0x72, 0xc0, 0x3b, 0xbe, 0x1c,
|
||||
0xc9, 0x09, 0x2d, 0x90, 0x53, 0x58, 0x4b, 0x42, 0x4f, 0xf2, 0x15, 0x46, 0x97, 0x85, 0x8b, 0x5b,
|
||||
0xad, 0xac, 0x2d, 0x3d, 0x07, 0x0b, 0xe4, 0x57, 0xd0, 0x50, 0x20, 0x22, 0xd9, 0x3f, 0xe7, 0x58,
|
||||
0x4b, 0x45, 0xb2, 0x0f, 0xb5, 0xe8, 0x23, 0x40, 0xd7, 0x47, 0xea, 0x9b, 0x20, 0xad, 0x71, 0x00,
|
||||
0xcd, 0x0e, 0xb3, 0xfb, 0xd2, 0xbd, 0x9a, 0x3d, 0xf8, 0x6c, 0xc6, 0xa5, 0x94, 0x1f, 0x43, 0xf5,
|
||||
0x8c, 0x5d, 0x63, 0x32, 0x11, 0xbd, 0x85, 0x44, 0x2b, 0x4e, 0x60, 0x58, 0xa4, 0xa7, 0x91, 0x6c,
|
||||
0x97, 0xfb, 0x7d, 0x26, 0x84, 0xeb, 0x0d, 0x32, 0x35, 0x42, 0xcb, 0x3f, 0x85, 0xd5, 0x50, 0x03,
|
||||
0x67, 0xe3, 0x6d, 0xc2, 0x21, 0x7a, 0xc8, 0x8f, 0x65, 0x2a, 0x5c, 0x0d, 0x51, 0x35, 0xc1, 0xce,
|
||||
0x1f, 0xff, 0x06, 0x48, 0x07, 0xfe, 0x04, 0xea, 0x69, 0x08, 0x4e, 0xee, 0xeb, 0xe4, 0xcc, 0x02,
|
||||
0xe6, 0x69, 0xfd, 0x67, 0xd0, 0x98, 0x01, 0x55, 0x41, 0xd3, 0xc9, 0xc3, 0x5a, 0xe9, 0x70, 0x2d,
|
||||
0x20, 0x67, 0xec, 0x3a, 0x5d, 0x20, 0x5f, 0xeb, 0xa7, 0x9d, 0x87, 0x36, 0x83, 0x89, 0x39, 0x03,
|
||||
0xfd, 0x30, 0x5f, 0x9b, 0x99, 0x68, 0xcb, 0x24, 0x6d, 0x6c, 0xf0, 0x73, 0x90, 0x58, 0x3a, 0xbc,
|
||||
0xa7, 0x60, 0x4c, 0xd3, 0xe7, 0x3f, 0xea, 0xcf, 0x29, 0x03, 0xbb, 0xb0, 0x12, 0xe4, 0xa7, 0x9e,
|
||||
0x0e, 0xf1, 0x91, 0x9f, 0x98, 0x01, 0x47, 0x4b, 0xbf, 0xaf, 0xe0, 0x9f, 0xdf, 0x7f, 0x07, 0x00,
|
||||
0x00, 0xff, 0xff, 0x71, 0xbc, 0xd9, 0x84, 0x28, 0x16, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
@ -2000,6 +2009,7 @@ type StorageAuthorityClient interface {
|
|||
NewAuthorizations2(ctx context.Context, in *AddPendingAuthorizationsRequest, opts ...grpc.CallOption) (*Authorization2IDs, error)
|
||||
FinalizeAuthorization2(ctx context.Context, in *FinalizeAuthorizationRequest, opts ...grpc.CallOption) (*proto1.Empty, error)
|
||||
DeactivateAuthorization2(ctx context.Context, in *AuthorizationID2, opts ...grpc.CallOption) (*proto1.Empty, error)
|
||||
SerialExists(ctx context.Context, in *Serial, opts ...grpc.CallOption) (*Exists, error)
|
||||
}
|
||||
|
||||
type storageAuthorityClient struct {
|
||||
|
@ -2325,6 +2335,15 @@ func (c *storageAuthorityClient) DeactivateAuthorization2(ctx context.Context, i
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *storageAuthorityClient) SerialExists(ctx context.Context, in *Serial, opts ...grpc.CallOption) (*Exists, error) {
|
||||
out := new(Exists)
|
||||
err := c.cc.Invoke(ctx, "/sa.StorageAuthority/SerialExists", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// StorageAuthorityServer is the server API for StorageAuthority service.
|
||||
type StorageAuthorityServer interface {
|
||||
// Getters
|
||||
|
@ -2366,6 +2385,7 @@ type StorageAuthorityServer interface {
|
|||
NewAuthorizations2(context.Context, *AddPendingAuthorizationsRequest) (*Authorization2IDs, error)
|
||||
FinalizeAuthorization2(context.Context, *FinalizeAuthorizationRequest) (*proto1.Empty, error)
|
||||
DeactivateAuthorization2(context.Context, *AuthorizationID2) (*proto1.Empty, error)
|
||||
SerialExists(context.Context, *Serial) (*Exists, error)
|
||||
}
|
||||
|
||||
// UnimplementedStorageAuthorityServer can be embedded to have forward compatible implementations.
|
||||
|
@ -2477,6 +2497,9 @@ func (*UnimplementedStorageAuthorityServer) FinalizeAuthorization2(ctx context.C
|
|||
func (*UnimplementedStorageAuthorityServer) DeactivateAuthorization2(ctx context.Context, req *AuthorizationID2) (*proto1.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeactivateAuthorization2 not implemented")
|
||||
}
|
||||
func (*UnimplementedStorageAuthorityServer) SerialExists(ctx context.Context, req *Serial) (*Exists, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SerialExists not implemented")
|
||||
}
|
||||
|
||||
func RegisterStorageAuthorityServer(s *grpc.Server, srv StorageAuthorityServer) {
|
||||
s.RegisterService(&_StorageAuthority_serviceDesc, srv)
|
||||
|
@ -3112,6 +3135,24 @@ func _StorageAuthority_DeactivateAuthorization2_Handler(srv interface{}, ctx con
|
|||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _StorageAuthority_SerialExists_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Serial)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(StorageAuthorityServer).SerialExists(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/sa.StorageAuthority/SerialExists",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(StorageAuthorityServer).SerialExists(ctx, req.(*Serial))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _StorageAuthority_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "sa.StorageAuthority",
|
||||
HandlerType: (*StorageAuthorityServer)(nil),
|
||||
|
@ -3256,6 +3297,10 @@ var _StorageAuthority_serviceDesc = grpc.ServiceDesc{
|
|||
MethodName: "DeactivateAuthorization2",
|
||||
Handler: _StorageAuthority_DeactivateAuthorization2_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SerialExists",
|
||||
Handler: _StorageAuthority_SerialExists_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "sa/proto/sa.proto",
|
||||
|
|
|
@ -45,6 +45,7 @@ service StorageAuthority {
|
|||
rpc NewAuthorizations2(AddPendingAuthorizationsRequest) returns (Authorization2IDs) {}
|
||||
rpc FinalizeAuthorization2(FinalizeAuthorizationRequest) returns (core.Empty) {}
|
||||
rpc DeactivateAuthorization2(AuthorizationID2) returns (core.Empty) {}
|
||||
rpc SerialExists(Serial) returns (Exists) {}
|
||||
}
|
||||
|
||||
message RegistrationID {
|
||||
|
@ -172,6 +173,7 @@ message AddCertificateRequest {
|
|||
// the current time. The orphan-finder uses this parameter to add
|
||||
// certificates with the correct historic issued date
|
||||
optional int64 issued = 4;
|
||||
optional int64 issuerID = 5;
|
||||
}
|
||||
|
||||
message AddCertificateResponse {
|
||||
|
|
97
sa/sa.go
97
sa/sa.go
|
@ -363,16 +363,16 @@ func (ssa *SQLStorageAuthority) GetCertificateStatus(ctx context.Context, serial
|
|||
return core.CertificateStatus{}, err
|
||||
}
|
||||
|
||||
var status core.CertificateStatus
|
||||
statusObj, err := ssa.dbMap.WithContext(ctx).Get(certStatusModel{}, serial)
|
||||
statusModel, err := SelectCertificateStatus(
|
||||
ssa.dbMap.WithContext(ctx),
|
||||
"WHERE serial = ?",
|
||||
serial,
|
||||
)
|
||||
if err != nil {
|
||||
return status, err
|
||||
return core.CertificateStatus{}, err
|
||||
}
|
||||
if statusObj == nil {
|
||||
return status, nil
|
||||
}
|
||||
statusModel := statusObj.(*certStatusModel)
|
||||
status = core.CertificateStatus{
|
||||
|
||||
return core.CertificateStatus{
|
||||
Serial: statusModel.Serial,
|
||||
Status: statusModel.Status,
|
||||
OCSPLastUpdated: statusModel.OCSPLastUpdated,
|
||||
|
@ -382,9 +382,7 @@ func (ssa *SQLStorageAuthority) GetCertificateStatus(ctx context.Context, serial
|
|||
OCSPResponse: statusModel.OCSPResponse,
|
||||
NotAfter: statusModel.NotAfter,
|
||||
IsExpired: statusModel.IsExpired,
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewRegistration stores a new Registration
|
||||
|
@ -1571,40 +1569,36 @@ func (ssa *SQLStorageAuthority) FinalizeAuthorization2(ctx context.Context, req
|
|||
// RevokeCertificate stores revocation information about a certificate. It will only store this
|
||||
// information if the certificate is not already marked as revoked.
|
||||
func (ssa *SQLStorageAuthority) RevokeCertificate(ctx context.Context, req *sapb.RevokeCertificateRequest) error {
|
||||
_, overallError := db.WithTransaction(ctx, ssa.dbMap, func(txWithCtx db.Transaction) (interface{}, error) {
|
||||
status, err := SelectCertificateStatus(
|
||||
txWithCtx,
|
||||
"WHERE serial = ? AND status != ?",
|
||||
*req.Serial,
|
||||
string(core.OCSPStatusRevoked),
|
||||
)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
// InternalServerError because we expected this certificate status to exist and
|
||||
// not be revoked.
|
||||
return nil, berrors.InternalServerError("no certificate with serial %s and status %s", *req.Serial, string(core.OCSPStatusRevoked))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
revokedDate := time.Unix(0, *req.Date)
|
||||
status.Status = core.OCSPStatusRevoked
|
||||
status.RevokedReason = revocation.Reason(*req.Reason)
|
||||
status.RevokedDate = revokedDate
|
||||
status.OCSPLastUpdated = revokedDate
|
||||
status.OCSPResponse = req.Response
|
||||
|
||||
n, err := txWithCtx.Update(&status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == 0 {
|
||||
return nil, berrors.InternalServerError("no certificate updated")
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
})
|
||||
return overallError
|
||||
revokedDate := time.Unix(0, *req.Date)
|
||||
res, err := ssa.dbMap.Exec(
|
||||
`UPDATE certificateStatus SET
|
||||
status = ?,
|
||||
revokedReason = ?,
|
||||
revokedDate = ?,
|
||||
ocspLastUpdated = ?,
|
||||
ocspResponse = ?
|
||||
WHERE serial = ? AND status != ?`,
|
||||
string(core.OCSPStatusRevoked),
|
||||
revocation.Reason(*req.Reason),
|
||||
revokedDate,
|
||||
revokedDate,
|
||||
req.Response,
|
||||
*req.Serial,
|
||||
string(core.OCSPStatusRevoked),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rows == 0 {
|
||||
// InternalServerError because we expected this certificate status to exist and
|
||||
// not be revoked.
|
||||
return berrors.InternalServerError("no certificate with serial %s and status %s", *req.Serial, string(core.OCSPStatusRevoked))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPendingAuthorization2 returns the most recent Pending authorization with
|
||||
|
@ -1779,3 +1773,16 @@ func (ssa *SQLStorageAuthority) GetValidAuthorizations2(ctx context.Context, req
|
|||
}
|
||||
return authz2ModelMapToPB(authzMap)
|
||||
}
|
||||
|
||||
// SerialExists returns a bool indicating whether the provided serial
|
||||
// exists in the serial table. This is currently only used to determine
|
||||
// if a serial passed to ca.GenerateOCSP is one which we have previously
|
||||
// generated a certificate for.
|
||||
func (ssa *SQLStorageAuthority) SerialExists(ctx context.Context, req *sapb.Serial) (*sapb.Exists, error) {
|
||||
err := ssa.dbMap.SelectOne(&recordedSerialModel{}, "SELECT * FROM serials WHERE serial = ?", req.Serial)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, err
|
||||
}
|
||||
exists := err != sql.ErrNoRows
|
||||
return &sapb.Exists{Exists: &exists}, nil
|
||||
}
|
||||
|
|
|
@ -2083,3 +2083,26 @@ func TestGetOrderExpired(t *testing.T) {
|
|||
test.AssertError(t, err, "GetOrder didn't fail for an expired order")
|
||||
test.Assert(t, berrors.Is(err, berrors.NotFound), "GetOrder error wasn't of type NotFound")
|
||||
}
|
||||
|
||||
func TestSerialExists(t *testing.T) {
|
||||
sa, _, cleanUp := initSA(t)
|
||||
defer cleanUp()
|
||||
reg := satest.CreateWorkingRegistration(t, sa)
|
||||
|
||||
serial := "asd"
|
||||
resp, err := sa.SerialExists(context.Background(), &sapb.Serial{Serial: &serial})
|
||||
test.AssertNotError(t, err, "SerialExists failed")
|
||||
test.AssertEquals(t, *resp.Exists, false)
|
||||
|
||||
zero := int64(0)
|
||||
_, err = sa.AddSerial(context.Background(), &sapb.AddSerialRequest{
|
||||
RegID: ®.ID,
|
||||
Serial: &serial,
|
||||
Created: &zero,
|
||||
Expires: &zero,
|
||||
})
|
||||
test.AssertNotError(t, err, "AddSerial failed")
|
||||
resp, err = sa.SerialExists(context.Background(), &sapb.Serial{Serial: &serial})
|
||||
test.AssertNotError(t, err, "SerialExists failed")
|
||||
test.AssertEquals(t, *resp.Exists, true)
|
||||
}
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
"maxConcurrentRPCServerRequests": 100000,
|
||||
"orphanQueueDir": "/tmp/orphaned-certificates-a",
|
||||
"features": {
|
||||
"StoreIssuerInfo": true
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@
|
|||
"maxConcurrentRPCServerRequests": 100000,
|
||||
"orphanQueueDir": "/tmp/orphaned-certificates-b",
|
||||
"features": {
|
||||
"StoreIssuerInfo": true
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
"timeout": "15s"
|
||||
},
|
||||
"features": {
|
||||
"StoreIssuerInfo": true
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
"features": {
|
||||
"DeleteUnusedChallenges": true,
|
||||
"FasterGetOrderForNames": true,
|
||||
"GetAuthorizationsPerf": true
|
||||
"GetAuthorizationsPerf": true,
|
||||
"StoreIssuerInfo": true
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ GRANT SELECT,INSERT ON requestedNames TO 'sa'@'localhost';
|
|||
GRANT SELECT,INSERT,DELETE ON orderFqdnSets TO 'sa'@'localhost';
|
||||
GRANT SELECT,INSERT,UPDATE ON authz2 TO 'sa'@'localhost';
|
||||
GRANT SELECT,INSERT ON orderToAuthz2 TO 'sa'@'localhost';
|
||||
GRANT INSERT ON serials TO 'sa'@'localhost';
|
||||
GRANT INSERT,SELECT ON serials TO 'sa'@'localhost';
|
||||
GRANT SELECT,INSERT ON precertificates TO 'sa'@'localhost';
|
||||
|
||||
-- OCSP Responder
|
||||
|
|
Loading…
Reference in New Issue