823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# This Source Code Form is subject to the terms of the Mozilla Public
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# License, v. 2.0. If a copy of the MPL was not distributed with this
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# file, You can obtain one at http://mozilla.org/MPL/2.0/.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# ans.py: See README.anspy for details.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# set up the RRs to be returned in the next answer
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the message contains up to two pipe-separated ('|') fields.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the first field of the message is a comma-separated list
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# of actions indicating what to put into the answer set
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# (e.g., a dname, a cname, another cname, etc)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# supported actions:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# - cname (cname from the current name to a new one in the same domain)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# - dname (dname to a new domain, plus a synthesized cname)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# - xname ("external" cname, to a new name in a new domain)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# example: xname, dname, cname represents a CNAME to an external
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# domain which is then answered by a DNAME and synthesized
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# CNAME pointing to yet another domain, which is then answered
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# by a CNAME within the same domain, and finally an answer
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# to the query. each RR in the answer set has a corresponding
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# RRSIG. these signatures are not valid, but will exercise the
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# response parser.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the second field is a comma-separated list of which RRs in the
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# answer set to include in the answer, in which order. if prepended
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# with 's', the number indicates which signature to include.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# examples: for the answer set "cname, cname, cname", an rr set
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# '1, s1, 2, s2, 3, s3, 4, s4' indicates that all four RRs should
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# be included in the answer, with siagntures, in the origninal
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# order, while 4, s4, 3, s3, 2, s2, 1, s1' indicates the order
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# should be reversed, 's3, s3, s3, s3' indicates that the third
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# RRSIG should be repeated four times and everything else should
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# be omitted, and so on.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# if there is no second field (i.e., no pipe symbol appears in
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the line) , the default is to send all answers and signatures.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# if a pipe symbol exists but the second field is empty, then
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# nothing is sent at all.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews actions = [x.strip() for x in msg[0].split(b',')]
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews n = functools.reduce(lambda n, act: (n + (2 if act == b'dname' else 1)), [0] + actions)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt for i in range(n):
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews rlist = [x.strip() for x in msg[1].split(b',')]
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# Respond to a DNS query.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt wantsigs = True if m.ednsflags & dns.flags.DO else False
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # for 'www.example.com.'...
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # - name is 'www'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # - domain is 'example.com.'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # - sld is 'example'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # - tld is 'com.'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # default answers, depending on QTYPE.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # currently only A, AAAA, TXT and NS are supported.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # RRSIG rdata - won't validate but will exercise response parsing
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigdata='OCXH2De0yE4NMTl9UykvOsJ4IBGs/ZIpff2rpaVJrVG7jQfmj50otBAp A0Zo7dpBU4ofv0N/F2Ar6LznCncIojkWptEJIAKA5tHegf/jY39arEpO cevbGp6DKxFhlkLXNcw7k9o7DSw14OaRmgAjXdTFbrl4AiAa0zAttFko Tso='
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # construct answer set.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add external CNAME %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add external RRISG(CNAME) %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add RRSIG(CNAME) %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, DNAME, newdom))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add RRSIG(DNAME) %s to %s' % (owner, newdom))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add synthesized CNAME %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add synthesized RRSIG(CNAME) %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # now add the final answer
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, rrtype, final))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt (typename, ttl, expiry, inception, domain, sigdata)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # prepare the response and convert to wire format
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.authority.append(dns.rrset.from_text(domain, ttl, IN, "NS",
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.additional.append(dns.rrset.from_text(('ns1.%s' % domain), 86400,
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.additional.append(dns.rrset.from_text(('ns1.%s' % domain), 86400,
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ("Shutting down now...")
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# Set up responder and control channel, open the pid file, and start
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the main loop, listening for queries on the query channel or commands
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# on the control channel and acting on them.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntquery4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntctrl_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews print ("Listening on %s port %d" % (ip6, sock))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntprint ("Control channel on %s port %d" % (ip4, sock + 1))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntprint ("Ctrl-c to quit")
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews input = [query4_socket, query6_socket, ctrl_socket]
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt inputready, outputready, exceptready = select.select(input, [], [])
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # Handle control channel input
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ("Control channel connected")
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ("Query received on %s" %
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # Handle incoming queries