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