Merge ~sbeattie/ubuntu-cve-tracker/+git/ubuntu-cve-tracker:create_uct_module_refactoring into ubuntu-cve-tracker:master
- Git
- lp:~sbeattie/ubuntu-cve-tracker/+git/ubuntu-cve-tracker
- create_uct_module_refactoring
- Merge into master
Status: | Needs review |
---|---|
Proposed branch: | ~sbeattie/ubuntu-cve-tracker/+git/ubuntu-cve-tracker:create_uct_module_refactoring |
Merge into: | ubuntu-cve-tracker:master |
Diff against target: |
1651 lines (+537/-339) 41 files modified
.coveragerc (+7/-0) .gitignore (+2/-0) .launchpad.yaml (+7/-5) Makefile (+31/-2) cache/.empty_dir (+0/-0) scripts/boilerplate-to-json.py (+2/-1) scripts/check-cves (+14/-234) scripts/check-unreplaced-templates.py (+2/-1) scripts/cve_lib.py (+7/-14) scripts/debian-cve-update (+3/-2) scripts/dump-features (+0/-2) scripts/gen-source-map-cache (+2/-1) scripts/generate-graphs.py (+0/-2) scripts/plot-usns.py (+2/-4) scripts/process_cves (+21/-18) scripts/pull-in-progress.py (+3/-2) scripts/report-bugs (+3/-2) scripts/report-bugs-by-assignee (+0/-3) scripts/report-bugs-by-team (+3/-2) scripts/report-bugs-for-eol (+3/-2) scripts/report-cve-age.py (+2/-1) scripts/report-mistriaged-cves.py (+3/-2) scripts/report-packages.py (+2/-1) scripts/report-todo-mir (+0/-4) scripts/report-todo-sponsoring (+0/-3) scripts/report-updates.py (+2/-1) scripts/report-version.py (+2/-1) scripts/sis-changes (+3/-2) scripts/sis-generate-usn (+2/-1) scripts/source_map.py (+4/-22) scripts/sync-bugs-kernel.py (+2/-1) scripts/sync-from-usns.py (+2/-1) scripts/test_uct_config.py (+48/-0) scripts/test_uct_suggestions.py (+124/-0) scripts/uct/config.py (+75/-0) scripts/uct/suggestions.py (+131/-0) scripts/usn_lib.py (+2/-2) test/uct/config/no_plb_auth_entry.conf (+2/-0) test/uct/config/plb_auth_dev_null.conf (+2/-0) test/uct/config/plb_auth_does_not_exist.conf (+2/-0) test/uct/config/uct.conf (+15/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marc Deslauriers | Approve | ||
Review via email: mp+462102@code.launchpad.net |
Commit message
[WIP] refactor UCT layout and add coverage and script syntax check reporting
This branch is motivated by a few different things:
- wanting to break up cve_lib.py into smaller components, as well as support moving things implemented in individual scripts into common importable places
- wanting to know about the deprecation warnings from newer versions of python (like the recent invalid escape sequence warnings that came from python 3.12)
- wanting to see test coverage reports
To do this, I made a couple of changes that we can bikeshed about:
- created a scripts/uct directory / module that can be imported and moved a few things in there.
- created an empty cache/ directory and adjusted process_cves to use it to store and look for external data files during triage
The motivation for the latter was to (a) reduce the number of things that we look at when identifying python or shell scripts to check for syntax or other errors, and (b) I would like to reduce the clutter from the top level of UCT. I have not done it yet, but would like to move the *supported.txt files to a subdirectory (likely the meta_lists/ directory but we can argue about the name/location).
Some results out of this series:
- there are new make targets:
- check-python: invokes the same tests that the launchpad.yaml unit test job does (these should probably be unified)
- check-syntax-
These targets are added as dependencies to the 'check' target but that also runs `check-syntax` on the cve files, so they need to be individually invokable if we're going to keep the separate test jobs in lpci.
Also a `coverage` make target was added that generates an html reoprt of the python test coverage in the coverage_html subdirectory, which reports details about which lines in each python have or have not been exercised. Interestingly, it identifies that a couple of small portions of the existing tests that are supposed to look at the subprojects tree don't get exercised (despite the symlink to the external repo being present on my system); not sure what's going wrong there. In an ideal world the test coverage pages would get published somewhere.
One thing to think about is how to integrate the rest of the oval functional and semi-end-to-end tests that are in the toplevel test/ directory, and work around that some of the data sources may not be available from lpci.
Another note: the read_config() and read_config_file() implementation cannot yet be removed, as there are a number of scripts in repos outsde of UCT Tthat need to be adjusted first.
Description of the change
UCT layout changes and add test coverage and syntax warning reports
* [988c62cb224] uct module: create, reproduce cve_lib.
* [3aa4f0a5186] UCT/scripts: remove unneeded calls to cve_lib.
* [a691753e5c9] UCT/scripts: convert most scripts to use uct.config.
* [26fcf6446ec] cve_lib.py: convert read_config to use uct.config.
* [657e0da2753] check-cves: move ignored_cache.py under scripts/uct
* [1ef963e634f] check-cves: move ignore suggestion reasons to separate file/class
* [4a803a179ca] launchpad.yaml: run pytest against scripts/test_*.py
* [6578c2f6e15] launchpad.yaml: drop calling check-cves --test
* [85aa9d5031e] check-cves: drop self unit test argument and implementation
* [1c539b24ed7] launchpad.yaml: generate a coverage report for the unit tests
* [6345465aed2] Makefile: add python check and coverage report targets
* [e62116181d9] Add empty cache dir
* [e01c4c53ac5] process_cves: use cache directory for triage
* [2161889cd62] Make: add targets for checking script syntax
* [196a1bff689] launchpad.yaml: add syntax warning to lpci unit test job
- 34c2e14... by Steve Beattie
-
gitignore: ignore cache directory
Signed-off-by: Steve Beattie <email address hidden>
Steve Beattie (sbeattie) wrote : | # |
On Sun, Mar 10, 2024 at 07:21:57PM -0000, Marc Deslauriers wrote:
> Do you need to add the new cache directory to .gitignore?
Not *strictly* necessary, but useful for not committing additional files
to that directory. Added a commit for that.
--
Steve Beattie
<email address hidden>
Marc Deslauriers (mdeslaur) wrote : | # |
I agree with the reasoning behind this, and everything looks good to me. ACK
Unmerged commits
- 34c2e14... by Steve Beattie
-
gitignore: ignore cache directory
Signed-off-by: Steve Beattie <email address hidden>
-
unit-tests:0 (build) check-cves:0 (build) 1 → 2 of 2 results First • Previous • Next • Last - 196a1bf... by Steve Beattie
-
launchpad.yaml: add syntax warning to lpci unit test job
Add needed dependencies and invoke make check-syntax-
scripts Signed-off-by: Steve Beattie <email address hidden>
-
unit-tests:0 (build) check-cves:0 (build) 1 → 2 of 2 results First • Previous • Next • Last - 2161889... by Steve Beattie
-
Make: add targets for checking script syntax
Add targets for checking scripts syntax, currently using pyflakes and
shellcheck; I tried to use flake8 but it has an issue with the version
of pycodestyle in noble.These invocations have their error codes suppressed, so that they are
informational only for now, as there are a large number of items
reported that need to be investigated.This is the reason for the prior commit to try to move the nvd files
into a cache subdirectory to make pruning directories easier so that
e.g. file isn't invoked on all the individual nvd cve json files.Signed-off-by: Steve Beattie <email address hidden>
- e01c4c5... by Steve Beattie
-
process_cves: use cache directory for triage
Signed-off-by: Steve Beattie <email address hidden>
-
unit-tests:0 (build) check-cves:0 (build) 1 → 2 of 2 results First • Previous • Next • Last - e621161... by Steve Beattie
-
Add empty cache dir
Signed-off-by: Steve Beattie <email address hidden>
- 6345465... by Steve Beattie
-
Makefile: add python check and coverage report targets
Use the coverage module to generate an html coverage report. As part of
this:- Adjust the .coveragerc config file to omit files that have not been
covnerted to be python3 parseable.
- add the coverage_html created directory to .gitignoreSigned-off-by: Steve Beattie <email address hidden>
- 1c539b2... by Steve Beattie
-
launchpad.yaml: generate a coverage report for the unit tests
Signed-off-by: Steve Beattie <email address hidden>
- 85aa9d5... by Steve Beattie
-
check-cves: drop self unit test argument and implementation
Signed-off-by: Steve Beattie <email address hidden>
- 6578c2f... by Steve Beattie
-
launchpad.yaml: drop calling check-cves --test
As the same tests are now covered in the unit tests section, via
test_uct_suggestions. py Signed-off-by: Steve Beattie <email address hidden>
- 4a803a1... by Steve Beattie
-
launchpad.yaml: run pytest against scripts/test_*.py
This way it will automatically pick up any new test scripts, including
the most recent scripts/test_uct_ suggestions. py Signed-off-by: Steve Beattie <email address hidden>
Preview Diff
1 | diff --git a/.coveragerc b/.coveragerc |
2 | index 3ad560c..d59ccbe 100644 |
3 | --- a/.coveragerc |
4 | +++ b/.coveragerc |
5 | @@ -3,3 +3,10 @@ branch = True |
6 | include = |
7 | scripts/generate-oval |
8 | scripts/oval_lib.py |
9 | +# the follow scripts have not been converted to be parseable by a |
10 | +# python3 intepreter |
11 | +omit = |
12 | + scripts/pull-in-progress.py |
13 | + scripts/report-date.py |
14 | + scripts/report-mismatched-cve-fixes.py |
15 | + scripts/report_universe_cves.py |
16 | diff --git a/.gitignore b/.gitignore |
17 | index 551e1e4..d8a74d4 100644 |
18 | --- a/.gitignore |
19 | +++ b/.gitignore |
20 | @@ -70,7 +70,9 @@ graphing/cosmic.data |
21 | ignore_package_regexes.txt |
22 | .login |
23 | .coverage |
24 | +coverage_html |
25 | /subprojects |
26 | /pkg_cache.json |
27 | .vscode/ |
28 | /.venv |
29 | +/cache/ |
30 | diff --git a/.launchpad.yaml b/.launchpad.yaml |
31 | index a089c1d..9bcdb5d 100644 |
32 | --- a/.launchpad.yaml |
33 | +++ b/.launchpad.yaml |
34 | @@ -13,7 +13,9 @@ jobs: |
35 | architectures: amd64 |
36 | packages: |
37 | - distro-info |
38 | + - file |
39 | - lsb-release |
40 | + - pyflakes3 |
41 | - python3 |
42 | - python3-apt |
43 | - python3-configobj |
44 | @@ -21,7 +23,9 @@ jobs: |
45 | - python3-mock |
46 | - python3-progressbar |
47 | - python3-pytest |
48 | + - python3-pytest-cov |
49 | - python3-yaml |
50 | + - shellcheck |
51 | run-before: | |
52 | # configure a basic ~/.ubuntu-cve-tracker.conf |
53 | echo plb_authentication=/dev/null > ~/.ubuntu-cve-tracker.conf |
54 | @@ -35,11 +39,10 @@ jobs: |
55 | # new one |
56 | rm -f embargoed |
57 | mkdir embargoed |
58 | + echo "reporting syntax issues on scripts" |
59 | + make check-syntax-scripts |
60 | echo "Running unit tests..." |
61 | - pytest-3 ./scripts/test_cve_lib.py ./scripts/test_kernel_lib.py ./scripts/test_usn_lib.py ./scripts/test_source_map.py ./scripts/test_publish-cves-to-website-api.py ./scripts/test_sync_from_usns.py ./test/test_oval_lib_unit.py |
62 | - # ideally we would also run ./scripts/check-cves --test here as well as it |
63 | - # is more of a unit test but it requires packages-mirror so run it as part |
64 | - # of check-syntax below |
65 | + pytest-3 --cov=scripts ./scripts/test_*.py ./test/test_oval_lib_unit.py |
66 | check-cves: |
67 | series: jammy |
68 | architectures: amd64 |
69 | @@ -75,6 +78,5 @@ jobs: |
70 | rm -f embargoed |
71 | mkdir embargoed |
72 | |
73 | - ./scripts/check-cves --test |
74 | echo "Checking syntax..." |
75 | ./scripts/check-syntax |
76 | diff --git a/Makefile b/Makefile |
77 | index 2c0abb7..254b074 100644 |
78 | --- a/Makefile |
79 | +++ b/Makefile |
80 | @@ -13,6 +13,9 @@ ifneq ($(UCT_REVIEWED)$(SCRIPTS_RELDIR),$(SCRIPTS_RELDIR)) |
81 | endif |
82 | export SCRIPTS=$(UCT_SCRIPTS) |
83 | export ACTIVE=$(shell pwd)/active |
84 | +PYTEST=pytest-3 |
85 | +PYTHON=python3 |
86 | +PYFLAKES=pyflakes3 |
87 | |
88 | all: cves pkgs tables |
89 | |
90 | @@ -79,7 +82,33 @@ dev_setup: |
91 | echo '*** $$UQT is not set, unable to find location of lpl_common.py ***' ; \ |
92 | fi |
93 | |
94 | -check: |
95 | +syntax-shell: |
96 | + # run shellcheck on the specific types of shell scripts we have |
97 | + # this does not propagate the error code yet because we have a |
98 | + # a bunch of warnings, some of which because of how things are |
99 | + # used, just need to be silenced. |
100 | + find -type d \( -name cache -o -name active -o -name retired -o -name ignored -o -name nvd-database -o -name .git \) -prune -o -exec file {} \+ | grep "Bourne-Again shell script" | cut -d ":" -f 1 | xargs shellcheck -s bash || true |
101 | + find -type d \( -name cache -o -name active -o -name retired -o -name ignored -o -name nvd-database -o -name .git \) -prune -o -exec file {} \+ | grep -i "posix shell script" | cut -d ":" -f 1 | xargs shellcheck -s dash || true |
102 | + |
103 | +syntax-python: |
104 | + # run pyflakes on the python scripts we have |
105 | + # this does not propagate the error code yet because there are |
106 | + # some scripts that need to be made python3 compliant and some |
107 | + # imports cleaned up |
108 | + find -type d \( -name cache -o -name active -o -name retired -o -name ignored -o -name nvd-database -o -name .git \) -prune -o -exec file {} \+ | grep "Python script" | cut -d ":" -f 1 | xargs $(PYFLAKES) || true |
109 | + |
110 | +check-syntax-scripts: syntax-shell syntax-python |
111 | + |
112 | +coverage-python: check-python .coverage |
113 | + $(PYTHON) -m coverage html --dir coverage_html |
114 | + |
115 | +.coverage: check-python |
116 | + |
117 | +check-python: |
118 | + $(PYTEST) --cov=scripts ./scripts/test_*.py ./test/test_oval_lib_unit.py |
119 | + |
120 | +check: check-syntax-scripts check-python |
121 | $(SCRIPTS)/check-syntax |
122 | |
123 | -.PHONY: dev_setup check |
124 | +.PHONY: dev_setup check check-python coverage-python check-syntax-scripts \ |
125 | +syntax-shell syntax-python |
126 | diff --git a/cache/.empty_dir b/cache/.empty_dir |
127 | new file mode 100644 |
128 | index 0000000..e69de29 |
129 | --- /dev/null |
130 | +++ b/cache/.empty_dir |
131 | diff --git a/scripts/boilerplate-to-json.py b/scripts/boilerplate-to-json.py |
132 | index 06d800f..4066116 100755 |
133 | --- a/scripts/boilerplate-to-json.py |
134 | +++ b/scripts/boilerplate-to-json.py |
135 | @@ -6,6 +6,7 @@ import re |
136 | import sys |
137 | |
138 | import cve_lib |
139 | +from uct.config import read_uct_config |
140 | |
141 | def parse_boilerplate(filepath): |
142 | cve_data = cve_lib.load_cve(filepath) |
143 | @@ -131,7 +132,7 @@ def parse_embedded_code_copies(filepath): |
144 | return data |
145 | |
146 | # also parse debian's embedded-code-copies and amalgate that into data |
147 | -config = cve_lib.read_config() |
148 | +config = read_uct_config() |
149 | debian_embedded_copies = os.path.join(config['secure_testing_path'], "data", "embedded-code-copies") |
150 | code_copies = parse_embedded_code_copies(debian_embedded_copies) |
151 | for pkg in code_copies["pkgs"]: |
152 | diff --git a/scripts/check-cves b/scripts/check-cves |
153 | index 8a9e8fc..020693f 100755 |
154 | --- a/scripts/check-cves |
155 | +++ b/scripts/check-cves |
156 | @@ -28,7 +28,6 @@ import subprocess |
157 | import sys |
158 | import tempfile |
159 | import time |
160 | -import unittest |
161 | import urllib.request |
162 | import xml.sax |
163 | import xml.sax.handler |
164 | @@ -38,10 +37,12 @@ import progressbar |
165 | |
166 | import cve_lib |
167 | import source_map |
168 | -from check_cves.ignored_cache import IgnoredCache |
169 | +from uct.ignored_cache import IgnoredCache |
170 | +from uct.suggestions import IgnoreSuggestions |
171 | +from uct.config import read_uct_config |
172 | |
173 | # load settings, if any |
174 | -cve_lib.read_config() |
175 | +uct_config = read_uct_config() |
176 | |
177 | parser = optparse.OptionParser() |
178 | parser.add_option("-r", "--report", help="Just report CVEs that need checking", action="store_true") |
179 | @@ -50,7 +51,7 @@ parser.add_option("-k", "--known", help="Only report CVEs already known", action |
180 | parser.add_option("-N", "--skip-nfu", help="Skip any CVEs marked as NFU (used with -k)", action="store_true") |
181 | parser.add_option("-R", "--refresh", help="Refresh CVE descriptions", action="store_true") |
182 | parser.add_option("-S", "--score-refresh", help="Refresh CVSS scores values only", action="store_true") |
183 | -parser.add_option("", "--test", help="Run regression tests", action="store_true") |
184 | +parser.add_option("", "--test", help="NO LONGER SUPPORTED, see test_uct_suggestions.py", action="help") |
185 | parser.add_option("--untriaged", help="Process untriaged CVEs from output of locate_cves.py", metavar="FILE") |
186 | parser.add_option("--mbox", help="Process untriaged CVEs from mbox file", metavar="FILE") |
187 | parser.add_option("--rhel8oval", help="Process untriaged RHEL8 CVEs", metavar="FILE") |
188 | @@ -242,7 +243,7 @@ def import_debian(handler): |
189 | return False |
190 | |
191 | # pull in CVEs from data/DSA/list |
192 | - dsas = cve_lib.load_debian_dsas(cve_lib.config['secure_testing_path'] + '/data/DSA/list', opt.verbose) |
193 | + dsas = cve_lib.load_debian_dsas(uct_config['secure_testing_path'] + '/data/DSA/list', opt.verbose) |
194 | for dsa in dsas: |
195 | for cve in dsas[dsa]['cves']: |
196 | if not cve_lib.CVE_RE.match(cve): |
197 | @@ -581,12 +582,14 @@ class CVEHandler(xml.sax.handler.ContentHandler): |
198 | self.saved_cve = "" |
199 | self.debian = None |
200 | |
201 | + # get ignore suggestion |
202 | + self.ignore_suggestion = IgnoreSuggestions() |
203 | # File-type detection |
204 | |
205 | |
206 | # Load debian CVE states, if configured |
207 | - if 'secure_testing_path' in cve_lib.config: |
208 | - self.debian = cve_lib.load_debian_cves(cve_lib.config['secure_testing_path'] + '/data/CVE/list') |
209 | + if 'secure_testing_path' in uct_config: |
210 | + self.debian = cve_lib.load_debian_cves(uct_config['secure_testing_path'] + '/data/CVE/list') |
211 | |
212 | def updateTimestamp(self): |
213 | # Get UTC time |
214 | @@ -792,117 +795,6 @@ class CVEHandler(xml.sax.handler.ContentHandler): |
215 | def cves(self): |
216 | return self.cve_list |
217 | |
218 | - def get_ignore_suggestion(self, text): |
219 | - '''Try to find a reasonable suggestion for the user.''' |
220 | - suggestion = "" |
221 | - |
222 | - # remove any whitespace |
223 | - rev_text = text.strip() |
224 | - # strip out the added mailing list stuff (locate_cves.py importing) |
225 | - rev_text = re.sub(r'^ML-Date: .* ML-Subject: ', '', rev_text) |
226 | - rev_text = re.sub(r'^(|Re: )CVE (r|R)equest: ', '', rev_text) |
227 | - |
228 | - first_sentence = re.split(r'\. ', rev_text)[0] |
229 | - |
230 | - # hunt for module/component |
231 | - nouns = ["library", "templates?", "components?", "modules?", "[Pp]lug-?ins?", "extension", "application", "[Tt]hemes?"] |
232 | - products = ["Joomla!", "Drupal", "WordPress", "TYPO3", "Mambo", "Android", "jQuery"] |
233 | - match = re.search(r'(?: in t|^T)he (.*) (%s) (?:.* )?for (%s)' % ("|".join(nouns), "|".join(products)), |
234 | - first_sentence) |
235 | - preposition = "for" |
236 | - if not match: |
237 | - # try swapping order of product and noun in which case there is no preposition |
238 | - match = re.search(r'(?: in t|^T)he (.*) (%s) (%s) (?:.* )' % ("|".join(products), "|".join(nouns)), |
239 | - first_sentence) |
240 | - preposition = "" |
241 | - if match: |
242 | - module = match.group(1) |
243 | - noun = match.group(2) |
244 | - product = match.group(3) |
245 | - for marker in [" module", " ("]: |
246 | - if marker in module: |
247 | - module = module.split(marker)[0] |
248 | - return " ".join(filter(lambda x: len(x) > 0, [module, noun, preposition, product])) |
249 | - |
250 | - # hunt for a description of a thing written in a language or for creating something else |
251 | - match = re.search(r'(.*) is a (?:.*) (written in|for creating) (?:.*)', first_sentence) |
252 | - if match: |
253 | - return match.group(1) |
254 | - |
255 | - # hunt for a product on a platform |
256 | - match = re.search(r'.* for (Windows|Linux|Mac OS|iOS|Android|iPhone|iPad|BlackBerry|Symbian)', first_sentence) |
257 | - if match: |
258 | - return match.group(0) |
259 | - |
260 | - # look for common pattern |
261 | - match = re.search(r'A vulnerability(?:, which was)? classified as (?:.*),? was found in (.*)', first_sentence) |
262 | - if match: |
263 | - return match.group(1) |
264 | - |
265 | - # drop commas-extensions |
266 | - if ',' in first_sentence: |
267 | - first_sentence = re.split(r',', first_sentence)[0] |
268 | - phrases = re.split(r' [io]n ', first_sentence) |
269 | - |
270 | - # default to the last phrase |
271 | - suggestion = phrases[-1] |
272 | - # move to earlier phrase if suggestion starts with "a" |
273 | - if suggestion.startswith('a ') and len(phrases) > 1: |
274 | - suggestion = phrases[-2] |
275 | - |
276 | - version_preps = r'(\s+(before|through|prior to|versions?|[<>]=?))+\s*' |
277 | - version_regex = r'\s+([a-zA-Z\._\-]*[0-9]+[a-zA-Z\._\-]*)+' |
278 | - # prefer 'Apple iOS before <version>' or 'Apple Mac OS X through |
279 | - # <version' in the last phrase over other suggestions |
280 | - if not re.search(r'' + version_preps + version_regex, suggestion): |
281 | - # grab the first phrase with something that may be a version number |
282 | - for p in phrases: |
283 | - if re.search(r'' + version_regex, p): |
284 | - suggestion = p |
285 | - break |
286 | - if re.search(r'^[^,]+\s+for\s+', p): |
287 | - suggestion = p |
288 | - break |
289 | - |
290 | - # try to find a good suggestion from the phrase (ie suggest 'Linux |
291 | - # kernel' from 'the Linux kernel before 2.6.27') |
292 | - suggestion = re.split(r'\s+([a-zA-Z\._\-]*[0-9]+[a-zA-Z\._\-]*)+', suggestion)[0] |
293 | - # "blah in component for Software" |
294 | - if re.search(r'^[^,]+\s+for\s+', suggestion): |
295 | - suggestion = re.split(r'[^,]+\s+for\s+', suggestion)[1] |
296 | - |
297 | - # Chop off action verbs |
298 | - cleanup_regexes = [ |
299 | - # clean up leading "in" or "the" |
300 | - r'^\s*([tT]he|[iI]n)\s+', |
301 | - # clean up trailing version prepositions like "before" or "through" |
302 | - # from version details |
303 | - r'' + version_preps + '$', |
304 | - # clean up trailing parens |
305 | - r'\s+\([^\)]+\)\s*$', |
306 | - # action verbs |
307 | - r'\s+(has|creates|allows|could|contains)($|\s+.*)', |
308 | - # "vulnerbale installations of" |
309 | - r'(^|\s+)vulnerable\sinstallations?\sof($|\s+)', |
310 | - # This affects all versions of package |
311 | - r'^This affects all versions of package\s+', |
312 | - # This affects the package |
313 | - r'^This affects the package\s+', |
314 | - ] |
315 | - |
316 | - for regex in cleanup_regexes: |
317 | - if re.search(regex, suggestion): |
318 | - suggestion = re.sub(regex, '', suggestion) |
319 | - |
320 | - # if the phrase is too long, truncate it to max_length, but make |
321 | - # sure we don't have a partial word at the end |
322 | - max_length = 64 |
323 | - if len(suggestion) > max_length: |
324 | - suggestion = suggestion[:max_length] |
325 | - suggestion = re.sub(r'\s+\w+$', '', suggestion) |
326 | - |
327 | - return suggestion |
328 | - |
329 | def display_command_file_usage(self, f, line_prefix=''): |
330 | f.write('%sThe following commands can be used in this file:\n' % (line_prefix)) |
331 | f.write('%s\n' % (line_prefix)) |
332 | @@ -1000,13 +892,13 @@ class CVEHandler(xml.sax.handler.ContentHandler): |
333 | # no debian info, display possible commented ignore command when |
334 | # using command file (i.e. wrap_desc is true) |
335 | if (self.debian[cve]['state'] == 'RESERVED' or self.debian[cve]['state'] == None) and wrap_desc: |
336 | - proposed_ignore = self.get_ignore_suggestion(self.cve_data[cve]['desc']) |
337 | + proposed_ignore = self.ignore_suggestion.get_ignore_suggestion(self.cve_data[cve]['desc']) |
338 | print('%s ignore "%s"' % (cve, proposed_ignore)) |
339 | # debian rejected, so offer to reject by ignoring when using command file (i.e. wrap_desc is true) |
340 | if (self.debian[cve]['state'] == 'REJECTED' and wrap_desc): |
341 | print('%s ignore "%s"' % (cve, "REJECTED")) |
342 | else: |
343 | - proposed_ignore = self.get_ignore_suggestion(self.cve_data[cve]['desc']) |
344 | + proposed_ignore = self.ignore_suggestion.get_ignore_suggestion(self.cve_data[cve]['desc']) |
345 | print('%s ignore %s' % (cve, proposed_ignore)) |
346 | |
347 | software_hints_from_cve_desc = self.get_software_hints_from_cve_description(self.cve_data[cve]["desc"]) |
348 | @@ -1096,7 +988,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): |
349 | return (action, reason, packages) |
350 | |
351 | def get_software_hints_from_cve_description(self, cve_description): |
352 | - desc = self.get_ignore_suggestion(cve_description) |
353 | + desc = self.ignore_suggestion.get_ignore_suggestion(cve_description) |
354 | # split based on brackets and other chars which aren't going to be |
355 | # helpful in matching a package name etc |
356 | words = set(filter(None, re.split("[\\s\\(\\){}\\[\\]!\\?\\\\/]+", desc.lower()))) |
357 | @@ -1166,7 +1058,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): |
358 | # Show debian reason first, then automatically determined |
359 | # reason, then saved reasons. This makes more sense |
360 | # than sorting the reasons and is more predictable |
361 | - choices = [reason, self.get_ignore_suggestion(self.cve_data[cve]['desc'])] |
362 | + choices = [reason, self.ignore_suggestion.get_ignore_suggestion(self.cve_data[cve]['desc'])] |
363 | choices.extend(self.saved_ignore_cache.get()) |
364 | for choice in choices: |
365 | if choice != "" and choice not in prompts: |
366 | @@ -1478,113 +1370,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): |
367 | def skip_cve(self): |
368 | self.num_skipped += 1 |
369 | |
370 | -class CheckCVETest(unittest.TestCase): |
371 | - def test_get_ignore_suggestion(self): |
372 | - '''"Ignore" suggestion text extraction''' |
373 | - |
374 | - # Re-use the global handler |
375 | - h = handler |
376 | - |
377 | - self.assertEqual("Courier-Authlib", h.get_ignore_suggestion('''SQL injection vulnerability in authpgsqllib.c in Courier-Authlib before 0.62.0, when a non-Latin locale Postgres database is used, allows remote attackers to execute arbitrary SQL commands via query parameters containing apostrophes.''')) |
378 | - |
379 | - self.assertEqual("Apple Mac OS X", h.get_ignore_suggestion('''Buffer overflow in the DirectoryService Proxy in DirectoryService in Apple Mac OS X through 10.6.8 allows remote attackers to execute arbitrary code or cause a denial of service (application crash) via unspecified vectors.''')) |
380 | - |
381 | - self.assertEqual("KDE", h.get_ignore_suggestion('''HTMLTokenizer::scriptHandler in Konqueror in KDE 3.5.9 and 3.5.10 allows remote attackers to cause a denial of service (application crash) via an invalid document.load call that triggers use of a deleted object. NOTE: some of these details are obtained from third party information.''')) |
382 | - |
383 | - self.assertEqual("Sun Solaris", h.get_ignore_suggestion('''The name service cache daemon (nscd) in Sun Solaris 10 and OpenSolaris snv_50 through snv_104 does not properly check permissions, which allows local users to gain privileges and obtain sensitive information via unspecified vectors.''')) |
384 | - |
385 | - self.assertEqual("Linux kernel", h.get_ignore_suggestion('''libata in the Linux kernel before 2.6.27.9 does not set minimum timeouts for SG_IO requests, which allows local users to cause a denial of service (Programmed I/O mode on drives) via multiple simultaneous invocations of an unspecified test program.''')) |
386 | - |
387 | - self.assertEqual("iGaming", h.get_ignore_suggestion('''Multiple SQL injection vulnerabilities in iGaming 1.5 and earlier allow remote attackers to execute arbitrary SQL commands via the browse parameter to (1) previews.php and (2) reviews.php, and the (3) id parameter to index.php in a viewarticle action.''')) |
388 | - |
389 | - self.assertEqual("PHP iCalendar", h.get_ignore_suggestion('''PHP iCalendar 2.24 and earlier allows remote attackers to bypass authentication by setting the phpicalendar and phpicalendar_login cookies to 1.' |
390 | -''')) |
391 | - |
392 | - # Test length truncation, tweaked to avoid "has" matcher |
393 | - self.assertEqual("** TEST CVE ** This candidate HAS been reserved by an", h.get_ignore_suggestion('''** TEST CVE ** This candidate HAS been reserved by an organization or individual that will use it when announcing a new security problem. When the candidate has been publicized, the details for this candidate will be provided.''')) |
394 | - |
395 | - self.assertEqual("Sun OpenSolaris", h.get_ignore_suggestion('''Unspecified vulnerability in the root/boot archive tool in Sun OpenSolaris has unknown impact and local attack vectors, related to a "Temporary file vulnerability," aka Bug ID 6653455.''')) |
396 | - |
397 | - self.assertEqual("Red Hat Certificate System", h.get_ignore_suggestion('''Red Hat Certificate System 7.2 uses world-readable permissions for password.conf and unspecified other configuration files, which allows local users to discover passwords by reading these files.''')) |
398 | - |
399 | - self.assertEqual("Microsoft Internet Explorer", h.get_ignore_suggestion('''An unspecified function in the JavaScript implementation in Microsoft Internet Explorer creates and exposes a "temporary footprint" when there is a current login to a web site, which makes it easier for remote attackers to trick a user into acting upon a spoofed pop-up message, aka an "in-session phishing attack." NOTE: as of 20090116, the only disclosure is a vague pre-advisory with no actionable information. However, because it is from a well-known researcher, it is being assigned a CVE identifier for tracking purposes.''')) |
400 | - |
401 | - self.assertEqual("Umer Inc Songs Portal", h.get_ignore_suggestion('''SQL injection vulnerability in albums.php in Umer Inc Songs Portal allows remote attackers to execute arbitrary SQL commands via the id parameter.''')) |
402 | - |
403 | - self.assertEqual("Limbo CMS", h.get_ignore_suggestion('''SQL injection vulnerability in open.php in the Private Messaging (com_privmsg) component for Limbo CMS allows remote attackers to execute arbitrary SQL commands via the id parameter in a pms action to index.php.''')) |
404 | - |
405 | - self.assertEqual("phpscripts Ranking Script", h.get_ignore_suggestion('''phpscripts Ranking Script allows remote attackers to bypass authentication and gain administrative access by sending an admin=ja cookie.''')) |
406 | - |
407 | - self.assertEqual("A4Desk Event Calendar", h.get_ignore_suggestion('''PHP remote file inclusion vulnerability in index.php in A4Desk Event Calendar, when magic_quotes_gpc is disabled, allows remote attackers to execute arbitrary PHP code via a URL in the v parameter.''')) |
408 | - |
409 | - self.assertEqual("Galatolo WebManager", h.get_ignore_suggestion('''Cross-site scripting (XSS) vulnerability in result.php in Galatolo WebManager (GWM) 1.0 allows remote attackers to inject arbitrary web script or HTML via the key parameter.''')) |
410 | - |
411 | - self.assertEqual("Sun OpenSolaris", h.get_ignore_suggestion('''Unspecified vulnerability in the process (aka proc) filesystem in Sun OpenSolaris snv_85 through snv_100 allows local users to gain privileges via vectors related to the contract filesystem.''')) |
412 | - |
413 | - self.assertEqual("Dreampics Gallery Builder", h.get_ignore_suggestion('''SQL injection vulnerability in index.php in Dreampics Gallery Builder allows remote attackers to execute arbitrary SQL commands via the exhibition_id parameter in a gallery.viewPhotos action.''')) |
414 | - |
415 | - self.assertEqual("Omilen Photo Gallery component for Joomla!", h.get_ignore_suggestion('''Directory traversal vulnerability in the Omilen Photo Gallery (com_omphotogallery) component Beta 0.5 for Joomla! allows remote attackers to include and execute arbitrary local files via directory traversal sequences in the controller parameter to index.php.''')) |
416 | - |
417 | - self.assertEqual("Webform module for Drupal", h.get_ignore_suggestion('''Cross-site scripting (XSS) vulnerability in the Webform module 5.x before 5.x-2.7 and 6.x before 6.x-2.7, a module for Drupal, allows remote attackers to inject arbitrary web script or HTML via a submission.''')) |
418 | - |
419 | - self.assertEqual("Itamar Elharar MusicGallery component for Joomla!", h.get_ignore_suggestion('''SQL injection vulnerability in the Itamar Elharar MusicGallery (com_musicgallery) component for Joomla! allows remote attackers to execute arbitrary SQL commands via the id parameter in an itempage action to index.php. NOTE: the provenance of this information is unknown; the details are obtained solely from third party information.''')) |
420 | - |
421 | - self.assertEqual("Kide Shoutbox component for Joomla!", h.get_ignore_suggestion('''The Kide Shoutbox (com_kide) component 0.4.6 for Joomla! does not properly perform authentication, which allows remote attackers to post messages with an arbitrary account name via an insertar action to index.php. NOTE: the provenance of this information is unknown; the details are obtained solely from third party information.''')) |
422 | |
423 | - self.assertEqual("WP-Forum plugin for WordPress", h.get_ignore_suggestion('''Multiple SQL injection vulnerabilities in the WP-Forum plugin before 2.4 for WordPress allow remote attackers to execute arbitrary SQL commands via (1) the search_max parameter in a search action to the default URI, related to wpf.class.php; (2) the forum parameter to an unspecified component, related to wpf.class.php; (3) the topic parameter in a viewforum action to the default URI, related to the remove_topic function in wpf.class.php; or the id parameter in a (4) editpost or (5) viewtopic action to the default URI, related to wpf-post.php.''')) |
424 | - |
425 | - self.assertEqual("ListMan extension for TYPO3", h.get_ignore_suggestion('''Cross-site scripting (XSS) vulnerability in the ListMan (nl_listman) extension 1.2.1 for TYPO3 allows remote attackers to inject arbitrary web script or HTML via unspecified vectors.''')) |
426 | - |
427 | - self.assertEqual("multiple status.net issues", h.get_ignore_suggestion('''ML-Date: 2011-01-25 12:08:05, ML-Subject: Re: CVE request: multiple status.net issues''')) |
428 | - self.assertEqual("multiple status.net issues", h.get_ignore_suggestion('''ML-Date: 2011-01-25 12:08:05, ML-Subject: CVE request: multiple status.net issues''')) |
429 | - self.assertEqual("multiple status.net issues", h.get_ignore_suggestion('''ML-Date: 2011-01-25 12:08:05, ML-Subject: multiple status.net issues''')) |
430 | - self.assertEqual("Mambo CMS", h.get_ignore_suggestion('''ML-Date: 2011-06-28 16:24:28, ML-Subject: Re: CVE Request: Mambo CMS 4.6.x | Multiple Cross Site Scripting Vulnerabilities''')) |
431 | - |
432 | - self.assertEqual("Apple iOS", h.get_ignore_suggestion('''The DNAv4 protocol implementation in the DHCP component in Apple iOS before 6 sends Wi-Fi packets containing a MAC address of a host on a previously used network, which might allow remote attackers to obtain sensitive information about previous device locations by sniffing an unencrypted Wi-Fi network for these packets.''')) |
433 | - |
434 | - self.assertEqual("Conceptronic", h.get_ignore_suggestion('''Multiple open redirect vulnerabilities on the Conceptronic C54APM access point with runtime code 1.26 allow remote attackers to redirect users to arbitrary web sites and conduct phishing attacks via (1) the submit-url parameter in a Refresh action to goform/formWlSiteSurvey or (2) the wlan-url parameter to goform/formWlanSetup.''')) |
435 | - |
436 | - self.assertEqual("Tapjoy library for Android", h.get_ignore_suggestion('''The Tapjoy library for Android does not verify X.509 certificates from SSL servers, which allows man-in-the-middle attackers to spoof servers and obtain sensitive information via a crafted certificate.''')) |
437 | - |
438 | - self.assertEqual("kamkomesan application for Android", h.get_ignore_suggestion('''The kamkomesan (aka com.anek.kamkomesan) application 1.0 for Android does not verify X.509 certificates from SSL servers, which allows man-in-the-middle attackers to spoof servers and obtain sensitive information via a crafted certificate.''')) |
439 | - |
440 | - self.assertEqual("DataTables plugin for jQuery", h.get_ignore_suggestion('''Cross-site scripting (XSS) vulnerability in the DataTables plugin 1.10.8 and earlier for jQuery allows remote attackers to inject arbitrary web script or HTML via the scripts parameter to media/unit_testing/templates/6776.php.''')) |
441 | - |
442 | - self.assertEqual("Cisco Application Policy Infrastructure Controller (APIC)", h.get_ignore_suggestion('''A vulnerability in Cisco Application Policy Infrastructure Controller (APIC) could allow an authenticated, remote attacker to gain higher privileges than the account is assigned.''')) |
443 | - |
444 | - self.assertEqual("Redirection", h.get_ignore_suggestion('''Redirection version 2.7.3 contains a ACE via file inclusion vulnerability in Pass-through mode that can result in allows admins to execute any PHP file in the filesystem.''')) |
445 | - |
446 | - self.assertEqual("topydo", h.get_ignore_suggestion('''topydo contains a CWE-20: Improper Input Validation vulnerability in ListFormatParser::parse, file topydo/lib/ListFormat.py line 292 as of d4f843dac71308b2f29a7c2cdc76f055c3841523 that can result in Injection of arbitrary bytes to the terminal,''')) |
447 | - |
448 | - self.assertEqual("Joplin", h.get_ignore_suggestion('''Joplin version prior to 1.0.90 contains a XSS evolving into code execution due to enabled nodeIntegration.''')) |
449 | - |
450 | - self.assertEqual("Foxit Reader", h.get_ignore_suggestion('''This vulnerability allows remote attackers to execute arbitrary code on vulnerable installations of Foxit Reader 9.2.0.9297.''')) |
451 | - |
452 | - self.assertEqual("Exquisite Ultimate Newspaper theme for WordPress", h.get_ignore_suggestion('''The Exquisite Ultimate Newspaper theme 1.3.3 for WordPress has XSS via the anchor identifier to assets/js/jquery.foundation.plugins.js.''')) |
453 | - self.assertEqual("Weaver Xtreme Theme for WordPress", h.get_ignore_suggestion('''The Weaver Xtreme Theme for WordPress is vulnerable to stored Cross-Site Scripting due to insufficient escaping of the profile display name in versions up to, and including, 5.0.7.''')) |
454 | - self.assertEqual("Weaver Show Posts Plugin for WordPress", h.get_ignore_suggestion('''The Weaver Show Posts Plugin for WordPress is vulnerable to stored Cross-Site Scripting due to insufficient escaping of the profile display name in versions up to, and including, 1.6.''')) |
455 | - self.assertEqual("WordPress File Upload and WordPress File Upload Pro plugins for WordPress", h.get_ignore_suggestion('''The WordPress File Upload and WordPress File Upload Pro plugins for WordPress are vulnerable to Path Traversal in versions up to, and including, 4.19.1 via the vulnerable parameter wfu_newpath.''')) |
456 | - self.assertEqual("browserless-chrome", h.get_ignore_suggestion('''This affects all versions of package browserless-chrome. User input flowing from the workspace endpoint gets used to create a file path filePath and this is fetched and then sent back to a user. This can be escaped to fetch arbitrary files from a server.''')) |
457 | - self.assertEqual("@absolunet/kafe", h.get_ignore_suggestion('''This affects the package @absolunet/kafe before 3.2.10. It allows cause a denial of service when validating crafted invalid emails.''')) |
458 | - self.assertEqual("Magneticlab Sàrl Homepage Pop-up plugin", h.get_ignore_suggestion('''Cross-Site Request Forgery (CSRF) vulnerability in Magneticlab Sàrl Homepage Pop-up plugin <= 1.2.5 versions.''')) |
459 | - |
460 | - # handle odd whitespace |
461 | - self.assertEqual("PTC Vuforia Studio does not require a token.", h.get_ignore_suggestion(''' |
462 | - |
463 | - |
464 | - |
465 | - |
466 | - PTC Vuforia Studio does not require a token. |
467 | - ''')) |
468 | - self.assertEqual("zxcvbn-ts", h.get_ignore_suggestion('''zxcvbn-ts is a password strength estimator written in typescript.''')) |
469 | - self.assertEqual("VMware Tools for Windows", h.get_ignore_suggestion('''VMware Tools for Windows (10.x.y prior to 10.3.10, 11.x.y prior to 11.1.5) contains a denial-of-service vulnerability due to NULL pointer dereference in vm3dmp driver. Successful exploitation of this issue may allow attackers with normal user privileges to create a denial-of-service condition on the guest machine where VMware Tools is installed.''')) |
470 | - |
471 | - self.assertEqual("3DPrint WordPress plugin", h.get_ignore_suggestion("The 3DPrint WordPress plugin before 3.5.6.9 does not protect against CSRF attacks in the modified version of Tiny File Manager included with the plugin, allowing an attacker to craft a malicious request that will create an archive of any files or directories on the target server by tricking a logged in admin into submitting a form.")) |
472 | - |
473 | - self.assertEqual("Feathersjs", h.get_ignore_suggestion('''Feathersjs is a framework for creating web APIs and real-time applications with TypeScript or JavaScript.''')) |
474 | - |
475 | - self.assertEqual("PaulPrinting CMS 2018", h.get_ignore_suggestion("A vulnerability, which was classified as problematic, was found in PaulPrinting CMS 2018")) |
476 | - |
477 | ignored_notforus_path = 'ignored/not-for-us.txt' |
478 | if destdir != './' and destdir != '.': |
479 | ignored_notforus_path = os.path.join(destdir, ignored_notforus_path) |
480 | @@ -1625,12 +1411,6 @@ parser = xml.sax.make_parser() |
481 | handler = CVEHandler(CVEIgnoreList) |
482 | parser.setContentHandler(handler) |
483 | |
484 | -if opt.test: |
485 | - suite = unittest.TestSuite() |
486 | - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(CheckCVETest)) |
487 | - unittest.TextTestRunner(verbosity=2).run(suite) |
488 | - sys.exit(0) |
489 | - |
490 | # if has specified to triage only specific CVEs, check these are not |
491 | # ignored |
492 | specific_cves = None |
493 | diff --git a/scripts/check-unreplaced-templates.py b/scripts/check-unreplaced-templates.py |
494 | index 4723688..3e438d9 100755 |
495 | --- a/scripts/check-unreplaced-templates.py |
496 | +++ b/scripts/check-unreplaced-templates.py |
497 | @@ -16,6 +16,7 @@ import cve_lib |
498 | import json |
499 | import optparse |
500 | import usn_lib |
501 | +from uct.config import read_uct_config |
502 | |
503 | parser = optparse.OptionParser() |
504 | parser.add_option("-d", "--debug", help="Report additional debugging while loading USNs", action='store_true') |
505 | @@ -26,7 +27,7 @@ parser.add_option("-j", "--json", help="Check json instead of default pickle dat |
506 | |
507 | cves = dict() |
508 | |
509 | -config = cve_lib.read_config() |
510 | +config = read_uct_config() |
511 | |
512 | changed = False |
513 | if opt.json: |
514 | diff --git a/scripts/cve_lib.py b/scripts/cve_lib.py |
515 | index a3104fa..e982b55 100755 |
516 | --- a/scripts/cve_lib.py |
517 | +++ b/scripts/cve_lib.py |
518 | @@ -24,6 +24,7 @@ import json |
519 | import yaml |
520 | import urllib.error |
521 | import urllib.request |
522 | +from uct.config import read_uct_config |
523 | |
524 | from functools import reduce |
525 | from functools import lru_cache |
526 | @@ -1698,24 +1699,16 @@ def read_config_file(config_file): |
527 | |
528 | return ConfigObj(config_file) |
529 | |
530 | -def read_config(): |
531 | - config_file = os.path.join(os.path.expanduser("~"), ".ubuntu-cve-tracker.conf") |
532 | - |
533 | - if not os.path.exists(config_file): |
534 | - raise ValueError("Could not find '%s'" % (config_file)) |
535 | |
536 | - # FIXME: Why does this need to be defined as "global" when other globals |
537 | - # like "releases" and "EXIT_OKAY" don't need it?? |
538 | +# this function has been deprecated in favor of |
539 | +# uct.config.read_uct_config() and callers should be converted to use |
540 | +# that directly |
541 | +def read_config(): |
542 | global config |
543 | - config = read_config_file(config_file) |
544 | - |
545 | - # Validate required arguments |
546 | - if "plb_authentication" not in config: |
547 | - raise ValueError(("Could not find 'plb_authentication' entry in %s." % (config_file))) |
548 | - if not os.path.exists(config["plb_authentication"]): |
549 | - raise ValueError(("Could not find file specified by 'plb_authentication' in %s." % (config_file))) |
550 | + config = read_uct_config() |
551 | return config |
552 | |
553 | + |
554 | def drop_dup_release(cve, rel): |
555 | output = codecs.open(cve + ".new", 'w', encoding="utf-8") |
556 | saw = set() |
557 | diff --git a/scripts/debian-cve-update b/scripts/debian-cve-update |
558 | index 07c1bea..37856fa 100755 |
559 | --- a/scripts/debian-cve-update |
560 | +++ b/scripts/debian-cve-update |
561 | @@ -10,12 +10,13 @@ from __future__ import print_function |
562 | |
563 | from cve_lib import ( |
564 | check_mirror_timestamp, get_cve_list, load_debian_cves, |
565 | - load_ignored_reasons, prepend_debian_cve, read_config, |
566 | + load_ignored_reasons, prepend_debian_cve, |
567 | update_debian_todo_cves, |
568 | ) |
569 | import source_map |
570 | import optparse |
571 | import os |
572 | +from uct.config import read_uct_config |
573 | |
574 | parser = optparse.OptionParser() |
575 | parser.add_option("-p", "--packages", help="Include known packages in the updates", action='store_true') |
576 | @@ -23,7 +24,7 @@ parser.add_option("-n", "--dry-run", help="Do not actually make changes", action |
577 | parser.add_option("-q", "--quiet", help="Report actions verbosely", dest="verbose", default=True, action='store_false') |
578 | (opt, args) = parser.parse_args() |
579 | |
580 | -config = read_config() |
581 | +config = read_uct_config() |
582 | if len(args) == 1: |
583 | debian_cve_list = args[0] |
584 | else: |
585 | diff --git a/scripts/dump-features b/scripts/dump-features |
586 | index 30ca715..5dccc03 100755 |
587 | --- a/scripts/dump-features |
588 | +++ b/scripts/dump-features |
589 | @@ -29,8 +29,6 @@ if opt.editmoin: |
590 | else: |
591 | sys.exit(1) |
592 | |
593 | -config = cve_lib.read_config() |
594 | - |
595 | features = dict() |
596 | |
597 | UNIMPLEMENTED = 0 |
598 | diff --git a/scripts/gen-source-map-cache b/scripts/gen-source-map-cache |
599 | index 1c84cc6..d6fd4cf 100755 |
600 | --- a/scripts/gen-source-map-cache |
601 | +++ b/scripts/gen-source-map-cache |
602 | @@ -23,10 +23,11 @@ if not "UCT" in os.environ and not os.path.islink('subprojects'): |
603 | |
604 | import cve_lib |
605 | import source_map |
606 | +from uct.config import read_uct_config |
607 | |
608 | def main(): |
609 | |
610 | - config = source_map.read_config_file(os.path.expanduser("~/.ubuntu-cve-tracker.conf")) |
611 | + config = read_uct_config() |
612 | if 'packages_mirror' not in config: |
613 | sys.stderr.write("\rERROR: Could not find packages_mirror in config file!\n") |
614 | sys.exit(1) |
615 | diff --git a/scripts/generate-graphs.py b/scripts/generate-graphs.py |
616 | index e699f04..cceb55c 100755 |
617 | --- a/scripts/generate-graphs.py |
618 | +++ b/scripts/generate-graphs.py |
619 | @@ -61,8 +61,6 @@ if opt.target == None: |
620 | print("Must specify --target", file=sys.stderr) |
621 | sys.exit(1) |
622 | |
623 | -config = cve_lib.read_config() |
624 | - |
625 | if not os.path.exists(opt.database): |
626 | print("Cannot find '%s'" % opt.database, file=sys.stderr) |
627 | sys.exit(1) |
628 | diff --git a/scripts/plot-usns.py b/scripts/plot-usns.py |
629 | index b6e8e2b..527bb22 100755 |
630 | --- a/scripts/plot-usns.py |
631 | +++ b/scripts/plot-usns.py |
632 | @@ -8,6 +8,7 @@ |
633 | # License: GPLv3 |
634 | import sys, time, usn_lib, cve_lib |
635 | import optparse |
636 | +from uct.config import read_uct_config |
637 | |
638 | import pprint |
639 | pp = pprint.PrettyPrinter(indent=4) |
640 | @@ -23,7 +24,7 @@ if opt.target not in ['usn','src','bin','cve']: |
641 | print("Unknown target '%s'" % (opt.target), file=sys.stderr) |
642 | sys.exit(1) |
643 | |
644 | -config = cve_lib.read_config() |
645 | +config = read_uct_config() |
646 | db = None |
647 | db_filename = config['usn_db_copy'] |
648 | if len(args) > 0: |
649 | @@ -33,9 +34,6 @@ db = usn_lib.load_database(db_filename) |
650 | columns = ['total', 'untriaged'] + cve_lib.priorities |
651 | |
652 | cves = dict() |
653 | -if opt.target == 'cve': |
654 | - cve_lib.read_config() |
655 | - |
656 | months = dict() |
657 | month_cves = dict() |
658 | for usn in sorted(db.keys()): |
659 | diff --git a/scripts/process_cves b/scripts/process_cves |
660 | index 97d15cc..334ae9b 100755 |
661 | --- a/scripts/process_cves |
662 | +++ b/scripts/process_cves |
663 | @@ -11,6 +11,7 @@ |
664 | set -e |
665 | |
666 | loc=$(readlink -f "$(dirname "$0")/..") |
667 | +cache_dir="${loc}/cache/" |
668 | |
669 | uctconf="$HOME/.ubuntu-cve-tracker.conf" |
670 | if [ -s "$uctconf" ]; then |
671 | @@ -26,6 +27,8 @@ is_http_url() { |
672 | } |
673 | |
674 | download() { |
675 | + local url |
676 | + |
677 | url="$1" |
678 | # if http, then download it with wget, otherwise, try to rsync it |
679 | if is_http_url "$url" ; then |
680 | @@ -35,11 +38,11 @@ download() { |
681 | file=$(basename "$url") |
682 | |
683 | echo "wget -N \"$url\"" |
684 | - wget -N "$url" ||: |
685 | - gunzip -f "$file" |
686 | + wget -N "$url" -P "${cache_dir}" ||: |
687 | + gunzip -f "${cache_dir}/$file" |
688 | else |
689 | - echo "rsync -avz --progress \"$url\" ." |
690 | - rsync -avz --progress "$url" . |
691 | + echo "rsync -avz --progress \"$url\" ${cache_dir}" |
692 | + rsync -avz --progress "$url" "${cache_dir}" |
693 | fi |
694 | echo "---" |
695 | } |
696 | @@ -107,18 +110,18 @@ update_files() { |
697 | |
698 | full_refresh() { |
699 | # get PubDate |
700 | - echo "update PubDate (check-cves --refresh nvdcve-*.json) ..." |
701 | - ./scripts/check-cves --refresh nvdcve-*.json |
702 | + echo "update PubDate (check-cves --refresh ${cache_dir}/nvdcve-*.json) ..." |
703 | + ./scripts/check-cves --refresh "${cache_dir}"/nvdcve-*.json |
704 | |
705 | # get authoritative descriptions |
706 | - echo "get authoritative descriptions (check-cves --refresh ./allitems.xml) ..." |
707 | - ./scripts/check-cves --refresh ./allitems.xml |
708 | + echo "get authoritative descriptions (check-cves --refresh ${cache_dir}/allitems.xml) ..." |
709 | + ./scripts/check-cves --refresh "${cache_dir}/allitems.xml" |
710 | } |
711 | |
712 | refresh_cvss_score() { |
713 | # get CVSS score from NVD |
714 | - echo "update CVSS score (check-cves --score-refresh nvdcve-*.json) ..." |
715 | - ./scripts/check-cves --score-refresh nvdcve-*.json |
716 | + echo "update CVSS score (check-cves --score-refresh ${cache_dir}/nvdcve-*.json) ..." |
717 | + ./scripts/check-cves --score-refresh "${cache_dir}"/nvdcve-*.json |
718 | } |
719 | |
720 | kernel_team_merge() { |
721 | @@ -303,7 +306,7 @@ case "$action" in |
722 | # kernel_team_merge |
723 | echo "Skipping merge from kernel team" |
724 | echo "check-cves nvdcve-*.json" |
725 | - ./scripts/check-cves nvdcve-*.json |
726 | + ./scripts/check-cves "${cache_dir}"/nvdcve-*.json |
727 | # this will also do missing debian |
728 | mistriaged |
729 | |
730 | @@ -321,10 +324,10 @@ case "$action" in |
731 | echo "Skipping merge from kernel team" |
732 | |
733 | # process new ones |
734 | - echo "check-cves ./nvdcve-1.1-recent.json" |
735 | - ./scripts/check-cves ./nvdcve-1.1-recent.json |
736 | - echo "check-cves ./allitems.xml" |
737 | - ./scripts/check-cves ./allitems.xml |
738 | + echo "check-cves ${cache_dir}/nvdcve-1.1-recent.json" |
739 | + ./scripts/check-cves "${cache_dir}/nvdcve-1.1-recent.json" |
740 | + echo "check-cves ${cache_dir}/allitems.xml" |
741 | + ./scripts/check-cves "${cache_dir}/allitems.xml" |
742 | |
743 | process_missing_debian |
744 | # Disabling this due to https://listman.redhat.com/archives/rhsa-announce/2023-October/012854.html |
745 | @@ -396,7 +399,7 @@ case "$action" in |
746 | update_files |
747 | echo "check-cves --cve ${action}" |
748 | # add all NVD details as well so we can get date etc for it |
749 | - ./scripts/check-cves --cve ${action} nvdcve-*.json |
750 | + ./scripts/check-cves --cve ${action} "${cache_dir}"/nvdcve-*.json |
751 | check_syntax |
752 | ;; |
753 | *.json) |
754 | @@ -420,8 +423,8 @@ case "$action" in |
755 | update_files |
756 | # kernel_team_merge |
757 | echo "Skipping merge from kernel team" |
758 | - echo "check-cves ./nvdcve-1.1-recent.json" |
759 | - ./scripts/check-cves ./nvdcve-1.1-recent.json |
760 | + echo "check-cves ${cache_dir}/nvdcve-1.1-recent.json" |
761 | + ./scripts/check-cves "${cache_dir}/nvdcve-1.1-recent.json" |
762 | process_missing_debian |
763 | refresh_cvss_score |
764 | check_syntax |
765 | diff --git a/scripts/pull-in-progress.py b/scripts/pull-in-progress.py |
766 | index a4a57d9..0426e74 100755 |
767 | --- a/scripts/pull-in-progress.py |
768 | +++ b/scripts/pull-in-progress.py |
769 | @@ -7,6 +7,7 @@ |
770 | import sys, os, os.path, re, urllib, tempfile |
771 | import optparse, glob |
772 | import cve_lib |
773 | +from utc.config import read_uct_config |
774 | |
775 | from launchpadlib.launchpad import Launchpad, EDGE_SERVICE_ROOT |
776 | from launchpadlib.credentials import Credentials |
777 | @@ -57,8 +58,8 @@ def get_cves(bug): |
778 | # |
779 | from launchpadbugs.connector import ConnectBugList |
780 | BugList = ConnectBugList() |
781 | -cve_lib.read_config() |
782 | -BugList.authentication = cve_lib.config["plb_authentication"] |
783 | +config = read_uct_config() |
784 | +BugList.authentication = config["plb_authentication"] |
785 | |
786 | url="https://bugs.launchpad.net/~ubuntu-security/+bugs?field.searchtext=&orderby=-importance&field.status%3Alist=INPROGRESS&assignee_option=any&field.assignee=&field.bug_reporter=&field.bug_supervisor=&field.bug_commenter=&field.subscriber=&field.status_upstream-empty-marker=1&field.omit_dupes.used=&field.has_patch.used=&field.has_patch=on&field.has_cve.used=&field.tag=&field.tags_combinator=ANY&search=Search" |
787 | if opt.any: |
788 | diff --git a/scripts/report-bugs b/scripts/report-bugs |
789 | index bb2d78c..de6684a 100755 |
790 | --- a/scripts/report-bugs |
791 | +++ b/scripts/report-bugs |
792 | @@ -14,6 +14,7 @@ import re |
793 | import subprocess |
794 | import sys |
795 | import time |
796 | +from uct.config import read_uct_config |
797 | |
798 | parser = optparse.OptionParser() |
799 | parser.add_option("--debug", help="Verbose processing output", action='store_true') |
800 | @@ -43,14 +44,14 @@ except: |
801 | sys.exit(1) |
802 | |
803 | # Load configuration |
804 | -cve_lib.read_config() |
805 | +config = read_uct_config() |
806 | |
807 | # API interface |
808 | debug("Connecting to LP ...\n") |
809 | lp = lpl_common.connect() |
810 | |
811 | # Get authenticated URL fetcher |
812 | -opener = lpl_common.opener_with_cookie(cve_lib.config["plb_authentication"]) |
813 | +opener = lpl_common.opener_with_cookie(config["plb_authentication"]) |
814 | if not opener: |
815 | raise ValueError("Could not open cookies") |
816 | |
817 | diff --git a/scripts/report-bugs-by-assignee b/scripts/report-bugs-by-assignee |
818 | index e34ba4b..2fc5d5e 100755 |
819 | --- a/scripts/report-bugs-by-assignee |
820 | +++ b/scripts/report-bugs-by-assignee |
821 | @@ -30,9 +30,6 @@ def debug(s): |
822 | if opt.debug: |
823 | print( "DEBUG: %s" % s, file=sys.stderr) |
824 | |
825 | -# Load configuration |
826 | -cve_lib.read_config() |
827 | - |
828 | # API interface |
829 | debug("Connecting to LP ...") |
830 | lp = UCTLaunchpad(opt) |
831 | diff --git a/scripts/report-bugs-by-team b/scripts/report-bugs-by-team |
832 | index e3b71ec..da7ae74 100755 |
833 | --- a/scripts/report-bugs-by-team |
834 | +++ b/scripts/report-bugs-by-team |
835 | @@ -19,6 +19,7 @@ import shutil |
836 | import subprocess |
837 | import sys |
838 | import time |
839 | +from uct.config import read_uct_config |
840 | |
841 | try: |
842 | import pickle |
843 | @@ -377,7 +378,7 @@ if all_bugs == None: |
844 | sys.exit(1) |
845 | |
846 | # Load configuration |
847 | - cve_lib.read_config() |
848 | + config = read_uct_config() |
849 | |
850 | # API interface |
851 | debug("Team: %s" % opt.team) |
852 | @@ -385,7 +386,7 @@ if all_bugs == None: |
853 | lp = lpl_common.connect() |
854 | |
855 | # Get authenticated URL fetcher |
856 | - opener = lpl_common.opener_with_cookie(cve_lib.config["plb_authentication"]) |
857 | + opener = lpl_common.opener_with_cookie(config["plb_authentication"]) |
858 | if not opener: |
859 | raise ValueError("Could not open cookies") |
860 | |
861 | diff --git a/scripts/report-bugs-for-eol b/scripts/report-bugs-for-eol |
862 | index 2cc2895..81e3397 100755 |
863 | --- a/scripts/report-bugs-for-eol |
864 | +++ b/scripts/report-bugs-for-eol |
865 | @@ -17,6 +17,7 @@ import optparse |
866 | import os |
867 | import re |
868 | import sys |
869 | +from uct.config import read_uct_config |
870 | |
871 | parser = optparse.OptionParser() |
872 | parser.add_option("--debug", help="Verbose processing output", action='store_true') |
873 | @@ -138,14 +139,14 @@ if bugs == None: |
874 | sys.exit(1) |
875 | |
876 | # Load configuration |
877 | - cve_lib.read_config() |
878 | + config = read_uct_config() |
879 | |
880 | # API interface |
881 | print("Connecting to LP ...", end=' ', file=sys.stderr) |
882 | lp = lpl_common.connect() |
883 | |
884 | # Get authenticated URL fetcher |
885 | - opener = lpl_common.opener_with_cookie(cve_lib.config["plb_authentication"]) |
886 | + opener = lpl_common.opener_with_cookie(config["plb_authentication"]) |
887 | if not opener: |
888 | raise ValueError("Could not open cookies") |
889 | |
890 | diff --git a/scripts/report-cve-age.py b/scripts/report-cve-age.py |
891 | index 26c2925..7d28820 100755 |
892 | --- a/scripts/report-cve-age.py |
893 | +++ b/scripts/report-cve-age.py |
894 | @@ -18,11 +18,12 @@ import os |
895 | import sys |
896 | import optparse |
897 | import cve_lib, usn_lib |
898 | +from uct.config import read_uct_config |
899 | |
900 | import source_map |
901 | source_map = source_map.load() |
902 | releases = cve_lib.releases |
903 | -config = cve_lib.read_config() |
904 | +config = read_uct_config() |
905 | |
906 | default_db = config['usn_db_copy'] |
907 | if '-all' not in default_db: |
908 | diff --git a/scripts/report-mistriaged-cves.py b/scripts/report-mistriaged-cves.py |
909 | index 352a104..90e717f 100755 |
910 | --- a/scripts/report-mistriaged-cves.py |
911 | +++ b/scripts/report-mistriaged-cves.py |
912 | @@ -9,6 +9,7 @@ |
913 | # Public License, Version 3 or later. See http://www.gnu.org/copyleft/gpl.html |
914 | # for details. |
915 | import sys, os, os.path, optparse, cve_lib, re, subprocess, signal |
916 | +from uct.config import read_uct_config |
917 | |
918 | def subprocess_setup(): |
919 | # Python installs a SIGPIPE handler by default. This is usually not what |
920 | @@ -63,7 +64,7 @@ def check_apt_cache(package): |
921 | |
922 | |
923 | # get base config for path to debian security tracker etc |
924 | -config = cve_lib.read_config() |
925 | +config = read_uct_config() |
926 | |
927 | parser = optparse.OptionParser() |
928 | parser.add_option("-v", "--verbose", dest="verbose", |
929 | @@ -139,7 +140,7 @@ if len(dups) > 0: |
930 | print('Duplicate entries in not-for-us.txt: ' + ' '.join(dups)) |
931 | |
932 | # get the list of CVEs which Debian knows about |
933 | -debian = cve_lib.load_debian_cves(cve_lib.config['secure_testing_path'] + |
934 | +debian = cve_lib.load_debian_cves(config['secure_testing_path'] + |
935 | '/data/CVE/list') |
936 | |
937 | cache = {} |
938 | diff --git a/scripts/report-packages.py b/scripts/report-packages.py |
939 | index bcc3406..33eb8a8 100755 |
940 | --- a/scripts/report-packages.py |
941 | +++ b/scripts/report-packages.py |
942 | @@ -23,9 +23,10 @@ import cve_lib |
943 | import usn_lib |
944 | |
945 | import source_map |
946 | +from uct.config import read_uct_config |
947 | source_map = source_map.load() |
948 | releases = cve_lib.releases |
949 | -config = cve_lib.read_config() |
950 | +config = read_uct_config() |
951 | |
952 | parser = optparse.OptionParser() |
953 | parser.add_option("-S", "--skip-devel", help="Show only those CVEs *not* in the current devel release", action="store_true") |
954 | diff --git a/scripts/report-todo-mir b/scripts/report-todo-mir |
955 | index d598fb6..e820a43 100755 |
956 | --- a/scripts/report-todo-mir |
957 | +++ b/scripts/report-todo-mir |
958 | @@ -14,7 +14,6 @@ import argparse |
959 | import re |
960 | import sys |
961 | from launchpadlib.launchpad import Launchpad |
962 | -import cve_lib |
963 | |
964 | # by default we want all not in Fix Released, Fix Committed, Opinion, Invalid, |
965 | # Won't Fix & Expired which leaves the following |
966 | @@ -225,9 +224,6 @@ def lookup_tasks_for_assignees(taskdb, assignees): |
967 | taskdb.add(mir_task) |
968 | |
969 | |
970 | -# Load configuration |
971 | -cve_lib.read_config() |
972 | - |
973 | # API interface |
974 | debug("Connecting to LP ...") |
975 | lp = Launchpad.login_anonymously("report-todo-mir", "production", version="devel") |
976 | diff --git a/scripts/report-todo-sponsoring b/scripts/report-todo-sponsoring |
977 | index 14c87d3..9294a40 100755 |
978 | --- a/scripts/report-todo-sponsoring |
979 | +++ b/scripts/report-todo-sponsoring |
980 | @@ -151,9 +151,6 @@ except: |
981 | print("lpl_common.py seems to be missing. Please create a symlink from $UQT/common/lpl_common.py to $UCT/scripts/", file=sys.stderr) |
982 | sys.exit(1) |
983 | |
984 | -# Load configuration |
985 | -cve_lib.read_config() |
986 | - |
987 | # API interface |
988 | debug("Connecting to LP ...") |
989 | lp = lpl_common.connect() |
990 | diff --git a/scripts/report-updates.py b/scripts/report-updates.py |
991 | index ed69604..4d939ca 100755 |
992 | --- a/scripts/report-updates.py |
993 | +++ b/scripts/report-updates.py |
994 | @@ -13,11 +13,12 @@ import os |
995 | import sys |
996 | import time |
997 | import usn_lib |
998 | +from uct.config import read_uct_config |
999 | |
1000 | import source_map |
1001 | source_map = source_map.load() |
1002 | |
1003 | -config = cve_lib.read_config() |
1004 | +config = read_uct_config() |
1005 | default_db = config['usn_db_copy'] |
1006 | if '-all' not in default_db: |
1007 | tmp = os.path.splitext(default_db) |
1008 | diff --git a/scripts/report-version.py b/scripts/report-version.py |
1009 | index 381c724..c1fdb7d 100755 |
1010 | --- a/scripts/report-version.py |
1011 | +++ b/scripts/report-version.py |
1012 | @@ -18,13 +18,14 @@ import sys |
1013 | import optparse |
1014 | import cve_lib |
1015 | import usn_lib |
1016 | +from uct.config import read_uct_config |
1017 | |
1018 | import apt_pkg |
1019 | apt_pkg.init_system() |
1020 | |
1021 | releases = cve_lib.releases |
1022 | esm_releases = cve_lib.esm_releases + cve_lib.esm_infra_releases |
1023 | -config = cve_lib.read_config() |
1024 | +config = read_uct_config() |
1025 | |
1026 | parser = optparse.OptionParser() |
1027 | parser.add_option("--db", help="Specify the USN database to load", metavar="FILENAME", default=config['usn_db_copy']) |
1028 | diff --git a/scripts/sis-changes b/scripts/sis-changes |
1029 | index d33da15..fc398f4 100755 |
1030 | --- a/scripts/sis-changes |
1031 | +++ b/scripts/sis-changes |
1032 | @@ -23,6 +23,7 @@ import urllib.request, urllib.error, urllib.parse |
1033 | import cve_lib |
1034 | import json |
1035 | from source_map import version_compare, load |
1036 | +from uct.config import read_uct_config |
1037 | |
1038 | try: |
1039 | import lpl_common |
1040 | @@ -148,13 +149,13 @@ parser.add_option("--distribution", help="Distribution to use (eg, 'ubuntu-rtm') |
1041 | (opt, args) = parser.parse_args() |
1042 | |
1043 | # Load configuration |
1044 | -cve_lib.read_config() |
1045 | +config = read_uct_config() |
1046 | |
1047 | # API interface |
1048 | lp = lpl_common.connect(beta=opt.beta, uri=opt.uri) |
1049 | |
1050 | # Get authenticated URL fetcher |
1051 | -opener = lpl_common.opener_with_cookie(cve_lib.config["plb_authentication"]) |
1052 | +opener = lpl_common.opener_with_cookie(config["plb_authentication"]) |
1053 | if not opener: |
1054 | raise ValueError("Could not open cookies") |
1055 | |
1056 | diff --git a/scripts/sis-generate-usn b/scripts/sis-generate-usn |
1057 | index 8947779..9ae7a8b 100755 |
1058 | --- a/scripts/sis-generate-usn |
1059 | +++ b/scripts/sis-generate-usn |
1060 | @@ -23,6 +23,7 @@ import subprocess |
1061 | import sys |
1062 | import tempfile |
1063 | import cve_lib |
1064 | +from uct.config import read_uct_config |
1065 | |
1066 | opter = optparse.OptionParser() |
1067 | opter.add_option("--debug", help="Verbose processing output", action='store_true') |
1068 | @@ -60,7 +61,7 @@ for rel in cve_lib.releases: |
1069 | # components (-updates has gotten wrecked by things in -proposed before). |
1070 | release_suffixes = ['','-security','-updates'] |
1071 | |
1072 | -config = cve_lib.read_config() |
1073 | +config = read_uct_config() |
1074 | archive = config['packages_mirror'] |
1075 | cve_lib.check_mirror_timestamp(config, mirror='packages_mirror') |
1076 | |
1077 | diff --git a/scripts/source_map.py b/scripts/source_map.py |
1078 | index c5ec9ad..b6377fb 100755 |
1079 | --- a/scripts/source_map.py |
1080 | +++ b/scripts/source_map.py |
1081 | @@ -19,6 +19,7 @@ import sys |
1082 | import cve_lib |
1083 | import yaml |
1084 | import pickle |
1085 | +from uct.config import read_uct_config |
1086 | |
1087 | built_using_tags = ["Built-Using", "Static-Built-Using", "X-Cargo-Built-Using"] |
1088 | apt_pkg.init_system() |
1089 | @@ -27,28 +28,9 @@ apt_pkg.init_system() |
1090 | def version_compare(one, two): |
1091 | return apt_pkg.version_compare(one, two) |
1092 | |
1093 | -def read_config_file(config_file): |
1094 | - '''Read in and do basic validation on config file''' |
1095 | - try: |
1096 | - from configobj import ConfigObj |
1097 | - except ImportError: |
1098 | - # Some releases lack this class, so reimplement it quickly |
1099 | - class ConfigObj(dict): |
1100 | - def __init__(self, filepath): |
1101 | - for line in open(filepath).readlines(): |
1102 | - line = line.strip() |
1103 | - if line.startswith('#') or len(line) == 0: |
1104 | - continue |
1105 | - name, stuff = line.strip().split('=', 1) |
1106 | - self[name] = eval(stuff) |
1107 | - |
1108 | - def __attr__(self, name): |
1109 | - return self.stuff[name] |
1110 | - |
1111 | - return ConfigObj(config_file) |
1112 | |
1113 | def _find_sources(pockets=None, releases=None, skip_eol_releases=True, arch='amd64'): |
1114 | - config = read_config_file(os.path.expanduser("~/.ubuntu-cve-tracker.conf")) |
1115 | + config = read_uct_config() |
1116 | if 'packages_mirror' in config: |
1117 | cve_lib.check_mirror_timestamp(config) |
1118 | return _find_from_mirror(config['packages_mirror'], |
1119 | @@ -62,7 +44,7 @@ def _find_sources(pockets=None, releases=None, skip_eol_releases=True, arch='amd |
1120 | |
1121 | |
1122 | def _find_packages(pockets=None, releases=None, skip_eol_releases=True, arch='amd64'): |
1123 | - config = read_config_file(os.path.expanduser("~/.ubuntu-cve-tracker.conf")) |
1124 | + config = read_uct_config() |
1125 | if 'packages_mirror' in config: |
1126 | cve_lib.check_mirror_timestamp(config) |
1127 | return _find_from_mirror(config['packages_mirror'], |
1128 | @@ -218,7 +200,7 @@ def load(data_type='sources', pockets=None, releases=None, skip_eol_releases=Tru |
1129 | raise ValueError("'data_type' should be either 'sources' or 'packages'") |
1130 | |
1131 | # Attempt to load from cached pickle files |
1132 | - config = read_config_file(os.path.expanduser("~/.ubuntu-cve-tracker.conf")) |
1133 | + config = read_uct_config() |
1134 | if 'packages_mirror' in config: |
1135 | mirror = config['packages_mirror'] |
1136 | |
1137 | diff --git a/scripts/sync-bugs-kernel.py b/scripts/sync-bugs-kernel.py |
1138 | index 67b1bf9..21e1c32 100755 |
1139 | --- a/scripts/sync-bugs-kernel.py |
1140 | +++ b/scripts/sync-bugs-kernel.py |
1141 | @@ -29,6 +29,7 @@ import sys |
1142 | import cve_lib |
1143 | import urlparse |
1144 | from lp_lib import UCTLaunchpad |
1145 | +from uct.config import read_uct_config |
1146 | |
1147 | priority_to_importance = { |
1148 | 'critical': 'Critical', |
1149 | @@ -61,7 +62,7 @@ uctlp = UCTLaunchpad(opt) |
1150 | # Use devel version so we get the bugtask delete API |
1151 | uctlp.lp_version = "devel" |
1152 | |
1153 | -config = cve_lib.read_config() |
1154 | +config = read_uct_config() |
1155 | ktools = config.get('kernel_team_tools_path', None) |
1156 | if not ktools: |
1157 | raise ValueError("'kernel_team_tools_path' missing in ~/.ubuntu-cve-tracker.conf") |
1158 | diff --git a/scripts/sync-from-usns.py b/scripts/sync-from-usns.py |
1159 | index c2a2a27..91a2ef3 100755 |
1160 | --- a/scripts/sync-from-usns.py |
1161 | +++ b/scripts/sync-from-usns.py |
1162 | @@ -24,6 +24,7 @@ import textwrap |
1163 | |
1164 | import cve_lib |
1165 | import usn_lib |
1166 | +from uct.config import read_uct_config |
1167 | |
1168 | from source_map import version_compare, load |
1169 | |
1170 | @@ -96,7 +97,7 @@ def parse_args(): |
1171 | return args |
1172 | |
1173 | if __name__ == '__main__': |
1174 | - config = cve_lib.read_config() |
1175 | + config = read_uct_config() |
1176 | |
1177 | args = parse_args() |
1178 | if args.git_stage: |
1179 | diff --git a/scripts/test_uct_config.py b/scripts/test_uct_config.py |
1180 | new file mode 100755 |
1181 | index 0000000..c69fbda |
1182 | --- /dev/null |
1183 | +++ b/scripts/test_uct_config.py |
1184 | @@ -0,0 +1,48 @@ |
1185 | +#!/usr/bin/env pytest-3 |
1186 | +# -*- coding: utf-8 -*- |
1187 | +# |
1188 | +# Test functions for scripts/uct/config.py |
1189 | +# |
1190 | +# Author: Steve Beattie <sbeattie@ubuntu.com> |
1191 | +# Copyright (C) 2005-2024 Canonical Ltd. |
1192 | +# |
1193 | +# This script is distributed under the terms and conditions of the GNU General |
1194 | +# Public License, Version 2 or later. See http://www.gnu.org/copyleft/gpl.html |
1195 | +# for details. |
1196 | + |
1197 | +import os |
1198 | +import pytest |
1199 | + |
1200 | +# _read_config and _read_config_cached are private functions in |
1201 | +# uct/config.py for testing |
1202 | +# users of uct/config.py should only use read_config() |
1203 | +from uct.config import _read_config, _read_config_cached |
1204 | + |
1205 | +TEST_DATA_DIR = "test/uct/config/" |
1206 | + |
1207 | + |
1208 | +class TestUCTConfig: |
1209 | + |
1210 | + def test_config_file_not_exist(self): |
1211 | + with pytest.raises(ValueError): |
1212 | + _read_config(os.path.join(TEST_DATA_DIR, "does-not-exist.conf")) |
1213 | + |
1214 | + def test_plb_auth_config_not_exist(self): |
1215 | + with pytest.raises(ValueError): |
1216 | + _read_config(os.path.join(TEST_DATA_DIR, "plb_auth_does_not_exist.conf")) |
1217 | + |
1218 | + def test_no_plb_auth_entry(self): |
1219 | + with pytest.raises(ValueError): |
1220 | + _read_config(os.path.join(TEST_DATA_DIR, "no_plb_auth_entry.conf")) |
1221 | + |
1222 | + def test_plb_auth_config_simple(self): |
1223 | + expected = { |
1224 | + 'plb_authentication': '/dev/null' |
1225 | + } |
1226 | + config = _read_config(os.path.join(TEST_DATA_DIR, "plb_auth_dev_null.conf")) |
1227 | + assert config == expected |
1228 | + |
1229 | + def test_returned_config_is_singleton(self): |
1230 | + first_config = _read_config_cached(os.path.join(TEST_DATA_DIR, "uct.conf")) |
1231 | + second_config = _read_config_cached(os.path.join(TEST_DATA_DIR, "uct.conf")) |
1232 | + assert first_config is second_config |
1233 | diff --git a/scripts/test_uct_suggestions.py b/scripts/test_uct_suggestions.py |
1234 | new file mode 100755 |
1235 | index 0000000..43cfb75 |
1236 | --- /dev/null |
1237 | +++ b/scripts/test_uct_suggestions.py |
1238 | @@ -0,0 +1,124 @@ |
1239 | +#!/usr/bin/env pytest-3 |
1240 | +# -*- coding: utf-8 -*- |
1241 | + |
1242 | +# Author: Martin Pitt <martin.pitt@ubuntu.com> |
1243 | +# Author: Kees Cook <kees@ubuntu.com> |
1244 | +# Author: Jamie Strandboge <jamie@ubuntu.com> |
1245 | +# Author: Marc Deslauriers <marc.deslauriers@ubuntu.com> |
1246 | +# Author: Steve Beattie <sbeattie@ubuntu.com> |
1247 | +# Copyright (C) 2005-2024 Canonical Ltd. |
1248 | +# |
1249 | +# This script is distributed under the terms and conditions of the GNU General |
1250 | +# Public License, Version 2 or later. See http://www.gnu.org/copyleft/gpl.html |
1251 | +# for details. |
1252 | + |
1253 | +import unittest |
1254 | +from uct.suggestions import IgnoreSuggestions |
1255 | + |
1256 | +class CheckCVETest(unittest.TestCase): |
1257 | + def test_get_ignore_suggestion(self): |
1258 | + '''"Ignore" suggestion text extraction''' |
1259 | + |
1260 | + # instantiate the suggestion handler |
1261 | + h = IgnoreSuggestions() |
1262 | + |
1263 | + self.assertEqual("Courier-Authlib", h.get_ignore_suggestion('''SQL injection vulnerability in authpgsqllib.c in Courier-Authlib before 0.62.0, when a non-Latin locale Postgres database is used, allows remote attackers to execute arbitrary SQL commands via query parameters containing apostrophes.''')) |
1264 | + |
1265 | + self.assertEqual("Apple Mac OS X", h.get_ignore_suggestion('''Buffer overflow in the DirectoryService Proxy in DirectoryService in Apple Mac OS X through 10.6.8 allows remote attackers to execute arbitrary code or cause a denial of service (application crash) via unspecified vectors.''')) |
1266 | + |
1267 | + self.assertEqual("KDE", h.get_ignore_suggestion('''HTMLTokenizer::scriptHandler in Konqueror in KDE 3.5.9 and 3.5.10 allows remote attackers to cause a denial of service (application crash) via an invalid document.load call that triggers use of a deleted object. NOTE: some of these details are obtained from third party information.''')) |
1268 | + |
1269 | + self.assertEqual("Sun Solaris", h.get_ignore_suggestion('''The name service cache daemon (nscd) in Sun Solaris 10 and OpenSolaris snv_50 through snv_104 does not properly check permissions, which allows local users to gain privileges and obtain sensitive information via unspecified vectors.''')) |
1270 | + |
1271 | + self.assertEqual("Linux kernel", h.get_ignore_suggestion('''libata in the Linux kernel before 2.6.27.9 does not set minimum timeouts for SG_IO requests, which allows local users to cause a denial of service (Programmed I/O mode on drives) via multiple simultaneous invocations of an unspecified test program.''')) |
1272 | + |
1273 | + self.assertEqual("iGaming", h.get_ignore_suggestion('''Multiple SQL injection vulnerabilities in iGaming 1.5 and earlier allow remote attackers to execute arbitrary SQL commands via the browse parameter to (1) previews.php and (2) reviews.php, and the (3) id parameter to index.php in a viewarticle action.''')) |
1274 | + |
1275 | + self.assertEqual("PHP iCalendar", h.get_ignore_suggestion('''PHP iCalendar 2.24 and earlier allows remote attackers to bypass authentication by setting the phpicalendar and phpicalendar_login cookies to 1.' |
1276 | +''')) |
1277 | + |
1278 | + # Test length truncation, tweaked to avoid "has" matcher |
1279 | + self.assertEqual("** TEST CVE ** This candidate HAS been reserved by an", h.get_ignore_suggestion('''** TEST CVE ** This candidate HAS been reserved by an organization or individual that will use it when announcing a new security problem. When the candidate has been publicized, the details for this candidate will be provided.''')) |
1280 | + |
1281 | + self.assertEqual("Sun OpenSolaris", h.get_ignore_suggestion('''Unspecified vulnerability in the root/boot archive tool in Sun OpenSolaris has unknown impact and local attack vectors, related to a "Temporary file vulnerability," aka Bug ID 6653455.''')) |
1282 | + |
1283 | + self.assertEqual("Red Hat Certificate System", h.get_ignore_suggestion('''Red Hat Certificate System 7.2 uses world-readable permissions for password.conf and unspecified other configuration files, which allows local users to discover passwords by reading these files.''')) |
1284 | + |
1285 | + self.assertEqual("Microsoft Internet Explorer", h.get_ignore_suggestion('''An unspecified function in the JavaScript implementation in Microsoft Internet Explorer creates and exposes a "temporary footprint" when there is a current login to a web site, which makes it easier for remote attackers to trick a user into acting upon a spoofed pop-up message, aka an "in-session phishing attack." NOTE: as of 20090116, the only disclosure is a vague pre-advisory with no actionable information. However, because it is from a well-known researcher, it is being assigned a CVE identifier for tracking purposes.''')) |
1286 | + |
1287 | + self.assertEqual("Umer Inc Songs Portal", h.get_ignore_suggestion('''SQL injection vulnerability in albums.php in Umer Inc Songs Portal allows remote attackers to execute arbitrary SQL commands via the id parameter.''')) |
1288 | + |
1289 | + self.assertEqual("Limbo CMS", h.get_ignore_suggestion('''SQL injection vulnerability in open.php in the Private Messaging (com_privmsg) component for Limbo CMS allows remote attackers to execute arbitrary SQL commands via the id parameter in a pms action to index.php.''')) |
1290 | + |
1291 | + self.assertEqual("phpscripts Ranking Script", h.get_ignore_suggestion('''phpscripts Ranking Script allows remote attackers to bypass authentication and gain administrative access by sending an admin=ja cookie.''')) |
1292 | + |
1293 | + self.assertEqual("A4Desk Event Calendar", h.get_ignore_suggestion('''PHP remote file inclusion vulnerability in index.php in A4Desk Event Calendar, when magic_quotes_gpc is disabled, allows remote attackers to execute arbitrary PHP code via a URL in the v parameter.''')) |
1294 | + |
1295 | + self.assertEqual("Galatolo WebManager", h.get_ignore_suggestion('''Cross-site scripting (XSS) vulnerability in result.php in Galatolo WebManager (GWM) 1.0 allows remote attackers to inject arbitrary web script or HTML via the key parameter.''')) |
1296 | + |
1297 | + self.assertEqual("Sun OpenSolaris", h.get_ignore_suggestion('''Unspecified vulnerability in the process (aka proc) filesystem in Sun OpenSolaris snv_85 through snv_100 allows local users to gain privileges via vectors related to the contract filesystem.''')) |
1298 | + |
1299 | + self.assertEqual("Dreampics Gallery Builder", h.get_ignore_suggestion('''SQL injection vulnerability in index.php in Dreampics Gallery Builder allows remote attackers to execute arbitrary SQL commands via the exhibition_id parameter in a gallery.viewPhotos action.''')) |
1300 | + |
1301 | + self.assertEqual("Omilen Photo Gallery component for Joomla!", h.get_ignore_suggestion('''Directory traversal vulnerability in the Omilen Photo Gallery (com_omphotogallery) component Beta 0.5 for Joomla! allows remote attackers to include and execute arbitrary local files via directory traversal sequences in the controller parameter to index.php.''')) |
1302 | + |
1303 | + self.assertEqual("Webform module for Drupal", h.get_ignore_suggestion('''Cross-site scripting (XSS) vulnerability in the Webform module 5.x before 5.x-2.7 and 6.x before 6.x-2.7, a module for Drupal, allows remote attackers to inject arbitrary web script or HTML via a submission.''')) |
1304 | + |
1305 | + self.assertEqual("Itamar Elharar MusicGallery component for Joomla!", h.get_ignore_suggestion('''SQL injection vulnerability in the Itamar Elharar MusicGallery (com_musicgallery) component for Joomla! allows remote attackers to execute arbitrary SQL commands via the id parameter in an itempage action to index.php. NOTE: the provenance of this information is unknown; the details are obtained solely from third party information.''')) |
1306 | + |
1307 | + self.assertEqual("Kide Shoutbox component for Joomla!", h.get_ignore_suggestion('''The Kide Shoutbox (com_kide) component 0.4.6 for Joomla! does not properly perform authentication, which allows remote attackers to post messages with an arbitrary account name via an insertar action to index.php. NOTE: the provenance of this information is unknown; the details are obtained solely from third party information.''')) |
1308 | + |
1309 | + self.assertEqual("WP-Forum plugin for WordPress", h.get_ignore_suggestion('''Multiple SQL injection vulnerabilities in the WP-Forum plugin before 2.4 for WordPress allow remote attackers to execute arbitrary SQL commands via (1) the search_max parameter in a search action to the default URI, related to wpf.class.php; (2) the forum parameter to an unspecified component, related to wpf.class.php; (3) the topic parameter in a viewforum action to the default URI, related to the remove_topic function in wpf.class.php; or the id parameter in a (4) editpost or (5) viewtopic action to the default URI, related to wpf-post.php.''')) |
1310 | + |
1311 | + self.assertEqual("ListMan extension for TYPO3", h.get_ignore_suggestion('''Cross-site scripting (XSS) vulnerability in the ListMan (nl_listman) extension 1.2.1 for TYPO3 allows remote attackers to inject arbitrary web script or HTML via unspecified vectors.''')) |
1312 | + |
1313 | + self.assertEqual("multiple status.net issues", h.get_ignore_suggestion('''ML-Date: 2011-01-25 12:08:05, ML-Subject: Re: CVE request: multiple status.net issues''')) |
1314 | + self.assertEqual("multiple status.net issues", h.get_ignore_suggestion('''ML-Date: 2011-01-25 12:08:05, ML-Subject: CVE request: multiple status.net issues''')) |
1315 | + self.assertEqual("multiple status.net issues", h.get_ignore_suggestion('''ML-Date: 2011-01-25 12:08:05, ML-Subject: multiple status.net issues''')) |
1316 | + self.assertEqual("Mambo CMS", h.get_ignore_suggestion('''ML-Date: 2011-06-28 16:24:28, ML-Subject: Re: CVE Request: Mambo CMS 4.6.x | Multiple Cross Site Scripting Vulnerabilities''')) |
1317 | + |
1318 | + self.assertEqual("Apple iOS", h.get_ignore_suggestion('''The DNAv4 protocol implementation in the DHCP component in Apple iOS before 6 sends Wi-Fi packets containing a MAC address of a host on a previously used network, which might allow remote attackers to obtain sensitive information about previous device locations by sniffing an unencrypted Wi-Fi network for these packets.''')) |
1319 | + |
1320 | + self.assertEqual("Conceptronic", h.get_ignore_suggestion('''Multiple open redirect vulnerabilities on the Conceptronic C54APM access point with runtime code 1.26 allow remote attackers to redirect users to arbitrary web sites and conduct phishing attacks via (1) the submit-url parameter in a Refresh action to goform/formWlSiteSurvey or (2) the wlan-url parameter to goform/formWlanSetup.''')) |
1321 | + |
1322 | + self.assertEqual("Tapjoy library for Android", h.get_ignore_suggestion('''The Tapjoy library for Android does not verify X.509 certificates from SSL servers, which allows man-in-the-middle attackers to spoof servers and obtain sensitive information via a crafted certificate.''')) |
1323 | + |
1324 | + self.assertEqual("kamkomesan application for Android", h.get_ignore_suggestion('''The kamkomesan (aka com.anek.kamkomesan) application 1.0 for Android does not verify X.509 certificates from SSL servers, which allows man-in-the-middle attackers to spoof servers and obtain sensitive information via a crafted certificate.''')) |
1325 | + |
1326 | + self.assertEqual("DataTables plugin for jQuery", h.get_ignore_suggestion('''Cross-site scripting (XSS) vulnerability in the DataTables plugin 1.10.8 and earlier for jQuery allows remote attackers to inject arbitrary web script or HTML via the scripts parameter to media/unit_testing/templates/6776.php.''')) |
1327 | + |
1328 | + self.assertEqual("Cisco Application Policy Infrastructure Controller (APIC)", h.get_ignore_suggestion('''A vulnerability in Cisco Application Policy Infrastructure Controller (APIC) could allow an authenticated, remote attacker to gain higher privileges than the account is assigned.''')) |
1329 | + |
1330 | + self.assertEqual("Redirection", h.get_ignore_suggestion('''Redirection version 2.7.3 contains a ACE via file inclusion vulnerability in Pass-through mode that can result in allows admins to execute any PHP file in the filesystem.''')) |
1331 | + |
1332 | + self.assertEqual("topydo", h.get_ignore_suggestion('''topydo contains a CWE-20: Improper Input Validation vulnerability in ListFormatParser::parse, file topydo/lib/ListFormat.py line 292 as of d4f843dac71308b2f29a7c2cdc76f055c3841523 that can result in Injection of arbitrary bytes to the terminal,''')) |
1333 | + |
1334 | + self.assertEqual("Joplin", h.get_ignore_suggestion('''Joplin version prior to 1.0.90 contains a XSS evolving into code execution due to enabled nodeIntegration.''')) |
1335 | + |
1336 | + self.assertEqual("Foxit Reader", h.get_ignore_suggestion('''This vulnerability allows remote attackers to execute arbitrary code on vulnerable installations of Foxit Reader 9.2.0.9297.''')) |
1337 | + |
1338 | + self.assertEqual("Exquisite Ultimate Newspaper theme for WordPress", h.get_ignore_suggestion('''The Exquisite Ultimate Newspaper theme 1.3.3 for WordPress has XSS via the anchor identifier to assets/js/jquery.foundation.plugins.js.''')) |
1339 | + self.assertEqual("Weaver Xtreme Theme for WordPress", h.get_ignore_suggestion('''The Weaver Xtreme Theme for WordPress is vulnerable to stored Cross-Site Scripting due to insufficient escaping of the profile display name in versions up to, and including, 5.0.7.''')) |
1340 | + self.assertEqual("Weaver Show Posts Plugin for WordPress", h.get_ignore_suggestion('''The Weaver Show Posts Plugin for WordPress is vulnerable to stored Cross-Site Scripting due to insufficient escaping of the profile display name in versions up to, and including, 1.6.''')) |
1341 | + self.assertEqual("WordPress File Upload and WordPress File Upload Pro plugins for WordPress", h.get_ignore_suggestion('''The WordPress File Upload and WordPress File Upload Pro plugins for WordPress are vulnerable to Path Traversal in versions up to, and including, 4.19.1 via the vulnerable parameter wfu_newpath.''')) |
1342 | + self.assertEqual("browserless-chrome", h.get_ignore_suggestion('''This affects all versions of package browserless-chrome. User input flowing from the workspace endpoint gets used to create a file path filePath and this is fetched and then sent back to a user. This can be escaped to fetch arbitrary files from a server.''')) |
1343 | + self.assertEqual("@absolunet/kafe", h.get_ignore_suggestion('''This affects the package @absolunet/kafe before 3.2.10. It allows cause a denial of service when validating crafted invalid emails.''')) |
1344 | + self.assertEqual("Magneticlab Sàrl Homepage Pop-up plugin", h.get_ignore_suggestion('''Cross-Site Request Forgery (CSRF) vulnerability in Magneticlab Sàrl Homepage Pop-up plugin <= 1.2.5 versions.''')) |
1345 | + |
1346 | + # handle odd whitespace |
1347 | + self.assertEqual("PTC Vuforia Studio does not require a token.", h.get_ignore_suggestion(''' |
1348 | + |
1349 | + |
1350 | + |
1351 | + |
1352 | + PTC Vuforia Studio does not require a token. |
1353 | + ''')) |
1354 | + self.assertEqual("zxcvbn-ts", h.get_ignore_suggestion('''zxcvbn-ts is a password strength estimator written in typescript.''')) |
1355 | + self.assertEqual("VMware Tools for Windows", h.get_ignore_suggestion('''VMware Tools for Windows (10.x.y prior to 10.3.10, 11.x.y prior to 11.1.5) contains a denial-of-service vulnerability due to NULL pointer dereference in vm3dmp driver. Successful exploitation of this issue may allow attackers with normal user privileges to create a denial-of-service condition on the guest machine where VMware Tools is installed.''')) |
1356 | + |
1357 | + self.assertEqual("3DPrint WordPress plugin", h.get_ignore_suggestion("The 3DPrint WordPress plugin before 3.5.6.9 does not protect against CSRF attacks in the modified version of Tiny File Manager included with the plugin, allowing an attacker to craft a malicious request that will create an archive of any files or directories on the target server by tricking a logged in admin into submitting a form.")) |
1358 | + |
1359 | + self.assertEqual("Feathersjs", h.get_ignore_suggestion('''Feathersjs is a framework for creating web APIs and real-time applications with TypeScript or JavaScript.''')) |
1360 | + |
1361 | + self.assertEqual("PaulPrinting CMS 2018", h.get_ignore_suggestion("A vulnerability, which was classified as problematic, was found in PaulPrinting CMS 2018")) |
1362 | + |
1363 | diff --git a/scripts/uct/config.py b/scripts/uct/config.py |
1364 | new file mode 100644 |
1365 | index 0000000..9476199 |
1366 | --- /dev/null |
1367 | +++ b/scripts/uct/config.py |
1368 | @@ -0,0 +1,75 @@ |
1369 | +#!/usr/bin/env python3 |
1370 | +# -*- coding: utf-8 -*- |
1371 | +# |
1372 | +# Copyright (C) 2008-2024 Canonical Ltd. |
1373 | +# Author: Jamie Strandboge <jamie@ubuntu.com> |
1374 | +# Author: Kees Cook <kees@ubuntu.com> |
1375 | +# Author: Steve Beattie <steve.beattie@canonical.com> |
1376 | +# |
1377 | +# This script is distributed under the terms and conditions of the GNU General |
1378 | +# Public License, Version 3 or later. See http://www.gnu.org/copyleft/gpl.html |
1379 | +# for details. |
1380 | + |
1381 | +from __future__ import print_function |
1382 | + |
1383 | +import os |
1384 | + |
1385 | +# nobody should be using ubuntu 14.04 LTS with this code, so we don't |
1386 | +# need a fallback implementation to ConfigObj |
1387 | +from configobj import ConfigObj |
1388 | + |
1389 | +# private singleton object, use read_config() to access |
1390 | +_config = None |
1391 | + |
1392 | + |
1393 | +# _read_config: does the actual work without writing to the global |
1394 | +# singleton. This can be used in tests where read_config() will always |
1395 | +# return the same thing. |
1396 | +def _read_config(_config_file=None): |
1397 | + |
1398 | + if _config_file: |
1399 | + config_file = _config_file |
1400 | + else: |
1401 | + config_file = os.path.join( |
1402 | + os.path.expanduser("~"), ".ubuntu-cve-tracker.conf" |
1403 | + ) |
1404 | + |
1405 | + if not os.path.exists(config_file): |
1406 | + raise ValueError("Could not find '%s'" % (config_file)) |
1407 | + |
1408 | + config = ConfigObj(config_file) |
1409 | + |
1410 | + validate_config(config, config_file) |
1411 | + |
1412 | + return config |
1413 | + |
1414 | + |
1415 | +# _read_config_cached: if the results of parsing the config file have |
1416 | +# not already been cached, save it; otherwise return the singleton. |
1417 | +# Takes an optional config file path as an argument. This can be used in tests |
1418 | +# where read_config() will only use ~/.ubuntu-cve-tracker.conf |
1419 | +def _read_config_cached(_config_file=None): |
1420 | + global _config |
1421 | + |
1422 | + # if we've already parsed the config file, return what we already |
1423 | + # have |
1424 | + if not _config: |
1425 | + _config = _read_config() |
1426 | + |
1427 | + return _config |
1428 | + |
1429 | + |
1430 | +# read_uct_config: call with no arguments to get the contents of |
1431 | +# ~/.ubuntu-cve-tracker.conf |
1432 | +def read_uct_config(): |
1433 | + return _read_config_cached() |
1434 | + |
1435 | + |
1436 | +# XXX-FIXME this should use configobj's Validator stuff |
1437 | +def validate_config(config, config_file): |
1438 | + |
1439 | + # Validate required arguments |
1440 | + if "plb_authentication" not in config: |
1441 | + raise ValueError(("Could not find 'plb_authentication' entry in %s." % (config_file))) |
1442 | + if not os.path.exists(config["plb_authentication"]): |
1443 | + raise ValueError(("Could not find file specified by 'plb_authentication' in %s." % (config_file))) |
1444 | diff --git a/scripts/check_cves/ignored_cache.py b/scripts/uct/ignored_cache.py |
1445 | similarity index 100% |
1446 | rename from scripts/check_cves/ignored_cache.py |
1447 | rename to scripts/uct/ignored_cache.py |
1448 | diff --git a/scripts/uct/suggestions.py b/scripts/uct/suggestions.py |
1449 | new file mode 100755 |
1450 | index 0000000..fe496fc |
1451 | --- /dev/null |
1452 | +++ b/scripts/uct/suggestions.py |
1453 | @@ -0,0 +1,131 @@ |
1454 | +#!/usr/bin/env python3 |
1455 | +# -*- coding: utf-8 -*- |
1456 | + |
1457 | +# suggestions module |
1458 | +# |
1459 | +# Author: Martin Pitt <martin.pitt@ubuntu.com> |
1460 | +# Author: Kees Cook <kees@ubuntu.com> |
1461 | +# Author: Jamie Strandboge <jamie@ubuntu.com> |
1462 | +# Author: Marc Deslauriers <marc.deslauriers@ubuntu.com> |
1463 | +# Author: Steve Beattie <sbeattie@ubuntu.com> |
1464 | +# Copyright (C) 2005-2024 Canonical Ltd. |
1465 | +# |
1466 | +# This script is distributed under the terms and conditions of the GNU General |
1467 | +# Public License, Version 2 or later. See http://www.gnu.org/copyleft/gpl.html |
1468 | +# for details. |
1469 | + |
1470 | +import re |
1471 | + |
1472 | +class IgnoreSuggestions: |
1473 | + |
1474 | + def get_ignore_suggestion(self, text): |
1475 | + '''Try to find a reasonable suggestion for the user.''' |
1476 | + suggestion = "" |
1477 | + |
1478 | + # remove any whitespace |
1479 | + rev_text = text.strip() |
1480 | + # strip out the added mailing list stuff (locate_cves.py importing) |
1481 | + rev_text = re.sub(r'^ML-Date: .* ML-Subject: ', '', rev_text) |
1482 | + rev_text = re.sub(r'^(|Re: )CVE (r|R)equest: ', '', rev_text) |
1483 | + |
1484 | + first_sentence = re.split(r'\. ', rev_text)[0] |
1485 | + |
1486 | + # hunt for module/component |
1487 | + nouns = ["library", "templates?", "components?", "modules?", "[Pp]lug-?ins?", "extension", "application", "[Tt]hemes?"] |
1488 | + products = ["Joomla!", "Drupal", "WordPress", "TYPO3", "Mambo", "Android", "jQuery"] |
1489 | + match = re.search(r'(?: in t|^T)he (.*) (%s) (?:.* )?for (%s)' % ("|".join(nouns), "|".join(products)), |
1490 | + first_sentence) |
1491 | + preposition = "for" |
1492 | + if not match: |
1493 | + # try swapping order of product and noun in which case there is no preposition |
1494 | + match = re.search(r'(?: in t|^T)he (.*) (%s) (%s) (?:.* )' % ("|".join(products), "|".join(nouns)), |
1495 | + first_sentence) |
1496 | + preposition = "" |
1497 | + if match: |
1498 | + module = match.group(1) |
1499 | + noun = match.group(2) |
1500 | + product = match.group(3) |
1501 | + for marker in [" module", " ("]: |
1502 | + if marker in module: |
1503 | + module = module.split(marker)[0] |
1504 | + return " ".join(filter(lambda x: len(x) > 0, [module, noun, preposition, product])) |
1505 | + |
1506 | + # hunt for a description of a thing written in a language or for creating something else |
1507 | + match = re.search(r'(.*) is a (?:.*) (written in|for creating) (?:.*)', first_sentence) |
1508 | + if match: |
1509 | + return match.group(1) |
1510 | + |
1511 | + # hunt for a product on a platform |
1512 | + match = re.search(r'.* for (Windows|Linux|Mac OS|iOS|Android|iPhone|iPad|BlackBerry|Symbian)', first_sentence) |
1513 | + if match: |
1514 | + return match.group(0) |
1515 | + |
1516 | + # look for common pattern |
1517 | + match = re.search(r'A vulnerability(?:, which was)? classified as (?:.*),? was found in (.*)', first_sentence) |
1518 | + if match: |
1519 | + return match.group(1) |
1520 | + |
1521 | + # drop commas-extensions |
1522 | + if ',' in first_sentence: |
1523 | + first_sentence = re.split(r',', first_sentence)[0] |
1524 | + phrases = re.split(r' [io]n ', first_sentence) |
1525 | + |
1526 | + # default to the last phrase |
1527 | + suggestion = phrases[-1] |
1528 | + # move to earlier phrase if suggestion starts with "a" |
1529 | + if suggestion.startswith('a ') and len(phrases) > 1: |
1530 | + suggestion = phrases[-2] |
1531 | + |
1532 | + version_preps = r'(\s+(before|through|prior to|versions?|[<>]=?))+\s*' |
1533 | + version_regex = r'\s+([a-zA-Z\._\-]*[0-9]+[a-zA-Z\._\-]*)+' |
1534 | + # prefer 'Apple iOS before <version>' or 'Apple Mac OS X through |
1535 | + # <version' in the last phrase over other suggestions |
1536 | + if not re.search(r'' + version_preps + version_regex, suggestion): |
1537 | + # grab the first phrase with something that may be a version number |
1538 | + for p in phrases: |
1539 | + if re.search(r'' + version_regex, p): |
1540 | + suggestion = p |
1541 | + break |
1542 | + if re.search(r'^[^,]+\s+for\s+', p): |
1543 | + suggestion = p |
1544 | + break |
1545 | + |
1546 | + # try to find a good suggestion from the phrase (ie suggest 'Linux |
1547 | + # kernel' from 'the Linux kernel before 2.6.27') |
1548 | + suggestion = re.split(r'\s+([a-zA-Z\._\-]*[0-9]+[a-zA-Z\._\-]*)+', suggestion)[0] |
1549 | + # "blah in component for Software" |
1550 | + if re.search(r'^[^,]+\s+for\s+', suggestion): |
1551 | + suggestion = re.split(r'[^,]+\s+for\s+', suggestion)[1] |
1552 | + |
1553 | + # Chop off action verbs |
1554 | + cleanup_regexes = [ |
1555 | + # clean up leading "in" or "the" |
1556 | + r'^\s*([tT]he|[iI]n)\s+', |
1557 | + # clean up trailing version prepositions like "before" or "through" |
1558 | + # from version details |
1559 | + r'' + version_preps + '$', |
1560 | + # clean up trailing parens |
1561 | + r'\s+\([^\)]+\)\s*$', |
1562 | + # action verbs |
1563 | + r'\s+(has|creates|allows|could|contains)($|\s+.*)', |
1564 | + # "vulnerbale installations of" |
1565 | + r'(^|\s+)vulnerable\sinstallations?\sof($|\s+)', |
1566 | + # This affects all versions of package |
1567 | + r'^This affects all versions of package\s+', |
1568 | + # This affects the package |
1569 | + r'^This affects the package\s+', |
1570 | + ] |
1571 | + |
1572 | + for regex in cleanup_regexes: |
1573 | + if re.search(regex, suggestion): |
1574 | + suggestion = re.sub(regex, '', suggestion) |
1575 | + |
1576 | + # if the phrase is too long, truncate it to max_length, but make |
1577 | + # sure we don't have a partial word at the end |
1578 | + max_length = 64 |
1579 | + if len(suggestion) > max_length: |
1580 | + suggestion = suggestion[:max_length] |
1581 | + suggestion = re.sub(r'\s+\w+$', '', suggestion) |
1582 | + |
1583 | + return suggestion |
1584 | + |
1585 | diff --git a/scripts/usn_lib.py b/scripts/usn_lib.py |
1586 | index 3e45239..d8c7622 100644 |
1587 | --- a/scripts/usn_lib.py |
1588 | +++ b/scripts/usn_lib.py |
1589 | @@ -16,7 +16,7 @@ import subprocess |
1590 | import sys |
1591 | import urllib |
1592 | from source_map import version_compare |
1593 | -import cve_lib |
1594 | +from uct.config import read_uct_config |
1595 | |
1596 | try: |
1597 | import cPickle |
1598 | @@ -164,7 +164,7 @@ class USNdb(object): |
1599 | if db: |
1600 | db_name = db |
1601 | else: |
1602 | - config = cve_lib.read_config() |
1603 | + config = read_uct_config() |
1604 | if config['usn_db_copy']: |
1605 | db_name = config['usn_db_copy'] |
1606 | |
1607 | diff --git a/test/uct/config/no_plb_auth_entry.conf b/test/uct/config/no_plb_auth_entry.conf |
1608 | new file mode 100644 |
1609 | index 0000000..755ad8c |
1610 | --- /dev/null |
1611 | +++ b/test/uct/config/no_plb_auth_entry.conf |
1612 | @@ -0,0 +1,2 @@ |
1613 | +# python-launchpad-bugs authentication cookies file (sis-changes) |
1614 | +not_plb_authentication="/bin/true" |
1615 | diff --git a/test/uct/config/plb_auth_dev_null.conf b/test/uct/config/plb_auth_dev_null.conf |
1616 | new file mode 100644 |
1617 | index 0000000..1e33174 |
1618 | --- /dev/null |
1619 | +++ b/test/uct/config/plb_auth_dev_null.conf |
1620 | @@ -0,0 +1,2 @@ |
1621 | +# python-launchpad-bugs authentication cookies file (sis-changes) |
1622 | +plb_authentication="/dev/null" |
1623 | diff --git a/test/uct/config/plb_auth_does_not_exist.conf b/test/uct/config/plb_auth_does_not_exist.conf |
1624 | new file mode 100644 |
1625 | index 0000000..9a81f39 |
1626 | --- /dev/null |
1627 | +++ b/test/uct/config/plb_auth_does_not_exist.conf |
1628 | @@ -0,0 +1,2 @@ |
1629 | +# python-launchpad-bugs authentication cookies file (sis-changes) |
1630 | +plb_authentication="/does/not/exist" |
1631 | diff --git a/test/uct/config/uct.conf b/test/uct/config/uct.conf |
1632 | new file mode 100644 |
1633 | index 0000000..8bf6334 |
1634 | --- /dev/null |
1635 | +++ b/test/uct/config/uct.conf |
1636 | @@ -0,0 +1,15 @@ |
1637 | +# python-launchpad-bugs authentication cookies file (sis-changes) |
1638 | +plb_authentication="/dev/null" |
1639 | + |
1640 | +# path to Debian "security-tracker" GIT tree (check-cves) |
1641 | +secure_testing_path='/home/ubuntu-security/git/cve_trackers/debian-security-tracker' |
1642 | + |
1643 | +# path to archive-layout mirror of supported architectures |
1644 | +# sis-generate-usn, packages-mirror) |
1645 | +packages_mirror='/home/ubuntu-security/archive-metadata/ubuntu-archive-metadata' |
1646 | + |
1647 | +# same as packages_mirror, but for Debian testing repository |
1648 | +debian_mirror='/home/ubuntu-security/archive-metadata/debian-testing-archive-metadata' |
1649 | + |
1650 | +# path to usn-tool bzr tree, used to manipulate USN databases |
1651 | +usn_tool='/home/ubuntu-security/git/usn-tool' |
Do you need to add the new cache directory to .gitignore?