Exemplo n.º 1
0
    def _CalculateAddrList(self, addr_list, addr_exclude_list, target_af,
                           direction):
        """Calculates and stores address list for target AF and direction.

    Args:
      addr_list: address list.
      addr_exclude_list: address exclude list of the term.
      target_af: target address family.
      direction: direction in which address list will be used.

    Returns:
      calculated address list.

    """
        if not addr_list:
            addr_list = [self._all_ips]
        addr_list = [addr for addr in addr_list if addr.version == target_af]
        if addr_exclude_list:
            addr_exclude_list = [
                addr_exclude for addr_exclude in addr_exclude_list
                if addr_exclude.version == target_af
            ]
            addr_list = nacaddr.ExcludeAddrs(addr_list, addr_exclude_list)
        if len(addr_list) > 1:
            set_name = self._GenerateSetName(self.term.name, direction)
            self.addr_sets[direction] = (set_name, addr_list)
            addr_list = [self._all_ips]
        return addr_list
Exemplo n.º 2
0
 def _CalculateAddrs(self, addr_list, addr_exclude_list):
   addr_list = [addr for addr in addr_list
                if addr.version == self.AF_MAP[self.af]]
   if addr_exclude_list:
     if not addr_list:
       addr_list = [self.all_ips]
     addr_list = nacaddr.ExcludeAddrs(addr_list, addr_exclude_list)
   return addr_list
Exemplo n.º 3
0
    def _CalculateAddresses(self, term_saddr, exclude_saddr, term_daddr,
                            exclude_daddr):
        """Calculate source and destination address list for a term.

    Args:
      term_saddr: source address list of the term
      exclude_saddr: source address exclude list of the term
      term_daddr: destination address list of the term
      exclude_daddr: destination address exclude list of the term

    Returns:
      tuple containing source address list, source exclude address list,
      destination address list, destination exclude address list in
      that order

    """
        # source address
        term_saddr_excluded = []
        if not term_saddr:
            term_saddr = [self._all_ips]
        if exclude_saddr:
            term_saddr_excluded.extend(
                nacaddr.ExcludeAddrs(term_saddr, exclude_saddr))

        # destination address
        term_daddr_excluded = []
        if not term_daddr:
            term_daddr = [self._all_ips]
        if exclude_daddr:
            term_daddr_excluded.extend(
                nacaddr.ExcludeAddrs(term_daddr, exclude_daddr))

        # Just to be safe, always have a result of at least 1 to avoid * by zero
        # returning incorrect results (10src*10dst=100, but 10src*0dst=0, not 10)
        bailout_count = len(exclude_saddr) + len(exclude_daddr) + (
            (len(self.term.source_address) or 1) *
            (len(self.term.destination_address) or 1))
        exclude_count = ((len(term_saddr_excluded) or 1) *
                         (len(term_daddr_excluded) or 1))

        # Use bailout jumps for excluded addresses if it results in fewer output
        # lines than nacaddr.ExcludeAddrs() method.
        if exclude_count < bailout_count:
            exclude_saddr = []
            exclude_daddr = []
            if term_saddr_excluded:
                term_saddr = term_saddr_excluded
            if term_daddr_excluded:
                term_daddr = term_daddr_excluded

        # With many sources and destinations, iptables needs to generate the
        # cartesian product of sources and destinations.  If there are no
        # exclude rules, this can instead be written as exclude [0/0 -
        # srcs], exclude [0/0 - dsts].
        v4_src_count = len([x for x in term_saddr if x.version == 4])
        v4_dst_count = len([x for x in term_daddr if x.version == 4])
        v6_src_count = len([x for x in term_saddr if x.version == 6])
        v6_dst_count = len([x for x in term_daddr if x.version == 6])
        num_pairs = v4_src_count * v4_dst_count + v6_src_count * v6_dst_count
        if num_pairs > 100:
            new_exclude_source = nacaddr.ExcludeAddrs([self._all_ips],
                                                      term_saddr)
            new_exclude_dest = nacaddr.ExcludeAddrs([self._all_ips],
                                                    term_daddr)
            # Invert the shortest list that does not already have exclude addresses
            if len(new_exclude_source) < len(
                    new_exclude_dest) and not exclude_saddr:
                if len(new_exclude_source) + len(term_daddr) < num_pairs:
                    exclude_saddr = new_exclude_source
                    term_saddr = [self._all_ips]
            elif not exclude_daddr:
                if len(new_exclude_dest) + len(term_saddr) < num_pairs:
                    exclude_daddr = new_exclude_dest
                    term_daddr = [self._all_ips]
        term_saddr = [
            x for x in term_saddr if x.version == self.AF_MAP[self.af]
        ]
        exclude_saddr = [
            x for x in exclude_saddr if x.version == self.AF_MAP[self.af]
        ]
        term_daddr = [
            x for x in term_daddr if x.version == self.AF_MAP[self.af]
        ]
        exclude_daddr = [
            x for x in exclude_daddr if x.version == self.AF_MAP[self.af]
        ]
        return (term_saddr, exclude_saddr, term_daddr, exclude_daddr)
