1 |
commit: eed0fdb7e16ff4d2b475f7803a6888c8a3c0d7da |
2 |
Author: John Helmert III <ajak <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Jul 4 04:41:53 2021 +0000 |
4 |
Commit: John Helmert III <ajak <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Jul 4 04:41:53 2021 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/security.git/commit/?id=eed0fdb7 |
7 |
|
8 |
cvetool: implement dobug command |
9 |
|
10 |
This command grabs bug data from Bugzilla and adds the CVEs in its alias |
11 |
field to the GLSAMaker CVE database and assigns the CVEs to that bug in |
12 |
GLSAMaker. |
13 |
|
14 |
Signed-off-by: John Helmert III <ajak <AT> gentoo.org> |
15 |
|
16 |
bin/cvetool | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++----- |
17 |
1 file changed, 50 insertions(+), 5 deletions(-) |
18 |
|
19 |
diff --git a/bin/cvetool b/bin/cvetool |
20 |
index dc9c35d..233375a 100755 |
21 |
--- a/bin/cvetool |
22 |
+++ b/bin/cvetool |
23 |
@@ -9,7 +9,8 @@ from urllib.parse import urlencode |
24 |
from base64 import b64encode |
25 |
import requests |
26 |
|
27 |
-URI_BASE = 'https://glsamaker.gentoo.org' |
28 |
+GLSAMAKER_URI = 'https://glsamaker.gentoo.org' |
29 |
+BGO_URI = 'https://bugs.gentoo.org' |
30 |
|
31 |
|
32 |
class CVETool: |
33 |
@@ -78,6 +79,13 @@ class CVETool: |
34 |
sys.exit(1) |
35 |
|
36 |
self.pw(sys.argv[2], sys.argv[3]) |
37 |
+ elif command == 'dobug': |
38 |
+ if len(sys.argv) != 3: |
39 |
+ print('Usage: dobug <bug>') |
40 |
+ print('Adds and assigns a bug\'s CVEs') |
41 |
+ sys.exit(1) |
42 |
+ |
43 |
+ self.dobug(sys.argv[2]) |
44 |
else: |
45 |
self.usage(sys.argv[0]) |
46 |
sys.exit(1) |
47 |
@@ -162,6 +170,36 @@ class CVETool: |
48 |
def pw(self, user, password): |
49 |
print(b64encode(bytes(user + ':' + password, 'utf-8')).decode('ascii')) |
50 |
|
51 |
+ def dobug(self, bug): |
52 |
+ cves = [] |
53 |
+ data = self.request('/rest/bug/' + bug, jsondata=True, bgo=True) |
54 |
+ for alias in data['bugs'][0]['alias']: |
55 |
+ # If we were able to catch a sane error in new() to |
56 |
+ # reflect a duplicate CVE we wouldn't have to check if the |
57 |
+ # CVE exists beforehand with cve_exists, but it seems the |
58 |
+ # only other way is to try to do two requests and check if |
59 |
+ # one fails and the other succeeds (as new() currently |
60 |
+ # works). By doing it this way though, we actually reduce |
61 |
+ # the number of requests by not making useless requests in |
62 |
+ # new(). |
63 |
+ if self.is_cve(alias) and not self.cve_exists(alias): |
64 |
+ self.new(alias) |
65 |
+ cves.append(alias) |
66 |
+ # We can do assignment in one request, so do it |
67 |
+ if cves: |
68 |
+ self.assign(bug, cves) |
69 |
+ |
70 |
+ def cve_exists(self, cve): |
71 |
+ try: |
72 |
+ return self.request('/cve/info/' + cve, method='HEAD') == '' |
73 |
+ except RuntimeError: |
74 |
+ return False |
75 |
+ |
76 |
+ @staticmethod |
77 |
+ def is_cve(string): |
78 |
+ regex = re.compile('^(CVE-)?\d{4}-\d{4,}$') |
79 |
+ return regex.match(string) |
80 |
+ |
81 |
def get_internal_cve_id(self, cve): |
82 |
""" Resolves a CVE id to the internal databse ID """ |
83 |
return self.json_request('/cve/info/' + cve + '.json')['id'] |
84 |
@@ -170,8 +208,7 @@ class CVETool: |
85 |
return self.request(uri, method, jsondata=True) |
86 |
|
87 |
def cleanup_cve(self, string): |
88 |
- regex = re.compile('^(CVE-)?\d{4}-\d{4,}$') |
89 |
- if not regex.match(string): |
90 |
+ if not self.is_cve(string): |
91 |
raise ValueError('Cannot parse CVE: ' + string) |
92 |
|
93 |
if not string.startswith('CVE-'): |
94 |
@@ -179,8 +216,12 @@ class CVETool: |
95 |
else: |
96 |
return string |
97 |
|
98 |
- def request(self, uri, method='GET', jsondata=False): |
99 |
- full_uri = URI_BASE + uri |
100 |
+ def request(self, uri, method='GET', jsondata=False, bgo=False): |
101 |
+ if bgo: |
102 |
+ full_uri = BGO_URI + uri |
103 |
+ else: |
104 |
+ full_uri = GLSAMAKER_URI + uri |
105 |
+ |
106 |
if method == 'GET': |
107 |
response = \ |
108 |
requests.get(full_uri, |
109 |
@@ -189,6 +230,10 @@ class CVETool: |
110 |
response = \ |
111 |
requests.post(full_uri, |
112 |
headers={'Authorization': 'Basic ' + self.auth}) |
113 |
+ elif method == 'HEAD': |
114 |
+ response = \ |
115 |
+ requests.head(full_uri, |
116 |
+ headers={'Authorization': 'Basic ' + self.auth}) |
117 |
|
118 |
status = response.status_code |
119 |
if status == 404: |