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