Exemplo n.º 4
0
    def __str__(self):
        """Convert term to a rule string.

    Returns:
      A rule as a string.

    Raises:
      NsxvAclTermError: When unknown icmp-types are specified

    """
        # Verify platform specific terms. Skip whole term if platform does not
        # match.
        if self.term.platform:
            if 'nsxv' not in self.term.platform:
                return ''
        if self.term.platform_exclude:
            if 'nsxv' in self.term.platform_exclude:
                return ''

        ret_str = ['']

        # Don't render icmpv6 protocol terms under inet, or icmp under inet6
        if ((self.af == 6 and 'icmp' in self.term.protocol)
                or (self.af == 4 and 'icmpv6' in self.term.protocol)):
            logging.debug(
                self.NO_AF_LOG_PROTO.substitute(term=self.term.name,
                                                proto=self.term.protocol,
                                                af=self.filter_type))
            return ''

        # Term verbatim is not supported
        if self.term.verbatim:
            raise NsxvAclTermError(
                'Verbatim are not implemented in standard ACLs')

        # Term option is not supported
        if self.term.option:
            for opt in [
                    str(single_option) for single_option in self.term.option
            ]:
                if ((opt.find('tcp-established') == 0)
                        or (opt.find('established') == 0)):
                    return ''
                else:
                    raise NsxvAclTermError(
                        'Option are not implemented in standard ACLs')

        # check for keywords Nsxv does not support
        term_keywords = self.term.__dict__
        unsupported_keywords = []
        for key in term_keywords:
            if term_keywords[key]:
                # translated is obj attribute not keyword
                if ('translated'
                        not in key) and (key not in _NSXV_SUPPORTED_KEYWORDS):
                    unsupported_keywords.append(key)
        if unsupported_keywords:
            logging.warning(
                'WARNING: The keywords %s in Term %s are not supported '
                'in Nsxv ', unsupported_keywords, self.term.name)

        name = '%s%s%s' % (_XML_TABLE.get('nameStart'), self.term.name,
                           _XML_TABLE.get('nameEnd'))

        notes = ''
        if self.term.comment:
            for comment in self.term.comment:
                notes = '%s%s' % (notes, comment)
            notes = '%s%s%s' % (_XML_TABLE.get('noteStart'), notes,
                                _XML_TABLE.get('noteEnd'))

        # protocol
        protocol = None

        if self.term.protocol:
            protocol = list(
                map(self.PROTO_MAP.get, self.term.protocol,
                    self.term.protocol))

            # icmp-types
            icmp_types = ['']
            if self.term.icmp_type:
                icmp_types = self.NormalizeIcmpTypes(self.term.icmp_type,
                                                     self.term.protocol,
                                                     self.af)

        # for mixed filter type get both IPV4address and IPv6Address
        af_list = []
        if self.filter_type == 'mixed':
            af_list = [4, 6]
        else:
            af_list = [self.af]

        source_address = None
        destination_address = None
        source_addr = []
        destination_addr = []

        source_v4_addr = []
        source_v6_addr = []
        dest_v4_addr = []
        dest_v6_addr = []

        for af in af_list:
            # source address
            if self.term.source_address:
                source_address = self.term.GetAddressOfVersion(
                    'source_address', af)
                source_address_exclude = self.term.GetAddressOfVersion(
                    'source_address_exclude', af)
                if source_address_exclude:
                    source_address = nacaddr.ExcludeAddrs(
                        source_address, source_address_exclude)

                if source_address:
                    if af == 4:
                        source_v4_addr = source_address
                    else:
                        source_v6_addr = source_address
                source_addr = source_v4_addr + source_v6_addr

            # destination address
            if self.term.destination_address:
                destination_address = self.term.GetAddressOfVersion(
                    'destination_address', af)
                destination_address_exclude = self.term.GetAddressOfVersion(
                    'destination_address_exclude', af)
                if destination_address_exclude:
                    destination_address = nacaddr.ExcludeAddrs(
                        destination_address, destination_address_exclude)

                if destination_address:
                    if af == 4:
                        dest_v4_addr = destination_address
                    else:
                        dest_v6_addr = destination_address
                destination_addr = dest_v4_addr + dest_v6_addr

        # Check for mismatch IP for source and destination address for mixed filter
        if self.filter_type == 'mixed':
            if source_addr and destination_addr:
                if source_v4_addr and not dest_v4_addr:
                    source_addr = source_v6_addr
                elif source_v6_addr and not dest_v6_addr:
                    source_addr = source_v4_addr
                elif dest_v4_addr and not source_v4_addr:
                    destination_addr = dest_v6_addr
                elif dest_v6_addr and not source_v6_addr:
                    destination_addr = dest_v4_addr

                if not source_addr or not destination_addr:
                    logging.warning(
                        'Term %s will not be rendered as it has IPv4/IPv6 '
                        'mismatch for source/destination for mixed address '
                        'family.', self.term.name)
                    return ''

        # ports
        source_port = None
        destination_port = None
        if self.term.source_port:
            source_port = self.term.source_port
        if self.term.destination_port:
            destination_port = self.term.destination_port

        # logging
        log = 'false'
        if self.term.logging:
            log = 'true'

        sources = ''
        if source_addr:
            sources = '<sources excluded="false">'
            for saddr in source_addr:

                # inet4
                if isinstance(saddr, nacaddr.IPv4):
                    if saddr.num_addresses > 1:
                        saddr = '%s%s%s' % (
                            _XML_TABLE.get('srcIpv4Start'),
                            saddr.with_prefixlen,
                            _XML_TABLE.get('srcIpv4End'),
                        )
                    else:
                        saddr = '%s%s%s' % (_XML_TABLE.get('srcIpv4Start'),
                                            saddr.network_address,
                                            _XML_TABLE.get('srcIpv4End'))
                    sources = '%s%s' % (sources, saddr)
                # inet6
                if isinstance(saddr, nacaddr.IPv6):
                    if saddr.num_addresses > 1:
                        saddr = '%s%s%s' % (
                            _XML_TABLE.get('srcIpv6Start'),
                            saddr.with_prefixlen,
                            _XML_TABLE.get('srcIpv6End'),
                        )
                    else:
                        saddr = '%s%s%s' % (_XML_TABLE.get('srcIpv6Start'),
                                            saddr.network_address,
                                            _XML_TABLE.get('srcIpv6End'))
                    sources = '%s%s' % (sources, saddr)
            sources = '%s%s' % (sources, '</sources>')

        destinations = ''
        if destination_addr:
            destinations = '<destinations excluded="false">'
            for daddr in destination_addr:
                # inet4
                if isinstance(daddr, nacaddr.IPv4):
                    if daddr.num_addresses > 1:
                        daddr = '%s%s%s' % (
                            _XML_TABLE.get('destIpv4Start'),
                            daddr.with_prefixlen,
                            _XML_TABLE.get('destIpv4End'),
                        )
                    else:
                        daddr = '%s%s%s' % (_XML_TABLE.get('destIpv4Start'),
                                            daddr.network_address,
                                            _XML_TABLE.get('destIpv4End'))
                    destinations = '%s%s' % (destinations, daddr)
                # inet6
                if isinstance(daddr, nacaddr.IPv6):
                    if daddr.num_addresses > 1:
                        daddr = '%s%s%s' % (
                            _XML_TABLE.get('destIpv6Start'),
                            daddr.with_prefixlen,
                            _XML_TABLE.get('destIpv6End'),
                        )
                    else:
                        daddr = '%s%s%s' % (_XML_TABLE.get('destIpv6Start'),
                                            daddr.network_address,
                                            _XML_TABLE.get('destIpv6End'))
                    destinations = '%s%s' % (destinations, daddr)
            destinations = '%s%s' % (destinations, '</destinations>')

        services = []
        if protocol:
            services.append('<services>')
            for proto in protocol:
                if proto != 'any':
                    services.append(
                        self._ServiceToString(proto, source_port,
                                              destination_port, icmp_types))
            services.append('</services>')

        service = ''
        for s in services:
            service = '%s%s' % (service, s)

        # applied_to
        applied_to_list = ''
        if self.applied_to:
            applied_to_list = '<appliedToList>'
            applied_to_element = '%s%s%s' % (_XML_TABLE.get('appliedToStart'),
                                             self.applied_to,
                                             _XML_TABLE.get('appliedToEnd'))
            applied_to_list = '%s%s' % (applied_to_list, applied_to_element)
            applied_to_list = '%s%s' % (applied_to_list, '</appliedToList>')

        # action
        action = '%s%s%s' % (_XML_TABLE.get('actionStart'),
                             _ACTION_TABLE.get(str(self.term.action[0])),
                             _XML_TABLE.get('actionEnd'))

        ret_lines = []
        ret_lines.append('<rule logged="%s">%s%s%s%s%s%s%s</rule>' %
                         (log, name, action, sources, destinations, service,
                          applied_to_list, notes))

        # remove any trailing spaces and replace multiple spaces with singles
        stripped_ret_lines = [
            re.sub(r'\s+', ' ', x).rstrip() for x in ret_lines
        ]
        ret_str.extend(stripped_ret_lines)
        return ''.join(ret_str)
