def get_contiguous(self): """ Return the number of possible networks matching a non contiguous wildcard for source and destination Return 0 is Source and Destination has a contiguous wildcard :return: Integer (check description) """ def __number_nets(wild): # The number of matches in a wildcard is defined by the number of 1 x = 0 wildS = wild.split('.') for octect in wildS: wildB = format(int(octect), 'b').zfill(8) x += wildB.count('1') return x net_number = 0 if self.wildcard: if self.source_address != 'any' and self.source_address != '0.0.0.0/255.255.255.255': if not wild_is_contiguous(self.source_address.split('/')[1]): net_number = __number_nets( self.source_address.split('/')[1]) if self.destination_address != 'any' and self.destination_address != '0.0.0.0/255.255.255.255': if not wild_is_contiguous( self.destination_address.split('/')[1]): if net_number == 0: net_number = __number_nets( self.destination_address.split('/')[1]) else: net_number = net_number * __number_nets( self.destination_address.split('/')[1]) return net_number
def _checkNetWild(self, net, wild, net_check): """ Check if net_check is included in a network/wildcard :param net: network address :param mask: mask address :param net_check: network to find if it's included. :return: """ if '/' not in net_check: return False if net == '0.0.0.0': return True if not wild_is_contiguous(wild): net_list = split_non_contiguous(net, wild) else: net_list = [net + '/' + wild] if not wild_is_contiguous(net_check.split('/')[1]): net_check_list = split_non_contiguous( net_check.split('/')[0], net_check.split('/')[1]) else: net_check_list = [net_check] ''' Now we should have two lists without any non-contiguous IP included. Time to go through both of them checking that all networks to be "checked" are included ''' net_checked = [] for net1 in net_list: try: if net1.split('/')[1] == '0.0.0.0': # When using wildcard 0.0.0.0 is 255.255.255.255, but Netaddr use the 0.0.0.0 ask mask for ALL, so this needs to be changed net1 = net1.split('/')[0] + '/' + '255.255.255.255' net_object_ori = netaddr.IPNetwork(net1) except: return None if len(net_check_list) == 0: break net_check_temp = net_check_list[:] for net2 in net_check_temp: try: net_object_des = netaddr.IPNetwork(net2) except: return None if net2 in net_checked: continue if net_object_des in net_object_ori: net_checked.append(net2) net_check_list.remove(net2) return len(net_check_list) == 0
def has_non_contiguous(self): """ Check if there is any wildcard non contiguous in the rule :return: TRUE/FALSE """ if self.wildcard: if self.source_address == 'any': if self.destination_address == 'any': return False else: return not wild_is_contiguous(self.destination_address.split('/')[1]) elif self.destination_address == 'any': return not wild_is_contiguous(self.source_address.split('/')[1]) return not (wild_is_contiguous(self.source_address.split('/')[1]) or wild_is_contiguous(self.destination_address.split('/')[1])) return False
def split_non_contiguous_wild(self): """ It will try to split a rule with a non contiguous wildcard into several networks It's not going to split any rule in more than <NONCONT_LIMIT> networks :return: None """ end = False pos_list = -1 non_c = False if type(self.rules[0]) != str: # To avoid errors with "empty" policies while not end: pos_list += 1 if pos_list >= len(self.rules): break contig_num = self.rules[pos_list].get_contiguous() if 0 < contig_num <= NONCONT_LIMIT: # This is a limit in the number of "new rules" that can be created original_rule = self.rules[pos_list].get_rule() original_rule_number = pos_list + 1 if original_rule[1] != 'any' and original_rule[ 1] != '0.0.0.0/255.255.255.255': if not wild_is_contiguous( original_rule[1].split('/')[1]): netlistS = split_non_contiguous( original_rule[1].split('/')[0], original_rule[1].split('/')[1]) if len(netlistS) > 0: non_c = True else: # It's possible that we can't split the source (because it will create more than 128) # but still it's possible to split the destination netlistS = [original_rule[1]] else: netlistS = [original_rule[1]] else: netlistS = ['0.0.0.0/255.255.255.255'] if original_rule[2] != 'any' and original_rule[ 2] != '0.0.0.0/255.255.255.255': if not wild_is_contiguous( original_rule[2].split('/')[1]): netlistD = split_non_contiguous( original_rule[2].split('/')[0], original_rule[2].split('/')[1]) if len(netlistD) > 0: non_c = True else: netlistD = [original_rule[2]] else: netlistD = [original_rule[2]] else: netlistD = ['0.0.0.0/255.255.255.255'] # At this point we could have two different list with Source IPs and Dest IP, that together they # can't reach NONCONT_LIMIT networks. We just combine then. if non_c: source_dest_list = [] for a in netlistS: for b in netlistD: source_dest_list.append([a, b]) inew_number = original_rule_number for new_net in source_dest_list: if source_dest_list.index(new_net) == 0: self.rules[original_rule_number - 1].set_source(new_net[0]) self.rules[original_rule_number - 1].set_destination(new_net[1]) else: inew_number += 1 # The first entry we already have it newrule = FWRule() newrule.set_rule_data( sAddress=new_net[0], dAddress=new_net[1], dPort=original_rule[3], sPort=original_rule[4], protocol=original_rule[5], ACCEPT=original_rule[6], wildcard=True, name=original_rule[0], rulenumber=inew_number) if self.DEBUG: newrule.set_debug() self.rules.insert(inew_number - 1, newrule) pos_list = inew_number - 1 # Lists starts in 0! if self.get_rules_number() == pos_list or pos_list >= 50000: # 50000 seems to be a good safe value to break the while in case of any issue. I would not expect to split in more than 50k rules break self.renum_policy()