0
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
1 # -*- coding: utf-8 -*- |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
2 # Description: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
3 # Methods for parsing CVRF documents |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
4 # |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
5 # Authors: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
6 # BenoƮt Allard <benoit.allard@greenbone.net> |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
7 # |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
8 # Copyright: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
9 # Copyright (C) 2014 Greenbone Networks GmbH |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
10 # |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
11 # This program is free software; you can redistribute it and/or |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
12 # modify it under the terms of the GNU General Public License |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
13 # as published by the Free Software Foundation; either version 2 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
14 # of the License, or (at your option) any later version. |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
15 # |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
16 # This program is distributed in the hope that it will be useful, |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
19 # GNU General Public License for more details. |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
20 # |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
21 # You should have received a copy of the GNU General Public License |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
22 # along with this program; if not, write to the Free Software |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
23 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
24 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
25 """\ |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
26 Methods for parsing of CVRF Documents |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
27 """ |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
28 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
29 from __future__ import print_function |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
30 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
31 import re |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
32 import textwrap |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
33 import xml.etree.ElementTree as ET |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
34 from datetime import datetime, timedelta |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
35 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
36 try: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
37 from datetime import timezone |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
38 except ImportError: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
39 from ..py2 import FixedTimeZone as timezone |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
40 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
41 from ..cvrf import (CVRF, CVRFPublisher, CVRFTracking, CVRFRevision, CVRFNote, |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
42 CVRFAcknowledgment, CVRFProductBranch, CVRFFullProductName, CVRFGenerator, |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
43 CVRFRelationship, CVRFVulnerability, CVRFVulnerabilityID, CVRFThreat, |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
44 CVRFProductStatus, CVRFCVSSSet, CVRFReference, CVRFRemediation, CVRFGroup, |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
45 CVRFInvolvement, CVRFCWE, CVRFTrackingID) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
46 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
47 NAMESPACES = { |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
48 'cvrf': "http://www.icasi.org/CVRF/schema/cvrf/1.1", |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
49 'prod': "http://www.icasi.org/CVRF/schema/prod/1.1", |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
50 'vuln': "http://www.icasi.org/CVRF/schema/vuln/1.1", |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
51 'xml': "http://www.w3.org/XML/1998/namespace", |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
52 } |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
53 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
54 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
55 def UN(ns, name): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
56 """ UN for Universal Name """ |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
57 return "{%s}%s" % (NAMESPACES[ns], name) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
58 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
59 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
60 def parseVersion(string): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
61 return tuple(int(i) for i in string.split('.')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
62 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
63 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
64 def parseDate(string): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
65 m = re.match('(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:([+-])(\d{2}):(\d{2})|(Z))?', string) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
66 if (m.group(7) is None) or (m.group(7) == 'Z'): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
67 tzhours = 0 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
68 tzmin = 0 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
69 else: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
70 tzhours = int(m.group(8)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
71 if m.group(7) == '-': |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
72 tzhours = - tzhours |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
73 tzmin = int(m.group(9)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
74 return datetime(int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)), int(m.group(5)), int(m.group(6)), tzinfo=timezone(timedelta(hours=tzhours, minutes=tzmin))) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
75 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
76 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
77 def parseNote(elem): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
78 return CVRFNote( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
79 elem.attrib['Type'], |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
80 int(elem.attrib['Ordinal']), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
81 textwrap.dedent(elem.text).strip(), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
82 elem.attrib.get('Title'), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
83 elem.attrib.get('Audience') |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
84 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
85 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
86 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
87 def parseReference(elem, ns='cvrf'): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
88 """ ns is the current namespace """ |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
89 return CVRFReference( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
90 elem.findtext(UN(ns, 'URL')).strip(), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
91 textwrap.dedent(elem.findtext(UN(ns, 'Description'))).strip(), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
92 elem.attrib.get('Type') |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
93 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
94 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
95 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
96 def parseAcknowledgment(elem, ns='cvrf'): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
97 return CVRFAcknowledgment( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
98 elem.findtext(UN(ns, 'Name')), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
99 elem.findtext(UN(ns, 'Organization')), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
100 elem.findtext(UN(ns, 'Description')), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
101 elem.findtext(UN(ns, 'URL')), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
102 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
103 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
104 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
105 def parseFullProductName(elem, parent): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
106 return CVRFFullProductName( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
107 elem.attrib['ProductID'], |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
108 elem.text.strip(), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
109 parent, |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
110 cpe=elem.attrib.get('CPE') |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
111 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
112 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
113 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
114 def parseProdBranch(elem, ptree, parentbranch=None): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
115 """ Recursively parses the branches and the terminal productnames """ |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
116 fpncvrf = elem.find(UN('prod', 'FullProductName')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
117 if (parentbranch is not None) and (fpncvrf is not None): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
118 # Don't process the products at the root of the tree |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
119 prod = parseFullProductName(fpncvrf, parentbranch) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
120 ptree.addProduct(prod) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
121 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
122 if parentbranch is None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
123 parentbranch = ptree |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
124 for brcvrf in elem.findall(UN('prod', 'Branch')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
125 br = CVRFProductBranch(brcvrf.attrib['Type'], brcvrf.attrib['Name'], parentbranch) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
126 # And go into recursion ... |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
127 br._childs = list(parseProdBranch(brcvrf, ptree, br)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
128 yield br |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
129 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
130 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
131 def parseVulnerability(elem): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
132 vuln = CVRFVulnerability(int(elem.attrib['Ordinal'])) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
133 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
134 xmltitle = elem.findtext(UN('vuln', 'Title')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
135 if xmltitle is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
136 vuln.setTitle(xmltitle.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
137 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
138 xmlID = elem.find(UN('vuln', 'ID')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
139 if xmlID is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
140 vuln.setID(CVRFVulnerabilityID(xmlID.attrib['SystemName'], xmlID.text.strip())) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
141 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
142 for xmlnote in elem.findall('/'.join([UN('vuln', 'Notes'), UN('vuln', 'Note')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
143 vuln.addNote(parseNote(xmlnote)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
144 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
145 xmldiscoverydate = elem.findtext(UN('vuln', 'DiscoveryDate')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
146 if xmldiscoverydate is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
147 vuln.setDiscoveryDate(parseDate(xmldiscoverydate)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
148 xmlreleasedate = elem.findtext(UN('vuln', 'ReleaseDate')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
149 if xmlreleasedate is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
150 vuln.setReleaseDate(parseDate(xmlreleasedate)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
151 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
152 for xmlinv in elem.findall('/'.join([UN('vuln', 'Involvements'), UN('vuln', 'Involvement')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
153 involvement = CVRFInvolvement( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
154 xmlinv.attrib['Party'], |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
155 xmlinv.attrib['Status'] |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
156 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
157 xmldescr = xmlinv.findtext(UN('vuln', 'Description')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
158 if xmldescr is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
159 involvement.setDescription(textwrap.dedent(xmldescr).strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
160 vuln.addInvolvement(involvement) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
161 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
162 xmlcve = elem.findtext(UN('vuln', 'CVE')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
163 if xmlcve is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
164 vuln.setCVE(xmlcve.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
165 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
166 for xmlcwe in elem.findall(UN('vuln', 'CWE')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
167 vuln.addCWE(CVRFCWE( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
168 xmlcwe.attrib['ID'], |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
169 xmlcwe.text.strip() |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
170 )) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
171 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
172 for xmlstatus in elem.findall('/'.join([UN('vuln', 'ProductStatuses'), UN('vuln', 'Status')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
173 status = CVRFProductStatus(xmlstatus.attrib['Type']) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
174 for xmlproductid in xmlstatus.findall(UN('vuln', 'ProductID')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
175 status.addProductID(xmlproductid.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
176 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
177 vuln.addProductStatus(status) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
178 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
179 for xmlthreat in elem.findall('/'.join([UN('vuln', 'Threats'), UN('vuln', 'Threat')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
180 threat = CVRFThreat( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
181 xmlthreat.attrib['Type'], |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
182 textwrap.dedent(xmlthreat.findtext(UN('vuln', 'Description'))).strip() |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
183 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
184 xmldate = xmlthreat.findtext(UN('vuln', 'Date')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
185 if xmldate is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
186 threat.setDate(parseDate(xmldate)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
187 for xmlpid in xmlthreat.findall(UN('vuln', 'ProductID')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
188 threat.addProductID(xmlpid.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
189 for xmlgid in xmlthreat.findall(UN('vuln', 'GroupID')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
190 threat.addGroupID(xmlgid.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
191 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
192 vuln.addThreat(threat) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
193 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
194 for xmlcvss in elem.findall('/'.join([UN('vuln', 'CVSSScoreSets'), UN('vuln', 'ScoreSet')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
195 cvss_set = CVRFCVSSSet(float(xmlcvss.findtext(UN('vuln', 'BaseScore')).strip())) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
196 xmltempscore = xmlcvss.findtext(UN('vuln', 'TemporalScore')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
197 if xmltempscore is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
198 cvss_set.setTemporalScore(float(xmltempscore.strip())) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
199 xmlenvscore = xmlcvss.findtext(UN('vuln', 'EnvironmentalScore')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
200 if xmlenvscore is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
201 cvss_set.setEnvironmentalScore(float(xmlenvscore.strip())) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
202 xmlvector = xmlcvss.findtext(UN('vuln', 'Vector')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
203 if xmlvector is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
204 cvss_set.setVector(xmlvector.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
205 for xmlprodid in xmlcvss.findall(UN('vuln', 'ProductID')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
206 cvss_set.addProductID(xmlprodid.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
207 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
208 vuln.addCVSSSet(cvss_set) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
209 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
210 for xmlremediation in elem.findall('/'.join([UN('vuln', 'Remediations'), UN('vuln', 'Remediation')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
211 remediation = CVRFRemediation( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
212 xmlremediation.attrib['Type'], |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
213 textwrap.dedent(xmlremediation.findtext(UN('vuln', 'Description'))).strip() |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
214 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
215 xmldate = xmlremediation.findtext(UN('vuln', 'Date')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
216 if xmldate is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
217 remediation.setDate(parseDate(xmldate)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
218 xmlentitlement = xmlremediation.findtext(UN('vuln', 'Entitlement')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
219 if xmlentitlement is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
220 remediation.setEntitlement(textwrap.dedent(xmlentitlement).strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
221 xmlurl = xmlremediation.findtext(UN('vuln', 'URL')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
222 if xmlurl is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
223 remediation.setURL(xmlurl.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
224 for xmlpid in xmlremediation.findall(UN('vuln', 'ProductID')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
225 remediation.addProductID(xmlpid.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
226 for xmlgid in xmlremediation.findall(UN('vuln', 'GroupID')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
227 remediation.addGroupID(xmlgid.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
228 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
229 vuln.addRemediation(remediation) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
230 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
231 for xmlref in elem.findall('/'.join([UN('vuln', 'References'), UN('vuln', 'Reference')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
232 vuln.addReference(parseReference(xmlref, 'vuln')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
233 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
234 for xmlack in elem.findall('/'.join([UN('vuln', 'Acknowledgments'), UN('vuln', 'Acknowledgment')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
235 vuln.addAcknowledgment(parseAcknowledgment(xmlack, 'vuln')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
236 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
237 return vuln |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
238 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
239 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
240 def parse(xml): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
241 if hasattr(xml, 'read'): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
242 xml = xml.read() |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
243 cvrfdoc = ET.fromstring(xml) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
244 if cvrfdoc.tag != UN('cvrf', 'cvrfdoc'): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
245 raise ValueError('Not a CVRF document !') |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
246 doc = CVRF( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
247 cvrfdoc.findtext(UN('cvrf', 'DocumentTitle')).strip(), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
248 cvrfdoc.findtext(UN('cvrf', 'DocumentType')).strip() |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
249 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
250 cvrfpub = cvrfdoc.find(UN('cvrf', 'DocumentPublisher')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
251 pub = CVRFPublisher(cvrfpub.attrib['Type'], cvrfpub.attrib.get('VendorID')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
252 doc.setPublisher(pub) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
253 contact = cvrfpub.find(UN('cvrf', 'ContactDetails')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
254 if contact is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
255 pub.setContact(contact.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
256 authority = cvrfpub.find(UN('cvrf', 'IssuingAuthority')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
257 if authority is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
258 pub.setAuthority(authority.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
259 cvrftracking = cvrfdoc.find(UN('cvrf', 'DocumentTracking')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
260 identification = CVRFTrackingID( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
261 cvrftracking.findtext('/'.join([UN('cvrf', 'Identification'), UN('cvrf', 'ID')])).strip() |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
262 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
263 for cvrfalias in cvrftracking.findall('/'.join([UN('cvrf', 'Identification'), UN('cvrf', 'Alias')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
264 identification.addAlias(cvrfalias.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
265 tracking = CVRFTracking( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
266 identification, |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
267 cvrftracking.findtext(UN('cvrf', 'Status')).strip(), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
268 parseVersion(cvrftracking.findtext(UN('cvrf', 'Version')).strip()), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
269 parseDate(cvrftracking.findtext(UN('cvrf', 'InitialReleaseDate')).strip()), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
270 parseDate(cvrftracking.findtext(UN('cvrf', 'CurrentReleaseDate')).strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
271 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
272 doc.setTracking(tracking) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
273 for cvrfrev in cvrftracking.findall('/'.join([UN('cvrf', 'RevisionHistory'), UN('cvrf', 'Revision')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
274 rev = CVRFRevision( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
275 parseVersion(cvrfrev.findtext(UN('cvrf', 'Number')).strip()), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
276 parseDate(cvrfrev.findtext(UN('cvrf', 'Date')).strip()), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
277 cvrfrev.findtext(UN('cvrf', 'Description')).strip(), |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
278 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
279 tracking.addRevision(rev) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
280 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
281 xmlgenerator = cvrftracking.find(UN('cvrf', 'Generator')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
282 if xmlgenerator is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
283 generator = CVRFGenerator() |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
284 xmlengine = xmlgenerator.findtext(UN('cvrf', 'Engine')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
285 if xmlengine is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
286 generator.setEngine(xmlengine.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
287 xmldate = xmlgenerator.findtext(UN('cvrf', 'Date')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
288 if xmldate is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
289 generator.setDate(parseDate(xmldate.strip())) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
290 tracking.setGenerator(generator) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
291 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
292 for cvrfnote in cvrfdoc.findall('/'.join([UN('cvrf', 'DocumentNotes'), UN('cvrf', 'Note')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
293 doc.addNote(parseNote(cvrfnote)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
294 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
295 distr = cvrfdoc.findtext(UN('cvrf', 'DocumentDistribution')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
296 if distr is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
297 doc.setDistribution(textwrap.dedent(distr).strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
298 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
299 # This is in a quite free format, not sure how to do something with it ... |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
300 xmlaggsev = cvrfdoc.find(UN('cvrf', 'AggregateSeverity')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
301 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
302 for xmlref in cvrfdoc.findall('/'.join([UN('cvrf', 'DocumentReferences'), UN('cvrf', 'Reference')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
303 doc.addReference(parseReference(xmlref)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
304 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
305 for cvrfack in cvrfdoc.findall('/'.join([UN('cvrf', 'Acknowledgments'), UN('cvrf', 'Acknowledgment')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
306 doc.addAcknowledgment(parseAcknowledgment(cvrfack)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
307 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
308 # --- The ProductTree |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
309 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
310 cvrfptree = cvrfdoc.find(UN('prod', 'ProductTree')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
311 if cvrfptree is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
312 producttree = doc.createProductTree() |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
313 for branch in parseProdBranch(cvrfptree, producttree): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
314 producttree.addBranch(branch) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
315 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
316 for product in cvrfptree.findall(UN('prod', 'FullProductName')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
317 producttree.addProduct(parseFullProductName(product, producttree)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
318 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
319 for cvrfrel in cvrfptree.findall(UN('prod', 'Relationship')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
320 rel = CVRFRelationship( |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
321 cvrfrel.attrib['ProductReference'], |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
322 cvrfrel.attrib['RelationType'], |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
323 cvrfrel.attrib['RelatesToProductReference'] |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
324 ) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
325 producttree.addRelationship(rel) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
326 producttree.addProduct(parseFullProductName(cvrfrel.find(UN('prod', 'FullProductName')), rel)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
327 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
328 for xmlgroup in cvrfptree.findall('/'.join([UN('prod', 'ProductGroups'), UN('prod', 'Group')])): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
329 group = CVRFGroup(xmlgroup.attrib['GroupID']) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
330 xmldescr = xmlgroup.findtext(UN('prod', 'Description')) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
331 if xmldescr is not None: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
332 group.setDescription(textwrap.dedent(xmldescr).strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
333 for xmlpid in xmlgroup.findall(UN('prod', 'ProductID')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
334 group.addProductID(xmlpid.text.strip()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
335 producttree.addGroup(group) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
336 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
337 # --- The Vulnerabilities |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
338 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
339 for cvrfvuln in cvrfdoc.findall(UN('vuln', 'Vulnerability')): |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
340 doc.addVulnerability(parseVulnerability(cvrfvuln)) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
341 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
342 return doc |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
343 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
344 |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
345 if __name__ == "__main__": |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
346 import sys |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
347 with open(sys.argv[1], 'rt') as f: |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
348 cvrf = parse(f) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
349 cvrf.validate() |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
350 print(cvrf) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
351 print(cvrf.getHighestCVSS()._vector) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
352 print(cvrf.getProductList()) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
353 print(cvrf._producttree._branches) |
Benoît Allard <benoit.allard@greenbone.net>
parents:
diff
changeset
|
354 # print(cvrf._producttree._branches[0]._childs) |