def decode_request(message):

    # decode the query
    message = dns.message.from_wire(message)
    myprint(type(message))
    myprint("---query----")
    myprint(message)
    myprint("------------")
    # section eg: message.question or message.answer
    # section=message.question
    # name="A"
    # rdclass= 1 # IN the internet

    # rdtype= 1 # A 1 a host address
    # rrs = message.find_rrset(section, name, rdclass, rdtype)
    # rrs = message.get_rrset(section, name, rdclass, rdtype)
    myprint("id %s" % message.id)
    myprint("rcode %s" % message.rcode())
    myprint(" rcode %s" % dns.rcode.to_text(message.rcode()))
    # print dir(message.rcode)
    myprint("opcode %s" % message.opcode())
    myprint(" opcode %s" % dns.opcode.to_text(message.opcode()))
    myprint("flags %s" % message.flags)
    myprint(" flags %s" % dns.flags.to_text(message.flags))
    myprint("index %s" % message.index)
    for rrset in message.question:  # list of dns.rrset.RRset objects
        myprint("----> rrset: %s" % rrset)
        myprint(" covers %i" % rrset.covers)
        myprint(" rdclass %i" % rrset.rdclass)
        myprint(" rdtype %i" % rrset.rdtype)
        myprint(" ttl %i" % rrset.ttl)
        myprint(" name  %s" % rrset.name)
    return message
Example #2
0
def main():
    # Parse the arguments
    parser = argparse.ArgumentParser(description='A basic DoH client')
    parser.add_argument('label', metavar='label', type=str,
                        help='The label to make the query for')
    parser.add_argument('uri', metavar='uri', type=str,
                        help='The URI template to make the query to')
    parser.add_argument('type', metavar='type', type=str, default='A',
                        help='The type to query for')
    parser.add_argument('--get', dest='req', action='store_const',
                        const=get, default=post,
                        help='Make a GET request instead of POST')
    parser.add_argument('--insecure', action='store_true',
                        help='Ignore TLS/SSL issues')
    args = parser.parse_args()

    # Build the response, using the values determined from the arguments
    resp = args.req(args.label, args.uri, args.type)
    message = dns.message.from_wire(resp)

    # If NoError, print message info
    if message.rcode() == 0:
        print('Question:')
        for result in message.question:
            print('\t' + str(result))

        print('\nAnswer:')
        for result in message.answer:
            print('\t' + str(result))

        print('\nAuthority:')
        for result in message.authority:
            print('\t' + str(result))

        print('\nAdditional:')
        for result in message.additional:
            print('\t' + str(result))
    elif message.rcode() == 3:
        print('Got NXDOMAIN, label does not exist\n')
        print('Question:')
        for result in message.question:
            print('\t' + str(result))

        print('\nAuthority:')
        for result in message.authority:
            print('\t' + str(result))

        print('\nAdditional:')
        for result in message.additional:
            print('\t' + str(result))
    else:
        print('Error, got rcode ' + str(message.rcode()))
Example #3
0
def main():
    global testdomain

    if len(sys.argv) < 2:
        sys.stderr.write("Usage error")
        return 2
    # create resolver object
    resolver = dns.resolver.Resolver()
    # create common query for all nameservers
    query = dns.message.make_query(testdomain, "A")
    # list of faulty nameservers
    renegades = []
    # process nameserver records
    for nsarg in sys.argv[1:]:
        # get ip addresses of nameserver
        (ns, addrs) = get_ns_addrs(nsarg)
        message = None
        for addr in addrs:
            try:
                dbg_print("Query nameserver %s (%s) for A rr %s" %
                          (ns, addr, testdomain))
                message = dns.query.udp(query, addr, 3)
                break
            except dns.exception.Timeout, e:
                # timeout means that it is good - some nameservers do not
                # send answers for domain which are not delegated on them
                break
        # if there is any answer it means that recursive query was done
        if message and message.rcode() == dns.rcode.NXDOMAIN:
            dbg_print("Answer with result received")
            renegades.append(ns)
