def verify_packet(self, response, response_packet, request_mac=b""): self.assertEqual(response.additional[0].rr_type, dns.DNS_QTYPE_TSIG) tsig_record = response.additional[0].rdata mac = binary_type(bytearray(tsig_record.mac)) # Cut off tsig record from dns response packet for MAC verification # and reset additional record count. key_name_len = len(self.key_name) + 2 tsig_record_len = len(ndr.ndr_pack(tsig_record)) + key_name_len + 10 # convert str/bytes to a list (of string char or int) # so it can be modified response_packet_list = [ x if isinstance(x, int) else ord(x) for x in response_packet ] del response_packet_list[-tsig_record_len:] if isinstance(response_packet_list[11], int): response_packet_list[11] = 0 else: response_packet_list[11] = chr(0) # convert modified list (of string char or int) to str/bytes response_packet_wo_tsig = binary_type(bytearray(response_packet_list)) fake_tsig = dns.fake_tsig_rec() fake_tsig.name = self.key_name fake_tsig.rr_class = dns.DNS_QCLASS_ANY fake_tsig.ttl = 0 fake_tsig.time_prefix = tsig_record.time_prefix fake_tsig.time = tsig_record.time fake_tsig.algorithm_name = tsig_record.algorithm_name fake_tsig.fudge = tsig_record.fudge fake_tsig.error = 0 fake_tsig.other_size = 0 fake_tsig_packet = ndr.ndr_pack(fake_tsig) data = request_mac + response_packet_wo_tsig + fake_tsig_packet self.g.check_packet(data, data, mac)
def tkey_trans(self, creds=None): "Do a TKEY transaction and establish a gensec context" if creds is None: creds = self.creds self.key_name = "%s.%s" % (uuid.uuid4(), self.get_dns_domain()) p = self.make_name_packet(dns.DNS_OPCODE_QUERY) q = self.make_name_question(self.key_name, dns.DNS_QTYPE_TKEY, dns.DNS_QCLASS_IN) questions = [] questions.append(q) self.finish_name_packet(p, questions) r = dns.res_rec() r.name = self.key_name r.rr_type = dns.DNS_QTYPE_TKEY r.rr_class = dns.DNS_QCLASS_IN r.ttl = 0 r.length = 0xffff rdata = dns.tkey_record() rdata.algorithm = "gss-tsig" rdata.inception = int(time.time()) rdata.expiration = int(time.time()) + 60 * 60 rdata.mode = dns.DNS_TKEY_MODE_GSSAPI rdata.error = 0 rdata.other_size = 0 self.g = gensec.Security.start_client(self.settings) self.g.set_credentials(creds) self.g.set_target_service("dns") self.g.set_target_hostname(self.server) self.g.want_feature(gensec.FEATURE_SIGN) self.g.start_mech_by_name("spnego") finished = False client_to_server = b"" (finished, server_to_client) = self.g.update(client_to_server) self.assertFalse(finished) data = [ x if isinstance(x, int) else ord(x) for x in list(server_to_client) ] rdata.key_data = data rdata.key_size = len(data) r.rdata = rdata additional = [r] p.arcount = 1 p.additional = additional (response, response_packet) =\ self.dns_transaction_tcp(p, self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) tkey_record = response.answers[0].rdata server_to_client = binary_type(bytearray(tkey_record.key_data)) (finished, client_to_server) = self.g.update(server_to_client) self.assertTrue(finished) self.verify_packet(response, response_packet)