Commit 4709b338 authored by Jason Yellick's avatar Jason Yellick
Browse files

[FAB-5207] Check channel create channelID mismatch



The flow for channel creation works loosely as follows.

1. Look up channel resources by channelID from ChannelHeader
2. If missing, propose a new channel, based on the config update
3. Extract the channel ID from the config update, create a template
config from the consortium definition, and check if the config update
satisfies the channel creation policy.
4. Add the new channel resources to the channels map.

The problem is that between step 1/2 if the channelID is mismatched, the
internal channel construction logic will believe it is building
channelInner, while externally, this channel gets registered as
channelOuter.

Thus, it is possible to replay a channel creation TX by modifying the
outer header.  The new channel will be somewhat broken and all
configuration updates against it will fail.

This CR adds a simple check to verify that the ChannelHeader ChannelID
matches the ConfigUpdate channelID.

Change-Id: I23b088563016e0aa9f30524887c3c3d49b5942fb
Signed-off-by: default avatarJason Yellick <jyellick@us.ibm.com>
parent 9d159a79
......@@ -213,11 +213,20 @@ func (ml *multiLedger) NewChannelConfig(envConfigUpdate *cb.Envelope) (configtxa
return nil, fmt.Errorf("Failing initial channel config creation because of config update envelope unmarshaling error: %s", err)
}
if configUpdatePayload.Header == nil {
return nil, fmt.Errorf("Failed initial channel config creation because config update header was missing")
}
channelHeader, err := utils.UnmarshalChannelHeader(configUpdatePayload.Header.ChannelHeader)
configUpdate, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
if err != nil {
return nil, fmt.Errorf("Failing initial channel config creation because of config update unmarshaling error: %s", err)
}
if configUpdate.ChannelId != channelHeader.ChannelId {
return nil, fmt.Errorf("Failing initial channel config creation: mismatched channel IDs: '%s' != '%s'", configUpdate.ChannelId, channelHeader.ChannelId)
}
if configUpdate.WriteSet == nil {
return nil, fmt.Errorf("Config update has an empty writeset")
}
......
......@@ -299,6 +299,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"BadConfigUpdate",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: []byte("bad config update envelope data"),
}),
......@@ -308,6 +309,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"EmptyConfigUpdateWriteSet",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(
&cb.ConfigUpdate{},
......@@ -319,6 +321,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"WriteSetNoGroups",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(
&cb.ConfigUpdate{
......@@ -332,6 +335,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"WriteSetNoApplicationGroup",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(
&cb.ConfigUpdate{
......@@ -347,6 +351,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"BadWriteSetApplicationGroupVersion",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(
&cb.ConfigUpdate{
......@@ -366,6 +371,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"MissingWriteSetConsortiumValue",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(
&cb.ConfigUpdate{
......@@ -386,6 +392,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"BadWriteSetConsortiumValueValue",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(
&cb.ConfigUpdate{
......@@ -410,6 +417,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"UnknownConsortiumName",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(
&cb.ConfigUpdate{
......@@ -438,6 +446,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"Missing consortium members",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(
&cb.ConfigUpdate{
......@@ -466,6 +475,7 @@ func TestNewChannelConfig(t *testing.T) {
{
"Member not in consortium",
&cb.Payload{
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(
&cb.ConfigUpdate{
......@@ -505,6 +515,26 @@ func TestNewChannelConfig(t *testing.T) {
// SampleConsortium
}
func TestMismatchedChannelIDs(t *testing.T) {
innerChannelID := "foo"
outerChannelID := "bar"
template := configtx.NewChainCreationTemplate(genesisconfig.SampleConsortiumName, nil)
configUpdateEnvelope, err := template.Envelope(innerChannelID)
createTx, err := utils.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, outerChannelID, nil, configUpdateEnvelope, msgVersion, epoch)
assert.NoError(t, err)
lf, _ := NewRAMLedgerAndFactory(10)
consenters := make(map[string]Consenter)
consenters[conf.Orderer.OrdererType] = &mockConsenter{}
manager := NewManagerImpl(lf, consenters, mockCrypto())
_, err = manager.NewChannelConfig(createTx)
assert.Error(t, err, "Mismatched channel IDs")
assert.Regexp(t, "mismatched channel IDs", err.Error())
}
// This test brings up the entire system, with the mock consenter, including the broadcasters etc. and creates a new chain
func TestNewChain(t *testing.T) {
expectedLastConfigBlockNumber := uint64(0)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment