Update vendored github.com/cloudflare/cfssl (#3078)
This commit is contained in:
parent
94e4947c58
commit
c03d96212b
|
@ -12,73 +12,73 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/auth",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/certdb",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/config",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/csr",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/errors",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/helpers",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/helpers/derhelpers",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/info",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/log",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/ocsp",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/ocsp/config",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/signer",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cloudflare/cfssl/signer/local",
|
||||
"Comment": "1.2.0-169-gc9a961e",
|
||||
"Rev": "c9a961ed337dbde794abb97a2a302320a99869da"
|
||||
"Comment": "1.2.0-195-gb92b544",
|
||||
"Rev": "b92b544a91e70c91d9db888dfc9216197329df30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||
|
|
|
@ -69,11 +69,11 @@ type dbResponse struct {
|
|||
}
|
||||
|
||||
// Response is called by the HTTP server to handle a new OCSP request.
|
||||
func (src *DBSource) Response(req *ocsp.Request) ([]byte, bool) {
|
||||
func (src *DBSource) Response(req *ocsp.Request) ([]byte, http.Header, error) {
|
||||
// Check that this request is for the proper CA
|
||||
if bytes.Compare(req.IssuerKeyHash, src.caKeyHash) != 0 {
|
||||
src.log.Debug(fmt.Sprintf("Request intended for CA Cert ID: %s", hex.EncodeToString(req.IssuerKeyHash)))
|
||||
return nil, false
|
||||
return nil, nil, cfocsp.ErrNotFound
|
||||
}
|
||||
|
||||
serialString := core.SerialToString(req.SerialNumber)
|
||||
|
@ -94,14 +94,14 @@ func (src *DBSource) Response(req *ocsp.Request) ([]byte, bool) {
|
|||
src.log.AuditErr(fmt.Sprintf("Failed to retrieve response from certificateStatus table: %s", err))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, false
|
||||
return nil, nil, cfocsp.ErrNotFound
|
||||
}
|
||||
if response.OCSPLastUpdated.IsZero() {
|
||||
src.log.Debug(fmt.Sprintf("OCSP Response not sent (ocspLastUpdated is zero) for CA=%s, Serial=%s", hex.EncodeToString(src.caKeyHash), serialString))
|
||||
return nil, false
|
||||
return nil, nil, cfocsp.ErrNotFound
|
||||
}
|
||||
|
||||
return response.OCSPResponse, true
|
||||
return response.OCSPResponse, nil, nil
|
||||
}
|
||||
|
||||
func makeDBSource(dbMap dbSelector, issuerCert string, log blog.Logger) (*DBSource, error) {
|
||||
|
|
|
@ -133,8 +133,8 @@ func TestErrorLog(t *testing.T) {
|
|||
ocspReq, err := ocsp.ParseRequest(req)
|
||||
test.AssertNotError(t, err, "Failed to parse OCSP request")
|
||||
|
||||
_, found := src.Response(ocspReq)
|
||||
test.Assert(t, !found, "Somehow found OCSP response")
|
||||
_, _, err = src.Response(ocspReq)
|
||||
test.AssertEquals(t, err, cfocsp.ErrNotFound)
|
||||
|
||||
test.AssertEquals(t, len(mockLog.GetAllMatching("Failed to retrieve response from certificateStatus table")), 1)
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ type Accessor interface {
|
|||
GetCertificate(serial, aki string) ([]CertificateRecord, error)
|
||||
GetUnexpiredCertificates() ([]CertificateRecord, error)
|
||||
GetRevokedAndUnexpiredCertificates() ([]CertificateRecord, error)
|
||||
GetRevokedAndUnexpiredCertificatesByLabel(label string) ([]CertificateRecord, error)
|
||||
RevokeCertificate(serial, aki string, reasonCode int) error
|
||||
InsertOCSP(rr OCSPRecord) error
|
||||
GetOCSP(serial, aki string) ([]OCSPRecord, error)
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/google/certificate-transparency-go"
|
||||
|
@ -383,51 +382,6 @@ func GetKeyDERFromPEM(in []byte, password []byte) ([]byte, error) {
|
|||
return nil, cferr.New(cferr.PrivateKeyError, cferr.DecodeFailed)
|
||||
}
|
||||
|
||||
// CheckSignature verifies a signature made by the key on a CSR, such
|
||||
// as on the CSR itself.
|
||||
func CheckSignature(csr *x509.CertificateRequest, algo x509.SignatureAlgorithm, signed, signature []byte) error {
|
||||
var hashType crypto.Hash
|
||||
|
||||
switch algo {
|
||||
case x509.SHA1WithRSA, x509.ECDSAWithSHA1:
|
||||
hashType = crypto.SHA1
|
||||
case x509.SHA256WithRSA, x509.ECDSAWithSHA256:
|
||||
hashType = crypto.SHA256
|
||||
case x509.SHA384WithRSA, x509.ECDSAWithSHA384:
|
||||
hashType = crypto.SHA384
|
||||
case x509.SHA512WithRSA, x509.ECDSAWithSHA512:
|
||||
hashType = crypto.SHA512
|
||||
default:
|
||||
return x509.ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if !hashType.Available() {
|
||||
return x509.ErrUnsupportedAlgorithm
|
||||
}
|
||||
h := hashType.New()
|
||||
|
||||
h.Write(signed)
|
||||
digest := h.Sum(nil)
|
||||
|
||||
switch pub := csr.PublicKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
return rsa.VerifyPKCS1v15(pub, hashType, digest, signature)
|
||||
case *ecdsa.PublicKey:
|
||||
ecdsaSig := new(struct{ R, S *big.Int })
|
||||
if _, err := asn1.Unmarshal(signature, ecdsaSig); err != nil {
|
||||
return err
|
||||
}
|
||||
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
|
||||
return errors.New("x509: ECDSA signature contained zero or negative values")
|
||||
}
|
||||
if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) {
|
||||
return errors.New("x509: ECDSA verification failure")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return x509.ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
// ParseCSR parses a PEM- or DER-encoded PKCS #10 certificate signing request.
|
||||
func ParseCSR(in []byte) (csr *x509.CertificateRequest, rest []byte, err error) {
|
||||
in = bytes.TrimSpace(in)
|
||||
|
@ -446,7 +400,7 @@ func ParseCSR(in []byte) (csr *x509.CertificateRequest, rest []byte, err error)
|
|||
return nil, rest, err
|
||||
}
|
||||
|
||||
err = CheckSignature(csr, csr.SignatureAlgorithm, csr.RawTBSCertificateRequest, csr.Signature)
|
||||
err = csr.CheckSignature()
|
||||
if err != nil {
|
||||
return nil, rest, err
|
||||
}
|
||||
|
|
|
@ -58,6 +58,10 @@ type SignRequest struct {
|
|||
// in the OCSP response. Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384,
|
||||
// and crypto.SHA512. If zero, the default is crypto.SHA1.
|
||||
IssuerHash crypto.Hash
|
||||
// If provided ThisUpdate will override the default usage of time.Now().Truncate(time.Hour)
|
||||
ThisUpdate *time.Time
|
||||
// If provided NextUpdate will override the default usage of ThisUpdate.Add(signerInterval)
|
||||
NextUpdate *time.Time
|
||||
}
|
||||
|
||||
// Signer represents a general signer of OCSP responses. It is
|
||||
|
@ -164,9 +168,18 @@ func (s StandardSigner) Sign(req SignRequest) ([]byte, error) {
|
|||
return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch)
|
||||
}
|
||||
|
||||
// Round thisUpdate times down to the nearest hour
|
||||
thisUpdate := time.Now().Truncate(time.Hour)
|
||||
nextUpdate := thisUpdate.Add(s.interval)
|
||||
var thisUpdate, nextUpdate time.Time
|
||||
if req.ThisUpdate != nil {
|
||||
thisUpdate = *req.ThisUpdate
|
||||
} else {
|
||||
// Round thisUpdate times down to the nearest hour
|
||||
thisUpdate = time.Now().Truncate(time.Hour)
|
||||
}
|
||||
if req.NextUpdate != nil {
|
||||
nextUpdate = *req.NextUpdate
|
||||
} else {
|
||||
nextUpdate = thisUpdate.Add(s.interval)
|
||||
}
|
||||
|
||||
status, ok := StatusCode[req.Status]
|
||||
if !ok {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -30,14 +31,25 @@ var (
|
|||
tryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03}
|
||||
sigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05}
|
||||
unauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06}
|
||||
|
||||
// ErrNotFound indicates the request OCSP response was not found. It is used to
|
||||
// indicate that the responder should reply with unauthorizedErrorResponse.
|
||||
ErrNotFound = errors.New("Request OCSP Response not found")
|
||||
)
|
||||
|
||||
// Source represents the logical source of OCSP responses, i.e.,
|
||||
// the logic that actually chooses a response based on a request. In
|
||||
// order to create an actual responder, wrap one of these in a Responder
|
||||
// object and pass it to http.Handle.
|
||||
// object and pass it to http.Handle. By default the Responder will set
|
||||
// the headers Cache-Control to "max-age=(response.NextUpdate-now), public, no-transform, must-revalidate",
|
||||
// Last-Modified to response.ThisUpdate, Expires to response.NextUpdate,
|
||||
// ETag to the SHA256 hash of the response, and Content-Type to
|
||||
// application/ocsp-response. If you want to override these headers,
|
||||
// or set extra headers, your source should return a http.Header
|
||||
// with the headers you wish to set. If you don't want to set any
|
||||
// extra headers you may return nil instead.
|
||||
type Source interface {
|
||||
Response(*ocsp.Request) ([]byte, bool)
|
||||
Response(*ocsp.Request) ([]byte, http.Header, error)
|
||||
}
|
||||
|
||||
// An InMemorySource is a map from serialNumber -> der(response)
|
||||
|
@ -46,9 +58,12 @@ type InMemorySource map[string][]byte
|
|||
// Response looks up an OCSP response to provide for a given request.
|
||||
// InMemorySource looks up a response purely based on serial number,
|
||||
// without regard to what issuer the request is asking for.
|
||||
func (src InMemorySource) Response(request *ocsp.Request) (response []byte, present bool) {
|
||||
response, present = src[request.SerialNumber.String()]
|
||||
return
|
||||
func (src InMemorySource) Response(request *ocsp.Request) ([]byte, http.Header, error) {
|
||||
response, present := src[request.SerialNumber.String()]
|
||||
if !present {
|
||||
return nil, nil, ErrNotFound
|
||||
}
|
||||
return response, nil, nil
|
||||
}
|
||||
|
||||
// DBSource represnts a source of OCSP responses backed by the certdb package.
|
||||
|
@ -65,26 +80,23 @@ func NewDBSource(dbAccessor certdb.Accessor) Source {
|
|||
|
||||
// Response implements cfssl.ocsp.responder.Source, which returns the
|
||||
// OCSP response in the Database for the given request with the expiration
|
||||
// date furthest in the future. Response also returns a bool that is false
|
||||
// if there were any errors obtaining the OCSP response and/or no OCSP response
|
||||
// is present in the DB for the given request. Response will return a true
|
||||
// bool if the byte array returned is a valid OCSP response.
|
||||
func (src DBSource) Response(req *ocsp.Request) ([]byte, bool) {
|
||||
// date furthest in the future.
|
||||
func (src DBSource) Response(req *ocsp.Request) ([]byte, http.Header, error) {
|
||||
if req == nil {
|
||||
return nil, false
|
||||
return nil, nil, errors.New("called with nil request")
|
||||
}
|
||||
|
||||
aki := hex.EncodeToString(req.IssuerKeyHash)
|
||||
sn := req.SerialNumber
|
||||
|
||||
if sn == nil {
|
||||
return nil, false
|
||||
return nil, nil, errors.New("request contains no serial")
|
||||
}
|
||||
strSN := sn.String()
|
||||
|
||||
if src.Accessor == nil {
|
||||
log.Errorf("No DB Accessor")
|
||||
return nil, false
|
||||
return nil, nil, errors.New("called with nil DB accessor")
|
||||
}
|
||||
records, err := src.Accessor.GetOCSP(strSN, aki)
|
||||
|
||||
|
@ -92,11 +104,11 @@ func (src DBSource) Response(req *ocsp.Request) ([]byte, bool) {
|
|||
// and returns nil, false.
|
||||
if err != nil {
|
||||
log.Errorf("Error obtaining OCSP response: %s", err)
|
||||
return nil, false
|
||||
return nil, nil, fmt.Errorf("failed to obtain OCSP response: %s", err)
|
||||
}
|
||||
|
||||
if len(records) == 0 {
|
||||
return nil, false
|
||||
return nil, nil, ErrNotFound
|
||||
}
|
||||
|
||||
// Response() finds the OCSPRecord with the expiration date furthest in the future.
|
||||
|
@ -106,7 +118,7 @@ func (src DBSource) Response(req *ocsp.Request) ([]byte, bool) {
|
|||
cur = rec
|
||||
}
|
||||
}
|
||||
return []byte(cur.Body), true
|
||||
return []byte(cur.Body), nil, nil
|
||||
}
|
||||
|
||||
// NewSourceFromFile reads the named file into an InMemorySource.
|
||||
|
@ -161,6 +173,19 @@ func NewResponder(source Source) *Responder {
|
|||
}
|
||||
}
|
||||
|
||||
func overrideHeaders(response http.ResponseWriter, headers http.Header) {
|
||||
for k, v := range headers {
|
||||
if len(v) == 1 {
|
||||
response.Header().Set(k, v[0])
|
||||
} else if len(v) > 1 {
|
||||
response.Header().Del(k)
|
||||
for _, e := range v {
|
||||
response.Header().Add(k, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A Responder can process both GET and POST requests. The mapping
|
||||
// from an OCSP request to an OCSP response is done by the Source;
|
||||
// the Responder simply decodes the request, and passes back whatever
|
||||
|
@ -243,11 +268,18 @@ func (rs Responder) ServeHTTP(response http.ResponseWriter, request *http.Reques
|
|||
}
|
||||
|
||||
// Look up OCSP response from source
|
||||
ocspResponse, found := rs.Source.Response(ocspRequest)
|
||||
if !found {
|
||||
log.Infof("No response found for request: serial %x, request body %s",
|
||||
ocspRequest.SerialNumber, b64Body)
|
||||
response.Write(unauthorizedErrorResponse)
|
||||
ocspResponse, headers, err := rs.Source.Response(ocspRequest)
|
||||
if err != nil {
|
||||
if err == ErrNotFound {
|
||||
log.Infof("No response found for request: serial %x, request body %s",
|
||||
ocspRequest.SerialNumber, b64Body)
|
||||
response.Write(unauthorizedErrorResponse)
|
||||
return
|
||||
}
|
||||
log.Infof("Error retrieving response for request: serial %x, request body %s, error: %s",
|
||||
ocspRequest.SerialNumber, b64Body, err)
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
response.Write(internalErrorErrorResponse)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -281,6 +313,10 @@ func (rs Responder) ServeHTTP(response http.ResponseWriter, request *http.Reques
|
|||
responseHash := sha256.Sum256(ocspResponse)
|
||||
response.Header().Add("ETag", fmt.Sprintf("\"%X\"", responseHash))
|
||||
|
||||
if headers != nil {
|
||||
overrideHeaders(response, headers)
|
||||
}
|
||||
|
||||
// RFC 7232 says that a 304 response must contain the above
|
||||
// headers if they would also be sent for a 200 for the same
|
||||
// request, so we have to wait until here to do this
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/google/certificate-transparency-go/client"
|
||||
"github.com/google/certificate-transparency-go/jsonclient"
|
||||
"golang.org/x/net/context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Signer contains a signer that uses the standard library to
|
||||
|
@ -96,14 +97,14 @@ func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signe
|
|||
return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy)
|
||||
}
|
||||
|
||||
func (s *Signer) sign(template *x509.Certificate, profile *config.SigningProfile) (cert []byte, err error) {
|
||||
func (s *Signer) sign(template *x509.Certificate, profile *config.SigningProfile, notBefore time.Time, notAfter time.Time) (cert []byte, err error) {
|
||||
var distPoints = template.CRLDistributionPoints
|
||||
err = signer.FillTemplate(template, s.policy.Default, profile)
|
||||
if distPoints != nil && len(distPoints) > 0 {
|
||||
template.CRLDistributionPoints = distPoints
|
||||
}
|
||||
err = signer.FillTemplate(template, s.policy.Default, profile, notBefore, notAfter)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var initRoot bool
|
||||
|
@ -342,7 +343,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
|||
var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}}
|
||||
var poisonedPreCert = certTBS
|
||||
poisonedPreCert.ExtraExtensions = append(safeTemplate.ExtraExtensions, poisonExtension)
|
||||
cert, err = s.sign(&poisonedPreCert, profile)
|
||||
cert, err = s.sign(&poisonedPreCert, profile, req.NotBefore, req.NotAfter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -382,17 +383,22 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
|||
certTBS.ExtraExtensions = append(certTBS.ExtraExtensions, SCTListExtension)
|
||||
}
|
||||
var signedCert []byte
|
||||
signedCert, err = s.sign(&certTBS, profile)
|
||||
signedCert, err = s.sign(&certTBS, profile, req.NotBefore, req.NotAfter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the AKI from signedCert. This is required to support Go 1.9+.
|
||||
// In prior versions of Go, x509.CreateCertificate updated the
|
||||
// AuthorityKeyId of certTBS.
|
||||
parsedCert, _ := helpers.ParseCertificatePEM(signedCert)
|
||||
|
||||
if s.dbAccessor != nil {
|
||||
var certRecord = certdb.CertificateRecord{
|
||||
Serial: certTBS.SerialNumber.String(),
|
||||
// this relies on the specific behavior of x509.CreateCertificate
|
||||
// which updates certTBS AuthorityKeyId from the signer's SubjectKeyId
|
||||
AKI: hex.EncodeToString(certTBS.AuthorityKeyId),
|
||||
// which sets the AuthorityKeyId from the signer's SubjectKeyId
|
||||
AKI: hex.EncodeToString(parsedCert.AuthorityKeyId),
|
||||
CALabel: req.Label,
|
||||
Status: "good",
|
||||
Expiry: certTBS.NotAfter,
|
||||
|
@ -452,6 +458,11 @@ func (s *Signer) SetDBAccessor(dba certdb.Accessor) {
|
|||
s.dbAccessor = dba
|
||||
}
|
||||
|
||||
// GetDBAccessor returns the signers' cert db accessor
|
||||
func (s *Signer) GetDBAccessor() certdb.Accessor {
|
||||
return s.dbAccessor
|
||||
}
|
||||
|
||||
// SetReqModifier does nothing for local
|
||||
func (s *Signer) SetReqModifier(func(*http.Request, []byte)) {
|
||||
// noop
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"github.com/cloudflare/cfssl/config"
|
||||
"github.com/cloudflare/cfssl/csr"
|
||||
cferr "github.com/cloudflare/cfssl/errors"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/info"
|
||||
)
|
||||
|
||||
|
@ -56,6 +55,15 @@ type SignRequest struct {
|
|||
Label string `json:"label"`
|
||||
Serial *big.Int `json:"serial,omitempty"`
|
||||
Extensions []Extension `json:"extensions,omitempty"`
|
||||
// If provided, NotBefore will be used without modification (except
|
||||
// for canonicalization) as the value of the notBefore field of the
|
||||
// certificate. In particular no backdating adjustment will be made
|
||||
// when NotBefore is provided.
|
||||
NotBefore time.Time
|
||||
// If provided, NotAfter will be used without modification (except
|
||||
// for canonicalization) as the value of the notAfter field of the
|
||||
// certificate.
|
||||
NotAfter time.Time
|
||||
}
|
||||
|
||||
// appendIf appends to a if s is not an empty string.
|
||||
|
@ -97,6 +105,7 @@ type Signer interface {
|
|||
Info(info.Req) (*info.Resp, error)
|
||||
Policy() *config.Signing
|
||||
SetDBAccessor(certdb.Accessor)
|
||||
GetDBAccessor() certdb.Accessor
|
||||
SetPolicy(*config.Signing)
|
||||
SigAlgo() x509.SignatureAlgorithm
|
||||
Sign(req SignRequest) (cert []byte, err error)
|
||||
|
@ -163,7 +172,7 @@ func ParseCertificateRequest(s Signer, csrBytes []byte) (template *x509.Certific
|
|||
return
|
||||
}
|
||||
|
||||
err = helpers.CheckSignature(csrv, csrv.SignatureAlgorithm, csrv.RawTBSCertificateRequest, csrv.Signature)
|
||||
err = csrv.CheckSignature()
|
||||
if err != nil {
|
||||
err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
|
||||
return
|
||||
|
@ -231,7 +240,7 @@ func ComputeSKI(template *x509.Certificate) ([]byte, error) {
|
|||
// the certificate template as possible from the profiles and current
|
||||
// template. It fills in the key uses, expiration, revocation URLs
|
||||
// and SKI.
|
||||
func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.SigningProfile) error {
|
||||
func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.SigningProfile, notBefore time.Time, notAfter time.Time) error {
|
||||
ski, err := ComputeSKI(template)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -242,8 +251,6 @@ func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.Si
|
|||
ku x509.KeyUsage
|
||||
backdate time.Duration
|
||||
expiry time.Duration
|
||||
notBefore time.Time
|
||||
notAfter time.Time
|
||||
crlURL, ocspURL string
|
||||
issuerURL = profile.IssuerURL
|
||||
)
|
||||
|
@ -270,23 +277,29 @@ func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.Si
|
|||
if ocspURL = profile.OCSP; ocspURL == "" {
|
||||
ocspURL = defaultProfile.OCSP
|
||||
}
|
||||
if backdate = profile.Backdate; backdate == 0 {
|
||||
backdate = -5 * time.Minute
|
||||
} else {
|
||||
backdate = -1 * profile.Backdate
|
||||
}
|
||||
|
||||
if !profile.NotBefore.IsZero() {
|
||||
notBefore = profile.NotBefore.UTC()
|
||||
} else {
|
||||
notBefore = time.Now().Round(time.Minute).Add(backdate).UTC()
|
||||
if notBefore.IsZero() {
|
||||
if !profile.NotBefore.IsZero() {
|
||||
notBefore = profile.NotBefore
|
||||
} else {
|
||||
if backdate = profile.Backdate; backdate == 0 {
|
||||
backdate = -5 * time.Minute
|
||||
} else {
|
||||
backdate = -1 * profile.Backdate
|
||||
}
|
||||
notBefore = time.Now().Round(time.Minute).Add(backdate)
|
||||
}
|
||||
}
|
||||
notBefore = notBefore.UTC()
|
||||
|
||||
if !profile.NotAfter.IsZero() {
|
||||
notAfter = profile.NotAfter.UTC()
|
||||
} else {
|
||||
notAfter = notBefore.Add(expiry).UTC()
|
||||
if notAfter.IsZero() {
|
||||
if !profile.NotAfter.IsZero() {
|
||||
notAfter = profile.NotAfter
|
||||
} else {
|
||||
notAfter = notBefore.Add(expiry)
|
||||
}
|
||||
}
|
||||
notAfter = notAfter.UTC()
|
||||
|
||||
template.NotBefore = notBefore
|
||||
template.NotAfter = notAfter
|
||||
|
|
Loading…
Reference in New Issue