Skip to content

Commit

Permalink
Support for DelegationUsage extension
Browse files Browse the repository at this point in the history
This special cases the DelegationUsage extension, copying it to the
output when signing. It also adds support for a flag
delegation_enabled in certificate specifications. I have manually
confirmed this works.
  • Loading branch information
Watson Ladd committed Sep 15, 2021
1 parent 29ae05f commit a8591c3
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 15 deletions.
5 changes: 3 additions & 2 deletions cli/testdata/csr.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
"1.2.3.4.5": "abc"
}
}
]
}
],
"delegation_enabled": true
}
29 changes: 17 additions & 12 deletions csr/csr.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type Name struct {
L string `json:"L,omitempty" yaml:"L,omitempty"` // Locality
O string `json:"O,omitempty" yaml:"O,omitempty"` // OrganisationName
OU string `json:"OU,omitempty" yaml:"OU,omitempty"` // OrganisationalUnitName
E string `json:"E,omitempty" yaml:"E,omitempty"`
E string `json:"E,omitempty" yaml:"E,omitempty"`
SerialNumber string `json:"SerialNumber,omitempty" yaml:"SerialNumber,omitempty"`
OID map[string]string `json:"OID,omitempty", yaml:"OID,omitempty"`
}
Expand Down Expand Up @@ -136,14 +136,15 @@ type CAConfig struct {
// A CertificateRequest encapsulates the API interface to the
// certificate request functionality.
type CertificateRequest struct {
CN string `json:"CN" yaml:"CN"`
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"`
Extensions []pkix.Extension `json:"extensions,omitempty" yaml:"extensions,omitempty"`
CRL string `json:"crl_url,omitempty" yaml:"crl_url,omitempty"`
CN string `json:"CN" yaml:"CN"`
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"`
DelegationEnabled bool `json:"delegation_enabled,omitempty" yaml:"delegation_enabled,omitempty"`
Extensions []pkix.Extension `json:"extensions,omitempty" yaml:"extensions,omitempty"`
CRL string `json:"crl_url,omitempty" yaml:"crl_url,omitempty"`
}

// New returns a new, empty CertificateRequest with a
Expand Down Expand Up @@ -196,9 +197,9 @@ func (cr *CertificateRequest) Name() (pkix.Name, error) {
}
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: oid, Value: v})
}
if n.E != "" {
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: n.E})
}
if n.E != "" {
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: n.E})
}
}
name.SerialNumber = cr.SerialNumber
return name, nil
Expand Down Expand Up @@ -430,6 +431,10 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
}
}

if req.DelegationEnabled {
tpl.ExtraExtensions = append(tpl.Extensions, helpers.DelegationExtension)
}

if req.Extensions != nil {
err = appendExtensionsToCSR(req.Extensions, &tpl)
if err != nil {
Expand Down
47 changes: 47 additions & 0 deletions csr/csr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -786,3 +786,50 @@ func TestExtractCertificateRequest(t *testing.T) {
t.Fatal("Bad Certificate Request!")
}
}

// TestDelegationCSR tests that we create requests with the DC extension
func TestDelegationCSR(t *testing.T) {
var cr = &CertificateRequest{
CN: "Test Common Name",
Names: []Name{
{
C: "US",
ST: "California",
L: "San Francisco",
O: "CloudFlare, Inc.",
OU: "Systems Engineering",
},
{
C: "GB",
ST: "London",
L: "London",
O: "CloudFlare, Inc",
OU: "Systems Engineering",
},
},
DelegationEnabled: true,
Hosts: []string{"cloudflare.com", "www.cloudflare.com"},
KeyRequest: NewKeyRequest(),
}
csr, _, err := ParseRequest(cr)
if err != nil {
t.Fatal("could not generate csr")
}
unPem, _ := pem.Decode(csr)
if unPem == nil {
t.Fatal("Failed to decode pem")
}
res, err := x509.ParseCertificateRequest(unPem.Bytes)
if err != nil {
t.Fatalf("spat out nonsense as a csr: %v", err)
}
found := false
for _, ext := range res.Extensions {
if ext.Id.Equal(helpers.DelegationUsage) {
found = true
}
}
if !found {
t.Fatal("generated csr has no extension")
}
}
10 changes: 10 additions & 0 deletions helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ const OneYear = 8760 * time.Hour
// OneDay is a time.Duration representing a day's worth of seconds.
const OneDay = 24 * time.Hour

// DelegationUsage is the OID for the DelegationUseage extensions
var DelegationUsage = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 44}

// DelegationExtension
var DelegationExtension = pkix.Extension{
Id: DelegationUsage,
Critical: false,
Value: []byte{0x05, 0x00}, // ASN.1 NULL
}

// InclusiveDate returns the time.Time representation of a date - 1
// nanosecond. This allows time.After to be used inclusively.
func InclusiveDate(year int, month time.Month, day int) time.Time {
Expand Down
5 changes: 4 additions & 1 deletion signer/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ 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"
)

Expand All @@ -45,7 +46,7 @@ type Extension struct {
// Extensions provided in the signRequest are copied into the certificate, as
// long as they are in the ExtensionWhitelist for the signer's policy.
// Extensions requested in the CSR are ignored, except for those processed by
// ParseCertificateRequest (mainly subjectAltName).
// ParseCertificateRequest (mainly subjectAltName) and DelegationUsage.
type SignRequest struct {
Hosts []string `json:"hosts"`
Request string `json:"certificate_request"`
Expand Down Expand Up @@ -240,6 +241,8 @@ func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte
template.IsCA = constraints.IsCA
template.MaxPathLen = constraints.MaxPathLen
template.MaxPathLenZero = template.MaxPathLen == 0
} else if val.Id.Equal(helpers.DelegationUsage) {
template.ExtraExtensions = append(template.ExtraExtensions, val)
} else {
// If the profile has 'copy_extensions' to true then lets add it
if p.CopyExtensions {
Expand Down

0 comments on commit a8591c3

Please sign in to comment.