Пример #1
0
def to_address(name):
    """Convert a reverse map domain name into textual address form.
    @param name: an IPv4 or IPv6 address in reverse-map form.
    @type name: dns.name.Name object
    @rtype: str
    """
    if name.is_subdomain(ipv4_reverse_domain):
        name = name.relativize(ipv4_reverse_domain)
        labels = list(name.labels)
        labels.reverse()
        text = '.'.join([x.decode('ascii') for x in labels])
        # run through inet_aton() to check syntax and make pretty.
        return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text))
    elif name.is_subdomain(ipv6_reverse_domain):
        name = name.relativize(ipv6_reverse_domain)
        labels = list(name.labels)
        labels.reverse()
        parts = []
        i = 0
        l = len(labels)
        while i < l:
            parts.append(''.join([x.decode('ascii') for x in labels[i:i + 4]]))
            i += 4
        text = ':'.join(parts)
        # run through inet_aton() to check syntax and make pretty.
        return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text))
    else:
        raise dns.exception.SyntaxError('unknown reverse-map address family')
Пример #2
0
def to_address(name):
    """Convert a reverse map domain name into textual address form.

    *name*, a ``dns.name.Name``, an IPv4 or IPv6 address in reverse-map name
    form.

    Raises ``dns.exception.SyntaxError`` if the name does not have a
    reverse-map form.

    Returns a ``text``.
    """

    if name.is_subdomain(ipv4_reverse_domain):
        name = name.relativize(ipv4_reverse_domain)
        labels = list(name.labels)
        labels.reverse()
        text = b'.'.join(labels)
        # run through inet_aton() to check syntax and make pretty.
        return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text))
    elif name.is_subdomain(ipv6_reverse_domain):
        name = name.relativize(ipv6_reverse_domain)
        labels = list(name.labels)
        labels.reverse()
        parts = []
        i = 0
        l = len(labels)
        while i < l:
            parts.append(b''.join(labels[i:i + 4]))
            i += 4
        text = b':'.join(parts)
        # run through inet_aton() to check syntax and make pretty.
        return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text))
    else:
        raise dns.exception.SyntaxError('unknown reverse-map address family')
Пример #3
0
def to_address(name):
    """Convert a reverse map domain name into textual address form.

    *name*, a ``dns.name.Name``, an IPv4 or IPv6 address in reverse-map name
    form.

    Raises ``dns.exception.SyntaxError`` if the name does not have a
    reverse-map form.

    Returns a ``text``.
    """

    if name.is_subdomain(ipv4_reverse_domain):
        name = name.relativize(ipv4_reverse_domain)
        labels = list(name.labels)
        labels.reverse()
        text = b'.'.join(labels)
        # run through inet_aton() to check syntax and make pretty.
        return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text))
    elif name.is_subdomain(ipv6_reverse_domain):
        name = name.relativize(ipv6_reverse_domain)
        labels = list(name.labels)
        labels.reverse()
        parts = []
        i = 0
        l = len(labels)
        while i < l:
            parts.append(b''.join(labels[i:i + 4]))
            i += 4
        text = b':'.join(parts)
        # run through inet_aton() to check syntax and make pretty.
        return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text))
    else:
        raise dns.exception.SyntaxError('unknown reverse-map address family')
Пример #4
0
def to_address(name):
    """Convert a reverse map domain name into textual address form.
    @param name: an IPv4 or IPv6 address in reverse-map form.
    @type name: dns.name.Name object
    @rtype: str
    """
    if name.is_subdomain(ipv4_reverse_domain):
        name = name.relativize(ipv4_reverse_domain)
        labels = list(name.labels)
        labels.reverse()
        text = '.'.join(labels)
        # run through inet_aton() to check syntax and make pretty.
        return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text))
    elif name.is_subdomain(ipv6_reverse_domain):
        name = name.relativize(ipv6_reverse_domain)
        labels = list(name.labels)
        labels.reverse()
        parts = []
        i = 0
        l = len(labels)
        while i < l:
            parts.append(''.join(labels[i:i+4]))
            i += 4
        text = ':'.join(parts)
        # run through inet_aton() to check syntax and make pretty.
        return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text))
    else:
        raise dns.exception.SyntaxError('unknown reverse-map address family')
Пример #5
0
 def zone_for_name_effect(name):
     if isinstance(name, str):
         name = dns.name.from_text(name)
     zone = dns.name.from_text('zone.com')
     if name.is_subdomain(zone):
         return zone
     raise ValueError("Bad arguments")
Пример #6
0
 def _validate_name(self, name):
     if name.is_absolute():
         if not name.is_subdomain(self.zone.origin):
             raise KeyError("name is not a subdomain of the zone origin")
         if self.zone.relativize:
             name = name.relativize(self.origin)
     return name
Пример #7
0
 def zone_for_name_effect(name):
     if isinstance(name, str):
         name = dns.name.from_text(name)
     zone = dns.name.from_text('zone.com')
     if name.is_subdomain(zone):
         return zone
     raise ValueError("Bad arguments")
Пример #8
0
 def _validate_name(self, name):
     if name.is_absolute():
         if not name.is_subdomain(self.zone.origin):
             raise KeyError("name is not a subdomain of the zone origin")
         if self.zone.relativize:
             # XXXRTH should it be an error if self.origin is still None?
             name = name.relativize(self.origin)
     return name
Пример #9
0
def _create_and_serve_zone(zone, mappings, port):
    zonefile = tempfile.NamedTemporaryFile('w', prefix='dnsviz', delete=False)
    atexit.register(os.remove, zonefile.name)
    zonefile.write('$ORIGIN %s\n@ IN SOA localhost. root.localhost. 1 1800 900 86400 600\n@ IN NS @\n@ IN A 127.0.0.1\n' % lb2s(zone.canonicalize().to_text()))
    for name, rdtype in mappings:
        if not name.is_subdomain(zone):
            continue
        zonefile.write(mappings[(name, rdtype)].to_text() + '\n')
    zonefile.close()
    _serve_zone(zone, zonefile.name, port)
Пример #10
0
def _create_and_serve_zone(zone, mappings, port):
    zonefile = tempfile.NamedTemporaryFile('w', prefix='dnsviz', delete=False)
    atexit.register(os.remove, zonefile.name)
    zonefile.write('$ORIGIN %s\n@ IN SOA localhost. root.localhost. 1 1800 900 86400 600\n@ IN NS @\n@ IN A 127.0.0.1\n' % lb2s(zone.canonicalize().to_text()))
    for name, rdtype in mappings:
        if not name.is_subdomain(zone):
            continue
        zonefile.write(mappings[(name, rdtype)].to_text() + '\n')
    zonefile.close()
    _serve_zone(zone, zonefile.name, port)
Пример #11
0
 def _validate_name(self, name):
     if isinstance(name, (str, unicode)):
         name = dns.name.from_text(name, None)
     elif not isinstance(name, dns.name.Name):
         raise KeyError("name parameter must be convertable to a DNS name")
     if name.is_absolute():
         if not name.is_subdomain(self.origin):
             raise KeyError("name parameter must be a subdomain of the zone origin")
         if self.relativize:
             name = name.relativize(self.origin)
     return name
Пример #12
0
 def _validate_name(self, name):
     if isinstance(name, (str, unicode)):
         name = dns.name.from_text(name, None)
     elif not isinstance(name, dns.name.Name):
         raise KeyError("name parameter must be convertable to a DNS name")
     if name.is_absolute():
         if not name.is_subdomain(self.origin):
             raise KeyError("name parameter must be a subdomain of the zone origin")
         if self.relativize:
             name = name.relativize(self.origin)
     return name
Пример #13
0
def _get_zone(name, zones):
    """Determine which of the zones name is in.
    
    Returns the zone name is in, or None.
    """
    
    for zone in zones:
        if name.is_subdomain(zone):
            return zone
    
    return None
Пример #14
0
def is_delegated(delegated_names, name):
    '''
    Tests a name to see if it is in a delegated zone.

    :param list delegated_names: List of non-apex dns.name.Names in zone with NS RRSets.
    :param obj name: The dns.name.Name to test.
    :return: True if name is delegated, False otherwise.
    '''
    for deleg_name in delegated_names:
        if name.is_subdomain(deleg_name):
            return True
    return False
Пример #15
0
def to_address(
    name: dns.name.Name,
    v4_origin: dns.name.Name = ipv4_reverse_domain,
    v6_origin: dns.name.Name = ipv6_reverse_domain,
) -> str:
    """Convert a reverse map domain name into textual address form.

    *name*, a ``dns.name.Name``, an IPv4 or IPv6 address in reverse-map name
    form.

    *v4_origin*, a ``dns.name.Name`` representing the top-level domain for
    IPv4 addresses, instead of the default (in-addr.arpa.)

    *v6_origin*, a ``dns.name.Name`` representing the top-level domain for
    IPv4 addresses, instead of the default (ip6.arpa.)

    Raises ``dns.exception.SyntaxError`` if the name does not have a
    reverse-map form.

    Returns a ``str``.
    """

    if name.is_subdomain(v4_origin):
        name = name.relativize(v4_origin)
        text = b".".join(reversed(name.labels))
        # run through inet_ntoa() to check syntax and make pretty.
        return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text))
    elif name.is_subdomain(v6_origin):
        name = name.relativize(v6_origin)
        labels = list(reversed(name.labels))
        parts = []
        for i in range(0, len(labels), 4):
            parts.append(b"".join(labels[i:i + 4]))
        text = b":".join(parts)
        # run through inet_ntoa() to check syntax and make pretty.
        return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text))
    else:
        raise dns.exception.SyntaxError("unknown reverse-map address family")
Пример #16
0
def _analyze((cls, name, dlv_domain, try_ipv4, try_ipv6, client_ipv4, client_ipv6, ceiling, edns_diagnostics, explicit_delegations, extra_rdtypes, explicit_only, cache, cache_level, cache_lock, th_factories)):
    if ceiling is not None and name.is_subdomain(ceiling):
        c = ceiling
    else:
        c = name
    try:
        a = cls(name, dlv_domain=dlv_domain, try_ipv4=try_ipv4, try_ipv6=try_ipv6, client_ipv4=client_ipv4, client_ipv6=client_ipv6, ceiling=c, edns_diagnostics=edns_diagnostics, explicit_delegations=explicit_delegations, extra_rdtypes=extra_rdtypes, explicit_only=explicit_only, analysis_cache=cache, cache_level=cache_level, analysis_cache_lock=cache_lock, transport_manager=tm, th_factories=th_factories)
        return a.analyze()
    # re-raise a KeyboardInterrupt, as this means we've been interrupted
    except KeyboardInterrupt:
        raise
    # report exceptions related to network connectivity
    except (NetworkConnectivityException, transport.RemoteQueryTransportError), e:
        logger.error('Error analyzing %s: %s' % (fmt.humanize_name(name), e))
Пример #17
0
def _probe(
    analyst_cls: Analyst,
    name: str,
    config,
    rdclass,
    ceiling,
    query_class_mixin,
    explicit_delegations,
    odd_ports,
    cache,
    cache_lock,
    tm,
    resolver,
):
    if ceiling is not None and name.is_subdomain(ceiling):
        c = ceiling
    else:
        c = name
    try:
        a = analyst_cls(
            name,
            rdclass=rdclass,
            dlv_domain=config.dlv_domain,
            try_ipv4=config.try_ipv4,
            try_ipv6=config.try_ipv6,
            client_ipv4=config.client_ipv4,
            client_ipv6=config.client_ipv6,
            query_class_mixin=query_class_mixin,
            ceiling=c,
            edns_diagnostics=config.edns_diagnostics,
            explicit_delegations=explicit_delegations,
            stop_at_explicit=config.stop_at_explicit,
            odd_ports=odd_ports,
            extra_rdtypes=config.rdtypes,
            explicit_only=config.explicit_only,
            analysis_cache=cache,
            cache_level=config.cache_level,
            analysis_cache_lock=cache_lock,
            transport_manager=tm,
            th_factories=config.th_factories,
            resolver=resolver,
        )
        return a.analyze()
    # report exceptions related to network connectivity
    except (NetworkConnectivityException,
            transport.RemoteQueryTransportError) as e:
        logger.error("Error analyzing %s: %s" % (humanize_name(name), e))
    except:
        logger.exception("Error analyzing %s" % humanize_name(name))
    return None
Пример #18
0
def reply_from_zone(zone, query, allnames):
    name = query.question[0].name
    rtype = query.question[0].rdtype
    rclass = query.question[0].rdclass

    if not name.is_subdomain(zone.origin):
        return gen_refused(query)

    # qname is below delegation -> referral to the delegation
    t = name
    while len(t.labels) > len(zone.origin.labels):
        r = zone.get_rrset(t, dns.rdatatype.NS)
        if r:
            return gen_referral(zone, query, r)
        t = t.parent()

    # find exact match to qname & qtype
    r = zone.get_rrset(name, rtype)
    if r:
        return gen_answer(zone, query, (r, ))

    # try CNAME
    r = zone.get_rrset(name, dns.rdatatype.CNAME)
    if r:
        return gen_answer(zone, query, (r, ))
    # try ANY
    if rtype == dns.rdatatype.ANY:
        r = zone.get_node(name)
        rrsets = []
        if r:
            rrsets = []
            for rdataset in r.rdatasets:
                rrsets.append(
                    dns.rrset.from_rdata_list(name, rdataset.ttl, rdataset))
            return gen_answer(zone, query, rrsets)

    # TODO: try DNAME, wildcard,...

    # NODATA
    # 1. rrset not found for qname
    #   (we have A record only for qname but qtype is AAAA)
    # 2. empty non-terminal

    if name in allnames:
        return gen_nxdomain_nodata(zone, query, nxdomain=False)

    # generate NXDOMAIN
    return gen_nxdomain_nodata(zone, query, nxdomain=True)
Пример #19
0
 def _validate_name(self, name):
     if isinstance(name, str):
         name = dns.name.from_text(name, None)
     elif not isinstance(name, dns.name.Name):
         raise KeyError("name parameter must be convertible to a DNS name")
     if name.is_absolute():
         if not name.is_subdomain(self.origin):
             raise KeyError(
                 "name parameter must be a subdomain of the zone origin")
         if self.relativize:
             name = name.relativize(self.origin)
     elif not self.relativize:
         # We have a relative name in a non-relative zone, so derelativize.
         if self.origin is None:
             raise KeyError('no zone origin is defined')
         name = name.derelativize(self.origin)
     return name
Пример #20
0
 def _validate_name(self, name: dns.name.Name) -> dns.name.Name:
     if name.is_absolute():
         if self.origin is None:
             # This should probably never happen as other code (e.g.
             # _rr_line) will notice the lack of an origin before us, but
             # we check just in case!
             raise KeyError("no zone origin is defined")
         if not name.is_subdomain(self.origin):
             raise KeyError("name is not a subdomain of the zone origin")
         if self.zone.relativize:
             name = name.relativize(self.origin)
     elif not self.zone.relativize:
         # We have a relative name in a non-relative zone, so derelativize.
         if self.origin is None:
             raise KeyError("no zone origin is defined")
         name = name.derelativize(self.origin)
     return name
Пример #21
0
    def add_record(self, name, rdtype, content, rdclass="IN", ttl=None):
        """
        Add a resource record to the zone.

        :param name: The record's name.
        :type name: string
        :param rdtype: The record's type, e.g. "CNAME".
        :type rdtype: string
        :param content: The record's content.
        :type content: string
        :param rdclass: The record's class.
        :type rdclass: string
        :param ttl: The record's TTL.
        :type ttl: ttl
        :return: :class:`Record <Record>` object
        :rtype: localzone.models.Record
        """
        # TODO: standardize on named params?

        # convert string parameters to dnspython objects
        name = dns.name.from_text(name, self.origin)
        rdclass = dns.rdataclass.from_text(rdclass)
        rdtype = dns.rdatatype.from_text(rdtype)

        # TODO: won't this always be the case?
        if name.is_subdomain(self.origin):
            name = name.relativize(self.origin)

        if not ttl:
            ttl = self.ttl

        # create the record data
        rdata = dns.rdata.from_text(rdclass,
                                    rdtype,
                                    content,
                                    origin=self.origin)

        # get or create the node and rdataset that will conatin the record
        node = self.find_node(name, create=True)
        rdataset = self.find_rdataset(name, rdtype, create=True)

        # add the new rdata to the set
        rdataset.add(rdata, ttl)

        return Record(self.origin, name, node, rdataset, rdata)
Пример #22
0
def _analyze((cls, name, dlv_domain, client_ipv4, client_ipv6, ceiling, edns_diagnostics, explicit_delegations, extra_rdtypes, explicit_only, cache, cache_level, cache_lock)):
    if ceiling is not None and name.is_subdomain(ceiling):
        c = ceiling
    else:
        c = name
    try:
        a = cls(name, dlv_domain=dlv_domain, client_ipv4=client_ipv4, client_ipv6=client_ipv6, ceiling=c, edns_diagnostics=edns_diagnostics, explicit_delegations=explicit_delegations, extra_rdtypes=extra_rdtypes, explicit_only=explicit_only, analysis_cache=cache, cache_level=cache_level, analysis_cache_lock=cache_lock)
        return a.analyze()
    # re-raise a KeyboardInterrupt, as this means we've been interrupted
    except KeyboardInterrupt:
        raise
    # don't report EOFError, as that is what is raised if there is a
    # KeyboardInterrupt in ParallelAnalyst
    except EOFError:
        pass
    except:
        logger.exception('Error analyzing %s' % fmt.humanize_name(name))
        return None
Пример #23
0
def _analyze(args):
    (cls, name, dlv_domain, try_ipv4, try_ipv6, client_ipv4, client_ipv6, query_class_mixin, ceiling, edns_diagnostics, \
            stop_at_explicit, extra_rdtypes, explicit_only, cache, cache_level, cache_lock, th_factories) = args
    if ceiling is not None and name.is_subdomain(ceiling):
        c = ceiling
    else:
        c = name
    try:
        a = cls(name,
                dlv_domain=dlv_domain,
                try_ipv4=try_ipv4,
                try_ipv6=try_ipv6,
                client_ipv4=client_ipv4,
                client_ipv6=client_ipv6,
                query_class_mixin=query_class_mixin,
                ceiling=c,
                edns_diagnostics=edns_diagnostics,
                explicit_delegations=explicit_delegations,
                stop_at_explicit=stop_at_explicit,
                odd_ports=odd_ports,
                extra_rdtypes=extra_rdtypes,
                explicit_only=explicit_only,
                analysis_cache=cache,
                cache_level=cache_level,
                analysis_cache_lock=cache_lock,
                transport_manager=tm,
                th_factories=th_factories,
                resolver=full_resolver)
        return a.analyze()
    # re-raise a KeyboardInterrupt, as this means we've been interrupted
    except KeyboardInterrupt:
        raise
    # report exceptions related to network connectivity
    except (NetworkConnectivityException,
            transport.RemoteQueryTransportError) as e:
        logger.error('Error analyzing %s: %s' % (fmt.humanize_name(name), e))
    # don't report EOFError, as that is what is raised if there is a
    # KeyboardInterrupt in ParallelAnalyst
    except EOFError:
        pass
    except:
        logger.exception('Error analyzing %s' % fmt.humanize_name(name))
        return None
Пример #24
0
 def _validate_name(self, name: Union[dns.name.Name, str]) -> dns.name.Name:
     if isinstance(name, str):
         name = dns.name.from_text(name, None)
     elif not isinstance(name, dns.name.Name):
         raise KeyError("name parameter must be convertible to a DNS name")
     if name.is_absolute():
         if self.origin is None:
             # This should probably never happen as other code (e.g.
             # _rr_line) will notice the lack of an origin before us, but
             # we check just in case!
             raise KeyError("no zone origin is defined")
         if not name.is_subdomain(self.origin):
             raise KeyError(
                 "name parameter must be a subdomain of the zone origin")
         if self.relativize:
             name = name.relativize(self.origin)
     elif not self.relativize:
         # We have a relative name in a non-relative zone, so derelativize.
         if self.origin is None:
             raise KeyError("no zone origin is defined")
         name = name.derelativize(self.origin)
     return name
Пример #25
0
def inside_auto_empty_zone(name):
    """True if specified absolute name is a subdomain of an automatic empty
    zone.

    DNS domain is a subdomain of itself so this function
    returns True for zone apexes, too.

    >>> inside_auto_empty_zone(DNSName('in-addr.arpa.'))
    False
    >>> inside_auto_empty_zone(DNSName('10.in-addr.arpa.'))
    True
    >>> inside_auto_empty_zone(DNSName('1.10.in-addr.arpa.'))
    True
    >>> inside_auto_empty_zone(DNSName('1.10.in-addr.arpa'))
    Traceback (most recent call last):
      ...
    AssertionError: ...
    """
    assert_absolute_dnsname(name)
    for aez in EMPTY_ZONES:
        if name.is_subdomain(aez):
            return True
    return False
Пример #26
0
def _analyze(args):
    (cls, name, dlv_domain, try_ipv4, try_ipv6, client_ipv4, client_ipv6, query_class_mixin, ceiling, edns_diagnostics, \
            stop_at_explicit, extra_rdtypes, explicit_only, cache, cache_level, cache_lock) = args
    if ceiling is not None and name.is_subdomain(ceiling):
        c = ceiling
    else:
        c = name
    try:
        a = cls(name, dlv_domain=dlv_domain, try_ipv4=try_ipv4, try_ipv6=try_ipv6, client_ipv4=client_ipv4, client_ipv6=client_ipv6, query_class_mixin=query_class_mixin, ceiling=c, edns_diagnostics=edns_diagnostics, explicit_delegations=explicit_delegations, stop_at_explicit=stop_at_explicit, odd_ports=odd_ports, extra_rdtypes=extra_rdtypes, explicit_only=explicit_only, analysis_cache=cache, cache_level=cache_level, analysis_cache_lock=cache_lock, transport_manager=tm, th_factories=th_factories, resolver=resolver)
        return a.analyze()
    # re-raise a KeyboardInterrupt, as this means we've been interrupted
    except KeyboardInterrupt:
        raise
    # report exceptions related to network connectivity
    except (NetworkConnectivityException, transport.RemoteQueryTransportError) as e:
        logger.error('Error analyzing %s: %s' % (fmt.humanize_name(name), e))
    # don't report EOFError, as that is what is raised if there is a
    # KeyboardInterrupt in ParallelAnalyst
    except EOFError:
        pass
    except:
        logger.exception('Error analyzing %s' % fmt.humanize_name(name))
        return None
Пример #27
0
def inside_auto_empty_zone(name):
    """True if specified absolute name is a subdomain of an automatic empty
    zone.

    DNS domain is a subdomain of itself so this function
    returns True for zone apexes, too.

    >>> inside_auto_empty_zone(DNSName('in-addr.arpa.'))
    False
    >>> inside_auto_empty_zone(DNSName('10.in-addr.arpa.'))
    True
    >>> inside_auto_empty_zone(DNSName('1.10.in-addr.arpa.'))
    True
    >>> inside_auto_empty_zone(DNSName('1.10.in-addr.arpa'))
    Traceback (most recent call last):
      ...
    AssertionError: ...
    """
    assert_absolute_dnsname(name)
    for aez in EMPTY_ZONES:
        if name.is_subdomain(aez):
            return True
    return False
Пример #28
0
    def _generate_line(self):
        # range lhs [ttl] [class] type rhs [ comment ]
        """Process one line containing the GENERATE statement from a DNS
        master file."""
        if self.current_origin is None:
            raise UnknownOrigin

        token = self.tok.get()
        # Range (required)
        try:
            start, stop, step = dns.grange.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except:
            raise dns.exception.SyntaxError

        # lhs (required)
        try:
            lhs = token.value
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except:
            raise dns.exception.SyntaxError

        # TTL
        try:
            ttl = dns.ttl.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.ttl.BadTTL:
            ttl = self.ttl
        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except:
            rdclass = self.zone.rdclass
        if rdclass != self.zone.rdclass:
            raise dns.exception.SyntaxError("RR class is not zone's class")
        # Type
        try:
            rdtype = dns.rdatatype.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except:
            raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
                    token.value)

        # lhs (required)
        try:
            rhs = token.value
        except:
            raise dns.exception.SyntaxError


        lmod, lsign, loffset, lwidth, lbase = self._parse_modify(lhs)
        rmod, rsign, roffset, rwidth, rbase = self._parse_modify(rhs)
        for i in range(start, stop + 1, step):
            # +1 because bind is inclusive and python is exclusive

            if lsign == '+':
                lindex = i + int(loffset)
            elif lsign == '-':
                lindex = i - int(loffset)

            if rsign == '-':
                rindex = i - int(roffset)
            elif rsign == '+':
                rindex = i + int(roffset)

            lzfindex = str(lindex).zfill(int(lwidth))
            rzfindex = str(rindex).zfill(int(rwidth))


            name = lhs.replace('$%s' % (lmod), lzfindex)
            rdata = rhs.replace('$%s' % (rmod), rzfindex)

            self.last_name = dns.name.from_text(name, self.current_origin)
            name = self.last_name
            if not name.is_subdomain(self.zone.origin):
                self._eat_line()
                return
            if self.relativize:
                name = name.relativize(self.zone.origin)

            n = self.zone.nodes.get(name)
            if n is None:
                n = self.zone.node_factory()
                self.zone.nodes[name] = n
            try:
                rd = dns.rdata.from_text(rdclass, rdtype, rdata,
                                         self.current_origin, False)
            except dns.exception.SyntaxError:
                # Catch and reraise.
                (ty, va) = sys.exc_info()[:2]
                raise va
            except:
                # All exceptions that occur in the processing of rdata
                # are treated as syntax errors.  This is not strictly
                # correct, but it is correct almost all of the time.
                # We convert them to syntax errors so that we can emit
                # helpful filename:line info.
                (ty, va) = sys.exc_info()[:2]
                raise dns.exception.SyntaxError("caught exception %s: %s" %
                        (str(ty), str(va)))

            rd.choose_relativity(self.zone.origin, self.relativize)
            covers = rd.covers()
            rds = n.find_rdataset(rdclass, rdtype, covers, True)
            rds.add(rd, ttl)
Пример #29
0
    def _rr_line(self):
        """Process one line from a DNS master file."""
        # Name
        if self.current_origin is None:
            raise UnknownOrigin
        token = self.tok.get(want_leading = True)
        if not token.is_whitespace():
            self.last_name = dns.name.from_text(token.value, self.current_origin)
        else:
            token = self.tok.get()
            if token.is_eol_or_eof():
                # treat leading WS followed by EOL/EOF as if they were EOL/EOF.
                return
            self.tok.unget(token)
        name = self.last_name
        if not name.is_subdomain(self.zone.origin):
            self._eat_line()
            return
        if self.relativize:
            name = name.relativize(self.zone.origin)
        token = self.tok.get()
        if not token.is_identifier():
            raise dns.exception.SyntaxError
        # TTL
        try:
            ttl = dns.ttl.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.ttl.BadTTL:
            ttl = self.ttl
        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except:
            rdclass = self.zone.rdclass
        if rdclass != self.zone.rdclass:
            raise dns.exception.SyntaxError("RR class is not zone's class")
        # Type
        try:
            rdtype = dns.rdatatype.from_text(token.value)
        except:
            raise dns.exception.SyntaxError("unknown rdatatype '%s'" % token.value)
        n = self.zone.nodes.get(name)
        if n is None:
            n = self.zone.node_factory()
            self.zone.nodes[name] = n
        try:
            rd = dns.rdata.from_text(rdclass, rdtype, self.tok,
                                     self.current_origin, False)
        except dns.exception.SyntaxError:
            # Catch and reraise.
            (ty, va) = sys.exc_info()[:2]
            raise va
        except:
            # All exceptions that occur in the processing of rdata
            # are treated as syntax errors.  This is not strictly
            # correct, but it is correct almost all of the time.
            # We convert them to syntax errors so that we can emit
            # helpful filename:line info.
            (ty, va) = sys.exc_info()[:2]
            raise dns.exception.SyntaxError("caught exception %s: %s" % (str(ty), str(va)))

        rd.choose_relativity(self.zone.origin, self.relativize)
        covers = rd.covers()
        rds = n.find_rdataset(rdclass, rdtype, covers, True)
        rds.add(rd, ttl)
Пример #30
0
    def resolve(self, name, response):
        assert not name.is_absolute() or name.is_subdomain(self.origin)

        _logger = logging.getLogger(__name__)
        #_logger.debug('Enter ODUPPolicyRealm.resolve(): name: %s' % (name))

        # make sure name is relative to origin
        if name.is_absolute():
            name = name.relativize(self.origin)

        if self.origin == dns.name.root:
            origin = ''
        else:
            origin = self.origin.to_text()

        # check for org/bound directives in names in ancestry
        longest_match = None
        longest_match_boundary = None
        existing_labels = 0
        for i in range(len(name) + 1):

            if i == 0:
                test_domain = dns.name.empty
                wildcard_name = None
            else:
                test_domain = dns.name.Name(name[-i:])
                wildcard_name = dns.name.from_text('*', test_domain.parent())

            test_domain_qualified = dns.name.Name(test_domain.labels + ('_odup',) + self.origin.labels)

            policy = None
            # Name exists; check for policy
            if test_domain in self._policies:
                if i > 0:
                    existing_labels += 1
                if self._policies[test_domain] is not None:
                    _logger.debug('%s/TXT: NOERROR (local): %s' % (test_domain_qualified, self._policies[test_domain]))
                    policy = self._policies[test_domain]
                    response.add_query(test_domain_qualified, dns.rcode.NOERROR, policy)
                else:
                    # It's effectively a NODATA response
                    _logger.debug('%s/TXT: NODATA (local)' % (test_domain_qualified))
                    response.add_query(test_domain_qualified, dns.rcode.NOERROR, None)
                    pass

            # Name doesn't exist; check for wildcard
            elif wildcard_name in self._policies and self._policies[wildcard_name] is not None:
                _logger.debug('%s/TXT: NOERROR (wildcard local): %s' % (test_domain_qualified, self._policies[wildcard_name]))
                existing_labels += 1
                policy = self._policies[wildcard_name]
                response.add_query(test_domain_qualified, dns.rcode.NOERROR, policy)

            # Effective NXDOMAIN:
            # An NXDOMAIN result means that no further lookups are
            # necessary, as there is no subtree
            else:
                _logger.debug('%s/TXT: NXDOMAIN (local)' % (test_domain_qualified))
                response.add_query(test_domain_qualified, dns.rcode.NXDOMAIN, None)
                break

            if policy is not None:

                org_match = ORG_RE.search(policy)
                bound_match = BOUND_RE.search(policy)

                # Update longestMatch by giving org and bound highest
                # priority and ignoring policy statements below "bound".
                if org_match is not None or bound_match is not None or \
                        (longest_match is None or BOUND_RE.search(longest_match) is None):
                    longest_match = policy
                    longest_match_boundary = i

                # If this was a organizational domain designation,
                # then don't go any further; the organization will
                # dictate policy
                if org_match is not None:
                    break

                # If this was a boundary designation, and the answer
                # was synthesized from a wildcard, no further
                # lookups must be performed
                if bound_match is not None and \
                        bound_match.group('labels') is not None and \
                        int(bound_match.group('labels')) < i + 1:
                    break

            # Effective NODATA response
            else:
                pass

        if longest_match is not None:
            # If a policy has been found, then look for +org or +bound
            # directives, which will cause org names to be returned.
            # A +org directive indicates that the organizational domain and
            # policy are (at least) one level lower than the value of
            # longestMatchBoundary.
            if ORG_RE.search(longest_match) is not None:
                org_domain = dns.name.Name(name[-(longest_match_boundary+1):]).derelativize(self.origin)
                response.set_policy(None, org_domain, None)
                return response
            # A +bound directive indicates that the organizational domain
            # and policy are (at least) one level lower than the value of
            # longestExistingBoundary.
            if BOUND_RE.search(longest_match) is not None and \
                    existing_labels + 1 <= len(name):
                org_domain = dns.name.Name(name[-(existing_labels+1):]).derelativize(self.origin)
                response.set_policy(None, org_domain, None)
                return response

            # With no +org or +bound directives present, the orgDomain and
            # policy remain as they were looked up, and are returned with
            # the policy domain
            policy_domain = dns.name.Name(name[-(longest_match_boundary+1):]).derelativize(self.origin)
            response.set_policy(policy_domain, self.origin, longest_match)
            return response
        else:
            # Otherwise, return the policy for the orgDomain
            response.set_policy(None, self.origin, None)
            return response
Пример #31
0
    def _rr_line(self):
        """Process one line from a DNS master file."""
        # Name
        if self.current_origin is None:
            raise UnknownOrigin
        token = self.tok.get(want_leading=True)
        if not token.is_whitespace():
            self.last_name = dns.name.from_text(token.value,
                                                self.current_origin)
        else:
            token = self.tok.get()
            if token.is_eol_or_eof():
                # treat leading WS followed by EOL/EOF as if they were EOL/EOF.
                return
            self.tok.unget(token)
        name = self.last_name
        if not name.is_subdomain(self.zone.origin):
            self._eat_line()
            return
        if self.relativize:
            name = name.relativize(self.zone.origin)
        token = self.tok.get()
        if not token.is_identifier():
            raise dns.exception.SyntaxError
        # TTL
        try:
            ttl = dns.ttl.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.ttl.BadTTL:
            ttl = self.ttl
        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except:
            rdclass = self.zone.rdclass
        if rdclass != self.zone.rdclass:
            raise dns.exception.SyntaxError("RR class is not zone's class")
        # Type
        try:
            rdtype = dns.rdatatype.from_text(token.value)
        except:
            raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
                                            token.value)
        n = self.zone.nodes.get(name)
        if n is None:
            n = self.zone.node_factory()
            self.zone.nodes[name] = n
        try:
            rd = dns.rdata.from_text(rdclass, rdtype, self.tok,
                                     self.current_origin, False)
        except dns.exception.SyntaxError:
            # Catch and reraise.
            (ty, va) = sys.exc_info()[:2]
            raise va
        except:
            # All exceptions that occur in the processing of rdata
            # are treated as syntax errors.  This is not strictly
            # correct, but it is correct almost all of the time.
            # We convert them to syntax errors so that we can emit
            # helpful filename:line info.
            (ty, va) = sys.exc_info()[:2]
            raise dns.exception.SyntaxError("caught exception %s: %s" %
                                            (str(ty), str(va)))

        rd.choose_relativity(self.zone.origin, self.relativize)
        covers = rd.covers()
        rds = n.find_rdataset(rdclass, rdtype, covers, True)
        rds.add(rd, ttl)
Пример #32
0
    def _generate_line(self):
        # range lhs [ttl] [class] type rhs [ comment ]
        """Process one line containing the GENERATE statement from a DNS
        master file."""
        if self.current_origin is None:
            raise UnknownOrigin

        token = self.tok.get()
        # Range (required)
        try:
            start, stop, step = dns.grange.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except:
            raise dns.exception.SyntaxError

        # lhs (required)
        try:
            lhs = token.value
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except:
            raise dns.exception.SyntaxError

        # TTL
        try:
            ttl = dns.ttl.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.ttl.BadTTL:
            ttl = self.ttl
        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except:
            rdclass = self.zone.rdclass
        if rdclass != self.zone.rdclass:
            raise dns.exception.SyntaxError("RR class is not zone's class")
        # Type
        try:
            rdtype = dns.rdatatype.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except:
            raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
                                            token.value)

        # lhs (required)
        try:
            rhs = token.value
        except:
            raise dns.exception.SyntaxError

        lmod, lsign, loffset, lwidth, lbase = self._parse_modify(lhs)
        rmod, rsign, roffset, rwidth, rbase = self._parse_modify(rhs)
        for i in range(start, stop + 1, step):
            # +1 because bind is inclusive and python is exclusive

            if lsign == u'+':
                lindex = i + int(loffset)
            elif lsign == u'-':
                lindex = i - int(loffset)

            if rsign == u'-':
                rindex = i - int(roffset)
            elif rsign == u'+':
                rindex = i + int(roffset)

            lzfindex = str(lindex).zfill(int(lwidth))
            rzfindex = str(rindex).zfill(int(rwidth))

            name = lhs.replace(u'$%s' % (lmod), lzfindex)
            rdata = rhs.replace(u'$%s' % (rmod), rzfindex)

            self.last_name = dns.name.from_text(name, self.current_origin)
            name = self.last_name
            if not name.is_subdomain(self.zone.origin):
                self._eat_line()
                return
            if self.relativize:
                name = name.relativize(self.zone.origin)

            n = self.zone.nodes.get(name)
            if n is None:
                n = self.zone.node_factory()
                self.zone.nodes[name] = n
            try:
                rd = dns.rdata.from_text(rdclass, rdtype, rdata,
                                         self.current_origin, False)
            except dns.exception.SyntaxError:
                # Catch and reraise.
                (ty, va) = sys.exc_info()[:2]
                raise va
            except:
                # All exceptions that occur in the processing of rdata
                # are treated as syntax errors.  This is not strictly
                # correct, but it is correct almost all of the time.
                # We convert them to syntax errors so that we can emit
                # helpful filename:line info.
                (ty, va) = sys.exc_info()[:2]
                raise dns.exception.SyntaxError("caught exception %s: %s" %
                                                (str(ty), str(va)))

            rd.choose_relativity(self.zone.origin, self.relativize)
            covers = rd.covers()
            rds = n.find_rdataset(rdclass, rdtype, covers, True)
            rds.add(rd, ttl)
Пример #33
0
    def _get(self, request, name_obj, timestamp, url_subdir, date_form):
        options_form, values = get_dnssec_options_form_data({})

        trusted_keys_explicit = values['tk']
        trusted_zones = values['ta']
        trusted_keys = trusted_keys_explicit + trusted_zones

        name_obj.retrieve_all()
        name_obj.populate_status(trusted_keys)

        zone_obj = name_obj.zone

        delegation_matrix = []

        def stealth_cmp(x, y):
            return cmp((y[0], x[1], x[2]), (x[0], y[1], y[2]))

        all_names_list = list(zone_obj.get_ns_names())
        if not all_names_list:
            all_names_list = list(zone_obj.get_auth_ns_ip_mapping())

        all_names_list.sort()

        if zone_obj.parent is not None and not zone_obj.get_auth_or_designated_servers(
        ).difference(zone_obj.parent.get_auth_or_designated_servers()):
            no_non_auth_parent_msg = 'All %s servers are also authoritative for %s' % (
                fmt.humanize_name(
                    zone_obj.parent_name()), fmt.humanize_name(zone_obj.name))
        else:
            no_non_auth_parent_msg = None
        #XXX need something equivalent here for lack of authoritative response for NS
        show_msg = False

        ips_from_child = zone_obj.get_servers_in_child()
        ips_from_parent = zone_obj.get_servers_in_parent()

        for name in all_names_list:
            if zone_obj.parent is not None:
                in_bailiwick = name.is_subdomain(zone_obj.parent_name())
                glue_required = name.is_subdomain(zone_obj.name)
            else:
                in_bailiwick = None
                glue_required = None
            parent_status = {
                'in_bailiwick': in_bailiwick,
                'glue_required': glue_required
            }

            row = []
            row.append(fmt.humanize_name(name))
            # (t/f in parent), (glue IPs (or error, if missing)), (real IPs)
            if zone_obj.get_ns_names_in_parent():
                glue_mapping = zone_obj.get_glue_ip_mapping()
                parent_status['in_parent'] = name in glue_mapping
                glue_ips_v4 = filter(lambda x: x.version == 4,
                                     glue_mapping.get(name, set()))
                glue_ips_v4.sort()
                glue_ips_v6 = filter(lambda x: x.version == 6,
                                     glue_mapping.get(name, set()))
                glue_ips_v6.sort()
            else:
                glue_ips_v4 = []
                glue_ips_v6 = []
                if zone_obj.delegation_status == Status.DELEGATION_STATUS_INCOMPLETE:
                    parent_status['in_parent'] = False
                else:
                    parent_status['in_parent'] = None
                    show_msg = True

            row.append({
                'parent_status': parent_status,
                'glue_ips_v4': glue_ips_v4,
                'glue_ips_v6': glue_ips_v6
            })

            # (t/f in parent), (glue IPs (or error, if missing)), (real IPs)
            names_in_child = zone_obj.get_ns_names_in_child()
            if names_in_child:
                in_child = name in zone_obj.get_ns_names_in_child()
            #XXX
            #elif zone_obj.get_servers_authoritative_for_query(zone_obj.name, dns.rdatatype.NS):
            #    in_child = None
            else:
                in_child = False

            auth_mapping = zone_obj.get_auth_ns_ip_mapping()
            auth_ips_v4 = filter(lambda x: x.version == 4,
                                 auth_mapping.get(name, set()))
            auth_ips_v4.sort()
            auth_ips_v6 = filter(lambda x: x.version == 6,
                                 auth_mapping.get(name, set()))
            auth_ips_v6.sort()

            row.append({
                'in_child': in_child,
                'auth_ips_v4': auth_ips_v4,
                'auth_ips_v6': auth_ips_v6
            })
            delegation_matrix.append(row)

        stealth_matrix = []
        stealth_rows = []
        for server in zone_obj.get_stealth_servers():
            names, ancestor_zone = zone_obj.get_ns_name_for_ip(server)
            stealth_rows.append((ancestor_zone, names, server))
        stealth_rows.sort(cmp=stealth_cmp)

        for ancestor_zone, names, server in stealth_rows:
            names = map(fmt.humanize_name, names)
            if ancestor_zone is not None:
                ancestor_zone = fmt.humanize_name(ancestor_zone)
            row = (names, ancestor_zone, server)
            stealth_matrix.append(row)

        return render_to_response('servers.html', {
            'name_obj': name_obj,
            'timestamp': timestamp,
            'url_subdir': url_subdir,
            'title': name_obj,
            'date_form': date_form,
            'zone_obj': zone_obj,
            'delegation': delegation_matrix,
            'stealth': stealth_matrix,
            'no_non_auth_parent_msg': no_non_auth_parent_msg,
            'show_msg': show_msg,
            'ips_from_parent': ips_from_parent,
            'ips_from_child': ips_from_child
        },
                                  context_instance=RequestContext(request))
Пример #34
0
    def _rr_line(self):
        """Process one line from a DNS master file."""
        # Name
        if self.current_origin is None:
            raise UnknownOrigin
        token = self.tok.get(want_leading=True)
        if not token.is_whitespace():
            self.last_name = self.tok.as_name(token, self.current_origin)
        else:
            token = self.tok.get()
            if token.is_eol_or_eof():
                # treat leading WS followed by EOL/EOF as if they were EOL/EOF.
                return
            self.tok.unget(token)
        name = self.last_name
        if not name.is_subdomain(self.zone.origin):
            self._eat_line()
            return
        if self.relativize:
            name = name.relativize(self.zone.origin)
        token = self.tok.get()
        if not token.is_identifier():
            raise dns.exception.SyntaxError

        # TTL
        ttl = None
        try:
            ttl = dns.ttl.from_text(token.value)
            self.last_ttl = ttl
            self.last_ttl_known = True
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.ttl.BadTTL:
            if self.default_ttl_known:
                ttl = self.default_ttl
            elif self.last_ttl_known:
                ttl = self.last_ttl

        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except Exception:
            rdclass = self.zone.rdclass
        if rdclass != self.zone.rdclass:
            raise dns.exception.SyntaxError("RR class is not zone's class")
        # Type
        try:
            rdtype = dns.rdatatype.from_text(token.value)
        except:
            raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
                                            token.value)
        n = self.zone.nodes.get(name)
        if n is None:
            n = self.zone.node_factory()
            self.zone.nodes[name] = n
        try:
            rd = dns.rdata.from_text(rdclass, rdtype, self.tok,
                                     self.current_origin, self.relativize,
                                     self.zone.origin)
        except dns.exception.SyntaxError:
            # Catch and reraise.
            (ty, va) = sys.exc_info()[:2]
            raise va
        except:
            # All exceptions that occur in the processing of rdata
            # are treated as syntax errors.  This is not strictly
            # correct, but it is correct almost all of the time.
            # We convert them to syntax errors so that we can emit
            # helpful filename:line info.
            (ty, va) = sys.exc_info()[:2]
            raise dns.exception.SyntaxError("caught exception {}: {}".format(
                str(ty), str(va)))

        if not self.default_ttl_known and isinstance(rd,
                                                     dns.rdtypes.ANY.SOA.SOA):
            # The pre-RFC2308 and pre-BIND9 behavior inherits the zone default
            # TTL from the SOA minttl if no $TTL statement is present before the
            # SOA is parsed.
            self.default_ttl = rd.minimum
            self.default_ttl_known = True

        # TTL check
        if ttl is None:
            if not (self.last_ttl_known or self.default_ttl_known):
                raise dns.exception.SyntaxError("Missing default TTL value")
            else:
                if self.default_ttl_known:
                    ttl = self.default_ttl
                else:
                    ttl = self.last_ttl

        covers = rd.covers()
        rds = n.find_rdataset(rdclass, rdtype, covers, True)
        rds.add(rd, ttl)
Пример #35
0
    def _generate_line(self):
        # range lhs [ttl] [class] type rhs [ comment ]
        """Process one line containing the GENERATE statement from a DNS
        zone file."""
        if self.current_origin is None:
            raise UnknownOrigin

        token = self.tok.get()
        # Range (required)
        try:
            start, stop, step = dns.grange.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except Exception:
            raise dns.exception.SyntaxError

        # lhs (required)
        try:
            lhs = token.value
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except Exception:
            raise dns.exception.SyntaxError

        # TTL
        try:
            ttl = dns.ttl.from_text(token.value)
            self.last_ttl = ttl
            self.last_ttl_known = True
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.ttl.BadTTL:
            if not (self.last_ttl_known or self.default_ttl_known):
                raise dns.exception.SyntaxError("Missing default TTL value")
            if self.default_ttl_known:
                ttl = self.default_ttl
            elif self.last_ttl_known:
                ttl = self.last_ttl
        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except Exception:
            rdclass = self.zone_rdclass
        if rdclass != self.zone_rdclass:
            raise dns.exception.SyntaxError("RR class is not zone's class")
        # Type
        try:
            rdtype = dns.rdatatype.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except Exception:
            raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
                                            token.value)

        # rhs (required)
        rhs = token.value

        # The code currently only supports base 'd', so the last value
        # in the tuple _parse_modify returns is ignored
        lmod, lsign, loffset, lwidth, _ = self._parse_modify(lhs)
        rmod, rsign, roffset, rwidth, _ = self._parse_modify(rhs)
        for i in range(start, stop + 1, step):
            # +1 because bind is inclusive and python is exclusive

            if lsign == '+':
                lindex = i + int(loffset)
            elif lsign == '-':
                lindex = i - int(loffset)

            if rsign == '-':
                rindex = i - int(roffset)
            elif rsign == '+':
                rindex = i + int(roffset)

            lzfindex = str(lindex).zfill(int(lwidth))
            rzfindex = str(rindex).zfill(int(rwidth))

            name = lhs.replace('$%s' % (lmod), lzfindex)
            rdata = rhs.replace('$%s' % (rmod), rzfindex)

            self.last_name = dns.name.from_text(name, self.current_origin,
                                                self.tok.idna_codec)
            name = self.last_name
            if not name.is_subdomain(self.zone_origin):
                self._eat_line()
                return
            if self.relativize:
                name = name.relativize(self.zone_origin)

            try:
                rd = dns.rdata.from_text(rdclass, rdtype, rdata,
                                         self.current_origin, self.relativize,
                                         self.zone_origin)
            except dns.exception.SyntaxError:
                # Catch and reraise.
                raise
            except Exception:
                # All exceptions that occur in the processing of rdata
                # are treated as syntax errors.  This is not strictly
                # correct, but it is correct almost all of the time.
                # We convert them to syntax errors so that we can emit
                # helpful filename:line info.
                (ty, va) = sys.exc_info()[:2]
                raise dns.exception.SyntaxError("caught exception %s: %s" %
                                                (str(ty), str(va)))

            self.txn.add(name, ttl, rd)
Пример #36
0
    def _rr_line(self):
        """Process one line from a DNS zone file."""
        # Name
        if self.current_origin is None:
            raise UnknownOrigin
        token = self.tok.get(want_leading=True)
        if not token.is_whitespace():
            self.last_name = self.tok.as_name(token, self.current_origin)
        else:
            token = self.tok.get()
            if token.is_eol_or_eof():
                # treat leading WS followed by EOL/EOF as if they were EOL/EOF.
                return
            self.tok.unget(token)
        name = self.last_name
        if not name.is_subdomain(self.zone_origin):
            self._eat_line()
            return
        if self.relativize:
            name = name.relativize(self.zone_origin)
        token = self.tok.get()
        if not token.is_identifier():
            raise dns.exception.SyntaxError

        # TTL
        ttl = None
        try:
            ttl = dns.ttl.from_text(token.value)
            self.last_ttl = ttl
            self.last_ttl_known = True
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.ttl.BadTTL:
            if self.default_ttl_known:
                ttl = self.default_ttl
            elif self.last_ttl_known:
                ttl = self.last_ttl

        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise
        except Exception:
            rdclass = self.zone_rdclass
        if rdclass != self.zone_rdclass:
            raise dns.exception.SyntaxError("RR class is not zone's class")
        # Type
        try:
            rdtype = dns.rdatatype.from_text(token.value)
        except Exception:
            raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
                                            token.value)
        try:
            rd = dns.rdata.from_text(rdclass, rdtype, self.tok,
                                     self.current_origin, self.relativize,
                                     self.zone_origin)
        except dns.exception.SyntaxError:
            # Catch and reraise.
            raise
        except Exception:
            # All exceptions that occur in the processing of rdata
            # are treated as syntax errors.  This is not strictly
            # correct, but it is correct almost all of the time.
            # We convert them to syntax errors so that we can emit
            # helpful filename:line info.
            (ty, va) = sys.exc_info()[:2]
            raise dns.exception.SyntaxError("caught exception {}: {}".format(
                str(ty), str(va)))

        if not self.default_ttl_known and rdtype == dns.rdatatype.SOA:
            # The pre-RFC2308 and pre-BIND9 behavior inherits the zone default
            # TTL from the SOA minttl if no $TTL statement is present before the
            # SOA is parsed.
            self.default_ttl = rd.minimum
            self.default_ttl_known = True
            if ttl is None:
                # if we didn't have a TTL on the SOA, set it!
                ttl = rd.minimum

        # TTL check.  We had to wait until now to do this as the SOA RR's
        # own TTL can be inferred from its minimum.
        if ttl is None:
            raise dns.exception.SyntaxError("Missing default TTL value")

        self.txn.add(name, ttl, rd)
Пример #37
0
 def closest_zone(self, name):
     """find closest enclosing zone object in Cache"""
     for z in reversed(sorted(self.ZoneDict.keys())):
         if name.is_subdomain(z):
             return self.get_zone(z)
     return None