Example #4
0
def main():
	global testdomain

	if len(sys.argv) < 2:
		sys.stderr.write("Usage error")
		return 2
	# create resolver object
	resolver = dns.resolver.Resolver()
	# create common query for all nameservers
	query = dns.message.make_query(testdomain, "A")
	# list of faulty nameservers
	renegades = []
	# process nameserver records
	for nsarg in sys.argv[1:]:
		# get ip addresses of nameserver
		(ns, addrs) = get_ns_addrs(nsarg)
		message = None
		for addr in addrs:
			try:
				dbg_print("Query nameserver %s (%s) for A rr %s" %
						(ns, addr, testdomain))
				message = dns.query.udp(query, addr, 3)
				break
			except dns.exception.Timeout, e:
				# timeout means that it is good - some nameservers do not
				# send answers for domain which are not delegated on them
				break
		# if there is any answer it means that recursive query was done
		if message and message.rcode() == dns.rcode.NXDOMAIN:
			dbg_print("Answer with result received")
			renegades.append(ns)
Example #5
0
def to_doh_simple(message):
    simple = {"Status": message.rcode()}
    for f in dns.flags.Flag:
        if f != dns.flags.Flag.AA and f != dns.flags.Flag.QR:
            # DoH JSON doesn't need AA and omits it.  DoH JSON is only
            # used in replies so the QR flag is implied.
            simple[f.name] = (message.flags & f) != 0
    for i, s in enumerate(message.sections):
        k = dns.message.MessageSection.to_text(i).title()
        simple[k] = []
        for rrs in s:
            simple[k].extend(flatten_rrset(rrs))
    # we don't encode the ecs_client_subnet field
    return simple
