|
11 | 11 | import json |
12 | 12 | import inspect |
13 | 13 | import string |
| 14 | +import urllib.request |
| 15 | +import hashlib |
14 | 16 | from spdx_tools.spdx.model.document import Document |
15 | 17 | from spdx_tools.spdx.model.package import Package |
16 | 18 | from spdx_tools.spdx.parser import parse_anything |
@@ -96,7 +98,7 @@ def get_warnings(self): |
96 | 98 |
|
97 | 99 | def get_noasserts(self): |
98 | 100 | return list(problem for problem in self.items if problem.severity == Problem.SEVERITY_NOASSERT) |
99 | | - |
| 101 | + |
100 | 102 | def get_incorrect_urls(self): |
101 | 103 | return list(problem for problem in self.items if problem.severity == Problem.SEVERITY_INC_URL) |
102 | 104 |
|
@@ -564,6 +566,37 @@ def validate(self, |
564 | 566 | try: |
565 | 567 | logger.debug("Checking PackageDownloadLocation") |
566 | 568 | page = requests.get(package.download_location) |
| 569 | + |
| 570 | + # If we have a PackageChecksum, we verify it |
| 571 | + for algo in package.checksums: |
| 572 | + match algo.algorithm: |
| 573 | + case ChecksumAlgorithm.SHA1: |
| 574 | + algostring = "SHA1" |
| 575 | + case ChecksumAlgorithm.SHA224: |
| 576 | + algostring = "SHA224" |
| 577 | + case ChecksumAlgorithm.SHA256: |
| 578 | + algostring = "SHA256" |
| 579 | + case ChecksumAlgorithm.SHA384: |
| 580 | + algostring = "SHA384" |
| 581 | + case ChecksumAlgorithm.SHA512: |
| 582 | + algostring = "SHA512" |
| 583 | + case ChecksumAlgorithm.MD5: |
| 584 | + algostring = "MD5" |
| 585 | + case _: |
| 586 | + algostring = "" |
| 587 | + logger.error(f"{algo} is not supported.") |
| 588 | + calculated_checksum = package_checksum(package.download_location, algostring) |
| 589 | + if calculated_checksum == algo.value: |
| 590 | + logger.debug("Correct " + algostring + ": " + algo.value) |
| 591 | + else: |
| 592 | + problems.append("Invalid " + algostring, |
| 593 | + package.spdx_id, |
| 594 | + package.name, |
| 595 | + f"Checksum is {calculated_checksum}, should be {algo.value}", |
| 596 | + Problem.SCOPE_OPEN_CHAIN, |
| 597 | + Problem.SEVERITY_INC_URL, |
| 598 | + file) |
| 599 | + |
567 | 600 | except Exception as err: |
568 | 601 | logger.debug(f"Exception received ({format(err)})") |
569 | 602 | problems.append("Invalid field in Package", |
@@ -854,3 +887,16 @@ def referred_none(self, doc: Document, dir_name: str, problems: Problems, extens |
854 | 887 |
|
855 | 888 | def _dummy_referred_logic(self, doc: Document, dir_name: str, problems: Problems, extension: str = ""): |
856 | 889 | pass |
| 890 | + |
| 891 | +def package_checksum(download_location: str, algorithm: str): |
| 892 | + """Calculate package checksum""" |
| 893 | + algorithm = algorithm.upper() |
| 894 | + if not algorithm in ["SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "MD5"]: |
| 895 | + raise Exception("Unknown checksum algorithm: " + algorithm) |
| 896 | + tmp = "tmp" |
| 897 | + urllib.request.urlretrieve(download_location, tmp) |
| 898 | + with open(tmp, 'rb', buffering=0) as f: |
| 899 | + checksum = hashlib.file_digest(f, algorithm).hexdigest() |
| 900 | + f.close() |
| 901 | + os.remove(tmp) |
| 902 | + return checksum |
0 commit comments