xref: /netbsd-src/external/mpl/bind/dist/fuzz/dns_message_checksig.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: dns_message_checksig.c,v 1.3 2025/01/26 16:25:20 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 #include <inttypes.h>
17 #include <stdbool.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 
21 #include <isc/buffer.h>
22 #include <isc/commandline.h>
23 #include <isc/file.h>
24 #include <isc/mem.h>
25 #include <isc/result.h>
26 #include <isc/string.h>
27 #include <isc/tid.h>
28 #include <isc/util.h>
29 
30 #include <dns/fixedname.h>
31 #include <dns/message.h>
32 #include <dns/name.h>
33 #include <dns/rcode.h>
34 #include <dns/tsig.h>
35 #include <dns/view.h>
36 #include <dns/zone.h>
37 
38 #include "fuzz.h"
39 
40 bool debug = false;
41 
42 static isc_mem_t *mctx = NULL;
43 
44 /*
45  *	Packet dumps of validily signed request ./IN/SOA
46  *	requests.
47  *
48  *	TSIG:
49  *
50  *	0x0000:  600b 0900 006a 1140 0000 0000 0000 0000
51  *	0x0010:  0000 0000 0000 0001 0000 0000 0000 0000
52  *	0x0020:  0000 0000 0000 0001 cc88 0035 006a 007d
53  *	0x0030:  1dfa 0000 0001 0000 0000 0001 0000 0600
54  *	0x0040:  0108 7473 6967 2d6b 6579 0000 fa00 ff00
55  *	0x0050:  0000 0000 3d0b 686d 6163 2d73 6861 3235
56  *	0x0060:  3600 0000 622a cce1 012c 0020 224d 5807
57  *	0x0070:  648d 1400 9d8e fc1c d049 55e9 cc90 2187
58  *	0x0080:  3b5f af5c 8899 dc27 c8df b34b 1dfa 0000
59  *	0x0090:  0000
60  *
61  *	SIG(0):
62  *
63  *	0x0000:  6004 0e00 013f 1140 0000 0000 0000 0000
64  *	0x0010:  0000 0000 0000 0001 0000 0000 0000 0000
65  *	0x0020:  0000 0000 0000 0001 c0a7 0035 013f 0152
66  *	0x0030:  0000 0000 0001 0000 0000 0001 0000 0600
67  *	0x0040:  0100 0018 00ff 0000 0000 011b 0000 0800
68  *	0x0050:  0000 0000 622a ce0d 622a cbb5 da71 0773
69  *	0x0060:  6967 306b 6579 0068 988b 27bf 5c89 5270
70  *	0x0070:  c5ba ea8b 2e10 0512 9b44 48d3 69de b7ec
71  *	0x0080:  7c67 15f3 6bc7 b0dc 277b e8f1 6979 4c89
72  *	0x0090:  149a 0203 30a1 c0b7 a711 ee8a 8d90 ebb9
73  *	0x00a0:  9e33 dd65 33d5 5d1d 90db cf9c bb6a b346
74  *	0x00b0:  568f a399 71d7 c877 616d 2fb7 0f86 963f
75  *	0x00c0:  aa00 850d 180a 9f83 cd4b d115 c79f 64c9
76  *	0x00d0:  ff05 e751 6810 28b3 2249 c4ba 2d8d 57ba
77  *	0x00e0:  9aad f1fc b34e c237 9465 04fd fe4d 19c9
78  *	0x00f0:  2368 ec8e 7097 eaea e067 2b9c 06eb c383
79  *	0x0100:  e901 a11e 606b 4cce c12a 0e57 8c09 b7cb
80  *	0x0110:  23bb ec05 b68b 1852 9288 b665 fe89 cf62
81  *	0x0120:  0a41 5e5a acbe 6903 cbb7 e7b6 cab4 e4a2
82  *	0x0130:  b98f 884f c09d 5b39 c695 c84c 9a92 f110
83  *	0x0140:  ccc3 f2ee 313f a2a1 1cda 5aa2 faec d593
84  *	0x0150:  4514 724a 868f 94b9 0547 4dc9 7b73 c85e
85  *	0x0160:  544c 73d4 e892 f9
86  */
87 
88 #define HMACSHA256 "\x0bhmac-sha256"
89 
90 static isc_stdtime_t fuzztime = 0x622acce1;
91 static isc_loopmgr_t *loopmgr = NULL;
92 static dns_view_t *view = NULL;
93 static dns_tsigkey_t *tsigkey = NULL;
94 static dns_tsigkeyring_t *ring = NULL;
95 static dns_tsigkeyring_t *emptyring = NULL;
96 static char *wd = NULL;
97 static char template[] = "/tmp/dns-message-checksig-XXXXXX";
98 
99 static char f1[] = "Ksig0key.+008+55921.key";
100 static char c1[] = "sig0key. IN KEY 512 3 8 "
101 		   "AwEAAa22lgHi1vAbQvu5ETdTrm2H8rwga9tvyMa6LFiSDyevLvSv0Uo5 "
102 		   "uvfrXnxaLdtBMts6e1Ly2piSH9JRbOGMNibOK4EXWhWAn8MII4SWgQAs "
103 		   "bFwtiz4HyPn2wScrUQdo8DocKiQJBanesr7vDO8fdA6Rg1e0yAtSeNti "
104 		   "e8avx46/HJa6CFs3CoE0sf6oOFSxM954AgCBTXOGNBt1Nt3Bhfqt2qyA "
105 		   "TLFii5K1jLDTZDVkoiyDXL1M7wcTwKf9METgj1eQmH3GGlRM/OJ/j8xk "
106 		   "ZiFGbL3cipWdiH48031jiV2hlc92mKn8Ya0d9AN6c44piza/JSFydZXw "
107 		   "sY32nxzjDbs=\n";
108 
109 static char f2[] = "Ksig0key.+008+55921.private";
110 static char c2[] = "Private-key-format: v1.3\n\
111 Algorithm: 8 (RSASHA256)\n\
112 Modulus: rbaWAeLW8BtC+7kRN1OubYfyvCBr22/IxrosWJIPJ68u9K/RSjm69+tefFot20Ey2zp7UvLamJIf0lFs4Yw2Js4rgRdaFYCfwwgjhJaBACxsXC2LPgfI+fbBJytRB2jwOhwqJAkFqd6yvu8M7x90DpGDV7TIC1J422J7xq/Hjr8clroIWzcKgTSx/qg4VLEz3ngCAIFNc4Y0G3U23cGF+q3arIBMsWKLkrWMsNNkNWSiLINcvUzvBxPAp/0wROCPV5CYfcYaVEz84n+PzGRmIUZsvdyKlZ2IfjzTfWOJXaGVz3aYqfxhrR30A3pzjimLNr8lIXJ1lfCxjfafHOMNuw==\n\
113 PublicExponent: AQAB\n\
114 PrivateExponent: GDfclFkR5ToFGH9rMTRMnP73Q5dzjLgkx4vyHcuzKtxcvAans4+hNj+NazckAy2E+mpzV2j95TJ4wZjSM2RvB5xLwBIc4Dg6oyAHL6Ikoae6gw64cHFOaYb808n8CyqWqfX+QWAz9sRSVZXnTuPViX3A+svR7ejVak9Bzr1NTDm0DFlrhaKVCYA++dKVZerfuNiXT/jQvrc4wMCa7WWsfLsFO8aTNkEhqUnmS9c5VYgr7MkCV4ENDBcISpQc9wElI0hl12QPaSj8iSdk9liYp+HTiOxOyp6BGGuecKAoQijMwrZy4qExdOxvowptll8+nZLtwGRn/un/xvIZY5OLAQ==\n\
115 Prime1: ww3C6jwnrLQik/zxSgC0KuqgHq68cCjiRjwK2/euzs7NkMevFpXvV0cWO8x1/wKC1mszVLsUaKTvH6fzRsXfz5MPihzNzUYFwvobKVLserSxEwHNk+FKUU+q07Kf8WWnCqX5nX9QzVG1q4J8Q44N49I5S480jHLGYbyLZrEYMQE=\n\
116 Prime2: 4/3Ozq/8vRgcO4bieFs4CbZR7C98HiTi65SiLBIKY09mDfCleZI0uurAYBluZJgHS5AC5cdyHFuJr3uKxvD+Mgdlru40U6cSCEdK7HAhyUGZUndWl28wyMEB6Kke1/owxVn0S4RKLPOgFI2668H6JObaqXf0wyY89RdVQP6VQrs=\n\
117 Exponent1: Tbr9MyVX1j5PDVSev5P6OKQZvUB7PeM9ESo6VaCl3CqTxx+cic6ke86LcLcxSrewdkxwP1LydiVMWfwvOcP/RhRf+/Uwmp5OC35qNpSiQuAhNObiCw2b9T1fYU/s52FQKTEtgXNMOxZV5IxyguVoaaLMTG08TsAqiKZ/kyP99QE=\n\
118 Exponent2: Q4qSNKrwLbixzHS2LL+hR0dK17RtiaSV0QKUVIf3qdoAusp6yxwkIOegnBeMm6JqLtl38kh2pq37iRAJWcxVEc8dMYiB2fJZpjgwmwDREYUsfcC611vqUN7UyO8pIwSMZDq045ZKPyzhVJV0NZmemEYHq0LNMO7oCheiewGwiDc=\n\
119 Coefficient: T2u/J4NgyO+OqoLpXBIpTBzqrvDk8tb0feYgsp5d16hHvbXxNkMUR8cI07RdbI9HnEldtmhAnbQ6SvFiy2YYjpw/1Fz2WwdxRqLaDV7UlhrT+CqltvU9d/N/xThBNKDa23Wf5Vat+HRiLHSgzsY1PseVCWN+g4azuK2D8+DLeHE=\n\
120 Created: 20220311073606\n\
121 Publish: 20220311073606\n\
122 Activate: 20220311073606\n";
123 
124 static char f3[] = "sig0key.db";
125 static char c3[] = "sig0key. 0 IN SOA . . 0 0 0 0 0\n\
126 sig0key. 0 IN NS .\n\
127 sig0key. 0 IN KEY 512 3 8 AwEAAa22lgHi1vAbQvu5ETdTrm2H8rwga9tvyMa6LFiSDyevLvSv0Uo5 uvfrXnxaLdtBMts6e1Ly2piSH9JRbOGMNibOK4EXWhWAn8MII4SWgQAs bFwtiz4HyPn2wScrUQdo8DocKiQJBanesr7vDO8fdA6Rg1e0yAtSeNti e8avx46/HJa6CFs3CoE0sf6oOFSxM954AgCBTXOGNBt1Nt3Bhfqt2qyA TLFii5K1jLDTZDVkoiyDXL1M7wcTwKf9METgj1eQmH3GGlRM/OJ/j8xk ZiFGbL3cipWdiH48031jiV2hlc92mKn8Ya0d9AN6c44piza/JSFydZXw sY32nxzjDbs=\n";
128 
129 static bool destroy_dst = false;
130 
131 int
132 LLVMFuzzerInitialize(int *argc ISC_ATTR_UNUSED, char ***argv ISC_ATTR_UNUSED) {
133 	isc_result_t result;
134 	dns_fixedname_t fixed;
135 	dns_name_t *name = dns_fixedname_initname(&fixed);
136 	unsigned char secret[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
137 				     0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
138 				     0xff, 0xff, 0xff, 0xff };
139 	dns_zone_t *zone = NULL;
140 	char pathbuf[PATH_MAX];
141 	FILE *fd;
142 
143 	wd = mkdtemp(template);
144 	if (wd == NULL) {
145 		fprintf(stderr, "mkdtemp failed\n");
146 		return 1;
147 	}
148 
149 	snprintf(pathbuf, sizeof(pathbuf), "%s/%s", wd, f1);
150 	fd = fopen(pathbuf, "w");
151 	if (fd == NULL) {
152 		fprintf(stderr, "fopen(%s) failed\n", pathbuf);
153 		return 1;
154 	}
155 	fputs(c1, fd);
156 	fclose(fd);
157 
158 	snprintf(pathbuf, sizeof(pathbuf), "%s/%s", wd, f2);
159 	fd = fopen(pathbuf, "w");
160 	if (fd == NULL) {
161 		fprintf(stderr, "fopen(%s) failed\n", pathbuf);
162 		return 1;
163 	}
164 	fputs(c2, fd);
165 	fclose(fd);
166 
167 	snprintf(pathbuf, sizeof(pathbuf), "%s/%s", wd, f3);
168 	fd = fopen(pathbuf, "w");
169 	if (fd == NULL) {
170 		fprintf(stderr, "fopen(%s) failed\n", pathbuf);
171 		return 1;
172 	}
173 	fputs(c3, fd);
174 	fclose(fd);
175 
176 	isc_mem_create(&mctx);
177 
178 	result = dst_lib_init(mctx, NULL);
179 	if (result != ISC_R_SUCCESS) {
180 		fprintf(stderr, "dst_lib_init failed: %s\n",
181 			isc_result_totext(result));
182 		return 1;
183 	}
184 	destroy_dst = true;
185 
186 	isc_loopmgr_create(mctx, 1, &loopmgr);
187 
188 	result = dns_view_create(mctx, loopmgr, NULL, dns_rdataclass_in, "view",
189 				 &view);
190 	if (result != ISC_R_SUCCESS) {
191 		fprintf(stderr, "dns_view_create failed: %s\n",
192 			isc_result_totext(result));
193 		return 1;
194 	}
195 
196 	dns_tsigkeyring_create(mctx, &ring);
197 	dns_tsigkeyring_create(mctx, &emptyring);
198 
199 	result = dns_name_fromstring(name, "tsig-key", dns_rootname, 0, NULL);
200 	if (result != ISC_R_SUCCESS) {
201 		fprintf(stderr, "dns_name_fromstring failed: %s\n",
202 			isc_result_totext(result));
203 		return 1;
204 	}
205 
206 	result = dns_tsigkey_create(name, DST_ALG_HMACSHA256, secret,
207 				    sizeof(secret), mctx, &tsigkey);
208 	if (result != ISC_R_SUCCESS) {
209 		fprintf(stderr, "dns_tsigkey_create failed: %s\n",
210 			isc_result_totext(result));
211 		return 1;
212 	}
213 	result = dns_tsigkeyring_add(ring, tsigkey);
214 	if (result != ISC_R_SUCCESS) {
215 		fprintf(stderr, "dns_tsigkeyring_add failed: %s\n",
216 			isc_result_totext(result));
217 		return 1;
218 	}
219 
220 	result = dns_name_fromstring(name, "sig0key", dns_rootname, 0, NULL);
221 	if (result != ISC_R_SUCCESS) {
222 		fprintf(stderr, "dns_name_fromstring failed: %s\n",
223 			isc_result_totext(result));
224 		return 1;
225 	}
226 
227 	dns_zone_create(&zone, mctx, 0);
228 
229 	result = dns_zone_setorigin(zone, name);
230 	if (result != ISC_R_SUCCESS) {
231 		fprintf(stderr, "dns_zone_setorigin failed: %s\n",
232 			isc_result_totext(result));
233 		return 1;
234 	}
235 
236 	dns_zone_setclass(zone, view->rdclass);
237 	dns_zone_settype(zone, dns_zone_primary);
238 
239 	result = dns_zone_setkeydirectory(zone, wd);
240 	if (result != ISC_R_SUCCESS) {
241 		fprintf(stderr, "dns_zone_setkeydirectory failed: %s\n",
242 			isc_result_totext(result));
243 		return 1;
244 	}
245 
246 	result = dns_zone_setfile(zone, pathbuf, dns_masterformat_text,
247 				  &dns_master_style_default);
248 	if (result != ISC_R_SUCCESS) {
249 		fprintf(stderr, "dns_zone_setfile failed: %s\n",
250 			isc_result_totext(result));
251 		return 1;
252 	}
253 
254 	result = dns_zone_load(zone, false);
255 	if (result != ISC_R_SUCCESS) {
256 		fprintf(stderr, "dns_zone_load failed: %s\n",
257 			isc_result_totext(result));
258 		return 1;
259 	}
260 
261 	result = dns_view_addzone(view, zone);
262 	if (result != ISC_R_SUCCESS) {
263 		fprintf(stderr, "dns_view_addzone failed: %s\n",
264 			isc_result_totext(result));
265 		return 1;
266 	}
267 
268 	dns_zone_setview(zone, view);
269 	dns_view_freeze(view);
270 
271 	dns_zone_detach(&zone);
272 
273 	return 0;
274 }
275 
276 static isc_result_t
277 create_message(dns_message_t **messagep, const uint8_t *data, size_t size,
278 	       bool addasig, bool addtsig) {
279 	isc_result_t result;
280 	dns_message_t *message = NULL;
281 	isc_buffer_t b;
282 	static unsigned char buf[65535];
283 
284 	isc_buffer_init(&b, buf, sizeof(buf));
285 
286 	/* Message ID */
287 	isc_buffer_putuint16(&b, 0);
288 
289 	/* QR, Opcode, other flags = 0, rcode = 0 */
290 	isc_buffer_putuint16(&b, (*data & 0x1f) << 11);
291 	/* Counts */
292 	isc_buffer_putuint16(&b, 1);
293 	isc_buffer_putuint16(&b, 0);
294 	isc_buffer_putuint16(&b, 0);
295 	isc_buffer_putuint16(&b, addasig ? 1 : 0);
296 
297 	/* Question ./IN/SOA */
298 	isc_buffer_putuint8(&b, 0);
299 	isc_buffer_putuint16(&b, 6);
300 	isc_buffer_putuint16(&b, 1);
301 
302 	if (addasig) {
303 		/* Signature */
304 		if (addtsig) {
305 			const unsigned char keyname[] = "\x08tsig-key";
306 			isc_buffer_putmem(&b, keyname, sizeof(keyname));
307 			isc_buffer_putuint16(&b, dns_rdatatype_tsig);
308 			isc_buffer_putuint16(&b, dns_rdataclass_any);
309 		} else {
310 			isc_buffer_putuint8(&b, 0); /* '.' */
311 			isc_buffer_putuint16(&b, dns_rdatatype_sig);
312 			isc_buffer_putuint16(&b, dns_rdataclass_in);
313 		}
314 		isc_buffer_putuint32(&b, 0); /* ttl */
315 		data++;
316 		size--;
317 		if (size > isc_buffer_availablelength(&b) - 2) {
318 			size = isc_buffer_availablelength(&b) - 2;
319 		}
320 		isc_buffer_putuint16(&b, size);
321 		isc_buffer_putmem(&b, data, size);
322 	}
323 
324 	dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &message);
325 
326 	result = dns_message_parse(message, &b, 0);
327 	if (debug) {
328 		fprintf(stderr, "dns_message_parse => %s\n",
329 			isc_result_totext(result));
330 	}
331 	if (result != ISC_R_SUCCESS) {
332 		dns_message_detach(&message);
333 	} else {
334 		if (debug) {
335 			char text[200000];
336 			isc_buffer_init(&b, text, sizeof(text));
337 
338 			result = dns_message_totext(
339 				message, &dns_master_style_debug, 0, &b);
340 			if (result == ISC_R_SUCCESS) {
341 				fprintf(stderr, "%.*s", (int)b.used, text);
342 			} else {
343 				fprintf(stderr, "dns_message_totext => %s\n",
344 					isc_result_totext(result));
345 			}
346 		}
347 		*messagep = message;
348 	}
349 	return result;
350 }
351 
352 int
353 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
354 	isc_result_t result;
355 	dns_message_t *message = NULL;
356 	unsigned char query_tsig[23 + 32 + 6] = { 0 };
357 	bool addasig = false;
358 	bool addtime = false;
359 	bool addtsig = false;
360 	bool setquerytsig = false;
361 	bool settsigkey = false;
362 	bool subtime = false;
363 	bool withring = false;
364 	bool withview = false;
365 
366 	/*
367 	 * The first 2 octets affect setup.
368 	 * Octet 1 determines whether a signature is added and which type
369 	 * (addasig, addtsig), whether time should be adjusted (addtime,
370 	 * subtime), whether dns_message_setquerytsig and dns_message_settsigkey
371 	 * have been called, whether there is a keyring available with the
372 	 * TSIG key or a view is defined.
373 	 *
374 	 * The second octet defines if the message is a response and the
375 	 * opcode.
376 	 */
377 	if (size > 65535 || size < 2) {
378 		return 0;
379 	}
380 
381 	addasig = (*data & 0x80) != 0;
382 	addtime = (*data & 0x40) != 0;
383 	addtsig = (*data & 0x20) != 0;
384 	setquerytsig = (*data & 0x10) != 0;
385 	settsigkey = (*data & 0x08) != 0;
386 	subtime = (*data & 0x04) != 0;
387 	withring = (*data & 0x02) != 0;
388 	withview = (*data & 0x01) != 0;
389 
390 	data++;
391 	size--;
392 
393 	if (debug) {
394 		fprintf(stderr,
395 			"addasig=%u addtime=%u addtsig=%u setquerytsig=%u "
396 			"settsigkey=%u subtime=%u withring=%u\nwithview=%u\n",
397 			addasig, addtime, addtsig, setquerytsig, settsigkey,
398 			subtime, withring, withview);
399 	}
400 
401 	result = create_message(&message, data, size, addasig, addtsig);
402 	if (result != ISC_R_SUCCESS) {
403 		return 0;
404 	}
405 
406 	/*
407 	 * Make time calculations consistent.
408 	 */
409 	message->fuzzing = 1;
410 	message->fuzztime = fuzztime;
411 	if (addtime) {
412 		message->fuzztime += 1200;
413 	}
414 	if (subtime) {
415 		message->fuzztime -= 1200;
416 	}
417 
418 	if ((message->flags & DNS_MESSAGEFLAG_QR) != 0) {
419 		if (setquerytsig) {
420 			isc_buffer_t b;
421 			unsigned char hmacname[] = HMACSHA256;
422 			unsigned char hmacvalue[32] = {
423 				0x22, 0x4d, 0x58, 0x07, 0x64, 0x8d, 0x14, 0x00,
424 				0x9d, 0x8e, 0xfc, 0x1c, 0xd0, 0x49, 0x55, 0xe9,
425 				0xcc, 0x90, 0x21, 0x87, 0x3b, 0x5f, 0xaf, 0x5c,
426 				0x88, 0x99, 0xdc, 0x27, 0xc8, 0xdf, 0xb3, 0x4b
427 			};
428 
429 			/*
430 			 * Valid TSIG rdata for tsig-key over a plain
431 			 * DNS QUERY for ./SOA/IN with no flags set.
432 			 */
433 			isc_buffer_init(&b, query_tsig, sizeof(query_tsig));
434 			isc_buffer_putmem(&b, hmacname, sizeof(hmacname));
435 			isc_buffer_putuint16(&b, 0);	      /* time high */
436 			isc_buffer_putuint32(&b, 0x622abec0); /* time low */
437 			isc_buffer_putuint16(&b, 300);	      /* Fudge */
438 			isc_buffer_putuint16(&b, 32);	      /* Mac Length */
439 			/* Mac */
440 			isc_buffer_putmem(&b, hmacvalue, 32);
441 			isc_buffer_putuint16(&b, 7674); /* Original Id */
442 			isc_buffer_putuint16(&b, 0);	/* Error */
443 			isc_buffer_putuint16(&b, 0);	/* Other len */
444 
445 			dns_message_setquerytsig(message, &b);
446 		}
447 	}
448 
449 	if (settsigkey) {
450 		result = dns_message_settsigkey(message, tsigkey);
451 		if (debug) {
452 			fprintf(stderr, "dns_message_settsigkey => %s\n",
453 				isc_result_totext(result));
454 		}
455 	}
456 
457 	dns_view_setkeyring(view, withring ? ring : emptyring);
458 
459 	result = dns_message_checksig(message, withview ? view : NULL);
460 	if (debug) {
461 		char textbuf[64];
462 		isc_buffer_t b;
463 
464 		fprintf(stderr, "dns_message_checksig => %s\n",
465 			isc_result_totext(result));
466 		isc_buffer_init(&b, textbuf, sizeof(textbuf));
467 		dns_tsigrcode_totext(message->tsigstatus, &b);
468 		fprintf(stderr, "tsigstatus=%.*s\n", (int)b.used, textbuf);
469 		isc_buffer_init(&b, textbuf, sizeof(textbuf));
470 		dns_tsigrcode_totext(message->sig0status, &b);
471 		fprintf(stderr, "sig0status=%.*s\n", (int)b.used, textbuf);
472 	}
473 	if (result != ISC_R_SUCCESS) {
474 		goto cleanup;
475 	}
476 
477 cleanup:
478 	if (message != NULL) {
479 		dns_message_detach(&message);
480 	}
481 
482 	return 0;
483 }
484