Exemplo n.º 5
0
    def __str__(self):
        # Verify platform specific terms. Skip whole term if platform does not
        # match.
        if self.term.platform:
            if 'ciscoasa' not in self.term.platform:
                return ''
        if self.term.platform_exclude:
            if 'ciscoasa' in self.term.platform_exclude:
                return ''

        ret_str = ['\n']

        # Don't render icmpv6 protocol terms under inet, or icmp under inet6
        if ((self.af == 6 and 'icmp' in self.term.protocol)
                or (self.af == 4 and 'icmpv6' in self.term.protocol)):
            ret_str.append('remark Term %s' % self.term.name)
            ret_str.append('remark not rendered due to protocol/AF mismatch.')
            return '\n'.join(ret_str)

        ret_str.append('access-list %s remark %s' %
                       (self.filter_name, self.term.name))
        if self.term.owner:
            self.term.comment.append('Owner: %s' % self.term.owner)
        for comment in self.term.comment:
            for line in comment.split('\n'):
                ret_str.append('access-list %s remark %s' %
                               (self.filter_name, str(line)[:100]))

        # Term verbatim output - this will skip over normal term creation
        # code by returning early.  Warnings provided in policy.py.
        if self.term.verbatim:
            for line in self.term.verbatim:
                if line[0] == 'ciscoasa':
                    ret_str.append(str(line[1]))
                return '\n'.join(ret_str)

        # protocol
        if not self.term.protocol:
            protocol = ['ip']
        else:
            # fix the protocol
            protocol = self.term.protocol

        # source address
        if self.term.source_address:
            source_address = self.term.GetAddressOfVersion(
                'source_address', self.af)
            source_address_exclude = self.term.GetAddressOfVersion(
                'source_address_exclude', self.af)
            if source_address_exclude:
                source_address = nacaddr.ExcludeAddrs(source_address,
                                                      source_address_exclude)
        else:
            # source address not set
            source_address = ['any']

        # destination address
        if self.term.destination_address:
            destination_address = self.term.GetAddressOfVersion(
                'destination_address', self.af)
            destination_address_exclude = self.term.GetAddressOfVersion(
                'destination_address_exclude', self.af)
            if destination_address_exclude:
                destination_address = nacaddr.ExcludeAddrs(
                    destination_address, destination_address_exclude)
        else:
            # destination address not set
            destination_address = ['any']

        # options
        extra_options = []
        for opt in [str(x) for x in self.term.option]:
            if opt.find('tcp-established') == 0 and 6 in protocol:
                extra_options.append('established')
            elif opt.find('established') == 0 and 6 in protocol:
                # only needed for TCP, for other protocols policy.py handles high-ports
                extra_options.append('established')
        self.options.extend(extra_options)

        # ports
        source_port = [()]
        destination_port = [()]
        if self.term.source_port:
            source_port = self.term.source_port
        if self.term.destination_port:
            destination_port = self.term.destination_port

        # logging
        if self.term.logging:
            self.options.append('log')
            if 'disable' in [x.value for x in self.term.logging]:
                self.options.append('disable')

        # icmp-types
        icmp_types = ['']
        if self.term.icmp_type:
            icmp_types = self.NormalizeIcmpTypes(self.term.icmp_type,
                                                 self.term.protocol, self.af)

        for saddr in source_address:
            for daddr in destination_address:
                for sport in source_port:
                    for dport in destination_port:
                        for proto in protocol:
                            for icmp_type in icmp_types:
                                # only output address family appropriate IP addresses
                                do_output = False
                                if self.af == 4:
                                    if (((isinstance(saddr, nacaddr.IPv4)) or
                                         (saddr == 'any')) and
                                        ((isinstance(daddr, nacaddr.IPv4)) or
                                         (daddr == 'any'))):
                                        do_output = True
                                if self.af == 6:
                                    if (((isinstance(saddr, nacaddr.IPv6)) or
                                         (saddr == 'any')) and
                                        ((isinstance(daddr, nacaddr.IPv6)) or
                                         (daddr == 'any'))):
                                        do_output = True
                                if do_output:
                                    ret_str.extend(
                                        self._TermletToStr(
                                            self.filter_name,
                                            _ACTION_TABLE.get(
                                                str(self.term.action[0])),
                                            proto, saddr, sport, daddr, dport,
                                            icmp_type, self.options))

        return '\n'.join(ret_str)
