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