@@ -417,12 +417,31 @@ func New(
417
417
Cert : cert ,
418
418
}
419
419
chkp := checkpoint .StableCheckpointFromPb (_chkp .Pb ())
420
- // TODO: Technically this is wrong.
421
- // The memberhips information in the checkpint is used to verify the checkpoint itself.
422
- // This makes it possible to construct an arbitrary valid checkpoint.
423
- // Use an independent local source of memberhip information instead.
424
- if err := chkp .VerifyCert (iss .hashImpl , iss .chkpVerifier , chkp .PreviousMembership ()); err != nil {
425
- iss .logger .Log (logging .LevelWarn , "Ignoring stable checkpoint. Certificate don walid." ,
420
+ chkpMembershipOffset := int (chkp .Epoch ()) - 1 - int (iss .epoch .Nr ())
421
+
422
+ // Check how far the received stable checkpoint is ahead of the local node's state.
423
+ if chkpMembershipOffset <= 0 {
424
+ // Ignore stable checkpoints that are not far enough
425
+ // ahead of the current state of the local node.
426
+ return nil
427
+ }
428
+
429
+ chkpMembership := chkp .PreviousMembership () // TODO this is wrong and it is a vulnerability, come back to fix after discussion (issue #384)
430
+ if chkpMembershipOffset > iss .Params .ConfigOffset {
431
+ // cannot verify checkpoint signatures, too far ahead
432
+ // TODO here we should externalize verification/decision to dedicated module (issue #402)
433
+ iss .logger .Log (logging .LevelWarn , "-----------------------------------------------------\n " ,
434
+ "ATTENTION: cannot verify membership of checkpoint, too far ahead, proceed with caution\n " ,
435
+ "-----------------------------------------------------\n " ,
436
+ "localEpoch" , iss .epoch .Nr (),
437
+ "chkpEpoch" , chkp .Epoch (),
438
+ "configOffset" , iss .Params .ConfigOffset ,
439
+ )
440
+ } else {
441
+ chkpMembership = iss .memberships [chkpMembershipOffset ]
442
+ }
443
+ if err := chkp .VerifyCert (iss .hashImpl , iss .chkpVerifier , chkpMembership ); err != nil {
444
+ iss .logger .Log (logging .LevelWarn , "Ignoring stable checkpoint. Certificate not valid." ,
426
445
"localEpoch" , iss .epoch .Nr (),
427
446
"chkpEpoch" , chkp .Epoch (),
428
447
)
@@ -437,13 +456,6 @@ func New(
437
456
return nil
438
457
}
439
458
440
- // Check how far the received stable checkpoint is ahead of the local node's state.
441
- if chkp .Epoch () <= iss .epoch .Nr ()+ 1 {
442
- // Ignore stable checkpoints that are not far enough
443
- // ahead of the current state of the local node.
444
- return nil
445
- }
446
-
447
459
// Deserialize received leader selection policy. If deserialization fails, ignore the whole message.
448
460
result , err := lsp .LeaderPolicyFromBytes (chkp .Snapshot .EpochData .LeaderPolicy )
449
461
if err != nil {
0 commit comments