Codebase list dnsviz / fresh-snapshots/upstream
Import upstream version 0.9.3+git20210817.1.039c509 Debian Janitor 2 years ago
10 changed file(s) with 148 addition(s) and 107 deletion(s). Raw diff Collapse all Expand all
2323 The remainer of this section covers other methods of installation, including a
2424 list of [dependencies](#dependencies), installation to a
2525 [virtual environment](#installation-in-a-virtual-environment), and installation
26 on [Fedora](#fedora-rpm-build-and-install) and
27 [RHEL7](#rhel7-rpm-build-and-install).
26 on [Fedora, RHEL 8, CentOS 8,](#fedora--rhel-8--centos-8-rpm-build-and-install) and
27 [RHEL 7](#rhel-7-rpm-build-and-install).
2828
2929 Instructions for running in a Docker container are also available
3030 [later in this document](#docker-container).
9393 ```
9494
9595
96 ### Fedora RPM Build and Install
96 ### Fedora / RHEL 8 / CentOS 8 RPM Build and Install
97
98 *RHEL 8 only*: Enable CodeReady Linux Builder by following the instructions [here](https://access.redhat.com/articles/4348511).
99
100 *CentOS 8 only*: Enable PowerTools and EPEL with the following two commands:
101 ```
102 $ sudo dnf config-manager --set-enabled powertools
103 $ sudo dnf install epel-release
104 ```
105
106 The remaining instructions are for Fedora, RHEL 8, and CentOS 8.
97107
98108 Install the tools for building an RPM, and set up the rpmbuild tree.
99109 ```
114124 ```
115125 $ sudo dnf install python3-dns python3-pygraphviz python3-m2crypto
116126 ```
117 (Note that as of Fedora 33, the latest version of M2Crypto is 0.35.2. If you
127 (Note that as of Fedora 33 / RHEL 8 / CentOS 8, the latest version of M2Crypto is 0.35.2. If you
118128 would like support for DNSSEC algorithms 15 (Ed25519) and 16 (Ed448), you will
119129 need to install M2Crypto using `pip3`. For example, see [installation to a
120130 virtual environment](#installation-in-a-virtual-environment).)
126136 ```
127137
128138
129 ### RHEL7 RPM Build and Install
139 ### RHEL 7 RPM Build and Install
130140
131141 Install pygraphviz, M2Crypto, and dnspython, after installing their build dependencies.
132142 ```
16281628 required_params = []
16291629
16301630 class MissingRRSIGForAlg(ResponseError):
1631 description_template = 'The %(source)s RRset for the zone included algorithm %(algorithm)s (%(algorithm_text)s), but no RRSIG with algorithm %(algorithm)d covering the RRset was returned in the response.'
1631 description_template = 'The %(source)s RRset for the zone included algorithm %(algorithm)d (%(algorithm_text)s), but no RRSIG with algorithm %(algorithm)d covering the RRset was returned in the response.'
16321632 references = ['RFC 4035, Sec. 2.2', 'RFC 6840, Sec. 5.11']
16331633 required_params = ['algorithm']
16341634 source = None
19021902
19031903 _abstract = False
19041904 code = 'MISSING_SEP_FOR_ALG'
1905 description_template = "The %(source)s RRset for the zone included algorithm %(algorithm)s (%(algorithm_text)s), but no %(source)s RR matched a DNSKEY with algorithm %(algorithm)d that signs the zone's DNSKEY RRset."
1905 description_template = "The %(source)s RRset for the zone included algorithm %(algorithm)d (%(algorithm_text)s), but no %(source)s RR matched a DNSKEY with algorithm %(algorithm)d that signs the zone's DNSKEY RRset."
19061906 references = ['RFC 4035, Sec. 2.2', 'RFC 6840, Sec. 5.11']
19071907 required_params = ['algorithm']
19081908
15741574 rrset_info.rrset.rdtype != dns.rdatatype.DS and \
15751575 rrsig_status.dnskey is not None:
15761576 if rrset_info.rrset.rdtype == dns.rdatatype.DNSKEY:
1577 self.ksks.add(rrsig_status.dnskey)
1577 if self.ksks is not None:
1578 self.ksks.add(rrsig_status.dnskey)
15781579 else:
1579 self.zsks.add(rrsig_status.dnskey)
1580 if self.zsks is not None:
1581 self.zsks.add(rrsig_status.dnskey)
15801582
15811583 key = rrsig_status.rrset, rrsig_status.rrsig
15821584 break
16841686 self.response_errors = {}
16851687 self.response_warnings = {}
16861688
1687 if self.is_zone():
1689 if (self.name, dns.rdatatype.DNSKEY) in self.queries:
16881690 self.zsks = set()
16891691 self.ksks = set()
16901692
17131715 self._populate_invalid_response_status(query)
17141716
17151717 def _finalize_key_roles(self):
1716 if self.is_zone():
1718 if (self.name, dns.rdatatype.DNSKEY) in self.queries:
17171719 self.published_keys = set(self.get_dnskeys()).difference(self.zsks.union(self.ksks))
17181720 self.revoked_keys = set([x for x in self.get_dnskeys() if x.rdata.flags & fmt.DNSKEY_FLAGS['revoke']])
17191721
10301030 for cname in self.cname_targets:
10311031 for target in self.cname_targets[cname]:
10321032 self.cname_targets[cname][target] = self.__class__.deserialize(target, d, cache=cache)
1033 # these are optional
10331034 for signer in self.external_signers:
1034 self.external_signers[signer] = self.__class__.deserialize(signer, d, cache=cache)
1035
1036 # these two are optional
1035 if lb2s(signer.canonicalize().to_text()) in d:
1036 self.external_signers[signer] = self.__class__.deserialize(signer, d, cache=cache)
10371037 for target in self.ns_dependencies:
10381038 if lb2s(target.canonicalize().to_text()) in d:
10391039 self.ns_dependencies[target] = self.__class__.deserialize(target, d, cache=cache)
17461746 if self.dns_cookies:
17471747 self.logger.debug('Preparing DNS cookie diagnostic query %s/%s...' % (fmt.humanize_name(name_obj.name), dns.rdatatype.to_text(dns.rdatatype.SOA)))
17481748 queries[(name_obj.name, -(dns.rdatatype.SOA+104))] = self.diagnostic_query_bad_server_cookie(name_obj.name, dns.rdatatype.SOA, self.rdclass, servers, bailiwick, self.client_ipv4, self.client_ipv6, odd_ports=odd_ports, cookie_bad=COOKIE_BAD)
1749
1750 # NSEC3PARAM
1751 self.logger.debug('Preparing query %s/%s...' % (fmt.humanize_name(name_obj.name), dns.rdatatype.to_text(dns.rdatatype.NSEC3PARAM)))
1752 queries[(name_obj.name, dns.rdatatype.NSEC3PARAM)] = self.diagnostic_query(name_obj.name, dns.rdatatype.NSEC3PARAM, self.rdclass, servers, bailiwick, self.client_ipv4, self.client_ipv6, odd_ports=odd_ports, cookie_bad=COOKIE_STANDIN)
17491753
17501754 # negative queries for all zones
17511755 self._set_negative_queries(name_obj)
278278 if self.validation_status == RRSIG_STATUS_VALID:
279279 self.validation_status = RRSIG_STATUS_EXPIRED
280280 self.errors.append(Errors.ExpirationInPast(expiration=fmt.timestamp_to_datetime(self.rrsig.expiration), reference_time=fmt.timestamp_to_datetime(self.reference_ts)))
281 elif self.reference_ts + min_ttl >= self.rrsig.expiration:
281 elif self.reference_ts + min_ttl > self.rrsig.expiration:
282282 self.errors.append(Errors.TTLBeyondExpiration(expiration=fmt.timestamp_to_datetime(self.rrsig.expiration), rrsig_ttl=min_ttl, reference_time=fmt.timestamp_to_datetime(self.reference_ts)))
283283 elif self.reference_ts + CLOCK_SKEW_WARNING >= self.rrsig.expiration:
284284 self.warnings.append(Errors.ExpirationWithinClockSkew(expiration=fmt.timestamp_to_datetime(self.rrsig.expiration), reference_time=fmt.timestamp_to_datetime(self.reference_ts)))
118118 global tm
119119 if tm is not None:
120120 tm.close()
121 tm = None
121122
122123 def _init_stub_resolver():
123124 global resolver
490491 _allow_stop_at = None
491492 _handle_file_arg = None
492493
493 def __init__(self, domain, stop_at, resolver):
494 _resolvers_initialized = False
495 _stub_resolver = None
496 _full_resolver = None
497
498 def __init__(self, domain, stop_at):
494499 if not (self._allow_file is not None and \
495500 self._allow_name_only is not None and \
496501 self._allow_addr_only is not None and \
502507 raise argparse.ArgumentTypeError('The "+" may not be specified with this option')
503508
504509 self.domain = domain
505 self._resolver = resolver
506510 self._nsi = 1
507511
508512 self.delegation_mapping = {}
511515 self.filename = None
512516
513517 self.delegation_mapping[(self.domain, dns.rdatatype.NS)] = dns.rrset.RRset(self.domain, dns.rdataclass.IN, dns.rdatatype.NS)
518
519 @classmethod
520 def init_resolvers(cls):
521 if not NameServerMappingsForDomain._resolvers_initialized:
522 tm = transport.DNSQueryTransportManager()
523 try:
524 NameServerMappingsForDomain._stub_resolver = Resolver.from_file(RESOLV_CONF, StandardRecursiveQueryCD, transport_manager=tm)
525 except ResolvConfError:
526 pass
527 NameServerMappingsForDomain._full_resolver = PrivateFullResolver(transport_manager=tm)
528 NameServerMappingsForDomain._resolvers_initialized = True
529
530 @classmethod
531 def cleanup_resolvers(cls):
532 NameServerMappingsForDomain._stub_resolver = None
533 NameServerMappingsForDomain._full_resolver = None
534 NameServerMappingsForDomain._resolvers_initialized = False
514535
515536 @classmethod
516537 def _strip_port(cls, s):
539560 self._handle_name_addr_mapping(name_addr)
540561
541562 def _handle_name_no_addr(self, name, port):
563 resolver = None
564 self.init_resolvers()
565 if self._stub_resolver is not None:
566 resolver = self._stub_resolver
567 else:
568 resolver = self._full_resolver
542569 query_tuples = ((name, dns.rdatatype.A, dns.rdataclass.IN), (name, dns.rdatatype.AAAA, dns.rdataclass.IN))
543 answer_map = self._resolver.query_multiple_for_answer(*query_tuples)
570 answer_map = resolver.query_multiple_for_answer(*query_tuples)
544571 found_answer = False
545572 for (n, rdtype, rdclass) in answer_map:
546573 a = answer_map[(n, rdtype, rdclass)]
761788 _handle_file_arg = None
762789
763790 class DSForDomain:
764 def __init__(self, domain, stop_at, resolver):
791 def __init__(self, domain, stop_at):
765792 self.domain = domain
766793
767794 if stop_at and not self._allow_stop_at:
816843 class DomainListArgHelper:
817844 STOP_RE = re.compile(r'^(.*)\+$')
818845
819 def __init__(self, resolver):
820 self._resolver = resolver
821
822846 @classmethod
823847 def _strip_stop_marker(cls, s):
824848 match = cls.STOP_RE.search(s)
854878 if list_arg is not None:
855879 list_arg = list_arg.strip()
856880
857 obj = cls(domain, stop_at, self._resolver)
881 obj = cls(domain, stop_at)
858882
859883 if list_arg:
860884 obj.handle_list_arg(list_arg)
861885 return obj
862886
863887 def _handle_list_arg(self, cls, list_arg):
864 obj = cls(WILDCARD_EXPLICIT_DELEGATION, False, self._resolver)
888 obj = cls(WILDCARD_EXPLICIT_DELEGATION, False)
865889 obj.handle_list_arg(list_arg)
866890 return obj
867891
880904 class ArgHelper:
881905 BRACKETS_RE = re.compile(r'^\[(.*)\]$')
882906
883 def __init__(self, resolver, logger):
884 self._resolver = resolver
907 def __init__(self, logger):
885908 self.parser = None
886909
887910 self.odd_ports = {}
905928 self.args = None
906929 self._arg_mapping = None
907930
908 self._resolver = resolver
909931 self._logger = logger
910932 self._zones_to_serve = []
911933
912934 def build_parser(self, prog):
913935 self.parser = argparse.ArgumentParser(description='Issue diagnostic DNS queries', prog=prog)
914 helper = DomainListArgHelper(self._resolver)
936 helper = DomainListArgHelper()
915937
916938 # python3/python2 dual compatibility
917939 stdout_buffer = io.open(sys.stdout.fileno(), 'wb', closefd=False)
12361258
12371259 def populate_recursive_servers(self):
12381260 if not self.args.authoritative_analysis and not self.args.recursive_servers:
1261 try:
1262 resolver = Resolver.from_file(RESOLV_CONF, StandardRecursiveQueryCD, transport_manager=tm)
1263 except ResolvConfError:
1264 raise argparse.ArgumentTypeError('If servers are not specified with the %s option, then %s must have valid nameserver entries.\n' % \
1265 (self._arg_mapping['recursive_servers'], RESOLV_CONF))
12391266 if (WILDCARD_EXPLICIT_DELEGATION, dns.rdatatype.NS) not in self.explicit_delegations:
12401267 self.explicit_delegations[(WILDCARD_EXPLICIT_DELEGATION, dns.rdatatype.NS)] = dns.rrset.RRset(WILDCARD_EXPLICIT_DELEGATION, dns.rdataclass.IN, dns.rdatatype.NS)
1241 for i, server in enumerate(self._resolver._servers):
1268 for i, server in enumerate(resolver._servers):
12421269 if IPAddr(server).version == 6:
12431270 rdtype = dns.rdatatype.AAAA
12441271 else:
14461473 zone.serve()
14471474
14481475 def build_helper(logger, cmd, subcmd):
1449 try:
1450 resolver = Resolver.from_file(RESOLV_CONF, StandardRecursiveQueryCD, transport_manager=tm)
1451 except ResolvConfError:
1452 sys.stderr.write('File %s not found or contains no nameserver entries.\n' % RESOLV_CONF)
1453 sys.exit(1)
1454
1455 arghelper = ArgHelper(resolver, logger)
1476 arghelper = ArgHelper(logger)
14561477 arghelper.build_parser('%s %s' % (cmd, subcmd))
14571478 return arghelper
14581479
14591480 def main(argv):
1460 global tm
14611481 global th_factories
14621482 global explicit_delegations
14631483 global odd_ports
14641484
14651485 try:
1466 _init_tm()
14671486 arghelper = build_helper(logger, sys.argv[0], argv[0])
14681487 arghelper.parse_args(argv[1:])
14691488 logger.setLevel(arghelper.get_log_level())
15121531 kwargs = {}
15131532 dnsviz_meta = { 'version': DNS_RAW_VERSION, 'names': [lb2s(n.to_text()) for n in arghelper.names] }
15141533
1534 NameServerMappingsForDomain.cleanup_resolvers()
1535
1536 _init_tm()
1537
15151538 name_objs = []
15161539 if arghelper.args.input_file:
15171540 cache = {}
15321555
15331556 name_objs = a.analyze(arghelper.names)
15341557
1558 _cleanup_tm()
1559
15351560 name_objs = [x for x in name_objs if x is not None]
15361561
15371562 if not name_objs:
15521577 logger.error('Interrupted.')
15531578 sys.exit(4)
15541579
1555 # tm is global (because of possible multiprocessing), so we need to
1556 # explicitly close it here
1557 finally:
1558 _cleanup_tm()
1559
15601580 if __name__ == "__main__":
15611581 main(sys.argv)
15411541 # If this was a network error, determine if it was a binding
15421542 # error
15431543 if err == RESPONSE_ERROR_NETWORK_ERROR:
1544 if errno1 == errno.EADDRNOTAVAIL:
1545 # Address not unavailable
1546 if qh._client is not None:
1547 raise SourceAddressBindError('Unable to bind to local address %s (%s)' % (qh._client, errno.errorcode[errno1]))
1548 else:
1549 raise SourceAddressBindError('Unable to bind to local address (%s)' % (errno.errorcode[errno1]))
1544 if errno1 == errno.EADDRNOTAVAIL and qh._client is not None:
1545 raise SourceAddressBindError('Unable to bind to local address %s (%s)' % (qh._client, errno.errorcode[errno1]))
15501546 elif errno1 == errno.EADDRINUSE or \
15511547 (errno1 == errno.EACCES and qtm.src is None):
15521548 # Address/port in use (EADDRINUSE) or insufficient
15551551 raise PortBindError('Unable to bind to local port %d (%s)' % (qh.params['sport'], errno.errorcode[errno1]))
15561552 else:
15571553 raise PortBindError('Unable to bind to local port (%s)' % (errno.errorcode[errno1]))
1558 elif qtm.src is None and errno1 not in (errno.EHOSTUNREACH, errno.ENETUNREACH, errno.EAFNOSUPPORT):
1559 # If source is None it didn't bind properly. If the
1560 # errno1 value after bind() is EHOSTUNREACH or
1561 # ENETUNREACH, it is because there was no proper IPv4
1562 # or IPv6 connectivity (which is handled elsewhere).
1563 # If socket() failed and resulted in an errno value of
1564 # EAFNOSUPPORT, then likewise there is not IPv6
1565 # support. In other cases, it was something unknown, so
1554 elif qtm.src is None and errno1 not in (errno.EHOSTUNREACH, errno.ENETUNREACH, errno.EAFNOSUPPORT, errno.EADDRNOTAVAIL):
1555 # If source is None it didn't bind properly. There are several sub-cases:
1556 # 1. If the bind() failed and resulted in an errno
1557 # value of EHOSTUNREACH, it is because there was no
1558 # proper IPv4 or IPv6 connectivity; the error for
1559 # this is handled elsewhere).
1560 # 2. If socket() failed and resulted in an errno value
1561 # of EAFNOSUPPORT, then there is no IPv6 support.
1562 # 3. If connect() failed and resulted in an errno value
1563 # of EADDRNOTAVAIL, then there is no IPv6 support.
1564 # In other cases, it was something unknown, so
15661565 # raise an error.
15671566 raise BindError('Unable to bind to local address (%s)' % (errno.errorcode.get(errno1, "unknown")))
15681567
14021402 self._event_map = {}
14031403
14041404 self._close = threading.Event()
1405 t = threading.Thread(target=self._loop)
1405 # python3/python2 dual compatibility
1406 try:
1407 # python 3
1408 t = threading.Thread(target=self._loop, daemon=True)
1409 except TypeError:
1410 # python 2
1411 t = threading.Thread(target=self._loop)
1412 t.daemon = True
14061413 t.start()
14071414
14081415 def close(self):
12951295 for signed_keys, rrset_info in name_obj.get_dnskey_sets():
12961296 for rrsig in name_obj.rrsig_status[rrset_info]:
12971297 signer_obj = name_obj.get_name(rrsig.signer)
1298 if rrsig.signer != name_obj.name and not is_dlv:
1299 self.graph_zone_auth(signer_obj, False)
1298 if signer_obj is not None:
1299 # if we have the analysis corresponding to the signer, then
1300 # graph it too, if it was different from what we were
1301 # expecting
1302 if rrsig.signer != name_obj.name and not is_dlv:
1303 self.graph_zone_auth(signer_obj, False)
13001304 for dnskey in name_obj.rrsig_status[rrset_info][rrsig]:
13011305 rrsig_status = name_obj.rrsig_status[rrset_info][rrsig][dnskey]
13021306 if dnskey is None:
1111 import dns.name, dns.rdatatype, dns.rrset, dns.zone
1212
1313 from dnsviz.commands.probe import ZoneFileToServe, ArgHelper, DomainListArgHelper, StandardRecursiveQueryCD, WILDCARD_EXPLICIT_DELEGATION, AnalysisInputError, CustomQueryMixin
14 from dnsviz.ipaddr import IPAddr
1415 from dnsviz import transport
15 from dnsviz.resolver import Resolver
16 from dnsviz.ipaddr import IPAddr
1716
1817 DATA_DIR = os.path.dirname(__file__)
1918 EXAMPLE_COM_ZONE = os.path.join(DATA_DIR, 'zone', 'example.com.zone')
2221
2322 class DNSVizProbeOptionsTestCase(unittest.TestCase):
2423 def setUp(self):
25 self.tm = transport.DNSQueryTransportManager()
26 self.resolver = Resolver.from_file('/etc/resolv.conf', StandardRecursiveQueryCD, transport_manager=self.tm)
27 self.helper = DomainListArgHelper(self.resolver)
24 self.helper = DomainListArgHelper()
2825 self.logger = logging.getLogger()
2926 for handler in self.logger.handlers:
3027 self.logger.removeHandler(handler)
4037
4138 def tearDown(self):
4239 CustomQueryMixin.edns_options = self.custom_query_mixin_edns_options_orig[:]
43 if self.tm is not None:
44 self.tm.close()
4540
4641 def test_authoritative_option(self):
4742 arg1 = 'example.com+:ns1.example.com=192.0.2.1:1234,ns1.example.com=[2001:db8::1],' + \
598593
599594 ZoneFileToServe._next_free_port = self.first_port
600595
601 arghelper1 = ArgHelper(self.resolver, self.logger)
596 arghelper1 = ArgHelper(self.logger)
602597 arghelper1.build_parser('probe')
603598 arghelper1.parse_args(args1)
604599 arghelper1.aggregate_delegation_info()
611606
612607 ZoneFileToServe._next_free_port = self.first_port
613608
614 arghelper2 = ArgHelper(self.resolver, self.logger)
609 arghelper2 = ArgHelper(self.logger)
615610 arghelper2.build_parser('probe')
616611 arghelper2.parse_args(args2)
617612 arghelper2.aggregate_delegation_info()
624619
625620 ZoneFileToServe._next_free_port = self.first_port
626621
627 arghelper3 = ArgHelper(self.resolver, self.logger)
622 arghelper3 = ArgHelper(self.logger)
628623 arghelper3.build_parser('probe')
629624 arghelper3.parse_args(args3)
630625 arghelper3.aggregate_delegation_info()
633628
634629 ZoneFileToServe._next_free_port = self.first_port
635630
636 arghelper4 = ArgHelper(self.resolver, self.logger)
631 arghelper4 = ArgHelper(self.logger)
637632 arghelper4.build_parser('probe')
638633 arghelper4.parse_args(args4)
639634 arghelper4.aggregate_delegation_info()
674669
675670 ZoneFileToServe._next_free_port = self.first_port
676671
677 arghelper1 = ArgHelper(self.resolver, self.logger)
672 arghelper1 = ArgHelper(self.logger)
678673 arghelper1.build_parser('probe')
679674 arghelper1.parse_args(args1)
680675 arghelper1.aggregate_delegation_info()
685680 args1 = ['-A', '-N', 'example.com:ns1.example.com=192.0.2.1,ns1.example.com=[2001:db8::1]',
686681 '-x', 'com:ns1.foo.com=192.0.2.3']
687682
688 arghelper1 = ArgHelper(self.resolver, self.logger)
683 arghelper1 = ArgHelper(self.logger)
689684 arghelper1.build_parser('probe')
690685 arghelper1.parse_args(args1)
691686
717712
718713 odd_ports1 = {}
719714
720 arghelper1 = ArgHelper(self.resolver, self.logger)
715 arghelper1 = ArgHelper(self.logger)
721716 arghelper1.build_parser('probe')
722717 arghelper1.parse_args(args1)
723718 arghelper1.aggregate_delegation_info()
728723
729724 # Names, input file, or names file required
730725 args = []
731 arghelper = ArgHelper(self.resolver, self.logger)
726 arghelper = ArgHelper(self.logger)
732727 arghelper.build_parser('probe')
733728 arghelper.parse_args(args)
734729 with self.assertRaises(argparse.ArgumentTypeError):
736731
737732 # Names file and command-line domain names are mutually exclusive
738733 args = ['-f', '/dev/null', 'example.com']
739 arghelper = ArgHelper(self.resolver, self.logger)
734 arghelper = ArgHelper(self.logger)
740735 arghelper.build_parser('probe')
741736 arghelper.parse_args(args)
742737 with self.assertRaises(argparse.ArgumentTypeError):
745740
746741 # Authoritative analysis and recursive servers
747742 args = ['-A', '-s', '192.0.2.1', 'example.com']
748 arghelper = ArgHelper(self.resolver, self.logger)
743 arghelper = ArgHelper(self.logger)
749744 arghelper.build_parser('probe')
750745 arghelper.parse_args(args)
751746 with self.assertRaises(argparse.ArgumentTypeError):
753748
754749 # Authoritative servers with recursive analysis
755750 args = ['-x', 'example.com:ns1.example.com=192.0.2.1', 'example.com']
756 arghelper = ArgHelper(self.resolver, self.logger)
751 arghelper = ArgHelper(self.logger)
757752 arghelper.build_parser('probe')
758753 arghelper.parse_args(args)
759754 with self.assertRaises(argparse.ArgumentTypeError):
761756
762757 # Delegation information with recursive analysis
763758 args = ['-N', 'example.com:ns1.example.com=192.0.2.1', 'example.com']
764 arghelper = ArgHelper(self.resolver, self.logger)
759 arghelper = ArgHelper(self.logger)
765760 arghelper.build_parser('probe')
766761 arghelper.parse_args(args)
767762 with self.assertRaises(argparse.ArgumentTypeError):
769764
770765 # Delegation information with recursive analysis
771766 args = [ '-D', 'example.com:34983 10 1 EC358CFAAEC12266EF5ACFC1FEAF2CAFF083C418', 'example.com']
772 arghelper = ArgHelper(self.resolver, self.logger)
767 arghelper = ArgHelper(self.logger)
773768 arghelper.build_parser('probe')
774769 arghelper.parse_args(args)
775770 with self.assertRaises(argparse.ArgumentTypeError):
777772
778773 def test_ceiling(self):
779774 args = ['-a', 'com', 'example.com']
780 arghelper = ArgHelper(self.resolver, self.logger)
775 arghelper = ArgHelper(self.logger)
781776 arghelper.build_parser('probe')
782777 arghelper.parse_args(args)
783778 arghelper.set_kwargs()
784779 self.assertEqual(arghelper.ceiling, dns.name.from_text('com'))
785780
786781 args = ['example.com']
787 arghelper = ArgHelper(self.resolver, self.logger)
782 arghelper = ArgHelper(self.logger)
788783 arghelper.build_parser('probe')
789784 arghelper.parse_args(args)
790785 arghelper.set_kwargs()
791786 self.assertEqual(arghelper.ceiling, dns.name.root)
792787
793788 args = ['-A', 'example.com']
794 arghelper = ArgHelper(self.resolver, self.logger)
789 arghelper = ArgHelper(self.logger)
795790 arghelper.build_parser('probe')
796791 arghelper.parse_args(args)
797792 arghelper.set_kwargs()
799794
800795 def test_ip4_ipv6(self):
801796 args = []
802 arghelper = ArgHelper(self.resolver, self.logger)
797 arghelper = ArgHelper(self.logger)
803798 arghelper.build_parser('probe')
804799 arghelper.parse_args(args)
805800 arghelper.set_kwargs()
807802 self.assertEqual(arghelper.try_ipv6, True)
808803
809804 args = ['-4', '-6']
810 arghelper = ArgHelper(self.resolver, self.logger)
805 arghelper = ArgHelper(self.logger)
811806 arghelper.build_parser('probe')
812807 arghelper.parse_args(args)
813808 arghelper.set_kwargs()
815810 self.assertEqual(arghelper.try_ipv6, True)
816811
817812 args = ['-4']
818 arghelper = ArgHelper(self.resolver, self.logger)
813 arghelper = ArgHelper(self.logger)
819814 arghelper.build_parser('probe')
820815 arghelper.parse_args(args)
821816 arghelper.set_kwargs()
823818 self.assertEqual(arghelper.try_ipv6, False)
824819
825820 args = ['-6']
826 arghelper = ArgHelper(self.resolver, self.logger)
821 arghelper = ArgHelper(self.logger)
827822 arghelper.build_parser('probe')
828823 arghelper.parse_args(args)
829824 arghelper.set_kwargs()
832827
833828 def test_client_ip(self):
834829 args = []
835 arghelper = ArgHelper(self.resolver, self.logger)
830 arghelper = ArgHelper(self.logger)
836831 arghelper.build_parser('probe')
837832 arghelper.parse_args(args)
838833 arghelper.set_kwargs()
842837 args = ['-b', '127.0.0.1']
843838 if self.use_ipv6:
844839 args.extend(['-b', '::1'])
845 arghelper = ArgHelper(self.resolver, self.logger)
840 arghelper = ArgHelper(self.logger)
846841 arghelper.build_parser('probe')
847842 arghelper.parse_args(args)
848843 arghelper.set_kwargs()
852847
853848 def test_th_factories(self):
854849 args = ['example.com']
855 arghelper = ArgHelper(self.resolver, self.logger)
850 arghelper = ArgHelper(self.logger)
856851 arghelper.build_parser('probe')
857852 arghelper.parse_args(args)
858853 arghelper.set_kwargs()
859854 self.assertIsNone(arghelper.th_factories)
860855
861856 args = ['-u', 'http://example.com/', 'example.com']
862 arghelper = ArgHelper(self.resolver, self.logger)
857 arghelper = ArgHelper(self.logger)
863858 arghelper.build_parser('probe')
864859 arghelper.parse_args(args)
865860 arghelper.set_kwargs()
866861 self.assertIsInstance(arghelper.th_factories[0], transport.DNSQueryTransportHandlerHTTPFactory)
867862
868863 args = ['-u', 'ws:///dev/null', 'example.com']
869 arghelper = ArgHelper(self.resolver, self.logger)
864 arghelper = ArgHelper(self.logger)
870865 arghelper.build_parser('probe')
871866 arghelper.parse_args(args)
872867 arghelper.set_kwargs()
873868 self.assertIsInstance(arghelper.th_factories[0], transport.DNSQueryTransportHandlerWebSocketServerFactory)
874869
875870 args = ['-u', 'ssh://example.com/', 'example.com']
876 arghelper = ArgHelper(self.resolver, self.logger)
871 arghelper = ArgHelper(self.logger)
877872 arghelper.build_parser('probe')
878873 arghelper.parse_args(args)
879874 arghelper.set_kwargs()
884879
885880 # None
886881 args = ['-c', '', 'example.com']
887 arghelper = ArgHelper(self.resolver, self.logger)
882 arghelper = ArgHelper(self.logger)
888883 arghelper.build_parser('probe')
889884 arghelper.parse_args(args)
890885 arghelper.set_kwargs()
894889
895890 # Only DNS cookie
896891 args = ['example.com']
897 arghelper = ArgHelper(self.resolver, self.logger)
892 arghelper = ArgHelper(self.logger)
898893 arghelper.build_parser('probe')
899894 arghelper.parse_args(args)
900895 arghelper.set_kwargs()
904899
905900 # All EDNS options
906901 args = ['-n', '-e', '192.0.2.0/24', 'example.com']
907 arghelper = ArgHelper(self.resolver, self.logger)
902 arghelper = ArgHelper(self.logger)
908903 arghelper.build_parser('probe')
909904 arghelper.parse_args(args)
910905 arghelper.set_kwargs()
931926
932927 try:
933928 args = ['-r', example_auth_out.name]
934 arghelper = ArgHelper(self.resolver, self.logger)
929 arghelper = ArgHelper(self.logger)
935930 arghelper.build_parser('probe')
936931 arghelper.parse_args(args)
937932 arghelper.ingest_input()
938933
939934 # Bad json
940935 args = ['-r', example_bad_json.name]
941 arghelper = ArgHelper(self.resolver, self.logger)
936 arghelper = ArgHelper(self.logger)
942937 arghelper.build_parser('probe')
943938 arghelper.parse_args(args)
944939 with self.assertRaises(AnalysisInputError):
946941
947942 # No version
948943 args = ['-r', example_no_version.name]
949 arghelper = ArgHelper(self.resolver, self.logger)
944 arghelper = ArgHelper(self.logger)
950945 arghelper.build_parser('probe')
951946 arghelper.parse_args(args)
952947 with self.assertRaises(AnalysisInputError):
954949
955950 # Invalid version
956951 args = ['-r', example_invalid_version_1.name]
957 arghelper = ArgHelper(self.resolver, self.logger)
952 arghelper = ArgHelper(self.logger)
958953 arghelper.build_parser('probe')
959954 arghelper.parse_args(args)
960955 with self.assertRaises(AnalysisInputError):
962957
963958 # Invalid version
964959 args = ['-r', example_invalid_version_2.name]
965 arghelper = ArgHelper(self.resolver, self.logger)
960 arghelper = ArgHelper(self.logger)
966961 arghelper.build_parser('probe')
967962 arghelper.parse_args(args)
968963 with self.assertRaises(AnalysisInputError):
975970
976971 def test_ingest_names(self):
977972 args = ['example.com', 'example.net']
978 arghelper = ArgHelper(self.resolver, self.logger)
973 arghelper = ArgHelper(self.logger)
979974 arghelper.build_parser('probe')
980975 arghelper.parse_args(args)
981976 arghelper.ingest_names()
984979 unicode_name = 'ใƒ†ใ‚นใƒˆ'
985980
986981 args = [unicode_name]
987 arghelper = ArgHelper(self.resolver, self.logger)
982 arghelper = ArgHelper(self.logger)
988983 arghelper.build_parser('probe')
989984 arghelper.parse_args(args)
990985 arghelper.ingest_names()
10051000
10061001 try:
10071002 args = ['-f', names_file.name]
1008 arghelper = ArgHelper(self.resolver, self.logger)
1003 arghelper = ArgHelper(self.logger)
10091004 arghelper.build_parser('probe')
10101005 arghelper.parse_args(args)
10111006 arghelper.ingest_names()
10121007 self.assertEqual(list(arghelper.names), [dns.name.from_text('example.com'), dns.name.from_text('example.net')])
10131008
10141009 args = ['-f', names_file_unicode.name]
1015 arghelper = ArgHelper(self.resolver, self.logger)
1010 arghelper = ArgHelper(self.logger)
10161011 arghelper.build_parser('probe')
10171012 arghelper.parse_args(args)
10181013 arghelper.ingest_names()
10191014 self.assertEqual(list(arghelper.names), [dns.name.from_text('xn--zckzah.')])
10201015
10211016 args = ['-r', example_names_only.name]
1022 arghelper = ArgHelper(self.resolver, self.logger)
1017 arghelper = ArgHelper(self.logger)
10231018 arghelper.build_parser('probe')
10241019 arghelper.parse_args(args)
10251020 arghelper.ingest_input()
10271022 self.assertEqual(list(arghelper.names), [dns.name.from_text('example.com'), dns.name.from_text('example.net'), dns.name.from_text('example.org')])
10281023
10291024 args = ['-r', example_names_only.name, 'example.com']
1030 arghelper = ArgHelper(self.resolver, self.logger)
1025 arghelper = ArgHelper(self.logger)
10311026 arghelper.build_parser('probe')
10321027 arghelper.parse_args(args)
10331028 arghelper.ingest_input()