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