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