Skip to content

Commit

Permalink
[FAB-7235] Check profile for isCA
Browse files Browse the repository at this point in the history
Check for the CSR and the profile for the isCA bit.
The new test case fails before this change and passes
with this change.

Change-Id: Id2ff218c34a8db389b88df329b949600c555a7a7
Signed-off-by: Keith Smith <[email protected]>
Signed-off-by: Anil Ambati <[email protected]>
  • Loading branch information
Keith Smith authored and Anil Ambati committed Dec 4, 2017
1 parent d365e50 commit 604a634
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 21 deletions.
3 changes: 3 additions & 0 deletions lib/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,9 @@ func (ca *CA) initConfig() (err error) {
if cfg.CA.Keyfile == "" {
cfg.CA.Keyfile = "ca-key.pem"
}
if cfg.CA.Chainfile == "" {
cfg.CA.Chainfile = "ca-chain.pem"
}
if cfg.CSR.CA == nil {
cfg.CSR.CA = &cfcsr.CAConfig{}
}
Expand Down
25 changes: 25 additions & 0 deletions lib/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,31 @@ func testRegister(c *Client, t *testing.T) {
if err == nil {
t.Fatalf("Enroll should have failed because %s does not have attr3", userName)
}

// Register a user with no attributes.
userName = "MyTestUserWithNoAttrs"
registerReq = &api.RegistrationRequest{
Name: userName,
Type: "client",
Affiliation: "hyperledger",
}
resp, err = adminID.Register(registerReq)
if err != nil {
t.Fatalf("Register of %s failed: %s", userName, err)
}
// Try to enroll the user with no attributes with the "ca" profile.
// Since the identity doesn't have the "hf.IntermediateCA" attribute,
// this should fail.
req = &api.EnrollmentRequest{
Name: userName,
Secret: resp.Secret,
Profile: "ca",
}
_, err = c.Enroll(req)
if err == nil {
t.Fatalf("Enroll to 'ca' profile should have failed because %s does not have the hf.IntermediateCA attribute", userName)
}

}

func checkAttrResult(t *testing.T, name, val string, attrs *attrmgr.Attributes) {
Expand Down
72 changes: 53 additions & 19 deletions lib/serverenroll.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"github.com/pkg/errors"

"github.com/cloudflare/cfssl/config"
"github.com/cloudflare/cfssl/csr"
cferr "github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/log"
Expand Down Expand Up @@ -178,25 +179,16 @@ func processSignRequest(id string, req *signer.SignRequest, ca *CA, ctx *serverR
if (req.Subject != nil && req.Subject.CN != id) || csrReq.Subject.CommonName != id {
return errors.New("The CSR subject common name must equal the enrollment ID")
}
// Check the CSR for the X.509 BasicConstraints extension (RFC 5280, 4.2.1.9)
for _, val := range csrReq.Extensions {
if val.Id.Equal(basicConstraintsOID) {
var constraints csr.BasicConstraints
var rest []byte
if rest, err = asn1.Unmarshal(val.Value, &constraints); err != nil {
return newHTTPErr(400, ErrBadCSR, "Failed parsing CSR constraints: %s", err)
} else if len(rest) != 0 {
return newHTTPErr(400, ErrBadCSR, "Trailing data after X.509 BasicConstraints")
}
if constraints.IsCA {
log.Debug("sign request received for an intermediate CA")
// This is a request for a CA certificate, so make sure the caller
// has the 'hf.IntermediateCA' attribute
err := ca.attributeIsTrue(id, "hf.IntermediateCA")
if err != nil {
return err
}
}
isForCACert, err := isRequestForCASigningCert(csrReq, ca, req.Profile)
if err != nil {
return err
}
if isForCACert {
// This is a request for a CA certificate, so make sure the caller
// has the 'hf.IntermediateCA' attribute
err := ca.attributeIsTrue(id, "hf.IntermediateCA")
if err != nil {
return err
}
}
// Check the CSR input length
Expand All @@ -214,6 +206,48 @@ func processSignRequest(id string, req *signer.SignRequest, ca *CA, ctx *serverR
return nil
}

// Check to see if this is a request for a CA signing certificate.
// This can occur if the profile or the CSR has the IsCA bit set.
// See the X.509 BasicConstraints extension (RFC 5280, 4.2.1.9).
func isRequestForCASigningCert(csrReq *x509.CertificateRequest, ca *CA, profile string) (bool, error) {
// Check the profile to see if the IsCA bit is set
sp := getSigningProfile(ca, profile)
if sp == nil {
return false, errors.Errorf("Invalid profile: '%s'", profile)
}
if sp.CAConstraint.IsCA {
log.Debugf("Request is for a CA signing certificate as set in profile '%s'", profile)
return true, nil
}
// Check the CSR to see if the IsCA bit is set
for _, val := range csrReq.Extensions {
if val.Id.Equal(basicConstraintsOID) {
var constraints csr.BasicConstraints
var rest []byte
var err error
if rest, err = asn1.Unmarshal(val.Value, &constraints); err != nil {
return false, newHTTPErr(400, ErrBadCSR, "Failed parsing CSR constraints: %s", err)
} else if len(rest) != 0 {
return false, newHTTPErr(400, ErrBadCSR, "Trailing data after X.509 BasicConstraints")
}
if constraints.IsCA {
log.Debug("Request is for a CA signing certificate as indicated in the CSR")
return true, nil
}
}
}
// The IsCA bit was not set
log.Debug("Request is not for a CA signing certificate")
return false, nil
}

func getSigningProfile(ca *CA, profile string) *config.SigningProfile {
if profile == "" {
return ca.Config.Signing.Default
}
return ca.Config.Signing.Profiles[profile]
}

// Checks to make sure that character limits are not exceeded for CSR fields
func csrInputLengthCheck(req *x509.CertificateRequest) error {
log.Debug("Checking CSR fields to make sure that they do not exceed maximum character limits")
Expand Down
4 changes: 2 additions & 2 deletions scripts/fvt/cluster_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -270,12 +270,12 @@ EOF
if test "$SERVER" = "$INTERMEDIATE_PROXY_PORT"; then
dbname=$INTDBNAME
userdir=$INTUSERDIR
stype=root
stype=intermediate
backend=intserver
else
dbname=$DBNAME
userdir=$ROOTUSERDIR
stype=intermediate
stype=root
backend=server
fi

Expand Down

0 comments on commit 604a634

Please sign in to comment.