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