1#! /usr/bin/env python 2# -*- coding: utf-8 -*- 3 4""" 5This file is part of cpe package. 6 7This module contains the common characteristics of 8any name matching algorithm, associated with a version of Common Platform 9Enumeration (CPE) specification. 10 11Copyright (C) 2013 Alejandro Galindo García, Roberto Abdelkader Martínez Pérez 12 13This program is free software: you can redistribute it and/or modify 14it under the terms of the GNU Lesser General Public License as published by 15the Free Software Foundation, either version 3 of the License, or 16(at your option) any later version. 17 18This program is distributed in the hope that it will be useful, 19but WITHOUT ANY WARRANTY; without even the implied warranty of 20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21GNU Lesser General Public License for more details. 22 23You should have received a copy of the GNU Lesser General Public License 24along with this program. If not, see <http://www.gnu.org/licenses/>. 25 26For any problems using the cpe package, or general questions and 27feedback about it, please contact: 28 29- Alejandro Galindo García: galindo.garcia.alejandro@gmail.com 30- Roberto Abdelkader Martínez Pérez: robertomartinezp@gmail.com 31""" 32 33from .cpe import CPE 34from .comp.cpecomp import CPEComponent 35 36 37class CPESet(object): 38 """ 39 Represents a set of CPE Names. 40 41 This class allows: 42 43 - create a set of CPE Names. 44 - match a CPE Name against a set of CPE Names. 45 """ 46 47 #################### 48 # OBJECT METHODS # 49 #################### 50 51 def __getitem__(self, i): 52 """ 53 Returns the i'th CPE Name of set. 54 55 :param int i: CPE Name index to find 56 :returns: CPE Name found 57 :rtype: CPE 58 :exception: IndexError - list index out of range 59 """ 60 61 return self.K[i] 62 63 def __init__(self): 64 """ 65 Creates an empty set of CPE Names. 66 67 :returns: None 68 """ 69 self.K = [] 70 71 def __len__(self): 72 """ 73 Returns the count of CPE Names of set. 74 75 :returns: count of components of CPE Name 76 :rtype: int 77 78 TEST: empty set 79 80 >>> from .cpeset1_1 import CPESet1_1 81 >>> s = CPESet1_1() 82 >>> len(s) 83 0 84 """ 85 86 return len(self.K) 87 88 def __str__(self): 89 """ 90 Returns a human-readable representation of CPE set. 91 92 :returns: Representation of CPE set as string 93 :rtype: string 94 """ 95 96 setlen = self.__len__() 97 98 str = [] 99 str.append("CPE Set version {0} contains {1} elements".format( 100 self.VERSION, setlen)) 101 if setlen > 0: 102 str.append(":") 103 104 for i in range(0, setlen): 105 str.append(" {0}".format(self.K[i].__str__())) 106 107 return "\n".join(str) 108 109 def append(self, cpe): 110 """ 111 Adds a CPE Name to the set if not already. 112 113 :param CPE cpe: CPE Name to store in set 114 :returns: None 115 :exception: NotImplementedError - Method not implemented 116 """ 117 118 errmsg = "Method not implemented. Use the method of some child class" 119 raise NotImplementedError(errmsg) 120 121 def name_match(self, cpe): 122 """ 123 Accepts a set of known instances of CPE Names and a candidate CPE Name, 124 and returns 'True' if the candidate can be shown to be 125 an instance based on the content of the known instances. 126 Otherwise, it returns 'False'. 127 128 :param CPESet self: A set of m known CPE Names K = {K1, K2, …, Km}. 129 :param CPE cpe: A candidate CPE Name X. 130 :returns: True if X matches K, otherwise False. 131 :rtype: boolean 132 """ 133 134 # An empty set not matching with any CPE 135 if len(self) == 0: 136 return False 137 138 # If input CPE Name string is in set of CPE Name strings 139 # not do searching more because there is a matching 140 for k in self.K: 141 if (k.cpe_str == cpe.cpe_str): 142 return True 143 144 # If "cpe" is an empty CPE Name any system matches 145 if len(cpe) == 0: 146 return True 147 148 # There are not a CPE Name string in set equal to 149 # input CPE Name string 150 match = False 151 152 for p in CPE.CPE_PART_KEYS: 153 elems_cpe = cpe.get(p) 154 for ec in elems_cpe: 155 # Search of element of part of input CPE 156 157 # Each element ec of input cpe[p] is compared with 158 # each element ek of k[p] in set K 159 160 for k in self.K: 161 if (len(k) >= len(cpe)): 162 elems_k = k.get(p) 163 164 for ek in elems_k: 165 # Matching 166 167 # Each component in element ec is compared with 168 # each component in element ek 169 for c in range(0, len(cpe)): 170 key = CPEComponent.ordered_comp_parts[c] 171 comp_cpe = ec.get(key) 172 comp_k = ek.get(key) 173 match = comp_k in comp_cpe 174 175 if not match: 176 # Search compoment in another element ek[p] 177 break 178 179 # Component analyzed 180 181 if match: 182 # Element matched 183 break 184 if match: 185 break 186 # Next element in part in "cpe" 187 188 if not match: 189 # cpe part not match with parts in set 190 return False 191 192 # Next part in input CPE Name 193 194 # All parts in input CPE Name matched 195 return True 196