Exemplo n.º 6
0
    def __str__(self):
        # Verify platform specific terms. Skip whole term if platform does not
        # match.
        if self.term.platform:
            if self.platform not in self.term.platform:
                return ''
        if self.term.platform_exclude:
            if self.platform in self.term.platform_exclude:
                return ''

        ret_str = ['\n']

        # Don't render icmpv6 protocol terms under inet, or icmp under inet6
        if ((self.af == 6 and 'icmp' in self.term.protocol)
                or (self.af == 4 and 'icmpv6' in self.term.protocol)):
            logging.debug(
                self.NO_AF_LOG_PROTO.substitute(term=self.term.name,
                                                proto=', '.join(
                                                    self.term.protocol),
                                                af=self.text_af))
            return ''
        if self.verbose:
            if self.term_remark:
                ret_str.append(' remark ' + self.term.name)
            if self.term.owner:
                self.term.comment.append('Owner: %s' % self.term.owner)
            for comment in self.term.comment:
                for line in comment.split('\n'):
                    ret_str.append(' remark ' + str(line)[:100].rstrip())

        # Term verbatim output - this will skip over normal term creation
        # code by returning early.  Warnings provided in policy.py.
        if self.term.verbatim:
            for next_verbatim in self.term.verbatim:
                if next_verbatim[0] == self.platform:
                    ret_str.append(str(next_verbatim[1]))
                return '\n'.join(ret_str)

        # protocol
        if not self.term.protocol:
            if self.af == 6:
                protocol = ['ipv6']
            elif self.platform == 'ciscoxr':
                protocol = ['ipv4']
            else:
                protocol = ['ip']
        elif self.term.protocol == ['hopopt']:
            protocol = ['hbh']
        elif self.proto_int:
            protocol = [
                proto if proto in self.ALLOWED_PROTO_STRINGS else
                self.PROTO_MAP.get(proto) for proto in self.term.protocol
            ]
        else:
            protocol = self.term.protocol
        # Arista can not process acls with esp/ah, these must appear as integers.
        if self.platform == 'arista':
            if 'esp' in protocol:
                protocol = [x if x != 'esp' else '50' for x in protocol]
            if 'ah' in protocol:
                protocol = [x if x != 'ah' else '51' for x in protocol]

        # source address
        if self.term.source_address:
            source_address = self.term.GetAddressOfVersion(
                'source_address', self.af)
            source_address_exclude = self.term.GetAddressOfVersion(
                'source_address_exclude', self.af)
            if source_address_exclude:
                source_address = nacaddr.ExcludeAddrs(source_address,
                                                      source_address_exclude)
            if not source_address:
                logging.debug(
                    self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='source',
                                                   af=self.text_af))
                return ''
            if self.enable_dsmo:
                source_address = summarizer.Summarize(source_address)
        else:
            # source address not set
            source_address = ['any']

        # destination address
        if self.term.destination_address:
            destination_address = self.term.GetAddressOfVersion(
                'destination_address', self.af)
            destination_address_exclude = self.term.GetAddressOfVersion(
                'destination_address_exclude', self.af)
            if destination_address_exclude:
                destination_address = nacaddr.ExcludeAddrs(
                    destination_address, destination_address_exclude)
            if not destination_address:
                logging.debug(
                    self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='destination',
                                                   af=self.text_af))
                return ''
            if self.enable_dsmo:
                destination_address = summarizer.Summarize(destination_address)
        else:
            # destination address not set
            destination_address = ['any']

        # options
        opts = [str(x) for x in self.term.option]
        if ((self.PROTO_MAP['tcp'] in protocol or 'tcp' in protocol)
                and ('tcp-established' in opts or 'established' in opts)):
            if 'established' not in self.options:
                self.options.append('established')
        # Using both 'fragments' and 'is-fragment', ref Github Issue #187
        if ('ip' in protocol) and (('fragments' in opts) or
                                   ('is-fragment' in opts)):
            if 'fragments' not in self.options:
                self.options.append('fragments')
        # ACL-based Forwarding
        if (self.platform == 'ciscoxr'
            ) and not self.term.action and self.term.next_ip and ('nexthop1'
                                                                  not in opts):
            if len(self.term.next_ip) > 1:
                raise CiscoNextIpError(
                    'The following term has more than one next IP '
                    'value: %s' % self.term.name)
            if (not isinstance(self.term.next_ip[0], nacaddr.IPv4)
                    and not isinstance(self.term.next_ip[0], nacaddr.IPv6)):
                raise CiscoNextIpError('Next IP value must be an IP address. '
                                       'Invalid term: %s' % self.term.name)
            if self.term.next_ip[0].num_addresses > 1:
                raise CiscoNextIpError(
                    'The following term has a subnet instead of a '
                    'host: %s' % self.term.name)
            nexthop = self.term.next_ip[0].network_address
            nexthop_protocol = 'ipv4' if nexthop.version == 4 else 'ipv6'
            self.options.append('nexthop1 %s %s' % (nexthop_protocol, nexthop))
            action = _ACTION_TABLE.get('accept')

        if self.term.action:
            action = _ACTION_TABLE.get(str(self.term.action[0]))

        # ports
        source_port = [()]
        destination_port = [()]
        if self.term.source_port:
            source_port = self._FixConsecutivePorts(self.term.source_port)

        if self.term.destination_port:
            destination_port = self._FixConsecutivePorts(
                self.term.destination_port)

        # logging
        if self.term.logging:
            self.options.append('log')

        # dscp; unlike srx, cisco only supports single, non-except values
        if self.term.dscp_match:
            if len(self.term.dscp_match) > 1:
                raise ExtendedACLTermError(
                    'Extended ACLs cannot specify more than one dscp match value'
                )
            else:
                self.options.append('dscp %s' % ' '.join(self.term.dscp_match))

        # icmp-types
        icmp_types = ['']
        if self.term.icmp_type:
            icmp_types = self.NormalizeIcmpTypes(self.term.icmp_type,
                                                 self.term.protocol, self.af)
        icmp_codes = ['']
        if self.term.icmp_code:
            icmp_codes = self.term.icmp_code
        fixed_src_addresses = [self._GetIpString(x) for x in source_address]
        fixed_dst_addresses = [
            self._GetIpString(x) for x in destination_address
        ]
        fixed_opts = {}
        for p in protocol:
            fixed_opts[p] = self._FixOptions(p, self.options)
        for saddr in fixed_src_addresses:
            for daddr in fixed_dst_addresses:
                for sport in source_port:
                    for dport in destination_port:
                        for proto in protocol:
                            opts = fixed_opts[proto]
                            for icmp_type in icmp_types:
                                for icmp_code in icmp_codes:
                                    ret_str.extend(
                                        self._TermletToStr(
                                            action, proto, saddr,
                                            self._FormatPort(sport,
                                                             proto), daddr,
                                            self._FormatPort(dport, proto),
                                            icmp_type, icmp_code, opts))

        return '\n'.join(ret_str)
