Commit e66b57cf authored by Robert Edmonds's avatar Robert Edmonds

Import Upstream version 0.6.6

parent 1230534d
......@@ -4,6 +4,8 @@ rights in this software.
Copyright 2014-2016 VeriSign, Inc.
Copyright 2016-2017 Casey Deccio.
DNSViz is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
......
include COPYRIGHT LICENSE
include dnsviz/config.py.in
include doc/COPYRIGHT
include doc/Makefile
include doc/src/*dot
include doc/src/*svg
recursive-include contrib *
recursive-exclude external *
# The following are for versions of setuptools that don't seem to pull in the
# files that are listed in setup.py
include README.md
include doc/images/warning.png doc/images/error.png doc/images/logo*png
include doc/dnsviz-graph.html
recursive-include doc/man *
recursive-include share *
Metadata-Version: 1.1
Name: dnsviz
Version: 0.6.4
Version: 0.6.6
Summary: DNS analysis and visualization tool suite
Home-page: https://github.com/dnsviz/dnsviz/
Author: Casey Deccio
......
......@@ -96,24 +96,15 @@ Install dnspython.
$ sudo yum install python-dns
```
Install rpm-build tools to build the RPM.
Install rpm-build tools, then build and install the DNSViz RPM.
```
$ sudo yum install rpm-build
```
Download the latest DNSViz release (denoted ${VERS}), extract the files, and
build using custom install script (to handle man pages).
```
$ curl -L -O https://github.com/dnsviz/dnsviz/archive/v${VERS}.tar.gz
$ tar -zxvf v${VERS}.tar.gz
$ cd dnsviz-${VERS}/
$ python setup.py bdist_rpm --install-script contrib/rpm-install.sh --distribution-name el${RHEL_VERS}
$ sudo rpm -iv dist/dnsviz-*-1.noarch.rpm
```
Install the newly created RPM file.
```
$ sudo rpm -iv dist/dnsviz-${VERS}-1.noarch.rpm
```
Note that a custom install script is used to properly install the DNSViz man
pages. The value of ${RHEL_VERS} corresponds to the RHEL version (e.g., 6 or
7).
## Usage
......
......@@ -6,6 +6,8 @@
#
# Copyright 2014-2016 VeriSign, Inc.
#
# Copyright 2016-2017 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -234,15 +236,15 @@ class DigCommandLineQuery:
self.tcp = True
elif arg in ('+notcp', '+novc'):
self.tcp = False
elif arg.startswith('+time') and \
(len(arg) <= 5 or arg[5] == '='):
elif arg.startswith('+timeout') and \
(len(arg) <= 8 or arg[8] == '='):
try:
opt, arg = arg.split('=')
self.query_timeout = float(arg)
if self.query_timeout < 1.0:
self.query_timeout = 1.0
except ValueError:
raise CommandLineException('+time requires a numerical argument')
raise CommandLineException('+timeout requires a numerical argument')
#TODO +[no]topdown
#TODO +[no]trace
#TODO +[no]tries
......@@ -348,7 +350,7 @@ class DigCommandLineQuery:
def display(self, response, server, options):
if response is None:
return ';; no servers were queried'
return ';; no servers were queried\n'
elif response.message is not None:
if self.short:
......
Metadata-Version: 1.1
Name: dnsviz
Version: 0.6.6
Summary: DNS analysis and visualization tool suite
Home-page: https://github.com/dnsviz/dnsviz/
Author: Casey Deccio
Author-email: casey@deccio.net
License: LICENSE
Description: DNSViz is a tool suite for analysis and visualization of Domain Name System
(DNS) behavior, including its security extensions (DNSSEC). This tool suite
powers the Web-based analysis available at http://dnsviz.net/ .
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)
Classifier: Natural Language :: English
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Internet :: Name Service (DNS)
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Topic :: System :: Networking :: Monitoring
Requires: pygraphviz (>=1.1)
Requires: m2crypto (>=0.24.0)
Requires: dnspython (>=1.11)
COPYRIGHT
LICENSE
MANIFEST.in
README.md
setup.py
bin/dnsviz
contrib/digviz
contrib/dnsviz-lg-ws.js
contrib/dnsviz-lg.cgi
contrib/m2crypto-0.23.patch
contrib/m2crypto-pre0.23.patch
contrib/rpm-install.sh
contrib/dnsviz-lg-java/net/dnsviz/applet/DNSLookingGlassApplet.java
contrib/dnsviz-lg-java/net/dnsviz/lookingglass/DNSLookingGlass.java
contrib/dnsviz-lg-java/net/dnsviz/transport/DNSQueryTransportHandler.java
contrib/dnsviz-lg-java/net/dnsviz/transport/DNSQueryTransportHandlerComparator.java
contrib/dnsviz-lg-java/net/dnsviz/transport/DNSQueryTransportHandlerTCP.java
contrib/dnsviz-lg-java/net/dnsviz/transport/DNSQueryTransportHandlerUDP.java
contrib/dnsviz-lg-java/net/dnsviz/transport/DNSQueryTransportManager.java
contrib/dnsviz-lg-java/net/dnsviz/transport/Errno.java
contrib/dnsviz-lg-java/net/dnsviz/util/Base64.java
contrib/dnsviz-lg-java/net/dnsviz/util/Base64Decoder.java
contrib/dnsviz-lg-java/net/dnsviz/util/Base64Encoder.java
contrib/dnsviz-lg-java/net/dnsviz/util/DNSSettings.java
contrib/dnsviz-lg-java/net/dnsviz/websocket/WebSocketClient.java
dnsviz/__init__.py
dnsviz/base32.py
dnsviz/config.py.in
dnsviz/crypto.py
dnsviz/format.py
dnsviz/ipaddr.py
dnsviz/query.py
dnsviz/resolver.py
dnsviz/response.py
dnsviz/transport.py
dnsviz/util.py
dnsviz.egg-info/PKG-INFO
dnsviz.egg-info/SOURCES.txt
dnsviz.egg-info/dependency_links.txt
dnsviz.egg-info/top_level.txt
dnsviz/analysis/__init__.py
dnsviz/analysis/errors.py
dnsviz/analysis/offline.py
dnsviz/analysis/online.py
dnsviz/analysis/status.py
dnsviz/commands/__init__.py
dnsviz/commands/graph.py
dnsviz/commands/grok.py
dnsviz/commands/print.py
dnsviz/commands/probe.py
dnsviz/commands/query.py
dnsviz/viz/__init__.py
dnsviz/viz/dnssec.py
doc/COPYRIGHT
doc/Makefile
doc/dnsviz-graph.html
doc/images/error.png
doc/images/logo-16x16.png
doc/images/logo-220x100.png
doc/images/logo-60x60.png
doc/images/warning.png
doc/man/dnsviz-graph.1
doc/man/dnsviz-grok.1
doc/man/dnsviz-print.1
doc/man/dnsviz-probe.1
doc/man/dnsviz-query.1
doc/man/dnsviz.1
doc/src/alias.dot
doc/src/delegation-bogus.dot
doc/src/delegation-incomplete.dot
doc/src/delegation-lame.dot
doc/src/delegation-secure.dot
doc/src/delegation.dot
doc/src/dname-invalid.dot
doc/src/dname.dot
doc/src/dnskey-revoke.dot
doc/src/dnskey-sep.dot
doc/src/dnskey-trust-anchor.dot
doc/src/dnskey.dot
doc/src/ds-invalid-digest.dot
doc/src/ds-invalid.dot
doc/src/ds-nodnskey.dot
doc/src/ds-pre-revoke.dot
doc/src/ds-unknown-alg.dot
doc/src/ds.dot
doc/src/edges-errors.dot
doc/src/edges-warnings.dot
doc/src/error.svg
doc/src/logo.svg
doc/src/nodata.dot
doc/src/nodes-bogus.dot
doc/src/nodes-errors.dot
doc/src/nodes-insecure.dot
doc/src/nodes-secure.dot
doc/src/nodes-warnings.dot
doc/src/nsec-ds.dot
doc/src/nsec-invalid.dot
doc/src/nsec-partial-bogus.dot
doc/src/nsec.dot
doc/src/nsec3-optout.dot
doc/src/nsec3.dot
doc/src/nxdomain.dot
doc/src/response-error.dot
doc/src/response-warning.dot
doc/src/rrset.dot
doc/src/rrsig-dnskey-pruned.dot
doc/src/rrsig-dnskey-redundant.dot
doc/src/rrsig-dnskey.dot
doc/src/rrsig-ds.dot
doc/src/rrsig-nsec.dot
doc/src/rrsig-rrset-expired.dot
doc/src/rrsig-rrset-invalid-sig.dot
doc/src/rrsig-rrset-invalid.dot
doc/src/rrsig-rrset-nodnskey.dot
doc/src/rrsig-rrset-pre-revoke.dot
doc/src/rrsig-rrset-unknown-alg.dot
doc/src/rrsig-rrset.dot
doc/src/warning.svg
doc/src/wildcard.dot
doc/src/zone-errors.dot
doc/src/zone-warnings.dot
doc/src/zone.dot
share/css/dnsviz.css
share/hints/named.root
share/html/dnssec-template.html
share/js/dnsviz.js
share/trusted-keys/root.txt
\ No newline at end of file
......@@ -5,6 +5,8 @@
#
# Copyright 2015-2016 VeriSign, Inc.
#
# Copyright 2016-2017 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -1754,15 +1756,19 @@ class DNSKEYNotAtZoneApex(DNSKEYError):
code = 'DNSKEY_NOT_AT_ZONE_APEX'
required_params = ['zone', 'name']
class TrustAnchorNotSigning(DNSKEYError):
class TrustAnchorError(DomainNameAnalysisError):
pass
class NoTrustAnchorSigning(TrustAnchorError):
'''
>>> e = TrustAnchorNotSigning()
>>> e = NoTrustAnchorSigning(zone='foo.baz.')
>>> e.description
'The key was designated as a trust anchor but was not found signing the RRset.'
'One or more keys were designated as trust anchors for foo.baz., but none were found signing the DNSKEY RRset.'
'''
_abstract = False
description_template = "The key was designated as a trust anchor but was not found signing the RRset."
code = 'TRUST_ANCHOR_NOT_SIGNING'
description_template = "One or more keys were designated as trust anchors for %(zone)s, but none were found signing the DNSKEY RRset."
code = 'NO_TRUST_ANCHOR_SIGNING'
required_params = ['zone']
class RevokedNotSigning(DNSKEYError):
'''
......
......@@ -11,6 +11,8 @@
#
# Copyright 2014-2016 VeriSign, Inc.
#
# Copyright 2016-2017 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -503,7 +505,7 @@ class OfflineDomainNameAnalysis(OnlineDomainNameAnalysis):
if self.response_component_status is not None:
zone_status = Status.delegation_status_mapping[self.response_component_status[parent_obj]]
else:
zone_status = Status.delegation_status_mapping[Status.INSECURE]
zone_status = Status.delegation_status_mapping[Status.DELEGATION_STATUS_INSECURE]
zone_warnings = [w.terse_description for w in parent_obj.zone_warnings]
zone_errors = [e.terse_description for e in parent_obj.zone_errors]
if parent_obj.parent is not None:
......@@ -2133,8 +2135,7 @@ class OfflineDomainNameAnalysis(OnlineDomainNameAnalysis):
return
trusted_keys_rdata = set([k for z, k in trusted_keys if z == self.name])
trusted_keys_existing = set()
trusted_keys_not_self_signing = set()
trusted_keys_self_signing = set()
# buid a list of responsive servers
bailiwick_map, default_bailiwick = self.get_bailiwick_mapping()
......@@ -2146,10 +2147,8 @@ class OfflineDomainNameAnalysis(OnlineDomainNameAnalysis):
# any errors point to their own servers_clients value
for dnskey in self.get_dnskeys():
if dnskey.rdata in trusted_keys_rdata:
trusted_keys_existing.add(dnskey)
if dnskey not in self.ksks:
trusted_keys_not_self_signing.add(dnskey)
if dnskey.rdata in trusted_keys_rdata and dnskey in self.ksks:
trusted_keys_self_signing.add(dnskey)
if dnskey in self.revoked_keys and dnskey not in self.ksks:
err = Errors.RevokedNotSigning()
err.servers_clients = dnskey.servers_clients
......@@ -2170,18 +2169,15 @@ class OfflineDomainNameAnalysis(OnlineDomainNameAnalysis):
# if the key is shown to be signing anything other than the
# DNSKEY RRset, or if it associated with a DS or trust anchor,
# then mark it as an error; otherwise, mark it as a warning.
if dnskey in self.zsks or dnskey in self.dnskey_with_ds or dnskey in trusted_keys_existing:
if dnskey in self.zsks or dnskey in self.dnskey_with_ds or dnskey.rdata in trusted_keys_rdata:
dnskey.errors.append(err)
else:
dnskey.warnings.append(err)
for (server,client,response) in servers_clients_without:
err.add_server_client(server, client, response)
if not trusted_keys_existing.difference(trusted_keys_not_self_signing):
for dnskey in trusted_keys_not_self_signing:
err = Errors.TrustAnchorNotSigning()
err.servers_clients = dnskey.servers_clients
dnskey.errors.append(err)
if trusted_keys_rdata and not trusted_keys_self_signing:
self.zone_errors.append(Errors.NoTrustAnchorSigning(zone=fmt.humanize_name(self.zone.name)))
def populate_response_component_status(self, G):
response_component_status = {}
......
......@@ -496,6 +496,27 @@ class OnlineDomainNameAnalysis(object):
return self._glue_ip_mapping
def get_root_hint_mapping(self):
servers = {}
hints = util.get_root_hints()
for rdata in hints[(dns.name.root, dns.rdatatype.NS)]:
servers[rdata.target] = set()
for rdtype in (dns.rdatatype.A, dns.rdatatype.AAAA):
if (rdata.target, rdtype) in hints:
servers[rdata.target].update([IPAddr(r.address) for r in hints[(rdata.target, rdtype)]])
for name, server in util.HISTORICAL_ROOT_IPS:
if name not in servers:
servers[name] = set()
servers[name].add(server)
return servers
def _get_servers_from_hints(self, name, hints):
servers = set()
server_mapping = self._get_server_ip_mapping_from_hints(name, hints)
for ns_name in server_mapping:
servers.update(server_mapping[ns_name])
return servers
def get_auth_ns_ip_mapping(self):
'''Return a reference to the mapping of NS targets from delegation or
authoritative source to their authoritative IPv4 and IPv6 addresses.'''
......@@ -667,7 +688,10 @@ class OnlineDomainNameAnalysis(object):
if not hasattr(self, '_ip_ns_name_mapping') or self._ip_ns_name_mapping is None:
self._ip_ns_name_mapping = {}
glue_ips = self.get_glue_ip_mapping()
if self.name == dns.name.root:
glue_ips = self.get_root_hint_mapping()
else:
glue_ips = self.get_glue_ip_mapping()
auth_ips = self.get_auth_ns_ip_mapping()
if self.stub:
auth_names = set(auth_ips)
......@@ -971,7 +995,7 @@ class Analyst(object):
qname_only = True
analysis_type = ANALYSIS_TYPE_AUTHORITATIVE
clone_attrnames = ['dlv_domain', 'try_ipv4', 'try_ipv6', 'client_ipv4', 'client_ipv6', 'query_class_mixin', 'logger', 'ceiling', 'edns_diagnostics', 'follow_ns', 'explicit_delegations', 'stop_at_explicit', 'odd_ports', 'explicit_only', 'analysis_cache', 'cache_level', 'analysis_cache_lock', 'transport_manager', 'th_factories', 'resolver']
clone_attrnames = ['dlv_domain', 'try_ipv4', 'try_ipv6', 'client_ipv4', 'client_ipv6', 'query_class_mixin', 'logger', 'ceiling', 'edns_diagnostics', 'follow_ns', 'explicit_delegations', 'stop_at_explicit', 'odd_ports', 'analysis_cache', 'cache_level', 'analysis_cache_lock', 'transport_manager', 'th_factories', 'resolver']
def __init__(self, name, dlv_domain=None, try_ipv4=True, try_ipv6=True, client_ipv4=None, client_ipv6=None, query_class_mixin=None, logger=_logger, ceiling=None, edns_diagnostics=False,
follow_ns=False, follow_mx=False, trace=None, explicit_delegations=None, stop_at_explicit=None, odd_ports=None, extra_rdtypes=None, explicit_only=False,
......@@ -1926,7 +1950,7 @@ class Analyst(object):
kwargs = dict([(n, getattr(self, n)) for n in self.clone_attrnames])
for cname in name_obj.cname_targets:
for target in name_obj.cname_targets[cname]:
a = self.__class__(target, trace=self.trace + [(name_obj, dns.rdatatype.CNAME)], extra_rdtypes=self.extra_rdtypes, **kwargs)
a = self.__class__(target, trace=self.trace + [(name_obj, dns.rdatatype.CNAME)], explicit_only=self.explicit_only, extra_rdtypes=self.extra_rdtypes, **kwargs)
t = threading.Thread(target=self._analyze_dependency, args=(a, name_obj.cname_targets[cname], target, errors))
t.start()
threads.append(t)
......@@ -1946,7 +1970,7 @@ class Analyst(object):
if self.follow_mx:
for target in name_obj.mx_targets:
a = self.__class__(target, trace=self.trace + [(name_obj, dns.rdatatype.MX)], extra_rdtypes=[dns.rdatatype.A, dns.rdatatype.AAAA], **kwargs)
a = self.__class__(target, trace=self.trace + [(name_obj, dns.rdatatype.MX)], explicit_only=True, extra_rdtypes=[dns.rdatatype.A, dns.rdatatype.AAAA], **kwargs)
t = threading.Thread(target=self._analyze_dependency, args=(a, name_obj.mx_targets, target, errors))
t.start()
threads.append(t)
......
......@@ -6,6 +6,8 @@
#
# Copyright 2014-2016 VeriSign, Inc.
#
# Copyright 2016-2017 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -36,7 +38,7 @@ import dns.exception, dns.name
from dnsviz.analysis import OfflineDomainNameAnalysis, DNS_RAW_VERSION
from dnsviz.config import DNSVIZ_SHARE_PATH, JQUERY_PATH, JQUERY_UI_PATH, JQUERY_UI_CSS_PATH, RAPHAEL_PATH
from dnsviz.format import latin1_binary_to_string as lb2s
from dnsviz.util import TRUSTED_KEYS_ROOT, get_trusted_keys
from dnsviz.util import get_trusted_keys, get_default_trusted_keys
# If the import of DNSAuthGraph fails because of the lack of pygraphviz, it
# will be reported later
......@@ -280,18 +282,7 @@ def main(argv):
else:
names.append(name)
if '-t' not in opts:
try:
tk_str = io.open(TRUSTED_KEYS_ROOT, 'r', encoding='utf-8').read()
except IOError as e:
logger.error('Error reading trusted keys file "%s": %s' % (TRUSTED_KEYS_ROOT, e.strerror))
sys.exit(3)
try:
trusted_keys.extend(get_trusted_keys(tk_str))
except dns.exception.DNSException:
logger.error('There was an error parsing the trusted keys file: "%s"' % arg)
sys.exit(3)
latest_analysis_date = None
name_objs = []
cache = {}
for name in names:
......@@ -299,11 +290,18 @@ def main(argv):
if name_str not in analysis_structured or analysis_structured[name_str].get('stub', True):
logger.error('The analysis of "%s" was not found in the input.' % lb2s(name.to_text()))
continue
name_objs.append(OfflineDomainNameAnalysis.deserialize(name, analysis_structured, cache))
name_obj = OfflineDomainNameAnalysis.deserialize(name, analysis_structured, cache)
name_objs.append(name_obj)
if latest_analysis_date is None or latest_analysis_date > name_obj.analysis_end:
latest_analysis_date = name_obj.analysis_end
if not name_objs:
sys.exit(4)
if '-t' not in opts:
trusted_keys = get_default_trusted_keys(latest_analysis_date)
G = DNSAuthGraph()
for name_obj in name_objs:
name_obj.populate_status(trusted_keys)
......
......@@ -6,6 +6,8 @@
#
# Copyright 2014-2016 VeriSign, Inc.
#
# Copyright 2016-2017 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -41,7 +43,7 @@ import dns.exception, dns.name
from dnsviz.analysis import OfflineDomainNameAnalysis, DNS_RAW_VERSION
from dnsviz.format import latin1_binary_to_string as lb2s
from dnsviz.util import TRUSTED_KEYS_ROOT, get_trusted_keys
from dnsviz.util import get_trusted_keys
# If the import of DNSAuthGraph fails because of the lack of pygraphviz, it
# will be reported later
......@@ -316,7 +318,8 @@ def main(argv):
if name_str not in analysis_structured or analysis_structured[name_str].get('stub', True):
logger.error('The analysis of "%s" was not found in the input.' % lb2s(name.to_text()))
continue
name_objs.append(OfflineDomainNameAnalysis.deserialize(name, analysis_structured, cache))
name_obj = OfflineDomainNameAnalysis.deserialize(name, analysis_structured, cache)
name_objs.append(name_obj)
if not name_objs:
sys.exit(4)
......
......@@ -6,6 +6,8 @@
#
# Copyright 2014-2016 VeriSign, Inc.
#
# Copyright 2016-2017 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -35,7 +37,7 @@ import dns.exception, dns.name
from dnsviz.analysis import TTLAgnosticOfflineDomainNameAnalysis, DNS_RAW_VERSION
from dnsviz.format import latin1_binary_to_string as lb2s
from dnsviz.util import TRUSTED_KEYS_ROOT, get_trusted_keys
from dnsviz.util import get_trusted_keys, get_default_trusted_keys
# If the import of DNSAuthGraph fails because of the lack of pygraphviz, it
# will be reported later
......@@ -430,18 +432,7 @@ def main(argv):
else:
names.append(name)
if '-t' not in opts:
try:
tk_str = io.open(TRUSTED_KEYS_ROOT, 'r', encoding='utf-8').read()
except IOError as e:
logger.error('Error reading trusted keys file "%s": %s' % (TRUSTED_KEYS_ROOT, e.strerror))
sys.exit(3)
try:
trusted_keys.extend(get_trusted_keys(tk_str))
except dns.exception.DNSException:
logger.error('There was an error parsing the trusted keys file: "%s"' % arg)
sys.exit(3)
latest_analysis_date = None
name_objs = []
cache = {}
for name in names:
......@@ -449,11 +440,18 @@ def main(argv):
if name_str not in analysis_structured or analysis_structured[name_str].get('stub', True):
logger.error('The analysis of "%s" was not found in the input.' % lb2s(name.to_text()))
continue
name_objs.append(TTLAgnosticOfflineDomainNameAnalysis.deserialize(name, analysis_structured, cache))
name_obj = TTLAgnosticOfflineDomainNameAnalysis.deserialize(name, analysis_structured, cache)
name_objs.append(name_obj)
if latest_analysis_date is None or latest_analysis_date > name_obj.analysis_end:
latest_analysis_date = name_obj.analysis_end
if not name_objs:
sys.exit(4)
if '-t' not in opts:
trusted_keys = get_default_trusted_keys(latest_analysis_date)
G = DNSAuthGraph()
for name_obj in name_objs:
name_obj.populate_status(trusted_keys)
......
......@@ -6,6 +6,8 @@
#
# Copyright 2014-2016 VeriSign, Inc.
#
# Copyright 2016-2017 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -543,9 +545,24 @@ def _create_and_serve_zone(zone, mappings, port):
zonefile.close()
_serve_zone(zone, zonefile.name, port)
def _cleanup_process(working_dir, pid):
if pid is not None:
try:
os.kill(pid, signal.SIGINT)
except OSError:
return
while True:
try:
os.kill(pid, 0)
time.sleep(0.2)
except OSError:
break
shutil.rmtree(working_dir)
def _serve_zone(zone, zone_file, port):
tmpdir = tempfile.mkdtemp(prefix='dnsviz')
atexit.register(shutil.rmtree, tmpdir)
pid = None
io.open('%s/named.conf' % tmpdir, 'w', encoding='utf-8').write('''
options {
directory "%s";
......@@ -566,29 +583,47 @@ logging {
category unmatched { null; };
};
''' % (tmpdir, port, port, lb2s(zone.to_text()), os.path.abspath(zone_file), tmpdir))
try:
p = subprocess.Popen(['named-checkconf', '-z', '%s/named.conf' % tmpdir], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError as e:
usage('This option requires executing named-checkconf. Please ensure that it is installed and in PATH (%s).' % e)
_cleanup_process(tmpdir, pid)
sys.exit(1)
(stdout, stderr) = p.communicate()
if p.returncode != 0:
usage('There was an problem with the zone file for "%s":\n%s' % (lb2s(zone.to_text()), stdout))
_cleanup_process(tmpdir, pid)
sys.exit(1)
try:
p = subprocess.Popen(['named', '-c', '%s/named.conf' % tmpdir], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
p = subprocess.Popen(['named', '-L', '%s/named.log' % tmpdir, '-c', '%s/named.conf' % tmpdir], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError as e:
usage('This option requires executing named. Please ensure that it is installed and in PATH (%s).' % e)
_cleanup_process(tmpdir, pid)
sys.exit(1)
(stdout, stderr) = p.communicate()
if p.returncode != 0:
usage('There was an problem executing named to serve the "%s" zone\n%s' % (lb2s(zone.to_text()), stdout))
try:
log = io.open('%s/named.log' % tmpdir, 'r', encoding='utf-8').read()
except IOError as e:
log = ''
if not log:
log = stdout
usage('There was an problem executing named to serve the "%s" zone:\n%s' % (lb2s(zone.to_text()), log))
_cleanup_process(tmpdir, pid)
sys.exit(1)
try:
pid = int(io.open('%s/named.pid' % tmpdir, 'r', encoding='utf-8').read())
except (IOError, ValueError) as e:
usage('There was an error detecting the process ID for named: %s' % e)
_cleanup_process(tmpdir, pid)
sys.exit(1)
pid = int(io.open('%s/named.pid' % tmpdir, 'r', encoding='utf-8').read())
atexit.register(os.kill, pid, signal.SIGINT)
atexit.register(_cleanup_process, tmpdir, pid)
def _get_ecs_option(s):
try:
......
......@@ -6,6 +6,8 @@
#
# Copyright 2015-2016 VeriSign, Inc.
#
# Copyright 2016-2017 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -143,7 +145,10 @@ class DVCommandLineQuery:
if self.trace:
dnsget_args.append('-A')
else:
dnsget_args.extend(['-s', self.nameservers[0]])
if self.nameservers[0].version == 6:
dnsget_args.extend(['-s', '[%s]' % (self.nameservers[0])])
else:
dnsget_args.extend(['-s', self.nameservers[0]])
dnsget_args.append(self.qname)
if self.trusted_keys_file is not None:
......
......@@ -11,6 +11,8 @@
#
# Copyright 2014-2016 VeriSign, Inc.
#
# Copyright 2016 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -244,7 +246,10 @@ def _dnskey_to_ec(alg, key):
else:
raise ValueError('Algorithm not supported')
return EC.pub_key_from_params(curve, EC_NOCOMPRESSION + key)
try:
return EC.pub_key_from_params(curve, EC_NOCOMPRESSION + key)
except ValueError:
return None
def _validate_rrsig_rsa(alg, sig, msg, key):
pubkey = _dnskey_to_rsa(key)
......@@ -314,6 +319,10 @@ def _validate_rrsig_gost(alg, sig, msg, key):
def _validate_rrsig_ec(alg, sig, msg, key):
pubkey = _dnskey_to_ec(alg, key)
# if the key is invalid, then the signature is also invalid
if pubkey is None:
return False
if alg in (13,):
alg='sha256'
sigsize = 64
......
......@@ -11,6 +11,8 @@
#
# Copyright 2014-2016 VeriSign, Inc.
#
# Copyright 2016 Casey Deccio.
#
# DNSViz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
......@@ -168,5 +170,10 @@ def humanize_name(name, idn=False):
return name.rstrip('.')
def latin1_binary_to_string(s):
return codecs.decode(s, 'latin1')
# python3/python2 dual compatibility
#XXX In places where this method wraps calls to dns.name.Name.to_text(),
# this is no longer needed with dnspython 1.15.0
if isinstance(s, bytes):
return codecs.decode(s, 'latin1')
return s
lb2s = latin1_binary_to_string