xref: /illumos-gate/usr/src/cmd/gss/gssd/gssdtest.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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