Exemplo n.º 7
0
    def __str__(self):
        # Verify platform specific terms. Skip whole term if platform does not
        # match.
        if self.term.platform:
            if self.platform not in self.term.platform:
                return ''
        if self.term.platform_exclude:
            if self.platform in self.term.platform_exclude:
                return ''

        ret_str = ['\n']

        # Don't render icmpv6 protocol terms under inet, or icmp under inet6
        if ((self.af == 6 and 'icmp' in self.term.protocol)
                or (self.af == 4 and 'icmpv6' in self.term.protocol)):
            logging.debug(
                self.NO_AF_LOG_PROTO.substitute(term=self.term.name,
                                                proto=self.term.protocol,
                                                af=self.text_af))
            return ''

        if self.term_remark:
            ret_str.append(' remark ' + self.term.name)
        if self.term.owner:
            self.term.comment.append('Owner: %s' % self.term.owner)
        for comment in self.term.comment:
            for line in comment.split('\n'):
                ret_str.append(' remark ' + str(line)[:100].rstrip())

        # Term verbatim output - this will skip over normal term creation
        # code by returning early.  Warnings provided in policy.py.
        if self.term.verbatim:
            for next_verbatim in self.term.verbatim:
                if next_verbatim.value[0] == self.platform:
                    ret_str.append(str(next_verbatim.value[1]))
                return '\n'.join(ret_str)

        # protocol
        if not self.term.protocol:
            if self.af == 6:
                protocol = ['ipv6']
            elif self.platform == 'ciscoxr':
                protocol = ['ipv4']
            else:
                protocol = ['ip']
        elif self.term.protocol == ['hopopt']:
            protocol = ['hbh']
        elif self.proto_int:
            protocol = [
                proto if proto in self.ALLOWED_PROTO_STRINGS else
                self.PROTO_MAP.get(proto) for proto in self.term.protocol
            ]
        else:
            protocol = self.term.protocol
        # source address
        if self.term.source_address:
            source_address = self.term.GetAddressOfVersion(
                'source_address', self.af)
            source_address_exclude = self.term.GetAddressOfVersion(
                'source_address_exclude', self.af)
            if source_address_exclude:
                source_address = nacaddr.ExcludeAddrs(source_address,
                                                      source_address_exclude)
            if not source_address:
                logging.debug(
                    self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='source',
                                                   af=self.text_af))
                return ''
            if self.enable_dsmo:
                source_address = summarizer.Summarize(source_address)
        else:
            # source address not set
            source_address = ['any']

        # destination address
        if self.term.destination_address:
            destination_address = self.term.GetAddressOfVersion(
                'destination_address', self.af)
            destination_address_exclude = self.term.GetAddressOfVersion(
                'destination_address_exclude', self.af)
            if destination_address_exclude:
                destination_address = nacaddr.ExcludeAddrs(
                    destination_address, destination_address_exclude)
            if not destination_address:
                logging.debug(
                    self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='destination',
                                                   af=self.text_af))
                return ''
            if self.enable_dsmo:
                destination_address = summarizer.Summarize(destination_address)
        else:
            # destination address not set
            destination_address = ['any']

        # options
        opts = [str(x) for x in self.term.option]
        if ((self.PROTO_MAP['tcp'] in protocol or 'tcp' in protocol)
                and ('tcp-established' in opts or 'established' in opts)):
            if 'established' not in self.options:
                self.options.append('established')

        # ports
        source_port = [()]
        destination_port = [()]
        if self.term.source_port:
            source_port = self._FixConsecutivePorts(self.term.source_port)

        if self.term.destination_port:
            destination_port = self._FixConsecutivePorts(
                self.term.destination_port)

        # logging
        if self.term.logging:
            self.options.append('log')

        # dscp; unlike srx, cisco only supports single, non-except values
        if self.term.dscp_match:
            if len(self.term.dscp_match) > 1:
                raise ExtendedACLTermError(
                    'Extended ACLs cannot specify more than one dscp match value'
                )
            else:
                self.options.append('dscp %s' % ' '.join(self.term.dscp_match))

        # icmp-types
        icmp_types = ['']
        if self.term.icmp_type:
            icmp_types = self.NormalizeIcmpTypes(self.term.icmp_type,
                                                 self.term.protocol, self.af)
        icmp_codes = ['']
        if self.term.icmp_code:
            icmp_codes = self.term.icmp_code
        fixed_src_addresses = [self._GetIpString(x) for x in source_address]
        fixed_dst_addresses = [
            self._GetIpString(x) for x in destination_address
        ]
        fixed_opts = {}
        for p in protocol:
            fixed_opts[p] = self._FixOptions(p, self.options)
        for saddr in fixed_src_addresses:
            for daddr in fixed_dst_addresses:
                for sport in source_port:
                    for dport in destination_port:
                        for proto in protocol:
                            opts = fixed_opts[proto]
                            for icmp_type in icmp_types:
                                for icmp_code in icmp_codes:
                                    ret_str.extend(
                                        self._TermletToStr(
                                            _ACTION_TABLE.get(
                                                str(self.term.action[0])),
                                            proto, saddr,
                                            self._FormatPort(sport,
                                                             proto), daddr,
                                            self._FormatPort(dport, proto),
                                            icmp_type, icmp_code, opts))

        return '\n'.join(ret_str)