def _onVerify (self, dataPacket, status): if not status: return self.onError ("Query answer not trusted") if self.parse_dns: try: msg = dns.message.from_wire (dataPacket.content) except: if not self.rrtype: self.rrtype = self.query[-1] if self.query[-1][0] != '\xFD' else self.query[-2] if self.rrtype == "NDNCERT": if not self.zone or not self.label: matches = ndn.nre.match ("(<>*)<DNS>(<>*)<NDNCERT>", self.query) if not matches: return self.onError ("Incorrectly formatted query [%s]" % self.query) dns_zone = dns.name.from_text (dnsify (str (matches.expand ("\\1")))) dns_label = dns.name.from_text (dnsify (str (matches.expand ("\\2"))), origin = dns_zone) else: dns_zone = dns.name.from_text (dnsify (str (self.zone))) dns_label = dns.name.from_text (dnsify (str (self.label)), origin = dns_zone) ndncert = dns.rdtypes.IN.NDNCERT.NDNCERT (dns.rdataclass.IN, dns.rdatatype.NDNCERT, dataPacket.content) rrset = dns.rrset.RRset (dns_label, dns.rdataclass.IN, dns.rdatatype.NDNCERT) rrset.add (ttl = dataPacket.signedInfo.freshnessSeconds, rd = ndncert) msg = dns.message.Message (id=0) msg.answer.append (rrset) else: msg = dns.message.from_wire (dataPacket.content) else: msg = None return self.onResult (dataPacket, msg)
def add_rdataset(msg, name, rds): rrset = msg.get_rrset(msg.answer, name, rds.rdclass, rds.rdtype, create=True, force_unique=True) for rd in rds: rrset.add(rd, ttl=rds.ttl)
def _rr_line(self, section_number): """Process one line from the text format answer, authority, or additional data sections. """ section = self.message.sections[section_number] # Name token = self.tok.get(want_leading=True) if not token.is_whitespace(): self.last_name = self.tok.as_name(token, self.message.origin, self.relativize, self.relativize_to) name = self.last_name token = self.tok.get() if not token.is_identifier(): raise dns.exception.SyntaxError # TTL try: ttl = int(token.value, 0) token = self.tok.get() if not token.is_identifier(): raise dns.exception.SyntaxError except dns.exception.SyntaxError: raise dns.exception.SyntaxError except Exception: ttl = 0 # 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 = dns.rdataclass.IN # Type rdtype = dns.rdatatype.from_text(token.value) (rdclass, rdtype, deleting, empty) = \ self.message._parse_rr_header(section_number, name, rdclass, rdtype) token = self.tok.get() if empty and not token.is_eol_or_eof(): raise dns.exception.SyntaxError if not token.is_eol_or_eof(): self.tok.unget(token) rd = dns.rdata.from_text(rdclass, rdtype, self.tok, self.message.origin, self.relativize, self.relativize_to) covers = rd.covers() else: rd = None covers = dns.rdatatype.NONE rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, self.one_rr_per_rrset) if rd is not None: rrset.add(rd, ttl)
def _rr_line(self, section): """Process one line from the text format answer, authority, or additional data sections. """ deleting = None # Name token = self.tok.get(want_leading = True) if token[0] != dns.tokenizer.WHITESPACE: self.last_name = dns.name.from_text(token[1], None) name = self.last_name token = self.tok.get() if token[0] != dns.tokenizer.IDENTIFIER: raise dns.exception.SyntaxError # TTL try: ttl = int(token[1], 0) token = self.tok.get() if token[0] != dns.tokenizer.IDENTIFIER: raise dns.exception.SyntaxError except dns.exception.SyntaxError: raise dns.exception.SyntaxError except: ttl = 0 # Class try: rdclass = dns.rdataclass.from_text(token[1]) token = self.tok.get() if token[0] != dns.tokenizer.IDENTIFIER: raise dns.exception.SyntaxError if rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE: deleting = rdclass rdclass = self.zone_rdclass except dns.exception.SyntaxError: raise dns.exception.SyntaxError except: rdclass = dns.rdataclass.IN # Type rdtype = dns.rdatatype.from_text(token[1]) token = self.tok.get() if token[0] != dns.tokenizer.EOL and token[0] != dns.tokenizer.EOF: self.tok.unget(token) rd = dns.rdata.from_text(rdclass, rdtype, self.tok, None) covers = rd.covers() else: rd = None covers = dns.rdatatype.NONE rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, self.updating) if not rd is None: rrset.add(rd, ttl)
def _rr_line(self, section): """Process one line from the text format answer, authority, or additional data sections. """ deleting = None # Name token = self.tok.get(want_leading = True) if not token.is_whitespace(): self.last_name = dns.name.from_text(token.value, None) name = self.last_name token = self.tok.get() if not token.is_identifier(): raise dns.exception.SyntaxError # TTL try: ttl = int(token.value, 0) token = self.tok.get() if not token.is_identifier(): raise dns.exception.SyntaxError except dns.exception.SyntaxError: raise dns.exception.SyntaxError except: ttl = 0 # Class try: rdclass = dns.rdataclass.from_text(token.value) token = self.tok.get() if not token.is_identifier(): raise dns.exception.SyntaxError if rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE: deleting = rdclass rdclass = self.zone_rdclass except dns.exception.SyntaxError: raise dns.exception.SyntaxError except: rdclass = dns.rdataclass.IN # Type rdtype = dns.rdatatype.from_text(token.value) token = self.tok.get() if not token.is_eol_or_eof(): self.tok.unget(token) rd = dns.rdata.from_text(rdclass, rdtype, self.tok, None) covers = rd.covers() else: rd = None covers = dns.rdatatype.NONE rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, self.updating) if not rd is None: rrset.add(rd, ttl)
def _rr_line(self, section): """Process one line from the text format answer, authority, or additional data sections. """ deleting = None # Name token = self.tok.get(want_leading=True) if not token.is_whitespace(): self.last_name = dns.name.from_text(token.value, None) name = self.last_name token = self.tok.get() if not token.is_identifier(): raise dns.exception.SyntaxError # TTL try: ttl = int(token.value, 0) token = self.tok.get() if not token.is_identifier(): raise dns.exception.SyntaxError except dns.exception.SyntaxError: raise dns.exception.SyntaxError except Exception: ttl = 0 # Class try: rdclass = dns.rdataclass.from_text(token.value) token = self.tok.get() if not token.is_identifier(): raise dns.exception.SyntaxError if rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE: deleting = rdclass rdclass = self.zone_rdclass except dns.exception.SyntaxError: raise dns.exception.SyntaxError except Exception: rdclass = dns.rdataclass.IN # Type rdtype = dns.rdatatype.from_text(token.value) token = self.tok.get() if not token.is_eol_or_eof(): self.tok.unget(token) rd = dns.rdata.from_text(rdclass, rdtype, self.tok, None) covers = rd.covers() else: rd = None covers = dns.rdatatype.NONE rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, self.updating) if rd is not None: rrset.add(rd, ttl)
def fake_answer(name, rdtype, rvalues): name = dns.name.from_text(name) rdtype = dns.rdatatype.from_text(rdtype) msg = dns.message.make_query(name, rdtype, dns.rdataclass.IN) resp = dns.message.make_response(msg) rrset = resp.find_rrset(resp.answer, name, dns.rdataclass.IN, rdtype, create=True) for rvalue in rvalues: rrset.add(dns.rdata.from_text(dns.rdataclass.IN, rdtype, rvalue)) return dns.resolver.Answer(name, rdtype, dns.rdataclass.IN, resp)
def _rr_line(self, section): """Process one line from the text format answer, authority, or additional data sections. """ deleting = None # Name token = self.tok.get(want_leading=True) if token[0] != dns.tokenizer.WHITESPACE: self.last_name = dns.name.from_text(token[1], None) name = self.last_name token = self.tok.get() if token[0] != dns.tokenizer.IDENTIFIER: raise dns.exception.SyntaxError # TTL try: ttl = int(token[1], 0) token = self.tok.get() if token[0] != dns.tokenizer.IDENTIFIER: raise dns.exception.SyntaxError except dns.exception.SyntaxError: raise dns.exception.SyntaxError except: ttl = 0 # Class try: rdclass = dns.rdataclass.from_text(token[1]) token = self.tok.get() if token[0] != dns.tokenizer.IDENTIFIER: raise dns.exception.SyntaxError if rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE: deleting = rdclass rdclass = self.zone_rdclass except dns.exception.SyntaxError: raise dns.exception.SyntaxError except: rdclass = dns.rdataclass.IN # Type rdtype = dns.rdatatype.from_text(token[1]) token = self.tok.get() if token[0] != dns.tokenizer.EOL and token[0] != dns.tokenizer.EOF: self.tok.unget(token) rd = dns.rdata.from_text(rdclass, rdtype, self.tok, None) covers = rd.covers() else: rd = None covers = dns.rdatatype.NONE rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, self.updating) if not rd is None: rrset.add(rd, ttl)
def fake_answer(name, rdtype, rvalues, sig=None): name = dns.name.from_text(name) rdtype = dns.rdatatype.from_text(rdtype) msg = dns.message.make_query(name, rdtype, dns.rdataclass.IN) resp = dns.message.make_response(msg) rrset = resp.find_rrset(resp.answer, name, dns.rdataclass.IN, rdtype, create=True) for rvalue in rvalues: rrset.add(dns.rdata.from_text(dns.rdataclass.IN, rdtype, rvalue)) if sig: rrset = resp.find_rrset(resp.answer, name, dns.rdataclass.IN, dns.rdatatype.RRSIG, rdtype, create=True) rrset.add(dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.RRSIG, sig)) return dns.resolver.Answer(name, rdtype, dns.rdataclass.IN, resp)
def add(self, name, addr): """Add an address to a name and family""" try: rdata = dns.rdtypes.IN.A.A(dns.rdataclass.IN, dns.rdatatype.A, addr) family = socket.AF_INET except (socket.error, dns.exception.SyntaxError): rdata = dns.rdtypes.IN.AAAA.AAAA(dns.rdataclass.IN, dns.rdatatype.AAAA, addr) family = socket.AF_INET6 family_dict = self.answers.setdefault(name, {}) rrset = family_dict.get(family) if not rrset: family_dict[family] = rrset = dns.rrset.RRset( dns.name.from_text(name), rdata.rdclass, rdata.rdtype) rrset.add(rdata)
def _get_section(self, section, count): """Read the next I{count} records from the wire data and add them to the specified section. section: the section of the message to which to add records count: the number of records to read """ if self.updating or self.one_rr_per_rrset: force_unique = True else: force_unique = False seen_opt = False for i in range(0, count): rr_start = self.current (name, used) = dns.name.from_wire(self.wire, self.current) absolute_name = name if self.message.origin is not None: name = name.relativize(self.message.origin) self.current = self.current + used (rdtype, rdclass, ttl, rdlen) = \ struct.unpack('!HHIH', self.wire[self.current:self.current + 10]) self.current = self.current + 10 if rdtype == dns.rdatatype.OPT: if section is not self.message.additional or seen_opt: raise BadEDNS self.message.payload = rdclass self.message.ednsflags = ttl self.message.edns = (ttl & 0xff0000) >> 16 self.message.options = [] current = self.current optslen = rdlen while optslen > 0: (otype, olen) = \ struct.unpack('!HH', self.wire[current:current + 4]) current = current + 4 opt = dns.edns.option_from_wire( otype, self.wire, current, olen) self.message.options.append(opt) current = current + olen optslen = optslen - 4 - olen seen_opt = True elif rdtype == dns.rdatatype.TSIG: if not (section is self.message.additional and i == (count - 1)): raise BadTSIG if self.message.keyring is None: raise UnknownTSIGKey('got signed message without keyring') secret = self.message.keyring.get(absolute_name) if secret is None: raise UnknownTSIGKey("key '%s' unknown" % name) self.message.keyname = absolute_name (self.message.keyalgorithm, self.message.mac) = \ dns.tsig.get_algorithm_and_mac(self.wire, self.current, rdlen) self.message.tsig_ctx = \ dns.tsig.validate(self.wire, absolute_name, secret, int(time.time()), self.message.request_mac, rr_start, self.current, rdlen, self.message.tsig_ctx, self.message.multi, self.message.first) self.message.had_tsig = True else: if ttl < 0: ttl = 0 if self.updating and \ (rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE): deleting = rdclass rdclass = self.zone_rdclass else: deleting = None if deleting == dns.rdataclass.ANY or \ (deleting == dns.rdataclass.NONE and section is self.message.answer): covers = dns.rdatatype.NONE rd = None else: rd = dns.rdata.from_wire(rdclass, rdtype, self.wire, self.current, rdlen, self.message.origin) covers = rd.covers() if self.message.xfr and rdtype == dns.rdatatype.SOA: force_unique = True rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, force_unique) if rd is not None: rrset.add(rd, ttl) self.current = self.current + rdlen
def _get_section(self, section_number, count): """Read the next I{count} records from the wire data and add them to the specified section. section: the section of the message to which to add records count: the number of records to read """ section = self.message.sections[section_number] force_unique = self.one_rr_per_rrset for i in range(count): rr_start = self.parser.current absolute_name = self.parser.get_name() if self.message.origin is not None: name = absolute_name.relativize(self.message.origin) else: name = absolute_name (rdtype, rdclass, ttl, rdlen) = self.parser.get_struct('!HHIH') if rdtype in (dns.rdatatype.OPT, dns.rdatatype.TSIG): (rdclass, rdtype, deleting, empty) = \ self.message._parse_special_rr_header(section_number, count, i, name, rdclass, rdtype) else: (rdclass, rdtype, deleting, empty) = \ self.message._parse_rr_header(section_number, name, rdclass, rdtype) if empty: if rdlen > 0: raise dns.exception.FormError rd = None covers = dns.rdatatype.NONE else: with self.parser.restrict_to(rdlen): rd = dns.rdata.from_wire_parser(rdclass, rdtype, self.parser, self.message.origin) covers = rd.covers() if self.message.xfr and rdtype == dns.rdatatype.SOA: force_unique = True if rdtype == dns.rdatatype.OPT: self.message.opt = dns.rrset.from_rdata(name, ttl, rd) elif rdtype == dns.rdatatype.TSIG: if self.keyring is None: raise UnknownTSIGKey('got signed message without keyring') if isinstance(self.keyring, dict): key = self.keyring.get(absolute_name) if isinstance(key, bytes): key = dns.tsig.Key(absolute_name, key, rd.algorithm) else: key = self.keyring if key is None: raise UnknownTSIGKey("key '%s' unknown" % name) self.message.keyring = key self.message.tsig_ctx = \ dns.tsig.validate(self.parser.wire, key, absolute_name, rd, int(time.time()), self.message.request_mac, rr_start, self.message.tsig_ctx, self.multi) self.message.tsig = dns.rrset.from_rdata(absolute_name, 0, rd) else: rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, force_unique) if rd is not None: if ttl > 0x7fffffff: ttl = 0 rrset.add(rd, ttl)
def _get_section(self, section, count): """Read the next I{count} records from the wire data and add them to the specified section. @param section: the section of the message to which to add records @type section: list of dns.rrset.RRset objects @param count: the number of records to read @type count: int""" if self.updating or self.one_rr_per_rrset: force_unique = True else: force_unique = False seen_opt = False for i in xrange(0, count): rr_start = self.current (name, used) = dns.name.from_wire(self.wire, self.current) absolute_name = name if not self.message.origin is None: name = name.relativize(self.message.origin) self.current = self.current + used (rdtype, rdclass, ttl, rdlen) = \ struct.unpack('!HHIH', self.wire[self.current:self.current + 10]) self.current = self.current + 10 if rdtype == dns.rdatatype.OPT: if not section is self.message.additional or seen_opt: raise BadEDNS self.message.payload = rdclass self.message.ednsflags = ttl self.message.edns = (ttl & 0xff0000) >> 16 self.message.options = [] current = self.current optslen = rdlen while optslen > 0: (otype, olen) = \ struct.unpack('!HH', self.wire[current:current + 4]) current = current + 4 opt = dns.edns.option_from_wire(otype, self.wire, current, olen) self.message.options.append(opt) current = current + olen optslen = optslen - 4 - olen seen_opt = True elif rdtype == dns.rdatatype.TSIG: if not (section is self.message.additional and i == (count - 1)): raise BadTSIG if self.message.keyring is None: raise UnknownTSIGKey('got signed message without keyring') secret = self.message.keyring.get(absolute_name) if secret is None: raise UnknownTSIGKey("key '%s' unknown" % name) self.message.tsig_ctx = \ dns.tsig.validate(self.wire, absolute_name, secret, int(time.time()), self.message.request_mac, rr_start, self.current, rdlen, self.message.tsig_ctx, self.message.multi, self.message.first) self.message.had_tsig = True else: if ttl < 0: ttl = 0 if self.updating and \ (rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE): deleting = rdclass rdclass = self.zone_rdclass else: deleting = None if deleting == dns.rdataclass.ANY or \ (deleting == dns.rdataclass.NONE and \ section is self.message.answer): covers = dns.rdatatype.NONE rd = None else: rd = dns.rdata.from_wire(rdclass, rdtype, self.wire, self.current, rdlen, self.message.origin) covers = rd.covers() if self.message.xfr and rdtype == dns.rdatatype.SOA: force_unique = True rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, force_unique) if not rd is None: rrset.add(rd, ttl) self.current = self.current + rdlen
def cname_from_dname(name, dname_rrset): synthesized_cname = dns.name.Name(name.labels[:-len(dname_rrset.name)] + dname_rrset[0].target.labels) rrset = dns.rrset.RRset(name, dns.rdataclass.IN, dns.rdatatype.CNAME) rrset.update_ttl(dname_rrset.ttl) rrset.add(dns.rdtypes.ANY.CNAME.CNAME(dns.rdataclass.IN, dns.rdatatype.CNAME, synthesized_cname)) return rrset
_LOG.debug ("Invalid request: label [%s] cannot be dnsified (%s)" % (request_name[len(basename):-1], e)) return None rrset = self._ndns.query (ndns.RRSet).with_parent (zone).filter_by (label = label.to_text (), rtype = rrtype).first () if rrset is None: # check if there is more a specific record: more_specific_rrset = self._ndns.query (ndns.RRSet).\ with_parent (zone).\ filter (ndns.RRSet.label.like ("%%.%s" % label.to_text ()), ndns.RRSet.rtype == rrtype).first () if more_specific_rrset: msg = dns.message.Message (id=0) rrset = dns.rrset.RRset (zone.dns_name, dns.rdataclass.IN, dns.rdatatype.NDNAUTH) # zone.soa[0].rrs[0].ttl rrset.add (ttl = 1, rd = dns.rdtypes.IN.NDNAUTH.NDNAUTH (dns.rdataclass.IN, dns.rdatatype.NDNAUTH, zone.name)) msg.authority.append (rrset) dataPacket = ndns.createSignedData (self._ndns, interestName.appendVersion (), msg.to_wire (origin = zone.dns_name), zone.soa[0].rrs[0].ttl, # 1, zone.default_key) _LOG.debug ("<< Requested record doesn't exist, but there is a more specific record. Returning NDNAUTH as [%s]" % dataPacket.name) return dataPacket else: # _LOG.debug ("(!!! no action defined yet!!!) The requested record (%s %s) not found in zone [%s]" % # (label.to_text (), dns.rdatatype.to_text (rrtype), zone.name))
rrset = self._ndns.query(ndns.RRSet).with_parent(zone).filter_by( label=label.to_text(), rtype=rrtype).first() if rrset is None: # check if there is more a specific record: more_specific_rrset = self._ndns.query (ndns.RRSet).\ with_parent (zone).\ filter (ndns.RRSet.label.like ("%%.%s" % label.to_text ()), ndns.RRSet.rtype == rrtype).first () if more_specific_rrset: msg = dns.message.Message(id=0) rrset = dns.rrset.RRset(zone.dns_name, dns.rdataclass.IN, dns.rdatatype.NDNAUTH) # zone.soa[0].rrs[0].ttl rrset.add(ttl=1, rd=dns.rdtypes.IN.NDNAUTH.NDNAUTH( dns.rdataclass.IN, dns.rdatatype.NDNAUTH, zone.name)) msg.authority.append(rrset) dataPacket = ndns.createSignedData( self._ndns, interestName.appendVersion(), msg.to_wire(origin=zone.dns_name), zone.soa[0].rrs[0].ttl, # 1, zone.default_key) _LOG.debug( "<< Requested record doesn't exist, but there is a more specific record. Returning NDNAUTH as [%s]" % dataPacket.name) return dataPacket
def _get_section(self, section, count): """Read the next I{count} records from the wire data and add them to the specified section. @param section: the section of the message to which to add records @type section: list of dns.rrset.RRset objects @param count: the number of records to read @type count: int""" if self.updating: force_unique = True else: force_unique = False seen_opt = False for i in xrange(0, count): rr_start = self.current (name, used) = dns.name.from_wire(self.wire, self.current) if not self.message.origin is None: name = name.relativize(self.message.origin) self.current = self.current + used (rdtype, rdclass, ttl, rdlen) = \ struct.unpack('!HHIH', self.wire[self.current:self.current + 10]) self.current = self.current + 10 if rdtype == dns.rdatatype.OPT: if not section is self.message.additional or seen_opt: raise BadEDNS self.message.payload = rdclass self.message.ednsflags = ttl self.message.edns = (ttl & 0xff0000) >> 16 seen_opt = True elif rdtype == dns.rdatatype.TSIG: if not (section is self.message.additional and i == (count - 1)): raise BadTSIG if self.message.keyring is None: raise UnknownTSIGKey, 'got signed message without keyring' secret = self.message.keyring.get(name) if secret is None: raise UnknownTSIGKey, "key '%s' unknown" % name self.message.tsig_ctx = \ dns.tsig.validate(self.wire, name, secret, int(time.time()), self.message.request_mac, rr_start, self.current, rdlen, self.message.tsig_ctx, self.message.multi, self.message.first) self.message.had_tsig = True else: if ttl < 0: ttl = 0 if self.updating and \ (rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE): deleting = rdclass rdclass = self.zone_rdclass else: deleting = None if deleting == dns.rdataclass.ANY: covers = dns.rdatatype.NONE rd = None else: rd = dns.rdata.from_wire(rdclass, rdtype, self.wire, self.current, rdlen, self.message.origin) covers = rd.covers() if self.message.xfr and rdtype == dns.rdatatype.SOA: force_unique = True rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, force_unique) if not rd is None: rrset.add(rd, ttl) self.current = self.current + rdlen