def decode_nsec_rr(pkt, offset): """ Decode an NSEC resource record; used by zonewalk() routine""" domainname, offset = name_from_wire_message(pkt, offset) rrtype, rrclass, ttl, rdlen = \ struct.unpack("!HHIH", pkt[offset:offset+10]) if rrtype != 47: raise ErrorMessage("encountered RR type %s, expecting NSEC" % rrtype) offset += 10 rdata = pkt[offset:offset + rdlen] end_rdata = offset + rdlen d, offset = name_from_wire_message(pkt, offset) nextrr = d type_bitmap = pkt[offset:end_rdata] p = type_bitmap rrtypelist = [] while p: windownum, winlen = struct.unpack('BB', p[0:2]) bitmap = p[2:2 + winlen] rrtypelist += decode_typebitmap(windownum, bitmap) p = p[2 + winlen:] offset += rdlen return (domainname, rrtype, rrclass, ttl, nextrr, rrtypelist, offset)
def decode_soa_rdata(pkt, offset, rdlen): """decode SOA rdata: mname, rname, serial, refresh, retry, expire, min""" d, offset = name_from_wire_message(pkt, offset) mname = d.text() d, offset = name_from_wire_message(pkt, offset) rname = d.text() serial, refresh, retry, expire, min = \ struct.unpack("!IiiiI", pkt[offset:offset+20]) return "%s %s %d %d %d %d %d" % \ (mname, rname, serial, refresh, retry, expire, min)
def decode_rr(pkt, offset, hexrdata): """ Decode a resource record, given DNS packet and offset""" orig_offset = offset domainname, offset = name_from_wire_message(pkt, offset) rrtype, rrclass, ttl, rdlen = \ struct.unpack("!HHIH", pkt[offset:offset+10]) offset += 10 rdata = pkt[offset:offset + rdlen] if hexrdata: rdata = hexdump(rdata) elif options["generic"]: rdata = generic_rdata_encoding(rdata, rdlen) elif rrtype == 1: # A rdata = socket.inet_ntop(socket.AF_INET, rdata) elif rrtype in [2, 5, 12, 39]: # NS, CNAME, PTR rdata, _ = name_from_wire_message(pkt, offset) # DNAME rdata = rdata.text() elif rrtype == 6: # SOA rdata = decode_soa_rdata(pkt, offset, rdlen) elif rrtype == 15: # MX mx_pref, = struct.unpack('!H', pkt[offset:offset + 2]) rdata, _ = name_from_wire_message(pkt, offset + 2) rdata = "%d %s" % (mx_pref, rdata.text()) elif rrtype in [16, 99]: # TXT, SPF rdata = decode_txt_rdata(rdata, rdlen) elif rrtype == 28: # AAAA rdata = socket.inet_ntop(socket.AF_INET6, rdata) elif rrtype == 33: # SRV rdata = decode_srv_rdata(pkt, offset) elif rrtype == 41: # OPT pass elif rrtype in [43, 59, 32769]: # [C]DS, DLV rdata = decode_ds_rdata(pkt, offset, rdlen) elif rrtype == 45: # IPSECKEY rdata = decode_ipseckey_rdata(pkt, offset, rdlen) elif rrtype in [46, 24]: # RRSIG, SIG rdata = decode_rrsig_rdata(pkt, offset, rdlen) elif rrtype == 47: # NSEC rdata = decode_nsec_rdata(pkt, offset, rdlen) elif rrtype in [48, 25, 60]: # [C]DNSKEY, KEY rdata = decode_dnskey_rdata(pkt, offset, rdlen) elif rrtype == 50: # NSEC3 rdata = decode_nsec3_rdata(pkt, offset, rdlen) elif rrtype == 51: # NSEC3PARAM rdata = decode_nsec3param_rdata(rdata) elif rrtype == 257: # CAA rdata = decode_caa_rdata(rdata) else: # use RFC 3597 rdata = generic_rdata_encoding(rdata, rdlen) offset += rdlen return (domainname, rrtype, rrclass, ttl, rdata, offset)
def decode_naptr_rdata(pkt, offset, rdlen): """decode NAPTR: order, pref, flags, svc, regexp, replacement; RFC 2915""" param = {} order, pref = struct.unpack('!HH', pkt[offset:offset + 4]) position = offset + 4 for name in ["flags", "svc", "regexp"]: slen, = struct.unpack('B', pkt[position]) s = pkt[position + 1:position + 1 + slen] param[name] = '"%s"' % s.replace('\\', '\\\\') position += (1 + slen) d, _ = name_from_wire_message(pkt, position) replacement = d.text() return "%d %d %s %s %s %s" % (order, pref, param["flags"], param["svc"], param["regexp"], replacement)
def decode_nsec_rdata(pkt, offset, rdlen): """decode NSEC rdata: nextrr, type-bitmap; see RFC 4034""" end_rdata = offset + rdlen d, offset = name_from_wire_message(pkt, offset) nextrr = d.text() type_bitmap = pkt[offset:end_rdata] p = type_bitmap rrtypelist = [] while p: windownum, winlen = struct.unpack('BB', p[0:2]) bitmap = p[2:2 + winlen] rrtypelist += decode_typebitmap(windownum, bitmap) p = p[2 + winlen:] return "%s %s" % (nextrr, ' '.join(rrtypelist))
def decode_rrsig_rdata(pkt, offset, rdlen): """decode RRSIG rdata; see RFC 4034""" end_rdata = offset + rdlen type_covered, alg, labels, orig_ttl, sig_exp, sig_inc, keytag = \ struct.unpack('!HBBIIIH', pkt[offset:offset+18]) sig_exp = time.strftime("%Y%m%d%H%M%S", time.gmtime(sig_exp)) sig_inc = time.strftime("%Y%m%d%H%M%S", time.gmtime(sig_inc)) d, offset = name_from_wire_message(pkt, offset + 18) signer_name = d.text() signature = pkt[offset:end_rdata] retval = "{} {} {} {} {} {} {} {} {}".format( qt.get_name(type_covered), alg, labels, orig_ttl, sig_exp, sig_inc, keytag, signer_name, base64.standard_b64encode(signature).decode('ascii')) if options['DEBUG']: retval += " ; sigsize=%d" % (len(signature) * 8) return retval
def decode_rrsig_rdata(pkt, offset, rdlen): end_rdata = offset + rdlen type_covered, alg, labels, orig_ttl, sig_exp, sig_inc, keytag = \ struct.unpack('!HBBIIIH', pkt[offset:offset+18]) sig_exp_text = time.strftime("%Y%m%d%H%M%S", time.gmtime(sig_exp)) sig_inc_text = time.strftime("%Y%m%d%H%M%S", time.gmtime(sig_inc)) d, offset = name_from_wire_message(pkt, offset + 18) signer_name = d.text() signature = pkt[offset:end_rdata] retval = "{} {} {} {} {} {} {} {} {}".format( qt.get_name(type_covered), alg, labels, orig_ttl, sig_exp_text, sig_inc_text, keytag, signer_name, base64.standard_b64encode(signature).decode('ascii')) if options['DEBUG']: sig_validity = "%.2fd" % ((sig_exp - sig_inc) / 86400.0) retval += " ; sigsize=%d, validity=%s" % \ (len(signature) * 8, sig_validity) return retval
def decode_ipseckey_rdata(pkt, offset, rdlen): """decode IPSECKEY rdata; see RFC 4025""" prec, gwtype, alg = struct.unpack('BBB', pkt[offset:offset + 3]) position = offset + 3 if gwtype == 0: # no gateway present gw = "." elif gwtype == 1: # 4-byte IPv4 gw gw = socket.inet_ntop(socket.AF_INET, pkt[position:position + 4]) position += 4 elif gwtype == 2: # 16-byte IPv6 gw gw = socket.inet_ntop(socket.AF_INET6, pkt[position:position + 16]) position += 16 elif gwtype == 3: # domainname d, position = name_from_wire_message(pkt, position) gw = d.text() if alg == 0: # no public key pubkey = "" else: pubkeylen = rdlen - (position - offset) pubkey = base64.standard_b64encode(pkt[position:position + pubkeylen]).decode('ascii') return "{} {} {} {} {}".format(prec, gwtype, alg, gw, pubkey)
def decode_ipseckey_rdata(pkt, offset, rdlen): prec, gwtype, alg = struct.unpack('BBB', pkt[offset:offset + 3]) position = offset + 3 if gwtype == 0: gw = "." elif gwtype == 1: gw = socket.inet_ntop(socket.AF_INET, pkt[position:position + 4]) position += 4 elif gwtype == 2: gw = socket.inet_ntop(socket.AF_INET6, pkt[position:position + 16]) position += 16 elif gwtype == 3: d, position = name_from_wire_message(pkt, position) gw = d.text() if alg == 0: pubkey = "" else: pubkeylen = rdlen - (position - offset) pubkey = base64.standard_b64encode(pkt[position:position + pubkeylen]).decode('ascii') return "{} {} {} {} {}".format(prec, gwtype, alg, gw, pubkey)
def decode_srv_rdata(pkt, offset): """decode SRV rdata: priority (2), weight (2), port, target; RFC 2782""" priority, weight, port = struct.unpack("!HHH", pkt[offset:offset + 6]) d, offset = name_from_wire_message(pkt, offset + 6) target = d.text() return "%d %d %d %s" % (priority, weight, port, target)
def decode_question(self, offset): domainname, offset = name_from_wire_message(self.message, offset) rrtype, rrclass = struct.unpack("!HH", self.message[offset:offset + 4]) offset += 4 return (domainname, rrtype, rrclass, offset)