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 (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /*
26  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
27  *
28  * $Id: svc_auth_gssapi.c,v 1.19 1994/10/27 12:38:51 jik Exp $
29  */
30 
31 /*
32  * Server side handling of RPCSEC_GSS flavor.
33  */
34 
35 #include <sys/systm.h>
36 #include <sys/kstat.h>
37 #include <sys/cmn_err.h>
38 #include <sys/debug.h>
39 #include <sys/types.h>
40 #include <sys/time.h>
41 #include <gssapi/gssapi.h>
42 #include <gssapi/gssapi_ext.h>
43 #include <rpc/rpc.h>
44 #include <rpc/rpcsec_defs.h>
45 #include <sys/sunddi.h>
46 #include <sys/atomic.h>
47 
48 extern bool_t __rpc_gss_make_principal(rpc_gss_principal_t *, gss_buffer_t);
49 
50 #ifdef	DEBUG
51 extern void prom_printf();
52 #endif
53 
54 #ifdef  _KERNEL
55 #define	memcmp(a, b, l) bcmp((a), (b), (l))
56 #endif
57 
58 
59 /*
60  * Sequence window definitions.
61  */
62 #define	SEQ_ARR_SIZE	4
63 #define	SEQ_WIN		(SEQ_ARR_SIZE*32)
64 #define	SEQ_HI_BIT	0x80000000
65 #define	SEQ_LO_BIT	1
66 #define	DIV_BY_32	5
67 #define	SEQ_MASK	0x1f
68 #define	SEQ_MAX		((unsigned int)0x80000000)
69 
70 
71 /* cache retransmit data */
72 typedef struct _retrans_entry {
73 	uint32_t	xid;
74 	rpc_gss_init_res result;
75 } retrans_entry;
76 
77 /*
78  * Server side RPCSEC_GSS context information.
79  */
80 typedef struct _svc_rpc_gss_data {
81 	struct _svc_rpc_gss_data	*next, *prev;
82 	struct _svc_rpc_gss_data	*lru_next, *lru_prev;
83 	bool_t				established;
84 	gss_ctx_id_t			context;
85 	gss_buffer_desc			client_name;
86 	time_t				expiration;
87 	uint_t				seq_num;
88 	uint_t				seq_bits[SEQ_ARR_SIZE];
89 	uint_t				key;
90 	OM_uint32			qop;
91 	bool_t				done_docallback;
92 	bool_t				locked;
93 	rpc_gss_rawcred_t		raw_cred;
94 	rpc_gss_ucred_t			u_cred;
95 	time_t				u_cred_set;
96 	void				*cookie;
97 	gss_cred_id_t			deleg;
98 	kmutex_t			clm;
99 	int				ref_cnt;
100 	time_t				last_ref_time;
101 	bool_t				stale;
102 	retrans_entry			*retrans_data;
103 } svc_rpc_gss_data;
104 
105 /*
106  * Data structures used for LRU based context management.
107  */
108 
109 
110 #define	HASH(key) ((key) % svc_rpc_gss_hashmod)
111 /* Size of hash table for svc_rpc_gss_data structures */
112 #define	GSS_DATA_HASH_SIZE	1024
113 
114 /*
115  * The following two defines specify a time delta that is used in
116  * sweep_clients. When the last_ref_time of a context is older than
117  * than the current time minus the delta, i.e, the context has not
118  * been referenced in the last delta seconds, we will return the
119  * context back to the cache if the ref_cnt is zero. The first delta
120  * value will be used when sweep_clients is called from
121  * svc_data_reclaim, the kmem_cache reclaim call back. We will reclaim
122  * all entries except those that are currently "active". By active we
123  * mean those that have been referenced in the last ACTIVE_DELTA
124  * seconds. If sweep_client is not being called from reclaim, then we
125  * will reclaim all entries that are "inactive". By inactive we mean
126  * those entries that have not been accessed in INACTIVE_DELTA
127  * seconds.  Note we always assume that ACTIVE_DELTA is less than
128  * INACTIVE_DELTA, so that reaping entries from a reclaim operation
129  * will necessarily imply reaping all "inactive" entries and then
130  * some.
131  */
132 
133 /*
134  * If low on memory reap cache entries that have not been active for
135  * ACTIVE_DELTA seconds and have a ref_cnt equal to zero.
136  */
137 #define	ACTIVE_DELTA		30*60		/* 30 minutes */
138 
139 /*
140  * If in sweeping contexts we find contexts with a ref_cnt equal to zero
141  * and the context has not been referenced in INACTIVE_DELTA seconds, return
142  * the entry to the cache.
143  */
144 #define	INACTIVE_DELTA		8*60*60		/* 8 hours */
145 
146 int				svc_rpc_gss_hashmod = GSS_DATA_HASH_SIZE;
147 static svc_rpc_gss_data		**clients;
148 static svc_rpc_gss_data		*lru_first, *lru_last;
149 static time_t			sweep_interval = 60*60;
150 static time_t			last_swept = 0;
151 static int			num_gss_contexts = 0;
152 static time_t			svc_rpcgss_gid_timeout = 60*60*12;
153 static kmem_cache_t		*svc_data_handle;
154 static time_t			svc_rpc_gss_active_delta = ACTIVE_DELTA;
155 static time_t			svc_rpc_gss_inactive_delta = INACTIVE_DELTA;
156 
157 /*
158  * lock used with context/lru variables
159  */
160 static kmutex_t			ctx_mutex;
161 
162 /*
163  * Data structure to contain cache statistics
164  */
165 
166 static struct {
167 	int64_t total_entries_allocated;
168 	int64_t no_reclaims;
169 	int64_t no_returned_by_reclaim;
170 } svc_rpc_gss_cache_stats;
171 
172 
173 /*
174  * lock used with server credential variables list
175  *
176  * server cred list locking guidelines:
177  * - Writer's lock holder has exclusive access to the list
178  */
179 static krwlock_t		cred_lock;
180 
181 /*
182  * server callback list
183  */
184 typedef struct rpc_gss_cblist_s {
185 	struct rpc_gss_cblist_s		*next;
186 	rpc_gss_callback_t	cb;
187 } rpc_gss_cblist_t;
188 
189 static rpc_gss_cblist_t			*rpc_gss_cblist = NULL;
190 
191 /*
192  * lock used with callback variables
193  */
194 static kmutex_t			cb_mutex;
195 
196 /*
197  * forward declarations
198  */
199 static bool_t			svc_rpc_gss_wrap();
200 static bool_t			svc_rpc_gss_unwrap();
201 static svc_rpc_gss_data		*create_client();
202 static svc_rpc_gss_data		*get_client();
203 static svc_rpc_gss_data		*find_client();
204 static void			destroy_client();
205 static void			sweep_clients(bool_t);
206 static void			insert_client();
207 static bool_t			check_verf(struct rpc_msg *, gss_ctx_id_t,
208 					int *, uid_t);
209 static bool_t			set_response_verf();
210 static void			retrans_add(svc_rpc_gss_data *, uint32_t,
211 					rpc_gss_init_res *);
212 static void			retrans_del(svc_rpc_gss_data *);
213 static bool_t			transfer_sec_context(svc_rpc_gss_data *);
214 static void			common_client_data_free(svc_rpc_gss_data *);
215 
216 /*
217  * server side wrap/unwrap routines
218  */
219 struct svc_auth_ops svc_rpc_gss_ops = {
220 	svc_rpc_gss_wrap,
221 	svc_rpc_gss_unwrap,
222 };
223 
224 /* taskq(9F) */
225 typedef struct svcrpcsec_gss_taskq_arg {
226 	SVCXPRT			*rq_xprt;
227 	rpc_gss_init_arg	*rpc_call_arg;
228 	struct rpc_msg		*msg;
229 	svc_rpc_gss_data	*client_data;
230 	uint_t			cr_version;
231 	rpc_gss_service_t	cr_service;
232 } svcrpcsec_gss_taskq_arg_t;
233 
234 /* gssd is single threaded, so 1 thread for the taskq is probably good/ok */
235 int rpcsec_gss_init_taskq_nthreads = 1;
236 static ddi_taskq_t *svcrpcsec_gss_init_taskq = NULL;
237 
238 extern struct rpc_msg *rpc_msg_dup(struct rpc_msg *);
239 extern void rpc_msg_free(struct rpc_msg **, int);
240 
241 /*
242  * from svc_clts.c:
243  * Transport private data.
244  * Kept in xprt->xp_p2buf.
245  */
246 struct udp_data {
247 	mblk_t	*ud_resp;			/* buffer for response */
248 	mblk_t	*ud_inmp;			/* mblk chain of request */
249 };
250 
251 /*ARGSUSED*/
252 static int
253 svc_gss_data_create(void *buf, void *pdata, int kmflag)
254 {
255 	svc_rpc_gss_data *client_data = (svc_rpc_gss_data *)buf;
256 
257 	mutex_init(&client_data->clm, NULL, MUTEX_DEFAULT, NULL);
258 
259 	return (0);
260 }
261 
262 /*ARGSUSED*/
263 static void
264 svc_gss_data_destroy(void *buf, void *pdata)
265 {
266 	svc_rpc_gss_data *client_data = (svc_rpc_gss_data *)buf;
267 
268 	mutex_destroy(&client_data->clm);
269 }
270 
271 
272 /*ARGSUSED*/
273 static void
274 svc_gss_data_reclaim(void *pdata)
275 {
276 	mutex_enter(&ctx_mutex);
277 
278 	svc_rpc_gss_cache_stats.no_reclaims++;
279 	sweep_clients(TRUE);
280 
281 	mutex_exit(&ctx_mutex);
282 }
283 
284 /*
285  *  Init stuff on the server side.
286  */
287 void
288 svc_gss_init()
289 {
290 	mutex_init(&cb_mutex, NULL, MUTEX_DEFAULT, NULL);
291 	mutex_init(&ctx_mutex, NULL, MUTEX_DEFAULT, NULL);
292 	rw_init(&cred_lock, NULL, RW_DEFAULT, NULL);
293 	clients = (svc_rpc_gss_data **)
294 	    kmem_zalloc(svc_rpc_gss_hashmod * sizeof (svc_rpc_gss_data *),
295 	    KM_SLEEP);
296 	svc_data_handle = kmem_cache_create("rpc_gss_data_cache",
297 	    sizeof (svc_rpc_gss_data), 0,
298 	    svc_gss_data_create,
299 	    svc_gss_data_destroy,
300 	    svc_gss_data_reclaim,
301 	    NULL, NULL, 0);
302 
303 	if (svcrpcsec_gss_init_taskq == NULL) {
304 		svcrpcsec_gss_init_taskq = ddi_taskq_create(NULL,
305 		    "rpcsec_gss_init_taskq", rpcsec_gss_init_taskq_nthreads,
306 		    TASKQ_DEFAULTPRI, 0);
307 		if (svcrpcsec_gss_init_taskq == NULL)
308 			cmn_err(CE_NOTE,
309 			    "svc_gss_init: ddi_taskq_create failed");
310 	}
311 }
312 
313 /*
314  * Destroy structures allocated in svc_gss_init().
315  * This routine is called by _init() if mod_install() failed.
316  */
317 void
318 svc_gss_fini()
319 {
320 	mutex_destroy(&cb_mutex);
321 	mutex_destroy(&ctx_mutex);
322 	rw_destroy(&cred_lock);
323 	kmem_free(clients, svc_rpc_gss_hashmod * sizeof (svc_rpc_gss_data *));
324 	kmem_cache_destroy(svc_data_handle);
325 }
326 
327 /*
328  * Cleanup routine for destroying context, called after service
329  * procedure is executed. Actually we just decrement the reference count
330  * associated with this context. If the reference count is zero and the
331  * context is marked as stale, we would then destroy the context. Additionally,
332  * we check if its been longer than sweep_interval since the last sweep_clients
333  * was run, and if so run sweep_clients to free all stale contexts with zero
334  * reference counts or contexts that are old. (Haven't been access in
335  * svc_rpc_inactive_delta seconds).
336  */
337 void
338 rpc_gss_cleanup(SVCXPRT *clone_xprt)
339 {
340 	svc_rpc_gss_data	*cl;
341 	SVCAUTH			*svcauth;
342 
343 	/*
344 	 * First check if current context needs to be cleaned up.
345 	 * There might be other threads stale this client data
346 	 * in between.
347 	 */
348 	svcauth = &clone_xprt->xp_auth;
349 	mutex_enter(&ctx_mutex);
350 	if ((cl = (svc_rpc_gss_data *)svcauth->svc_ah_private) != NULL) {
351 		mutex_enter(&cl->clm);
352 		ASSERT(cl->ref_cnt > 0);
353 		if (--cl->ref_cnt == 0 && cl->stale) {
354 			mutex_exit(&cl->clm);
355 			destroy_client(cl);
356 			svcauth->svc_ah_private = NULL;
357 		} else
358 			mutex_exit(&cl->clm);
359 	}
360 
361 	/*
362 	 * Check for other expired contexts.
363 	 */
364 	if ((gethrestime_sec() - last_swept) > sweep_interval)
365 		sweep_clients(FALSE);
366 
367 	mutex_exit(&ctx_mutex);
368 }
369 
370 /*
371  * Shift the array arr of length arrlen right by nbits bits.
372  */
373 static void
374 shift_bits(arr, arrlen, nbits)
375 	uint_t	*arr;
376 	int	arrlen;
377 	int	nbits;
378 {
379 	int	i, j;
380 	uint_t	lo, hi;
381 
382 	/*
383 	 * If the number of bits to be shifted exceeds SEQ_WIN, just
384 	 * zero out the array.
385 	 */
386 	if (nbits < SEQ_WIN) {
387 		for (i = 0; i < nbits; i++) {
388 			hi = 0;
389 			for (j = 0; j < arrlen; j++) {
390 				lo = arr[j] & SEQ_LO_BIT;
391 				arr[j] >>= 1;
392 				if (hi)
393 					arr[j] |= SEQ_HI_BIT;
394 				hi = lo;
395 			}
396 		}
397 	} else {
398 		for (j = 0; j < arrlen; j++)
399 			arr[j] = 0;
400 	}
401 }
402 
403 /*
404  * Check that the received sequence number seq_num is valid.
405  */
406 static bool_t
407 check_seq(cl, seq_num, kill_context)
408 	svc_rpc_gss_data	*cl;
409 	uint_t			seq_num;
410 	bool_t			*kill_context;
411 {
412 	int			i, j;
413 	uint_t			bit;
414 
415 	/*
416 	 * If it exceeds the maximum, kill context.
417 	 */
418 	if (seq_num >= SEQ_MAX) {
419 		*kill_context = TRUE;
420 		RPCGSS_LOG0(4, "check_seq: seq_num not valid\n");
421 		return (FALSE);
422 	}
423 
424 	/*
425 	 * If greater than the last seen sequence number, just shift
426 	 * the sequence window so that it starts at the new sequence
427 	 * number and extends downwards by SEQ_WIN.
428 	 */
429 	if (seq_num > cl->seq_num) {
430 		(void) shift_bits(cl->seq_bits, SEQ_ARR_SIZE,
431 				(int)(seq_num - cl->seq_num));
432 		cl->seq_bits[0] |= SEQ_HI_BIT;
433 		cl->seq_num = seq_num;
434 		return (TRUE);
435 	}
436 
437 	/*
438 	 * If it is outside the sequence window, return failure.
439 	 */
440 	i = cl->seq_num - seq_num;
441 	if (i >= SEQ_WIN) {
442 		RPCGSS_LOG0(4, "check_seq: seq_num is outside the window\n");
443 		return (FALSE);
444 	}
445 
446 	/*
447 	 * If within sequence window, set the bit corresponding to it
448 	 * if not already seen;  if already seen, return failure.
449 	 */
450 	j = SEQ_MASK - (i & SEQ_MASK);
451 	bit = j > 0 ? (1 << j) : 1;
452 	i >>= DIV_BY_32;
453 	if (cl->seq_bits[i] & bit) {
454 		RPCGSS_LOG0(4, "check_seq: sequence number already seen\n");
455 		return (FALSE);
456 	}
457 	cl->seq_bits[i] |= bit;
458 	return (TRUE);
459 }
460 
461 /*
462  * Set server callback.
463  */
464 bool_t
465 rpc_gss_set_callback(cb)
466 	rpc_gss_callback_t	*cb;
467 {
468 	rpc_gss_cblist_t		*cbl, *tmp;
469 
470 	if (cb->callback == NULL) {
471 		RPCGSS_LOG0(1, "rpc_gss_set_callback: no callback to set\n");
472 		return (FALSE);
473 	}
474 
475 	/* check if there is already an entry in the rpc_gss_cblist. */
476 	mutex_enter(&cb_mutex);
477 	if (rpc_gss_cblist) {
478 		for (tmp = rpc_gss_cblist; tmp != NULL; tmp = tmp->next) {
479 			if ((tmp->cb.callback == cb->callback) &&
480 			    (tmp->cb.version == cb->version) &&
481 			    (tmp->cb.program == cb->program)) {
482 				mutex_exit(&cb_mutex);
483 				return (TRUE);
484 			}
485 		}
486 	}
487 
488 	/* Not in rpc_gss_cblist.  Create a new entry. */
489 	if ((cbl = (rpc_gss_cblist_t *)kmem_alloc(sizeof (*cbl), KM_SLEEP))
490 	    == NULL) {
491 		mutex_exit(&cb_mutex);
492 		return (FALSE);
493 	}
494 	cbl->cb = *cb;
495 	cbl->next = rpc_gss_cblist;
496 	rpc_gss_cblist = cbl;
497 	mutex_exit(&cb_mutex);
498 	return (TRUE);
499 }
500 
501 /*
502  * Locate callback (if specified) and call server.  Release any
503  * delegated credentials unless passed to server and the server
504  * accepts the context.  If a callback is not specified, accept
505  * the incoming context.
506  */
507 static bool_t
508 do_callback(req, client_data)
509 	struct svc_req		*req;
510 	svc_rpc_gss_data	*client_data;
511 {
512 	rpc_gss_cblist_t		*cbl;
513 	bool_t			ret = TRUE, found = FALSE;
514 	rpc_gss_lock_t		lock;
515 	OM_uint32		minor;
516 	mutex_enter(&cb_mutex);
517 	for (cbl = rpc_gss_cblist; cbl != NULL; cbl = cbl->next) {
518 		if (req->rq_prog != cbl->cb.program ||
519 					req->rq_vers != cbl->cb.version)
520 			continue;
521 		found = TRUE;
522 		lock.locked = FALSE;
523 		lock.raw_cred = &client_data->raw_cred;
524 		ret = (*cbl->cb.callback)(req, client_data->deleg,
525 			client_data->context, &lock, &client_data->cookie);
526 		req->rq_xprt->xp_cookie = client_data->cookie;
527 
528 		if (ret) {
529 			client_data->locked = lock.locked;
530 			client_data->deleg = GSS_C_NO_CREDENTIAL;
531 		}
532 		break;
533 	}
534 	if (!found) {
535 		if (client_data->deleg != GSS_C_NO_CREDENTIAL) {
536 			(void) kgss_release_cred(&minor, &client_data->deleg,
537 					crgetuid(CRED()));
538 			client_data->deleg = GSS_C_NO_CREDENTIAL;
539 		}
540 	}
541 	mutex_exit(&cb_mutex);
542 	return (ret);
543 }
544 
545 /*
546  * Get caller credentials.
547  */
548 bool_t
549 rpc_gss_getcred(req, rcred, ucred, cookie)
550 	struct svc_req		*req;
551 	rpc_gss_rawcred_t	**rcred;
552 	rpc_gss_ucred_t		**ucred;
553 	void			**cookie;
554 {
555 	SVCAUTH			*svcauth;
556 	svc_rpc_gss_data	*client_data;
557 	int			gssstat, gidlen;
558 
559 	svcauth = &req->rq_xprt->xp_auth;
560 	client_data = (svc_rpc_gss_data *)svcauth->svc_ah_private;
561 
562 	mutex_enter(&client_data->clm);
563 
564 	if (rcred != NULL) {
565 		svcauth->raw_cred = client_data->raw_cred;
566 		*rcred = &svcauth->raw_cred;
567 	}
568 	if (ucred != NULL) {
569 		*ucred = &client_data->u_cred;
570 
571 		if (client_data->u_cred_set == 0 ||
572 		    client_data->u_cred_set < gethrestime_sec()) {
573 		    if (client_data->u_cred_set == 0) {
574 			if ((gssstat = kgsscred_expname_to_unix_cred(
575 			    &client_data->client_name,
576 			    &client_data->u_cred.uid,
577 			    &client_data->u_cred.gid,
578 			    &client_data->u_cred.gidlist,
579 			    &gidlen, crgetuid(CRED()))) != GSS_S_COMPLETE) {
580 				RPCGSS_LOG(1, "rpc_gss_getcred: "
581 				    "kgsscred_expname_to_unix_cred failed %x\n",
582 				    gssstat);
583 				*ucred = NULL;
584 			} else {
585 				client_data->u_cred.gidlen = (short)gidlen;
586 				client_data->u_cred_set =
587 				    gethrestime_sec() + svc_rpcgss_gid_timeout;
588 			}
589 		    } else if (client_data->u_cred_set < gethrestime_sec()) {
590 			if ((gssstat = kgss_get_group_info(
591 			    client_data->u_cred.uid,
592 			    &client_data->u_cred.gid,
593 			    &client_data->u_cred.gidlist,
594 			    &gidlen, crgetuid(CRED()))) != GSS_S_COMPLETE) {
595 				RPCGSS_LOG(1, "rpc_gss_getcred: "
596 				    "kgss_get_group_info failed %x\n",
597 				    gssstat);
598 				*ucred = NULL;
599 			} else {
600 				client_data->u_cred.gidlen = (short)gidlen;
601 				client_data->u_cred_set =
602 				    gethrestime_sec() + svc_rpcgss_gid_timeout;
603 			}
604 		    }
605 		}
606 	}
607 
608 	if (cookie != NULL)
609 		*cookie = client_data->cookie;
610 	req->rq_xprt->xp_cookie = client_data->cookie;
611 
612 	mutex_exit(&client_data->clm);
613 
614 	return (TRUE);
615 }
616 
617 /*
618  * Transfer the context data from the user land to the kernel.
619  */
620 bool_t transfer_sec_context(svc_rpc_gss_data *client_data) {
621 
622 	gss_buffer_desc process_token;
623 	OM_uint32 gssstat, minor;
624 
625 	/*
626 	 * Call kgss_export_sec_context
627 	 * if an error is returned log a message
628 	 * go to error handling
629 	 * Otherwise call kgss_import_sec_context to
630 	 * convert the token into a context
631 	 */
632 	gssstat  = kgss_export_sec_context(&minor, client_data->context,
633 				&process_token);
634 	/*
635 	 * if export_sec_context returns an error we delete the
636 	 * context just to be safe.
637 	 */
638 	if (gssstat == GSS_S_NAME_NOT_MN) {
639 		RPCGSS_LOG0(4, "svc_rpcsec_gss: export sec context "
640 				"Kernel mod unavailable\n");
641 
642 	} else if (gssstat != GSS_S_COMPLETE) {
643 		RPCGSS_LOG(1, "svc_rpcsec_gss: export sec context failed  "
644 				" gssstat = 0x%x\n", gssstat);
645 		(void) gss_release_buffer(&minor, &process_token);
646 		(void) kgss_delete_sec_context(&minor, &client_data->context,
647 				NULL);
648 		return (FALSE);
649 
650 	} else if (process_token.length == 0) {
651 		RPCGSS_LOG0(1, "svc_rpcsec_gss:zero length token in response "
652 				"for export_sec_context, but "
653 				"gsstat == GSS_S_COMPLETE\n");
654 		(void) kgss_delete_sec_context(&minor, &client_data->context,
655 				NULL);
656 		return (FALSE);
657 
658 	} else {
659 		gssstat = kgss_import_sec_context(&minor, &process_token,
660 					client_data->context);
661 		if (gssstat != GSS_S_COMPLETE) {
662 			RPCGSS_LOG(1, "svc_rpcsec_gss: import sec context "
663 				" failed gssstat = 0x%x\n", gssstat);
664 			(void) kgss_delete_sec_context(&minor,
665 				&client_data->context, NULL);
666 			(void) gss_release_buffer(&minor, &process_token);
667 			return (FALSE);
668 		}
669 
670 		RPCGSS_LOG0(4, "gss_import_sec_context successful\n");
671 		(void) gss_release_buffer(&minor, &process_token);
672 	}
673 
674 	return (TRUE);
675 }
676 
677 /*
678  * do_gss_accept is called from a taskq and does all the work for a
679  * RPCSEC_GSS_INIT call (mostly calling kgss_accept_sec_context()).
680  */
681 static enum auth_stat
682 do_gss_accept(
683 	SVCXPRT *xprt,
684 	rpc_gss_init_arg *call_arg,
685 	struct rpc_msg *msg,
686 	svc_rpc_gss_data *client_data,
687 	uint_t cr_version,
688 	rpc_gss_service_t cr_service)
689 {
690 	rpc_gss_init_res	call_res;
691 	gss_buffer_desc		output_token;
692 	OM_uint32		gssstat, minor, minor_stat, time_rec;
693 	int			ret_flags, ret;
694 	gss_OID 		mech_type = GSS_C_NULL_OID;
695 	int			free_mech_type = 1;
696 	struct svc_req		r, *rqst;
697 
698 	rqst = &r;
699 	rqst->rq_xprt = xprt;
700 
701 	/*
702 	 * Initialize output_token.
703 	 */
704 	output_token.length = 0;
705 	output_token.value = NULL;
706 
707 	bzero((char *)&call_res, sizeof (call_res));
708 
709 	mutex_enter(&client_data->clm);
710 	if (client_data->stale) {
711 		ret = RPCSEC_GSS_NOCRED;
712 		RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n");
713 		goto error2;
714 	}
715 
716 	/*
717 	 * Any response we send will use ctx_handle, so set it now;
718 	 * also set seq_window since this won't change.
719 	 */
720 	call_res.ctx_handle.length = sizeof (client_data->key);
721 	call_res.ctx_handle.value = (char *)&client_data->key;
722 	call_res.seq_window = SEQ_WIN;
723 
724 	gssstat = GSS_S_FAILURE;
725 	minor = 0;
726 	minor_stat = 0;
727 	rw_enter(&cred_lock, RW_READER);
728 
729 	if (client_data->client_name.length) {
730 		(void) gss_release_buffer(&minor,
731 		    &client_data->client_name);
732 	}
733 	gssstat = kgss_accept_sec_context(&minor_stat,
734 	    &client_data->context,
735 	    GSS_C_NO_CREDENTIAL,
736 	    call_arg,
737 	    GSS_C_NO_CHANNEL_BINDINGS,
738 	    &client_data->client_name,
739 	    &mech_type,
740 	    &output_token,
741 	    &ret_flags,
742 	    &time_rec,
743 	    NULL,		/* don't need a delegated cred back */
744 	    crgetuid(CRED()));
745 
746 	RPCGSS_LOG(4, "gssstat 0x%x \n", gssstat);
747 
748 	if (gssstat == GSS_S_COMPLETE) {
749 		/*
750 		 * Set the raw and unix credentials at this
751 		 * point.  This saves a lot of computation
752 		 * later when credentials are retrieved.
753 		 */
754 		client_data->raw_cred.version = cr_version;
755 		client_data->raw_cred.service = cr_service;
756 
757 		if (client_data->raw_cred.mechanism) {
758 			kgss_free_oid(client_data->raw_cred.mechanism);
759 			client_data->raw_cred.mechanism = NULL;
760 		}
761 		client_data->raw_cred.mechanism = (rpc_gss_OID) mech_type;
762 		/*
763 		 * client_data is now responsible for freeing
764 		 * the data of 'mech_type'.
765 		 */
766 		free_mech_type = 0;
767 
768 		if (client_data->raw_cred.client_principal) {
769 			kmem_free((caddr_t)client_data->\
770 			    raw_cred.client_principal,
771 			    client_data->raw_cred.\
772 			    client_principal->len + sizeof (int));
773 			client_data->raw_cred.client_principal = NULL;
774 		}
775 
776 		/*
777 		 *  The client_name returned from
778 		 *  kgss_accept_sec_context() is in an
779 		 *  exported flat format.
780 		 */
781 		if (! __rpc_gss_make_principal(
782 		    &client_data->raw_cred.client_principal,
783 		    &client_data->client_name)) {
784 			RPCGSS_LOG0(1, "_svcrpcsec_gss: "
785 			    "make principal failed\n");
786 			gssstat = GSS_S_FAILURE;
787 			(void) gss_release_buffer(&minor_stat, &output_token);
788 		}
789 	}
790 
791 	rw_exit(&cred_lock);
792 
793 	call_res.gss_major = gssstat;
794 	call_res.gss_minor = minor_stat;
795 
796 	if (gssstat != GSS_S_COMPLETE &&
797 	    gssstat != GSS_S_CONTINUE_NEEDED) {
798 		call_res.ctx_handle.length = 0;
799 		call_res.ctx_handle.value = NULL;
800 		call_res.seq_window = 0;
801 		rpc_gss_display_status(gssstat, minor_stat, mech_type,
802 		    crgetuid(CRED()),
803 		    "_svc_rpcsec_gss gss_accept_sec_context");
804 		(void) svc_sendreply(rqst->rq_xprt,
805 		    __xdr_rpc_gss_init_res, (caddr_t)&call_res);
806 		client_data->stale = TRUE;
807 		ret = AUTH_OK;
808 		goto error2;
809 	}
810 
811 	/*
812 	 * If appropriate, set established to TRUE *after* sending
813 	 * response (otherwise, the client will receive the final
814 	 * token encrypted)
815 	 */
816 	if (gssstat == GSS_S_COMPLETE) {
817 		/*
818 		 * Context is established.  Set expiration time
819 		 * for the context.
820 		 */
821 		client_data->seq_num = 1;
822 		if ((time_rec == GSS_C_INDEFINITE) || (time_rec == 0)) {
823 			client_data->expiration = GSS_C_INDEFINITE;
824 		} else {
825 			client_data->expiration =
826 			    time_rec + gethrestime_sec();
827 		}
828 
829 		if (!transfer_sec_context(client_data)) {
830 			ret = RPCSEC_GSS_FAILED;
831 			client_data->stale = TRUE;
832 			RPCGSS_LOG0(1,
833 			    "_svc_rpcsec_gss: transfer sec context failed\n");
834 			goto error2;
835 		}
836 
837 		client_data->established = TRUE;
838 	}
839 
840 	/*
841 	 * This step succeeded.  Send a response, along with
842 	 * a token if there's one.  Don't dispatch.
843 	 */
844 
845 	if (output_token.length != 0)
846 		GSS_COPY_BUFFER(call_res.token, output_token);
847 
848 	/*
849 	 * If GSS_S_COMPLETE: set response verifier to
850 	 * checksum of SEQ_WIN
851 	 */
852 	if (gssstat == GSS_S_COMPLETE) {
853 		if (!set_response_verf(rqst, msg, client_data,
854 		    (uint_t)SEQ_WIN)) {
855 			ret = RPCSEC_GSS_FAILED;
856 			client_data->stale = TRUE;
857 			RPCGSS_LOG0(1,
858 			    "_svc_rpcsec_gss:set response verifier failed\n");
859 			goto error2;
860 		}
861 	}
862 
863 	if (!svc_sendreply(rqst->rq_xprt, __xdr_rpc_gss_init_res,
864 	    (caddr_t)&call_res)) {
865 		ret = RPCSEC_GSS_FAILED;
866 		client_data->stale = TRUE;
867 		RPCGSS_LOG0(1, "_svc_rpcsec_gss:send reply failed\n");
868 		goto error2;
869 	}
870 
871 	/*
872 	 * Cache last response in case it is lost and the client
873 	 * retries on an established context.
874 	 */
875 	(void) retrans_add(client_data, msg->rm_xid, &call_res);
876 	ASSERT(client_data->ref_cnt > 0);
877 	client_data->ref_cnt--;
878 	mutex_exit(&client_data->clm);
879 
880 	(void) gss_release_buffer(&minor_stat, &output_token);
881 
882 	return (AUTH_OK);
883 
884 error2:
885 	ASSERT(client_data->ref_cnt > 0);
886 	client_data->ref_cnt--;
887 	mutex_exit(&client_data->clm);
888 	(void) gss_release_buffer(&minor_stat, &output_token);
889 	if (free_mech_type && mech_type)
890 		kgss_free_oid(mech_type);
891 
892 	return (ret);
893 }
894 
895 static void
896 svcrpcsec_gss_taskq_func(void *svcrpcsecgss_taskq_arg)
897 {
898 	enum auth_stat retval;
899 	svcrpcsec_gss_taskq_arg_t *arg = svcrpcsecgss_taskq_arg;
900 
901 	retval = do_gss_accept(arg->rq_xprt, arg->rpc_call_arg, arg->msg,
902 	    arg->client_data, arg->cr_version, arg->cr_service);
903 	if (retval != AUTH_OK) {
904 		cmn_err(CE_NOTE,
905 		    "svcrpcsec_gss_taskq_func:  do_gss_accept fail 0x%x",
906 		    retval);
907 	}
908 	rpc_msg_free(&arg->msg, MAX_AUTH_BYTES);
909 	svc_clone_unlink(arg->rq_xprt);
910 	svc_clone_free(arg->rq_xprt);
911 	xdr_free(__xdr_rpc_gss_init_arg, (caddr_t)arg->rpc_call_arg);
912 	kmem_free(arg->rpc_call_arg, sizeof (*arg->rpc_call_arg));
913 
914 	kmem_free(arg, sizeof (*arg));
915 }
916 
917 static enum auth_stat
918 rpcsec_gss_init(
919 	struct svc_req		*rqst,
920 	struct rpc_msg		*msg,
921 	rpc_gss_creds		creds,
922 	bool_t			*no_dispatch,
923 	svc_rpc_gss_data	*c_d) /* client data, can be NULL */
924 {
925 	svc_rpc_gss_data	*client_data;
926 	int ret;
927 	svcrpcsec_gss_taskq_arg_t *arg;
928 
929 	if (creds.ctx_handle.length != 0) {
930 		RPCGSS_LOG0(1, "_svcrpcsec_gss: ctx_handle not null\n");
931 		ret = AUTH_BADCRED;
932 		return (ret);
933 	}
934 
935 	client_data = c_d ? c_d : create_client();
936 	if (client_data == NULL) {
937 		RPCGSS_LOG0(1,
938 		    "_svcrpcsec_gss: can't create a new cache entry\n");
939 		ret = AUTH_FAILED;
940 		return (ret);
941 	}
942 
943 	mutex_enter(&client_data->clm);
944 	if (client_data->stale) {
945 		ret = RPCSEC_GSS_NOCRED;
946 		RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n");
947 		goto error2;
948 	}
949 
950 	/*
951 	 * kgss_accept_sec_context()/gssd(1M) can be overly time
952 	 * consuming so let's queue it and return asap.
953 	 *
954 	 * taskq func must free arg.
955 	 */
956 	arg = kmem_alloc(sizeof (*arg), KM_SLEEP);
957 
958 	/* taskq func must free rpc_call_arg & deserialized arguments */
959 	arg->rpc_call_arg = kmem_alloc(sizeof (*arg->rpc_call_arg), KM_SLEEP);
960 
961 	/* deserialize arguments */
962 	bzero(arg->rpc_call_arg, sizeof (*arg->rpc_call_arg));
963 	if (!SVC_GETARGS(rqst->rq_xprt, __xdr_rpc_gss_init_arg,
964 	    (caddr_t)arg->rpc_call_arg)) {
965 		ret = RPCSEC_GSS_FAILED;
966 		client_data->stale = TRUE;
967 		goto error2;
968 	}
969 
970 	/* get a xprt clone for taskq thread, taskq func must free it */
971 	arg->rq_xprt = svc_clone_init();
972 	svc_clone_link(rqst->rq_xprt->xp_master, arg->rq_xprt, rqst->rq_xprt);
973 	arg->rq_xprt->xp_xid = rqst->rq_xprt->xp_xid;
974 
975 
976 	/* set the appropriate wrap/unwrap routine for RPCSEC_GSS */
977 	arg->rq_xprt->xp_auth.svc_ah_ops = svc_rpc_gss_ops;
978 	arg->rq_xprt->xp_auth.svc_ah_private = (caddr_t)client_data;
979 
980 	/* get a dup of rpc msg for taskq thread */
981 	arg->msg = rpc_msg_dup(msg);  /* taskq func must free msg dup */
982 
983 	arg->client_data = client_data;
984 	arg->cr_version = creds.version;
985 	arg->cr_service = creds.service;
986 
987 	/* We no longer need the xp_xdrin, destroy it all here. */
988 	XDR_DESTROY(&(rqst->rq_xprt->xp_xdrin));
989 
990 	/* should be ok to hold clm lock as taskq will have new thread(s) */
991 	ret = ddi_taskq_dispatch(svcrpcsec_gss_init_taskq,
992 	    svcrpcsec_gss_taskq_func, arg, DDI_SLEEP);
993 	if (ret == DDI_FAILURE) {
994 		cmn_err(CE_NOTE, "rpcsec_gss_init: taskq dispatch fail");
995 		ret = RPCSEC_GSS_FAILED;
996 		rpc_msg_free(&arg->msg, MAX_AUTH_BYTES);
997 		svc_clone_unlink(arg->rq_xprt);
998 		svc_clone_free(arg->rq_xprt);
999 		kmem_free(arg, sizeof (*arg));
1000 		goto error2;
1001 	}
1002 
1003 	mutex_exit(&client_data->clm);
1004 	*no_dispatch = TRUE;
1005 	return (AUTH_OK);
1006 
1007 error2:
1008 	ASSERT(client_data->ref_cnt > 0);
1009 	client_data->ref_cnt--;
1010 	mutex_exit(&client_data->clm);
1011 	cmn_err(CE_NOTE, "rpcsec_gss_init: error 0x%x", ret);
1012 	return (ret);
1013 }
1014 
1015 static enum auth_stat
1016 rpcsec_gss_continue_init(
1017 	struct svc_req		*rqst,
1018 	struct rpc_msg		*msg,
1019 	rpc_gss_creds		creds,
1020 	bool_t			*no_dispatch)
1021 {
1022 	int ret;
1023 	svc_rpc_gss_data	*client_data;
1024 	svc_rpc_gss_parms_t	*gss_parms;
1025 	rpc_gss_init_res	*retrans_result;
1026 
1027 	if (creds.ctx_handle.length == 0) {
1028 		RPCGSS_LOG0(1, "_svcrpcsec_gss: no ctx_handle\n");
1029 		ret = AUTH_BADCRED;
1030 		return (ret);
1031 	}
1032 	if ((client_data = get_client(&creds.ctx_handle)) == NULL) {
1033 		ret = RPCSEC_GSS_NOCRED;
1034 		RPCGSS_LOG0(1, "_svcrpcsec_gss: no security context\n");
1035 		return (ret);
1036 	}
1037 
1038 	mutex_enter(&client_data->clm);
1039 	if (client_data->stale) {
1040 		ret = RPCSEC_GSS_NOCRED;
1041 		RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n");
1042 		goto error2;
1043 	}
1044 
1045 	/*
1046 	 * If context not established, go thru INIT code but with
1047 	 * this client handle.
1048 	 */
1049 	if (!client_data->established) {
1050 		mutex_exit(&client_data->clm);
1051 		return (rpcsec_gss_init(rqst, msg, creds, no_dispatch,
1052 		    client_data));
1053 	}
1054 
1055 	/*
1056 	 * Set the appropriate wrap/unwrap routine for RPCSEC_GSS.
1057 	 */
1058 	rqst->rq_xprt->xp_auth.svc_ah_ops = svc_rpc_gss_ops;
1059 	rqst->rq_xprt->xp_auth.svc_ah_private = (caddr_t)client_data;
1060 
1061 	/*
1062 	 * Keep copy of parameters we'll need for response, for the
1063 	 * sake of reentrancy (we don't want to look in the context
1064 	 * data because when we are sending a response, another
1065 	 * request may have come in).
1066 	 */
1067 	gss_parms = &rqst->rq_xprt->xp_auth.svc_gss_parms;
1068 	gss_parms->established = client_data->established;
1069 	gss_parms->service = creds.service;
1070 	gss_parms->qop_rcvd = (uint_t)client_data->qop;
1071 	gss_parms->context = (void *)client_data->context;
1072 	gss_parms->seq_num = creds.seq_num;
1073 
1074 	/*
1075 	 * This is an established context. Continue to
1076 	 * satisfy retried continue init requests out of
1077 	 * the retransmit cache.  Throw away any that don't
1078 	 * have a matching xid or the cach is empty.
1079 	 * Delete the retransmit cache once the client sends
1080 	 * a data request.
1081 	 */
1082 	if (client_data->retrans_data &&
1083 	    (client_data->retrans_data->xid == msg->rm_xid)) {
1084 		retrans_result = &client_data->retrans_data->result;
1085 		if (set_response_verf(rqst, msg, client_data,
1086 		    (uint_t)retrans_result->seq_window)) {
1087 			gss_parms->established = FALSE;
1088 			(void) svc_sendreply(rqst->rq_xprt,
1089 			    __xdr_rpc_gss_init_res, (caddr_t)retrans_result);
1090 			*no_dispatch = TRUE;
1091 			ASSERT(client_data->ref_cnt > 0);
1092 			client_data->ref_cnt--;
1093 		}
1094 	}
1095 	mutex_exit(&client_data->clm);
1096 
1097 	return (AUTH_OK);
1098 
1099 error2:
1100 	ASSERT(client_data->ref_cnt > 0);
1101 	client_data->ref_cnt--;
1102 	mutex_exit(&client_data->clm);
1103 	return (ret);
1104 }
1105 
1106 static enum auth_stat
1107 rpcsec_gss_data(
1108 	struct svc_req		*rqst,
1109 	struct rpc_msg		*msg,
1110 	rpc_gss_creds		creds,
1111 	bool_t			*no_dispatch)
1112 {
1113 	int ret;
1114 	svc_rpc_gss_parms_t	*gss_parms;
1115 	svc_rpc_gss_data	*client_data;
1116 
1117 	switch (creds.service) {
1118 	case rpc_gss_svc_none:
1119 	case rpc_gss_svc_integrity:
1120 	case rpc_gss_svc_privacy:
1121 		break;
1122 	default:
1123 		cmn_err(CE_NOTE, "__svcrpcsec_gss: unknown service type=0x%x",
1124 		    creds.service);
1125 		RPCGSS_LOG(1, "_svcrpcsec_gss: unknown service type: 0x%x\n",
1126 		    creds.service);
1127 		ret = AUTH_BADCRED;
1128 		return (ret);
1129 	}
1130 
1131 	if (creds.ctx_handle.length == 0) {
1132 		RPCGSS_LOG0(1, "_svcrpcsec_gss: no ctx_handle\n");
1133 		ret = AUTH_BADCRED;
1134 		return (ret);
1135 	}
1136 	if ((client_data = get_client(&creds.ctx_handle)) == NULL) {
1137 		ret = RPCSEC_GSS_NOCRED;
1138 		RPCGSS_LOG0(1, "_svcrpcsec_gss: no security context\n");
1139 		return (ret);
1140 	}
1141 
1142 
1143 	mutex_enter(&client_data->clm);
1144 	if (!client_data->established) {
1145 		ret = AUTH_FAILED;
1146 		goto error2;
1147 	}
1148 	if (client_data->stale) {
1149 		ret = RPCSEC_GSS_NOCRED;
1150 		RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n");
1151 		goto error2;
1152 	}
1153 
1154 	/*
1155 	 * Once the context is established and there is no more
1156 	 * retransmission of last continue init request, it is safe
1157 	 * to delete the retransmit cache entry.
1158 	 */
1159 	if (client_data->retrans_data)
1160 		retrans_del(client_data);
1161 
1162 	/*
1163 	 * Set the appropriate wrap/unwrap routine for RPCSEC_GSS.
1164 	 */
1165 	rqst->rq_xprt->xp_auth.svc_ah_ops = svc_rpc_gss_ops;
1166 	rqst->rq_xprt->xp_auth.svc_ah_private = (caddr_t)client_data;
1167 
1168 	/*
1169 	 * Keep copy of parameters we'll need for response, for the
1170 	 * sake of reentrancy (we don't want to look in the context
1171 	 * data because when we are sending a response, another
1172 	 * request may have come in).
1173 	 */
1174 	gss_parms = &rqst->rq_xprt->xp_auth.svc_gss_parms;
1175 	gss_parms->established = client_data->established;
1176 	gss_parms->service = creds.service;
1177 	gss_parms->qop_rcvd = (uint_t)client_data->qop;
1178 	gss_parms->context = (void *)client_data->context;
1179 	gss_parms->seq_num = creds.seq_num;
1180 
1181 	/*
1182 	 * Context is already established.  Check verifier, and
1183 	 * note parameters we will need for response in gss_parms.
1184 	 */
1185 	if (!check_verf(msg, client_data->context,
1186 	    (int *)&gss_parms->qop_rcvd, client_data->u_cred.uid)) {
1187 		ret = RPCSEC_GSS_NOCRED;
1188 		RPCGSS_LOG0(1, "_svcrpcsec_gss: check verf failed\n");
1189 		goto error2;
1190 	}
1191 
1192 	/*
1193 	 *  Check and invoke callback if necessary.
1194 	 */
1195 	if (!client_data->done_docallback) {
1196 		client_data->done_docallback = TRUE;
1197 		client_data->qop = gss_parms->qop_rcvd;
1198 		client_data->raw_cred.qop = gss_parms->qop_rcvd;
1199 		client_data->raw_cred.service = creds.service;
1200 		if (!do_callback(rqst, client_data)) {
1201 			ret = AUTH_FAILED;
1202 			RPCGSS_LOG0(1, "_svc_rpcsec_gss:callback failed\n");
1203 			goto error2;
1204 		}
1205 	}
1206 
1207 	/*
1208 	 * If the context was locked, make sure that the client
1209 	 * has not changed QOP.
1210 	 */
1211 	if (client_data->locked && gss_parms->qop_rcvd != client_data->qop) {
1212 		ret = AUTH_BADVERF;
1213 		RPCGSS_LOG0(1, "_svcrpcsec_gss: can not change qop\n");
1214 		goto error2;
1215 	}
1216 
1217 	/*
1218 	 * Validate sequence number.
1219 	 */
1220 	if (!check_seq(client_data, creds.seq_num, &client_data->stale)) {
1221 		if (client_data->stale) {
1222 			ret = RPCSEC_GSS_FAILED;
1223 			RPCGSS_LOG0(1,
1224 			    "_svc_rpcsec_gss:check seq failed\n");
1225 		} else {
1226 			RPCGSS_LOG0(4, "_svc_rpcsec_gss:check seq "
1227 			    "failed on good context. Ignoring "
1228 			    "request\n");
1229 			/*
1230 			 * Operational error, drop packet silently.
1231 			 * The client will recover after timing out,
1232 			 * assuming this is a client error and not
1233 			 * a relpay attack.  Don't dispatch.
1234 			 */
1235 			ret = AUTH_OK;
1236 			*no_dispatch = TRUE;
1237 		}
1238 		goto error2;
1239 	}
1240 
1241 	/*
1242 	 * set response verifier
1243 	 */
1244 	if (!set_response_verf(rqst, msg, client_data, creds.seq_num)) {
1245 		ret = RPCSEC_GSS_FAILED;
1246 		client_data->stale = TRUE;
1247 		RPCGSS_LOG0(1,
1248 		    "_svc_rpcsec_gss:set response verifier failed\n");
1249 		goto error2;
1250 	}
1251 
1252 	/*
1253 	 * If context is locked, make sure that the client
1254 	 * has not changed the security service.
1255 	 */
1256 	if (client_data->locked &&
1257 	    client_data->raw_cred.service != creds.service) {
1258 		RPCGSS_LOG0(1, "_svc_rpcsec_gss: "
1259 		    "security service changed.\n");
1260 		ret = AUTH_FAILED;
1261 		goto error2;
1262 	}
1263 
1264 	/*
1265 	 * Set client credentials to raw credential
1266 	 * structure in context.  This is okay, since
1267 	 * this will not change during the lifetime of
1268 	 * the context (so it's MT safe).
1269 	 */
1270 	rqst->rq_clntcred = (char *)&client_data->raw_cred;
1271 
1272 	mutex_exit(&client_data->clm);
1273 	return (AUTH_OK);
1274 
1275 error2:
1276 	ASSERT(client_data->ref_cnt > 0);
1277 	client_data->ref_cnt--;
1278 	mutex_exit(&client_data->clm);
1279 	return (ret);
1280 }
1281 
1282 /*
1283  * Note we don't have a client yet to use this routine and test it.
1284  */
1285 static enum auth_stat
1286 rpcsec_gss_destroy(
1287 	struct svc_req		*rqst,
1288 	rpc_gss_creds		creds,
1289 	bool_t			*no_dispatch)
1290 {
1291 	svc_rpc_gss_data	*client_data;
1292 	int ret;
1293 
1294 	if (creds.ctx_handle.length == 0) {
1295 		RPCGSS_LOG0(1, "_svcrpcsec_gss: no ctx_handle\n");
1296 		ret = AUTH_BADCRED;
1297 		return (ret);
1298 	}
1299 	if ((client_data = get_client(&creds.ctx_handle)) == NULL) {
1300 		ret = RPCSEC_GSS_NOCRED;
1301 		RPCGSS_LOG0(1, "_svcrpcsec_gss: no security context\n");
1302 		return (ret);
1303 	}
1304 
1305 	mutex_enter(&client_data->clm);
1306 	if (!client_data->established) {
1307 		ret = AUTH_FAILED;
1308 		goto error2;
1309 	}
1310 	if (client_data->stale) {
1311 		ret = RPCSEC_GSS_NOCRED;
1312 		RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n");
1313 		goto error2;
1314 	}
1315 
1316 	(void) svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
1317 	*no_dispatch = TRUE;
1318 	ASSERT(client_data->ref_cnt > 0);
1319 	client_data->ref_cnt--;
1320 	client_data->stale = TRUE;
1321 	mutex_exit(&client_data->clm);
1322 	return (AUTH_OK);
1323 
1324 error2:
1325 	ASSERT(client_data->ref_cnt > 0);
1326 	client_data->ref_cnt--;
1327 	client_data->stale = TRUE;
1328 	mutex_exit(&client_data->clm);
1329 	return (ret);
1330 }
1331 
1332 /*
1333  * Server side authentication for RPCSEC_GSS.
1334  */
1335 enum auth_stat
1336 __svcrpcsec_gss(
1337 	struct svc_req		*rqst,
1338 	struct rpc_msg		*msg,
1339 	bool_t			*no_dispatch)
1340 {
1341 	XDR			xdrs;
1342 	rpc_gss_creds		creds;
1343 	struct opaque_auth	*cred;
1344 	int			ret;
1345 
1346 	*no_dispatch = FALSE;
1347 
1348 	/*
1349 	 * Initialize response verifier to NULL verifier.  If
1350 	 * necessary, this will be changed later.
1351 	 */
1352 	rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NONE;
1353 	rqst->rq_xprt->xp_verf.oa_base = NULL;
1354 	rqst->rq_xprt->xp_verf.oa_length = 0;
1355 
1356 	/*
1357 	 * Pull out and check credential and verifier.
1358 	 */
1359 	cred = &msg->rm_call.cb_cred;
1360 
1361 	if (cred->oa_length == 0) {
1362 		RPCGSS_LOG0(1, "_svcrpcsec_gss: zero length cred\n");
1363 		return (AUTH_BADCRED);
1364 	}
1365 
1366 	xdrmem_create(&xdrs, cred->oa_base, cred->oa_length, XDR_DECODE);
1367 	bzero((char *)&creds, sizeof (creds));
1368 	if (!__xdr_rpc_gss_creds(&xdrs, &creds)) {
1369 		XDR_DESTROY(&xdrs);
1370 		RPCGSS_LOG0(1, "_svcrpcsec_gss: can't decode creds\n");
1371 		ret = AUTH_BADCRED;
1372 		return (AUTH_BADCRED);
1373 	}
1374 	XDR_DESTROY(&xdrs);
1375 
1376 	switch (creds.gss_proc) {
1377 	case RPCSEC_GSS_INIT:
1378 		ret = rpcsec_gss_init(rqst, msg, creds, no_dispatch, NULL);
1379 		break;
1380 	case RPCSEC_GSS_CONTINUE_INIT:
1381 		ret = rpcsec_gss_continue_init(rqst, msg, creds, no_dispatch);
1382 		break;
1383 	case RPCSEC_GSS_DATA:
1384 		ret = rpcsec_gss_data(rqst, msg, creds, no_dispatch);
1385 		break;
1386 	case RPCSEC_GSS_DESTROY:
1387 		ret = rpcsec_gss_destroy(rqst, creds, no_dispatch);
1388 		break;
1389 	default:
1390 		cmn_err(CE_NOTE, "__svcrpcsec_gss: bad proc=%d",
1391 		    creds.gss_proc);
1392 		ret = AUTH_BADCRED;
1393 	}
1394 
1395 	if (creds.ctx_handle.length != 0)
1396 		xdr_free(__xdr_rpc_gss_creds, (caddr_t)&creds);
1397 	return (ret);
1398 }
1399 
1400 /*
1401  * Check verifier.  The verifier is the checksum of the RPC header
1402  * upto and including the credentials field.
1403  */
1404 
1405 /* ARGSUSED */
1406 static bool_t
1407 check_verf(struct rpc_msg *msg, gss_ctx_id_t context, int *qop_state, uid_t uid)
1408 {
1409 	int			*buf, *tmp;
1410 	char			hdr[128];
1411 	struct opaque_auth	*oa;
1412 	int			len;
1413 	gss_buffer_desc		msg_buf;
1414 	gss_buffer_desc		tok_buf;
1415 	OM_uint32		gssstat, minor_stat;
1416 
1417 	/*
1418 	 * We have to reconstruct the RPC header from the previously
1419 	 * parsed information, since we haven't kept the header intact.
1420 	 */
1421 
1422 	oa = &msg->rm_call.cb_cred;
1423 	if (oa->oa_length > MAX_AUTH_BYTES)
1424 		return (FALSE);
1425 
1426 	/* 8 XDR units from the IXDR macro calls. */
1427 	if (sizeof (hdr) < (8 * BYTES_PER_XDR_UNIT +
1428 	    RNDUP(oa->oa_length)))
1429 		return (FALSE);
1430 	buf = (int *)hdr;
1431 	IXDR_PUT_U_INT32(buf, msg->rm_xid);
1432 	IXDR_PUT_ENUM(buf, msg->rm_direction);
1433 	IXDR_PUT_U_INT32(buf, msg->rm_call.cb_rpcvers);
1434 	IXDR_PUT_U_INT32(buf, msg->rm_call.cb_prog);
1435 	IXDR_PUT_U_INT32(buf, msg->rm_call.cb_vers);
1436 	IXDR_PUT_U_INT32(buf, msg->rm_call.cb_proc);
1437 	IXDR_PUT_ENUM(buf, oa->oa_flavor);
1438 	IXDR_PUT_U_INT32(buf, oa->oa_length);
1439 	if (oa->oa_length) {
1440 		len = RNDUP(oa->oa_length);
1441 		tmp = buf;
1442 		buf += len / sizeof (int);
1443 		*(buf - 1) = 0;
1444 		(void) bcopy(oa->oa_base, (caddr_t)tmp, oa->oa_length);
1445 	}
1446 	len = ((char *)buf) - hdr;
1447 	msg_buf.length = len;
1448 	msg_buf.value = hdr;
1449 	oa = &msg->rm_call.cb_verf;
1450 	tok_buf.length = oa->oa_length;
1451 	tok_buf.value = oa->oa_base;
1452 
1453 	gssstat = kgss_verify(&minor_stat, context, &msg_buf, &tok_buf,
1454 	    qop_state);
1455 	if (gssstat != GSS_S_COMPLETE) {
1456 		RPCGSS_LOG(1, "check_verf: kgss_verify status 0x%x\n", gssstat);
1457 
1458 		RPCGSS_LOG(4, "check_verf: msg_buf length %d\n", len);
1459 		RPCGSS_LOG(4, "check_verf: msg_buf value 0x%x\n", *(int *)hdr);
1460 		RPCGSS_LOG(4, "check_verf: tok_buf length %ld\n",
1461 		    tok_buf.length);
1462 		RPCGSS_LOG(4, "check_verf: tok_buf value 0x%p\n",
1463 		    (void *)oa->oa_base);
1464 		RPCGSS_LOG(4, "check_verf: context 0x%p\n", (void *)context);
1465 
1466 		return (FALSE);
1467 	}
1468 	return (TRUE);
1469 }
1470 
1471 
1472 /*
1473  * Set response verifier.  This is the checksum of the given number.
1474  * (e.g. sequence number or sequence window)
1475  */
1476 static bool_t
1477 set_response_verf(rqst, msg, cl, num)
1478 	struct svc_req		*rqst;
1479 	struct rpc_msg		*msg;
1480 	svc_rpc_gss_data	*cl;
1481 	uint_t			num;
1482 {
1483 	OM_uint32		minor;
1484 	gss_buffer_desc		in_buf, out_buf;
1485 	uint_t			num_net;
1486 
1487 	num_net = (uint_t)htonl(num);
1488 	in_buf.length = sizeof (num);
1489 	in_buf.value = (char *)&num_net;
1490 /* XXX uid ? */
1491 
1492 	if ((kgss_sign(&minor, cl->context, cl->qop, &in_buf,
1493 				&out_buf)) != GSS_S_COMPLETE)
1494 		return (FALSE);
1495 
1496 	rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS;
1497 	rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base;
1498 	rqst->rq_xprt->xp_verf.oa_length = out_buf.length;
1499 	bcopy(out_buf.value, rqst->rq_xprt->xp_verf.oa_base, out_buf.length);
1500 	(void) gss_release_buffer(&minor, &out_buf);
1501 	return (TRUE);
1502 }
1503 
1504 /*
1505  * Create client context.
1506  */
1507 static svc_rpc_gss_data *
1508 create_client()
1509 {
1510 	svc_rpc_gss_data	*client_data;
1511 	static uint_t		key = 1;
1512 
1513 	client_data = (svc_rpc_gss_data *) kmem_cache_alloc(svc_data_handle,
1514 	    KM_SLEEP);
1515 	if (client_data == NULL)
1516 		return (NULL);
1517 
1518 	/*
1519 	 * set up client data structure
1520 	 */
1521 	client_data->next = NULL;
1522 	client_data->prev = NULL;
1523 	client_data->lru_next = NULL;
1524 	client_data->lru_prev = NULL;
1525 	client_data->client_name.length = 0;
1526 	client_data->client_name.value = NULL;
1527 	client_data->seq_num = 0;
1528 	bzero(client_data->seq_bits, sizeof (client_data->seq_bits));
1529 	client_data->key = 0;
1530 	client_data->cookie = NULL;
1531 	bzero(&client_data->u_cred, sizeof (client_data->u_cred));
1532 	client_data->established = FALSE;
1533 	client_data->locked = FALSE;
1534 	client_data->u_cred_set = 0;
1535 	client_data->context = GSS_C_NO_CONTEXT;
1536 	client_data->expiration = GSS_C_INDEFINITE;
1537 	client_data->deleg = GSS_C_NO_CREDENTIAL;
1538 	client_data->ref_cnt = 1;
1539 	client_data->last_ref_time = gethrestime_sec();
1540 	client_data->qop = GSS_C_QOP_DEFAULT;
1541 	client_data->done_docallback = FALSE;
1542 	client_data->stale = FALSE;
1543 	client_data->retrans_data = NULL;
1544 	bzero(&client_data->raw_cred, sizeof (client_data->raw_cred));
1545 
1546 	/*
1547 	 * The client context handle is a 32-bit key (unsigned int).
1548 	 * The key is incremented until there is no duplicate for it.
1549 	 */
1550 
1551 	svc_rpc_gss_cache_stats.total_entries_allocated++;
1552 	mutex_enter(&ctx_mutex);
1553 	for (;;) {
1554 		client_data->key = key++;
1555 		if (find_client(client_data->key) == NULL) {
1556 			insert_client(client_data);
1557 			mutex_exit(&ctx_mutex);
1558 			return (client_data);
1559 		}
1560 	}
1561 	/*NOTREACHED*/
1562 }
1563 
1564 /*
1565  * Insert client context into hash list and LRU list.
1566  */
1567 static void
1568 insert_client(client_data)
1569 	svc_rpc_gss_data	*client_data;
1570 {
1571 	svc_rpc_gss_data	*cl;
1572 	int			index = HASH(client_data->key);
1573 
1574 	ASSERT(mutex_owned(&ctx_mutex));
1575 
1576 	client_data->prev = NULL;
1577 	cl = clients[index];
1578 	if ((client_data->next = cl) != NULL)
1579 		cl->prev = client_data;
1580 	clients[index] = client_data;
1581 
1582 	client_data->lru_prev = NULL;
1583 	if ((client_data->lru_next = lru_first) != NULL)
1584 		lru_first->lru_prev = client_data;
1585 	else
1586 		lru_last = client_data;
1587 	lru_first = client_data;
1588 
1589 	num_gss_contexts++;
1590 }
1591 
1592 /*
1593  * Fetch a client, given the client context handle.  Move it to the
1594  * top of the LRU list since this is the most recently used context.
1595  */
1596 static svc_rpc_gss_data *
1597 get_client(ctx_handle)
1598 	gss_buffer_t		ctx_handle;
1599 {
1600 	uint_t			key = *(uint_t *)ctx_handle->value;
1601 	svc_rpc_gss_data	*cl;
1602 
1603 	mutex_enter(&ctx_mutex);
1604 	if ((cl = find_client(key)) != NULL) {
1605 		mutex_enter(&cl->clm);
1606 		if (cl->stale) {
1607 			if (cl->ref_cnt == 0) {
1608 				mutex_exit(&cl->clm);
1609 				destroy_client(cl);
1610 			} else {
1611 				mutex_exit(&cl->clm);
1612 			}
1613 			mutex_exit(&ctx_mutex);
1614 			return (NULL);
1615 		}
1616 		cl->ref_cnt++;
1617 		cl->last_ref_time = gethrestime_sec();
1618 		mutex_exit(&cl->clm);
1619 		if (cl != lru_first) {
1620 			cl->lru_prev->lru_next = cl->lru_next;
1621 			if (cl->lru_next != NULL)
1622 				cl->lru_next->lru_prev = cl->lru_prev;
1623 			else
1624 				lru_last = cl->lru_prev;
1625 			cl->lru_prev = NULL;
1626 			cl->lru_next = lru_first;
1627 			lru_first->lru_prev = cl;
1628 			lru_first = cl;
1629 		}
1630 	}
1631 	mutex_exit(&ctx_mutex);
1632 	return (cl);
1633 }
1634 
1635 /*
1636  * Given the client context handle, find the context corresponding to it.
1637  * Don't change its LRU state since it may not be used.
1638  */
1639 static svc_rpc_gss_data *
1640 find_client(key)
1641 	uint_t			key;
1642 {
1643 	int			index = HASH(key);
1644 	svc_rpc_gss_data	*cl = NULL;
1645 
1646 	ASSERT(mutex_owned(&ctx_mutex));
1647 
1648 	for (cl = clients[index]; cl != NULL; cl = cl->next) {
1649 		if (cl->key == key)
1650 			break;
1651 	}
1652 	return (cl);
1653 }
1654 
1655 /*
1656  * Destroy a client context.
1657  */
1658 static void
1659 destroy_client(client_data)
1660 	svc_rpc_gss_data	*client_data;
1661 {
1662 	OM_uint32		minor;
1663 	int			index = HASH(client_data->key);
1664 
1665 	ASSERT(mutex_owned(&ctx_mutex));
1666 
1667 	/*
1668 	 * remove from hash list
1669 	 */
1670 	if (client_data->prev == NULL)
1671 		clients[index] = client_data->next;
1672 	else
1673 		client_data->prev->next = client_data->next;
1674 	if (client_data->next != NULL)
1675 		client_data->next->prev = client_data->prev;
1676 
1677 	/*
1678 	 * remove from LRU list
1679 	 */
1680 	if (client_data->lru_prev == NULL)
1681 		lru_first = client_data->lru_next;
1682 	else
1683 		client_data->lru_prev->lru_next = client_data->lru_next;
1684 	if (client_data->lru_next != NULL)
1685 		client_data->lru_next->lru_prev = client_data->lru_prev;
1686 	else
1687 		lru_last = client_data->lru_prev;
1688 
1689 	/*
1690 	 * If there is a GSS context, clean up GSS state.
1691 	 */
1692 	if (client_data->context != GSS_C_NO_CONTEXT) {
1693 		(void) kgss_delete_sec_context(&minor, &client_data->context,
1694 					NULL);
1695 
1696 		common_client_data_free(client_data);
1697 
1698 		if (client_data->deleg != GSS_C_NO_CREDENTIAL) {
1699 		    (void) kgss_release_cred(&minor, &client_data->deleg,
1700 				crgetuid(CRED()));
1701 		}
1702 	}
1703 
1704 	if (client_data->u_cred.gidlist != NULL) {
1705 	    kmem_free((char *)client_data->u_cred.gidlist,
1706 			client_data->u_cred.gidlen * sizeof (gid_t));
1707 	    client_data->u_cred.gidlist = NULL;
1708 	}
1709 	if (client_data->retrans_data != NULL)
1710 		retrans_del(client_data);
1711 
1712 	kmem_cache_free(svc_data_handle, client_data);
1713 	num_gss_contexts--;
1714 }
1715 
1716 /*
1717  * Check for expired and stale client contexts.
1718  */
1719 static void
1720 sweep_clients(bool_t from_reclaim)
1721 {
1722 	svc_rpc_gss_data	*cl, *next;
1723 	time_t			last_reference_needed;
1724 	time_t			now = gethrestime_sec();
1725 
1726 	ASSERT(mutex_owned(&ctx_mutex));
1727 
1728 	last_reference_needed = now - (from_reclaim ?
1729 	    svc_rpc_gss_active_delta : svc_rpc_gss_inactive_delta);
1730 
1731 	cl = lru_last;
1732 	while (cl) {
1733 		/*
1734 		 * We assume here that any manipulation of the LRU pointers
1735 		 * and hash bucket pointers are only done when holding the
1736 		 * ctx_mutex.
1737 		 */
1738 		next = cl->lru_prev;
1739 
1740 		mutex_enter(&cl->clm);
1741 
1742 		if ((cl->expiration != GSS_C_INDEFINITE &&
1743 		    cl->expiration <= now) || cl->stale ||
1744 		    cl->last_ref_time <= last_reference_needed) {
1745 
1746 			if ((cl->expiration != GSS_C_INDEFINITE &&
1747 			    cl->expiration <= now) || cl->stale ||
1748 			    (cl->last_ref_time <= last_reference_needed &&
1749 			    cl->ref_cnt == 0)) {
1750 
1751 				cl->stale = TRUE;
1752 
1753 				if (cl->ref_cnt == 0) {
1754 					mutex_exit(&cl->clm);
1755 					if (from_reclaim)
1756 						svc_rpc_gss_cache_stats.
1757 						    no_returned_by_reclaim++;
1758 					destroy_client(cl);
1759 				} else
1760 					mutex_exit(&cl->clm);
1761 			} else
1762 				mutex_exit(&cl->clm);
1763 		} else
1764 			mutex_exit(&cl->clm);
1765 
1766 		cl = next;
1767 	}
1768 
1769 	last_swept = gethrestime_sec();
1770 }
1771 
1772 /*
1773  * Encrypt the serialized arguments from xdr_func applied to xdr_ptr
1774  * and write the result to xdrs.
1775  */
1776 static bool_t
1777 svc_rpc_gss_wrap(auth, out_xdrs, xdr_func, xdr_ptr)
1778 	SVCAUTH			*auth;
1779 	XDR			*out_xdrs;
1780 	bool_t			(*xdr_func)();
1781 	caddr_t			xdr_ptr;
1782 {
1783 	svc_rpc_gss_parms_t	*gss_parms = SVCAUTH_GSSPARMS(auth);
1784 	bool_t ret;
1785 
1786 	/*
1787 	 * If context is not established, or if neither integrity nor
1788 	 * privacy service is used, don't wrap - just XDR encode.
1789 	 * Otherwise, wrap data using service and QOP parameters.
1790 	 */
1791 	if (!gss_parms->established ||
1792 				gss_parms->service == rpc_gss_svc_none)
1793 		return ((*xdr_func)(out_xdrs, xdr_ptr));
1794 
1795 	ret = __rpc_gss_wrap_data(gss_parms->service,
1796 				(OM_uint32)gss_parms->qop_rcvd,
1797 				(gss_ctx_id_t)gss_parms->context,
1798 				gss_parms->seq_num,
1799 				out_xdrs, xdr_func, xdr_ptr);
1800 	return (ret);
1801 }
1802 
1803 /*
1804  * Decrypt the serialized arguments and XDR decode them.
1805  */
1806 static bool_t
1807 svc_rpc_gss_unwrap(auth, in_xdrs, xdr_func, xdr_ptr)
1808 	SVCAUTH			*auth;
1809 	XDR			*in_xdrs;
1810 	bool_t			(*xdr_func)();
1811 	caddr_t			xdr_ptr;
1812 {
1813 	svc_rpc_gss_parms_t	*gss_parms = SVCAUTH_GSSPARMS(auth);
1814 
1815 	/*
1816 	 * If context is not established, or if neither integrity nor
1817 	 * privacy service is used, don't unwrap - just XDR decode.
1818 	 * Otherwise, unwrap data.
1819 	 */
1820 	if (!gss_parms->established ||
1821 				gss_parms->service == rpc_gss_svc_none)
1822 		return ((*xdr_func)(in_xdrs, xdr_ptr));
1823 
1824 	return (__rpc_gss_unwrap_data(gss_parms->service,
1825 				(gss_ctx_id_t)gss_parms->context,
1826 				gss_parms->seq_num,
1827 				gss_parms->qop_rcvd,
1828 				in_xdrs, xdr_func, xdr_ptr));
1829 }
1830 
1831 
1832 /* ARGSUSED */
1833 int
1834 rpc_gss_svc_max_data_length(struct svc_req *req, int max_tp_unit_len)
1835 {
1836 	return (0);
1837 }
1838 
1839 /*
1840  * Add retransmit entry to the context cache entry for a new xid.
1841  * If there is already an entry, delete it before adding the new one.
1842  */
1843 static void retrans_add(client, xid, result)
1844 	svc_rpc_gss_data *client;
1845 	uint32_t	xid;
1846 	rpc_gss_init_res *result;
1847 {
1848 	retrans_entry	*rdata;
1849 
1850 	if (client->retrans_data && client->retrans_data->xid == xid)
1851 		return;
1852 
1853 	rdata = kmem_zalloc(sizeof (*rdata), KM_SLEEP);
1854 
1855 	if (rdata == NULL)
1856 		return;
1857 
1858 	rdata->xid = xid;
1859 	rdata->result = *result;
1860 
1861 	if (result->token.length != 0) {
1862 		GSS_DUP_BUFFER(rdata->result.token, result->token);
1863 	}
1864 
1865 	if (client->retrans_data)
1866 		retrans_del(client);
1867 
1868 	client->retrans_data = rdata;
1869 }
1870 
1871 /*
1872  * Delete the retransmit data from the context cache entry.
1873  */
1874 static void retrans_del(client)
1875 	svc_rpc_gss_data *client;
1876 {
1877 	retrans_entry *rdata;
1878 	OM_uint32 minor_stat;
1879 
1880 	if (client->retrans_data == NULL)
1881 		return;
1882 
1883 	rdata = client->retrans_data;
1884 	if (rdata->result.token.length != 0) {
1885 	    (void) gss_release_buffer(&minor_stat, &rdata->result.token);
1886 	}
1887 
1888 	kmem_free((caddr_t)rdata, sizeof (*rdata));
1889 	client->retrans_data = NULL;
1890 }
1891 
1892 /*
1893  * This function frees the following fields of svc_rpc_gss_data:
1894  *	client_name, raw_cred.client_principal, raw_cred.mechanism.
1895  */
1896 static void
1897 common_client_data_free(svc_rpc_gss_data *client_data)
1898 {
1899 	if (client_data->client_name.length > 0) {
1900 		(void) gss_release_buffer(NULL, &client_data->client_name);
1901 	}
1902 
1903 	if (client_data->raw_cred.client_principal) {
1904 		kmem_free((caddr_t)client_data->raw_cred.client_principal,
1905 		    client_data->raw_cred.client_principal->len +
1906 		    sizeof (int));
1907 		client_data->raw_cred.client_principal = NULL;
1908 	}
1909 
1910 	/*
1911 	 * In the user GSS-API library, mechanism (mech_type returned
1912 	 * by gss_accept_sec_context) is static storage, however
1913 	 * since all the work is done for gss_accept_sec_context under
1914 	 * gssd, what is returned in the kernel, is a copy from the oid
1915 	 * obtained under from gssd, so need to free it when destroying
1916 	 * the client data.
1917 	 */
1918 
1919 	if (client_data->raw_cred.mechanism) {
1920 		kgss_free_oid(client_data->raw_cred.mechanism);
1921 		client_data->raw_cred.mechanism = NULL;
1922 	}
1923 }
1924