1 /* $NetBSD: gsstest.c,v 1.9 2015/07/08 17:28:55 christos Exp $ */
4 * Copyright (C) 2006, 2007, 2009-2011, 2013-2015 Internet Systems Consortium, Inc. ("ISC")
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.
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.
19 /* Id: gsstest.c,v 1.19 2011/11/30 00:48:51 marka Exp */
28 #include <isc/base64.h>
29 #include <isc/entropy.h>
32 #include <isc/print.h>
33 #include <isc/sockaddr.h>
34 #include <isc/socket.h>
36 #include <isc/timer.h>
39 #include <dns/dispatch.h>
40 #include <dns/fixedname.h>
41 #include <dns/keyvalues.h>
43 #include <dns/message.h>
45 #include <dns/request.h>
46 #include <dns/result.h>
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>
58 #include <dst/result.h>
61 #include ISC_PLATFORM_GSSAPIHEADER
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)); \
77 static dns_fixedname_t servername
, gssname
;
79 static isc_mem_t
*mctx
;
80 static dns_requestmgr_t
*requestmgr
;
81 static isc_sockaddr_t address
;
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
;
88 #define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
93 static void initctx1(isc_task_t
*task
, isc_event_t
*event
);
94 static void sendquery(isc_task_t
*task
, isc_event_t
*event
);
98 console(isc_task_t
*task
, isc_event_t
*event
)
103 isc_event_t
*ev
= NULL
;
105 isc_event_free(&event
);
108 printf("\nCommand => ");
109 c
= scanf("%31s", buf
);
111 if (c
== EOF
|| strcmp(buf
, "quit") == 0) {
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
);
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
);
130 printf("Unknown command\n");
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
;
141 char output
[10 * 1024];
143 unsigned char array
[DNS_NAME_MAXTEXT
+ 1];
144 isc_buffer_init(&outtoken
, array
, sizeof(array
));
148 REQUIRE(reqev
!= NULL
);
150 query
= reqev
->ev_arg
;
152 if (reqev
->result
!= ISC_R_SUCCESS
) {
153 fprintf(stderr
, "I:request event result: %s\n",
154 isc_result_totext(reqev
->result
));
159 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &response
);
160 CHECK("dns_message_create", result
);
162 printf("\nReceived Response:\n");
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,
169 CHECK("dns_message_totext", result
);
170 printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf
),
171 (char *)isc_buffer_base(&outbuf
));
173 CHECK("dns_request_getresponse", result2
);
175 if (response
!= NULL
)
176 dns_message_destroy(&response
);
180 dns_message_destroy(&query
);
182 if (reqev
->request
!= NULL
)
183 dns_request_destroy(&reqev
->request
);
185 isc_event_free(&event
);
187 event
= isc_event_allocate(mctx
, (void *)1, 1, console
, NULL
,
189 isc_task_send(task
, &event
);
195 sendquery(isc_task_t
*task
, isc_event_t
*event
)
197 dns_request_t
*request
= NULL
;
198 dns_message_t
*message
= NULL
;
199 dns_name_t
*qname
= NULL
;
200 dns_rdataset_t
*qrdataset
= NULL
;
202 dns_fixedname_t queryname
;
205 char output
[10 * 1024];
206 static char host
[256];
209 isc_event_free(&event
);
212 c
= scanf("%255s", host
);
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
);
223 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
, &message
);
224 if (result
!= ISC_R_SUCCESS
)
227 message
->opcode
= dns_opcode_query
;
228 message
->rdclass
= dns_rdataclass_in
;
229 message
->id
= (unsigned short)(random() & 0xFFFF);
231 result
= dns_message_gettempname(message
, &qname
);
232 if (result
!= ISC_R_SUCCESS
)
235 result
= dns_message_gettemprdataset(message
, &qrdataset
);
236 if (result
!= ISC_R_SUCCESS
)
239 dns_name_init(qname
, NULL
);
240 dns_name_clone(dns_fixedname_name(&queryname
), qname
);
241 dns_rdataset_makequestion(qrdataset
, dns_rdataclass_in
,
243 ISC_LIST_APPEND(qname
->list
, qrdataset
, link
);
244 dns_message_addname(message
, qname
, DNS_SECTION_QUESTION
);
246 result
= dns_request_create(requestmgr
, message
, &address
, 0, tsigkey
,
247 TIMEOUT
, task
, recvresponse
,
249 CHECK("dns_request_create", result
);
251 printf("Submitting query:\n");
252 isc_buffer_init(&outbuf
, output
, sizeof(output
));
253 result
= dns_message_totext(message
, &dns_master_style_debug
, 0,
255 CHECK("dns_message_totext", result
);
256 printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf
),
257 (char *)isc_buffer_base(&outbuf
));
263 dns_message_puttempname(message
, &qname
);
264 if (qrdataset
!= NULL
)
265 dns_message_puttemprdataset(message
, &qrdataset
);
267 dns_message_destroy(&message
);
271 initctx2(isc_task_t
*task
, isc_event_t
*event
) {
272 dns_requestevent_t
*reqev
= (dns_requestevent_t
*)event
;
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
;
283 REQUIRE(reqev
!= NULL
);
285 query
= reqev
->ev_arg
;
287 if (reqev
->result
!= ISC_R_SUCCESS
) {
288 fprintf(stderr
, "I:request event result: %s\n",
289 isc_result_totext(reqev
->result
));
294 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &response
);
295 CHECK("dns_message_create", result
);
297 result
= dns_request_getresponse(reqev
->request
, response
,
298 DNS_MESSAGEPARSE_PRESERVEORDER
);
299 CHECK("dns_request_getresponse", result
);
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
));
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
),
313 &tsigkey
, ring
, NULL
);
315 CHECK("dns_tkey_processgssresponse", result
);
316 printf("Context accepted\n");
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");
327 printf("Did not receive TKEY response from server\n");
328 printf("Context not completed\n");
329 dns_tsigkey_detach(&tsigkey
);
333 dns_message_destroy(&response
);
337 dns_message_destroy(&query
);
339 if (reqev
->request
!= NULL
)
340 dns_request_destroy(&reqev
->request
);
342 isc_event_free(&event
);
344 event
= isc_event_allocate(mctx
, (void *)1, 1, console
, NULL
,
346 isc_task_send(task
, &event
);
351 initctx1(isc_task_t
*task
, isc_event_t
*event
) {
353 char contextname
[512];
356 dns_message_t
*query
;
357 dns_request_t
*request
;
360 isc_event_free(&event
);
362 printf("Initctx - GSS name => ");
363 c
= scanf("%511s", gssid
);
367 snprintf(contextname
, sizeof(contextname
),
368 "gsstest.context.%d.", (int)time(NULL
));
370 printf("Initctx - context name we're using: %s\n", contextname
);
372 printf("Negotiating GSSAPI context: ");
377 * Setup a GSSAPI context with the server
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
);
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
);
395 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
, &query
);
396 CHECK("dns_message_create", result
);
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
,
404 CHECK("dns_tkey_buildgssquery", result
);
406 printf("Sending context token to server\n");
408 result
= dns_request_create(requestmgr
, query
, &address
, 0, NULL
,
409 TIMEOUT
, task
, initctx2
, query
, &request
);
410 CHECK("dns_request_create", result
);
414 event
= isc_event_allocate(mctx
, (void *)1, 1, console
, NULL
,
416 isc_task_send(task
, &event
);return;
423 char serveraddress
[512];
424 struct in_addr inaddr
;
427 printf("Server IP => ");
428 c
= scanf("%511s", serveraddress
);
430 if (c
== EOF
|| strcmp(serveraddress
, "quit") == 0) {
435 if (inet_pton(AF_INET
, serveraddress
, &inaddr
) == 1) {
436 isc_sockaddr_fromin(&address
, &inaddr
, PORT
);
444 main(int argc
, char *argv
[]) {
445 isc_taskmgr_t
*taskmgr
;
446 isc_timermgr_t
*timermgr
;
447 isc_socketmgr_t
*socketmgr
;
449 unsigned int attrs
, attrmask
;
450 isc_sockaddr_t bind_any
;
451 dns_dispatchmgr_t
*dispatchmgr
;
452 dns_dispatch_t
*dispatchv4
;
456 isc_log_t
*lctx
= NULL
;
457 isc_logconfig_t
*lcfg
= NULL
;
458 isc_logdestination_t destination
;
463 RUNCHECK(isc_app_start());
465 dns_result_register();
468 RUNCHECK(isc_mem_create(0, 0, &mctx
));
470 RUNCHECK(isc_log_create(mctx
, &lctx
, &lcfg
));
471 isc_log_setcontext(lctx
);
473 dns_log_setcontext(lctx
);
476 * Create and install the default channel.
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",
485 &destination
, ISC_LOG_PRINTTIME
));
486 RUNCHECK(isc_log_usechannel(lcfg
, "_default", NULL
, NULL
));
488 isc_log_setdebuglevel(lctx
, 9);
491 RUNCHECK(isc_entropy_create(mctx
, &ectx
));
492 RUNCHECK(isc_entropy_createfilesource(ectx
, "/dev/urandom"));
494 RUNCHECK(dst_lib_init(mctx
, ectx
, ISC_ENTROPY_GOODONLY
));
497 RUNCHECK(isc_taskmgr_create(mctx
, 1, 0, &taskmgr
));
499 RUNCHECK(isc_task_create(taskmgr
, 0, &task
));
501 RUNCHECK(isc_timermgr_create(mctx
, &timermgr
));
503 RUNCHECK(isc_socketmgr_create(mctx
, &socketmgr
));
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
;
515 RUNCHECK(dns_dispatch_getudp(dispatchmgr
, socketmgr
, taskmgr
,
516 &bind_any
, 4096, 4, 2, 3, 5,
517 attrs
, attrmask
, &dispatchv4
));
519 RUNCHECK(dns_requestmgr_create(mctx
, timermgr
, socketmgr
, taskmgr
,
520 dispatchmgr
, dispatchv4
, NULL
,
524 RUNCHECK(dns_tsigkeyring_create(mctx
, &ring
));
527 RUNCHECK(dns_view_create(mctx
, 0, "_test", &view
));
528 dns_view_setkeyring(view
, ring
);
531 RUNCHECK(isc_socket_create(socketmgr
, PF_INET
, isc_sockettype_udp
,
536 RUNCHECK(isc_app_onrun(mctx
, task
, console
, NULL
));
541 dns_tsigkey_detach(&tsigkey
);
543 dns_requestmgr_shutdown(requestmgr
);
544 dns_requestmgr_detach(&requestmgr
);
546 dns_dispatch_detach(&dispatchv4
);
547 dns_dispatchmgr_destroy(&dispatchmgr
);
549 isc_timermgr_destroy(&timermgr
);
551 isc_task_detach(&task
);
552 isc_taskmgr_destroy(&taskmgr
);
554 isc_socket_detach(&sock
);
555 isc_socketmgr_destroy(&socketmgr
);
557 isc_mem_stats(mctx
, stdout
);
559 dns_view_detach(&view
);
562 isc_entropy_detach(&ectx
);
564 isc_mem_stats(mctx
, stdout
);
565 isc_mem_destroy(&mctx
);
573 main(int argc
, char *argv
[]) {
576 fprintf(stderr
, "R:GSSAPIONLY\n");