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