1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Test client for gssd. This program is not shipped on the binary 31 * release. 32 */ 33 34 #include <stdio.h> 35 #include <strings.h> 36 #include <ctype.h> 37 #include <stdlib.h> 38 #include <gssapi/gssapi.h> 39 #include <gssapi/gssapi_ext.h> 40 #include "gssd.h" 41 #include <rpc/rpc.h> 42 43 #define _KERNEL 44 #include <gssapi/gssapi.h> 45 #undef _KERNEL 46 47 int gss_major_code; 48 int gss_minor_code; 49 50 int init_sec_context_phase = 0; 51 int accept_sec_context_phase = 0; 52 53 gss_ctx_id_t initiator_context_handle; 54 gss_ctx_id_t acceptor_context_handle; 55 gss_cred_id_t acceptor_credentials; 56 gss_buffer_desc init_token_buffer; 57 gss_buffer_desc accept_token_buffer; 58 gss_buffer_desc delete_token_buffer; 59 gss_buffer_desc message_buffer; 60 gss_buffer_desc msg_token; 61 62 #define LOOP_COUNTER 100 63 #define GSS_KRB5_MECH_OID "1.2.840.113554.1.2.2" 64 #define GSS_DUMMY_MECH_OID "1.3.6.1.4.1.42.2.26.1.2" 65 #ifdef _KERNEL 66 #define OCTAL_MACRO "%03o." 67 #define MALLOC(n) kmem_alloc((n), KM_SLEEP) 68 #define CALLOC(n, s) kmem_zalloc((n)*(s), KM_SLEEP) 69 #define FREE(x, n) kmem_free((x), (n)) 70 #define memcpy(dst, src, n) bcopy((src), (dst), (n)) 71 #define fprintf(s, m) printf(m) 72 #define isspace(s) ((s) == ' ' || (s) == '\t' || (s) == '\n' || \ 73 (s) == '\r' || (s) == '\v' || (s) == '\f') 74 75 static char *strdup(const char *s) 76 { 77 int len = strlen(s); 78 char *new = MALLOC(len+1); 79 strcpy(new, s); 80 return (new); 81 } 82 83 #else /* !_KERNEL */ 84 #define OCTAL_MACRO "%03.3o." 85 #define MALLOC(n) malloc(n) 86 #define CALLOC(n, s) calloc((n), (s)) 87 #define FREE(x, n) free(x) 88 #endif /* _KERNEL */ 89 90 static gss_OID gss_str2oid(char *); 91 static char * gss_oid2str(gss_OID); 92 static void instructs(); 93 static void usage(); 94 static int parse_input_line(char *, int *, char ***); 95 extern uid_t getuid(); 96 97 static void _gss_init_sec_context(int, char **); 98 static void _gss_acquire_cred(int, char **); 99 static void _gss_add_cred(int, char **); 100 static void _gss_sign(int, char **); 101 static void _gss_release_cred(int, char **); 102 static void _gss_accept_sec_context(int, char **); 103 static void _gss_process_context_token(int, char **); 104 static void _gss_delete_sec_context(int, char **); 105 static void _gss_context_time(int, char **); 106 static void _gss_verify(int, char **); 107 static void _gss_seal(int, char **); 108 static void _gss_unseal(int, char **); 109 static void _gss_display_status(int, char **); 110 static void _gss_indicate_mechs(int, char **); 111 static void _gss_inquire_cred(int, char **); 112 static void _gssd_expname_to_unix_cred(int, char **); 113 static void _gssd_name_to_unix_cred(int, char **); 114 static void _gssd_get_group_info(int, char **); 115 116 static int do_gssdtest(char *buf); 117 118 119 #ifndef _KERNEL 120 static int read_line(char *buf, int size) 121 { 122 int len; 123 124 /* read the next line. If cntl-d, return with zero char count */ 125 printf(gettext("\n> ")); 126 127 if (fgets(buf, size, stdin) == NULL) 128 return (0); 129 130 len = strlen(buf); 131 buf[--len] = '\0'; 132 return (len); 133 } 134 135 int 136 main() 137 { 138 char buf[512]; 139 int len, ret; 140 141 /* Print out usage and instructions to start off the session */ 142 143 instructs(); 144 usage(); 145 146 /* 147 * Loop, repeatedly calling parse_input_line() to get the 148 * next line and parse it into argc and argv. Act on the 149 * arguements found on the line. 150 */ 151 152 do { 153 len = read_line(buf, 512); 154 if (len) 155 ret = do_gssdtest(buf); 156 } while (len && !ret); 157 158 return (0); 159 } 160 #endif /* !_KERNEL */ 161 162 static int 163 do_gssdtest(char *buf) 164 { 165 int argc, seal_argc; 166 int i; 167 char **argv, **argv_array; 168 169 char *cmd; 170 char *seal_ini_array [] = { "initiator", " Hello"}; 171 char *seal_acc_array [] = { "acceptor", " Hello"}; 172 char *unseal_acc_array [] = {"acceptor"}; 173 char *unseal_ini_array [] = {"initiator"}; 174 char *delet_acc_array [] = {"acceptor"}; 175 char *delet_ini_array [] = {"initiator"}; 176 177 argv = 0; 178 179 if (parse_input_line(buf, &argc, &argv) == 0) { 180 printf(gettext("\n")); 181 return (1); 182 } 183 184 if (argc == 0) { 185 usage(); 186 /*LINTED*/ 187 FREE(argv_array, (argc+1)*sizeof (char *)); 188 return (0); 189 } 190 191 /* 192 * remember argv_array address, which is memory calloc'd by 193 * parse_input_line, so it can be free'd at the end of the loop. 194 */ 195 196 argv_array = argv; 197 198 cmd = argv[0]; 199 200 argc--; 201 argv++; 202 203 if (strcmp(cmd, "gss_loop") == 0 || 204 strcmp(cmd, "loop") == 0) { 205 206 if (argc < 1) { 207 usage(); 208 FREE(argv_array, (argc+2) * sizeof (char *)); 209 return (0); 210 } 211 for (i = 0; i < LOOP_COUNTER; i++) { 212 printf(gettext("Loop Count is %d \n"), i); 213 /* 214 * if (i > 53) 215 * printf ("Loop counter is greater than 55\n"); 216 */ 217 _gss_acquire_cred(argc, argv); 218 _gss_init_sec_context(argc, argv); 219 _gss_accept_sec_context(0, argv); 220 _gss_init_sec_context(argc, argv); 221 222 seal_argc = 2; 223 _gss_seal(seal_argc, seal_ini_array); 224 seal_argc = 1; 225 _gss_unseal(seal_argc, unseal_acc_array); 226 seal_argc = 2; 227 _gss_seal(seal_argc, seal_acc_array); 228 seal_argc = 1; 229 _gss_unseal(seal_argc, unseal_ini_array); 230 seal_argc = 2; 231 _gss_sign(seal_argc, seal_ini_array); 232 seal_argc = 1; 233 _gss_verify(seal_argc, unseal_acc_array); 234 seal_argc = 2; 235 _gss_sign(seal_argc, seal_acc_array); 236 seal_argc = 1; 237 _gss_verify(seal_argc, unseal_ini_array); 238 _gss_delete_sec_context(argc, delet_acc_array); 239 _gss_delete_sec_context(argc, delet_ini_array); 240 } 241 } 242 if (strcmp(cmd, "gss_all") == 0 || 243 strcmp(cmd, "all") == 0) { 244 _gss_acquire_cred(argc, argv); 245 _gss_init_sec_context(argc, argv); 246 _gss_accept_sec_context(0, argv); 247 _gss_init_sec_context(argc, argv); 248 249 seal_argc = 2; 250 _gss_seal(seal_argc, seal_acc_array); 251 seal_argc = 1; 252 _gss_unseal(seal_argc, unseal_ini_array); 253 seal_argc = 2; 254 _gss_seal(seal_argc, seal_ini_array); 255 seal_argc = 1; 256 _gss_unseal(seal_argc, unseal_acc_array); 257 seal_argc = 2; 258 _gss_sign(seal_argc, seal_ini_array); 259 seal_argc = 1; 260 _gss_verify(seal_argc, unseal_acc_array); 261 seal_argc = 2; 262 _gss_sign(seal_argc, seal_acc_array); 263 seal_argc = 1; 264 _gss_verify(seal_argc, unseal_ini_array); 265 266 } 267 if (strcmp(cmd, "gss_acquire_cred") == 0 || 268 strcmp(cmd, "acquire") == 0) { 269 _gss_acquire_cred(argc, argv); 270 if (argc == 1) 271 _gss_add_cred(argc, argv); 272 } 273 274 else if (strcmp(cmd, "gss_release_cred") == 0 || 275 strcmp(cmd, "release") == 0) 276 _gss_release_cred(argc, argv); 277 else if (strcmp(cmd, "gss_init_sec_context") == 0 || 278 strcmp(cmd, "init") == 0) 279 _gss_init_sec_context(argc, argv); 280 else if (strcmp(cmd, "gss_accept_sec_context") == 0 || 281 strcmp(cmd, "accept") == 0) 282 _gss_accept_sec_context(argc, argv); 283 else if (strcmp(cmd, "gss_process_context_token") == 0 || 284 strcmp(cmd, "process") == 0) 285 _gss_process_context_token(argc, argv); 286 else if (strcmp(cmd, "gss_delete_sec_context") == 0 || 287 strcmp(cmd, "delete") == 0) 288 _gss_delete_sec_context(argc, argv); 289 else if (strcmp(cmd, "gss_context_time") == 0 || 290 strcmp(cmd, "time") == 0) 291 _gss_context_time(argc, argv); 292 else if (strcmp(cmd, "gss_sign") == 0 || 293 strcmp(cmd, "sign") == 0) 294 _gss_sign(argc, argv); 295 else if (strcmp(cmd, "gss_verify") == 0 || 296 strcmp(cmd, "verify") == 0) 297 _gss_verify(argc, argv); 298 else if (strcmp(cmd, "gss_seal") == 0 || 299 strcmp(cmd, "seal") == 0) 300 _gss_seal(argc, argv); 301 else if (strcmp(cmd, "gss_unseal") == 0 || 302 strcmp(cmd, "unseal") == 0) 303 _gss_unseal(argc, argv); 304 else if (strcmp(cmd, "gss_display_status") == 0|| 305 strcmp(cmd, "status") == 0) 306 _gss_display_status(argc, argv); 307 else if (strcmp(cmd, "gss_indicate_mechs") == 0 || 308 strcmp(cmd, "indicate") == 0) 309 _gss_indicate_mechs(argc, argv); 310 else if (strcmp(cmd, "gss_inquire_cred") == 0 || 311 strcmp(cmd, "inquire") == 0) 312 _gss_inquire_cred(argc, argv); 313 else if (strcmp(cmd, "expname2unixcred") == 0 || 314 strcmp(cmd, "gsscred_expname_to_unix_cred") == 0) 315 _gssd_expname_to_unix_cred(argc, argv); 316 else if (strcmp(cmd, "name2unixcred") == 0 || 317 strcmp(cmd, "gsscred_name_to_unix_cred") == 0) 318 _gssd_name_to_unix_cred(argc, argv); 319 else if (strcmp(cmd, "grpinfo") == 0 || 320 strcmp(cmd, "gss_get_group_info") == 0) 321 _gssd_get_group_info(argc, argv); 322 else if (strcmp(cmd, "exit") == 0) { 323 printf(gettext("\n")); 324 FREE(argv_array, (argc+2) * sizeof (char *)); 325 return (1); 326 } else 327 usage(); 328 329 /* free argv array */ 330 331 FREE(argv_array, (argc+2) * sizeof (char *)); 332 return (0); 333 } 334 335 static void 336 _gss_acquire_cred(argc, argv) 337 int argc; 338 char **argv; 339 { 340 341 OM_UINT32 status, minor_status; 342 gss_buffer_desc name; 343 gss_name_t desired_name = (gss_name_t) 0; 344 OM_uint32 time_req; 345 gss_OID_set_desc desired_mechs_desc; 346 gss_OID_set desired_mechs = &desired_mechs_desc; 347 int cred_usage; 348 gss_OID_set actual_mechs = GSS_C_NULL_OID_SET; 349 gss_OID_set inquire_mechs = GSS_C_NULL_OID_SET; 350 OM_UINT32 time_rec; 351 char * string; 352 char * inq_string; 353 uid_t uid; 354 gss_OID mech_type; 355 356 /* 357 * First set up the command line independent input arguments. 358 */ 359 360 time_req = (OM_uint32) 0; 361 cred_usage = GSS_C_ACCEPT; 362 uid = getuid(); 363 364 /* Parse the command line for the variable input arguments */ 365 366 if (argc == 0) { 367 usage(); 368 return; 369 } 370 371 /* 372 * Get the name of the principal. 373 */ 374 375 name.length = strlen(argv[0])+1; 376 name.value = argv[0]; 377 378 /* 379 * Now convert the string given by the first argument into internal 380 * form suitable for input to gss_acquire_cred() 381 */ 382 383 if ((status = gss_import_name(&minor_status, &name, 384 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &desired_name)) 385 != GSS_S_COMPLETE) { 386 printf(gettext( 387 "could not parse desired name: err (octal) %o (%s)\n"), 388 status, gettext("gss_acquire_cred error")); 389 return; 390 } 391 392 argc--; 393 argv++; 394 395 /* 396 * The next argument is an OID in dotted decimal form. 397 */ 398 399 if (argc == 0) { 400 printf(gettext("Assuming Kerberos V5 as the mechanism\n")); 401 printf(gettext( 402 "The mech OID 1.2.840.113554.1.2.2 will be used\n")); 403 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID); 404 } else 405 mech_type = gss_str2oid(argv[0]); 406 407 if (mech_type == 0 || mech_type->length == 0) { 408 printf(gettext("improperly formated mechanism OID\n")); 409 return; 410 } 411 412 /* 413 * set up desired_mechs so it points to mech_type. 414 */ 415 416 desired_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_desc)); 417 418 desired_mechs->count = 1; 419 desired_mechs->elements = mech_type; 420 421 status = kgss_acquire_cred( 422 &minor_status, 423 desired_name, 424 time_req, 425 desired_mechs, 426 cred_usage, 427 &acceptor_credentials, 428 &actual_mechs, 429 &time_rec, 430 uid); 431 432 /* store major and minor status for gss_display_status() call */ 433 434 gss_major_code = status; 435 gss_minor_code = minor_status; 436 437 if (status == GSS_S_COMPLETE) { 438 /* process returned values */ 439 440 printf(gettext("\nacquire succeeded\n\n")); 441 442 /* 443 * print out the actual mechs returned NB: Since only one 444 * mechanism is specified in desired_mechs, only one 445 * can be returned in actual_mechs. Consequently, 446 * actual_mechs->elements points to an array of only one 447 * element. 448 */ 449 450 if ((string = gss_oid2str(actual_mechs->elements)) == 0) { 451 printf(gettext("actual mechs == NULL\n\n")); 452 } else { 453 printf(gettext("actual mechs = %s\n\n"), string); 454 FREE(string, (actual_mechs->elements->length+1)*4+1); 455 } 456 457 if (cred_usage == GSS_C_BOTH) 458 printf(gettext("GSS_C_BOTH\n\n")); 459 460 if (cred_usage == GSS_C_INITIATE) 461 printf(gettext("GSS_C_INITIATE\n\n")); 462 463 if (cred_usage == GSS_C_ACCEPT) 464 printf(gettext("GSS_C_ACCEPT\n\n")); 465 status = kgss_inquire_cred( 466 &minor_status, 467 acceptor_credentials, 468 NULL, 469 &time_req, 470 &cred_usage, 471 &inquire_mechs, 472 uid); 473 474 if (status != GSS_S_COMPLETE) 475 printf(gettext("server ret err (octal) %o (%s)\n"), 476 status, gettext("gss_inquire_cred error")); 477 else { 478 if ((inq_string = 479 gss_oid2str(inquire_mechs->elements)) == 0) { 480 printf(gettext 481 ("mechs from inquire == NULL\n\n")); 482 } else { 483 printf(gettext 484 ("mechs from inquiry = %s\n\n"), 485 inq_string); 486 FREE(inq_string, 487 (inquire_mechs->elements->length+1)*4+1); 488 } 489 printf(gettext("inquire_cred successful \n\n")); 490 } 491 492 } else { 493 printf(gettext("server ret err (octal) %o (%s)\n"), 494 status, gettext("gss_acquire_cred error")); 495 } 496 497 /* free allocated memory */ 498 499 /* actual mechs is allocated by clnt_stubs. Release it here */ 500 if (actual_mechs != GSS_C_NULL_OID_SET) 501 gss_release_oid_set_and_oids(&minor_status, &actual_mechs); 502 if (inquire_mechs != GSS_C_NULL_OID_SET) 503 gss_release_oid_set_and_oids(&minor_status, &inquire_mechs); 504 505 gss_release_name(&minor_status, &desired_name); 506 507 /* mech_type and desired_mechs are allocated above. Release it here */ 508 509 FREE(mech_type->elements, mech_type->length); 510 FREE(mech_type, sizeof (gss_OID_desc)); 511 FREE(desired_mechs, sizeof (gss_OID_desc)); 512 } 513 514 static void 515 _gss_add_cred(argc, argv) 516 int argc; 517 char **argv; 518 { 519 520 OM_UINT32 status, minor_status; 521 gss_buffer_desc name; 522 gss_name_t desired_name = (gss_name_t) 0; 523 OM_uint32 time_req; 524 OM_uint32 initiator_time_req; 525 OM_uint32 acceptor_time_req; 526 int cred_usage; 527 gss_OID_set actual_mechs = GSS_C_NULL_OID_SET; 528 gss_OID_set inquire_mechs = GSS_C_NULL_OID_SET; 529 char * string; 530 uid_t uid; 531 gss_OID mech_type; 532 int i; 533 534 /* 535 * First set up the command line independent input arguments. 536 */ 537 538 initiator_time_req = (OM_uint32) 0; 539 acceptor_time_req = (OM_uint32) 0; 540 cred_usage = GSS_C_ACCEPT; 541 uid = getuid(); 542 543 /* Parse the command line for the variable input arguments */ 544 545 if (argc == 0) { 546 usage(); 547 return; 548 } 549 550 /* 551 * Get the name of the principal. 552 */ 553 554 name.length = strlen(argv[0])+1; 555 name.value = argv[0]; 556 557 /* 558 * Now convert the string given by the first argument into internal 559 * form suitable for input to gss_acquire_cred() 560 */ 561 562 if ((status = gss_import_name(&minor_status, &name, 563 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &desired_name)) 564 != GSS_S_COMPLETE) { 565 printf(gettext( 566 "could not parse desired name: err (octal) %o (%s)\n"), 567 status, gettext("gss_acquire_cred error")); 568 return; 569 } 570 571 argc--; 572 argv++; 573 574 /* 575 * The next argument is an OID in dotted decimal form. 576 */ 577 578 if (argc == 0) { 579 printf(gettext("Assuming dummy as the mechanism\n")); 580 printf(gettext( 581 "The mech OID 1.3.6.1.4.1.42.2.26.1.2 will be used\n")); 582 mech_type = gss_str2oid((char *)GSS_DUMMY_MECH_OID); 583 } else 584 mech_type = gss_str2oid(argv[0]); 585 586 if (mech_type == 0 || mech_type->length == 0) { 587 printf(gettext("improperly formated mechanism OID\n")); 588 return; 589 } 590 591 /* 592 * set up desired_mechs so it points to mech_type. 593 */ 594 595 status = kgss_add_cred( 596 &minor_status, 597 acceptor_credentials, 598 desired_name, 599 mech_type, 600 cred_usage, 601 initiator_time_req, 602 acceptor_time_req, 603 &actual_mechs, 604 NULL, 605 NULL, 606 uid); 607 608 /* store major and minor status for gss_display_status() call */ 609 610 gss_major_code = status; 611 gss_minor_code = minor_status; 612 if (status == GSS_S_COMPLETE) { 613 /* process returned values */ 614 615 printf(gettext("\nadd succeeded\n\n")); 616 if (actual_mechs) { 617 for (i = 0; i < actual_mechs->count; i++) { 618 if ((string = 619 gss_oid2str 620 (&actual_mechs->elements[i])) == 0) { 621 printf(gettext 622 ("actual mechs == NULL\n\n")); 623 } else { 624 printf(gettext 625 ("actual mechs = %s\n\n"), string); 626 FREE(string, 627 (actual_mechs->elements->length+1)*4+1); 628 } 629 } 630 } 631 /* 632 * Try adding the cred again for the same mech 633 * We should get GSS_S_DUPLICATE_ELEMENT 634 * if not return an error 635 */ 636 status = kgss_add_cred( 637 &minor_status, 638 acceptor_credentials, 639 desired_name, 640 mech_type, 641 cred_usage, 642 initiator_time_req, 643 acceptor_time_req, 644 NULL, /* &actual_mechs, */ 645 NULL, 646 NULL, 647 uid); 648 if (status != GSS_S_DUPLICATE_ELEMENT) { 649 printf(gettext("Expected duplicate element, Got " 650 " (octal) %o (%s)\n"), 651 status, gettext("gss_add_cred error")); 652 } 653 status = kgss_inquire_cred( 654 &minor_status, 655 acceptor_credentials, 656 NULL, 657 &time_req, 658 &cred_usage, 659 &inquire_mechs, 660 uid); 661 662 if (status != GSS_S_COMPLETE) 663 printf(gettext("server ret err (octal) %o (%s)\n"), 664 status, gettext("gss_inquire_cred error")); 665 else { 666 for (i = 0; i < inquire_mechs->count; i++) { 667 if ((string = 668 gss_oid2str 669 (&inquire_mechs->elements[i])) == 0) { 670 printf(gettext 671 ("inquire_mechs mechs == NULL\n\n")); 672 } else { 673 printf(gettext 674 ("inquire_cred mechs = %s\n\n"), 675 string); 676 FREE(string, 677 (inquire_mechs->elements->length+1)*4 678 +1); 679 } 680 } 681 printf(gettext("inquire_cred successful \n\n")); 682 } 683 684 } else { 685 printf(gettext("server ret err (octal) %o (%s)\n"), 686 status, gettext("gss_acquire_cred error")); 687 } 688 689 /* Let us do inquire_cred_by_mech for both mechanisms */ 690 status = kgss_inquire_cred_by_mech( 691 &minor_status, 692 acceptor_credentials, 693 mech_type, 694 uid); 695 if (status != GSS_S_COMPLETE) 696 printf(gettext("server ret err (octal) %o (%s)\n"), 697 status, gettext("gss_inquire_cred_by_mech")); 698 else 699 printf(gettext("gss_inquire_cred_by_mech successful")); 700 701 702 FREE(mech_type->elements, mech_type->length); 703 FREE(mech_type, sizeof (gss_OID_desc)); 704 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID); 705 status = kgss_inquire_cred_by_mech( 706 &minor_status, 707 acceptor_credentials, 708 mech_type, 709 uid); 710 if (status != GSS_S_COMPLETE) 711 printf(gettext("server ret err (octal) %o (%s)\n"), 712 status, gettext 713 ("gss_inquire_cred_by_mech for dummy mech error")); 714 715 /* free allocated memory */ 716 717 /* actual mechs is allocated by clnt_stubs. Release it here */ 718 if (actual_mechs != GSS_C_NULL_OID_SET) 719 gss_release_oid_set_and_oids(&minor_status, &actual_mechs); 720 if (inquire_mechs != GSS_C_NULL_OID_SET) 721 gss_release_oid_set_and_oids(&minor_status, &inquire_mechs); 722 723 gss_release_name(&minor_status, &desired_name); 724 725 /* mech_type and desired_mechs are allocated above. Release it here */ 726 727 FREE(mech_type->elements, mech_type->length); 728 FREE(mech_type, sizeof (gss_OID_desc)); 729 } 730 731 /*ARGSUSED*/ 732 static void 733 _gss_release_cred(argc, argv) 734 int argc; 735 char **argv; 736 { 737 OM_UINT32 status; 738 OM_UINT32 minor_status; 739 uid_t uid; 740 741 /* set up input arguments here */ 742 743 if (argc != 0) { 744 usage(); 745 return; 746 } 747 748 uid = getuid(); 749 750 status = kgss_release_cred( 751 &minor_status, 752 &acceptor_credentials, 753 uid); 754 755 /* store major and minor status for gss_display_status() call */ 756 757 gss_major_code = status; 758 gss_minor_code = minor_status; 759 760 if (status == GSS_S_COMPLETE) { 761 printf(gettext("\nrelease succeeded\n\n")); 762 } else { 763 printf(gettext("server ret err (octal) %o (%s)\n"), 764 status, gettext("gss_release_cred error")); 765 } 766 } 767 768 static void 769 _gss_init_sec_context(argc, argv) 770 int argc; 771 char **argv; 772 { 773 774 OM_uint32 status; 775 776 OM_uint32 minor_status; 777 gss_cred_id_t claimant_cred_handle; 778 gss_name_t target_name = (gss_name_t) 0; 779 gss_OID mech_type = (gss_OID) 0; 780 int req_flags; 781 OM_uint32 time_req; 782 gss_channel_bindings_t input_chan_bindings; 783 gss_buffer_t input_token; 784 gss_buffer_desc context_token; 785 gss_OID actual_mech_type; 786 int ret_flags; 787 OM_uint32 time_rec; 788 uid_t uid; 789 char * string; 790 gss_buffer_desc name; 791 792 /* 793 * If this is the first phase of the context establishment, 794 * clear initiator_context_handle and indicate next phase. 795 */ 796 797 if (init_sec_context_phase == 0) { 798 initiator_context_handle = GSS_C_NO_CONTEXT; 799 input_token = GSS_C_NO_BUFFER; 800 init_sec_context_phase = 1; 801 } else 802 input_token = &init_token_buffer; 803 804 /* 805 * First set up the non-variable command line independent input 806 * arguments 807 */ 808 809 claimant_cred_handle = GSS_C_NO_CREDENTIAL; 810 811 req_flags = GSS_C_MUTUAL_FLAG; 812 time_req = (OM_uint32) 0; 813 input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; 814 uid = getuid(); 815 816 /* Now parse the command line for the remaining input arguments */ 817 818 if (argc == 0) { 819 usage(); 820 return; 821 } 822 823 /* 824 * Get the name of the target. 825 */ 826 827 name.length = strlen(argv[0])+1; 828 name.value = argv[0]; 829 830 /* 831 * Now convert the string given by the first argument into a target 832 * name suitable for input to gss_init_sec_context() 833 */ 834 835 if ((status = gss_import_name(&minor_status, &name, 836 /* GSS_C_NULL_OID, &target_name)) */ 837 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &target_name)) 838 != GSS_S_COMPLETE) { 839 printf(gettext( 840 "could not parse target name: err (octal) %o (%s)\n"), 841 status, 842 gettext("gss_init_sec_context error")); 843 if (input_token != GSS_C_NO_BUFFER) 844 gss_release_buffer(&minor_status, &init_token_buffer); 845 init_sec_context_phase = 0; 846 return; 847 } 848 849 argc--; 850 argv++; 851 852 if (argc == 0) { 853 printf(gettext("Assuming Kerberos V5 as the mechanism\n")); 854 printf(gettext( 855 "The mech OID 1.2.840.113554.1.2.2 will be used\n")); 856 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID); 857 } else { 858 mech_type = gss_str2oid(argv[0]); 859 } 860 861 if (mech_type == 0 || mech_type->length == 0) { 862 printf(gettext("improperly formated mechanism OID\n")); 863 if (input_token != GSS_C_NO_BUFFER) 864 gss_release_buffer(&minor_status, &init_token_buffer); 865 init_sec_context_phase = 0; 866 return; 867 } 868 869 /* call kgss_init_sec_context */ 870 871 status = kgss_init_sec_context(&minor_status, 872 claimant_cred_handle, 873 &initiator_context_handle, 874 target_name, 875 mech_type, 876 req_flags, 877 time_req, 878 input_chan_bindings, 879 input_token, 880 &actual_mech_type, 881 &accept_token_buffer, 882 &ret_flags, 883 &time_rec, 884 uid); 885 886 /* store major and minor status for gss_display_status() call */ 887 gss_major_code = status; 888 gss_minor_code = minor_status; 889 890 if (status != GSS_S_COMPLETE && 891 status != GSS_S_CONTINUE_NEEDED) { 892 893 printf(gettext("server ret err (octal) %o (%s)\n"), 894 status, "gss_init_sec_context error"); 895 init_sec_context_phase = 0; 896 if (status == GSS_S_NO_CRED) 897 printf(gettext(" : no credentials")); 898 if (input_token != GSS_C_NO_BUFFER) 899 gss_release_buffer(&minor_status, &init_token_buffer); 900 if (status != GSS_S_FAILURE && minor_status != 0xffffffff) 901 status = kgss_delete_sec_context(&minor_status, 902 &initiator_context_handle, 903 &msg_token); 904 return; 905 906 } else if (status == GSS_S_COMPLETE) { 907 908 /* process returned values */ 909 910 printf(gettext("\ninit succeeded\n\n")); 911 912 /* print out the actual mechanism type */ 913 914 if ((string = gss_oid2str(actual_mech_type)) == 0) { 915 916 printf(gettext( 917 "gssapi internal err : actual " 918 "mech type null\n")); 919 init_sec_context_phase = 0; 920 if (input_token != GSS_C_NO_BUFFER) 921 gss_release_buffer(&minor_status, 922 &init_token_buffer); 923 gss_release_buffer(&minor_status, &accept_token_buffer); 924 status = kgss_delete_sec_context(&minor_status, 925 &initiator_context_handle, 926 &msg_token); 927 return; 928 } else { 929 printf(gettext("actual mech type = %s\n\n"), string); 930 FREE(string, (actual_mech_type->length+1)*4+1); 931 } 932 933 /* print out value of ret_flags and time_req */ 934 935 if (ret_flags & GSS_C_DELEG_FLAG) 936 printf(gettext("GSS_C_DELEG_FLAG = True\n")); 937 else 938 printf(gettext("GSS_C_DELEG_FLAG = False\n")); 939 940 if (ret_flags & GSS_C_MUTUAL_FLAG) 941 printf(gettext("GSS_C_MUTUAL_FLAG = True\n")); 942 else 943 printf(gettext("GSS_C_MUTUAL_FLAG = False\n")); 944 945 if (ret_flags & GSS_C_REPLAY_FLAG) 946 printf(gettext("GSS_C_REPLAY_FLAG = True\n")); 947 else 948 printf(gettext("GSS_C_REPLAY_FLAG = False\n")); 949 950 if (ret_flags & GSS_C_SEQUENCE_FLAG) 951 printf(gettext("GSS_C_SEQUENCE_FLAG = True\n")); 952 else 953 printf(gettext("GSS_C_SEQUENCE_FLAG = False\n")); 954 955 if (ret_flags & GSS_C_CONF_FLAG) 956 printf(gettext("GSS_C_CONF_FLAG = True\n")); 957 else 958 printf(gettext("GSS_C_CONF_FLAG = False\n")); 959 960 if (ret_flags & GSS_C_INTEG_FLAG) 961 printf(gettext("GSS_C_INTEG_FLAG = True\n\n")); 962 else 963 printf(gettext("GSS_C_INTEG_FLAG = False\n\n")); 964 965 printf(gettext("time_req = %u seconds\n\n"), time_rec); 966 967 /* free allocated memory */ 968 969 FREE(mech_type->elements, mech_type->length); 970 FREE(mech_type, sizeof (gss_OID_desc)); 971 972 /* these two were malloc'd by kgss_init_sec_context() */ 973 974 FREE(actual_mech_type->elements, actual_mech_type->length); 975 FREE(actual_mech_type, sizeof (gss_OID_desc)); 976 977 gss_release_name(&minor_status, &target_name); 978 979 if (input_token != GSS_C_NO_BUFFER) 980 gss_release_buffer(&minor_status, &init_token_buffer); 981 982 /* 983 * if status == GSS_S_COMPLETE, reset the phase to 0 and 984 * release token in accept_token_buffer 985 */ 986 987 init_sec_context_phase = 0; 988 /* Save and restore the context */ 989 status = kgss_export_sec_context(&minor_status, 990 &initiator_context_handle, 991 &context_token); 992 if (status != GSS_S_COMPLETE) { 993 printf(gettext("server ret err (octal) %o (%s)\n"), 994 status, gettext("gss_export_sec_context_error")); 995 return; 996 } 997 status = kgss_import_sec_context(&minor_status, 998 &context_token, 999 &initiator_context_handle); 1000 if (status != GSS_S_COMPLETE) { 1001 printf(gettext("server ret err (octal) %o (%s)\n"), 1002 status, gettext("gss_import_sec_context_error")); 1003 return; 1004 } 1005 (void) gss_release_buffer(&minor_status, &context_token); 1006 1007 /* gss_export & gss_import secxc_context worked, return */ 1008 printf(gettext("\nexport and import of contexts succeeded\n")); 1009 printf(gettext("\ninit completed")); 1010 1011 } else { 1012 printf(gettext("\nfirst phase of init succeeded")); 1013 printf(gettext("\ninit must be called again\n\n")); 1014 } 1015 1016 } 1017 1018 /*ARGSUSED*/ 1019 static void 1020 _gss_accept_sec_context(argc, argv) 1021 int argc; 1022 char **argv; 1023 { 1024 OM_UINT32 status; 1025 1026 OM_uint32 minor_status; 1027 gss_channel_bindings_t input_chan_bindings; 1028 gss_OID mech_type; 1029 int ret_flags; 1030 OM_uint32 time_rec; 1031 gss_cred_id_t delegated_cred_handle; 1032 uid_t uid; 1033 char *string; 1034 gss_buffer_desc src_name, src_name_string; 1035 gss_buffer_desc output_token; 1036 gss_name_t gss_name; 1037 gss_buffer_desc context_token; 1038 1039 /* 1040 * If this is the first phase of the context establishment, 1041 * clear acceptor_context_handle and indicate next phase. 1042 */ 1043 1044 if (accept_sec_context_phase == 0) { 1045 acceptor_context_handle = GSS_C_NO_CONTEXT; 1046 accept_sec_context_phase = 1; 1047 } 1048 1049 /* Now set up the other command line independent input arguments */ 1050 1051 input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; 1052 1053 uid = (uid_t) getuid(); 1054 1055 if (argc != 0) { 1056 usage(); 1057 return; 1058 } 1059 1060 status = kgss_accept_sec_context(&minor_status, 1061 &acceptor_context_handle, 1062 acceptor_credentials, 1063 &accept_token_buffer, 1064 input_chan_bindings, 1065 &src_name, 1066 &mech_type, 1067 &init_token_buffer, 1068 &ret_flags, 1069 &time_rec, 1070 &delegated_cred_handle, 1071 uid); 1072 1073 /* store major and minor status for gss_display_status() call */ 1074 1075 gss_major_code = status; 1076 gss_minor_code = minor_status; 1077 1078 if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) { 1079 printf(gettext("server ret err (octal) %o (%s)\n"), 1080 status, gettext("gss_accept_sec_context error")); 1081 gss_release_buffer(&minor_status, &accept_token_buffer); 1082 return; 1083 } else if (status == GSS_S_COMPLETE) { 1084 1085 /* process returned values */ 1086 1087 printf(gettext("\naccept succeeded\n\n")); 1088 1089 /* 1090 * convert the exported name returned in src_name into 1091 * a string and print it. 1092 */ 1093 if ((status = gss_import_name(&minor_status, &src_name, 1094 (gss_OID) GSS_C_NT_EXPORT_NAME, &gss_name)) 1095 != GSS_S_COMPLETE) { 1096 printf(gettext( 1097 "could not import src name 0x%x\n"), status); 1098 accept_sec_context_phase = 0; 1099 status = kgss_delete_sec_context(&minor_status, 1100 &acceptor_context_handle, 1101 &output_token); 1102 gss_release_buffer(&minor_status, &accept_token_buffer); 1103 if (status == GSS_S_CONTINUE_NEEDED) 1104 gss_release_buffer(&minor_status, 1105 &init_token_buffer); 1106 gss_release_buffer(&minor_status, &src_name); 1107 return; 1108 } 1109 1110 memset(&src_name_string, 0, sizeof (src_name_string)); 1111 if ((status = gss_display_name(&minor_status, gss_name, 1112 &src_name_string, NULL)) != GSS_S_COMPLETE) { 1113 printf(gettext("could not display src name: " 1114 "err (octal) %o (%s)\n"), status, 1115 "gss_init_sec_context error"); 1116 accept_sec_context_phase = 0; 1117 status = kgss_delete_sec_context(&minor_status, 1118 &acceptor_context_handle, 1119 &output_token); 1120 gss_release_buffer(&minor_status, &accept_token_buffer); 1121 if (status == GSS_S_CONTINUE_NEEDED) 1122 gss_release_buffer(&minor_status, 1123 &init_token_buffer); 1124 gss_release_buffer(&minor_status, &src_name); 1125 return; 1126 } 1127 printf(gettext("src name = %s\n"), src_name_string.value); 1128 gss_release_name(&minor_status, &gss_name); 1129 gss_release_buffer(&minor_status, &src_name_string); 1130 gss_release_buffer(&minor_status, &src_name); 1131 1132 /* print out the mechanism type */ 1133 1134 if ((string = gss_oid2str(mech_type)) == 0) { 1135 1136 printf(gettext( 1137 "gssapi internal err :" 1138 " actual mech type null\n")); 1139 accept_sec_context_phase = 0; 1140 status = kgss_delete_sec_context(&minor_status, 1141 &acceptor_context_handle, 1142 &output_token); 1143 gss_release_buffer(&minor_status, &accept_token_buffer); 1144 if (status == GSS_S_CONTINUE_NEEDED) 1145 gss_release_buffer(&minor_status, 1146 &init_token_buffer); 1147 return; 1148 } else { 1149 1150 printf(gettext("actual mech type = %s\n\n"), string); 1151 FREE(string, (mech_type->length+1)*4+1); 1152 } 1153 1154 /* Save and restore the context */ 1155 status = kgss_export_sec_context(&minor_status, 1156 &initiator_context_handle, 1157 &context_token); 1158 if (status != GSS_S_COMPLETE) { 1159 printf(gettext("server ret err (octal) %o (%s)\n"), 1160 status, gettext("gss_export_sec_context_error")); 1161 return; 1162 } 1163 status = kgss_import_sec_context(&minor_status, 1164 &context_token, 1165 &initiator_context_handle); 1166 if (status != GSS_S_COMPLETE) { 1167 printf(gettext("server ret err (octal) %o (%s)\n"), 1168 status, gettext("gss_import_sec_context_error")); 1169 return; 1170 } 1171 (void) gss_release_buffer(&minor_status, &context_token); 1172 1173 /* gss_export & gss_import secxc_context worked, return */ 1174 1175 /* print out value of ret_flags and time_req */ 1176 1177 if (ret_flags & GSS_C_DELEG_FLAG) 1178 printf(gettext("GSS_C_DELEG_FLAG = True\n")); 1179 else 1180 printf(gettext("GSS_C_DELEG_FLAG = False\n")); 1181 1182 if (ret_flags & GSS_C_MUTUAL_FLAG) 1183 printf(gettext("GSS_C_MUTUAL_FLAG = True\n")); 1184 else 1185 printf(gettext("GSS_C_MUTUAL_FLAG = False\n")); 1186 1187 if (ret_flags & GSS_C_REPLAY_FLAG) 1188 printf(gettext("GSS_C_REPLAY_FLAG = True\n")); 1189 else 1190 printf(gettext("GSS_C_REPLAY_FLAG = False\n")); 1191 1192 if (ret_flags & GSS_C_SEQUENCE_FLAG) 1193 printf(gettext("GSS_C_SEQUENCE_FLAG = True\n")); 1194 else 1195 printf(gettext("GSS_C_SEQUENCE_FLAG = False\n")); 1196 1197 if (ret_flags & GSS_C_CONF_FLAG) 1198 printf(gettext("GSS_C_CONF_FLAG = True\n")); 1199 else 1200 printf(gettext("GSS_C_CONF_FLAG = False\n")); 1201 1202 if (ret_flags & GSS_C_INTEG_FLAG) 1203 printf(gettext("GSS_C_INTEG_FLAG = True\n\n")); 1204 else 1205 printf(gettext("GSS_C_INTEG_FLAG = False\n\n")); 1206 1207 printf(gettext("time_rec = %d seconds\n\n"), time_rec); 1208 1209 /* free allocated memory */ 1210 1211 printf(gettext("\nexport and import of contexts succeeded\n")); 1212 1213 FREE(mech_type->elements, mech_type->length); 1214 FREE(mech_type, sizeof (gss_OID_desc)); 1215 } else { 1216 printf(gettext("\nfirst phase of accept succeeded")); 1217 printf(gettext("\naccept must be called again\n\n")); 1218 } 1219 1220 1221 /* free the input token in accept_token_buffer */ 1222 gss_release_buffer(&minor_status, &accept_token_buffer); 1223 1224 /* if status == GSS_S_COMPLETE, reset the phase to 0 */ 1225 1226 if (status == GSS_S_COMPLETE) 1227 accept_sec_context_phase = 0; 1228 1229 /* gss_accept_sec_context worked, return */ 1230 } 1231 1232 void 1233 _gss_process_context_token(argc, argv) 1234 int argc; 1235 char **argv; 1236 { 1237 OM_UINT32 status; 1238 1239 gss_ctx_id_t context_handle; 1240 OM_uint32 minor_status; 1241 uid_t uid; 1242 1243 uid = (uid_t) getuid(); 1244 1245 /* parse the command line to determine the variable input argument */ 1246 1247 if (argc == 0) { 1248 usage(); 1249 return; 1250 } 1251 1252 if (strcmp(argv[0], "initiator") == 0) 1253 context_handle = initiator_context_handle; 1254 else if (strcmp(argv[0], "acceptor") == 0) 1255 context_handle = acceptor_context_handle; 1256 else { 1257 printf(gettext( 1258 "must specify either \"initiator\" or \"acceptor\"\n")); 1259 return; 1260 } 1261 1262 argc--; 1263 argv++; 1264 1265 if (argc != 0) { 1266 usage(); 1267 return; 1268 } 1269 1270 status = kgss_process_context_token(&minor_status, 1271 context_handle, 1272 delete_token_buffer, 1273 uid); 1274 1275 /* store major and minor status for gss_display_status() call */ 1276 1277 gss_major_code = status; 1278 gss_minor_code = minor_status; 1279 1280 if (status != GSS_S_COMPLETE) { 1281 printf(gettext("server ret err (octal) %o (%s)\n"), 1282 status, gettext("gss_process_context_token error")); 1283 return; 1284 1285 } else { 1286 printf(gettext("\nprocess succeeded\n\n")); 1287 return; 1288 } 1289 } 1290 1291 static void 1292 _gss_delete_sec_context(argc, argv) 1293 int argc; 1294 char **argv; 1295 { 1296 OM_UINT32 status; 1297 gss_ctx_id_t *context_handle; 1298 OM_uint32 minor_status; 1299 uid_t uid; 1300 1301 uid = (uid_t) getuid(); 1302 1303 /* parse the command line to determine the variable input argument */ 1304 1305 if (argc == 0) { 1306 usage(); 1307 return; 1308 } 1309 1310 if (strcmp(argv[0], "initiator") == 0) { 1311 context_handle = &initiator_context_handle; 1312 } else if (strcmp(argv[0], "acceptor") == 0) { 1313 context_handle = &acceptor_context_handle; 1314 } else { 1315 printf(gettext( 1316 "must specify either \"initiator\" or \"acceptor\"\n")); 1317 return; 1318 } 1319 1320 argc--; 1321 argv++; 1322 1323 if (argc != 0) { 1324 usage(); 1325 return; 1326 } 1327 1328 1329 status = kgss_delete_sec_context(&minor_status, 1330 context_handle, 1331 &delete_token_buffer); 1332 1333 1334 /* store major and minor status for gss_display_status() call */ 1335 1336 gss_major_code = status; 1337 gss_minor_code = minor_status; 1338 1339 if (status != GSS_S_COMPLETE) { 1340 1341 printf(gettext("server ret err (octal) %o (%s)\n"), 1342 status, gettext("gss_delete_sec_context error")); 1343 return; 1344 1345 } else { 1346 printf(gettext("\ndelete succeeded\n\n")); 1347 return; 1348 } 1349 } 1350 1351 /*ARGSUSED*/ 1352 static void 1353 _gss_context_time(argc, argv) 1354 int argc; 1355 char **argv; 1356 { 1357 /* 1358 * set up input arguments here 1359 * this function is unimplemented. Call usage() and return 1360 */ 1361 1362 printf(gettext("\nunimplemented function")); 1363 } 1364 1365 static void 1366 _gss_sign(argc, argv) 1367 int argc; 1368 char **argv; 1369 { 1370 OM_UINT32 status; 1371 OM_uint32 minor_status; 1372 gss_ctx_id_t context_handle; 1373 int qop_req; 1374 uid_t uid; 1375 1376 uid = (uid_t) getuid(); 1377 1378 /* specify the default quality of protection */ 1379 1380 qop_req = GSS_C_QOP_DEFAULT; 1381 1382 /* set up the arguments specified in the input parameters */ 1383 1384 if (argc == 0) { 1385 usage(); 1386 return; 1387 } 1388 1389 1390 if (strcmp(argv[0], "initiator") == 0) 1391 context_handle = initiator_context_handle; 1392 else if (strcmp(argv[0], "acceptor") == 0) 1393 context_handle = acceptor_context_handle; 1394 else { 1395 printf(gettext( 1396 "must specify either \"initiator\" or \"acceptor\"\n")); 1397 return; 1398 } 1399 1400 argc--; 1401 argv++; 1402 1403 if (argc == 0) { 1404 usage(); 1405 return; 1406 } 1407 1408 message_buffer.length = strlen(argv[0])+1; 1409 message_buffer.value = (void *) MALLOC(message_buffer.length); 1410 strcpy(message_buffer.value, argv[0]); 1411 1412 argc--; 1413 argv++; 1414 1415 if (argc != 0) { 1416 usage(); 1417 return; 1418 } 1419 1420 status = kgss_sign(&minor_status, 1421 context_handle, 1422 qop_req, 1423 &message_buffer, 1424 &msg_token, 1425 uid); 1426 1427 /* store major and minor status for gss_display_status() call */ 1428 1429 gss_major_code = status; 1430 gss_minor_code = minor_status; 1431 1432 if (status != GSS_S_COMPLETE) { 1433 printf(gettext("server ret err (octal) %o (%s)\n"), 1434 status, gettext("gss_sign error")); 1435 return; 1436 1437 } else { 1438 printf(gettext("\nsign succeeded\n\n")); 1439 return; 1440 } 1441 } 1442 1443 static void 1444 _gss_verify(argc, argv) 1445 int argc; 1446 char **argv; 1447 { 1448 OM_UINT32 status, minor_status; 1449 gss_ctx_id_t context_handle; 1450 int qop_state; 1451 uid_t uid; 1452 1453 uid = (uid_t) getuid(); 1454 1455 /* set up the arguments specified in the input parameters */ 1456 1457 if (argc == 0) { 1458 usage(); 1459 return; 1460 } 1461 1462 1463 if (strcmp(argv[0], "initiator") == 0) 1464 context_handle = initiator_context_handle; 1465 else if (strcmp(argv[0], "acceptor") == 0) 1466 context_handle = acceptor_context_handle; 1467 else { 1468 printf(gettext( 1469 "must specify either \"initiator\" or \"acceptor\"\n")); 1470 return; 1471 } 1472 1473 argc--; 1474 argv++; 1475 1476 if (argc != 0) { 1477 usage(); 1478 return; 1479 } 1480 1481 status = kgss_verify(&minor_status, 1482 context_handle, 1483 &message_buffer, 1484 &msg_token, 1485 &qop_state, 1486 uid); 1487 1488 /* store major and minor status for gss_display_status() call */ 1489 1490 gss_major_code = status; 1491 gss_minor_code = minor_status; 1492 1493 if (status != GSS_S_COMPLETE) { 1494 printf(gettext("server ret err (octal) %o (%s)\n"), 1495 status, gettext("gss_verify error")); 1496 return; 1497 } else { 1498 1499 /* print out the verified message */ 1500 1501 printf(gettext( 1502 "verified message = \"%s\"\n\n"), message_buffer.value); 1503 1504 /* print out the quality of protection returned */ 1505 1506 printf(gettext("quality of protection = %d \n\n"), qop_state); 1507 1508 /* free the message buffer and message token and return */ 1509 1510 gss_release_buffer(&minor_status, &message_buffer); 1511 gss_release_buffer(&minor_status, &msg_token); 1512 1513 return; 1514 } 1515 } 1516 1517 static void 1518 _gss_seal(argc, argv) 1519 int argc; 1520 char **argv; 1521 { 1522 OM_UINT32 status; 1523 1524 OM_uint32 minor_status; 1525 gss_ctx_id_t context_handle; 1526 int conf_req_flag; 1527 int qop_req; 1528 gss_buffer_desc input_message_buffer; 1529 int conf_state; 1530 uid_t uid; 1531 1532 uid = (uid_t) getuid(); 1533 1534 /* 1535 * specify the default confidentiality requested (both integrity 1536 * and confidentiality) and quality of protection 1537 */ 1538 1539 conf_req_flag = 1; 1540 qop_req = GSS_C_QOP_DEFAULT; 1541 1542 /* set up the arguments specified in the input parameters */ 1543 1544 if (argc == 0) { 1545 usage(); 1546 return; 1547 } 1548 1549 1550 if (strcmp(argv[0], "initiator") == 0) 1551 context_handle = initiator_context_handle; 1552 else if (strcmp(argv[0], "acceptor") == 0) 1553 context_handle = acceptor_context_handle; 1554 else { 1555 printf(gettext( 1556 "must specify either \"initiator\" or \"acceptor\"\n")); 1557 return; 1558 } 1559 1560 argc--; 1561 argv++; 1562 1563 if (argc == 0) { 1564 usage(); 1565 return; 1566 } 1567 1568 1569 input_message_buffer.length = strlen(argv[0])+1; 1570 input_message_buffer.value = 1571 (void *) MALLOC(input_message_buffer.length); 1572 strcpy(input_message_buffer.value, argv[0]); 1573 1574 argc--; 1575 argv++; 1576 1577 if (argc != 0) { 1578 usage(); 1579 return; 1580 } 1581 1582 status = kgss_seal(&minor_status, 1583 context_handle, 1584 conf_req_flag, 1585 qop_req, 1586 &input_message_buffer, 1587 &conf_state, 1588 &message_buffer, 1589 uid); 1590 1591 /* store major and minor status for gss_display_status() call */ 1592 1593 gss_major_code = status; 1594 gss_minor_code = minor_status; 1595 1596 /* free the inputmessage buffer */ 1597 1598 gss_release_buffer(&minor_status, &input_message_buffer); 1599 1600 if (status != GSS_S_COMPLETE) { 1601 printf(gettext("server ret err (octal) %o (%s)\n"), 1602 status, gettext("gss_seal error")); 1603 return; 1604 } else { 1605 printf(gettext("\nseal succeeded\n\n")); 1606 return; 1607 } 1608 } 1609 1610 static void 1611 _gss_unseal(argc, argv) 1612 int argc; 1613 char **argv; 1614 { 1615 OM_UINT32 status; 1616 1617 OM_uint32 minor_status; 1618 gss_ctx_id_t context_handle; 1619 gss_buffer_desc output_message_buffer; 1620 int conf_state; 1621 int qop_state; 1622 uid_t uid; 1623 1624 uid = (uid_t) getuid(); 1625 1626 /* set up the arguments specified in the input parameters */ 1627 1628 if (argc == 0) { 1629 usage(); 1630 return; 1631 } 1632 1633 1634 if (strcmp(argv[0], "initiator") == 0) 1635 context_handle = initiator_context_handle; 1636 else if (strcmp(argv[0], "acceptor") == 0) 1637 context_handle = acceptor_context_handle; 1638 else { 1639 printf(gettext( 1640 "must specify either \"initiator\" or \"acceptor\"\n")); 1641 return; 1642 } 1643 1644 argc--; 1645 argv++; 1646 1647 if (argc != 0) { 1648 usage(); 1649 return; 1650 } 1651 1652 status = kgss_unseal(&minor_status, 1653 context_handle, 1654 &message_buffer, 1655 &output_message_buffer, 1656 &conf_state, 1657 &qop_state, 1658 uid); 1659 1660 /* store major and minor status for gss_display_status() call */ 1661 1662 gss_major_code = status; 1663 gss_minor_code = minor_status; 1664 1665 if (status == GSS_S_COMPLETE) { 1666 printf(gettext("\nunseal succeeded\n\n")); 1667 printf(gettext("unsealed message = \"%s\"\n\n"), 1668 output_message_buffer.value); 1669 if (conf_state) 1670 printf(gettext("confidentiality and integrity used\n")); 1671 else 1672 printf(gettext("only integrity used\n")); 1673 printf(gettext("quality of protection = %d\n\n"), qop_state); 1674 gss_release_buffer(&minor_status, &output_message_buffer); 1675 } else { 1676 printf(gettext("server ret err (octal) %o (%s)\n"), 1677 status, gettext("gss_unseal error")); 1678 } 1679 1680 /* free the message buffer and return */ 1681 1682 gss_release_buffer(&minor_status, &message_buffer); 1683 } 1684 1685 static void 1686 _gss_display_status(argc, argv) 1687 int argc; 1688 char **argv; 1689 { 1690 OM_UINT32 status; 1691 OM_uint32 minor_status; 1692 int status_type; 1693 int status_value; 1694 gss_OID mech_type = (gss_OID) 0; 1695 int message_context; 1696 gss_buffer_desc status_string; 1697 uid_t uid; 1698 1699 uid = (uid_t) getuid(); 1700 1701 /* initialize message context to zero */ 1702 1703 message_context = 0; 1704 1705 if (argc == 0) { 1706 printf(gettext("Assuming Kerberos V5 as the mechanism\n")); 1707 printf(gettext( 1708 "The mech OID 1.2.840.113554.1.2.2 will be used\n")); 1709 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID); 1710 } else 1711 mech_type = gss_str2oid(argv[0]); 1712 1713 if (mech_type == 0 || mech_type->length == 0) { 1714 printf(gettext("improperly formated mechanism OID\n")); 1715 return; 1716 } 1717 1718 /* Is this call for the major or minor status? */ 1719 1720 if (strcmp(argv[0], "major") == 0) { 1721 status_type = GSS_C_GSS_CODE; 1722 status_value = gss_major_code; 1723 } else if (strcmp(argv[0], "minor") == 0) { 1724 status_type = GSS_C_MECH_CODE; 1725 status_value = gss_minor_code; 1726 } else { 1727 printf(gettext("must specify either \"major\" or \"minor\"\n")); 1728 return; 1729 } 1730 1731 argc--; 1732 argv++; 1733 1734 if (argc != 0) { 1735 usage(); 1736 return; 1737 } 1738 1739 status = kgss_display_status(&minor_status, 1740 status_value, 1741 status_type, 1742 mech_type, 1743 &message_context, 1744 &status_string, 1745 uid); 1746 1747 if (status == GSS_S_COMPLETE) { 1748 printf(gettext("status =\n %s\n\n"), status_string.value); 1749 } else if (status == GSS_S_BAD_MECH) { 1750 printf(gettext("invalide mechanism OID\n\n")); 1751 } else { 1752 printf(gettext("server ret err (octal) %o (%s)\n"), 1753 status, gettext("gss_display_status error")); 1754 } 1755 } 1756 1757 /*ARGSUSED*/ 1758 static void 1759 _gss_indicate_mechs(argc, argv) 1760 int argc; 1761 char **argv; 1762 { 1763 OM_UINT32 status; 1764 OM_UINT32 minor_status; 1765 gss_OID_set oid_set = GSS_C_NULL_OID_SET; 1766 uid_t uid; 1767 1768 uid = (uid_t) getuid(); 1769 1770 /* set up input arguments here */ 1771 1772 if (argc != 0) { 1773 usage(); 1774 return; 1775 } 1776 1777 status = kgss_indicate_mechs(&minor_status, &oid_set, uid); 1778 1779 if (status == GSS_S_COMPLETE) { 1780 int i; 1781 char *string; 1782 1783 printf(gettext("%d supported mechanism%s%s\n"), oid_set->count, 1784 (oid_set->count == 1) ? "" : "s", 1785 (oid_set->count > 0) ? ":" : ""); 1786 1787 for (i = 0; i < oid_set->count; i++) { 1788 string = gss_oid2str(&oid_set->elements[i]); 1789 printf(gettext("\t%s\n"), string); 1790 FREE(string, ((oid_set->elements[i].length+1)*4)+1); 1791 } 1792 printf("\n"); 1793 1794 } else { 1795 printf(gettext("server ret err (octal) %o (%s)\n"), 1796 status, gettext("gss_indicate_mechs error")); 1797 } 1798 1799 if (oid_set) 1800 gss_release_oid_set_and_oids(&minor_status, &oid_set); 1801 } 1802 1803 /*ARGSUSED*/ 1804 static void 1805 _gss_inquire_cred(argc, argv) 1806 int argc; 1807 char **argv; 1808 { 1809 /* set up input arguments here */ 1810 1811 if (argc != 0) { 1812 usage(); 1813 return; 1814 } 1815 1816 1817 /* this function is unimplemented. Call usage() and return */ 1818 1819 printf(gettext("\nUnsupported function")); 1820 } 1821 1822 static char hexChars[] = "0123456789ABCDEF"; 1823 1824 static void 1825 _gssd_expname_to_unix_cred(argc, argv) 1826 int argc; 1827 char **argv; 1828 { 1829 OM_uint32 major; 1830 gss_buffer_desc expName; 1831 char krb5_root_name[] = "040100092A864886F712010202000000" 1832 "25000A2A864886F71201020101726F6F744053554E534F46" 1833 "542E454E472E53554E2E434F4D00"; 1834 unsigned char *byteStr, *hexStr; 1835 uid_t uidOut, uidIn; 1836 gid_t *gids, gidOut; 1837 int gidsLen, i, newLen; 1838 1839 /* set up the arguments */ 1840 uidIn = (uid_t) getuid(); 1841 1842 if (argc < 1) { 1843 printf(gettext( 1844 "Using principal name of root for krberos_v5\n")); 1845 expName.value = (void*)krb5_root_name; 1846 expName.length = strlen(krb5_root_name); 1847 } else { 1848 expName.value = (void*)argv[0]; 1849 expName.length = strlen(argv[0]); 1850 } 1851 1852 /* convert the name from hex to byte... */ 1853 hexStr = (unsigned char *)expName.value; 1854 newLen = expName.length/2; 1855 byteStr = (unsigned char *)MALLOC(newLen+1); 1856 expName.value = (char *)byteStr; 1857 for (i = 0; i < expName.length; i += 2) { 1858 *byteStr = (strchr(hexChars, *hexStr++) - hexChars) << 4; 1859 *byteStr += (strchr(hexChars, *hexStr++) - hexChars); 1860 byteStr++; 1861 } 1862 expName.length = newLen; 1863 1864 major = kgsscred_expname_to_unix_cred(&expName, &uidOut, &gidOut, 1865 &gids, &gidsLen, uidIn); 1866 1867 FREE(expName.value, newLen); 1868 1869 if (major == GSS_S_COMPLETE) { 1870 printf(gettext("uid = <%d>\tgid = <%d>\t"), uidOut, gidOut); 1871 if (gidsLen > 0) 1872 printf(gettext(" %d gids <"), gidsLen); 1873 else 1874 printf(gettext( 1875 " no supplementary group information\n")); 1876 for (i = 0; i < gidsLen; i++) 1877 printf(" %d ", gids[i]); 1878 if (gidsLen > 0) { 1879 printf(">\n"); 1880 FREE(gids, gidsLen * sizeof (gid_t)); 1881 } 1882 } else { 1883 printf(gettext("server ret err (octal) %o (%s)\n"), 1884 major, gettext("gsscred_expname_to_unix_cred")); 1885 } 1886 } 1887 1888 static void 1889 _gssd_name_to_unix_cred(argc, argv) 1890 int argc; 1891 char **argv; 1892 { 1893 OM_uint32 major, minor; 1894 gss_name_t gssName; 1895 gss_buffer_desc gssBuf = GSS_C_EMPTY_BUFFER; 1896 int gidsLen, i; 1897 gid_t *gids, gidOut; 1898 uid_t uidOut, uid; 1899 char defaultPrincipal[] = "root"; 1900 gss_OID mechType, nameType; 1901 1902 uid = getuid(); 1903 1904 /* optional argument 1 - contains principal name */ 1905 if (argc > 0) { 1906 gssBuf.value = (void *)argv[0]; 1907 gssBuf.length = strlen((char *)argv[0]); 1908 } else { 1909 gssBuf.value = (void *)defaultPrincipal; 1910 gssBuf.length = strlen(defaultPrincipal); 1911 } 1912 printf(gettext( 1913 "Using <%s> as the principal name.\n"), (char *)gssBuf.value); 1914 1915 1916 /* optional argument 2 - contains name oid */ 1917 if (argc > 1) 1918 nameType = gss_str2oid((char *) argv[1]); 1919 else 1920 nameType = (gss_OID)GSS_C_NT_USER_NAME; 1921 1922 if (nameType == NULL || nameType->length == 0) { 1923 printf(gettext("improperly formated name OID\n")); 1924 return; 1925 } 1926 printf(gettext("Principal name of type: <%s>.\n"), 1927 (argc > 1) ? argv[1] : "GSS_C_NT_USER_NAME"); 1928 1929 1930 /* optional argument 3 - contains mech oid */ 1931 if (argc > 2) 1932 mechType = gss_str2oid(argv[2]); 1933 else 1934 mechType = gss_str2oid((char *)GSS_KRB5_MECH_OID); 1935 1936 if (mechType == NULL || mechType->length == NULL) { 1937 FREE(nameType->elements, nameType->length); 1938 FREE(nameType, sizeof (gss_OID_desc)); 1939 printf(gettext("improperly formated mech OID\n")); 1940 return; 1941 } 1942 printf(gettext("Mechanism oid: <%s>.\n"), 1943 (argc > 2) ? argv[2] : 1944 (char *)GSS_KRB5_MECH_OID "(Kerberos v5)"); 1945 1946 1947 /* convert the name to internal format */ 1948 if ((major = gss_import_name(&minor, &gssBuf, 1949 nameType, &gssName)) != GSS_S_COMPLETE) { 1950 printf(gettext("could not parse name: err (octal) %o (%s)\n"), 1951 major, "gss_import_name"); 1952 1953 FREE(nameType->elements, nameType->length); 1954 FREE(nameType, sizeof (gss_OID_desc)); 1955 return; 1956 } 1957 1958 major = kgsscred_name_to_unix_cred(gssName, mechType, &uidOut, 1959 &gidOut, &gids, &gidsLen, uid); 1960 1961 gss_release_name(&minor, &gssName); 1962 FREE(mechType->elements, mechType->length); 1963 FREE(mechType, sizeof (gss_OID_desc)); 1964 if (argc > 1) { 1965 FREE(nameType->elements, nameType->length); 1966 FREE(nameType, sizeof (gss_OID_desc)); 1967 } 1968 1969 if (major == GSS_S_COMPLETE) { 1970 printf("uid = <%d>\tgid = <%d>\t", uidOut, gidOut); 1971 if (gidsLen > 0) 1972 printf(gettext(" %d gids <"), gidsLen); 1973 else 1974 printf(gettext( 1975 " no supplementary group information\n")); 1976 for (i = 0; i < gidsLen; i++) 1977 printf(" %d ", gids[i]); 1978 if (gidsLen > 0) { 1979 printf(">\n"); 1980 FREE(gids, gidsLen * sizeof (gid_t)); 1981 } 1982 } else { 1983 printf(gettext("server ret err (octal) %o (%s)\n"), 1984 major, gettext("gsscred_name_to_unix_cred")); 1985 } 1986 } 1987 1988 static void 1989 _gssd_get_group_info(argc, argv) 1990 int argc; 1991 char **argv; 1992 { 1993 OM_uint32 major; 1994 uid_t puid, uidIn; 1995 gid_t *gids, gidOut; 1996 int gidsLen, i; 1997 1998 /* set up the arguments */ 1999 uidIn = (uid_t) getuid(); 2000 2001 if (argc < 1) 2002 puid = 0; 2003 else 2004 puid = atol(argv[0]); 2005 2006 printf(gettext("Retrieving group info for uid of <%d>\n"), puid); 2007 2008 major = kgss_get_group_info(puid, &gidOut, &gids, &gidsLen, uidIn); 2009 2010 if (major == GSS_S_COMPLETE) { 2011 printf(gettext("group id = <%d>\t"), gidOut); 2012 if (gidsLen > 0) 2013 printf(gettext(" %d gids <"), gidsLen); 2014 else 2015 printf(gettext( 2016 " no supplementary group information\n")); 2017 for (i = 0; i < gidsLen; i++) 2018 printf(" %d ", gids[i]); 2019 if (gidsLen > 0) { 2020 printf(">\n"); 2021 FREE(gids, gidsLen * sizeof (gid_t)); 2022 } 2023 } else { 2024 printf(gettext("server ret err (octal) %o (%s)\n"), 2025 major, "gss_get_group_info"); 2026 } 2027 } 2028 2029 static gss_OID 2030 gss_str2oid(string) 2031 char * string; 2032 { 2033 /* 2034 * a convenient wrapper routine for gss_str_to_oid 2035 * this can handle all valid oid strings. 2036 */ 2037 OM_uint32 minor; 2038 gss_buffer_desc abuf; 2039 gss_OID oidOut; 2040 2041 abuf.value = (void*)string; 2042 abuf.length = strlen(string); 2043 2044 if (gss_str_to_oid(&minor, &abuf, &oidOut) != GSS_S_COMPLETE) 2045 return (NULL); 2046 2047 return (oidOut); 2048 } 2049 2050 static char * 2051 gss_oid2str(oid) 2052 gss_OID oid; 2053 { 2054 /* 2055 * a convenient wrapper for gss_oid_to_str 2056 * this calls the GSS-API routine which should 2057 * be able to handle all types of oids. 2058 */ 2059 OM_uint32 minor; 2060 gss_buffer_desc oidStr; 2061 2062 if (gss_oid_to_str(&minor, oid, &oidStr) != GSS_S_COMPLETE) 2063 return (NULL); 2064 2065 return ((char *)oidStr.value); 2066 } /* gss_oid2str */ 2067 2068 static void 2069 instructs() 2070 { 2071 fprintf(stderr, 2072 gettext( 2073 "\nThis program must be run as root. Root must be installed on the KDC\n" 2074 "and exist in srvtab as root/<hostname>, where <hostname> is the machine on\n" 2075 "which the test runs. Before running gssdtest for Kerberos mechanism, the\n" 2076 "operator running as root must kinit as some other principal, e.g., test.\n" 2077 "There are two mechanisms avaialble: dummy and Kerberos(default).\n" 2078 "The OID for dummy mechanism is 1.3.6.1.4.1.42.2.26.1.2.\n" 2079 "The OID for Kerberos mechanism is 1.2.840.113554.1.2.2.\n" 2080 "The order of context establishment calls is important. First, acquire must" 2081 "\nbe called. This obtains the credentials used by accept. Acquire need\n" 2082 "only be called once, since the credentials it returns are used each time\n" 2083 "accept is called. Then init is called, followed by accept. Calling init\n" 2084 "twice without calling accept or calling these in a different order gives\n" 2085 "erroneous results and will cause memory leaks in the gssapi daemon. \n" 2086 "Finally, after calling init and accept, init must be called again to\n" 2087 "finish context establishment. So an example sequence (with data valid for\n" 2088 "the Kerberos mechanism and running on the machine \"elrond\" in the realm\n" 2089 "FOO.BAR.SUN.COM is :\n")); 2090 fprintf(stderr, 2091 gettext("\nacquire service@host 1.2.840.113554.1.2.2\n" 2092 "init service@host 1.2.840.113554.1.2.2\n" 2093 "accept\ninit service@host 1.2.840.113554.1.2.2\n" 2094 "\nAfter a context is established, sign, seal,\n" 2095 "verify and unseal may be called. Here are some examples\n" 2096 "for these routines : \n\n" 2097 "sign initiator ThisTestMessageIsForSigning\n" 2098 "verify acceptor\nseal initiator ThisTestMessageIsForSealing\n" 2099 "unseal acceptor\n\nEach input line is terminated by <cr>.\n" 2100 "The program is terminated by cntl-d\nor the command \"exit\"" 2101 "\nfrom the prompt\n\n")); 2102 } 2103 2104 static void 2105 usage() 2106 { 2107 fprintf(stderr, 2108 gettext( 2109 "\nusage:\t[acquire | gss_acquire_cred]" 2110 "desired_name mech_type\n" 2111 "\t[release | gss_release_cred]\n" 2112 "\t[init | gss_init_sec_context] target_name mech_type\n" 2113 "\t[accept | gss_accept_sec_context]\n" 2114 "\t[process | gss_process_context_token] initiator | acceptor\n" 2115 "\t[delete | gss_delete_sec_context] initiator | acceptor\n" 2116 "\t[time | gss_context_time] {not yet implemented}\n" 2117 "\t[sign | gss_sign] initiator | acceptor message-to-sign\n" 2118 "\t[verify | gss_verify] initiator | acceptor\n" 2119 "\t[seal | gss_seal] initiator | acceptor message-to-seal\n" 2120 "\t[unseal | gss_unseal] initiator | acceptor\n" 2121 "\t[status | gss_display_status] mech_type [major | minor] \n" 2122 "\t[indicate | gss_indicate_mechs]\n" 2123 "\t[inquire | gss_inquire_cred] {not yet implemented}\n" 2124 "\t[expname2unixcred | gsscred_expname_to_unix_cred]" 2125 " export-name\n" 2126 "\t[name2unixcred | gsscred_name_to_unix_cred] " 2127 "pname [name_type mech_type]\n" 2128 "\t[grpinfo | gss_get_group_info] uid\n" 2129 "\t[gss_all | all] desired_name\n" 2130 "\t[gss_loop | loop] desired_name\n" 2131 "\texit\n\n")); 2132 } 2133 2134 /* Copied from parse_argv(), then modified */ 2135 2136 static int 2137 parse_input_line(input_line, argc, argv) 2138 char *input_line; 2139 int * argc; 2140 char ***argv; 2141 { 2142 const char nil = '\0'; 2143 char * chptr; 2144 int chr_cnt; 2145 int arg_cnt = 0; 2146 int ch_was_space = 1; 2147 int ch_is_space; 2148 2149 chr_cnt = strlen(input_line); 2150 2151 /* Count the arguments in the input_line string */ 2152 2153 *argc = 1; 2154 2155 for (chptr = &input_line[0]; *chptr != nil; chptr++) { 2156 ch_is_space = isspace(*chptr); 2157 if (ch_is_space && !ch_was_space) { 2158 (*argc)++; 2159 } 2160 ch_was_space = ch_is_space; 2161 } 2162 2163 if (ch_was_space) { 2164 (*argc)--; 2165 } /* minus trailing spaces */ 2166 2167 /* Now that we know how many args calloc the argv array */ 2168 2169 *argv = (char **) CALLOC((*argc)+1, sizeof (char *)); 2170 chptr = (char *) (&input_line[0]); 2171 2172 for (ch_was_space = 1; *chptr != nil; chptr++) { 2173 ch_is_space = isspace(*chptr); 2174 if (ch_is_space) { 2175 *chptr = nil; /* replace each space with nil */ 2176 } else if (ch_was_space) { /* begining of word? */ 2177 (*argv)[arg_cnt++] = chptr; /* new argument ? */ 2178 } 2179 2180 ch_was_space = ch_is_space; 2181 } 2182 2183 return (chr_cnt); 2184 }