Example #6
0
    def process_message(self, message):
        """Process one message in the transfer.

        The message should have the same relativization as was specified when
        the `dns.xfr.Inbound` was created.  The message should also have been
        created with `one_rr_per_rrset=True` because order matters.

        Returns `True` if the transfer is complete, and `False` otherwise.
        """
        if self.txn is None:
            replacement = self.rdtype == dns.rdatatype.AXFR
            self.txn = self.txn_manager.writer(replacement)
        rcode = message.rcode()
        if rcode != dns.rcode.NOERROR:
            raise TransferError(rcode)
        #
        # We don't require a question section, but if it is present is
        # should be correct.
        #
        if len(message.question) > 0:
            if message.question[0].name != self.origin:
                raise dns.exception.FormError("wrong question name")
            if message.question[0].rdtype != self.rdtype:
                raise dns.exception.FormError("wrong question rdatatype")
        answer_index = 0
        if self.soa_rdataset is None:
            #
            # This is the first message.  We're expecting an SOA at
            # the origin.
            #
            if not message.answer or message.answer[0].name != self.origin:
                raise dns.exception.FormError("No answer or RRset not "
                                              "for zone origin")
            rrset = message.answer[0]
            name = rrset.name
            rdataset = rrset
            if rdataset.rdtype != dns.rdatatype.SOA:
                raise dns.exception.FormError("first RRset is not an SOA")
            answer_index = 1
            self.soa_rdataset = rdataset.copy()
            if self.rdtype == dns.rdatatype.IXFR:
                if self.soa_rdataset[0].serial == self.serial:
                    #
                    # We're already up-to-date.
                    #
                    self.done = True
                elif dns.serial.Serial(self.soa_rdataset[0].serial) < \
                     self.serial:
                    # It went backwards!
                    raise SerialWentBackwards
                else:
                    if self.is_udp and len(message.answer[answer_index:]) == 0:
                        #
                        # There are no more records, so this is the
                        # "truncated" response.  Say to use TCP
                        #
                        raise UseTCP
                    #
                    # Note we're expecting another SOA so we can detect
                    # if this IXFR response is an AXFR-style response.
                    #
                    self.expecting_SOA = True
        #
        # Process the answer section (other than the initial SOA in
        # the first message).
        #
        for rrset in message.answer[answer_index:]:
            name = rrset.name
            rdataset = rrset
            if self.done:
                raise dns.exception.FormError("answers after final SOA")
            if rdataset.rdtype == dns.rdatatype.SOA and \
               name == self.origin:
                #
                # Every time we see an origin SOA delete_mode inverts
                #
                if self.rdtype == dns.rdatatype.IXFR:
                    self.delete_mode = not self.delete_mode
                #
                # If this SOA Rdataset is equal to the first we saw
                # then we're finished. If this is an IXFR we also
                # check that we're seeing the record in the expected
                # part of the response.
                #
                if rdataset == self.soa_rdataset and \
                        (self.rdtype == dns.rdatatype.AXFR or
                         (self.rdtype == dns.rdatatype.IXFR and
                          self.delete_mode)):
                    #
                    # This is the final SOA
                    #
                    if self.expecting_SOA:
                        # We got an empty IXFR sequence!
                        raise dns.exception.FormError('empty IXFR sequence')
                    if self.rdtype == dns.rdatatype.IXFR \
                       and self.serial != rdataset[0].serial:
                        raise dns.exception.FormError('unexpected end of IXFR '
                                                      'sequence')
                    self.txn.replace(name, rdataset)
                    self.txn.commit()
                    self.txn = None
                    self.done = True
                else:
                    #
                    # This is not the final SOA
                    #
                    self.expecting_SOA = False
                    if self.rdtype == dns.rdatatype.IXFR:
                        if self.delete_mode:
                            # This is the start of an IXFR deletion set
                            if rdataset[0].serial != self.serial:
                                raise dns.exception.FormError(
                                    "IXFR base serial mismatch")
                        else:
                            # This is the start of an IXFR addition set
                            self.serial = rdataset[0].serial
                            self.txn.replace(name, rdataset)
                    else:
                        # We saw a non-final SOA for the origin in an AXFR.
                        raise dns.exception.FormError('unexpected origin SOA '
                                                      'in AXFR')
                continue
            if self.expecting_SOA:
                #
                # We made an IXFR request and are expecting another
                # SOA RR, but saw something else, so this must be an
                # AXFR response.
                #
                self.rdtype = dns.rdatatype.AXFR
                self.expecting_SOA = False
                self.delete_mode = False
                self.txn.rollback()
                self.txn = self.txn_manager.writer(True)
                #
                # Note we are falling through into the code below
                # so whatever rdataset this was gets written.
                #
            # Add or remove the data
            if self.delete_mode:
                self.txn.delete_exact(name, rdataset)
            else:
                self.txn.add(name, rdataset)
        if self.is_udp and not self.done:
            #
            # This is a UDP IXFR and we didn't get to done, and we didn't
            # get the proper "truncated" response
            #
            raise dns.exception.FormError('unexpected end of UDP IXFR')
        return self.done
Example #7
0
        # decode the query
        message = dns.message.from_wire(message)
        print type(message)
        print "---query----"
        print message
        print "------------"
        # section eg: message.question or message.answer
        # section=message.question
        # name="A"
        # rdclass= 1 # IN the internet

        # rdtype= 1 # A 1 a host address
        # rrs = message.find_rrset(section, name, rdclass, rdtype)
        # rrs = message.get_rrset(section, name, rdclass, rdtype)
        print "id %s" % message.id
        print "rcode %s" % message.rcode()
        print " rcode %s" % dns.rcode.to_text(message.rcode())
        # print dir(message.rcode)
        print "opcode %s" % message.opcode()
        print " opcode %s" % dns.opcode.to_text(message.opcode())
        print "flags %s" % message.flags
        print " flags %s" % dns.flags.to_text(message.flags)
        print "index %s" % message.index
        for rrset in message.question:  # list of dns.rrset.RRset objects
            print "----> rrset: %s" % rrset
            print " covers %i" % rrset.covers
            print " rdclass %i" % rrset.rdclass
            print " rdtype %i" % rrset.rdtype
            print " ttl %i" % rrset.ttl
            print " name  %s" % rrset.name
