Bump cfssl to be compatible with Go 1.10
This commit is contained in:
33
vendor/github.com/cloudflare/cfssl/certdb/README.md
generated
vendored
33
vendor/github.com/cloudflare/cfssl/certdb/README.md
generated
vendored
@@ -16,21 +16,26 @@ A database is required for the following:
|
||||
|
||||
This directory stores [goose](https://bitbucket.org/liamstask/goose/) db migration scripts for various DB backends.
|
||||
Currently supported:
|
||||
- SQLite in sqlite
|
||||
- MySQL in mysql
|
||||
- PostgreSQL in pg
|
||||
- SQLite in sqlite
|
||||
|
||||
### Get goose
|
||||
|
||||
go get https://bitbucket.org/liamstask/goose/
|
||||
go get bitbucket.org/liamstask/goose/cmd/goose
|
||||
|
||||
### Use goose to start and terminate a SQLite DB
|
||||
To start a SQLite DB using goose:
|
||||
### Use goose to start and terminate a MySQL DB
|
||||
To start a MySQL using goose:
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite up'
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/mysql up
|
||||
|
||||
To tear down a SQLite DB using goose
|
||||
To tear down a MySQL DB using goose
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite down
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/mysql down
|
||||
|
||||
Note: the administration of MySQL DB is not included. We assume
|
||||
the databases being connected to are already created and access control
|
||||
is properly handled.
|
||||
|
||||
### Use goose to start and terminate a PostgreSQL DB
|
||||
To start a PostgreSQL using goose:
|
||||
@@ -43,7 +48,16 @@ To tear down a PostgreSQL DB using goose
|
||||
|
||||
Note: the administration of PostgreSQL DB is not included. We assume
|
||||
the databases being connected to are already created and access control
|
||||
are properly handled.
|
||||
is properly handled.
|
||||
|
||||
### Use goose to start and terminate a SQLite DB
|
||||
To start a SQLite DB using goose:
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite up
|
||||
|
||||
To tear down a SQLite DB using goose
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite down
|
||||
|
||||
## CFSSL Configuration
|
||||
|
||||
@@ -55,4 +69,7 @@ JSON dictionary:
|
||||
or
|
||||
|
||||
{"driver":"postgres","data_source":"postgres://user:password@host/db"}
|
||||
|
||||
or
|
||||
|
||||
{"driver":"mysql","data_source":"user:password@tcp(hostname:3306)/db?parseTime=true"}
|
||||
|
2
vendor/github.com/cloudflare/cfssl/certdb/certdb.go
generated
vendored
2
vendor/github.com/cloudflare/cfssl/certdb/certdb.go
generated
vendored
@@ -31,6 +31,8 @@ type Accessor interface {
|
||||
InsertCertificate(cr CertificateRecord) error
|
||||
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)
|
||||
|
130
vendor/github.com/cloudflare/cfssl/config/config.go
generated
vendored
130
vendor/github.com/cloudflare/cfssl/config/config.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/json"
|
||||
@@ -59,26 +60,35 @@ type AuthRemote struct {
|
||||
AuthKeyName string `json:"auth_key"`
|
||||
}
|
||||
|
||||
// CAConstraint specifies various CA constraints on the signed certificate.
|
||||
// CAConstraint would verify against (and override) the CA
|
||||
// extensions in the given CSR.
|
||||
type CAConstraint struct {
|
||||
IsCA bool `json:"is_ca"`
|
||||
MaxPathLen int `json:"max_path_len"`
|
||||
MaxPathLenZero bool `json:"max_path_len_zero"`
|
||||
}
|
||||
|
||||
// A SigningProfile stores information that the CA needs to store
|
||||
// signature policy.
|
||||
type SigningProfile struct {
|
||||
Usage []string `json:"usages"`
|
||||
IssuerURL []string `json:"issuer_urls"`
|
||||
OCSP string `json:"ocsp_url"`
|
||||
CRL string `json:"crl_url"`
|
||||
CA bool `json:"is_ca"`
|
||||
OCSPNoCheck bool `json:"ocsp_no_check"`
|
||||
ExpiryString string `json:"expiry"`
|
||||
BackdateString string `json:"backdate"`
|
||||
AuthKeyName string `json:"auth_key"`
|
||||
RemoteName string `json:"remote"`
|
||||
NotBefore time.Time `json:"not_before"`
|
||||
NotAfter time.Time `json:"not_after"`
|
||||
NameWhitelistString string `json:"name_whitelist"`
|
||||
AuthRemote AuthRemote `json:"auth_remote"`
|
||||
CTLogServers []string `json:"ct_log_servers"`
|
||||
AllowedExtensions []OID `json:"allowed_extensions"`
|
||||
CertStore string `json:"cert_store"`
|
||||
Usage []string `json:"usages"`
|
||||
IssuerURL []string `json:"issuer_urls"`
|
||||
OCSP string `json:"ocsp_url"`
|
||||
CRL string `json:"crl_url"`
|
||||
CAConstraint CAConstraint `json:"ca_constraint"`
|
||||
OCSPNoCheck bool `json:"ocsp_no_check"`
|
||||
ExpiryString string `json:"expiry"`
|
||||
BackdateString string `json:"backdate"`
|
||||
AuthKeyName string `json:"auth_key"`
|
||||
RemoteName string `json:"remote"`
|
||||
NotBefore time.Time `json:"not_before"`
|
||||
NotAfter time.Time `json:"not_after"`
|
||||
NameWhitelistString string `json:"name_whitelist"`
|
||||
AuthRemote AuthRemote `json:"auth_remote"`
|
||||
CTLogServers []string `json:"ct_log_servers"`
|
||||
AllowedExtensions []OID `json:"allowed_extensions"`
|
||||
CertStore string `json:"cert_store"`
|
||||
|
||||
Policies []CertificatePolicy
|
||||
Expiry time.Duration
|
||||
@@ -86,6 +96,8 @@ type SigningProfile struct {
|
||||
Provider auth.Provider
|
||||
RemoteProvider auth.Provider
|
||||
RemoteServer string
|
||||
RemoteCAs *x509.CertPool
|
||||
ClientCert *tls.Certificate
|
||||
CSRWhitelist *CSRWhitelist
|
||||
NameWhitelist *regexp.Regexp
|
||||
ExtensionWhitelist map[string]bool
|
||||
@@ -303,6 +315,44 @@ func (p *Signing) OverrideRemotes(remote string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetClientCertKeyPairFromFile updates the properties to set client certificates for mutual
|
||||
// authenticated TLS remote requests
|
||||
func (p *Signing) SetClientCertKeyPairFromFile(certFile string, keyFile string) error {
|
||||
if certFile != "" && keyFile != "" {
|
||||
cert, err := helpers.LoadClientCertificate(certFile, keyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, profile := range p.Profiles {
|
||||
profile.ClientCert = cert
|
||||
}
|
||||
p.Default.ClientCert = cert
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRemoteCAsFromFile reads root CAs from file and updates the properties to set remote CAs for TLS
|
||||
// remote requests
|
||||
func (p *Signing) SetRemoteCAsFromFile(caFile string) error {
|
||||
if caFile != "" {
|
||||
remoteCAs, err := helpers.LoadPEMCertPool(caFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.SetRemoteCAs(remoteCAs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRemoteCAs updates the properties to set remote CAs for TLS
|
||||
// remote requests
|
||||
func (p *Signing) SetRemoteCAs(remoteCAs *x509.CertPool) {
|
||||
for _, profile := range p.Profiles {
|
||||
profile.RemoteCAs = remoteCAs
|
||||
}
|
||||
p.Default.RemoteCAs = remoteCAs
|
||||
}
|
||||
|
||||
// NeedsRemoteSigner returns true if one of the profiles has a remote set
|
||||
func (p *Signing) NeedsRemoteSigner() bool {
|
||||
for _, profile := range p.Profiles {
|
||||
@@ -360,6 +410,11 @@ func (p *SigningProfile) validProfile(isDefault bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.AuthRemote.RemoteName == "" && p.AuthRemote.AuthKeyName != "" {
|
||||
log.Debugf("invalid auth remote profile: no remote signer specified")
|
||||
return false
|
||||
}
|
||||
|
||||
if p.RemoteName != "" {
|
||||
log.Debugf("validate remote profile")
|
||||
|
||||
@@ -375,6 +430,7 @@ func (p *SigningProfile) validProfile(isDefault bool) bool {
|
||||
|
||||
if p.AuthRemote.RemoteName != "" {
|
||||
log.Debugf("invalid remote profile: auth remote is also specified")
|
||||
return false
|
||||
}
|
||||
} else if p.AuthRemote.RemoteName != "" {
|
||||
log.Debugf("validate auth remote profile")
|
||||
@@ -409,6 +465,43 @@ func (p *SigningProfile) validProfile(isDefault bool) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// This checks if the SigningProfile object contains configurations that are only effective with a local signer
|
||||
// which has access to CA private key.
|
||||
func (p *SigningProfile) hasLocalConfig() bool {
|
||||
if p.Usage != nil ||
|
||||
p.IssuerURL != nil ||
|
||||
p.OCSP != "" ||
|
||||
p.ExpiryString != "" ||
|
||||
p.BackdateString != "" ||
|
||||
p.CAConstraint.IsCA != false ||
|
||||
!p.NotBefore.IsZero() ||
|
||||
!p.NotAfter.IsZero() ||
|
||||
p.NameWhitelistString != "" ||
|
||||
len(p.CTLogServers) != 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// warnSkippedSettings prints a log warning message about skipped settings
|
||||
// in a SigningProfile, usually due to remote signer.
|
||||
func (p *Signing) warnSkippedSettings() {
|
||||
const warningMessage = `The configuration value by "usages", "issuer_urls", "ocsp_url", "crl_url", "ca_constraint", "expiry", "backdate", "not_before", "not_after", "cert_store" and "ct_log_servers" are skipped`
|
||||
if p == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if (p.Default.RemoteName != "" || p.Default.AuthRemote.RemoteName != "") && p.Default.hasLocalConfig() {
|
||||
log.Warning("default profile points to a remote signer: ", warningMessage)
|
||||
}
|
||||
|
||||
for name, profile := range p.Profiles {
|
||||
if (profile.RemoteName != "" || profile.AuthRemote.RemoteName != "") && profile.hasLocalConfig() {
|
||||
log.Warningf("Profiles[%s] points to a remote signer: %s", name, warningMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Signing codifies the signature configuration policy for a CA.
|
||||
type Signing struct {
|
||||
Profiles map[string]*SigningProfile `json:"profiles"`
|
||||
@@ -450,6 +543,9 @@ func (p *Signing) Valid() bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
p.warnSkippedSettings()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go
generated
vendored
2
vendor/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// Package pkcs7 implements the subset of the CMS PKCS #7 datatype that is typically
|
||||
// used to package certificates and CRLs. Using openssl, every certificate converted
|
||||
// to PKCS #7 format from another encoding such as PEM conforms to this implementation.
|
||||
// reference: https://www.openssl.org/docs/apps/crl2pkcs7.html
|
||||
// reference: https://www.openssl.org/docs/man1.1.0/apps/crl2pkcs7.html
|
||||
//
|
||||
// PKCS #7 Data type, reference: https://tools.ietf.org/html/rfc2315
|
||||
//
|
||||
|
88
vendor/github.com/cloudflare/cfssl/csr/csr.go
generated
vendored
88
vendor/github.com/cloudflare/cfssl/csr/csr.go
generated
vendored
@@ -9,6 +9,7 @@ import (
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"net"
|
||||
@@ -46,8 +47,8 @@ type KeyRequest interface {
|
||||
|
||||
// A BasicKeyRequest contains the algorithm and key size for a new private key.
|
||||
type BasicKeyRequest struct {
|
||||
A string `json:"algo"`
|
||||
S int `json:"size"`
|
||||
A string `json:"algo" yaml:"algo"`
|
||||
S int `json:"size" yaml:"size"`
|
||||
}
|
||||
|
||||
// NewBasicKeyRequest returns a default BasicKeyRequest.
|
||||
@@ -129,19 +130,21 @@ func (kr *BasicKeyRequest) SigAlgo() x509.SignatureAlgorithm {
|
||||
|
||||
// CAConfig is a section used in the requests initialising a new CA.
|
||||
type CAConfig struct {
|
||||
PathLength int `json:"pathlen"`
|
||||
Expiry string `json:"expiry"`
|
||||
PathLength int `json:"pathlen" yaml:"pathlen"`
|
||||
PathLenZero bool `json:"pathlenzero" yaml:"pathlenzero"`
|
||||
Expiry string `json:"expiry" yaml:"expiry"`
|
||||
Backdate string `json:"backdate" yaml:"backdate"`
|
||||
}
|
||||
|
||||
// A CertificateRequest encapsulates the API interface to the
|
||||
// certificate request functionality.
|
||||
type CertificateRequest struct {
|
||||
CN string
|
||||
Names []Name `json:"names"`
|
||||
Hosts []string `json:"hosts"`
|
||||
KeyRequest KeyRequest `json:"key,omitempty"`
|
||||
CA *CAConfig `json:"ca,omitempty"`
|
||||
SerialNumber string `json:"serialnumber,omitempty"`
|
||||
Names []Name `json:"names" yaml:"names"`
|
||||
Hosts []string `json:"hosts" yaml:"hosts"`
|
||||
KeyRequest KeyRequest `json:"key,omitempty" yaml:"key,omitempty"`
|
||||
CA *CAConfig `json:"ca,omitempty" yaml:"ca,omitempty"`
|
||||
SerialNumber string `json:"serialnumber,omitempty" yaml:"serialnumber,omitempty"`
|
||||
}
|
||||
|
||||
// New returns a new, empty CertificateRequest with a
|
||||
@@ -175,6 +178,12 @@ func (cr *CertificateRequest) Name() pkix.Name {
|
||||
return name
|
||||
}
|
||||
|
||||
// BasicConstraints CSR information RFC 5280, 4.2.1.9
|
||||
type BasicConstraints struct {
|
||||
IsCA bool `asn1:"optional"`
|
||||
MaxPathLen int `asn1:"optional,default:-1"`
|
||||
}
|
||||
|
||||
// ParseRequest takes a certificate request and generates a key and
|
||||
// CSR from it. It does no validation -- caveat emptor. It will,
|
||||
// however, fail if the key request is not valid (i.e., an unsupported
|
||||
@@ -217,34 +226,11 @@ func ParseRequest(req *CertificateRequest) (csr, key []byte, err error) {
|
||||
panic("Generate should have failed to produce a valid key.")
|
||||
}
|
||||
|
||||
var tpl = x509.CertificateRequest{
|
||||
Subject: req.Name(),
|
||||
SignatureAlgorithm: req.KeyRequest.SigAlgo(),
|
||||
}
|
||||
|
||||
for i := range req.Hosts {
|
||||
if ip := net.ParseIP(req.Hosts[i]); ip != nil {
|
||||
tpl.IPAddresses = append(tpl.IPAddresses, ip)
|
||||
} else if email, err := mail.ParseAddress(req.Hosts[i]); err == nil && email != nil {
|
||||
tpl.EmailAddresses = append(tpl.EmailAddresses, req.Hosts[i])
|
||||
} else {
|
||||
tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i])
|
||||
}
|
||||
}
|
||||
|
||||
csr, err = x509.CreateCertificateRequest(rand.Reader, &tpl, priv)
|
||||
csr, err = Generate(priv.(crypto.Signer), req)
|
||||
if err != nil {
|
||||
log.Errorf("failed to generate a CSR: %v", err)
|
||||
err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
|
||||
return
|
||||
}
|
||||
block := pem.Block{
|
||||
Type: "CERTIFICATE REQUEST",
|
||||
Bytes: csr,
|
||||
}
|
||||
|
||||
log.Info("encoded CSR")
|
||||
csr = pem.EncodeToMemory(&block)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -265,6 +251,7 @@ func ExtractCertificateRequest(cert *x509.Certificate) *CertificateRequest {
|
||||
// issue date and expiry date.
|
||||
req.CA.Expiry = cert.NotAfter.Sub(cert.NotBefore).String()
|
||||
req.CA.PathLength = cert.MaxPathLen
|
||||
req.CA.PathLenZero = cert.MaxPathLenZero
|
||||
}
|
||||
|
||||
return req
|
||||
@@ -341,7 +328,7 @@ func (g *Generator) ProcessRequest(req *CertificateRequest) (csr, key []byte, er
|
||||
err = g.Validator(req)
|
||||
if err != nil {
|
||||
log.Warningf("invalid request: %v", err)
|
||||
return
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
csr, key, err = ParseRequest(req)
|
||||
@@ -377,7 +364,7 @@ func Regenerate(priv crypto.Signer, csr []byte) ([]byte, error) {
|
||||
// Generate creates a new CSR from a CertificateRequest structure and
|
||||
// an existing key. The KeyRequest field is ignored.
|
||||
func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err error) {
|
||||
sigAlgo := helpers.SignerAlgo(priv, crypto.SHA256)
|
||||
sigAlgo := helpers.SignerAlgo(priv)
|
||||
if sigAlgo == x509.UnknownSignatureAlgorithm {
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
|
||||
}
|
||||
@@ -397,6 +384,14 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
|
||||
}
|
||||
}
|
||||
|
||||
if req.CA != nil {
|
||||
err = appendCAInfoToCSR(req.CA, &tpl)
|
||||
if err != nil {
|
||||
err = cferr.Wrap(cferr.CSRError, cferr.GenerationFailed, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
csr, err = x509.CreateCertificateRequest(rand.Reader, &tpl, priv)
|
||||
if err != nil {
|
||||
log.Errorf("failed to generate a CSR: %v", err)
|
||||
@@ -412,3 +407,26 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
|
||||
csr = pem.EncodeToMemory(&block)
|
||||
return
|
||||
}
|
||||
|
||||
// appendCAInfoToCSR appends CAConfig BasicConstraint extension to a CSR
|
||||
func appendCAInfoToCSR(reqConf *CAConfig, csr *x509.CertificateRequest) error {
|
||||
pathlen := reqConf.PathLength
|
||||
if pathlen == 0 && !reqConf.PathLenZero {
|
||||
pathlen = -1
|
||||
}
|
||||
val, err := asn1.Marshal(BasicConstraints{true, pathlen})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
csr.ExtraExtensions = []pkix.Extension{
|
||||
{
|
||||
Id: asn1.ObjectIdentifier{2, 5, 29, 19},
|
||||
Value: val,
|
||||
Critical: true,
|
||||
},
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
7
vendor/github.com/cloudflare/cfssl/errors/error.go
generated
vendored
7
vendor/github.com/cloudflare/cfssl/errors/error.go
generated
vendored
@@ -149,6 +149,8 @@ const (
|
||||
|
||||
// UnknownProfile indicates that the profile does not exist.
|
||||
UnknownProfile // 54XX
|
||||
|
||||
UnmatchedWhitelist // 55xx
|
||||
)
|
||||
|
||||
// The following are API client related errors, and should be
|
||||
@@ -189,6 +191,9 @@ const (
|
||||
// PrecertSubmissionFailed occurs when submitting a precertificate to
|
||||
// a log server fails
|
||||
PrecertSubmissionFailed = 100 * (iota + 1)
|
||||
// CTClientConstructionFailed occurs when the construction of a new
|
||||
// github.com/google/certificate-transparency client fails.
|
||||
CTClientConstructionFailed
|
||||
)
|
||||
|
||||
// Certificate persistence related errors specified with CertStoreError
|
||||
@@ -313,6 +318,8 @@ func New(category Category, reason Reason) *Error {
|
||||
msg = "Policy violation request"
|
||||
case UnknownProfile:
|
||||
msg = "Unknown policy profile"
|
||||
case UnmatchedWhitelist:
|
||||
msg = "Request does not match policy whitelist"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PolicyError.",
|
||||
reason))
|
||||
|
3
vendor/github.com/cloudflare/cfssl/helpers/BUILD
generated
vendored
3
vendor/github.com/cloudflare/cfssl/helpers/BUILD
generated
vendored
@@ -10,6 +10,9 @@ go_library(
|
||||
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
|
||||
"//vendor/github.com/cloudflare/cfssl/helpers/derhelpers:go_default_library",
|
||||
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
|
||||
"//vendor/github.com/google/certificate-transparency-go:go_default_library",
|
||||
"//vendor/github.com/google/certificate-transparency-go/tls:go_default_library",
|
||||
"//vendor/golang.org/x/crypto/ocsp:go_default_library",
|
||||
"//vendor/golang.org/x/crypto/pkcs12:go_default_library",
|
||||
],
|
||||
)
|
||||
|
249
vendor/github.com/cloudflare/cfssl/helpers/helpers.go
generated
vendored
249
vendor/github.com/cloudflare/cfssl/helpers/helpers.go
generated
vendored
@@ -6,13 +6,23 @@ import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/binary"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/google/certificate-transparency-go"
|
||||
cttls "github.com/google/certificate-transparency-go/tls"
|
||||
"golang.org/x/crypto/ocsp"
|
||||
|
||||
"strings"
|
||||
"time"
|
||||
@@ -310,11 +320,23 @@ func ParseOneCertificateFromPEM(certsPEM []byte) ([]*x509.Certificate, []byte, e
|
||||
|
||||
// LoadPEMCertPool loads a pool of PEM certificates from file.
|
||||
func LoadPEMCertPool(certsFile string) (*x509.CertPool, error) {
|
||||
if certsFile == "" {
|
||||
return nil, nil
|
||||
}
|
||||
pemCerts, err := ioutil.ReadFile(certsFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return PEMToCertPool(pemCerts)
|
||||
}
|
||||
|
||||
// PEMToCertPool concerts PEM certificates to a CertPool.
|
||||
func PEMToCertPool(pemCerts []byte) (*x509.CertPool, error) {
|
||||
if len(pemCerts) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
certPool := x509.NewCertPool()
|
||||
if !certPool.AppendCertsFromPEM(pemCerts) {
|
||||
return nil, errors.New("failed to load cert pool")
|
||||
@@ -360,57 +382,12 @@ 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)
|
||||
p, rest := pem.Decode(in)
|
||||
if p != nil {
|
||||
if p.Type != "CERTIFICATE REQUEST" {
|
||||
if p.Type != "NEW CERTIFICATE REQUEST" && p.Type != "CERTIFICATE REQUEST" {
|
||||
return nil, rest, cferr.New(cferr.CSRError, cferr.BadRequest)
|
||||
}
|
||||
|
||||
@@ -423,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
|
||||
}
|
||||
@@ -436,8 +413,10 @@ func ParseCSR(in []byte) (csr *x509.CertificateRequest, rest []byte, err error)
|
||||
// locally.
|
||||
func ParseCSRPEM(csrPEM []byte) (*x509.CertificateRequest, error) {
|
||||
block, _ := pem.Decode([]byte(csrPEM))
|
||||
der := block.Bytes
|
||||
csrObject, err := x509.ParseCertificateRequest(der)
|
||||
if block == nil {
|
||||
return nil, cferr.New(cferr.CSRError, cferr.DecodeFailed)
|
||||
}
|
||||
csrObject, err := x509.ParseCertificateRequest(block.Bytes)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -446,28 +425,28 @@ func ParseCSRPEM(csrPEM []byte) (*x509.CertificateRequest, error) {
|
||||
return csrObject, nil
|
||||
}
|
||||
|
||||
// SignerAlgo returns an X.509 signature algorithm corresponding to
|
||||
// the crypto.Hash provided from a crypto.Signer.
|
||||
func SignerAlgo(priv crypto.Signer, h crypto.Hash) x509.SignatureAlgorithm {
|
||||
switch priv.Public().(type) {
|
||||
// SignerAlgo returns an X.509 signature algorithm from a crypto.Signer.
|
||||
func SignerAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
|
||||
switch pub := priv.Public().(type) {
|
||||
case *rsa.PublicKey:
|
||||
switch h {
|
||||
case crypto.SHA512:
|
||||
bitLength := pub.N.BitLen()
|
||||
switch {
|
||||
case bitLength >= 4096:
|
||||
return x509.SHA512WithRSA
|
||||
case crypto.SHA384:
|
||||
case bitLength >= 3072:
|
||||
return x509.SHA384WithRSA
|
||||
case crypto.SHA256:
|
||||
case bitLength >= 2048:
|
||||
return x509.SHA256WithRSA
|
||||
default:
|
||||
return x509.SHA1WithRSA
|
||||
}
|
||||
case *ecdsa.PublicKey:
|
||||
switch h {
|
||||
case crypto.SHA512:
|
||||
switch pub.Curve {
|
||||
case elliptic.P521():
|
||||
return x509.ECDSAWithSHA512
|
||||
case crypto.SHA384:
|
||||
case elliptic.P384():
|
||||
return x509.ECDSAWithSHA384
|
||||
case crypto.SHA256:
|
||||
case elliptic.P256():
|
||||
return x509.ECDSAWithSHA256
|
||||
default:
|
||||
return x509.ECDSAWithSHA1
|
||||
@@ -476,3 +455,149 @@ func SignerAlgo(priv crypto.Signer, h crypto.Hash) x509.SignatureAlgorithm {
|
||||
return x509.UnknownSignatureAlgorithm
|
||||
}
|
||||
}
|
||||
|
||||
// LoadClientCertificate load key/certificate from pem files
|
||||
func LoadClientCertificate(certFile string, keyFile string) (*tls.Certificate, error) {
|
||||
if certFile != "" && keyFile != "" {
|
||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
log.Critical("Unable to read client certificate from file: %s or key from file: %s", certFile, keyFile)
|
||||
return nil, err
|
||||
}
|
||||
log.Debug("Client certificate loaded ")
|
||||
return &cert, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// CreateTLSConfig creates a tls.Config object from certs and roots
|
||||
func CreateTLSConfig(remoteCAs *x509.CertPool, cert *tls.Certificate) *tls.Config {
|
||||
var certs []tls.Certificate
|
||||
if cert != nil {
|
||||
certs = []tls.Certificate{*cert}
|
||||
}
|
||||
return &tls.Config{
|
||||
Certificates: certs,
|
||||
RootCAs: remoteCAs,
|
||||
}
|
||||
}
|
||||
|
||||
// SerializeSCTList serializes a list of SCTs.
|
||||
func SerializeSCTList(sctList []ct.SignedCertificateTimestamp) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
for _, sct := range sctList {
|
||||
sct, err := cttls.Marshal(sct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
binary.Write(&buf, binary.BigEndian, uint16(len(sct)))
|
||||
buf.Write(sct)
|
||||
}
|
||||
|
||||
var sctListLengthField = make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(sctListLengthField, uint16(buf.Len()))
|
||||
return bytes.Join([][]byte{sctListLengthField, buf.Bytes()}, nil), nil
|
||||
}
|
||||
|
||||
// DeserializeSCTList deserializes a list of SCTs.
|
||||
func DeserializeSCTList(serializedSCTList []byte) (*[]ct.SignedCertificateTimestamp, error) {
|
||||
sctList := new([]ct.SignedCertificateTimestamp)
|
||||
sctReader := bytes.NewBuffer(serializedSCTList)
|
||||
|
||||
var sctListLen uint16
|
||||
err := binary.Read(sctReader, binary.BigEndian, &sctListLen)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown,
|
||||
errors.New("serialized SCT list could not be read"))
|
||||
}
|
||||
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
if sctReader.Len() != int(sctListLen) {
|
||||
return sctList, errors.New("SCT length field and SCT length don't match")
|
||||
}
|
||||
|
||||
for err != io.EOF {
|
||||
var sctLen uint16
|
||||
err = binary.Read(sctReader, binary.BigEndian, &sctLen)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return sctList, nil
|
||||
}
|
||||
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
|
||||
if sctReader.Len() < int(sctLen) {
|
||||
return sctList, errors.New("SCT length field and SCT length don't match")
|
||||
}
|
||||
|
||||
serializedSCT := sctReader.Next(int(sctLen))
|
||||
var sct ct.SignedCertificateTimestamp
|
||||
if _, err := cttls.Unmarshal(serializedSCT, &sct); err != nil {
|
||||
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
|
||||
temp := append(*sctList, sct)
|
||||
sctList = &temp
|
||||
}
|
||||
|
||||
return sctList, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
|
||||
// SCTListFromOCSPResponse extracts the SCTList from an ocsp.Response,
|
||||
// returning an empty list if the SCT extension was not found or could not be
|
||||
// unmarshalled.
|
||||
func SCTListFromOCSPResponse(response *ocsp.Response) ([]ct.SignedCertificateTimestamp, error) {
|
||||
// This loop finds the SCTListExtension in the OCSP response.
|
||||
var SCTListExtension, ext pkix.Extension
|
||||
for _, ext = range response.Extensions {
|
||||
// sctExtOid is the ObjectIdentifier of a Signed Certificate Timestamp.
|
||||
sctExtOid := asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 5}
|
||||
if ext.Id.Equal(sctExtOid) {
|
||||
SCTListExtension = ext
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// This code block extracts the sctList from the SCT extension.
|
||||
var emptySCTList []ct.SignedCertificateTimestamp
|
||||
sctList := &emptySCTList
|
||||
var err error
|
||||
if numBytes := len(SCTListExtension.Value); numBytes != 0 {
|
||||
serializedSCTList := new([]byte)
|
||||
rest := make([]byte, numBytes)
|
||||
copy(rest, SCTListExtension.Value)
|
||||
for len(rest) != 0 {
|
||||
rest, err = asn1.Unmarshal(rest, serializedSCTList)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
}
|
||||
sctList, err = DeserializeSCTList(*serializedSCTList)
|
||||
}
|
||||
return *sctList, err
|
||||
}
|
||||
|
||||
// ReadBytes reads a []byte either from a file or an environment variable.
|
||||
// If valFile has a prefix of 'env:', the []byte is read from the environment
|
||||
// using the subsequent name. If the prefix is 'file:' the []byte is read from
|
||||
// the subsequent file. If no prefix is provided, valFile is assumed to be a
|
||||
// file path.
|
||||
func ReadBytes(valFile string) ([]byte, error) {
|
||||
switch splitVal := strings.SplitN(valFile, ":", 2); len(splitVal) {
|
||||
case 1:
|
||||
return ioutil.ReadFile(valFile)
|
||||
case 2:
|
||||
switch splitVal[0] {
|
||||
case "env":
|
||||
return []byte(os.Getenv(splitVal[1])), nil
|
||||
case "file":
|
||||
return ioutil.ReadFile(splitVal[1])
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown prefix: %s", splitVal[0])
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("multiple prefixes: %s",
|
||||
strings.Join(splitVal[:len(splitVal)-1], ", "))
|
||||
}
|
||||
}
|
||||
|
36
vendor/github.com/cloudflare/cfssl/log/log.go
generated
vendored
36
vendor/github.com/cloudflare/cfssl/log/log.go
generated
vendored
@@ -6,7 +6,6 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -45,12 +44,12 @@ var Level = LevelInfo
|
||||
//
|
||||
// SyslogWriter is satisfied by *syslog.Writer.
|
||||
type SyslogWriter interface {
|
||||
Debug(string) error
|
||||
Info(string) error
|
||||
Warning(string) error
|
||||
Err(string) error
|
||||
Crit(string) error
|
||||
Emerg(string) error
|
||||
Debug(string)
|
||||
Info(string)
|
||||
Warning(string)
|
||||
Err(string)
|
||||
Crit(string)
|
||||
Emerg(string)
|
||||
}
|
||||
|
||||
// syslogWriter stores the SetLogger() parameter.
|
||||
@@ -63,33 +62,22 @@ func SetLogger(logger SyslogWriter) {
|
||||
syslogWriter = logger
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Only define loglevel flag once.
|
||||
if flag.Lookup("loglevel") == nil {
|
||||
flag.IntVar(&Level, "loglevel", LevelInfo, "Log level (0 = DEBUG, 5 = FATAL)")
|
||||
}
|
||||
}
|
||||
|
||||
func print(l int, msg string) {
|
||||
if l >= Level {
|
||||
if syslogWriter != nil {
|
||||
var err error
|
||||
switch l {
|
||||
case LevelDebug:
|
||||
err = syslogWriter.Debug(msg)
|
||||
syslogWriter.Debug(msg)
|
||||
case LevelInfo:
|
||||
err = syslogWriter.Info(msg)
|
||||
syslogWriter.Info(msg)
|
||||
case LevelWarning:
|
||||
err = syslogWriter.Warning(msg)
|
||||
syslogWriter.Warning(msg)
|
||||
case LevelError:
|
||||
err = syslogWriter.Err(msg)
|
||||
syslogWriter.Err(msg)
|
||||
case LevelCritical:
|
||||
err = syslogWriter.Crit(msg)
|
||||
syslogWriter.Crit(msg)
|
||||
case LevelFatal:
|
||||
err = syslogWriter.Emerg(msg)
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("Unable to write syslog: %v for msg: %s\n", err, msg)
|
||||
syslogWriter.Emerg(msg)
|
||||
}
|
||||
} else {
|
||||
log.Printf("[%s] %s", levelPrefix[l], msg)
|
||||
|
1
vendor/github.com/cloudflare/cfssl/signer/BUILD
generated
vendored
1
vendor/github.com/cloudflare/cfssl/signer/BUILD
generated
vendored
@@ -10,7 +10,6 @@ go_library(
|
||||
"//vendor/github.com/cloudflare/cfssl/config:go_default_library",
|
||||
"//vendor/github.com/cloudflare/cfssl/csr:go_default_library",
|
||||
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
|
||||
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
|
||||
"//vendor/github.com/cloudflare/cfssl/info:go_default_library",
|
||||
],
|
||||
)
|
||||
|
6
vendor/github.com/cloudflare/cfssl/signer/local/BUILD
generated
vendored
6
vendor/github.com/cloudflare/cfssl/signer/local/BUILD
generated
vendored
@@ -13,8 +13,10 @@ go_library(
|
||||
"//vendor/github.com/cloudflare/cfssl/info:go_default_library",
|
||||
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
|
||||
"//vendor/github.com/cloudflare/cfssl/signer:go_default_library",
|
||||
"//vendor/github.com/google/certificate-transparency/go:go_default_library",
|
||||
"//vendor/github.com/google/certificate-transparency/go/client:go_default_library",
|
||||
"//vendor/github.com/google/certificate-transparency-go:go_default_library",
|
||||
"//vendor/github.com/google/certificate-transparency-go/client:go_default_library",
|
||||
"//vendor/github.com/google/certificate-transparency-go/jsonclient:go_default_library",
|
||||
"//vendor/golang.org/x/net/context:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
118
vendor/github.com/cloudflare/cfssl/signer/local/local.go
generated
vendored
118
vendor/github.com/cloudflare/cfssl/signer/local/local.go
generated
vendored
@@ -8,14 +8,13 @@ import (
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
"os"
|
||||
|
||||
@@ -26,8 +25,10 @@ import (
|
||||
"github.com/cloudflare/cfssl/info"
|
||||
"github.com/cloudflare/cfssl/log"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/google/certificate-transparency/go"
|
||||
"github.com/google/certificate-transparency/go/client"
|
||||
"github.com/google/certificate-transparency-go"
|
||||
"github.com/google/certificate-transparency-go/client"
|
||||
"github.com/google/certificate-transparency-go/jsonclient"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Signer contains a signer that uses the standard library to
|
||||
@@ -65,12 +66,12 @@ func NewSigner(priv crypto.Signer, cert *x509.Certificate, sigAlgo x509.Signatur
|
||||
// and a caKey file, both PEM encoded.
|
||||
func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signer, error) {
|
||||
log.Debug("Loading CA: ", caFile)
|
||||
ca, err := ioutil.ReadFile(caFile)
|
||||
ca, err := helpers.ReadBytes(caFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debug("Loading CA key: ", caKeyFile)
|
||||
cakey, err := ioutil.ReadFile(caKeyFile)
|
||||
cakey, err := helpers.ReadBytes(caKeyFile)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ReadFailed, err)
|
||||
}
|
||||
@@ -95,12 +96,7 @@ 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) {
|
||||
err = signer.FillTemplate(template, s.policy.Default, profile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Signer) sign(template *x509.Certificate) (cert []byte, err error) {
|
||||
var initRoot bool
|
||||
if s.ca == nil {
|
||||
if !template.IsCA {
|
||||
@@ -111,11 +107,6 @@ func (s *Signer) sign(template *x509.Certificate, profile *config.SigningProfile
|
||||
template.EmailAddresses = nil
|
||||
s.ca = template
|
||||
initRoot = true
|
||||
template.MaxPathLen = signer.MaxPathLen
|
||||
} else if template.IsCA {
|
||||
template.MaxPathLen = 1
|
||||
template.DNSNames = nil
|
||||
template.EmailAddresses = nil
|
||||
}
|
||||
|
||||
derBytes, err := x509.CreateCertificate(rand.Reader, template, s.ca, template.PublicKey, s.priv)
|
||||
@@ -203,9 +194,9 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
||||
return nil, cferr.New(cferr.CSRError, cferr.DecodeFailed)
|
||||
}
|
||||
|
||||
if block.Type != "CERTIFICATE REQUEST" {
|
||||
if block.Type != "NEW CERTIFICATE REQUEST" && block.Type != "CERTIFICATE REQUEST" {
|
||||
return nil, cferr.Wrap(cferr.CSRError,
|
||||
cferr.BadRequest, errors.New("not a certificate or csr"))
|
||||
cferr.BadRequest, errors.New("not a csr"))
|
||||
}
|
||||
|
||||
csrTemplate, err := signer.ParseCertificateRequest(s, block.Bytes)
|
||||
@@ -243,6 +234,29 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if req.CRLOverride != "" {
|
||||
safeTemplate.CRLDistributionPoints = []string{req.CRLOverride}
|
||||
}
|
||||
|
||||
if safeTemplate.IsCA {
|
||||
if !profile.CAConstraint.IsCA {
|
||||
log.Error("local signer policy disallows issuing CA certificate")
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
|
||||
}
|
||||
|
||||
if s.ca != nil && s.ca.MaxPathLen > 0 {
|
||||
if safeTemplate.MaxPathLen >= s.ca.MaxPathLen {
|
||||
log.Error("local signer certificate disallows CA MaxPathLen extending")
|
||||
// do not sign a cert with pathlen > current
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
|
||||
}
|
||||
} else if s.ca != nil && s.ca.MaxPathLen == 0 && s.ca.MaxPathLenZero {
|
||||
log.Error("local signer certificate disallows issuing CA certificate")
|
||||
// signer has pathlen of 0, do not sign more intermediate CAs
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
|
||||
}
|
||||
}
|
||||
|
||||
OverrideHosts(&safeTemplate, req.Hosts)
|
||||
safeTemplate.Subject = PopulateSubjectFromCSR(req.Subject, safeTemplate.Subject)
|
||||
|
||||
@@ -250,17 +264,17 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
||||
if profile.NameWhitelist != nil {
|
||||
if safeTemplate.Subject.CommonName != "" {
|
||||
if profile.NameWhitelist.Find([]byte(safeTemplate.Subject.CommonName)) == nil {
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
|
||||
}
|
||||
}
|
||||
for _, name := range safeTemplate.DNSNames {
|
||||
if profile.NameWhitelist.Find([]byte(name)) == nil {
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
|
||||
}
|
||||
}
|
||||
for _, name := range safeTemplate.EmailAddresses {
|
||||
if profile.NameWhitelist.Find([]byte(name)) == nil {
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -312,6 +326,15 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
var distPoints = safeTemplate.CRLDistributionPoints
|
||||
err = signer.FillTemplate(&safeTemplate, s.policy.Default, profile, req.NotBefore, req.NotAfter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if distPoints != nil && len(distPoints) > 0 {
|
||||
safeTemplate.CRLDistributionPoints = distPoints
|
||||
}
|
||||
|
||||
var certTBS = safeTemplate
|
||||
|
||||
if len(profile.CTLogServers) > 0 {
|
||||
@@ -319,20 +342,24 @@ 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)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
derCert, _ := pem.Decode(cert)
|
||||
prechain := []ct.ASN1Cert{derCert.Bytes, s.ca.Raw}
|
||||
prechain := []ct.ASN1Cert{{Data: derCert.Bytes}, {Data: s.ca.Raw}}
|
||||
var sctList []ct.SignedCertificateTimestamp
|
||||
|
||||
for _, server := range profile.CTLogServers {
|
||||
log.Infof("submitting poisoned precertificate to %s", server)
|
||||
var ctclient = client.New(server)
|
||||
ctclient, err := client.New(server, nil, jsonclient.Options{})
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.PrecertSubmissionFailed, err)
|
||||
}
|
||||
var resp *ct.SignedCertificateTimestamp
|
||||
resp, err = ctclient.AddPreChain(prechain)
|
||||
ctx := context.Background()
|
||||
resp, err = ctclient.AddPreChain(ctx, prechain)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.PrecertSubmissionFailed, err)
|
||||
}
|
||||
@@ -340,7 +367,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
||||
}
|
||||
|
||||
var serializedSCTList []byte
|
||||
serializedSCTList, err = serializeSCTList(sctList)
|
||||
serializedSCTList, err = helpers.SerializeSCTList(sctList)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
@@ -355,17 +382,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)
|
||||
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,
|
||||
@@ -382,22 +414,6 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
||||
return signedCert, nil
|
||||
}
|
||||
|
||||
func serializeSCTList(sctList []ct.SignedCertificateTimestamp) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
for _, sct := range sctList {
|
||||
sct, err := ct.SerializeSCT(sct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
binary.Write(&buf, binary.BigEndian, uint16(len(sct)))
|
||||
buf.Write(sct)
|
||||
}
|
||||
|
||||
var sctListLengthField = make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(sctListLengthField, uint16(buf.Len()))
|
||||
return bytes.Join([][]byte{sctListLengthField, buf.Bytes()}, nil), nil
|
||||
}
|
||||
|
||||
// Info return a populated info.Resp struct or an error.
|
||||
func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
|
||||
cert, err := s.Certificate(req.Label, req.Profile)
|
||||
@@ -441,6 +457,16 @@ 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
|
||||
}
|
||||
|
||||
// Policy returns the signer's policy.
|
||||
func (s *Signer) Policy() *config.Signing {
|
||||
return s.policy
|
||||
|
123
vendor/github.com/cloudflare/cfssl/signer/signer.go
generated
vendored
123
vendor/github.com/cloudflare/cfssl/signer/signer.go
generated
vendored
@@ -12,6 +12,7 @@ import (
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -19,13 +20,9 @@ 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"
|
||||
)
|
||||
|
||||
// MaxPathLen is the default path length for a new CA certificate.
|
||||
var MaxPathLen = 2
|
||||
|
||||
// Subject contains the information that should be used to override the
|
||||
// subject information when signing a certificate.
|
||||
type Subject struct {
|
||||
@@ -50,13 +47,23 @@ type Extension struct {
|
||||
// Extensions requested in the CSR are ignored, except for those processed by
|
||||
// ParseCertificateRequest (mainly subjectAltName).
|
||||
type SignRequest struct {
|
||||
Hosts []string `json:"hosts"`
|
||||
Request string `json:"certificate_request"`
|
||||
Subject *Subject `json:"subject,omitempty"`
|
||||
Profile string `json:"profile"`
|
||||
Label string `json:"label"`
|
||||
Serial *big.Int `json:"serial,omitempty"`
|
||||
Extensions []Extension `json:"extensions,omitempty"`
|
||||
Hosts []string `json:"hosts"`
|
||||
Request string `json:"certificate_request"`
|
||||
Subject *Subject `json:"subject,omitempty"`
|
||||
Profile string `json:"profile"`
|
||||
CRLOverride string `json:"crl_override"`
|
||||
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.
|
||||
@@ -98,9 +105,11 @@ 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)
|
||||
SetReqModifier(func(*http.Request, []byte))
|
||||
}
|
||||
|
||||
// Profile gets the specific profile from the signer
|
||||
@@ -157,26 +166,46 @@ func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
|
||||
// ParseCertificateRequest takes an incoming certificate request and
|
||||
// builds a certificate template from it.
|
||||
func ParseCertificateRequest(s Signer, csrBytes []byte) (template *x509.Certificate, err error) {
|
||||
csr, err := x509.ParseCertificateRequest(csrBytes)
|
||||
csrv, err := x509.ParseCertificateRequest(csrBytes)
|
||||
if err != nil {
|
||||
err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = helpers.CheckSignature(csr, csr.SignatureAlgorithm, csr.RawTBSCertificateRequest, csr.Signature)
|
||||
err = csrv.CheckSignature()
|
||||
if err != nil {
|
||||
err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
|
||||
return
|
||||
}
|
||||
|
||||
template = &x509.Certificate{
|
||||
Subject: csr.Subject,
|
||||
PublicKeyAlgorithm: csr.PublicKeyAlgorithm,
|
||||
PublicKey: csr.PublicKey,
|
||||
Subject: csrv.Subject,
|
||||
PublicKeyAlgorithm: csrv.PublicKeyAlgorithm,
|
||||
PublicKey: csrv.PublicKey,
|
||||
SignatureAlgorithm: s.SigAlgo(),
|
||||
DNSNames: csr.DNSNames,
|
||||
IPAddresses: csr.IPAddresses,
|
||||
EmailAddresses: csr.EmailAddresses,
|
||||
DNSNames: csrv.DNSNames,
|
||||
IPAddresses: csrv.IPAddresses,
|
||||
EmailAddresses: csrv.EmailAddresses,
|
||||
}
|
||||
|
||||
for _, val := range csrv.Extensions {
|
||||
// Check the CSR for the X.509 BasicConstraints (RFC 5280, 4.2.1.9)
|
||||
// extension and append to template if necessary
|
||||
if val.Id.Equal(asn1.ObjectIdentifier{2, 5, 29, 19}) {
|
||||
var constraints csr.BasicConstraints
|
||||
var rest []byte
|
||||
|
||||
if rest, err = asn1.Unmarshal(val.Value, &constraints); err != nil {
|
||||
return nil, cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
|
||||
} else if len(rest) != 0 {
|
||||
return nil, cferr.Wrap(cferr.CSRError, cferr.ParseFailed, errors.New("x509: trailing data after X.509 BasicConstraints"))
|
||||
}
|
||||
|
||||
template.BasicConstraintsValid = true
|
||||
template.IsCA = constraints.IsCA
|
||||
template.MaxPathLen = constraints.MaxPathLen
|
||||
template.MaxPathLenZero = template.MaxPathLen == 0
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
@@ -211,17 +240,19 @@ 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
|
||||
}
|
||||
|
||||
var (
|
||||
eku []x509.ExtKeyUsage
|
||||
ku x509.KeyUsage
|
||||
backdate time.Duration
|
||||
expiry time.Duration
|
||||
notBefore time.Time
|
||||
notAfter time.Time
|
||||
crlURL, ocspURL string
|
||||
issuerURL = profile.IssuerURL
|
||||
)
|
||||
|
||||
// The third value returned from Usages is a list of unknown key usages.
|
||||
@@ -229,7 +260,7 @@ func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.Si
|
||||
// here.
|
||||
ku, eku, _ = profile.Usages()
|
||||
if profile.IssuerURL == nil {
|
||||
profile.IssuerURL = defaultProfile.IssuerURL
|
||||
issuerURL = defaultProfile.IssuerURL
|
||||
}
|
||||
|
||||
if ku == 0 && len(eku) == 0 {
|
||||
@@ -246,30 +277,44 @@ 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
|
||||
template.KeyUsage = ku
|
||||
template.ExtKeyUsage = eku
|
||||
template.BasicConstraintsValid = true
|
||||
template.IsCA = profile.CA
|
||||
template.IsCA = profile.CAConstraint.IsCA
|
||||
if template.IsCA {
|
||||
template.MaxPathLen = profile.CAConstraint.MaxPathLen
|
||||
if template.MaxPathLen == 0 {
|
||||
template.MaxPathLenZero = profile.CAConstraint.MaxPathLenZero
|
||||
}
|
||||
template.DNSNames = nil
|
||||
template.EmailAddresses = nil
|
||||
}
|
||||
template.SubjectKeyId = ski
|
||||
|
||||
if ocspURL != "" {
|
||||
@@ -279,8 +324,8 @@ func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.Si
|
||||
template.CRLDistributionPoints = []string{crlURL}
|
||||
}
|
||||
|
||||
if len(profile.IssuerURL) != 0 {
|
||||
template.IssuingCertificateURL = profile.IssuerURL
|
||||
if len(issuerURL) != 0 {
|
||||
template.IssuingCertificateURL = issuerURL
|
||||
}
|
||||
if len(profile.Policies) != 0 {
|
||||
err = addPolicies(template, profile.Policies)
|
||||
|
Reference in New Issue
Block a user