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