Mercurial > farol > farolluz
diff farolluz/cvrf.py @ 18:8a89b7a591e6
merged
author | Benoît Allard <benoit.allard@greenbone.net> |
---|---|
date | Tue, 14 Oct 2014 16:49:36 +0200 |
parents | 90852c11fabd |
children | 4b53e7bcff0d |
line wrap: on
line diff
--- a/farolluz/cvrf.py Wed Sep 24 17:47:14 2014 +0200 +++ b/farolluz/cvrf.py Tue Oct 14 16:49:36 2014 +0200 @@ -65,6 +65,9 @@ def addAlias(self, alias): self._aliases.append(alias) + def getId(self): + return self._id + def validate(self): if not self._id: raise ValidationError('Document ID cannot be left empty') @@ -92,6 +95,9 @@ def setGenerator(self, generator): self._generator = generator + def getId(self): + return self._identification.getId() + def validate(self): if self._identification is None: raise ValidationError('Document Tracking needs to have an Identification') @@ -225,18 +231,19 @@ class CVRFAcknowledgment(object): - def __init__(self, name=None, organization=None, description=None, + def __init__(self, names=[], organizations=[], description=None, url=None): - self._name = name - self._organization = organization + self._names = names + self._organizations = organizations self._description = description self._url = url def getTitle(self): - return "%s - %s" % (self._name, self._organization) + return "%s - %s" % (', '.join(self._names), + ', '.join(self._organizations)) def validate(self): - if (not self._name) and (not self._organization) and (not self._description): + if (not self._names) and (not self._organizations) and (not self._description): raise ValidationError('An Acknowledgment must have at least a Name, an Organization or a Description') @@ -249,18 +256,9 @@ self._products = [] self._groups = [] - def addBranch(self, branch): - parent = self.getBranch(branch.getParent().getPath()) - if parent is self: - self._branches.append(branch) - else: - parent._childs.append(branch) - def addProduct(self, product): - if product not in self._products: - self._products.append(product) - if product._parent is not self: - product._parent._product = product + """ Add to the product list """ + self._products.append(product) def addRelationship(self, rel): self._relationships.append(rel) @@ -396,9 +394,9 @@ def __init__(self, _type, name, parentbranch): self._type = _type self._name = name - self._parentbranch = parentbranch self._childs = [] self._product = None + self.link(parentbranch) def getParent(self): return self._parentbranch @@ -455,6 +453,15 @@ self.getParent()._childs.remove(self) self._parentbranch = None + def link(self, parent): + """ Actually, only set the parent """ + self._parentbranch = parent + if self.isRoot(): + parent._branches.append(self) + else: + parent._childs.append(self) + + def validate(self): if not self._type: raise ValidationError('A Branch must have a Type') @@ -475,10 +482,10 @@ def __init__(self, productid, name, parent, cpe=None): self._productid = productid self._name = name + self._cpe = cpe # Can be None (directly under the tree), a ProductBranch, or a # Relationship - self._parent = parent - self._cpe = cpe + self.link(parent) def isRoot(self): return isinstance(self._parent, CVRFProductTree) @@ -502,13 +509,18 @@ return None def unlink(self): - """ Unset our _parent, and remove us from the _parent._childs """ - if self.isRoot(): - self._parent._products.remove(self) - else: + """ Unset our _parent, and remove us from the _parent._childs + We are still in the product list. + """ + if not self.isRoot(): self._parent._product = None self._parent = None + def link(self, parent): + self._parent = parent + if not self.isRoot(): + parent._product = self + def validate(self): if not self._productid: raise ValidationError('A Product must have a ProductID') @@ -655,6 +667,46 @@ return self._id._value return "#%d" % self._ordinal + def getNote(self, ordinal): + for note in self._notes: + if note._ordinal == ordinal: + return note + return None + + def mentionsProdId(self, productid): + """ Returns in which sub element, self is mentioning the productid """ + for category in (self._productstatuses, self._threats, self._cvsss, self._remediations): + for subelem in category: + if productid in subelem._productids: + yield subelem + + def isMentioningProdId(self, productid): + """ Returns if self is mentioning the productid """ + for e in self.mentionsProdId(productid): + # We only need to know if the generator yield at least one elem. + return True + return False + + def mentionsGroupId(self, groupid): + for category in (self._threats, self._remediations): + for subelem in category: + if groupid in subelem._groupids: + yield subelem + + def isMentioningGroupId(self, groupids): + """ Make sure you call this with a list (not a generator or a tuple) + when wished """ + if not isinstance(groupids, list): + groupids = [groupids] + for groupid in groupids: + print "testing GroupId: ", groupid + for _ in self.mentionsGroupId(groupid): + # We only need to know if the generator yield at least one elem. + print 'True' + return True + print 'False' + return False + def validate(self, productids, groupids): if not self._ordinal: raise ValidationError('A Vulnerability must have an ordinal') @@ -672,10 +724,22 @@ cwe.validate() for status in self._productstatuses: status.validate(productids) + pids = set() + for status in self._productstatuses: + for pid in status._productids: + if pid in pids: + raise ValidationError('ProductID %s mentionned in two different ProductStatuses for Vulnerability %d' % (pid, self._ordinal)) + pids.add(pid) for threat in self._threats: threat.validate(productids, groupids) for cvss in self._cvsss: cvss.validate(productids) + pids = set() + for cvss in self._cvsss: + for pid in (cvss._productids or productids): + if pid in pids: + raise ValidationError('ProductID %s mentionned in two different CVSS Score Sets for Vulnerability %d' % (pid, self._ordinal)) + pids.add(pid) for remediation in self._remediations: remediation.validate(productids, groupids) for reference in self._references: @@ -684,7 +748,6 @@ acknowledgment.validate() - class CVRFInvolvement(object): PARTIES = CVRFPublisher.TYPES STATUSES = ('Open', 'Disputed', 'In Progress', 'Completed', @@ -726,6 +789,7 @@ class CVRFProductStatus(object): TYPES = ('First Affected', 'Known Affected', 'Known Not Affected', 'First Fixed', 'Fixed', 'Recommended', 'Last Affected') + NAME = "Product Status" def __init__(self, _type): self._type = _type self._productids = [] @@ -750,6 +814,7 @@ class CVRFThreat(object): TYPES = ('Impact', 'Exploit Status', 'Target Set') + NAME = "Threat" def __init__(self, _type, description): self._type = _type self._description = description @@ -792,6 +857,7 @@ 'C': {'N':0.0, 'P':0.275, 'C':0.66}, 'I': {'N':0.0, 'P':0.275, 'C':0.66}, 'A': {'N':0.0, 'P':0.275, 'C':0.66}} + NAME = "CVSS Score Set" def __init__(self, basescore): self._basescore = basescore self._temporalscore = None @@ -844,6 +910,7 @@ class CVRFRemediation(object): TYPES = ('Workaround', 'Mitigation', 'Vendor Fix', 'None Available', 'Will Not Fix') + NAME = "Remediation" def __init__(self, _type, description): self._type = _type self._description = description @@ -972,12 +1039,39 @@ products.add(productid) return set(self.getProductForID(p) for p in products) + def isProductOrphan(self, productid): + """ Returns if a productid is mentionned nowhere in the document """ + # We first look at the ProductTree + ptree = self._producttree + for relation in ptree._relationships: + if productid == relation._productreference: + return False + if productid == relation._relatestoproductreference: + return False + groupids = [g._groupid for g in ptree._groups if productid in g._productids] + if len(groupids) > 0: + return False + # Go through all the Vulnerabilities + for vulnerability in self._vulnerabilities: + if vulnerability.isMentioningProdId(productid): + return False + for groupid in groupids: + if vulnerability.isMentioningGroupId(groupid): + return False + return True + def getNote(self, ordinal): for note in self._notes: if note._ordinal == ordinal: return note return None + def getDocId(self): + if self._tracking is not None: + return self._tracking.getId() + # Make up something ... + return self._title.lower() + def validate(self): if not self._title: raise ValidationError('Document Title cannot be empty')