2 * Copyright (C) 2006, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
17 /* $Id: gsstest.c,v 1.8 2009/09/02 23:48:01 tbox Exp $ */
25 #include <isc/base64.h>
26 #include <isc/entropy.h>
29 #include <isc/sockaddr.h>
30 #include <isc/socket.h>
32 #include <isc/timer.h>
35 #include <dns/dispatch.h>
36 #include <dns/fixedname.h>
37 #include <dns/keyvalues.h>
39 #include <dns/message.h>
41 #include <dns/request.h>
42 #include <dns/result.h>
47 #include <dns/dnssec.h>
48 #include <dns/events.h>
49 #include <dns/masterdump.h>
50 #include <dns/rdataset.h>
51 #include <dns/resolver.h>
52 #include <dns/types.h>
54 #include <dst/result.h>
57 #include ISC_PLATFORM_GSSAPIHEADER
66 #define CHECK(str, x) { \
67 if ((x) != ISC_R_SUCCESS) { \
68 fprintf(stderr, "I:%d:%s: %s\n", __LINE__, (str), isc_result_totext(x)); \
73 static char contextname[512];
74 static char gssid[512];
75 static char serveraddress[512];
76 static dns_fixedname_t servername, gssname;
78 static isc_mem_t *mctx;
79 static dns_requestmgr_t *requestmgr;
80 static isc_sockaddr_t address;
82 static dns_tsig_keyring_t *ring;
83 static dns_tsigkey_t *tsigkey = NULL;
84 static gss_ctx_id_t gssctx;
85 static gss_ctx_id_t *gssctxp = &gssctx;
87 #define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
92 static void initctx1(isc_task_t *task, isc_event_t *event);
93 static void sendquery(isc_task_t *task, isc_event_t *event);
97 console(isc_task_t *task, isc_event_t *event)
100 isc_event_t *ev = NULL;
102 isc_event_free(&event);
105 printf("\nCommand => ");
108 if(strcmp(buf, "quit") == 0) {
113 if(strcmp(buf, "initctx") == 0) {
114 ev = isc_event_allocate(mctx, (void *)1, 1, initctx1,
115 NULL, sizeof(*event));
116 isc_task_send(task, &ev);
120 if(strcmp(buf, "query") == 0) {
121 ev = isc_event_allocate(mctx, (void *)1, 1, sendquery,
122 NULL, sizeof(*event));
123 isc_task_send(task, &ev);
127 printf("Unknown command\n");
132 recvresponse(isc_task_t *task, isc_event_t *event) {
133 dns_requestevent_t *reqev = (dns_requestevent_t *)event;
134 isc_result_t result, result2;
135 dns_message_t *query, *response = NULL;
136 isc_buffer_t outtoken;
138 char output[10 * 1024];
140 unsigned char array[DNS_NAME_MAXTEXT + 1];
141 isc_buffer_init(&outtoken, array, sizeof(array));
145 REQUIRE(reqev != NULL);
147 if (reqev->result != ISC_R_SUCCESS) {
148 fprintf(stderr, "I:request event result: %s\n",
149 isc_result_totext(reqev->result));
153 query = reqev->ev_arg;
156 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
157 CHECK("dns_message_create", result);
159 printf("\nReceived Response:\n");
161 result2 = dns_request_getresponse(reqev->request, response,
162 DNS_MESSAGEPARSE_PRESERVEORDER);
163 isc_buffer_init(&outbuf, output, sizeof(output));
164 result = dns_message_totext(response, &dns_master_style_debug, 0,
166 CHECK("dns_message_totext", result);
167 printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
168 (char *)isc_buffer_base(&outbuf));
170 CHECK("dns_request_getresponse", result2);
173 dns_message_destroy(&response);
177 dns_message_destroy(&query);
180 dns_request_destroy(&reqev->request);
182 isc_event_free(&event);
184 event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
186 isc_task_send(task, &event);
192 sendquery(isc_task_t *task, isc_event_t *event)
194 dns_request_t *request = NULL;
195 dns_message_t *message = NULL;
196 dns_name_t *qname = NULL;
197 dns_rdataset_t *qrdataset = NULL;
199 dns_fixedname_t queryname;
202 char output[10 * 1024];
204 static char host[256];
206 isc_event_free(&event);
211 dns_fixedname_init(&queryname);
212 isc_buffer_init(&buf, host, strlen(host));
213 isc_buffer_add(&buf, strlen(host));
214 result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf,
215 dns_rootname, 0, NULL);
216 CHECK("dns_name_fromtext", result);
218 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
220 message->opcode = dns_opcode_query;
221 message->rdclass = dns_rdataclass_in;
222 message->id = (unsigned short)(random() & 0xFFFF);
224 result = dns_message_gettempname(message, &qname);
225 if (result != ISC_R_SUCCESS)
228 result = dns_message_gettemprdataset(message, &qrdataset);
229 if (result != ISC_R_SUCCESS)
232 dns_name_init(qname, NULL);
233 dns_name_clone(dns_fixedname_name(&queryname), qname);
234 dns_rdataset_init(qrdataset);
235 dns_rdataset_makequestion(qrdataset, dns_rdataclass_in,
237 ISC_LIST_APPEND(qname->list, qrdataset, link);
238 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
240 result = dns_request_create(requestmgr, message, &address, 0, tsigkey,
241 TIMEOUT, task, recvresponse,
243 CHECK("dns_request_create", result);
245 printf("Submitting query:\n");
246 isc_buffer_init(&outbuf, output, sizeof(output));
247 result = dns_message_totext(message, &dns_master_style_debug, 0,
249 CHECK("dns_message_totext", result);
250 printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
251 (char *)isc_buffer_base(&outbuf));
257 dns_message_puttempname(message, &qname);
258 if (qrdataset != NULL)
259 dns_message_puttemprdataset(message, &qrdataset);
261 dns_message_destroy(&message);
265 initctx2(isc_task_t *task, isc_event_t *event) {
266 dns_requestevent_t *reqev = (dns_requestevent_t *)event;
268 dns_message_t *query, *response = NULL;
269 isc_buffer_t outtoken;
270 unsigned char array[DNS_NAME_MAXTEXT + 1];
271 dns_rdataset_t *rdataset;
272 dns_rdatatype_t qtype;
273 dns_name_t *question_name;
277 REQUIRE(reqev != NULL);
279 if (reqev->result != ISC_R_SUCCESS) {
280 fprintf(stderr, "I:request event result: %s\n",
281 isc_result_totext(reqev->result));
285 query = reqev->ev_arg;
288 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
289 CHECK("dns_message_create", result);
291 result = dns_request_getresponse(reqev->request, response,
292 DNS_MESSAGEPARSE_PRESERVEORDER);
293 CHECK("dns_request_getresponse", result);
295 if (response->rcode != dns_rcode_noerror) {
296 result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
297 fprintf(stderr, "I:response rcode: %s\n",
298 isc_result_totext(result));
302 printf("Received token from server, calling gss_init_sec_context()\n");
303 isc_buffer_init(&outtoken, array, DNS_NAME_MAXTEXT + 1);
304 result = dns_tkey_processgssresponse(query, response,
305 dns_fixedname_name(&gssname),
309 CHECK("dns_tkey_processgssresponse", result);
310 printf("Context accepted\n");
312 question_name = NULL;
313 dns_message_currentname(response, DNS_SECTION_ANSWER, &question_name);
314 rdataset = ISC_LIST_HEAD(question_name->list);
315 INSIST(rdataset != NULL);
316 qtype = rdataset->type;
317 if(qtype == dns_rdatatype_tkey) {
318 printf("Received TKEY response from server\n");
319 printf("Context completed\n");
321 printf("Did not receive TKEY response from server\n");
322 printf("Context not completed\n");
323 dns_tsigkey_detach(&tsigkey);
328 dns_message_destroy(&response);
332 dns_message_destroy(&query);
335 dns_request_destroy(&reqev->request);
337 isc_event_free(&event);
339 event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
341 isc_task_send(task, &event);
346 initctx1(isc_task_t *task, isc_event_t *event) {
349 dns_message_t *query;
350 dns_request_t *request;
352 isc_event_free(&event);
354 printf("Initctx - GSS name => ");
357 sprintf(contextname, "gsstest.context.%d.", (int)time(NULL));
359 printf("Initctx - context name we're using: %s\n", contextname);
361 printf("Negotiating GSSAPI context: ");
366 * Setup a GSSAPI context with the server
368 dns_fixedname_init(&servername);
369 isc_buffer_init(&buf, contextname, strlen(contextname));
370 isc_buffer_add(&buf, strlen(contextname));
371 result = dns_name_fromtext(dns_fixedname_name(&servername), &buf,
372 dns_rootname, 0, NULL);
373 CHECK("dns_name_fromtext", result);
375 /* Make name happen */
376 dns_fixedname_init(&gssname);
377 isc_buffer_init(&buf, gssid, strlen(gssid));
378 isc_buffer_add(&buf, strlen(gssid));
379 result = dns_name_fromtext(dns_fixedname_name(&gssname), &buf,
380 dns_rootname, 0, NULL);
381 CHECK("dns_name_fromtext", result);
384 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
385 CHECK("dns_message_create", result);
387 printf("Calling gss_init_sec_context()\n");
388 gssctx = GSS_C_NO_CONTEXT;
389 result = dns_tkey_buildgssquery(query, dns_fixedname_name(&servername),
390 dns_fixedname_name(&gssname),
391 NULL, 36000, &gssctx, ISC_TRUE);
392 CHECK("dns_tkey_buildgssquery", result);
394 printf("Sending context token to server\n");
396 result = dns_request_create(requestmgr, query, &address, 0, NULL,
397 TIMEOUT, task, initctx2, query, &request);
398 CHECK("dns_request_create", result);
402 event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
404 isc_task_send(task, &event);return;
410 struct in_addr inaddr;
414 printf("Server IP => ");
415 c = scanf("%s", serveraddress);
417 if(c == EOF || strcmp(serveraddress, "quit") == 0) {
422 if (inet_pton(AF_INET, serveraddress, &inaddr) == 1) {
423 isc_sockaddr_fromin(&address, &inaddr, PORT);
431 main(int argc, char *argv[]) {
432 isc_taskmgr_t *taskmgr;
433 isc_timermgr_t *timermgr;
434 isc_socketmgr_t *socketmgr;
436 unsigned int attrs, attrmask;
437 isc_sockaddr_t bind_any;
438 dns_dispatchmgr_t *dispatchmgr;
439 dns_dispatch_t *dispatchv4;
443 isc_log_t *lctx = NULL;
444 isc_logconfig_t *lcfg = NULL;
445 isc_logdestination_t destination;
450 RUNCHECK(isc_app_start());
452 dns_result_register();
455 RUNCHECK(isc_mem_create(0, 0, &mctx));
457 RUNCHECK(isc_log_create(mctx, &lctx, &lcfg));
458 isc_log_setcontext(lctx);
460 dns_log_setcontext(lctx);
463 * Create and install the default channel.
465 destination.file.stream = stderr;
466 destination.file.name = NULL;
467 destination.file.versions = ISC_LOG_ROLLNEVER;
468 destination.file.maximum_size = 0;
469 RUNCHECK(isc_log_createchannel(lcfg, "_default",
472 &destination, ISC_LOG_PRINTTIME));
473 RUNCHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL));
475 isc_log_setdebuglevel(lctx, 9);
478 RUNCHECK(isc_entropy_create(mctx, &ectx));
479 RUNCHECK(isc_entropy_createfilesource(ectx, "/dev/urandom"));
481 RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
484 RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
486 RUNCHECK(isc_task_create(taskmgr, 0, &task));
488 RUNCHECK(isc_timermgr_create(mctx, &timermgr));
490 RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
492 RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr));
493 isc_sockaddr_any(&bind_any);
494 attrs = DNS_DISPATCHATTR_UDP |
495 DNS_DISPATCHATTR_MAKEQUERY |
496 DNS_DISPATCHATTR_IPV4;
497 attrmask = DNS_DISPATCHATTR_UDP |
498 DNS_DISPATCHATTR_TCP |
499 DNS_DISPATCHATTR_IPV4 |
500 DNS_DISPATCHATTR_IPV6;
502 RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
503 &bind_any, 4096, 4, 2, 3, 5,
504 attrs, attrmask, &dispatchv4));
506 RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
507 dispatchmgr, dispatchv4, NULL,
511 RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
514 RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
515 dns_view_setkeyring(view, ring);
518 RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
523 RUNCHECK(isc_app_onrun(mctx, task, console, NULL));
528 dns_tsigkey_detach(&tsigkey);
530 dns_requestmgr_shutdown(requestmgr);
531 dns_requestmgr_detach(&requestmgr);
533 dns_dispatch_detach(&dispatchv4);
534 dns_dispatchmgr_destroy(&dispatchmgr);
536 isc_timermgr_destroy(&timermgr);
538 isc_task_detach(&task);
539 isc_taskmgr_destroy(&taskmgr);
541 isc_socket_detach(&sock);
542 isc_socketmgr_destroy(&socketmgr);
544 isc_mem_stats(mctx, stdout);
546 dns_view_detach(&view);
549 isc_entropy_detach(&ectx);
551 isc_mem_stats(mctx, stdout);
552 isc_mem_destroy(&mctx);
560 main(int argc, char *argv[]) {
563 fprintf(stderr, "R:GSSAPIONLY\n");