コード例 #1
0
ファイル: ipset.py プロジェクト: yijxiang/capirca
    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
コード例 #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
コード例 #3
0
ファイル: ciscoasa.py プロジェクト: rarcotvmw/capirca
  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 next in self.term.verbatim:
        if next.value[0] == 'ciscoasa':
          ret_str.append(str(next.value[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 (((type(saddr) is nacaddr.IPv4) or (saddr == 'any')) and
                      ((type(daddr) is nacaddr.IPv4) or (daddr == 'any'))):
                    do_output = True
                if self.af == 6:
                  if (((type(saddr) is nacaddr.IPv6) or (saddr == 'any')) and
                      ((type(daddr) is 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)
コード例 #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:
            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.warn(
                '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 = 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 = []

        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 not source_address:
                    logging.warn(
                        self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                       direction='source',
                                                       af=self.filter_type))
                    return ''
                if not source_addr:
                    source_addr.extend(source_address)
                else:
                    source_addr = source_address

            # 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 not destination_address:
                    logging.warn(
                        self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                       direction='destination',
                                                       af=self.filter_type))
                    return ''
                destination_addr.extend(destination_address)

        # 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 type(saddr) is nacaddr.IPv4:
                    if saddr.numhosts > 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.ip,
                                            _XML_TABLE.get('srcIpv4End'))
                    sources = '%s%s' % (sources, saddr)
                # inet6
                if type(saddr) is nacaddr.IPv6:
                    if saddr.numhosts > 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.ip,
                                            _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 type(daddr) is nacaddr.IPv4:
                    if daddr.numhosts > 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.ip,
                                            _XML_TABLE.get('destIpv4End'))
                    destinations = '%s%s' % (destinations, daddr)
                # inet6
                if type(daddr) is nacaddr.IPv6:
                    if daddr.numhosts > 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.ip,
                                            _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)

        # 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 </rule>' %
            (log, name, action, sources, destinations, service, 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 '\n'.join(ret_str)
コード例 #5
0
ファイル: iptables.py プロジェクト: yijxiang/capirca
  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)
コード例 #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=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)

        fixed_src_addresses = [self._GetIpString(x) for x in source_address]
        fixed_dst_addresses = [
            self._GetIpString(x) for x in destination_address
        ]
        fixed_src_ports = [self._FormatPort(x) for x in source_port]
        fixed_dst_ports = [self._FormatPort(x) for x in destination_port]
        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 fixed_src_ports:
                    for dport in fixed_dst_ports:
                        for proto in protocol:
                            opts = fixed_opts[proto]
                            for icmp_type in icmp_types:
                                ret_str.extend(
                                    self._TermletToStr(
                                        _ACTION_TABLE.get(
                                            str(self.term.action[0])), proto,
                                        saddr, sport, daddr, dport, icmp_type,
                                        opts))

        return '\n'.join(ret_str)