@@ -1373,9 +1373,115 @@ def _verify_root_self_signed(self, signable):
1373
1373
1374
1374
1375
1375
1376
+ def _validate_metadata_version (self , expected_version , metadata_role ,
1377
+ version_downloaded ):
1378
+ """
1379
+ <Purpose>
1380
+ Non-public method validating the metadata version number.
1381
+ If the expected_version is unspecified, ensure that the version number
1382
+ downloaded is equal or greater than the currently trusted version number
1383
+ for 'metadata_role'.
1384
+
1385
+ <Arguments>
1386
+ expected_version:
1387
+ An integer or "None" value representing the expected and required
1388
+ version number of the 'metadata_role' file downloaded.
1389
+
1390
+ metadata_role:
1391
+ The role name of the metadata (e.g., 'root', 'targets').
1392
+
1393
+ version_downloaded:
1394
+ The version of the newly downloaded metadata file.
1395
+
1396
+ <Exceptions>
1397
+ tuf.exceptions.BadVersionNumberError:
1398
+ In case the expected_version is not None and version_downloaded
1399
+ is not equal to it.
1400
+
1401
+ tuf.exceptions.ReplayedMetadataError:
1402
+ if expected_version is None and version_downloaded is lower than
1403
+ the current version.
1404
+ """
1405
+
1406
+ if expected_version is not None :
1407
+ if version_downloaded != expected_version :
1408
+ raise tuf .exceptions .BadVersionNumberError ('Downloaded'
1409
+ ' version number: ' + repr (version_downloaded ) + '. Version'
1410
+ ' number MUST be: ' + repr (expected_version ))
1411
+
1412
+ # The caller does not know which version to download.
1413
+ # Verify that the downloaded version is equal or
1414
+ # greater than the currently trusted version number.
1415
+ else :
1416
+ try :
1417
+ current_version = self .metadata ['current' ][metadata_role ]['version' ]
1418
+
1419
+ if version_downloaded < current_version :
1420
+ raise tuf .exceptions .ReplayedMetadataError (metadata_role ,
1421
+ version_downloaded , current_version )
1422
+
1423
+ except KeyError :
1424
+ logger .info (metadata_role + ' not available locally.' )
1425
+
1426
+
1427
+
1428
+ def _validate_spec_version (self , metadata_spec_version ):
1429
+ """
1430
+ <Purpose>
1431
+ Non-public method verifying a metadata specification version.
1432
+ It is assumed that "spec_version" is in (major.minor.fix) format,
1433
+ (for example: "1.4.3") and that releases with the same major version
1434
+ number maintain backward compatibility.
1435
+ Consequently, if the major version number of new metadata equals our
1436
+ expected major version number, the new metadata is safe to parse.
1437
+
1438
+ <Arguments>
1439
+ metadata_spec_version:
1440
+ A string representing the metadata spec version. It is assumed that
1441
+ it is in semantic versioning (major.minor.fix) format.
1442
+
1443
+ <Exceptions>
1444
+ tuf.exceptions.UnsupportedSpecificationError:
1445
+ In case the metadata major spec version is not supported.
1446
+
1447
+ securesystemslib.exceptions.FormatError:
1448
+ In case the metadata_spec_version string is not in the expected format.
1449
+ """
1450
+
1451
+ try :
1452
+ metadata_spec_version_split = metadata_spec_version .split ('.' )
1453
+ metadata_spec_major_version = int (metadata_spec_version_split [0 ])
1454
+ metadata_spec_minor_version = int (metadata_spec_version_split [1 ])
1455
+
1456
+ code_spec_version_split = tuf .SPECIFICATION_VERSION .split ('.' )
1457
+ code_spec_major_version = int (code_spec_version_split [0 ])
1458
+ code_spec_minor_version = int (code_spec_version_split [1 ])
1459
+
1460
+ if metadata_spec_major_version != code_spec_major_version :
1461
+ raise tuf .exceptions .UnsupportedSpecificationError (
1462
+ 'Downloaded metadata that specifies an unsupported spec_version. '
1463
+ 'This code supports major version number: ' +
1464
+ repr (code_spec_major_version ) + '; however,'
1465
+ 'metadata spec version is: ' + str (metadata_spec_version ))
1466
+
1467
+ # report to user if minor versions do not match, continue with update
1468
+ if metadata_spec_minor_version != code_spec_minor_version :
1469
+ logger .info ("Downloaded metadata that specifies a different minor " +
1470
+ "spec_version." )
1471
+ logger .info ("This code has version " + tuf .SPECIFICATION_VERSION +
1472
+ " and the metadata lists version number " +
1473
+ str (metadata_spec_version ) + "." )
1474
+ logger .info ("The update will continue as the major versions match." )
1475
+
1476
+ except (ValueError , TypeError ) as error :
1477
+ six .raise_from (securesystemslib .exceptions .FormatError ('Improperly'
1478
+ ' formatted spec_version, which must be in major.minor.fix format' ),
1479
+ error )
1480
+
1481
+
1376
1482
1377
1483
def _verify_metadata_file (self , metadata_file_object ,
1378
- metadata_role ):
1484
+ metadata_role , expected_version ):
1379
1485
"""
1380
1486
<Purpose>
1381
1487
Non-public method that verifies a metadata file. An exception is
@@ -1390,15 +1496,29 @@ def _verify_metadata_file(self, metadata_file_object,
1390
1496
The role name of the metadata (e.g., 'root', 'targets',
1391
1497
'unclaimed').
1392
1498
1499
+ expected_version:
1500
+ An integer or "None" value representing the expected and required
1501
+ version number of the 'metadata_role' file downloaded.
1502
+
1393
1503
<Exceptions>
1394
1504
securesystemslib.exceptions.FormatError:
1395
- In case the metadata file is valid JSON, but not valid TUF metadata.
1505
+ In case the metadata file is valid JSON, but not valid TUF metadata
1506
+ or when the metadata spec version is not in the rigth format.
1396
1507
1397
1508
tuf.exceptions.InvalidMetadataJSONError:
1398
1509
In case the metadata file is not valid JSON.
1399
1510
1511
+ tuf.exceptions.UnsupportedSpecificationError:
1512
+ In case the metadata spec version is not supported.
1513
+
1400
1514
tuf.exceptions.ReplayedMetadataError:
1401
- In case the downloaded metadata file is older than the current one.
1515
+ In case the downloaded metadata file is older than the current one or
1516
+ if expected_version is None and version_downloaded is lower than the
1517
+ trusted current version.
1518
+
1519
+ tuf.exceptions.BadVersionNumberError:
1520
+ In case the expected_version is not None and version_downloaded is not
1521
+ equal to it.
1402
1522
1403
1523
tuf.exceptions.RepositoryError:
1404
1524
In case the repository is somehow inconsistent; e.g. a parent has not
@@ -1429,6 +1549,11 @@ def _verify_metadata_file(self, metadata_file_object,
1429
1549
# 'securesystemslib.exceptions.FormatError' if not.
1430
1550
tuf .formats .check_signable_object_format (metadata_signable )
1431
1551
1552
+ self ._validate_spec_version (metadata_signable ['signed' ]['spec_version' ])
1553
+
1554
+ self ._validate_metadata_version (expected_version , metadata_role ,
1555
+ metadata_signable ['signed' ]['version' ])
1556
+
1432
1557
# Is 'metadata_signable' expired?
1433
1558
self ._ensure_not_expired (metadata_signable ['signed' ], metadata_role )
1434
1559
@@ -1482,8 +1607,8 @@ def _get_metadata_file(self, metadata_role, remote_filename,
1482
1607
downloaded.
1483
1608
1484
1609
expected_version:
1485
- The expected and required version number of the 'metadata_role' file
1486
- downloaded. 'expected_version' is an integer .
1610
+ An integer representing the expected and required version number
1611
+ of the 'metadata_role' file downloaded .
1487
1612
1488
1613
<Exceptions>
1489
1614
tuf.exceptions.NoWorkingMirrorError:
@@ -1510,85 +1635,9 @@ def _get_metadata_file(self, metadata_role, remote_filename,
1510
1635
try :
1511
1636
file_object = tuf .download .unsafe_download (file_mirror ,
1512
1637
upperbound_filelength )
1513
- file_object .seek (0 )
1514
-
1515
- # Verify 'file_object' according to the callable function.
1516
- # 'file_object' is also verified if decompressed above (i.e., the
1517
- # uncompressed version).
1518
- metadata_signable = \
1519
- securesystemslib .util .load_json_string (file_object .read ().decode ('utf-8' ))
1520
-
1521
- # Determine if the specification version number is supported. It is
1522
- # assumed that "spec_version" is in (major.minor.fix) format, (for
1523
- # example: "1.4.3") and that releases with the same major version
1524
- # number maintain backwards compatibility. Consequently, if the major
1525
- # version number of new metadata equals our expected major version
1526
- # number, the new metadata is safe to parse.
1527
- try :
1528
- metadata_spec_version = metadata_signable ['signed' ]['spec_version' ]
1529
- metadata_spec_version_split = metadata_spec_version .split ('.' )
1530
- metadata_spec_major_version = int (metadata_spec_version_split [0 ])
1531
- metadata_spec_minor_version = int (metadata_spec_version_split [1 ])
1532
-
1533
- code_spec_version_split = tuf .SPECIFICATION_VERSION .split ('.' )
1534
- code_spec_major_version = int (code_spec_version_split [0 ])
1535
- code_spec_minor_version = int (code_spec_version_split [1 ])
1536
-
1537
- if metadata_spec_major_version != code_spec_major_version :
1538
- raise tuf .exceptions .UnsupportedSpecificationError (
1539
- 'Downloaded metadata that specifies an unsupported '
1540
- 'spec_version. This code supports major version number: ' +
1541
- repr (code_spec_major_version ) + '; however, the obtained '
1542
- 'metadata lists version number: ' + str (metadata_spec_version ))
1543
-
1544
- #report to user if minor versions do not match, continue with update
1545
- if metadata_spec_minor_version != code_spec_minor_version :
1546
- logger .info ("Downloaded metadata that specifies a different minor " +
1547
- "spec_version. This code has version " +
1548
- str (tuf .SPECIFICATION_VERSION ) +
1549
- " and the metadata lists version number " +
1550
- str (metadata_spec_version ) +
1551
- ". The update will continue as the major versions match." )
1552
-
1553
- except (ValueError , TypeError ) as error :
1554
- six .raise_from (securesystemslib .exceptions .FormatError ('Improperly'
1555
- ' formatted spec_version, which must be in major.minor.fix format' ),
1556
- error )
1557
-
1558
- # If the version number is unspecified, ensure that the version number
1559
- # downloaded is greater than the currently trusted version number for
1560
- # 'metadata_role'.
1561
- version_downloaded = metadata_signable ['signed' ]['version' ]
1562
-
1563
- if expected_version is not None :
1564
- # Verify that the downloaded version matches the version expected by
1565
- # the caller.
1566
- if version_downloaded != expected_version :
1567
- raise tuf .exceptions .BadVersionNumberError ('Downloaded'
1568
- ' version number: ' + repr (version_downloaded ) + '. Version'
1569
- ' number MUST be: ' + repr (expected_version ))
1570
-
1571
- # The caller does not know which version to download. Verify that the
1572
- # downloaded version is at least greater than the one locally
1573
- # available.
1574
- else :
1575
- # Verify that the version number of the locally stored
1576
- # 'timestamp.json', if available, is less than what was downloaded.
1577
- # Otherwise, accept the new timestamp with version number
1578
- # 'version_downloaded'.
1579
-
1580
- try :
1581
- current_version = \
1582
- self .metadata ['current' ][metadata_role ]['version' ]
1583
-
1584
- if version_downloaded < current_version :
1585
- raise tuf .exceptions .ReplayedMetadataError (metadata_role ,
1586
- version_downloaded , current_version )
1587
-
1588
- except KeyError :
1589
- logger .info (metadata_role + ' not available locally.' )
1590
1638
1591
- self ._verify_metadata_file (file_object , metadata_role )
1639
+ self ._verify_metadata_file (file_object , metadata_role ,
1640
+ expected_version )
1592
1641
1593
1642
except Exception as exception :
1594
1643
# Remember the error from this mirror, and "reset" the target file.
0 commit comments