Example #8
0
        # decode the query
        message = dns.message.from_wire(message)
        myprint(type(message))
        myprint("---query----")
        myprint(message)
        myprint("------------")
        # section eg: message.question or message.answer
        # section=message.question
        # name="A"
        # rdclass= 1 # IN the internet

        # rdtype= 1 # A 1 a host address
        # rrs = message.find_rrset(section, name, rdclass, rdtype)
        # rrs = message.get_rrset(section, name, rdclass, rdtype)
        myprint("id %s" % message.id)
        myprint("rcode %s" % message.rcode())
        myprint(" rcode %s" % dns.rcode.to_text(message.rcode()))
        # print dir(message.rcode)
        myprint("opcode %s" % message.opcode())
        myprint(" opcode %s" % dns.opcode.to_text(message.opcode()))
        myprint("flags %s" % message.flags)
        myprint(" flags %s" % dns.flags.to_text(message.flags))
        myprint("index %s" % message.index)
        for rrset in message.question:  # list of dns.rrset.RRset objects
            myprint("----> rrset: %s" % rrset)
            myprint(" covers %i" % rrset.covers)
            myprint(" rdclass %i" % rrset.rdclass)
            myprint(" rdtype %i" % rrset.rdtype)
            myprint(" ttl %i" % rrset.ttl)
            myprint(" name  %s" % rrset.name)
Example #9
0
    def _parse(self):
        try:
            message = dns.message.from_wire(self.data)
        except dns.exception.ShortHeader:
            print("The message is less than 12 octets long.", file=sys.stderr)
            raise
        except dns.exception.TrailingJunk:
            print("There were octets in the message past the end of the proper DNS message.",
                  file=sys.stderr)
            raise
        except dns.exception.BadEDNS:
            print("An OPT record was in the wrong section, or occurred more than once.",
                  file=sys.stderr)
            raise
        except dns.exception.BadTSIG:
            print("A TSIG record was not the last record of the additional data section.",
                  file=sys.stderr)
            raise

        message_id = message.id

        flags = []
        for flag in dns.flags.to_text(message.flags).split():
            flags.append(flag)

        flags.append(dns.opcode.to_text(message.opcode()))
        flags.append(dns.rcode.to_text(message.rcode()))

        total_questions = len(message.question)
        total_answer_rrs = len(message.answer)
        total_authority_rrs = len(message.authority)
        total_additional_rrs = len(message.additional)

        questions = []
        for question in message.question:
            questions.append({"name": question.name.to_text(),
                              "type": dns.rdatatype.to_text(question.rdtype),
                              "class": dns.rdataclass.to_text(question.rdclass)})
        answer_rrs = []
        for answer in message.answer:
            rdata_items = []
            for item in answer.items:
                rdata_items.append(item.to_text())

            answer_rrs.append({"name": answer.name.to_text(),
                               "type": dns.rdatatype.to_text(answer.rdtype),
                               "class": dns.rdataclass.to_text(answer.rdclass),
                               "ttl": answer.ttl,
                               "rdata_length": len(answer.items),
                               "rdata": rdata_items})

        authority_rrs = []
        for authority in message.authority:
            rdata_items = []
            for item in authority.items:
                rdata_items.append(item.to_text())

            authority_rrs.append({"name": authority.name.to_text(),
                                  "type": dns.rdatatype.to_text(dnsauthority.rdtype),
                                  "class": dns.rdataclass.to_text(authority.rdclass),
                                  "ttl": authority.ttl,
                                  "rdata_length": len(authority.items),
                                  "rdata": rdata_items})

        additional_rrs = []
        for additional in message.additional:
            rdata_items = []
            for item in additional.items:
                rdata_items.append(item.to_text())

            additional_rrs.append({"name": additional.name.to_text(),
                                   "type": dns.rdatatype.to_text(additional.rdtype),
                                   "class": dns.rdataclass.to_text(additional.rdclass),
                                   "ttl": additional.ttl,
                                   "rdata_length": len(additional.items),
                                   "rdata": rdata_items})

        return (message_id, flags, total_questions, total_answer_rrs,
                total_authority_rrs, total_additional_rrs, questions,
                answer_rrs, authority_rrs, additional_rrs)