Skip to content

Commit 4709b33

Browse files
author
Jason Yellick
committed
[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: Jason Yellick <[email protected]>
1 parent 9d159a7 commit 4709b33

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

orderer/multichain/manager.go

+9
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,20 @@ func (ml *multiLedger) NewChannelConfig(envConfigUpdate *cb.Envelope) (configtxa
213213
return nil, fmt.Errorf("Failing initial channel config creation because of config update envelope unmarshaling error: %s", err)
214214
}
215215

216+
if configUpdatePayload.Header == nil {
217+
return nil, fmt.Errorf("Failed initial channel config creation because config update header was missing")
218+
}
219+
channelHeader, err := utils.UnmarshalChannelHeader(configUpdatePayload.Header.ChannelHeader)
220+
216221
configUpdate, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
217222
if err != nil {
218223
return nil, fmt.Errorf("Failing initial channel config creation because of config update unmarshaling error: %s", err)
219224
}
220225

226+
if configUpdate.ChannelId != channelHeader.ChannelId {
227+
return nil, fmt.Errorf("Failing initial channel config creation: mismatched channel IDs: '%s' != '%s'", configUpdate.ChannelId, channelHeader.ChannelId)
228+
}
229+
221230
if configUpdate.WriteSet == nil {
222231
return nil, fmt.Errorf("Config update has an empty writeset")
223232
}

orderer/multichain/manager_test.go

+30
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ func TestNewChannelConfig(t *testing.T) {
299299
{
300300
"BadConfigUpdate",
301301
&cb.Payload{
302+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
302303
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
303304
ConfigUpdate: []byte("bad config update envelope data"),
304305
}),
@@ -308,6 +309,7 @@ func TestNewChannelConfig(t *testing.T) {
308309
{
309310
"EmptyConfigUpdateWriteSet",
310311
&cb.Payload{
312+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
311313
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
312314
ConfigUpdate: utils.MarshalOrPanic(
313315
&cb.ConfigUpdate{},
@@ -319,6 +321,7 @@ func TestNewChannelConfig(t *testing.T) {
319321
{
320322
"WriteSetNoGroups",
321323
&cb.Payload{
324+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
322325
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
323326
ConfigUpdate: utils.MarshalOrPanic(
324327
&cb.ConfigUpdate{
@@ -332,6 +335,7 @@ func TestNewChannelConfig(t *testing.T) {
332335
{
333336
"WriteSetNoApplicationGroup",
334337
&cb.Payload{
338+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
335339
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
336340
ConfigUpdate: utils.MarshalOrPanic(
337341
&cb.ConfigUpdate{
@@ -347,6 +351,7 @@ func TestNewChannelConfig(t *testing.T) {
347351
{
348352
"BadWriteSetApplicationGroupVersion",
349353
&cb.Payload{
354+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
350355
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
351356
ConfigUpdate: utils.MarshalOrPanic(
352357
&cb.ConfigUpdate{
@@ -366,6 +371,7 @@ func TestNewChannelConfig(t *testing.T) {
366371
{
367372
"MissingWriteSetConsortiumValue",
368373
&cb.Payload{
374+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
369375
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
370376
ConfigUpdate: utils.MarshalOrPanic(
371377
&cb.ConfigUpdate{
@@ -386,6 +392,7 @@ func TestNewChannelConfig(t *testing.T) {
386392
{
387393
"BadWriteSetConsortiumValueValue",
388394
&cb.Payload{
395+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
389396
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
390397
ConfigUpdate: utils.MarshalOrPanic(
391398
&cb.ConfigUpdate{
@@ -410,6 +417,7 @@ func TestNewChannelConfig(t *testing.T) {
410417
{
411418
"UnknownConsortiumName",
412419
&cb.Payload{
420+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
413421
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
414422
ConfigUpdate: utils.MarshalOrPanic(
415423
&cb.ConfigUpdate{
@@ -438,6 +446,7 @@ func TestNewChannelConfig(t *testing.T) {
438446
{
439447
"Missing consortium members",
440448
&cb.Payload{
449+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
441450
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
442451
ConfigUpdate: utils.MarshalOrPanic(
443452
&cb.ConfigUpdate{
@@ -466,6 +475,7 @@ func TestNewChannelConfig(t *testing.T) {
466475
{
467476
"Member not in consortium",
468477
&cb.Payload{
478+
Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(utils.MakeChannelHeader(cb.HeaderType_CONFIG_UPDATE, 0, "", epoch))},
469479
Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
470480
ConfigUpdate: utils.MarshalOrPanic(
471481
&cb.ConfigUpdate{
@@ -505,6 +515,26 @@ func TestNewChannelConfig(t *testing.T) {
505515
// SampleConsortium
506516
}
507517

518+
func TestMismatchedChannelIDs(t *testing.T) {
519+
innerChannelID := "foo"
520+
outerChannelID := "bar"
521+
template := configtx.NewChainCreationTemplate(genesisconfig.SampleConsortiumName, nil)
522+
configUpdateEnvelope, err := template.Envelope(innerChannelID)
523+
createTx, err := utils.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, outerChannelID, nil, configUpdateEnvelope, msgVersion, epoch)
524+
assert.NoError(t, err)
525+
526+
lf, _ := NewRAMLedgerAndFactory(10)
527+
528+
consenters := make(map[string]Consenter)
529+
consenters[conf.Orderer.OrdererType] = &mockConsenter{}
530+
531+
manager := NewManagerImpl(lf, consenters, mockCrypto())
532+
533+
_, err = manager.NewChannelConfig(createTx)
534+
assert.Error(t, err, "Mismatched channel IDs")
535+
assert.Regexp(t, "mismatched channel IDs", err.Error())
536+
}
537+
508538
// This test brings up the entire system, with the mock consenter, including the broadcasters etc. and creates a new chain
509539
func TestNewChain(t *testing.T) {
510540
expectedLastConfigBlockNumber := uint64(0)

0 commit comments

Comments
 (0)