diff options
Diffstat (limited to 'poky/meta/recipes-core/meta/cve-update-nvd2-native.bb')
-rw-r--r-- | poky/meta/recipes-core/meta/cve-update-nvd2-native.bb | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/poky/meta/recipes-core/meta/cve-update-nvd2-native.bb b/poky/meta/recipes-core/meta/cve-update-nvd2-native.bb index 2b585983ac..2f7dad7e82 100644 --- a/poky/meta/recipes-core/meta/cve-update-nvd2-native.bb +++ b/poky/meta/recipes-core/meta/cve-update-nvd2-native.bb @@ -17,6 +17,10 @@ deltask do_populate_sysroot NVDCVE_URL ?= "https://services.nvd.nist.gov/rest/json/cves/2.0" +# If you have a NVD API key (https://nvd.nist.gov/developers/request-an-api-key) +# then setting this to get higher rate limits. +NVDCVE_API_KEY ?= "" + # CVE database update interval, in seconds. By default: once a day (24*60*60). # Use 0 to force the update # Use a negative value to skip the update @@ -119,18 +123,16 @@ def nvd_request_next(url, api_key, args): import urllib.parse import gzip import http + import time - headers = {} + request = urllib.request.Request(url + "?" + urllib.parse.urlencode(args)) if api_key: - headers['apiKey'] = api_key - - data = urllib.parse.urlencode(args) - - full_request = url + '?' + data + request.add_header("apiKey", api_key) + bb.note("Requesting %s" % request.full_url) - for attempt in range(3): + for attempt in range(5): try: - r = urllib.request.urlopen(full_request) + r = urllib.request.urlopen(request) if (r.headers['content-encoding'] == 'gzip'): buf = r.read() @@ -140,13 +142,9 @@ def nvd_request_next(url, api_key, args): r.close() - except UnicodeDecodeError: - # Received garbage, retry - bb.debug(2, "CVE database: received malformed data, retrying (request: %s)" %(full_request)) - pass - except http.client.IncompleteRead: - # Read incomplete, let's try again - bb.debug(2, "CVE database: received incomplete data, retrying (request: %s)" %(full_request)) + except Exception as e: + bb.note("CVE database: received error (%s), retrying" % (e)) + time.sleep(6) pass else: return raw_data @@ -172,11 +170,11 @@ def update_db_file(db_tmp_file, d, database_time): # The maximum range for time is 120 days # Force a complete update if our range is longer if (database_time != 0): - database_date = datetime.datetime.combine(datetime.date.fromtimestamp(database_time), datetime.time()) - today_date = datetime.datetime.combine(datetime.date.today(), datetime.time()) + database_date = datetime.datetime.fromtimestamp(database_time, tz=datetime.timezone.utc) + today_date = datetime.datetime.now(tz=datetime.timezone.utc) delta = today_date - database_date if delta.days < 120: - bb.debug(2, "CVE database: performing partial update") + bb.note("CVE database: performing partial update") req_args['lastModStartDate'] = database_date.isoformat() req_args['lastModEndDate'] = today_date.isoformat() else: @@ -184,12 +182,14 @@ def update_db_file(db_tmp_file, d, database_time): with bb.progress.ProgressHandler(d) as ph, open(os.path.join(d.getVar("TMPDIR"), 'cve_check'), 'a') as cve_f: - bb.debug(2, "Updating entries") + bb.note("Updating entries") index = 0 url = d.getVar("NVDCVE_URL") + api_key = d.getVar("NVDCVE_API_KEY") or None + while True: req_args['startIndex'] = index - raw_data = nvd_request_next(url, None, req_args) + raw_data = nvd_request_next(url, api_key, req_args) if raw_data is None: # We haven't managed to download data return False @@ -199,7 +199,7 @@ def update_db_file(db_tmp_file, d, database_time): index = data["startIndex"] total = data["totalResults"] per_page = data["resultsPerPage"] - + bb.note("Got %d entries" % per_page) for cve in data["vulnerabilities"]: update_db(conn, cve) @@ -312,22 +312,30 @@ def update_db(conn, elt): cvssv2 = elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['baseScore'] except KeyError: cvssv2 = 0.0 + cvssv3 = None try: - accessVector = accessVector or elt['impact']['baseMetricV3']['cvssV3']['attackVector'] - cvssv3 = elt['impact']['baseMetricV3']['cvssV3']['baseScore'] + accessVector = accessVector or elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['attackVector'] + cvssv3 = elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['baseScore'] except KeyError: - accessVector = accessVector or "UNKNOWN" - cvssv3 = 0.0 + pass + try: + accessVector = accessVector or elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['attackVector'] + cvssv3 = cvssv3 or elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['baseScore'] + except KeyError: + pass + accessVector = accessVector or "UNKNOWN" + cvssv3 = cvssv3 or 0.0 conn.execute("insert or replace into NVD values (?, ?, ?, ?, ?, ?)", [cveId, cveDesc, cvssv2, cvssv3, date, accessVector]).close() try: - configurations = elt['cve']['configurations'][0]['nodes'] - for config in configurations: - parse_node_and_insert(conn, config, cveId) + for config in elt['cve']['configurations']: + # This is suboptimal as it doesn't handle AND/OR and negate, but is better than nothing + for node in config["nodes"]: + parse_node_and_insert(conn, node, cveId) except KeyError: - bb.debug(2, "Entry without a configuration") + bb.note("CVE %s has no configurations" % cveId) do_fetch[nostamp] = "1" |