Home | History | Annotate | Download | only in gssd
      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 }
   2193