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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 *  GSSAPI library stub module for gssd.
28 */
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <mechglueP.h>
33#include "gssd.h"
34#include <rpc/rpc.h>
35
36#ifdef	_KERNEL
37#define	MALLOC(n) kmem_alloc((n), KM_SLEEP)
38#define	FREE(x, n) kmem_free((x), (n))
39#define	memcpy(dst, src, n) bcopy((src), (dst), (n))
40#define	clnt_pcreateerror(srv) printf("Cannot connect to server on %s\n", srv)
41
42#ifdef	DEBUG
43#ifndef	_SYS_CMN_ERR_H
44#define	_SYS_CMN_ERR_H
45#define	CE_NOTE 1
46#endif
47#include <sys/types.h>
48#include <sys/devops.h>
49#include <sys/open.h>
50#include <sys/stat.h>
51#include <sys/conf.h>
52#include <sys/ddi.h>
53#include <sys/sunddi.h>
54#include <sys/uio.h>
55#endif /* DEBUG */
56
57#else /* !_KERNEL */
58#define	MALLOC(n) malloc(n)
59#define	FREE(x, n) free(x)
60#endif /* _KERNEL */
61#define	DEFAULT_MINOR_STAT	((OM_uint32) ~0)
62
63CLIENT  *clnt, *getgssd_handle();
64char *server = "localhost";
65
66OM_uint32
67kgss_acquire_cred_wrapped(minor_status,
68			desired_name,
69			time_req,
70			desired_mechs,
71			cred_usage,
72			output_cred_handle,
73			actual_mechs,
74			time_rec,
75			uid,
76			gssd_cred_verifier)
77	OM_uint32 *minor_status;
78	gss_name_t desired_name;
79	OM_uint32 time_req;
80	gss_OID_set desired_mechs;
81	int cred_usage;
82	gssd_cred_id_t *output_cred_handle;
83	gss_OID_set *actual_mechs;
84	OM_uint32 *time_rec;
85	uid_t uid;
86	OM_uint32 *gssd_cred_verifier;
87{
88	OM_uint32 minor_status_temp;
89	gss_buffer_desc	external_name;
90	gss_OID name_type;
91	int i;
92
93	gss_acquire_cred_arg arg;
94	gss_acquire_cred_res res;
95
96	/* get the client handle to GSSD */
97
98	if ((clnt = getgssd_handle()) == NULL) {
99		clnt_pcreateerror(server);
100		return (GSS_S_FAILURE);
101	}
102
103	/* convert the desired name from internal to external format */
104
105	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
106				&name_type) != GSS_S_COMPLETE) {
107
108			*minor_status = (OM_uint32) minor_status_temp;
109			gss_release_buffer(&minor_status_temp, &external_name);
110		return ((OM_uint32) GSS_S_FAILURE);
111	}
112
113
114	/* copy the procedure arguments into the rpc arg parameter */
115
116	arg.uid = (OM_uint32)uid;
117
118	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
119	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
120
121	arg.name_type.GSS_OID_len =
122		name_type == GSS_C_NULL_OID ?
123			0 : (uint_t)name_type->length;
124
125	arg.name_type.GSS_OID_val =
126		name_type == GSS_C_NULL_OID ?
127			(char *)NULL : (char *)name_type->elements;
128
129	arg.time_req = time_req;
130
131	if (desired_mechs != GSS_C_NULL_OID_SET) {
132		arg.desired_mechs.GSS_OID_SET_len =
133			(uint_t)desired_mechs->count;
134		arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *)
135			MALLOC(sizeof (GSS_OID) * desired_mechs->count);
136
137		for (i = 0; i < desired_mechs->count; i++) {
138			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len =
139				(uint_t)desired_mechs->elements[i].length;
140			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val =
141				(char *)
142				MALLOC(desired_mechs->elements[i].length);
143			memcpy(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
144				desired_mechs->elements[i].elements,
145				desired_mechs->elements[i].length);
146		}
147	} else
148		arg.desired_mechs.GSS_OID_SET_len = 0;
149
150	arg.cred_usage = cred_usage;
151
152	/* call the remote procedure */
153
154	memset(&res, 0, sizeof (res));
155	if (gss_acquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
156
157	/*
158	 * if the RPC call times out, null out all return arguments,
159	 * set minor_status to its maximum value, and return GSS_S_FAILURE
160	 */
161
162		if (minor_status != NULL)
163			*minor_status = DEFAULT_MINOR_STAT;
164		if (output_cred_handle != NULL)
165			*output_cred_handle = NULL;
166		if (actual_mechs != NULL)
167			*actual_mechs = NULL;
168		if (time_rec != NULL)
169			*time_rec = 0;
170
171		return (GSS_S_FAILURE);
172	}
173
174	/* free the allocated memory for the flattened name and desire_mechs */
175
176	gss_release_buffer(&minor_status_temp, &external_name);
177	for (i = 0; i < desired_mechs->count; i++)
178		FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val,
179			arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len);
180	FREE(arg.desired_mechs.GSS_OID_SET_val,
181		arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID));
182
183	/* copy the rpc results into the return arguments */
184
185	if (minor_status != NULL)
186		*minor_status = res.minor_status;
187
188	if (output_cred_handle != NULL) {
189		 *output_cred_handle =
190		/*LINTED*/
191		*((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val);
192		 *gssd_cred_verifier = res.gssd_cred_verifier;
193	}
194
195	if (res.status == GSS_S_COMPLETE &&
196		res.actual_mechs.GSS_OID_SET_len != 0 &&
197		actual_mechs != NULL) {
198		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
199		(*actual_mechs)->count =
200			(int)res.actual_mechs.GSS_OID_SET_len;
201		(*actual_mechs)->elements = (gss_OID)
202			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
203
204		for (i = 0; i < (*actual_mechs)->count; i++) {
205			(*actual_mechs)->elements[i].length = (OM_uint32)
206			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
207			(*actual_mechs)->elements[i].elements =
208			(void *) MALLOC((*actual_mechs)->elements[i].length);
209			memcpy((*actual_mechs)->elements[i].elements,
210			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
211			(*actual_mechs)->elements[i].length);
212		}
213	} else {
214		if (res.status == GSS_S_COMPLETE && actual_mechs != NULL)
215			(*actual_mechs)->count = 0;
216	}
217
218	if (time_rec != NULL)
219		*time_rec = res.time_rec;
220
221	/*
222	 * free the memory allocated for the results and return with the status
223	 * received in the rpc call
224	 */
225
226	clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res);
227	return (res.status);
228}
229
230OM_uint32
231kgss_acquire_cred(minor_status,
232		desired_name,
233		time_req,
234		desired_mechs,
235		cred_usage,
236		output_cred_handle,
237		actual_mechs,
238		time_rec,
239		uid)
240	OM_uint32 *minor_status;
241	gss_name_t desired_name;
242	OM_uint32 time_req;
243	gss_OID_set desired_mechs;
244	int cred_usage;
245	gss_cred_id_t *output_cred_handle;
246	gss_OID_set *actual_mechs;
247	OM_uint32 *time_rec;
248	uid_t uid;
249{
250
251		OM_uint32	err;
252		struct kgss_cred *kcred;
253
254		kcred = KGSS_CRED_ALLOC();
255		*output_cred_handle = (gss_cred_id_t)kcred;
256		err = kgss_acquire_cred_wrapped(minor_status,
257					desired_name, time_req,
258					desired_mechs, cred_usage,
259					&kcred->gssd_cred, actual_mechs,
260					time_rec, uid,
261					&kcred->gssd_cred_verifier);
262		if (GSS_ERROR(err)) {
263			KGSS_CRED_FREE(kcred);
264			*output_cred_handle = GSS_C_NO_CREDENTIAL;
265		}
266		return (err);
267}
268
269OM_uint32
270kgss_add_cred_wrapped(minor_status,
271			input_cred_handle,
272			gssd_cred_verifier,
273			desired_name,
274			desired_mech_type,
275			cred_usage,
276			initiator_time_req,
277			acceptor_time_req,
278			actual_mechs,
279			initiator_time_rec,
280			acceptor_time_rec,
281			uid)
282	OM_uint32 *minor_status;
283	gssd_cred_id_t input_cred_handle;
284	OM_uint32 gssd_cred_verifier;
285	gss_name_t desired_name;
286	gss_OID desired_mech_type;
287	int cred_usage;
288	int initiator_time_req;
289	int acceptor_time_req;
290	gss_OID_set *actual_mechs;
291	OM_uint32 *initiator_time_rec;
292	OM_uint32 *acceptor_time_rec;
293	uid_t uid;
294{
295	CLIENT *clnt;
296
297	OM_uint32 	minor_status_temp;
298	gss_buffer_desc	external_name;
299	gss_OID		name_type;
300	int		i;
301
302	gss_add_cred_arg arg;
303	gss_add_cred_res res;
304
305	/* get the client handle to GSSD */
306
307	if ((clnt = getgssd_handle()) == NULL) {
308		clnt_pcreateerror(server);
309		return (GSS_S_FAILURE);
310	}
311
312
313	/* convert the desired name from internal to external format */
314
315	if (gss_display_name(&minor_status_temp, desired_name, &external_name,
316				&name_type) != GSS_S_COMPLETE) {
317
318		*minor_status = (OM_uint32) minor_status_temp;
319		(void) gss_release_buffer(&minor_status_temp, &external_name);
320		clnt_pcreateerror(server);
321		return ((OM_uint32) GSS_S_FAILURE);
322	}
323
324
325	/* copy the procedure arguments into the rpc arg parameter */
326
327	arg.uid = (OM_uint32) uid;
328	arg.input_cred_handle.GSS_CRED_ID_T_len =
329			input_cred_handle ==
330			(gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
331			0 : (uint_t)sizeof (gssd_cred_id_t);
332	arg.input_cred_handle.GSS_CRED_ID_T_val =
333						(char *)&input_cred_handle;
334	arg.gssd_cred_verifier = gssd_cred_verifier;
335	arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
336	arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value;
337	arg.name_type.GSS_OID_len =
338		name_type == GSS_C_NULL_OID ?
339			0 : (uint_t)name_type->length;
340	arg.name_type.GSS_OID_val =
341		name_type == GSS_C_NULL_OID ?
342			(char *)NULL : (char *)name_type->elements;
343
344	arg.desired_mech_type.GSS_OID_len =
345		(uint_t)(desired_mech_type != GSS_C_NULL_OID ?
346		desired_mech_type->length : 0);
347	arg.desired_mech_type.GSS_OID_val =
348		(char *)(desired_mech_type != GSS_C_NULL_OID ?
349		desired_mech_type->elements : 0);
350	arg.cred_usage = cred_usage;
351	arg.initiator_time_req = initiator_time_req;
352	arg.acceptor_time_req = acceptor_time_req;
353
354	/* call the remote procedure */
355
356	bzero((caddr_t)&res, sizeof (res));
357	if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
358
359		/*
360		 * if the RPC call times out, null out all return arguments,
361		 * set minor_status to its maximum value, and return
362		 * GSS_S_FAILURE
363		 */
364
365		if (minor_status != NULL)
366			*minor_status = DEFAULT_MINOR_STAT;
367		if (actual_mechs != NULL)
368			*actual_mechs = NULL;
369		if (initiator_time_rec != NULL)
370			*initiator_time_rec = 0;
371		if (acceptor_time_rec != NULL)
372			*acceptor_time_rec = 0;
373		return (GSS_S_FAILURE);
374	}
375
376	/* free the allocated memory for the flattened name */
377
378	(void) gss_release_buffer(&minor_status_temp, &external_name);
379
380	/* copy the rpc results into the return arguments */
381
382	if (minor_status != NULL)
383		*minor_status = res.minor_status;
384
385	if (res.status == GSS_S_COMPLETE &&
386		res.actual_mechs.GSS_OID_SET_len != 0 &&
387		actual_mechs != NULL) {
388		*actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
389		(*actual_mechs)->count =
390					(int)res.actual_mechs.GSS_OID_SET_len;
391		(*actual_mechs)->elements = (gss_OID)
392			MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count);
393
394		for (i = 0; i < (*actual_mechs)->count; i++) {
395		    (*actual_mechs)->elements[i].length = (OM_uint32)
396			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len;
397		    (*actual_mechs)->elements[i].elements =
398			(void *) MALLOC((*actual_mechs)->elements[i].length);
399		    memcpy((*actual_mechs)->elements[i].elements,
400			res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val,
401			(*actual_mechs)->elements[i].length);
402		}
403	} else {
404		if (res.status == GSS_S_COMPLETE &&
405			actual_mechs != NULL)
406			(*actual_mechs)->count = 0;
407	}
408	if (initiator_time_rec != NULL)
409		*initiator_time_rec = res.initiator_time_rec;
410	if (acceptor_time_rec != NULL)
411		*acceptor_time_rec = res.acceptor_time_rec;
412
413	/*
414	 * free the memory allocated for the results and return with the status
415	 * received in the rpc call
416	 */
417
418	clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res);
419	return (res.status);
420
421}
422
423OM_uint32
424kgss_add_cred(minor_status,
425			input_cred_handle,
426			desired_name,
427			desired_mech_type,
428			cred_usage,
429			initiator_time_req,
430			acceptor_time_req,
431			actual_mechs,
432			initiator_time_rec,
433			acceptor_time_rec,
434			uid)
435	OM_uint32 *minor_status;
436	gss_cred_id_t input_cred_handle;
437	gss_name_t desired_name;
438	gss_OID desired_mech_type;
439	int cred_usage;
440	int initiator_time_req;
441	int acceptor_time_req;
442	gss_OID_set *actual_mechs;
443	OM_uint32 *initiator_time_rec;
444	OM_uint32 *acceptor_time_rec;
445	uid_t uid;
446{
447
448	OM_uint32	err;
449	OM_uint32 gssd_cred_verifier;
450	gssd_cred_id_t gssd_input_cred_handle;
451
452
453	if (input_cred_handle != GSS_C_NO_CREDENTIAL) {
454		gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle);
455		gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle);
456	} else
457		gssd_input_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
458
459	err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle,
460			gssd_cred_verifier, desired_name, desired_mech_type,
461			cred_usage, initiator_time_req, acceptor_time_req,
462			actual_mechs, initiator_time_rec,
463			acceptor_time_rec, uid);
464	return (err);
465}
466
467OM_uint32
468kgss_release_cred_wrapped(minor_status,
469		cred_handle,
470		uid,
471		gssd_cred_verifier)
472OM_uint32 *minor_status;
473gssd_cred_id_t *cred_handle;
474uid_t uid;
475OM_uint32 gssd_cred_verifier;
476{
477
478	gss_release_cred_arg arg;
479	gss_release_cred_res res;
480
481
482	/* get the client handle to GSSD */
483	if ((clnt = getgssd_handle()) == NULL) {
484		clnt_pcreateerror(server);
485		return (GSS_S_FAILURE);
486	}
487
488	/* copy the procedure arguments into the rpc arg parameter */
489
490	arg.uid = (OM_uint32) uid;
491	arg.gssd_cred_verifier = gssd_cred_verifier;
492
493	if (cred_handle != NULL) {
494		arg.cred_handle.GSS_CRED_ID_T_len =
495			(uint_t)sizeof (gssd_cred_id_t);
496		arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle;
497	} else
498		arg.cred_handle.GSS_CRED_ID_T_len = 0;
499
500	/* call the remote procedure */
501
502	memset(&res, 0, sizeof (res));
503	if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
504
505		/*
506		 * if the RPC call times out, null out all return arguments,
507		 * set minor_status to its max value, and return GSS_S_FAILURE
508		 */
509
510		if (minor_status != NULL)
511			*minor_status = DEFAULT_MINOR_STAT;
512		if (cred_handle != NULL)
513			*cred_handle = NULL;
514
515		return (GSS_S_FAILURE);
516	}
517
518	/* if the release succeeded, null out the cred_handle */
519	if (res.status == GSS_S_COMPLETE && cred_handle != NULL)
520		*cred_handle = NULL;
521
522	/* copy the rpc results into the return arguments */
523	if (minor_status != NULL)
524		*minor_status = res.minor_status;
525
526	/* return with status returned in rpc call */
527	return (res.status);
528}
529
530OM_uint32
531kgss_release_cred(minor_status,
532			cred_handle,
533			uid)
534	OM_uint32 *minor_status;
535	gss_cred_id_t *cred_handle;
536	uid_t uid;
537
538{
539
540		OM_uint32	err;
541		struct kgss_cred *kcred;
542
543		if (*cred_handle == GSS_C_NO_CREDENTIAL)
544			return (GSS_S_COMPLETE);
545		else
546			kcred = KCRED_TO_KGSS_CRED(*cred_handle);
547
548		err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred,
549			uid, kcred->gssd_cred_verifier);
550		KGSS_CRED_FREE(kcred);
551		*cred_handle = GSS_C_NO_CREDENTIAL;
552		return (err);
553}
554
555OM_uint32
556kgss_init_sec_context_wrapped(minor_status,
557			claimant_cred_handle,
558			gssd_cred_verifier,
559			context_handle,
560			gssd_context_verifier,
561		target_name,
562		mech_type,
563		req_flags,
564		time_req,
565		input_chan_bindings,
566		input_token,
567		actual_mech_type,
568		output_token,
569		ret_flags,
570		time_rec,
571		uid)
572	OM_uint32 *minor_status;
573	gssd_cred_id_t claimant_cred_handle;
574	OM_uint32 gssd_cred_verifier;
575	OM_uint32 *context_handle;
576	OM_uint32 *gssd_context_verifier;
577	gss_name_t target_name;
578	gss_OID mech_type;
579	int req_flags;
580	OM_uint32 time_req;
581	gss_channel_bindings_t input_chan_bindings;
582	gss_buffer_t input_token;
583	gss_OID *actual_mech_type;
584	gss_buffer_t output_token;
585	int *ret_flags;
586	OM_uint32 *time_rec;
587	uid_t uid;
588{
589	OM_uint32 minor_status_temp;
590	gss_buffer_desc external_name;
591	gss_OID name_type;
592	gss_init_sec_context_arg arg;
593	gss_init_sec_context_res res;
594
595	/* get the client handle to GSSD */
596
597	if ((clnt = getgssd_handle()) == NULL) {
598		clnt_pcreateerror(server);
599		return (GSS_S_FAILURE);
600	}
601
602	/* convert the target name from internal to external format */
603
604	if (gss_display_name(&minor_status_temp, target_name,
605			&external_name, &name_type) != GSS_S_COMPLETE) {
606
607		*minor_status = (OM_uint32) minor_status_temp;
608		return ((OM_uint32) GSS_S_FAILURE);
609	}
610
611
612/* copy the procedure arguments into the rpc arg parameter */
613
614	arg.uid = (OM_uint32) uid;
615
616	arg.context_handle.GSS_CTX_ID_T_len =
617		*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
618		(uint_t)sizeof (OM_uint32);
619	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
620	arg.gssd_context_verifier = *gssd_context_verifier;
621
622	arg.claimant_cred_handle.GSS_CRED_ID_T_len =
623		claimant_cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
624		0 : (uint_t)sizeof (gssd_cred_id_t);
625	arg.claimant_cred_handle.GSS_CRED_ID_T_val =
626		(char *)&claimant_cred_handle;
627	arg.gssd_cred_verifier =  gssd_cred_verifier;
628
629	arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length;
630	arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value;
631
632	arg.name_type.GSS_OID_len =
633		name_type == GSS_C_NULL_OID ?
634		0 : (uint_t)name_type->length;
635
636	arg.name_type.GSS_OID_val =
637		name_type == GSS_C_NULL_OID ?
638		(char *)NULL : (char *)name_type->elements;
639
640	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
641				mech_type->length : 0);
642	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
643				mech_type->elements : 0);
644
645	arg.req_flags = req_flags;
646
647	arg.time_req = time_req;
648
649	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
650		arg.input_chan_bindings.present = YES;
651		arg.input_chan_bindings.initiator_addrtype =
652			input_chan_bindings->initiator_addrtype;
653		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
654			(uint_t)input_chan_bindings->initiator_address.length;
655		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
656			(void *) input_chan_bindings->initiator_address.value;
657		arg.input_chan_bindings.acceptor_addrtype =
658			input_chan_bindings->acceptor_addrtype;
659		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
660			(uint_t)input_chan_bindings->acceptor_address.length;
661		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
662			(void *) input_chan_bindings->acceptor_address.value;
663		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
664			(uint_t)input_chan_bindings->application_data.length;
665		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
666			(void *) input_chan_bindings->application_data.value;
667	} else {
668		arg.input_chan_bindings.present = NO;
669		arg.input_chan_bindings.initiator_addrtype = 0;
670		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
671		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
672		arg.input_chan_bindings.acceptor_addrtype = 0;
673		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
674		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
675		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
676		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
677	}
678
679	arg.input_token.GSS_BUFFER_T_len = (uint_t)
680		(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
681	arg.input_token.GSS_BUFFER_T_val = (char *)
682		(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
683
684	/* initialize the output parameters to empty values */
685	if (minor_status != NULL)
686		*minor_status = DEFAULT_MINOR_STAT;
687	if (actual_mech_type != NULL)
688		*actual_mech_type = NULL;
689	if (output_token != NULL)
690		output_token->length = 0;
691	if (ret_flags != NULL)
692		*ret_flags = 0;
693	if (time_rec != NULL)
694		*time_rec = 0;
695
696	/* call the remote procedure */
697	memset(&res, 0, sizeof (res));
698	if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
699
700		/* free the allocated memory for the flattened name */
701		gss_release_buffer(&minor_status_temp, &external_name);
702
703		return (GSS_S_FAILURE);
704	}
705
706	/*
707	 * We could return from a GSS error here and need to return both the
708	 * minor_status and output_token, back to the caller if applicable.
709	 */
710	if (minor_status != NULL)
711		*minor_status = res.minor_status;
712
713	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
714		output_token->length =
715			(size_t)res.output_token.GSS_BUFFER_T_len;
716		output_token->value =
717			(void *)res.output_token.GSS_BUFFER_T_val;
718		res.output_token.GSS_BUFFER_T_val = NULL;
719		res.output_token.GSS_BUFFER_T_len = 0;
720	}
721
722	/* free the allocated memory for the flattened name */
723	gss_release_buffer(&minor_status_temp, &external_name);
724
725	/* if the call was successful, copy out the results */
726	if (res.status == (OM_uint32) GSS_S_COMPLETE ||
727		res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
728		/*
729		 * copy the rpc results into the return argument
730		 * on CONTINUE_NEEDED only ctx handle is ready.
731		 */
732		/*LINTED*/
733		*context_handle = *((OM_uint32 *)
734			res.context_handle.GSS_CTX_ID_T_val);
735
736		*gssd_context_verifier = res.gssd_context_verifier;
737
738		/* the rest of the parameters is only ready on COMPLETE */
739		if (res.status == GSS_S_COMPLETE) {
740			if (actual_mech_type != NULL) {
741				*actual_mech_type = (gss_OID)
742					MALLOC(sizeof (gss_OID_desc));
743				(*actual_mech_type)->length = (OM_UINT32)
744					res.actual_mech_type.GSS_OID_len;
745				(*actual_mech_type)->elements = (void *)
746					MALLOC((*actual_mech_type)->length);
747				memcpy((*actual_mech_type)->elements, (void *)
748					res.actual_mech_type.GSS_OID_val,
749					(*actual_mech_type)->length);
750			}
751
752
753			if (ret_flags != NULL)
754				*ret_flags = res.ret_flags;
755
756			if (time_rec != NULL)
757				*time_rec = res.time_rec;
758		}
759	}
760
761
762	/*
763	 * free the memory allocated for the results and return with the
764	 * status received in the rpc call.
765	 */
766
767	clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res);
768	return (res.status);
769}
770OM_uint32
771kgss_init_sec_context(
772		OM_uint32 *minor_status,
773		gss_cred_id_t claimant_cred_handle,
774		gss_ctx_id_t *context_handle,
775		gss_name_t target_name,
776		gss_OID mech_type,
777		int req_flags,
778		OM_uint32 time_req,
779		gss_channel_bindings_t input_chan_bindings,
780		gss_buffer_t input_token,
781		gss_OID *actual_mech_type,
782		gss_buffer_t output_token,
783		int *ret_flags,
784		OM_uint32 *time_rec,
785		uid_t uid)
786{
787		OM_uint32	err;
788		struct kgss_ctx	*kctx;
789		OM_uint32 gssd_cred_verifier;
790		gssd_cred_id_t gssd_cl_cred_handle;
791
792		/*
793		 * If this is an initial call, we'll need to create the
794		 * wrapper struct that contains kernel state information, and
795		 * a reference to the handle from gssd.
796		 */
797		if (*context_handle == GSS_C_NO_CONTEXT) {
798			kctx = KGSS_ALLOC();
799			*context_handle = (gss_ctx_id_t)kctx;
800			kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
801		} else
802			kctx = (struct kgss_ctx *)*context_handle;
803
804		if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
805			gssd_cred_verifier =
806				KCRED_TO_CREDV(claimant_cred_handle);
807			gssd_cl_cred_handle =
808				KCRED_TO_CRED(claimant_cred_handle);
809		} else
810			gssd_cl_cred_handle =
811					(gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
812
813		err = kgss_init_sec_context_wrapped(minor_status,
814			gssd_cl_cred_handle,
815			gssd_cred_verifier, &kctx->gssd_ctx,
816			&kctx->gssd_ctx_verifier,
817			target_name, mech_type, req_flags, time_req,
818			input_chan_bindings, input_token, actual_mech_type,
819			output_token, ret_flags, time_rec, uid);
820
821		if (GSS_ERROR(err)) {
822			KGSS_FREE(kctx);
823			*context_handle = GSS_C_NO_CONTEXT;
824		}
825		return (err);
826}
827OM_uint32
828kgss_accept_sec_context_wrapped(minor_status,
829				context_handle,
830				gssd_context_verifier,
831				verifier_cred_handle,
832				gssd_cred_verifier,
833		input_token,
834		input_chan_bindings,
835		src_name,
836		mech_type,
837		output_token,
838		ret_flags,
839		time_rec,
840		delegated_cred_handle,
841		uid)
842	OM_uint32 *minor_status;
843	gssd_ctx_id_t *context_handle;
844	OM_uint32 *gssd_context_verifier;
845	gssd_cred_id_t verifier_cred_handle;
846	OM_uint32 gssd_cred_verifier;
847	gss_buffer_t input_token;
848	gss_channel_bindings_t input_chan_bindings;
849	gss_buffer_t src_name;
850	gss_OID *mech_type;
851	gss_buffer_t output_token;
852	int *ret_flags;
853	OM_uint32 *time_rec;
854	gss_cred_id_t *delegated_cred_handle;
855	uid_t uid;
856{
857	gss_accept_sec_context_arg arg;
858	gss_accept_sec_context_res res;
859	struct kgss_cred *kcred;
860
861	/* get the client handle to GSSD */
862	if ((clnt = getgssd_handle()) == NULL) {
863		clnt_pcreateerror(server);
864		return (GSS_S_FAILURE);
865	}
866
867	/* copy the procedure arguments into the rpc arg parameter */
868	arg.uid = (OM_uint32) uid;
869
870	arg.context_handle.GSS_CTX_ID_T_len =
871		*context_handle == (gssd_ctx_id_t)GSS_C_NO_CONTEXT ?
872			0 : (uint_t)sizeof (gssd_ctx_id_t);
873	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
874	arg.gssd_context_verifier =
875		*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ?
876			0 : *gssd_context_verifier;
877
878	arg.verifier_cred_handle.GSS_CRED_ID_T_len =
879			verifier_cred_handle ==
880			(gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
881			0 : (uint_t)sizeof (gssd_cred_id_t);
882	arg.verifier_cred_handle.GSS_CRED_ID_T_val =
883						(char *)&verifier_cred_handle;
884	arg.gssd_cred_verifier = gssd_cred_verifier;
885
886	arg.input_token_buffer.GSS_BUFFER_T_len =
887			(uint_t)(input_token != GSS_C_NO_BUFFER ?
888					input_token->length : 0);
889	arg.input_token_buffer.GSS_BUFFER_T_val =
890			(char *)(input_token != GSS_C_NO_BUFFER ?
891					input_token->value : 0);
892
893	if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
894		arg.input_chan_bindings.present = YES;
895		arg.input_chan_bindings.initiator_addrtype =
896			input_chan_bindings->initiator_addrtype;
897		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len =
898			(uint_t)input_chan_bindings->initiator_address.length;
899		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val =
900			(void *) input_chan_bindings->initiator_address.value;
901		arg.input_chan_bindings.acceptor_addrtype =
902			input_chan_bindings->acceptor_addrtype;
903		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len =
904			(uint_t)input_chan_bindings->acceptor_address.length;
905		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val =
906			(void *) input_chan_bindings->acceptor_address.value;
907		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len =
908			(uint_t)input_chan_bindings->application_data.length;
909		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val =
910			(void *) input_chan_bindings->application_data.value;
911	} else {
912		arg.input_chan_bindings.present = NO;
913		arg.input_chan_bindings.initiator_addrtype = 0;
914		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0;
915		arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0;
916		arg.input_chan_bindings.acceptor_addrtype = 0;
917		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0;
918		arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0;
919		arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0;
920		arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0;
921	}
922
923	/* set the output parameters to empty values.... */
924	if (minor_status != NULL)
925		*minor_status = DEFAULT_MINOR_STAT;
926	if (src_name != NULL) {
927		src_name->length = 0;
928		src_name->value = NULL;
929	}
930	if (mech_type != NULL)
931		*mech_type = NULL;
932	if (output_token != NULL)
933		output_token->length = 0;
934	if (ret_flags != NULL)
935		*ret_flags = 0;
936	if (time_rec != NULL)
937		*time_rec = 0;
938	if (delegated_cred_handle != NULL)
939		*delegated_cred_handle = NULL;
940
941	/* call the remote procedure */
942	memset(&res, 0, sizeof (res));
943	if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
944		return (GSS_S_FAILURE);
945	}
946
947	/*
948	 * We could return from a GSS error here and need to return both the
949	 * minor_status and output_token, back to the caller if applicable.
950	 */
951	if (minor_status != NULL)
952		*minor_status = res.minor_status;
953
954	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
955		output_token->length =
956			res.output_token.GSS_BUFFER_T_len;
957		output_token->value =
958			(void *) res.output_token.GSS_BUFFER_T_val;
959		res.output_token.GSS_BUFFER_T_val = 0;
960		res.output_token.GSS_BUFFER_T_len = 0;
961	}
962
963	if (res.status == (OM_uint32) GSS_S_COMPLETE ||
964		res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) {
965		/*
966		 * when gss returns CONTINUE_NEEDED we can only
967		 * use the context parameter.
968		 */
969		/*LINTED*/
970		*context_handle = *((gssd_ctx_id_t *)
971			res.context_handle.GSS_CTX_ID_T_val);
972		*gssd_context_verifier = res.gssd_context_verifier;
973
974		/* the other parameters are ready on for COMPLETE */
975		if (res.status == GSS_S_COMPLETE)
976		{
977
978			/*
979			 *  The src_name is in external format.
980			 */
981			if (src_name != NULL) {
982			    src_name->length = res.src_name.GSS_BUFFER_T_len;
983			    src_name->value = res.src_name.GSS_BUFFER_T_val;
984			    res.src_name.GSS_BUFFER_T_val = NULL;
985			    res.src_name.GSS_BUFFER_T_len = 0;
986			}
987			/*
988			 * move mech type returned to mech_type
989			 * for gss_import_name_for_mech()
990			 */
991			if (mech_type != NULL) {
992				*mech_type =
993					(gss_OID) MALLOC(sizeof (gss_OID_desc));
994				(*mech_type)->length =
995					(OM_UINT32) res.mech_type.GSS_OID_len;
996				(*mech_type)->elements =
997					(void *) MALLOC((*mech_type)->length);
998				memcpy((*mech_type)->elements,
999					res.mech_type.GSS_OID_val,
1000					(*mech_type)->length);
1001			}
1002
1003			if (ret_flags != NULL)
1004				*ret_flags = res.ret_flags;
1005
1006			if (time_rec != NULL)
1007				*time_rec = res.time_rec;
1008
1009			if ((delegated_cred_handle != NULL) &&
1010				(res.delegated_cred_handle.GSS_CRED_ID_T_len
1011					!= 0)) {
1012				kcred = KGSS_CRED_ALLOC();
1013				/*LINTED*/
1014				kcred->gssd_cred = *((gssd_cred_id_t *)
1015				res.delegated_cred_handle.GSS_CRED_ID_T_val);
1016				kcred->gssd_cred_verifier =
1017					res.gssd_context_verifier;
1018				*delegated_cred_handle = (gss_cred_id_t)kcred;
1019			}
1020		} /* res.status == GSS_S_COMPLETE */
1021	} /* res.status == GSS_S_COMPLETE or GSS_CONTINUE_NEEDED */
1022
1023
1024	/*
1025	 * free the memory allocated for the results and return with the status
1026	 * received in the rpc call
1027	 */
1028
1029	clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res);
1030	return (res.status);
1031}
1032
1033OM_uint32
1034kgss_accept_sec_context(
1035		OM_uint32 *minor_status,
1036		gss_ctx_id_t *context_handle,
1037		gss_cred_id_t verifier_cred_handle,
1038		gss_buffer_t input_token,
1039		gss_channel_bindings_t input_chan_bindings,
1040		gss_buffer_t src_name,
1041		gss_OID *mech_type,
1042		gss_buffer_t output_token,
1043		int *ret_flags,
1044		OM_uint32 *time_rec,
1045		gss_cred_id_t *delegated_cred_handle,
1046		uid_t uid)
1047{
1048		OM_uint32 err;
1049		struct kgss_ctx *kctx;
1050		OM_uint32 gssd_cred_verifier;
1051		gssd_cred_id_t gssd_ver_cred_handle;
1052
1053
1054		if (*context_handle == GSS_C_NO_CONTEXT) {
1055			kctx = KGSS_ALLOC();
1056			*context_handle = (gss_ctx_id_t)kctx;
1057		kctx->gssd_ctx = (gssd_ctx_id_t)GSS_C_NO_CONTEXT;
1058		} else
1059			kctx = (struct kgss_ctx *)*context_handle;
1060
1061	if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) {
1062			gssd_cred_verifier =
1063				KCRED_TO_CREDV(verifier_cred_handle);
1064			gssd_ver_cred_handle =
1065				KCRED_TO_CRED(verifier_cred_handle);
1066	} else
1067		gssd_ver_cred_handle = (gssd_cred_id_t)GSS_C_NO_CREDENTIAL;
1068
1069		err = kgss_accept_sec_context_wrapped(minor_status,
1070			&kctx->gssd_ctx,
1071			&kctx->gssd_ctx_verifier, gssd_ver_cred_handle,
1072			gssd_cred_verifier, input_token, input_chan_bindings,
1073			src_name, mech_type, output_token, ret_flags,
1074			time_rec, delegated_cred_handle, uid);
1075
1076	if (GSS_ERROR(err)) {
1077		KGSS_FREE(kctx);
1078		*context_handle = GSS_C_NO_CONTEXT;
1079
1080	}
1081
1082	return (err);
1083}
1084
1085OM_uint32
1086kgss_process_context_token(minor_status,
1087			context_handle,
1088			token_buffer,
1089			uid)
1090	OM_uint32 *minor_status;
1091	gss_ctx_id_t context_handle;
1092	gss_buffer_t token_buffer;
1093	uid_t uid;
1094{
1095	OM_uint32 gssd_context_verifier;
1096
1097	gss_process_context_token_arg arg;
1098	gss_process_context_token_res res;
1099
1100	gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle);
1101
1102	/* get the client handle to GSSD */
1103
1104	if ((clnt = getgssd_handle()) == NULL) {
1105		clnt_pcreateerror(server);
1106		return (GSS_S_FAILURE);
1107	}
1108
1109	/* copy the procedure arguments into the rpc arg parameter */
1110	arg.uid = (OM_uint32) uid;
1111
1112	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t);
1113	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1114	arg.gssd_context_verifier = gssd_context_verifier;
1115	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer;
1116	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
1117
1118	/* call the remote procedure */
1119
1120	memset(&res, 0, sizeof (res));
1121	if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) {
1122
1123	/*
1124	 * if the RPC call times out, null out all return arguments,
1125	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1126	 */
1127
1128		if (minor_status != NULL)
1129			*minor_status = DEFAULT_MINOR_STAT;
1130
1131		return (GSS_S_FAILURE);
1132	}
1133
1134	/* copy the rpc results into the return arguments */
1135
1136	if (minor_status != NULL)
1137		*minor_status = res.minor_status;
1138
1139	/* return with status returned in rpc call */
1140
1141	return (res.status);
1142}
1143
1144OM_uint32
1145kgss_delete_sec_context_wrapped(minor_status,
1146			context_handle,
1147			gssd_context_verifier,
1148			output_token)
1149	OM_uint32 *minor_status;
1150	gssd_ctx_id_t *context_handle;
1151	OM_uint32 gssd_context_verifier;
1152	gss_buffer_t output_token;
1153{
1154	gss_delete_sec_context_arg arg;
1155	gss_delete_sec_context_res res;
1156
1157
1158	/* get the client handle to GSSD */
1159	if ((clnt = getgssd_handle()) == NULL) {
1160		clnt_pcreateerror(server);
1161		return (GSS_S_FAILURE);
1162	}
1163
1164	/* copy the procedure arguments into the rpc arg parameter */
1165
1166	arg.context_handle.GSS_CTX_ID_T_len =
1167		*context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 :
1168		(uint_t)sizeof (OM_uint32);
1169	arg.context_handle.GSS_CTX_ID_T_val =  (char *)context_handle;
1170
1171	arg.gssd_context_verifier = gssd_context_verifier;
1172
1173	/* call the remote procedure */
1174
1175	memset(&res, 0, sizeof (res));
1176	if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
1177
1178		/*
1179		 * if the RPC call times out, null out all return arguments,
1180		 * set minor_status to its max value, and return GSS_S_FAILURE
1181		 */
1182
1183		if (minor_status != NULL)
1184			*minor_status = DEFAULT_MINOR_STAT;
1185		if (context_handle != NULL)
1186			*context_handle = NULL;
1187		if (output_token != NULL)
1188			output_token->length = 0;
1189
1190		return (GSS_S_FAILURE);
1191	}
1192
1193	/* copy the rpc results into the return arguments */
1194
1195	if (minor_status != NULL)
1196		*minor_status = res.minor_status;
1197
1198	if (res.context_handle.GSS_CTX_ID_T_len == 0)
1199		*context_handle = NULL;
1200	else
1201		/*LINTED*/
1202		*context_handle = *((gssd_ctx_id_t *)
1203			res.context_handle.GSS_CTX_ID_T_val);
1204
1205	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
1206		output_token->length = res.output_token.GSS_BUFFER_T_len;
1207		output_token->value = res.output_token.GSS_BUFFER_T_val;
1208		res.output_token.GSS_BUFFER_T_len = 0;
1209		res.output_token.GSS_BUFFER_T_val = NULL;
1210	}
1211
1212	/*
1213	 * free the memory allocated for the results and return with the status
1214	 * received in the rpc call
1215	 */
1216
1217	clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res);
1218	return (res.status);
1219}
1220
1221/*ARGSUSED*/
1222OM_uint32
1223kgss_delete_sec_context(
1224		OM_uint32 *minor_status,
1225		gss_ctx_id_t *context_handle,
1226		gss_buffer_t output_token)
1227{
1228		OM_uint32 err;
1229		struct kgss_ctx *kctx;
1230
1231		if (*context_handle == GSS_C_NO_CONTEXT) {
1232			return (GSS_S_NO_CONTEXT);
1233		} else
1234			kctx = KCTX_TO_KGSS_CTX(*context_handle);
1235
1236		err = kgss_delete_sec_context_wrapped(minor_status,
1237				&kctx->gssd_ctx, kctx->gssd_ctx_verifier,
1238				output_token);
1239
1240		if (kctx->gssd_ctx != (gssd_ctx_id_t)GSS_C_NO_CONTEXT)
1241			err = GSS_S_FAILURE;
1242		else
1243			err = GSS_S_COMPLETE;
1244
1245		KGSS_FREE(kctx);
1246		*context_handle = GSS_C_NO_CONTEXT;
1247		return (err);
1248}
1249
1250/*ARGSUSED*/
1251OM_uint32
1252kgss_context_time(minor_status,
1253		context_handle,
1254		time_rec,
1255		uid)
1256	OM_uint32 *minor_status;
1257	gss_ctx_id_t context_handle;
1258	OM_uint32 *time_rec;
1259	uid_t uid;
1260{
1261	return (GSS_S_FAILURE);
1262}
1263
1264OM_uint32
1265kgss_sign_wrapped(minor_status,
1266		context_handle,
1267		qop_req,
1268		message_buffer,
1269		msg_token,
1270		gssd_context_verifier)
1271	OM_uint32 *minor_status;
1272	gssd_ctx_id_t context_handle;
1273	OM_uint32 gssd_context_verifier;
1274	int qop_req;
1275	gss_buffer_t message_buffer;
1276	gss_buffer_t msg_token;
1277{
1278
1279	gss_sign_arg arg;
1280	gss_sign_res res;
1281
1282	/* get the client handle to GSSD */
1283
1284	if ((clnt = getgssd_handle()) == NULL) {
1285		clnt_pcreateerror(server);
1286		return (GSS_S_FAILURE);
1287	}
1288
1289	/* copy the procedure arguments into the rpc arg parameter */
1290
1291
1292	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1293	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1294	arg.gssd_context_verifier = gssd_context_verifier;
1295
1296	arg.qop_req = qop_req;
1297	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
1298	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
1299
1300	/* call the remote procedure */
1301
1302	memset(&res, 0, sizeof (res));
1303	if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) {
1304
1305	/*
1306	 * if the RPC call times out, null out all return arguments,
1307	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1308	 */
1309
1310		if (minor_status != NULL)
1311			*minor_status = DEFAULT_MINOR_STAT;
1312		if (msg_token != NULL)
1313			msg_token->length = 0;
1314
1315		return (GSS_S_FAILURE);
1316	}
1317
1318	/* copy the rpc results into the return arguments */
1319
1320	if (minor_status != NULL)
1321		*minor_status = res.minor_status;
1322
1323	if (msg_token != NULL) {
1324		msg_token->length = res.msg_token.GSS_BUFFER_T_len;
1325		msg_token->value = (void *) MALLOC(msg_token->length);
1326		memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val,
1327			msg_token->length);
1328	}
1329
1330	/*
1331	 * free the memory allocated for the results and return with the status
1332	 * received in the rpc call
1333	 */
1334
1335	clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res);
1336	return (res.status);
1337}
1338
1339OM_uint32
1340kgss_sign(
1341		OM_uint32 *minor_status,
1342		gss_ctx_id_t context_handle,
1343		int qop_req,
1344		gss_buffer_t message_buffer,
1345		gss_buffer_t msg_token)
1346{
1347		if (context_handle == GSS_C_NO_CONTEXT)
1348			return (GSS_S_FAILURE);
1349
1350		return (KGSS_SIGN(minor_status,
1351			context_handle, qop_req, message_buffer,
1352			msg_token));
1353}
1354
1355OM_uint32
1356kgss_verify_wrapped(
1357		minor_status,
1358		context_handle,
1359		message_buffer,
1360		token_buffer,
1361		qop_state,
1362		gssd_context_verifier)
1363	OM_uint32 *minor_status;
1364	gssd_ctx_id_t context_handle;
1365	OM_uint32 gssd_context_verifier;
1366	gss_buffer_t message_buffer;
1367	gss_buffer_t token_buffer;
1368	int *qop_state;
1369{
1370	gss_verify_arg arg;
1371	gss_verify_res res;
1372
1373/* get the client handle to GSSD */
1374
1375	if ((clnt = getgssd_handle()) == NULL) {
1376		clnt_pcreateerror(server);
1377		return (GSS_S_FAILURE);
1378	}
1379
1380	/* copy the procedure arguments into the rpc arg parameter */
1381
1382	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1383	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1384
1385	arg.gssd_context_verifier = gssd_context_verifier;
1386
1387	arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length;
1388	arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value;
1389
1390	arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length;
1391	arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value;
1392
1393	/* call the remote procedure */
1394
1395	memset(&res, 0, sizeof (res));
1396	if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) {
1397
1398	/*
1399	 * if the RPC call times out, null out all return arguments,
1400	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1401	 */
1402
1403		if (minor_status != NULL)
1404			*minor_status = DEFAULT_MINOR_STAT;
1405		if (qop_state != NULL)
1406			*qop_state = 0;
1407
1408		return (GSS_S_FAILURE);
1409	}
1410
1411	/* copy the rpc results into the return arguments */
1412
1413	if (minor_status != NULL)
1414		*minor_status = res.minor_status;
1415
1416	if (qop_state != NULL)
1417		*qop_state = res.qop_state;
1418
1419	/* return with status returned in rpc call */
1420
1421	return (res.status);
1422}
1423
1424OM_uint32
1425kgss_verify(OM_uint32 *minor_status,
1426	gss_ctx_id_t context_handle,
1427	gss_buffer_t message_buffer,
1428	gss_buffer_t token_buffer,
1429	int *qop_state)
1430{
1431		if (context_handle == GSS_C_NO_CONTEXT)
1432			return (GSS_S_FAILURE);
1433
1434		return (KGSS_VERIFY(minor_status, context_handle,
1435			message_buffer,
1436			token_buffer, qop_state));
1437}
1438
1439
1440/* EXPORT DELETE START */
1441
1442OM_uint32
1443kgss_seal_wrapped(
1444	minor_status,
1445	context_handle,
1446	conf_req_flag,
1447	qop_req,
1448	input_message_buffer,
1449	conf_state,
1450	output_message_buffer,
1451	gssd_context_verifier)
1452
1453	OM_uint32 *minor_status;
1454	gssd_ctx_id_t context_handle;
1455	OM_uint32 gssd_context_verifier;
1456	int conf_req_flag;
1457	int qop_req;
1458	gss_buffer_t input_message_buffer;
1459	int *conf_state;
1460	gss_buffer_t output_message_buffer;
1461{
1462	gss_seal_arg arg;
1463	gss_seal_res res;
1464
1465	/* get the client handle to GSSD */
1466
1467	if ((clnt = getgssd_handle()) == NULL) {
1468		clnt_pcreateerror(server);
1469		return (GSS_S_FAILURE);
1470	}
1471
1472	/* copy the procedure arguments into the rpc arg parameter */
1473
1474
1475	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1476	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1477	arg.gssd_context_verifier = gssd_context_verifier;
1478
1479	arg.conf_req_flag = conf_req_flag;
1480
1481	arg.qop_req = qop_req;
1482
1483	arg.input_message_buffer.GSS_BUFFER_T_len =
1484				(uint_t)input_message_buffer->length;
1485
1486	arg.input_message_buffer.GSS_BUFFER_T_val =
1487				(char *)input_message_buffer->value;
1488
1489	/* call the remote procedure */
1490
1491	memset(&res, 0, sizeof (res));
1492	if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) {
1493
1494	/*
1495	 * if the RPC call times out, null out all return arguments,
1496	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1497	 */
1498
1499		if (minor_status != NULL)
1500			*minor_status = DEFAULT_MINOR_STAT;
1501		if (conf_state != NULL)
1502			*conf_state = 0;
1503		if (output_message_buffer != NULL)
1504			output_message_buffer->length = 0;
1505
1506		return (GSS_S_FAILURE);
1507	}
1508
1509	/* copy the rpc results into the return arguments */
1510
1511	if (minor_status != NULL)
1512		*minor_status = res.minor_status;
1513
1514	if (conf_state != NULL)
1515		*conf_state = res.conf_state;
1516
1517	if (output_message_buffer != NULL) {
1518		output_message_buffer->length =
1519				res.output_message_buffer.GSS_BUFFER_T_len;
1520
1521		output_message_buffer->value =
1522				(void *) MALLOC(output_message_buffer->length);
1523		memcpy(output_message_buffer->value,
1524			res.output_message_buffer.GSS_BUFFER_T_val,
1525			output_message_buffer->length);
1526	}
1527
1528	/*
1529	 * free the memory allocated for the results and return with the status
1530	 * received in the rpc call
1531	 */
1532
1533	clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res);
1534	return (res.status);
1535}
1536
1537OM_uint32
1538kgss_seal(OM_uint32 *minor_status,
1539		gss_ctx_id_t context_handle,
1540		int conf_req_flag,
1541		int qop_req,
1542		gss_buffer_t input_message_buffer,
1543		int *conf_state,
1544		gss_buffer_t output_message_buffer)
1545
1546{
1547		if (context_handle == GSS_C_NO_CONTEXT)
1548			return (GSS_S_FAILURE);
1549
1550		return (KGSS_SEAL(minor_status, context_handle,
1551			conf_req_flag, qop_req,
1552			input_message_buffer,
1553			conf_state, output_message_buffer));
1554}
1555
1556OM_uint32
1557kgss_unseal_wrapped(minor_status,
1558		context_handle,
1559		input_message_buffer,
1560		output_message_buffer,
1561		conf_state,
1562		qop_state,
1563		gssd_context_verifier)
1564	OM_uint32 *minor_status;
1565	gssd_ctx_id_t context_handle;
1566	OM_uint32 gssd_context_verifier;
1567	gss_buffer_t input_message_buffer;
1568	gss_buffer_t output_message_buffer;
1569	int *conf_state;
1570	int *qop_state;
1571{
1572	gss_unseal_arg arg;
1573	gss_unseal_res res;
1574
1575	/* get the client handle to GSSD */
1576
1577	if ((clnt = getgssd_handle()) == NULL) {
1578		clnt_pcreateerror(server);
1579		return (GSS_S_FAILURE);
1580	}
1581
1582	/* copy the procedure arguments into the rpc arg parameter */
1583
1584
1585	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
1586	arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle;
1587	arg.gssd_context_verifier = gssd_context_verifier;
1588
1589	arg.input_message_buffer.GSS_BUFFER_T_len =
1590				(uint_t)input_message_buffer->length;
1591
1592	arg.input_message_buffer.GSS_BUFFER_T_val =
1593				(char *)input_message_buffer->value;
1594
1595/* call the remote procedure */
1596
1597	memset(&res, 0, sizeof (res));
1598	if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) {
1599
1600	/*
1601	 * if the RPC call times out, null out all return arguments,
1602	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1603	 */
1604
1605		if (minor_status != NULL)
1606			*minor_status = DEFAULT_MINOR_STAT;
1607		if (output_message_buffer != NULL)
1608			output_message_buffer->length = 0;
1609		if (conf_state != NULL)
1610			*conf_state = 0;
1611		if (qop_state != NULL)
1612			*qop_state = 0;
1613
1614		return (GSS_S_FAILURE);
1615	}
1616
1617	/* copy the rpc results into the return arguments */
1618
1619	if (minor_status != NULL)
1620		*minor_status = res.minor_status;
1621
1622	if (output_message_buffer != NULL) {
1623		output_message_buffer->length =
1624				res.output_message_buffer.GSS_BUFFER_T_len;
1625
1626		output_message_buffer->value =
1627			(void *) MALLOC(output_message_buffer->length);
1628		memcpy(output_message_buffer->value,
1629			res.output_message_buffer.GSS_BUFFER_T_val,
1630			output_message_buffer->length);
1631	}
1632
1633	if (conf_state != NULL)
1634		*conf_state = res.conf_state;
1635
1636	if (qop_state != NULL)
1637		*qop_state = res.qop_state;
1638
1639	/*
1640	 * free the memory allocated for the results and return with the status
1641	 * received in the rpc call
1642	 */
1643
1644	clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res);
1645	return (res.status);
1646}
1647
1648OM_uint32
1649kgss_unseal(OM_uint32 *minor_status,
1650	gss_ctx_id_t context_handle,
1651	gss_buffer_t input_message_buffer,
1652	gss_buffer_t output_message_buffer,
1653	int *conf_state,
1654	int *qop_state)
1655{
1656		if (context_handle == GSS_C_NO_CONTEXT)
1657			return (GSS_S_FAILURE);
1658
1659		return (KGSS_UNSEAL(minor_status, context_handle,
1660			input_message_buffer,
1661			output_message_buffer,
1662			conf_state, qop_state));
1663}
1664
1665/* EXPORT DELETE END */
1666
1667OM_uint32
1668kgss_display_status(minor_status,
1669		status_value,
1670		status_type,
1671		mech_type,
1672		message_context,
1673		status_string,
1674		uid)
1675	OM_uint32 *minor_status;
1676	OM_uint32 status_value;
1677	int status_type;
1678	gss_OID mech_type;
1679	int *message_context;
1680	gss_buffer_t status_string;
1681	uid_t uid;
1682{
1683	gss_display_status_arg arg;
1684	gss_display_status_res res;
1685
1686	/* get the client handle to GSSD */
1687
1688	if ((clnt = getgssd_handle()) == NULL) {
1689		clnt_pcreateerror(server);
1690		return (GSS_S_FAILURE);
1691	}
1692
1693	/* copy the procedure arguments into the rpc arg parameter */
1694
1695	arg.uid = (OM_uint32) uid;
1696
1697	arg.status_value = status_value;
1698	arg.status_type = status_type;
1699
1700	arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ?
1701					mech_type->length : 0);
1702	arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ?
1703					mech_type->elements : 0);
1704
1705	arg.message_context = *message_context;
1706
1707	/* call the remote procedure */
1708
1709	if (message_context != NULL)
1710		*message_context = 0;
1711	if (status_string != NULL) {
1712		status_string->length = 0;
1713		status_string->value = NULL;
1714	}
1715
1716	memset(&res, 0, sizeof (res));
1717	if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) {
1718
1719	/*
1720	 * if the RPC call times out, null out all return arguments,
1721	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1722	 */
1723
1724		if (minor_status != NULL)
1725			*minor_status = DEFAULT_MINOR_STAT;
1726
1727		return (GSS_S_FAILURE);
1728	}
1729
1730	if (minor_status != NULL)
1731		*minor_status = res.minor_status;
1732
1733	/* now process the results and pass them back to the caller */
1734
1735	if (res.status == GSS_S_COMPLETE) {
1736		if (message_context != NULL)
1737			*message_context = res.message_context;
1738		if (status_string != NULL) {
1739			status_string->length =
1740				(size_t)res.status_string.GSS_BUFFER_T_len;
1741			status_string->value =
1742				(void *)MALLOC(status_string->length);
1743			memcpy(status_string->value,
1744				res.status_string.GSS_BUFFER_T_val,
1745				status_string->length);
1746		}
1747	}
1748
1749	clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res);
1750	return (res.status);
1751}
1752
1753/*ARGSUSED*/
1754OM_uint32
1755kgss_indicate_mechs(minor_status,
1756		mech_set,
1757		uid)
1758	OM_uint32 *minor_status;
1759	gss_OID_set *mech_set;
1760	uid_t uid;
1761{
1762	void *arg;
1763	gss_indicate_mechs_res res;
1764	int i;
1765
1766	/* get the client handle to GSSD */
1767
1768	if ((clnt = getgssd_handle()) == NULL) {
1769		clnt_pcreateerror(server);
1770		return (GSS_S_FAILURE);
1771	}
1772
1773	memset(&res, 0, sizeof (res));
1774	if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) {
1775
1776	/*
1777	 * if the RPC call times out, null out all return arguments,
1778	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1779	 */
1780
1781		if (minor_status != NULL)
1782			*minor_status = DEFAULT_MINOR_STAT;
1783		if (mech_set != NULL)
1784			*mech_set = NULL;
1785
1786		return (GSS_S_FAILURE);
1787	}
1788
1789	/* copy the rpc results into the return arguments */
1790
1791	if (minor_status != NULL)
1792		*minor_status = res.minor_status;
1793
1794	if (mech_set != NULL) {
1795		*mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
1796		(*mech_set)->count = res.mech_set.GSS_OID_SET_len;
1797		(*mech_set)->elements = (void *)
1798			MALLOC ((*mech_set)->count * sizeof (gss_OID_desc));
1799		for (i = 0; i < (*mech_set)->count; i++) {
1800			(*mech_set)->elements[i].length =
1801				res.mech_set.GSS_OID_SET_val[i].GSS_OID_len;
1802			(*mech_set)->elements[i].elements = (void *)
1803				MALLOC ((*mech_set)->elements[i].length);
1804			memcpy ((*mech_set)->elements[i].elements,
1805				res.mech_set.GSS_OID_SET_val[i].GSS_OID_val,
1806				(*mech_set)->elements[i].length);
1807		}
1808	}
1809
1810	/*
1811	 * free the memory allocated for the results and return with the status
1812	 * received in the rpc call
1813	 */
1814
1815	clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res);
1816	return (res.status);
1817}
1818
1819
1820OM_uint32
1821kgss_inquire_cred_wrapped(minor_status,
1822			cred_handle,
1823			gssd_cred_verifier,
1824			name,
1825			lifetime,
1826			cred_usage,
1827			mechanisms,
1828			uid)
1829	OM_uint32 *minor_status;
1830	gssd_cred_id_t cred_handle;
1831	OM_uint32 gssd_cred_verifier;
1832	gss_name_t *name;
1833	OM_uint32 *lifetime;
1834	int *cred_usage;
1835	gss_OID_set *mechanisms;
1836	uid_t uid;
1837{
1838	OM_uint32 minor_status_temp;
1839	gss_buffer_desc external_name;
1840	gss_OID name_type;
1841	int i;
1842
1843	gss_inquire_cred_arg arg;
1844	gss_inquire_cred_res res;
1845
1846	/* get the client handle to GSSD */
1847
1848	if ((clnt = getgssd_handle()) == NULL) {
1849		clnt_pcreateerror(server);
1850		return (GSS_S_FAILURE);
1851	}
1852
1853
1854	/* copy the procedure arguments into the rpc arg parameter */
1855
1856	arg.uid = (OM_uint32) uid;
1857
1858	arg.cred_handle.GSS_CRED_ID_T_len =
1859			cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
1860			0 : (uint_t)sizeof (gssd_cred_id_t);
1861	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
1862	arg.gssd_cred_verifier = gssd_cred_verifier;
1863
1864	/* call the remote procedure */
1865
1866	memset(&res, 0, sizeof (res));
1867	if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) {
1868
1869	/*
1870	 * if the RPC call times out, null out all return arguments,
1871	 * set minor_status to its maximum value, and return GSS_S_FAILURE
1872	 */
1873
1874		if (minor_status != NULL)
1875			*minor_status = DEFAULT_MINOR_STAT;
1876		if (name != NULL)
1877			*name = NULL;
1878		if (lifetime != NULL)
1879			*lifetime = 0;
1880		if (cred_usage != NULL)
1881			*cred_usage = 0;
1882		if (mechanisms != NULL)
1883			*mechanisms = NULL;
1884
1885		return (GSS_S_FAILURE);
1886	}
1887
1888	/* copy the rpc results into the return arguments */
1889
1890	if (minor_status != NULL)
1891		*minor_status = res.minor_status;
1892
1893	/* convert name from external to internal format */
1894
1895	if (name != NULL) {
1896		external_name.length = res.name.GSS_BUFFER_T_len;
1897		external_name.value = res.name.GSS_BUFFER_T_val;
1898
1899		/*
1900		 * we have to allocate a name_type descriptor and
1901		 * elements storage, since gss_import_name() only
1902		 * stores a pointer to the name_type info in the
1903		 * union_name struct
1904		 */
1905
1906		name_type = (gss_OID) MALLOC(sizeof (gss_OID_desc));
1907
1908		name_type->length = res.name_type.GSS_OID_len;
1909		name_type->elements = (void *) MALLOC(name_type->length);
1910		memcpy(name_type->elements, res.name_type.GSS_OID_val,
1911			name_type->length);
1912
1913		if (gss_import_name(&minor_status_temp, &external_name,
1914			name_type, name) != GSS_S_COMPLETE) {
1915
1916			*minor_status = (OM_uint32) minor_status_temp;
1917			gss_release_buffer(&minor_status_temp, &external_name);
1918
1919			clnt_freeres(clnt, xdr_gss_inquire_cred_res,
1920							(caddr_t)&res);
1921			return ((OM_uint32) GSS_S_FAILURE);
1922		}
1923	}
1924
1925	if (lifetime != NULL)
1926		*lifetime = res.lifetime;
1927
1928	if (cred_usage != NULL)
1929		*cred_usage = res.cred_usage;
1930
1931	if (mechanisms != NULL) {
1932		*mechanisms =
1933			(gss_OID_set) MALLOC(sizeof (gss_OID_set_desc));
1934		if (res.mechanisms.GSS_OID_SET_len != 0) {
1935			(*mechanisms)->count =
1936					(int)res.mechanisms.GSS_OID_SET_len;
1937			(*mechanisms)->elements = (gss_OID)
1938				MALLOC(sizeof (gss_OID) * (*mechanisms)->count);
1939
1940			for (i = 0; i < (*mechanisms)->count; i++) {
1941				(*mechanisms)->elements[i].length = (OM_uint32)
1942				res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len;
1943				(*mechanisms)->elements[i].elements = (void *)
1944				MALLOC((*mechanisms)->elements[i].length);
1945				memcpy((*mechanisms)->elements[i].elements,
1946				res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val,
1947				(*mechanisms)->elements[i].length);
1948			}
1949		} else
1950			(*mechanisms)->count = 0;
1951	}
1952
1953	/*
1954	 * free the memory allocated for the results and return with the status
1955	 * received in the rpc call
1956	 */
1957
1958	clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res);
1959	return (res.status);
1960}
1961
1962
1963OM_uint32
1964kgss_inquire_cred(minor_status,
1965			cred_handle,
1966			name,
1967			lifetime,
1968			cred_usage,
1969			mechanisms,
1970			uid)
1971	OM_uint32 *minor_status;
1972	gss_cred_id_t cred_handle;
1973	gss_name_t *name;
1974	OM_uint32 *lifetime;
1975	int *cred_usage;
1976	gss_OID_set * mechanisms;
1977	uid_t uid;
1978{
1979
1980	OM_uint32 gssd_cred_verifier;
1981	gssd_cred_id_t gssd_cred_handle;
1982
1983		gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
1984		gssd_cred_handle = KCRED_TO_CRED(cred_handle);
1985
1986		return (kgss_inquire_cred_wrapped(minor_status,
1987				gssd_cred_handle, gssd_cred_verifier,
1988				name, lifetime, cred_usage, mechanisms, uid));
1989}
1990
1991
1992OM_uint32
1993kgss_inquire_cred_by_mech_wrapped(minor_status,
1994			cred_handle,
1995			gssd_cred_verifier,
1996			mech_type,
1997			uid)
1998	OM_uint32 *minor_status;
1999	gssd_cred_id_t cred_handle;
2000	OM_uint32 gssd_cred_verifier;
2001	gss_OID mech_type;
2002	uid_t uid;
2003{
2004	OM_uint32 minor_status_temp;
2005
2006	gss_inquire_cred_by_mech_arg arg;
2007	gss_inquire_cred_by_mech_res res;
2008
2009	/* get the client handle to GSSD */
2010
2011	if ((clnt = getgssd_handle()) == NULL) {
2012		clnt_pcreateerror(server);
2013		return (GSS_S_FAILURE);
2014	}
2015
2016
2017	/* copy the procedure arguments into the rpc arg parameter */
2018
2019	arg.uid = (OM_uint32) uid;
2020
2021	arg.cred_handle.GSS_CRED_ID_T_len =
2022			cred_handle == (gssd_cred_id_t)GSS_C_NO_CREDENTIAL ?
2023			0 : (uint_t)sizeof (gssd_cred_id_t);
2024	arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle;
2025	arg.gssd_cred_verifier = gssd_cred_verifier;
2026
2027	arg.mech_type.GSS_OID_len =
2028		(uint_t)(mech_type != GSS_C_NULL_OID ?
2029		mech_type->length : 0);
2030	arg.mech_type.GSS_OID_val =
2031		(char *)(mech_type != GSS_C_NULL_OID ?
2032		mech_type->elements : 0);
2033	/* call the remote procedure */
2034
2035	memset(&res, 0, sizeof (res));
2036	if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) {
2037
2038	/*
2039	 * if the RPC call times out, null out all return arguments,
2040	 * set minor_status to its maximum value, and return GSS_S_FAILURE
2041	 */
2042
2043		if (minor_status != NULL)
2044			*minor_status = DEFAULT_MINOR_STAT;
2045		return (GSS_S_FAILURE);
2046	}
2047
2048	/* copy the rpc results into the return arguments */
2049
2050	if (minor_status != NULL)
2051		*minor_status = res.minor_status;
2052
2053	/* convert name from external to internal format */
2054
2055	/*
2056	 * free the memory allocated for the results and return with the status
2057	 * received in the rpc call
2058	 */
2059
2060	clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res);
2061	return (res.status);
2062}
2063
2064
2065OM_uint32
2066kgss_inquire_cred_by_mech(minor_status,
2067			cred_handle,
2068			mech_type,
2069			uid)
2070	OM_uint32 *minor_status;
2071	gss_cred_id_t cred_handle;
2072	gss_OID mech_type;
2073	uid_t uid;
2074{
2075
2076	OM_uint32 gssd_cred_verifier;
2077	gssd_cred_id_t gssd_cred_handle;
2078
2079	gssd_cred_verifier = KCRED_TO_CREDV(cred_handle);
2080	gssd_cred_handle = KCRED_TO_CRED(cred_handle);
2081
2082	return (kgss_inquire_cred_by_mech_wrapped(minor_status,
2083			gssd_cred_handle, gssd_cred_verifier,
2084			mech_type, uid));
2085}
2086
2087OM_uint32
2088kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid)
2089	const gss_buffer_t expName;
2090	uid_t *uidOut;
2091	gid_t *gidOut;
2092	gid_t *gids[];
2093	int *gidsLen;
2094	uid_t uid;
2095{
2096	gsscred_expname_to_unix_cred_arg args;
2097	gsscred_expname_to_unix_cred_res res;
2098
2099	/* check input/output parameters */
2100	if (expName == NULL || expName->value == NULL)
2101		return (GSS_S_CALL_INACCESSIBLE_READ);
2102
2103	if (uidOut == NULL)
2104		return (GSS_S_CALL_INACCESSIBLE_WRITE);
2105
2106	/* NULL out output parameters */
2107	*uidOut = 0;
2108	if (gidsLen)
2109		*gidsLen = 0;
2110
2111	if (gids)
2112		*gids = NULL;
2113
2114	/* get the client handle to gssd */
2115	if ((clnt = getgssd_handle()) == NULL)
2116	{
2117		clnt_pcreateerror(server);
2118		return (GSS_S_FAILURE);
2119	}
2120
2121	/* copy the procedure arguments */
2122	args.uid = uid;
2123	args.expname.GSS_BUFFER_T_val = expName->value;
2124	args.expname.GSS_BUFFER_T_len = expName->length;
2125
2126	/* null out the return buffer and call the remote proc */
2127	memset(&res, 0, sizeof (res));
2128
2129	if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
2130	{
2131		return (GSS_S_FAILURE);
2132	}
2133
2134	/* copy the results into the result parameters */
2135	if (res.major == GSS_S_COMPLETE)
2136	{
2137		*uidOut = res.uid;
2138		if (gidOut)
2139			*gidOut = res.gid;
2140		if (gids && gidsLen)
2141		{
2142			*gids = res.gids.GSSCRED_GIDS_val;
2143			*gidsLen = res.gids.GSSCRED_GIDS_len;
2144			res.gids.GSSCRED_GIDS_val = NULL;
2145			res.gids.GSSCRED_GIDS_len = 0;
2146		}
2147	}
2148
2149	/* free RPC results */
2150	clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res);
2151
2152	return (res.major);
2153} /* kgsscred_expname_to_unix_cred */
2154
2155OM_uint32
2156kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids,
2157				gidsLen, uid)
2158	const gss_name_t intName;
2159	const gss_OID mechType;
2160	uid_t *uidOut;
2161	gid_t *gidOut;
2162	gid_t *gids[];
2163	int *gidsLen;
2164	uid_t uid;
2165{
2166	gsscred_name_to_unix_cred_arg args;
2167	gsscred_name_to_unix_cred_res res;
2168	OM_uint32 major, minor;
2169	gss_OID nameOid;
2170	gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER;
2171
2172
2173	/* check the input/output parameters */
2174	if (intName == NULL || mechType == NULL)
2175		return (GSS_S_CALL_INACCESSIBLE_READ);
2176
2177	if (uidOut == NULL)
2178		return (GSS_S_CALL_INACCESSIBLE_WRITE);
2179
2180	/* NULL out the output parameters */
2181	*uidOut = 0;
2182	if (gids)
2183		*gids = NULL;
2184
2185	if (gidsLen)
2186		*gidsLen = 0;
2187
2188	/* get the client handle to gssd */
2189	if ((clnt = getgssd_handle()) == NULL)
2190	{
2191		clnt_pcreateerror(server);
2192		return (GSS_S_FAILURE);
2193	}
2194
2195	/* convert the name to flat representation */
2196	if ((major = gss_display_name(&minor, intName, &flatName, &nameOid))
2197			!= GSS_S_COMPLETE)
2198	{
2199		return (major);
2200	}
2201
2202	/* set the rpc parameters */
2203	args.uid = uid;
2204	args.pname.GSS_BUFFER_T_len = flatName.length;
2205	args.pname.GSS_BUFFER_T_val = flatName.value;
2206	args.name_type.GSS_OID_len = nameOid->length;
2207	args.name_type.GSS_OID_val = nameOid->elements;
2208	args.mech_type.GSS_OID_len = mechType->length;
2209	args.mech_type.GSS_OID_val = mechType->elements;
2210
2211	/* call the remote procedure */
2212	memset(&res, 0, sizeof (res));
2213	if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS)
2214	{
2215		gss_release_buffer(&minor, &flatName);
2216		return (GSS_S_FAILURE);
2217	}
2218
2219	gss_release_buffer(&minor, &flatName);
2220	/* copy the output parameters on output */
2221	if (res.major == GSS_S_COMPLETE)
2222	{
2223		*uidOut = res.uid;
2224		if (gidOut)
2225			*gidOut = res.gid;
2226		if (gids && gidsLen)
2227		{
2228			*gids = res.gids.GSSCRED_GIDS_val;
2229			*gidsLen = res.gids.GSSCRED_GIDS_len;
2230			res.gids.GSSCRED_GIDS_val = NULL;
2231			res.gids.GSSCRED_GIDS_len = 0;
2232		}
2233	}
2234
2235	/* delete RPC allocated memory */
2236	clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res);
2237
2238	return (res.major);
2239} /* kgsscred_name_to_unix_cred */
2240
2241OM_uint32
2242kgss_get_group_info(puid, gidOut, gids, gidsLen, uid)
2243	const uid_t puid;
2244	gid_t *gidOut;
2245	gid_t *gids[];
2246	int *gidsLen;
2247	uid_t uid;
2248{
2249	gss_get_group_info_arg args;
2250	gss_get_group_info_res res;
2251
2252
2253	/* check the output parameters */
2254	if (gidOut == NULL || gids == NULL || gidsLen == NULL)
2255		return (GSS_S_CALL_INACCESSIBLE_WRITE);
2256
2257	/* get the client GSSD handle */
2258	if ((clnt = getgssd_handle()) == NULL)
2259	{
2260		clnt_pcreateerror(server);
2261		return (GSS_S_FAILURE);
2262	}
2263
2264	/* set the input parameters */
2265	args.uid = uid;
2266	args.puid = puid;
2267
2268
2269	/* call the remote procedure */
2270	memset(&res, 0, sizeof (res));
2271	if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS)
2272	{
2273		return (GSS_S_FAILURE);
2274	}
2275
2276	/* copy the results */
2277	if (res.major == GSS_S_COMPLETE)
2278	{
2279		*gidOut = res.gid;
2280		*gids = res.gids.GSSCRED_GIDS_val;
2281		*gidsLen = res.gids.GSSCRED_GIDS_len;
2282		res.gids.GSSCRED_GIDS_val = NULL;
2283		res.gids.GSSCRED_GIDS_len = 0;
2284	}
2285
2286	/* nothing to free */
2287
2288	return (res.major);
2289} /* kgss_get_group_info */
2290
2291OM_uint32
2292kgss_export_sec_context_wrapped(minor_status,
2293				context_handle,
2294				output_token,
2295				gssd_context_verifier)
2296	OM_uint32 *minor_status;
2297	gssd_ctx_id_t *context_handle;
2298	gss_buffer_t output_token;
2299	OM_uint32 gssd_context_verifier;
2300{
2301	CLIENT *clnt;
2302	gss_export_sec_context_arg arg;
2303	gss_export_sec_context_res res;
2304
2305
2306/* get the client handle to GSSD */
2307
2308	if ((clnt = getgssd_handle()) == NULL) {
2309		clnt_pcreateerror(server);
2310		return (GSS_S_FAILURE);
2311	}
2312
2313/* copy the procedure arguments into the rpc arg parameter */
2314
2315	arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t);
2316	arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle;
2317	arg.gssd_context_verifier = gssd_context_verifier;
2318
2319/* call the remote procedure */
2320
2321	memset(&res, 0, sizeof (res));
2322	if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
2323
2324/*
2325 * if the RPC call times out, null out all return arguments, set minor_status
2326 * to its maximum value, and return GSS_S_FAILURE
2327 */
2328
2329		if (minor_status != NULL)
2330			*minor_status = DEFAULT_MINOR_STAT;
2331		if (context_handle != NULL)
2332			*context_handle = NULL;
2333		if (output_token != NULL)
2334			output_token->length = 0;
2335
2336		return (GSS_S_FAILURE);
2337	}
2338
2339/* copy the rpc results into the return arguments */
2340
2341	if (minor_status != NULL)
2342		*minor_status = res.minor_status;
2343
2344	if (res.context_handle.GSS_CTX_ID_T_len == 0)
2345		*context_handle = NULL;
2346	else
2347		*context_handle =
2348		    *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
2349
2350	if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) {
2351		output_token->length = res.output_token.GSS_BUFFER_T_len;
2352		output_token->value =
2353			(void *) MALLOC(output_token->length);
2354		memcpy(output_token->value,
2355			res.output_token.GSS_BUFFER_T_val,
2356			output_token->length);
2357	}
2358
2359/*
2360 * free the memory allocated for the results and return with the status
2361 * received in the rpc call
2362 */
2363
2364	clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res);
2365	return (res.status);
2366
2367}
2368
2369OM_uint32
2370kgss_export_sec_context(minor_status,
2371			context_handle,
2372			output_token)
2373	OM_uint32 *minor_status;
2374	gss_ctx_id_t *context_handle;
2375	gss_buffer_t output_token;
2376{
2377	OM_uint32 err;
2378	struct kgss_ctx *kctx;
2379
2380	if (*context_handle == GSS_C_NO_CONTEXT) {
2381		return (GSS_S_NO_CONTEXT);
2382	} else
2383		kctx = KCTX_TO_KGSS_CTX(*context_handle);
2384
2385	err = kgss_export_sec_context_wrapped(minor_status,
2386		&kctx->gssd_ctx, output_token,
2387		kctx->gssd_ctx_verifier);
2388
2389	if (GSS_ERROR(err))
2390		return (err);
2391	else {
2392		KGSS_FREE(kctx);
2393		*context_handle = GSS_C_NO_CONTEXT;
2394		return (err);
2395	}
2396
2397}
2398
2399OM_uint32
2400kgss_import_sec_context_wrapped(minor_status,
2401			input_token,
2402			context_handle,
2403			gssd_context_verifier)
2404	OM_uint32 *minor_status;
2405	gss_buffer_t input_token;
2406	gss_ctx_id_t *context_handle;
2407	OM_uint32 gssd_context_verifier;
2408{
2409	CLIENT *clnt;
2410	gss_import_sec_context_arg arg;
2411	gss_import_sec_context_res res;
2412
2413
2414/* get the client handle to GSSD */
2415
2416	if ((clnt = getgssd_handle()) == NULL) {
2417		clnt_pcreateerror(server);
2418		return (GSS_S_FAILURE);
2419	}
2420
2421/* copy the procedure arguments into the rpc arg parameter */
2422	arg.input_token.GSS_BUFFER_T_len = (uint_t)
2423		(input_token != GSS_C_NO_BUFFER ? input_token->length : 0);
2424	arg.input_token.GSS_BUFFER_T_val = (char *)
2425		(input_token != GSS_C_NO_BUFFER ? input_token->value : 0);
2426	arg.gssd_context_verifier = gssd_context_verifier;
2427
2428
2429/* call the remote procedure */
2430
2431	memset(&res, 0, sizeof (res));
2432	if (gss_import_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) {
2433
2434/*
2435 * if the RPC call times out, null out all return arguments, set minor_status
2436 * to its maximum value, and return GSS_S_FAILURE
2437 */
2438
2439		if (minor_status != NULL)
2440			*minor_status = DEFAULT_MINOR_STAT;
2441		if (context_handle != NULL)
2442			*context_handle = NULL;
2443
2444		return (GSS_S_FAILURE);
2445	}
2446
2447/* copy the rpc results into the return arguments */
2448
2449	if (minor_status != NULL)
2450		*minor_status = res.minor_status;
2451
2452	if (res.context_handle.GSS_CTX_ID_T_len == 0)
2453		*context_handle = NULL;
2454	else
2455		*context_handle =
2456		    *((gss_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val);
2457
2458
2459/*
2460 * free the memory allocated for the results and return with the status
2461 * received in the rpc call
2462 */
2463
2464	clnt_freeres(clnt, xdr_gss_import_sec_context_res, (caddr_t)&res);
2465	return (res.status);
2466}
2467
2468OM_uint32
2469kgss_import_sec_context(minor_status,
2470			input_token,
2471			context_handle)
2472	OM_uint32 *minor_status;
2473	gss_buffer_t input_token;
2474	gss_ctx_id_t *context_handle;
2475{
2476	struct kgss_ctx *kctx;
2477
2478	if (*context_handle == GSS_C_NO_CONTEXT) {
2479		kctx = KGSS_ALLOC();
2480		*context_handle = (gss_ctx_id_t)kctx;
2481		kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT;
2482	} else
2483		kctx = (struct kgss_ctx *)*context_handle;
2484	return (kgss_import_sec_context_wrapped(minor_status,
2485		input_token, &kctx->gssd_ctx,
2486		KCTX_TO_CTXV(context_handle)));
2487}
2488
2489#ifdef _KERNEL
2490#include <sys/modctl.h>
2491
2492static void *gss_clnt = NULL;
2493
2494#ifdef DEBUG
2495typedef struct {
2496	char		*name;		/* just put something here */
2497} gssd_devstate_t;
2498
2499
2500static void *gssd_state;
2501
2502static int gssd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2503{
2504	/*	 cmn_err(CE_NOTE, "In gssd_attach"); */
2505	switch (cmd) {
2506	case DDI_ATTACH:
2507		if (ddi_create_minor_node(dip, "gssd", S_IFCHR, 0, "gssd", 0)
2508			== DDI_FAILURE) {
2509			ddi_remove_minor_node(dip, NULL);
2510			return (DDI_FAILURE);
2511		}
2512		return (DDI_SUCCESS);
2513
2514	default:
2515		return (DDI_FAILURE);
2516	}
2517}
2518
2519static int gssd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
2520		void *arg, void **result)
2521{
2522	dev_t dev;
2523	int error;
2524
2525/*	 cmn_err(CE_NOTE, "In gssd_getinfo"); */
2526
2527	switch (infocmd) {
2528	case DDI_INFO_DEVT2INSTANCE:
2529		dev = (dev_t)arg;
2530		*result = (void *) getminor(dev);
2531		error = DDI_SUCCESS;
2532		break;
2533
2534	case DDI_INFO_DEVT2DEVINFO:
2535	/*	cmn_err(CE_NOTE, "getinfo wants devinfo"); */
2536	default:
2537		error = DDI_FAILURE;
2538		break;
2539	}
2540	return (error);
2541}
2542
2543static int gssd_identify(dev_info_t *dip)
2544{
2545	/*	 cmn_err(CE_NOTE, "in gssd_identify"); */
2546	if (strcmp(ddi_get_name(dip), "gssd") == 0)
2547		return (DDI_IDENTIFIED);
2548	else
2549		return (DDI_NOT_IDENTIFIED);
2550}
2551
2552static int gssd_probe(dev_info_t *dip)
2553{
2554	/*	 cmn_err(CE_NOTE, "In gssd_probe"); */
2555
2556	return (DDI_PROBE_SUCCESS);
2557}
2558
2559static int gssd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
2560{
2561	/*	 cmn_err (CE_NOTE, "In gssd_open"); */
2562	if (otyp != OTYP_CHR)
2563		return (EINVAL);
2564
2565	gss_clnt = getgssd_handle();
2566	return (0);
2567}
2568
2569static int gssd_close(dev_t dev, int flag, int otyp, cred_t *credp)
2570{
2571	/*	 cmn_err(CE_NOTE, "In gssd_close"); */
2572	killgssd_handle(gss_clnt);
2573	return (0);
2574}
2575
2576static int gssd_write(dev_t dev, struct uio *uiop, cred_t *credp)
2577{
2578	char buffer[1024];
2579	int len;
2580
2581	/*	 cmn_err(CE_NOTE, "In gssd_write"); */
2582	bzero(buffer, 1024);
2583
2584	uiomove(buffer, 1024, UIO_WRITE, uiop);
2585	len = strlen(buffer);
2586
2587	if (buffer[len-1] == '\n')
2588		buffer[--len] = '\0';
2589
2590	cmn_err(CE_NOTE, "Got command: (%d) \"%s\"", len, buffer);
2591	do_gssdtest(buffer);
2592	return (0);
2593}
2594
2595static struct cb_ops gssd_cb_ops = {
2596	gssd_open,		/* cb_open */
2597	gssd_close,		/* cb_close */
2598	nodev,			/* cb_strategy */
2599	nodev,			/* cb_print */
2600	nodev,			/* cb_dump */
2601	nulldev,		/* cb_read */
2602	gssd_write,		/* cb_write */
2603	nodev,			/* cb_ioctl */
2604	nodev,			/* cb_devmap */
2605	nodev,			/* cb_mmap */
2606	nodev,			/* cb_segmap */
2607	nochpoll,		/* cb_chpoll */
2608	ddi_prop_op,		/* cb_prop_op */
2609	NULL,			/* cb_stream */
2610	(int)(D_NEW|D_MP)	/* cb_flag */
2611};
2612
2613static struct dev_ops gssd_ops = {
2614	DEVO_REV,		/* devo_rev */
2615	0,			/* devo_refcnt */
2616	gssd_getinfo,		/* devo_getinfo */
2617	gssd_identify,		/* devo_identify */
2618	nulldev,		/* devo_probe */
2619	gssd_attach,		/* devo_attach */
2620	nulldev,		/* devo_detach */
2621	nodev,			/* devo_reset */
2622	&gssd_cb_ops,		/* devo_cb_ops */
2623	(struct bus_ops *)NULL	/* devo_bus_ops */
2624};
2625
2626extern struct mod_ops mod_driverops;
2627
2628static struct modldrv modlmisc = {
2629	&mod_driverops,
2630	"GSSD DRV Client Module",
2631	&gssd_ops
2632
2633#else /* !DEBUG */
2634
2635static struct modlmisc modlmisc = {
2636	&mod_miscops,
2637	"GSSD Client Module"
2638#endif /* DEBUG */
2639};
2640
2641static struct modlinkage modlinkage = {
2642	MODREV_1,
2643	(void *)&modlmisc,
2644	NULL
2645};
2646
2647char _depends_on[] = "strmod/rpcmod misc/tlimod";
2648
2649_init(void)
2650{
2651	int status;
2652
2653	if ((status = ddi_soft_state_init(&gssd_state,
2654			sizeof (gssd_devstate_t), 1)) != 0)
2655		return (status);
2656
2657	if ((status = mod_install((struct modlinkage *)&modlinkage)) != 0)
2658		ddi_soft_state_fini(&gssd_state);
2659
2660	cmn_err(CE_NOTE, "gssd: I'm in the kernel: %d.", status);
2661	return (status);
2662}
2663
2664_fini()
2665{
2666	int status;
2667
2668	killgssd_handle(gss_clnt);
2669	cmn_err(CE_NOTE, "gssd: Handle destroyed.. leaving module.");
2670
2671	if ((status = mod_remove(&modlinkage)) != 0)
2672		return (status);
2673
2674	ddi_soft_state_fini(&gssd_state);
2675	return (status);
2676}
2677
2678_info(modinfop)
2679struct modinfo *modinfop;
2680{
2681	return (mod_info(&modlinkage, modinfop));
2682}
2683
2684#endif
2685