4 * Copyright (C) 2006, 2007, 2009 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.8 2009/09/02 23:48:01 tbox Exp */
27 #include <isc/base64.h>
28 #include <isc/entropy.h>
31 #include <isc/sockaddr.h>
32 #include <isc/socket.h>
34 #include <isc/timer.h>
37 #include <dns/dispatch.h>
38 #include <dns/fixedname.h>
39 #include <dns/keyvalues.h>
41 #include <dns/message.h>
43 #include <dns/request.h>
44 #include <dns/result.h>
49 #include <dns/dnssec.h>
50 #include <dns/events.h>
51 #include <dns/masterdump.h>
52 #include <dns/rdataset.h>
53 #include <dns/resolver.h>
54 #include <dns/types.h>
56 #include <dst/result.h>
59 #include ISC_PLATFORM_GSSAPIHEADER
68 #define CHECK(str, x) { \
69 if ((x) != ISC_R_SUCCESS) { \
70 fprintf(stderr, "I:%d:%s: %s\n", __LINE__, (str), isc_result_totext(x)); \
75 static char contextname
[512];
76 static char gssid
[512];
77 static char serveraddress
[512];
78 static dns_fixedname_t servername
, gssname
;
80 static isc_mem_t
*mctx
;
81 static dns_requestmgr_t
*requestmgr
;
82 static isc_sockaddr_t address
;
84 static dns_tsig_keyring_t
*ring
;
85 static dns_tsigkey_t
*tsigkey
= NULL
;
86 static gss_ctx_id_t gssctx
;
87 static gss_ctx_id_t
*gssctxp
= &gssctx
;
89 #define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
94 static void initctx1(isc_task_t
*task
, isc_event_t
*event
);
95 static void sendquery(isc_task_t
*task
, isc_event_t
*event
);
99 console(isc_task_t
*task
, isc_event_t
*event
)
102 isc_event_t
*ev
= NULL
;
104 isc_event_free(&event
);
107 printf("\nCommand => ");
110 if(strcmp(buf
, "quit") == 0) {
115 if(strcmp(buf
, "initctx") == 0) {
116 ev
= isc_event_allocate(mctx
, (void *)1, 1, initctx1
,
117 NULL
, sizeof(*event
));
118 isc_task_send(task
, &ev
);
122 if(strcmp(buf
, "query") == 0) {
123 ev
= isc_event_allocate(mctx
, (void *)1, 1, sendquery
,
124 NULL
, sizeof(*event
));
125 isc_task_send(task
, &ev
);
129 printf("Unknown command\n");
134 recvresponse(isc_task_t
*task
, isc_event_t
*event
) {
135 dns_requestevent_t
*reqev
= (dns_requestevent_t
*)event
;
136 isc_result_t result
, result2
;
137 dns_message_t
*query
, *response
= NULL
;
138 isc_buffer_t outtoken
;
140 char output
[10 * 1024];
142 unsigned char array
[DNS_NAME_MAXTEXT
+ 1];
143 isc_buffer_init(&outtoken
, array
, sizeof(array
));
147 REQUIRE(reqev
!= NULL
);
149 if (reqev
->result
!= ISC_R_SUCCESS
) {
150 fprintf(stderr
, "I:request event result: %s\n",
151 isc_result_totext(reqev
->result
));
155 query
= reqev
->ev_arg
;
158 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &response
);
159 CHECK("dns_message_create", result
);
161 printf("\nReceived Response:\n");
163 result2
= dns_request_getresponse(reqev
->request
, response
,
164 DNS_MESSAGEPARSE_PRESERVEORDER
);
165 isc_buffer_init(&outbuf
, output
, sizeof(output
));
166 result
= dns_message_totext(response
, &dns_master_style_debug
, 0,
168 CHECK("dns_message_totext", result
);
169 printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf
),
170 (char *)isc_buffer_base(&outbuf
));
172 CHECK("dns_request_getresponse", result2
);
175 dns_message_destroy(&response
);
179 dns_message_destroy(&query
);
182 dns_request_destroy(&reqev
->request
);
184 isc_event_free(&event
);
186 event
= isc_event_allocate(mctx
, (void *)1, 1, console
, NULL
,
188 isc_task_send(task
, &event
);
194 sendquery(isc_task_t
*task
, isc_event_t
*event
)
196 dns_request_t
*request
= NULL
;
197 dns_message_t
*message
= NULL
;
198 dns_name_t
*qname
= NULL
;
199 dns_rdataset_t
*qrdataset
= NULL
;
201 dns_fixedname_t queryname
;
204 char output
[10 * 1024];
206 static char host
[256];
208 isc_event_free(&event
);
213 dns_fixedname_init(&queryname
);
214 isc_buffer_init(&buf
, host
, strlen(host
));
215 isc_buffer_add(&buf
, strlen(host
));
216 result
= dns_name_fromtext(dns_fixedname_name(&queryname
), &buf
,
217 dns_rootname
, 0, NULL
);
218 CHECK("dns_name_fromtext", result
);
220 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
, &message
);
222 message
->opcode
= dns_opcode_query
;
223 message
->rdclass
= dns_rdataclass_in
;
224 message
->id
= (unsigned short)(random() & 0xFFFF);
226 result
= dns_message_gettempname(message
, &qname
);
227 if (result
!= ISC_R_SUCCESS
)
230 result
= dns_message_gettemprdataset(message
, &qrdataset
);
231 if (result
!= ISC_R_SUCCESS
)
234 dns_name_init(qname
, NULL
);
235 dns_name_clone(dns_fixedname_name(&queryname
), qname
);
236 dns_rdataset_init(qrdataset
);
237 dns_rdataset_makequestion(qrdataset
, dns_rdataclass_in
,
239 ISC_LIST_APPEND(qname
->list
, qrdataset
, link
);
240 dns_message_addname(message
, qname
, DNS_SECTION_QUESTION
);
242 result
= dns_request_create(requestmgr
, message
, &address
, 0, tsigkey
,
243 TIMEOUT
, task
, recvresponse
,
245 CHECK("dns_request_create", result
);
247 printf("Submitting query:\n");
248 isc_buffer_init(&outbuf
, output
, sizeof(output
));
249 result
= dns_message_totext(message
, &dns_master_style_debug
, 0,
251 CHECK("dns_message_totext", result
);
252 printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf
),
253 (char *)isc_buffer_base(&outbuf
));
259 dns_message_puttempname(message
, &qname
);
260 if (qrdataset
!= NULL
)
261 dns_message_puttemprdataset(message
, &qrdataset
);
263 dns_message_destroy(&message
);
267 initctx2(isc_task_t
*task
, isc_event_t
*event
) {
268 dns_requestevent_t
*reqev
= (dns_requestevent_t
*)event
;
270 dns_message_t
*query
, *response
= NULL
;
271 isc_buffer_t outtoken
;
272 unsigned char array
[DNS_NAME_MAXTEXT
+ 1];
273 dns_rdataset_t
*rdataset
;
274 dns_rdatatype_t qtype
;
275 dns_name_t
*question_name
;
279 REQUIRE(reqev
!= NULL
);
281 if (reqev
->result
!= ISC_R_SUCCESS
) {
282 fprintf(stderr
, "I:request event result: %s\n",
283 isc_result_totext(reqev
->result
));
287 query
= reqev
->ev_arg
;
290 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &response
);
291 CHECK("dns_message_create", result
);
293 result
= dns_request_getresponse(reqev
->request
, response
,
294 DNS_MESSAGEPARSE_PRESERVEORDER
);
295 CHECK("dns_request_getresponse", result
);
297 if (response
->rcode
!= dns_rcode_noerror
) {
298 result
= ISC_RESULTCLASS_DNSRCODE
+ response
->rcode
;
299 fprintf(stderr
, "I:response rcode: %s\n",
300 isc_result_totext(result
));
304 printf("Received token from server, calling gss_init_sec_context()\n");
305 isc_buffer_init(&outtoken
, array
, DNS_NAME_MAXTEXT
+ 1);
306 result
= dns_tkey_processgssresponse(query
, response
,
307 dns_fixedname_name(&gssname
),
311 CHECK("dns_tkey_processgssresponse", result
);
312 printf("Context accepted\n");
314 question_name
= NULL
;
315 dns_message_currentname(response
, DNS_SECTION_ANSWER
, &question_name
);
316 rdataset
= ISC_LIST_HEAD(question_name
->list
);
317 INSIST(rdataset
!= NULL
);
318 qtype
= rdataset
->type
;
319 if(qtype
== dns_rdatatype_tkey
) {
320 printf("Received TKEY response from server\n");
321 printf("Context completed\n");
323 printf("Did not receive TKEY response from server\n");
324 printf("Context not completed\n");
325 dns_tsigkey_detach(&tsigkey
);
330 dns_message_destroy(&response
);
334 dns_message_destroy(&query
);
337 dns_request_destroy(&reqev
->request
);
339 isc_event_free(&event
);
341 event
= isc_event_allocate(mctx
, (void *)1, 1, console
, NULL
,
343 isc_task_send(task
, &event
);
348 initctx1(isc_task_t
*task
, isc_event_t
*event
) {
351 dns_message_t
*query
;
352 dns_request_t
*request
;
354 isc_event_free(&event
);
356 printf("Initctx - GSS name => ");
359 sprintf(contextname
, "gsstest.context.%d.", (int)time(NULL
));
361 printf("Initctx - context name we're using: %s\n", contextname
);
363 printf("Negotiating GSSAPI context: ");
368 * Setup a GSSAPI context with the server
370 dns_fixedname_init(&servername
);
371 isc_buffer_init(&buf
, contextname
, strlen(contextname
));
372 isc_buffer_add(&buf
, strlen(contextname
));
373 result
= dns_name_fromtext(dns_fixedname_name(&servername
), &buf
,
374 dns_rootname
, 0, NULL
);
375 CHECK("dns_name_fromtext", result
);
377 /* Make name happen */
378 dns_fixedname_init(&gssname
);
379 isc_buffer_init(&buf
, gssid
, strlen(gssid
));
380 isc_buffer_add(&buf
, strlen(gssid
));
381 result
= dns_name_fromtext(dns_fixedname_name(&gssname
), &buf
,
382 dns_rootname
, 0, NULL
);
383 CHECK("dns_name_fromtext", result
);
386 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
, &query
);
387 CHECK("dns_message_create", result
);
389 printf("Calling gss_init_sec_context()\n");
390 gssctx
= GSS_C_NO_CONTEXT
;
391 result
= dns_tkey_buildgssquery(query
, dns_fixedname_name(&servername
),
392 dns_fixedname_name(&gssname
),
393 NULL
, 36000, &gssctx
, ISC_TRUE
);
394 CHECK("dns_tkey_buildgssquery", result
);
396 printf("Sending context token to server\n");
398 result
= dns_request_create(requestmgr
, query
, &address
, 0, NULL
,
399 TIMEOUT
, task
, initctx2
, query
, &request
);
400 CHECK("dns_request_create", result
);
404 event
= isc_event_allocate(mctx
, (void *)1, 1, console
, NULL
,
406 isc_task_send(task
, &event
);return;
412 struct in_addr inaddr
;
416 printf("Server IP => ");
417 c
= scanf("%s", serveraddress
);
419 if(c
== EOF
|| strcmp(serveraddress
, "quit") == 0) {
424 if (inet_pton(AF_INET
, serveraddress
, &inaddr
) == 1) {
425 isc_sockaddr_fromin(&address
, &inaddr
, PORT
);
433 main(int argc
, char *argv
[]) {
434 isc_taskmgr_t
*taskmgr
;
435 isc_timermgr_t
*timermgr
;
436 isc_socketmgr_t
*socketmgr
;
438 unsigned int attrs
, attrmask
;
439 isc_sockaddr_t bind_any
;
440 dns_dispatchmgr_t
*dispatchmgr
;
441 dns_dispatch_t
*dispatchv4
;
445 isc_log_t
*lctx
= NULL
;
446 isc_logconfig_t
*lcfg
= NULL
;
447 isc_logdestination_t destination
;
452 RUNCHECK(isc_app_start());
454 dns_result_register();
457 RUNCHECK(isc_mem_create(0, 0, &mctx
));
459 RUNCHECK(isc_log_create(mctx
, &lctx
, &lcfg
));
460 isc_log_setcontext(lctx
);
462 dns_log_setcontext(lctx
);
465 * Create and install the default channel.
467 destination
.file
.stream
= stderr
;
468 destination
.file
.name
= NULL
;
469 destination
.file
.versions
= ISC_LOG_ROLLNEVER
;
470 destination
.file
.maximum_size
= 0;
471 RUNCHECK(isc_log_createchannel(lcfg
, "_default",
474 &destination
, ISC_LOG_PRINTTIME
));
475 RUNCHECK(isc_log_usechannel(lcfg
, "_default", NULL
, NULL
));
477 isc_log_setdebuglevel(lctx
, 9);
480 RUNCHECK(isc_entropy_create(mctx
, &ectx
));
481 RUNCHECK(isc_entropy_createfilesource(ectx
, "/dev/urandom"));
483 RUNCHECK(dst_lib_init(mctx
, ectx
, ISC_ENTROPY_GOODONLY
));
486 RUNCHECK(isc_taskmgr_create(mctx
, 1, 0, &taskmgr
));
488 RUNCHECK(isc_task_create(taskmgr
, 0, &task
));
490 RUNCHECK(isc_timermgr_create(mctx
, &timermgr
));
492 RUNCHECK(isc_socketmgr_create(mctx
, &socketmgr
));
494 RUNCHECK(dns_dispatchmgr_create(mctx
, ectx
, &dispatchmgr
));
495 isc_sockaddr_any(&bind_any
);
496 attrs
= DNS_DISPATCHATTR_UDP
|
497 DNS_DISPATCHATTR_MAKEQUERY
|
498 DNS_DISPATCHATTR_IPV4
;
499 attrmask
= DNS_DISPATCHATTR_UDP
|
500 DNS_DISPATCHATTR_TCP
|
501 DNS_DISPATCHATTR_IPV4
|
502 DNS_DISPATCHATTR_IPV6
;
504 RUNCHECK(dns_dispatch_getudp(dispatchmgr
, socketmgr
, taskmgr
,
505 &bind_any
, 4096, 4, 2, 3, 5,
506 attrs
, attrmask
, &dispatchv4
));
508 RUNCHECK(dns_requestmgr_create(mctx
, timermgr
, socketmgr
, taskmgr
,
509 dispatchmgr
, dispatchv4
, NULL
,
513 RUNCHECK(dns_tsigkeyring_create(mctx
, &ring
));
516 RUNCHECK(dns_view_create(mctx
, 0, "_test", &view
));
517 dns_view_setkeyring(view
, ring
);
520 RUNCHECK(isc_socket_create(socketmgr
, PF_INET
, isc_sockettype_udp
,
525 RUNCHECK(isc_app_onrun(mctx
, task
, console
, NULL
));
530 dns_tsigkey_detach(&tsigkey
);
532 dns_requestmgr_shutdown(requestmgr
);
533 dns_requestmgr_detach(&requestmgr
);
535 dns_dispatch_detach(&dispatchv4
);
536 dns_dispatchmgr_destroy(&dispatchmgr
);
538 isc_timermgr_destroy(&timermgr
);
540 isc_task_detach(&task
);
541 isc_taskmgr_destroy(&taskmgr
);
543 isc_socket_detach(&sock
);
544 isc_socketmgr_destroy(&socketmgr
);
546 isc_mem_stats(mctx
, stdout
);
548 dns_view_detach(&view
);
551 isc_entropy_detach(&ectx
);
553 isc_mem_stats(mctx
, stdout
);
554 isc_mem_destroy(&mctx
);
562 main(int argc
, char *argv
[]) {
565 fprintf(stderr
, "R:GSSAPIONLY\n");