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