diff --git a/msp/configbuilder_test.go b/msp/configbuilder_test.go new file mode 100644 index 00000000000..7ad39965c84 --- /dev/null +++ b/msp/configbuilder_test.go @@ -0,0 +1,46 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package msp + +import ( + "testing" + + "github.com/hyperledger/fabric/core/config" + "github.com/stretchr/testify/assert" +) + +func TestGetLocalMspConfig(t *testing.T) { + mspDir, err := config.GetDevMspDir() + assert.NoError(t, err) + _, err = GetLocalMspConfig(mspDir, nil, "DEFAULT") + assert.NoError(t, err) +} + +func TestGetLocalMspConfigFails(t *testing.T) { + _, err := GetLocalMspConfig("/tmp/", nil, "DEFAULT") + assert.Error(t, err) +} + +func TestReadFileUtils(t *testing.T) { + // test that reading a file with an empty path doesn't crash + _, err := readPemFile("") + assert.Error(t, err) + + // test that reading an existing file which is not a PEM file doesn't crash + _, err = readPemFile("/dev/null") + assert.Error(t, err) +} diff --git a/msp/identities.go b/msp/identities.go index fb05a917952..cc33fc6d763 100644 --- a/msp/identities.go +++ b/msp/identities.go @@ -144,12 +144,12 @@ func (id *identity) Verify(msg []byte, sig []byte) error { func (id *identity) VerifyOpts(msg []byte, sig []byte, opts SignatureOpts) error { // TODO - return nil + return errors.New("This method is unimplemented") } func (id *identity) VerifyAttributes(proof []byte, spec *AttributeProofSpec) error { // TODO - return nil + return errors.New("This method is unimplemented") } // Serialize returns a byte array representation of this identity @@ -225,12 +225,12 @@ func (id *signingidentity) Sign(msg []byte) ([]byte, error) { func (id *signingidentity) SignOpts(msg []byte, opts SignatureOpts) ([]byte, error) { // TODO - return nil, nil + return nil, errors.New("This method is unimplemented") } func (id *signingidentity) GetAttributeProof(spec *AttributeProofSpec) (proof []byte, err error) { // TODO - return nil, nil + return nil, errors.New("This method is unimplemented") } func (id *signingidentity) GetPublicVersion() Identity { @@ -239,5 +239,5 @@ func (id *signingidentity) GetPublicVersion() Identity { func (id *signingidentity) Renew() error { // TODO - return nil + return errors.New("This method is unimplemented") } diff --git a/msp/msp_test.go b/msp/msp_test.go index 052a964cb25..dd653dece72 100644 --- a/msp/msp_test.go +++ b/msp/msp_test.go @@ -32,12 +32,118 @@ import ( "github.com/stretchr/testify/assert" ) +var notACert = `-----BEGIN X509 CRL----- +MIIBYzCCAQgCAQEwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxEzARBgNVBAgT +CkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHzAdBgNVBAoTFklu +dGVybmV0IFdpZGdldHMsIEluYy4xDDAKBgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhh +bXBsZS5jb20XDTE3MDEyMzIwNTYyMFoXDTE3MDEyNjIwNTYyMFowJzAlAhQERXCx +LHROap1vM3CV40EHOghPTBcNMTcwMTIzMjA0NzMxWqAvMC0wHwYDVR0jBBgwFoAU +F2dCPaqegj/ExR2fW8OZ0bWcSBAwCgYDVR0UBAMCAQgwCgYIKoZIzj0EAwIDSQAw +RgIhAOTTpQYkGO+gwVe1LQOcNMD5fzFViOwBUraMrk6dRMlmAiEA8z2dpXKGwHrj +FRBbKkDnSpaVcZgjns+mLdHV2JkF0gk= +-----END X509 CRL-----` + +func TestMSPParsers(t *testing.T) { + _, _, err := localMsp.(*bccspmsp).getIdentityFromConf(nil) + assert.Error(t, err) + _, _, err = localMsp.(*bccspmsp).getIdentityFromConf([]byte("barf")) + assert.Error(t, err) + _, _, err = localMsp.(*bccspmsp).getIdentityFromConf([]byte(notACert)) + assert.Error(t, err) + + _, err = localMsp.(*bccspmsp).getSigningIdentityFromConf(nil) + assert.Error(t, err) + + sigid := &msp.SigningIdentityInfo{PublicSigner: []byte("barf"), PrivateSigner: nil} + _, err = localMsp.(*bccspmsp).getSigningIdentityFromConf(sigid) + + keyinfo := &msp.KeyInfo{KeyIdentifier: "PEER", KeyMaterial: nil} + sigid = &msp.SigningIdentityInfo{PublicSigner: []byte("barf"), PrivateSigner: keyinfo} + _, err = localMsp.(*bccspmsp).getSigningIdentityFromConf(sigid) + assert.Error(t, err) +} + +func TestMSPSetupNoCryptoConf(t *testing.T) { + mspDir, err := config.GetDevMspDir() + if err != nil { + fmt.Printf("Errog getting DevMspDir: %s", err) + os.Exit(-1) + } + + conf, err := GetLocalMspConfig(mspDir, nil, "DEFAULT") + if err != nil { + fmt.Printf("Setup should have succeeded, got err %s instead", err) + os.Exit(-1) + } + + mspconf := &msp.FabricMSPConfig{} + err = proto.Unmarshal(conf.Config, mspconf) + assert.NoError(t, err) + + // here we test the case of an MSP configuration + // where the hash function to be used to obtain + // the identity identifier is unspecified - a + // sane default should be picked + mspconf.CryptoConfig.IdentityIdentifierHashFunction = "" + b, err := proto.Marshal(mspconf) + assert.NoError(t, err) + conf.Config = b + newmsp, err := NewBccspMsp() + assert.NoError(t, err) + err = newmsp.Setup(conf) + assert.NoError(t, err) + + // here we test the case of an MSP configuration + // where the hash function to be used to compute + // signatures is unspecified - a sane default + // should be picked + mspconf.CryptoConfig.SignatureHashFamily = "" + b, err = proto.Marshal(mspconf) + assert.NoError(t, err) + conf.Config = b + newmsp, err = NewBccspMsp() + assert.NoError(t, err) + err = newmsp.Setup(conf) + assert.NoError(t, err) + + // here we test the case of an MSP configuration + // that has NO crypto configuration specified; + // the code will use appropriate defaults + mspconf.CryptoConfig = nil + b, err = proto.Marshal(mspconf) + assert.NoError(t, err) + conf.Config = b + newmsp, err = NewBccspMsp() + assert.NoError(t, err) + err = newmsp.Setup(conf) + assert.NoError(t, err) +} + +func TestGetters(t *testing.T) { + typ := localMsp.GetType() + assert.Equal(t, typ, FABRIC) + assert.NotNil(t, localMsp.GetRootCerts()) + assert.NotNil(t, localMsp.GetIntermediateCerts()) +} + func TestMSPSetupBad(t *testing.T) { _, err := GetLocalMspConfig("barf", nil, "DEFAULT") if err == nil { t.Fatalf("Setup should have failed on an invalid config file") return } + + mgr := NewMSPManager() + err = mgr.Setup(nil) + assert.Error(t, err) + err = mgr.Setup([]MSP{}) + assert.Error(t, err) +} + +func TestDoubleSetup(t *testing.T) { + // note that we've already called setup once on this + err := mspMgr.Setup(nil) + assert.NoError(t, err) } func TestGetIdentities(t *testing.T) { @@ -48,6 +154,47 @@ func TestGetIdentities(t *testing.T) { } } +func TestDeserializeIdentityFails(t *testing.T) { + _, err := localMsp.DeserializeIdentity([]byte("barf")) + assert.Error(t, err) + + id := &msp.SerializedIdentity{Mspid: "DEFAULT", IdBytes: []byte("barfr")} + b, err := proto.Marshal(id) + assert.NoError(t, err) + _, err = localMsp.DeserializeIdentity(b) + assert.Error(t, err) + + id = &msp.SerializedIdentity{Mspid: "DEFAULT", IdBytes: []byte(notACert)} + b, err = proto.Marshal(id) + assert.NoError(t, err) + _, err = localMsp.DeserializeIdentity(b) + assert.Error(t, err) +} + +func TestGetSigningIdentityFromVerifyingMSP(t *testing.T) { + mspDir, err := config.GetDevMspDir() + if err != nil { + fmt.Printf("Errog getting DevMspDir: %s", err) + os.Exit(-1) + } + + conf, err = GetVerifyingMspConfig(mspDir, nil, "DEFAULT") + if err != nil { + fmt.Printf("Setup should have succeeded, got err %s instead", err) + os.Exit(-1) + } + + newmsp, err := NewBccspMsp() + assert.NoError(t, err) + err = newmsp.Setup(conf) + assert.NoError(t, err) + + _, err = newmsp.GetDefaultSigningIdentity() + assert.Error(t, err) + _, err = newmsp.GetSigningIdentity(nil) + assert.Error(t, err) +} + func TestSerializeIdentities(t *testing.T) { id, err := localMsp.GetDefaultSigningIdentity() if err != nil { @@ -148,6 +295,39 @@ func TestSerializeIdentitiesWithMSPManager(t *testing.T) { assert.Error(t, err) } +func TestIdentitiesGetters(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + if err != nil { + t.Fatalf("GetSigningIdentity should have succeeded, got err %s", err) + return + } + + idid := id.GetIdentifier() + assert.NotNil(t, idid) + mspid := id.GetMSPIdentifier() + assert.NotNil(t, mspid) +} + +func TestUnimplementedMethods(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + if err != nil { + t.Fatalf("GetSigningIdentity should have succeeded, got err %s", err) + return + } + + // these methods are currently unimplemented - we assert that they return an error + err = id.VerifyOpts(nil, nil, SignatureOpts{}) + assert.Error(t, err) + err = id.VerifyAttributes(nil, nil) + assert.Error(t, err) + _, err = id.SignOpts(nil, SignatureOpts{}) + assert.Error(t, err) + _, err = id.GetAttributeProof(nil) + assert.Error(t, err) + err = id.Renew() + assert.Error(t, err) +} + func TestSignAndVerify(t *testing.T) { id, err := localMsp.GetDefaultSigningIdentity() if err != nil { @@ -185,6 +365,65 @@ func TestSignAndVerify(t *testing.T) { t.Fatalf("The signature should be valid") return } + + err = id.Verify(msg[1:], sig) + assert.Error(t, err) + err = id.Verify(msg, sig[1:]) + assert.Error(t, err) +} + +func TestSignAndVerifyFailures(t *testing.T) { + msg := []byte("foo") + + id, err := localMsp.GetDefaultSigningIdentity() + if err != nil { + t.Fatalf("GetSigningIdentity should have succeeded") + return + } + + hash := id.(*signingidentity).msp.cryptoConfig.SignatureHashFamily + id.(*signingidentity).msp.cryptoConfig.SignatureHashFamily = "barf" + + sig, err := id.Sign(msg) + assert.Error(t, err) + + id.(*signingidentity).msp.cryptoConfig.SignatureHashFamily = hash + + sig, err = id.Sign(msg) + if err != nil { + t.Fatalf("Sign should have succeeded") + return + } + + id.(*signingidentity).msp.cryptoConfig.SignatureHashFamily = "barf" + + err = id.Verify(msg, sig) + assert.Error(t, err) + + id.(*signingidentity).msp.cryptoConfig.SignatureHashFamily = hash +} + +func TestSignAndVerifyOtherHash(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + if err != nil { + t.Fatalf("GetSigningIdentity should have succeeded") + return + } + + hash := id.(*signingidentity).msp.cryptoConfig.SignatureHashFamily + id.(*signingidentity).msp.cryptoConfig.SignatureHashFamily = bccsp.SHA3 + + msg := []byte("foo") + sig, err := id.Sign(msg) + if err != nil { + t.Fatalf("Sign should have succeeded") + return + } + + err = id.Verify(msg, sig) + assert.NoError(t, err) + + id.(*signingidentity).msp.cryptoConfig.SignatureHashFamily = hash } func TestSignAndVerify_longMessage(t *testing.T) { @@ -236,6 +475,28 @@ func TestGetOU(t *testing.T) { assert.Equal(t, "COP", id.GetOrganizationalUnits()[0].OrganizationalUnitIdentifier) } +func TestGetOUFail(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + if err != nil { + t.Fatalf("GetSigningIdentity should have succeeded") + return + } + + certTmp := id.(*signingidentity).cert + id.(*signingidentity).cert = nil + ou := id.GetOrganizationalUnits() + assert.Nil(t, ou) + + id.(*signingidentity).cert = certTmp + + opts := id.(*signingidentity).msp.opts + id.(*signingidentity).msp.opts = nil + ou = id.GetOrganizationalUnits() + assert.Nil(t, ou) + + id.(*signingidentity).msp.opts = opts +} + func TestCertificationIdentifierComputation(t *testing.T) { id, err := localMsp.GetDefaultSigningIdentity() assert.NoError(t, err) @@ -278,6 +539,43 @@ func TestOUPolicyPrincipal(t *testing.T) { assert.NoError(t, err) } +func TestOUPolicyPrincipalBadPrincipal(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + assert.NoError(t, err) + + principal := &msp.MSPPrincipal{ + PrincipalClassification: msp.MSPPrincipal_ORGANIZATION_UNIT, + Principal: []byte("barf"), + } + + err = id.SatisfiesPrincipal(principal) + assert.Error(t, err) +} + +func TestOUPolicyPrincipalBadMSPID(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + assert.NoError(t, err) + + cid, err := localMsp.(*bccspmsp).getCertificationChainIdentifier(id.GetPublicVersion()) + assert.NoError(t, err) + + ou := &msp.OrganizationUnit{ + OrganizationalUnitIdentifier: "COP", + MspIdentifier: "DEFAULTbarfbarf", + CertifiersIdentifier: cid, + } + bytes, err := proto.Marshal(ou) + assert.NoError(t, err) + + principal := &msp.MSPPrincipal{ + PrincipalClassification: msp.MSPPrincipal_ORGANIZATION_UNIT, + Principal: bytes, + } + + err = id.SatisfiesPrincipal(principal) + assert.Error(t, err) +} + func TestOUPolicyPrincipalBadPath(t *testing.T) { id, err := localMsp.GetDefaultSigningIdentity() assert.NoError(t, err) @@ -315,6 +613,66 @@ func TestOUPolicyPrincipalBadPath(t *testing.T) { assert.Error(t, err) } +func TestPolicyPrincipalBogusType(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + assert.NoError(t, err) + + principalBytes, err := proto.Marshal(&msp.MSPRole{Role: 35, MspIdentifier: "DEFAULT"}) + assert.NoError(t, err) + + principal := &msp.MSPPrincipal{ + PrincipalClassification: 35, + Principal: principalBytes} + + err = id.SatisfiesPrincipal(principal) + assert.Error(t, err) +} + +func TestPolicyPrincipalBogusRole(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + assert.NoError(t, err) + + principalBytes, err := proto.Marshal(&msp.MSPRole{Role: 35, MspIdentifier: "DEFAULT"}) + assert.NoError(t, err) + + principal := &msp.MSPPrincipal{ + PrincipalClassification: msp.MSPPrincipal_ROLE, + Principal: principalBytes} + + err = id.SatisfiesPrincipal(principal) + assert.Error(t, err) +} + +func TestPolicyPrincipalWrongMSPID(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + assert.NoError(t, err) + + principalBytes, err := proto.Marshal(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "DEFAULTBARFBARF"}) + assert.NoError(t, err) + + principal := &msp.MSPPrincipal{ + PrincipalClassification: msp.MSPPrincipal_ROLE, + Principal: principalBytes} + + err = id.SatisfiesPrincipal(principal) + assert.Error(t, err) +} + +func TestMemberPolicyPrincipal(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + assert.NoError(t, err) + + principalBytes, err := proto.Marshal(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: "DEFAULT"}) + assert.NoError(t, err) + + principal := &msp.MSPPrincipal{ + PrincipalClassification: msp.MSPPrincipal_ROLE, + Principal: principalBytes} + + err = id.SatisfiesPrincipal(principal) + assert.NoError(t, err) +} + func TestAdminPolicyPrincipal(t *testing.T) { id, err := localMsp.GetDefaultSigningIdentity() assert.NoError(t, err) @@ -363,6 +721,18 @@ func TestIdentityPolicyPrincipal(t *testing.T) { assert.NoError(t, err) } +func TestIdentityPolicyPrincipalBadBytes(t *testing.T) { + id, err := localMsp.GetDefaultSigningIdentity() + assert.NoError(t, err) + + principal := &msp.MSPPrincipal{ + PrincipalClassification: msp.MSPPrincipal_IDENTITY, + Principal: []byte("barf")} + + err = id.SatisfiesPrincipal(principal) + assert.Error(t, err) +} + func TestMSPOus(t *testing.T) { // Set the OUIdentifiers backup := localMsp.(*bccspmsp).ouIdentifiers diff --git a/msp/mspimpl.go b/msp/mspimpl.go index 4d6f7ed3c28..ef3d285af5d 100644 --- a/msp/mspimpl.go +++ b/msp/mspimpl.go @@ -424,7 +424,7 @@ func (msp *bccspmsp) GetDefaultSigningIdentity() (SigningIdentity, error) { // identity identified by the supplied identifier func (msp *bccspmsp) GetSigningIdentity(identifier *IdentityIdentifier) (SigningIdentity, error) { // TODO - return nil, nil + return nil, fmt.Errorf("No signing identity for %#v", identifier) } // Validate attempts to determine whether