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 }