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