xref: /minix/external/bsd/bind/dist/bin/tests/dst/gsstest.c (revision fb9c64b2)
1 /*	$NetBSD: gsstest.c,v 1.9 2015/07/08 17:28:55 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2006, 2007, 2009-2011, 2013-2015  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /* Id: gsstest.c,v 1.19 2011/11/30 00:48:51 marka Exp  */
20 
21 #include <config.h>
22 
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 
27 #include <isc/app.h>
28 #include <isc/base64.h>
29 #include <isc/entropy.h>
30 #include <isc/log.h>
31 #include <isc/mem.h>
32 #include <isc/print.h>
33 #include <isc/sockaddr.h>
34 #include <isc/socket.h>
35 #include <isc/task.h>
36 #include <isc/timer.h>
37 #include <isc/util.h>
38 
39 #include <dns/dispatch.h>
40 #include <dns/fixedname.h>
41 #include <dns/keyvalues.h>
42 #include <dns/log.h>
43 #include <dns/message.h>
44 #include <dns/name.h>
45 #include <dns/request.h>
46 #include <dns/result.h>
47 #include <dns/tkey.h>
48 #include <dns/tsig.h>
49 #include <dns/view.h>
50 
51 #include <dns/dnssec.h>
52 #include <dns/events.h>
53 #include <dns/masterdump.h>
54 #include <dns/rdataset.h>
55 #include <dns/resolver.h>
56 #include <dns/types.h>
57 
58 #include <dst/result.h>
59 
60 #ifdef GSSAPI
61 #include ISC_PLATFORM_GSSAPIHEADER
62 
63 struct dst_context {
64 	unsigned int magic;
65 	dst_key_t *key;
66 	isc_mem_t *mctx;
67 	void *opaque;
68 };
69 
70 #define CHECK(str, x) { \
71 	if ((x) != ISC_R_SUCCESS) { \
72 		fprintf(stderr, "I:%d:%s: %s\n", __LINE__, (str), isc_result_totext(x)); \
73 		goto end; \
74 	} \
75 }
76 
77 static dns_fixedname_t servername, gssname;
78 
79 static isc_mem_t *mctx;
80 static dns_requestmgr_t *requestmgr;
81 static isc_sockaddr_t address;
82 
83 static dns_tsig_keyring_t *ring;
84 static dns_tsigkey_t *tsigkey = NULL;
85 static gss_ctx_id_t gssctx;
86 static gss_ctx_id_t *gssctxp = &gssctx;
87 
88 #define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
89 
90 #define PORT 53
91 #define TIMEOUT 30
92 
93 static void initctx1(isc_task_t *task, isc_event_t *event);
94 static void sendquery(isc_task_t *task, isc_event_t *event);
95 static void setup();
96 
97 static void
98 console(isc_task_t *task, isc_event_t *event)
99 {
100 	char buf[32];
101 	int c;
102 
103 	isc_event_t *ev = NULL;
104 
105 	isc_event_free(&event);
106 
107 	for (;;) {
108 		printf("\nCommand => ");
109 		c = scanf("%31s", buf);
110 
111 		if (c == EOF || strcmp(buf, "quit") == 0) {
112 			isc_app_shutdown();
113 			return;
114 		}
115 
116 		if (strcmp(buf, "initctx") == 0) {
117 			ev = isc_event_allocate(mctx, (void *)1, 1, initctx1,
118 						NULL, sizeof(*event));
119 			isc_task_send(task, &ev);
120 			return;
121 		}
122 
123 		if (strcmp(buf, "query") == 0) {
124 			ev = isc_event_allocate(mctx, (void *)1, 1, sendquery,
125 						NULL, sizeof(*event));
126 			isc_task_send(task, &ev);
127 			return;
128 		}
129 
130 		printf("Unknown command\n");
131 	}
132 }
133 
134 static void
135 recvresponse(isc_task_t *task, isc_event_t *event) {
136 	dns_requestevent_t *reqev = (dns_requestevent_t *)event;
137 	isc_result_t result, result2;
138 	dns_message_t *query = NULL, *response = NULL;
139 	isc_buffer_t outtoken;
140 	isc_buffer_t outbuf;
141 	char output[10 * 1024];
142 
143 	unsigned char array[DNS_NAME_MAXTEXT + 1];
144 	isc_buffer_init(&outtoken, array, sizeof(array));
145 
146 	UNUSED(task);
147 
148 	REQUIRE(reqev != NULL);
149 
150 	query = reqev->ev_arg;
151 
152 	if (reqev->result != ISC_R_SUCCESS) {
153 		fprintf(stderr, "I:request event result: %s\n",
154 			isc_result_totext(reqev->result));
155 		goto end;
156 	}
157 
158 	response = NULL;
159 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
160 	CHECK("dns_message_create", result);
161 
162 	printf("\nReceived Response:\n");
163 
164 	result2 = dns_request_getresponse(reqev->request, response,
165 					 DNS_MESSAGEPARSE_PRESERVEORDER);
166 	isc_buffer_init(&outbuf, output, sizeof(output));
167 	result = dns_message_totext(response, &dns_master_style_debug, 0,
168 				    &outbuf);
169 	CHECK("dns_message_totext", result);
170 	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
171 	       (char *)isc_buffer_base(&outbuf));
172 
173 	CHECK("dns_request_getresponse", result2);
174 
175 	if (response != NULL)
176 		dns_message_destroy(&response);
177 
178  end:
179 	if (query != NULL)
180 		dns_message_destroy(&query);
181 
182 	if (reqev->request != NULL)
183 		dns_request_destroy(&reqev->request);
184 
185 	isc_event_free(&event);
186 
187 	event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
188 				   sizeof(*event));
189 	isc_task_send(task, &event);
190 	return;
191 }
192 
193 
194 static void
195 sendquery(isc_task_t *task, isc_event_t *event)
196 {
197 	dns_request_t *request = NULL;
198 	dns_message_t *message = NULL;
199 	dns_name_t *qname = NULL;
200 	dns_rdataset_t *qrdataset = NULL;
201 	isc_result_t result;
202 	dns_fixedname_t queryname;
203 	isc_buffer_t buf;
204 	isc_buffer_t outbuf;
205 	char output[10 * 1024];
206 	static char host[256];
207 	int c;
208 
209 	isc_event_free(&event);
210 
211 	printf("Query => ");
212 	c = scanf("%255s", host);
213 	if (c == EOF)
214 		return;
215 
216 	dns_fixedname_init(&queryname);
217 	isc_buffer_init(&buf, host, strlen(host));
218 	isc_buffer_add(&buf, strlen(host));
219 	result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf,
220 				   dns_rootname, 0, NULL);
221 	CHECK("dns_name_fromtext", result);
222 
223 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
224 	if (result != ISC_R_SUCCESS)
225 		goto end;
226 
227 	message->opcode = dns_opcode_query;
228 	message->rdclass = dns_rdataclass_in;
229 	message->id = (unsigned short)(random() & 0xFFFF);
230 
231 	result = dns_message_gettempname(message, &qname);
232 	if (result != ISC_R_SUCCESS)
233 		goto end;
234 
235 	result = dns_message_gettemprdataset(message, &qrdataset);
236 	if (result != ISC_R_SUCCESS)
237 		goto end;
238 
239 	dns_name_init(qname, NULL);
240 	dns_name_clone(dns_fixedname_name(&queryname), qname);
241 	dns_rdataset_makequestion(qrdataset, dns_rdataclass_in,
242 				  dns_rdatatype_a);
243 	ISC_LIST_APPEND(qname->list, qrdataset, link);
244 	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
245 
246 	result = dns_request_create(requestmgr, message, &address, 0, tsigkey,
247 				    TIMEOUT, task, recvresponse,
248 		message, &request);
249 	CHECK("dns_request_create", result);
250 
251 	printf("Submitting query:\n");
252 	isc_buffer_init(&outbuf, output, sizeof(output));
253 	result = dns_message_totext(message, &dns_master_style_debug, 0,
254 				    &outbuf);
255 	CHECK("dns_message_totext", result);
256 	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
257 	       (char *)isc_buffer_base(&outbuf));
258 
259 	return;
260 
261  end:
262 	if (qname != NULL)
263 		dns_message_puttempname(message, &qname);
264 	if (qrdataset != NULL)
265 		dns_message_puttemprdataset(message, &qrdataset);
266 	if (message != NULL)
267 		dns_message_destroy(&message);
268 }
269 
270 static void
271 initctx2(isc_task_t *task, isc_event_t *event) {
272 	dns_requestevent_t *reqev = (dns_requestevent_t *)event;
273 	isc_result_t result;
274 	dns_message_t *query = NULL, *response = NULL;
275 	isc_buffer_t outtoken;
276 	unsigned char array[DNS_NAME_MAXTEXT + 1];
277 	dns_rdataset_t *rdataset;
278 	dns_rdatatype_t qtype;
279 	dns_name_t *question_name;
280 
281 	UNUSED(task);
282 
283 	REQUIRE(reqev != NULL);
284 
285 	query = reqev->ev_arg;
286 
287 	if (reqev->result != ISC_R_SUCCESS) {
288 		fprintf(stderr, "I:request event result: %s\n",
289 			isc_result_totext(reqev->result));
290 		goto end;
291 	}
292 
293 	response = NULL;
294 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
295 	CHECK("dns_message_create", result);
296 
297 	result = dns_request_getresponse(reqev->request, response,
298 					 DNS_MESSAGEPARSE_PRESERVEORDER);
299 	CHECK("dns_request_getresponse", result);
300 
301 	if (response->rcode != dns_rcode_noerror) {
302 		result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
303 		fprintf(stderr, "I:response rcode: %s\n",
304 			isc_result_totext(result));
305 		goto end;
306 	}
307 
308 	printf("Received token from server, calling gss_init_sec_context()\n");
309 	isc_buffer_init(&outtoken, array, DNS_NAME_MAXTEXT + 1);
310 	result = dns_tkey_processgssresponse(query, response,
311 					     dns_fixedname_name(&gssname),
312 					     &gssctx, &outtoken,
313 					     &tsigkey, ring, NULL);
314 	gssctx = *gssctxp;
315 	CHECK("dns_tkey_processgssresponse", result);
316 	printf("Context accepted\n");
317 
318 	question_name = NULL;
319 	dns_message_currentname(response, DNS_SECTION_ANSWER, &question_name);
320 	rdataset = ISC_LIST_HEAD(question_name->list);
321 	INSIST(rdataset != NULL);
322 	qtype = rdataset->type;
323 	if (qtype == dns_rdatatype_tkey) {
324 		printf("Received TKEY response from server\n");
325 		printf("Context completed\n");
326 	} else {
327 		printf("Did not receive TKEY response from server\n");
328 		printf("Context not completed\n");
329 		dns_tsigkey_detach(&tsigkey);
330 		tsigkey = NULL;
331 	}
332 
333 	dns_message_destroy(&response);
334 
335  end:
336 	if (query != NULL)
337 		dns_message_destroy(&query);
338 
339 	if (reqev->request != NULL)
340 		dns_request_destroy(&reqev->request);
341 
342 	isc_event_free(&event);
343 
344 	event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
345 				   sizeof(*event));
346 	isc_task_send(task, &event);
347 	return;
348 }
349 
350 static void
351 initctx1(isc_task_t *task, isc_event_t *event) {
352 	char gssid[512];
353 	char contextname[512];
354 	isc_result_t result;
355 	isc_buffer_t buf;
356 	dns_message_t *query;
357 	dns_request_t *request;
358 	int c;
359 
360 	isc_event_free(&event);
361 
362 	printf("Initctx - GSS name => ");
363 	c = scanf("%511s", gssid);
364 	if (c == EOF)
365 		return;
366 
367 	snprintf(contextname, sizeof(contextname),
368 		 "gsstest.context.%d.", (int)time(NULL));
369 
370 	printf("Initctx - context name we're using: %s\n", contextname);
371 
372 	printf("Negotiating GSSAPI context: ");
373 	printf("%s", gssid);
374 	printf("\n");
375 
376 	/*
377 	 * Setup a GSSAPI context with the server
378 	 */
379 	dns_fixedname_init(&servername);
380 	isc_buffer_init(&buf, contextname, strlen(contextname));
381 	isc_buffer_add(&buf, strlen(contextname));
382 	result = dns_name_fromtext(dns_fixedname_name(&servername), &buf,
383 				   dns_rootname, 0, NULL);
384 	CHECK("dns_name_fromtext", result);
385 
386 	/* Make name happen */
387 	dns_fixedname_init(&gssname);
388 	isc_buffer_init(&buf, gssid, strlen(gssid));
389 	isc_buffer_add(&buf, strlen(gssid));
390 	result = dns_name_fromtext(dns_fixedname_name(&gssname), &buf,
391 				   dns_rootname, 0, NULL);
392 	CHECK("dns_name_fromtext", result);
393 
394 	query = NULL;
395 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
396 	CHECK("dns_message_create", result);
397 
398 	printf("Calling gss_init_sec_context()\n");
399 	gssctx = GSS_C_NO_CONTEXT;
400 	result = dns_tkey_buildgssquery(query, dns_fixedname_name(&servername),
401 					dns_fixedname_name(&gssname),
402 					NULL, 36000, &gssctx, ISC_TRUE,
403 					mctx, NULL);
404 	CHECK("dns_tkey_buildgssquery", result);
405 
406 	printf("Sending context token to server\n");
407 	request = NULL;
408 	result = dns_request_create(requestmgr, query, &address, 0, NULL,
409 				    TIMEOUT, task, initctx2, query, &request);
410 	CHECK("dns_request_create", result);
411 
412 	return;
413  end:
414 	event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
415 				   sizeof(*event));
416 	isc_task_send(task, &event);return;
417 }
418 
419 static void
420 setup(void)
421 {
422 	for (;;) {
423 		char serveraddress[512];
424 		struct in_addr inaddr;
425 		int c;
426 
427 		printf("Server IP => ");
428 		c = scanf("%511s", serveraddress);
429 
430 		if (c == EOF || strcmp(serveraddress, "quit") == 0) {
431 			isc_app_shutdown();
432 			return;
433 		}
434 
435 		if (inet_pton(AF_INET, serveraddress, &inaddr) == 1) {
436 			isc_sockaddr_fromin(&address, &inaddr, PORT);
437 			return;
438 		}
439 
440 	}
441 }
442 
443 int
444 main(int argc, char *argv[]) {
445 	isc_taskmgr_t *taskmgr;
446 	isc_timermgr_t *timermgr;
447 	isc_socketmgr_t *socketmgr;
448 	isc_socket_t *sock;
449 	unsigned int attrs, attrmask;
450 	isc_sockaddr_t bind_any;
451 	dns_dispatchmgr_t *dispatchmgr;
452 	dns_dispatch_t *dispatchv4;
453 	dns_view_t *view;
454 	isc_entropy_t *ectx;
455 	isc_task_t *task;
456 	isc_log_t *lctx = NULL;
457 	isc_logconfig_t *lcfg = NULL;
458 	isc_logdestination_t destination;
459 
460 	UNUSED(argv);
461 	UNUSED(argc);
462 
463 	RUNCHECK(isc_app_start());
464 
465 	dns_result_register();
466 
467 	mctx = NULL;
468 	RUNCHECK(isc_mem_create(0, 0, &mctx));
469 
470 	RUNCHECK(isc_log_create(mctx, &lctx, &lcfg));
471 	isc_log_setcontext(lctx);
472 	dns_log_init(lctx);
473 	dns_log_setcontext(lctx);
474 
475 	/*
476 	 * Create and install the default channel.
477 	 */
478 	destination.file.stream = stderr;
479 	destination.file.name = NULL;
480 	destination.file.versions = ISC_LOG_ROLLNEVER;
481 	destination.file.maximum_size = 0;
482 	RUNCHECK(isc_log_createchannel(lcfg, "_default",
483 				       ISC_LOG_TOFILEDESC,
484 				       ISC_LOG_DYNAMIC,
485 				       &destination, ISC_LOG_PRINTTIME));
486 	RUNCHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL));
487 
488 	isc_log_setdebuglevel(lctx, 9);
489 
490 	ectx = NULL;
491 	RUNCHECK(isc_entropy_create(mctx, &ectx));
492 	RUNCHECK(isc_entropy_createfilesource(ectx, "/dev/urandom"));
493 
494 	RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
495 
496 	taskmgr = NULL;
497 	RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
498 	task = NULL;
499 	RUNCHECK(isc_task_create(taskmgr, 0, &task));
500 	timermgr = NULL;
501 	RUNCHECK(isc_timermgr_create(mctx, &timermgr));
502 	socketmgr = NULL;
503 	RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
504 	dispatchmgr = NULL;
505 	RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr));
506 	isc_sockaddr_any(&bind_any);
507 	attrs = DNS_DISPATCHATTR_UDP |
508 		DNS_DISPATCHATTR_MAKEQUERY |
509 		DNS_DISPATCHATTR_IPV4;
510 	attrmask = DNS_DISPATCHATTR_UDP |
511 		   DNS_DISPATCHATTR_TCP |
512 		   DNS_DISPATCHATTR_IPV4 |
513 		   DNS_DISPATCHATTR_IPV6;
514 	dispatchv4 = NULL;
515 	RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
516 					  &bind_any, 4096, 4, 2, 3, 5,
517 					  attrs, attrmask, &dispatchv4));
518 	requestmgr = NULL;
519 	RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
520 					    dispatchmgr, dispatchv4, NULL,
521 					    &requestmgr));
522 
523 	ring = NULL;
524 	RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
525 
526 	view = NULL;
527 	RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
528 	dns_view_setkeyring(view, ring);
529 
530 	sock = NULL;
531 	RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
532 				   &sock));
533 
534 	setup();
535 
536 	RUNCHECK(isc_app_onrun(mctx, task, console, NULL));
537 
538 	(void)isc_app_run();
539 
540 	if (tsigkey)
541 		dns_tsigkey_detach(&tsigkey);
542 
543 	dns_requestmgr_shutdown(requestmgr);
544 	dns_requestmgr_detach(&requestmgr);
545 
546 	dns_dispatch_detach(&dispatchv4);
547 	dns_dispatchmgr_destroy(&dispatchmgr);
548 
549 	isc_timermgr_destroy(&timermgr);
550 
551 	isc_task_detach(&task);
552 	isc_taskmgr_destroy(&taskmgr);
553 
554 	isc_socket_detach(&sock);
555 	isc_socketmgr_destroy(&socketmgr);
556 
557 	isc_mem_stats(mctx, stdout);
558 
559 	dns_view_detach(&view);
560 
561 	dst_lib_destroy();
562 	isc_entropy_detach(&ectx);
563 
564 	isc_mem_stats(mctx, stdout);
565 	isc_mem_destroy(&mctx);
566 
567 	isc_app_finish();
568 
569 	return (0);
570 }
571 #else
572 int
573 main(int argc, char *argv[]) {
574 	UNUSED(argc);
575 	UNUSED(argv);
576 	fprintf(stderr, "R:GSSAPIONLY\n");
577 	return (0);
578 }
579 #endif
580