1 /* 2 * Copyright (c) 2006 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of KTH nor the names of its contributors may be 18 * used to endorse or promote products derived from this software without 19 * specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <common.h> 35 RCSID("$Id$"); 36 37 static FILE *logfile; 38 39 /* 40 * 41 */ 42 43 struct client { 44 char *name; 45 struct sockaddr *sa; 46 socklen_t salen; 47 krb5_storage *sock; 48 int32_t capabilities; 49 char *target_name; 50 char *moniker; 51 krb5_storage *logsock; 52 int have_log; 53 #ifdef ENABLE_PTHREAD_SUPPORT 54 pthread_t thr; 55 #else 56 pid_t child; 57 #endif 58 }; 59 60 static struct client **clients; 61 static int num_clients; 62 63 static int 64 init_sec_context(struct client *client, 65 int32_t *hContext, int32_t *hCred, 66 int32_t flags, 67 const char *targetname, 68 const krb5_data *itoken, krb5_data *otoken) 69 { 70 int32_t val; 71 krb5_data_zero(otoken); 72 put32(client, eInitContext); 73 put32(client, *hContext); 74 put32(client, *hCred); 75 put32(client, flags); 76 putstring(client, targetname); 77 putdata(client, *itoken); 78 ret32(client, *hContext); 79 ret32(client, val); 80 retdata(client, *otoken); 81 return val; 82 } 83 84 static int 85 accept_sec_context(struct client *client, 86 int32_t *hContext, 87 int32_t flags, 88 const krb5_data *itoken, 89 krb5_data *otoken, 90 int32_t *hDelegCred) 91 { 92 int32_t val; 93 krb5_data_zero(otoken); 94 put32(client, eAcceptContext); 95 put32(client, *hContext); 96 put32(client, flags); 97 putdata(client, *itoken); 98 ret32(client, *hContext); 99 ret32(client, val); 100 retdata(client, *otoken); 101 ret32(client, *hDelegCred); 102 return val; 103 } 104 105 static int 106 acquire_cred(struct client *client, 107 const char *username, 108 const char *password, 109 int32_t flags, 110 int32_t *hCred) 111 { 112 int32_t val; 113 put32(client, eAcquireCreds); 114 putstring(client, username); 115 putstring(client, password); 116 put32(client, flags); 117 ret32(client, val); 118 ret32(client, *hCred); 119 return val; 120 } 121 122 static int 123 toast_resource(struct client *client, 124 int32_t hCred) 125 { 126 int32_t val; 127 put32(client, eToastResource); 128 put32(client, hCred); 129 ret32(client, val); 130 return val; 131 } 132 133 static int 134 goodbye(struct client *client) 135 { 136 put32(client, eGoodBye); 137 return GSMERR_OK; 138 } 139 140 static int 141 get_targetname(struct client *client, 142 char **target) 143 { 144 put32(client, eGetTargetName); 145 retstring(client, *target); 146 return GSMERR_OK; 147 } 148 149 static int32_t 150 encrypt_token(struct client *client, int32_t hContext, int32_t flags, 151 krb5_data *in, krb5_data *out) 152 { 153 int32_t val; 154 put32(client, eEncrypt); 155 put32(client, hContext); 156 put32(client, flags); 157 put32(client, 0); 158 putdata(client, *in); 159 ret32(client, val); 160 retdata(client, *out); 161 return val; 162 } 163 164 static int32_t 165 decrypt_token(struct client *client, int32_t hContext, int flags, 166 krb5_data *in, krb5_data *out) 167 { 168 int32_t val; 169 put32(client, eDecrypt); 170 put32(client, hContext); 171 put32(client, flags); 172 put32(client, 0); 173 putdata(client, *in); 174 ret32(client, val); 175 retdata(client, *out); 176 return val; 177 } 178 179 static int32_t 180 wrap_token_ext(struct client *client, int32_t hContext, int32_t flags, 181 int32_t bflags, krb5_data *header, krb5_data *in, krb5_data *trailer, 182 krb5_data *out) 183 { 184 int32_t val; 185 put32(client, eWrapExt); 186 put32(client, hContext); 187 put32(client, flags); 188 put32(client, bflags); 189 putdata(client, *header); 190 putdata(client, *in); 191 putdata(client, *trailer); 192 ret32(client, val); 193 retdata(client, *out); 194 return val; 195 } 196 197 static int32_t 198 unwrap_token_ext(struct client *client, int32_t hContext, int32_t flags, 199 int32_t bflags, krb5_data *header, krb5_data *in, krb5_data *trailer, 200 krb5_data *out) 201 { 202 int32_t val; 203 put32(client, eUnwrapExt); 204 put32(client, hContext); 205 put32(client, flags); 206 put32(client, bflags); 207 putdata(client, *header); 208 putdata(client, *in); 209 putdata(client, *trailer); 210 ret32(client, val); 211 retdata(client, *out); 212 return val; 213 } 214 215 static int32_t 216 get_mic(struct client *client, int32_t hContext, 217 krb5_data *in, krb5_data *mic) 218 { 219 int32_t val; 220 put32(client, eSign); 221 put32(client, hContext); 222 put32(client, 0); 223 put32(client, 0); 224 putdata(client, *in); 225 ret32(client, val); 226 retdata(client, *mic); 227 return val; 228 } 229 230 static int32_t 231 verify_mic(struct client *client, int32_t hContext, 232 krb5_data *in, krb5_data *mic) 233 { 234 int32_t val; 235 put32(client, eVerify); 236 put32(client, hContext); 237 put32(client, 0); 238 put32(client, 0); 239 putdata(client, *in); 240 putdata(client, *mic); 241 ret32(client, val); 242 return val; 243 } 244 245 246 static int32_t 247 get_version_capa(struct client *client, 248 int32_t *version, int32_t *capa, 249 char **version_str) 250 { 251 put32(client, eGetVersionAndCapabilities); 252 ret32(client, *version); 253 ret32(client, *capa); 254 retstring(client, *version_str); 255 return GSMERR_OK; 256 } 257 258 static int32_t 259 get_moniker(struct client *client, 260 char **moniker) 261 { 262 put32(client, eGetMoniker); 263 retstring(client, *moniker); 264 return GSMERR_OK; 265 } 266 267 static int 268 wait_log(struct client *c) 269 { 270 int32_t port; 271 struct sockaddr_storage sast; 272 socklen_t salen = sizeof(sast); 273 int fd, fd2, ret; 274 275 memset(&sast, 0, sizeof(sast)); 276 277 assert(sizeof(sast) >= c->salen); 278 279 fd = socket(c->sa->sa_family, SOCK_STREAM, 0); 280 if (fd < 0) 281 err(1, "failed to build socket for %s's logging port", c->moniker); 282 283 ((struct sockaddr *)&sast)->sa_family = c->sa->sa_family; 284 ret = bind(fd, (struct sockaddr *)&sast, c->salen); 285 if (ret < 0) 286 err(1, "failed to bind %s's logging port", c->moniker); 287 288 if (listen(fd, SOMAXCONN) < 0) 289 err(1, "failed to listen %s's logging port", c->moniker); 290 291 salen = sizeof(sast); 292 ret = getsockname(fd, (struct sockaddr *)&sast, &salen); 293 if (ret < 0) 294 err(1, "failed to get address of local socket for %s", c->moniker); 295 296 port = socket_get_port((struct sockaddr *)&sast); 297 298 put32(c, eSetLoggingSocket); 299 put32(c, ntohs(port)); 300 301 salen = sizeof(sast); 302 fd2 = accept(fd, (struct sockaddr *)&sast, &salen); 303 if (fd2 < 0) 304 err(1, "failed to accept local socket for %s", c->moniker); 305 close(fd); 306 307 return fd2; 308 } 309 310 311 312 313 static int 314 build_context(struct client *ipeer, struct client *apeer, 315 int32_t flags, int32_t hCred, 316 int32_t *iContext, int32_t *aContext, int32_t *hDelegCred) 317 { 318 int32_t val = GSMERR_ERROR, ic = 0, ac = 0, deleg = 0; 319 krb5_data itoken, otoken; 320 int iDone = 0, aDone = 0; 321 int step = 0; 322 int first_call = 0x80; 323 324 if (apeer->target_name == NULL) 325 errx(1, "apeer %s have no target name", apeer->name); 326 327 krb5_data_zero(&itoken); 328 329 while (!iDone || !aDone) { 330 331 if (iDone) { 332 warnx("iPeer already done, aPeer want extra rtt"); 333 val = GSMERR_ERROR; 334 goto out; 335 } 336 337 val = init_sec_context(ipeer, &ic, &hCred, flags|first_call, 338 apeer->target_name, &itoken, &otoken); 339 step++; 340 switch(val) { 341 case GSMERR_OK: 342 iDone = 1; 343 if (aDone) 344 continue; 345 break; 346 case GSMERR_CONTINUE_NEEDED: 347 break; 348 default: 349 warnx("iPeer %s failed with %d (step %d)", 350 ipeer->name, (int)val, step); 351 goto out; 352 } 353 354 if (aDone) { 355 warnx("aPeer already done, iPeer want extra rtt"); 356 val = GSMERR_ERROR; 357 goto out; 358 } 359 360 val = accept_sec_context(apeer, &ac, flags|first_call, 361 &otoken, &itoken, &deleg); 362 step++; 363 switch(val) { 364 case GSMERR_OK: 365 aDone = 1; 366 if (iDone) 367 continue; 368 break; 369 case GSMERR_CONTINUE_NEEDED: 370 break; 371 default: 372 warnx("aPeer %s failed with %d (step %d)", 373 apeer->name, (int)val, step); 374 val = GSMERR_ERROR; 375 goto out; 376 } 377 first_call = 0; 378 val = GSMERR_OK; 379 } 380 381 if (iContext == NULL || val != GSMERR_OK) { 382 if (ic) 383 toast_resource(ipeer, ic); 384 if (iContext) 385 *iContext = 0; 386 } else 387 *iContext = ic; 388 389 if (aContext == NULL || val != GSMERR_OK) { 390 if (ac) 391 toast_resource(apeer, ac); 392 if (aContext) 393 *aContext = 0; 394 } else 395 *aContext = ac; 396 397 if (hDelegCred == NULL || val != GSMERR_OK) { 398 if (deleg) 399 toast_resource(apeer, deleg); 400 if (hDelegCred) 401 *hDelegCred = 0; 402 } else 403 *hDelegCred = deleg; 404 405 out: 406 return val; 407 } 408 409 static void 410 test_mic(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2) 411 { 412 krb5_data msg, mic; 413 int32_t val; 414 415 msg.data = "foo"; 416 msg.length = 3; 417 418 krb5_data_zero(&mic); 419 420 val = get_mic(c1, hc1, &msg, &mic); 421 if (val) 422 errx(1, "get_mic failed to host: %s", c1->moniker); 423 val = verify_mic(c2, hc2, &msg, &mic); 424 if (val) 425 errx(1, "verify_mic failed to host: %s", c2->moniker); 426 427 krb5_data_free(&mic); 428 } 429 430 static int32_t 431 test_wrap(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2, 432 int conf) 433 { 434 krb5_data msg, wrapped, out; 435 int32_t val; 436 437 msg.data = "foo"; 438 msg.length = 3; 439 440 krb5_data_zero(&wrapped); 441 krb5_data_zero(&out); 442 443 val = encrypt_token(c1, hc1, conf, &msg, &wrapped); 444 if (val) { 445 warnx("encrypt_token failed to host: %s", c1->moniker); 446 return val; 447 } 448 val = decrypt_token(c2, hc2, conf, &wrapped, &out); 449 if (val) { 450 krb5_data_free(&wrapped); 451 warnx("decrypt_token failed to host: %s", c2->moniker); 452 return val; 453 } 454 455 if (msg.length != out.length) { 456 warnx("decrypted'ed token have wrong length (%lu != %lu)", 457 (unsigned long)msg.length, (unsigned long)out.length); 458 val = GSMERR_ERROR; 459 } else if (memcmp(msg.data, out.data, msg.length) != 0) { 460 warnx("decryptd'ed token have wrong data"); 461 val = GSMERR_ERROR; 462 } 463 464 krb5_data_free(&wrapped); 465 krb5_data_free(&out); 466 return val; 467 } 468 469 static int32_t 470 test_wrap_ext(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2, 471 int conf, int bflags) 472 { 473 krb5_data header, msg, trailer, wrapped, out; 474 int32_t val; 475 476 header.data = "header"; 477 header.length = 6; 478 479 msg.data = "0123456789abcdef"; /* padded for most enctypes */ 480 msg.length = 32; 481 482 trailer.data = "trailer"; 483 trailer.length = 7; 484 485 krb5_data_zero(&wrapped); 486 krb5_data_zero(&out); 487 488 val = wrap_token_ext(c1, hc1, conf, bflags, &header, &msg, &trailer, &wrapped); 489 if (val) { 490 warnx("encrypt_token failed to host: %s", c1->moniker); 491 return val; 492 } 493 val = unwrap_token_ext(c2, hc2, conf, bflags, &header, &wrapped, &trailer, &out); 494 if (val) { 495 krb5_data_free(&wrapped); 496 warnx("decrypt_token failed to host: %s", c2->moniker); 497 return val; 498 } 499 500 if (msg.length != out.length) { 501 warnx("decrypted'ed token have wrong length (%lu != %lu)", 502 (unsigned long)msg.length, (unsigned long)out.length); 503 val = GSMERR_ERROR; 504 } else if (memcmp(msg.data, out.data, msg.length) != 0) { 505 warnx("decryptd'ed token have wrong data"); 506 val = GSMERR_ERROR; 507 } 508 509 krb5_data_free(&wrapped); 510 krb5_data_free(&out); 511 return val; 512 } 513 514 515 static int32_t 516 test_token(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2, int wrap_ext) 517 { 518 int32_t val; 519 int i; 520 521 for (i = 0; i < 10; i++) { 522 /* mic */ 523 test_mic(c1, hc1, c2, hc2); 524 test_mic(c2, hc2, c1, hc1); 525 526 /* wrap */ 527 val = test_wrap(c1, hc1, c2, hc2, 0); 528 if (val) return val; 529 val = test_wrap(c2, hc2, c1, hc1, 0); 530 if (val) return val; 531 532 val = test_wrap(c1, hc1, c2, hc2, 1); 533 if (val) return val; 534 val = test_wrap(c2, hc2, c1, hc1, 1); 535 if (val) return val; 536 537 if (wrap_ext) { 538 /* wrap ext */ 539 val = test_wrap_ext(c1, hc1, c2, hc2, 1, 0); 540 if (val) return val; 541 val = test_wrap_ext(c2, hc2, c1, hc1, 1, 0); 542 if (val) return val; 543 544 val = test_wrap_ext(c1, hc1, c2, hc2, 1, 1); 545 if (val) return val; 546 val = test_wrap_ext(c2, hc2, c1, hc1, 1, 1); 547 if (val) return val; 548 549 val = test_wrap_ext(c1, hc1, c2, hc2, 0, 0); 550 if (val) return val; 551 val = test_wrap_ext(c2, hc2, c1, hc1, 0, 0); 552 if (val) return val; 553 554 val = test_wrap_ext(c1, hc1, c2, hc2, 0, 1); 555 if (val) return val; 556 val = test_wrap_ext(c2, hc2, c1, hc1, 0, 1); 557 if (val) return val; 558 } 559 } 560 return GSMERR_OK; 561 } 562 563 static int 564 log_function(void *ptr) 565 { 566 struct client *c = ptr; 567 int32_t cmd, line; 568 char *file, *string; 569 570 while (1) { 571 if (krb5_ret_int32(c->logsock, &cmd)) 572 goto out; 573 574 switch (cmd) { 575 case eLogSetMoniker: 576 if (krb5_ret_string(c->logsock, &file)) 577 goto out; 578 free(file); 579 break; 580 case eLogInfo: 581 case eLogFailure: 582 if (krb5_ret_string(c->logsock, &file)) 583 goto out; 584 if (krb5_ret_int32(c->logsock, &line)) 585 goto out; 586 if (krb5_ret_string(c->logsock, &string)) 587 goto out; 588 printf("%s:%lu: %s\n", 589 file, (unsigned long)line, string); 590 fprintf(logfile, "%s:%lu: %s\n", 591 file, (unsigned long)line, string); 592 fflush(logfile); 593 free(file); 594 free(string); 595 if (krb5_store_int32(c->logsock, 0)) 596 goto out; 597 break; 598 default: 599 errx(1, "client send bad log command: %d", (int)cmd); 600 } 601 } 602 out: 603 604 return 0; 605 } 606 607 static void 608 connect_client(const char *slave) 609 { 610 char *name, *port; 611 struct client *c = ecalloc(1, sizeof(*c)); 612 struct addrinfo hints, *res0, *res; 613 int ret, fd; 614 615 name = estrdup(slave); 616 port = strchr(name, ':'); 617 if (port == NULL) 618 errx(1, "port missing from %s", name); 619 *port++ = 0; 620 621 c->name = estrdup(slave); 622 623 memset(&hints, 0, sizeof(hints)); 624 hints.ai_family = PF_UNSPEC; 625 hints.ai_socktype = SOCK_STREAM; 626 627 ret = getaddrinfo(name, port, &hints, &res0); 628 if (ret) 629 errx(1, "error resolving %s", name); 630 631 for (res = res0, fd = -1; res; res = res->ai_next) { 632 fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 633 if (fd < 0) 634 continue; 635 if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) { 636 close(fd); 637 fd = -1; 638 continue; 639 } 640 c->sa = ecalloc(1, res->ai_addrlen); 641 memcpy(c->sa, res->ai_addr, res->ai_addrlen); 642 c->salen = res->ai_addrlen; 643 break; /* okay we got one */ 644 } 645 if (fd < 0) 646 err(1, "connect to host: %s", name); 647 freeaddrinfo(res); 648 649 c->sock = krb5_storage_from_fd(fd); 650 close(fd); 651 if (c->sock == NULL) 652 errx(1, "krb5_storage_from_fd"); 653 654 { 655 int32_t version; 656 char *str = NULL; 657 get_version_capa(c, &version, &c->capabilities, &str); 658 if (str) { 659 free(str); 660 } 661 if (c->capabilities & HAS_MONIKER) 662 get_moniker(c, &c->moniker); 663 else 664 c->moniker = c->name; 665 if (c->capabilities & ISSERVER) 666 get_targetname(c, &c->target_name); 667 } 668 669 if (logfile) { 670 int fd; 671 672 printf("starting log socket to client %s\n", c->moniker); 673 674 fd = wait_log(c); 675 676 c->logsock = krb5_storage_from_fd(fd); 677 close(fd); 678 if (c->logsock == NULL) 679 errx(1, "failed to create log krb5_storage"); 680 #ifdef ENABLE_PTHREAD_SUPPORT 681 pthread_create(&c->thr, NULL, log_function, c); 682 #else 683 c->child = fork(); 684 if (c->child == -1) 685 errx(1, "failed to fork"); 686 else if (c->child == 0) { 687 log_function(c); 688 fclose(logfile); 689 exit(0); 690 } 691 #endif 692 } 693 694 695 clients = erealloc(clients, (num_clients + 1) * sizeof(*clients)); 696 697 clients[num_clients] = c; 698 num_clients++; 699 700 free(name); 701 } 702 703 static struct client * 704 get_client(const char *slave) 705 { 706 size_t i; 707 for (i = 0; i < num_clients; i++) 708 if (strcmp(slave, clients[i]->name) == 0) 709 return clients[i]; 710 errx(1, "failed to find client %s", slave); 711 } 712 713 /* 714 * 715 */ 716 717 static int version_flag; 718 static int help_flag; 719 static int wrap_ext = 0; 720 static char *logfile_str; 721 static getarg_strings principals; 722 static getarg_strings slaves; 723 724 struct getargs args[] = { 725 { "principals", 0, arg_strings, &principals, "Test principal", 726 NULL }, 727 { "slaves", 0, arg_strings, &slaves, "Slaves", 728 NULL }, 729 { "log-file", 0, arg_string, &logfile_str, "Logfile", 730 NULL }, 731 { "wrap-ext", 0, arg_flag, &wrap_ext, "test wrap extended", 732 NULL }, 733 { "version", 0, arg_flag, &version_flag, "Print version", 734 NULL }, 735 { "help", 0, arg_flag, &help_flag, NULL, 736 NULL } 737 }; 738 739 static void 740 usage(int ret) 741 { 742 arg_printusage (args, 743 sizeof(args) / sizeof(args[0]), 744 NULL, 745 ""); 746 exit (ret); 747 } 748 749 int 750 main(int argc, char **argv) 751 { 752 int optidx= 0; 753 char *user; 754 char *password; 755 char ***list, **p; 756 size_t num_list, i, j, k; 757 int failed = 0; 758 759 setprogname (argv[0]); 760 761 if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 762 usage (1); 763 764 if (help_flag) 765 usage (0); 766 767 if (version_flag) { 768 print_version (NULL); 769 return 0; 770 } 771 772 if (optidx != argc) 773 usage (1); 774 775 if (principals.num_strings == 0) 776 errx(1, "no principals"); 777 778 user = estrdup(principals.strings[0]); 779 password = strchr(user, ':'); 780 if (password == NULL) 781 errx(1, "password missing from %s", user); 782 *password++ = 0; 783 784 if (slaves.num_strings == 0) 785 errx(1, "no principals"); 786 787 if (logfile_str) { 788 printf("open logfile %s\n", logfile_str); 789 logfile = fopen(logfile_str, "w+"); 790 if (logfile == NULL) 791 err(1, "failed to open: %s", logfile_str); 792 } 793 794 /* 795 * 796 */ 797 798 list = permutate_all(&slaves, &num_list); 799 800 /* 801 * Set up connection to all clients 802 */ 803 804 printf("Connecting to slaves\n"); 805 for (i = 0; i < slaves.num_strings; i++) 806 connect_client(slaves.strings[i]); 807 808 /* 809 * Test acquire credentials 810 */ 811 812 printf("Test acquire credentials\n"); 813 for (i = 0; i < slaves.num_strings; i++) { 814 int32_t hCred, val; 815 816 val = acquire_cred(clients[i], user, password, 1, &hCred); 817 if (val != GSMERR_OK) { 818 warnx("Failed to acquire_cred on host %s: %d", 819 clients[i]->moniker, (int)val); 820 failed = 1; 821 } else 822 toast_resource(clients[i], hCred); 823 } 824 825 if (failed) 826 goto out; 827 828 /* 829 * First test if all slaves can build context to them-self. 830 */ 831 832 printf("Self context tests\n"); 833 for (i = 0; i < num_clients; i++) { 834 int32_t hCred, val, delegCred; 835 int32_t clientC, serverC; 836 struct client *c = clients[i]; 837 838 if (c->target_name == NULL) 839 continue; 840 841 printf("%s connects to self using %s\n", 842 c->moniker, c->target_name); 843 844 val = acquire_cred(c, user, password, 1, &hCred); 845 if (val != GSMERR_OK) 846 errx(1, "failed to acquire_cred: %d", (int)val); 847 848 val = build_context(c, c, 849 GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG| 850 GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG| 851 GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG, 852 hCred, &clientC, &serverC, &delegCred); 853 if (val == GSMERR_OK) { 854 test_token(c, clientC, c, serverC, wrap_ext); 855 toast_resource(c, clientC); 856 toast_resource(c, serverC); 857 if (delegCred) 858 toast_resource(c, delegCred); 859 } else { 860 warnx("build_context failed: %d", (int)val); 861 } 862 /* 863 * 864 */ 865 866 val = build_context(c, c, 867 GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG, 868 hCred, &clientC, &serverC, &delegCred); 869 if (val == GSMERR_OK) { 870 test_token(c, clientC, c, serverC, wrap_ext); 871 toast_resource(c, clientC); 872 toast_resource(c, serverC); 873 if (delegCred) 874 toast_resource(c, delegCred); 875 } else { 876 warnx("build_context failed: %d", (int)val); 877 } 878 879 toast_resource(c, hCred); 880 } 881 /* 882 * Build contexts though all entries in each lists, including the 883 * step from the last entry to the first, ie treat the list as a 884 * circle. 885 * 886 * Only follow the delegated credential, but test "all" 887 * flags. (XXX only do deleg|mutual right now. 888 */ 889 890 printf("\"All\" permutation tests\n"); 891 892 for (i = 0; i < num_list; i++) { 893 int32_t hCred, val, delegCred = 0; 894 int32_t clientC = 0, serverC = 0; 895 struct client *client, *server; 896 897 p = list[i]; 898 899 client = get_client(p[0]); 900 901 val = acquire_cred(client, user, password, 1, &hCred); 902 if (val != GSMERR_OK) 903 errx(1, "failed to acquire_cred: %d", (int)val); 904 905 for (j = 1; j < num_clients + 1; j++) { 906 server = get_client(p[j % num_clients]); 907 908 if (server->target_name == NULL) 909 break; 910 911 for (k = 1; k < j; k++) 912 printf("\t"); 913 printf("%s -> %s\n", client->moniker, server->moniker); 914 915 val = build_context(client, server, 916 GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG| 917 GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG| 918 GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG, 919 hCred, &clientC, &serverC, &delegCred); 920 if (val != GSMERR_OK) { 921 warnx("build_context failed: %d", (int)val); 922 break; 923 } 924 925 val = test_token(client, clientC, server, serverC, wrap_ext); 926 if (val) 927 break; 928 929 toast_resource(client, clientC); 930 toast_resource(server, serverC); 931 if (!delegCred) { 932 warnx("no delegated cred on %s", server->moniker); 933 break; 934 } 935 toast_resource(client, hCred); 936 hCred = delegCred; 937 client = server; 938 } 939 if (hCred) 940 toast_resource(client, hCred); 941 } 942 943 /* 944 * Close all connections to clients 945 */ 946 947 out: 948 printf("sending goodbye and waiting for log sockets\n"); 949 for (i = 0; i < num_clients; i++) { 950 goodbye(clients[i]); 951 if (clients[i]->logsock) { 952 #ifdef ENABLE_PTHREAD_SUPPORT 953 pthread_join(&clients[i]->thr, NULL); 954 #else 955 waitpid(clients[i]->child, NULL, 0); 956 #endif 957 } 958 } 959 960 printf("done\n"); 961 962 return 0; 963 } 964