10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55302Sth199096 * Common Development and Distribution License (the "License").
65302Sth199096 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12190SP.Kumar@Sun.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #include <sys/param.h>
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/systm.h>
280Sstevel@tonic-gate #include <sys/cred.h>
290Sstevel@tonic-gate #include <sys/proc.h>
300Sstevel@tonic-gate #include <sys/user.h>
310Sstevel@tonic-gate #include <sys/time.h>
320Sstevel@tonic-gate #include <sys/buf.h>
330Sstevel@tonic-gate #include <sys/vfs.h>
340Sstevel@tonic-gate #include <sys/vnode.h>
350Sstevel@tonic-gate #include <sys/socket.h>
360Sstevel@tonic-gate #include <sys/stat.h>
370Sstevel@tonic-gate #include <sys/uio.h>
380Sstevel@tonic-gate #include <sys/tiuser.h>
390Sstevel@tonic-gate #include <sys/swap.h>
400Sstevel@tonic-gate #include <sys/errno.h>
410Sstevel@tonic-gate #include <sys/debug.h>
420Sstevel@tonic-gate #include <sys/kmem.h>
430Sstevel@tonic-gate #include <sys/kstat.h>
440Sstevel@tonic-gate #include <sys/cmn_err.h>
450Sstevel@tonic-gate #include <sys/vtrace.h>
460Sstevel@tonic-gate #include <sys/session.h>
470Sstevel@tonic-gate #include <sys/dnlc.h>
480Sstevel@tonic-gate #include <sys/bitmap.h>
490Sstevel@tonic-gate #include <sys/thread.h>
500Sstevel@tonic-gate #include <sys/policy.h>
510Sstevel@tonic-gate
520Sstevel@tonic-gate #include <netinet/in.h>
530Sstevel@tonic-gate #include <rpc/types.h>
540Sstevel@tonic-gate #include <rpc/xdr.h>
550Sstevel@tonic-gate #include <rpc/auth.h>
560Sstevel@tonic-gate #include <rpc/auth_des.h> /* for authdes_create() */
570Sstevel@tonic-gate #include <rpc/clnt.h>
580Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
590Sstevel@tonic-gate
600Sstevel@tonic-gate #define MAXCLIENTS 16
61*12190SP.Kumar@Sun.COM
62*12190SP.Kumar@Sun.COM /*
63*12190SP.Kumar@Sun.COM * Currently there is no maximum length defined withing the gss
64*12190SP.Kumar@Sun.COM * specification. Because of security issues the maximum gss
65*12190SP.Kumar@Sun.COM * authentication length is checked to be under the MAXAUTHLEN
66*12190SP.Kumar@Sun.COM * defined below. The value was chosen because it will be a safe
67*12190SP.Kumar@Sun.COM * maximum value for some time. Currently lengths are generally
68*12190SP.Kumar@Sun.COM * under the 16 byte length
69*12190SP.Kumar@Sun.COM */
70*12190SP.Kumar@Sun.COM #define MINAUTHLEN 1 /* minimum gss authentication length */
71*12190SP.Kumar@Sun.COM #define MAXAUTHLEN 65535 /* maximum gss authentication length */
720Sstevel@tonic-gate static int clnt_authdes_cachesz = 64;
730Sstevel@tonic-gate
740Sstevel@tonic-gate static uint_t authdes_win = 5*60; /* 5 minutes -- should be mount option */
750Sstevel@tonic-gate
760Sstevel@tonic-gate struct kmem_cache *authkern_cache;
770Sstevel@tonic-gate
788637SVallish.Vaidyeshwara@Sun.COM struct kmem_cache *authnone_cache;
798637SVallish.Vaidyeshwara@Sun.COM
800Sstevel@tonic-gate struct kmem_cache *authloopback_cache;
810Sstevel@tonic-gate
820Sstevel@tonic-gate static struct desauthent {
830Sstevel@tonic-gate struct sec_data *da_data;
840Sstevel@tonic-gate uid_t da_uid;
850Sstevel@tonic-gate zoneid_t da_zoneid;
860Sstevel@tonic-gate short da_inuse;
870Sstevel@tonic-gate AUTH *da_auth;
880Sstevel@tonic-gate } *desauthtab;
890Sstevel@tonic-gate static int nextdesvictim;
900Sstevel@tonic-gate static kmutex_t desauthtab_lock; /* Lock to protect DES auth cache */
910Sstevel@tonic-gate
920Sstevel@tonic-gate /* RPC stuff */
930Sstevel@tonic-gate kmutex_t authdes_ops_lock; /* auth_ops initialization in authdes_ops() */
940Sstevel@tonic-gate
950Sstevel@tonic-gate static void purge_authtab(struct sec_data *);
960Sstevel@tonic-gate
970Sstevel@tonic-gate /* Zone stuff */
980Sstevel@tonic-gate zone_key_t auth_zone_key;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate * Load RPCSEC_GSS specific data from user space to kernel space.
1020Sstevel@tonic-gate */
1030Sstevel@tonic-gate /*ARGSUSED*/
1040Sstevel@tonic-gate static int
gss_clnt_loadinfo(caddr_t usrdata,caddr_t * kdata,model_t model)1050Sstevel@tonic-gate gss_clnt_loadinfo(caddr_t usrdata, caddr_t *kdata, model_t model)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate struct gss_clnt_data *data;
1080Sstevel@tonic-gate caddr_t elements;
1090Sstevel@tonic-gate int error = 0;
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate /* map opaque data to gss specific structure */
1120Sstevel@tonic-gate data = kmem_alloc(sizeof (*data), KM_SLEEP);
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1150Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
1160Sstevel@tonic-gate struct gss_clnt_data32 gd32;
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate if (copyin(usrdata, &gd32, sizeof (gd32)) == -1) {
1190Sstevel@tonic-gate error = EFAULT;
1200Sstevel@tonic-gate } else {
1210Sstevel@tonic-gate data->mechanism.length = gd32.mechanism.length;
1220Sstevel@tonic-gate data->mechanism.elements =
1235302Sth199096 (caddr_t)(uintptr_t)gd32.mechanism.elements;
1240Sstevel@tonic-gate data->service = gd32.service;
1250Sstevel@tonic-gate bcopy(gd32.uname, data->uname, sizeof (gd32.uname));
1260Sstevel@tonic-gate bcopy(gd32.inst, data->inst, sizeof (gd32.inst));
1270Sstevel@tonic-gate bcopy(gd32.realm, data->realm, sizeof (gd32.realm));
1280Sstevel@tonic-gate data->qop = gd32.qop;
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate } else
1310Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
1320Sstevel@tonic-gate if (copyin(usrdata, data, sizeof (*data)))
1330Sstevel@tonic-gate error = EFAULT;
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate if (error == 0) {
136*12190SP.Kumar@Sun.COM if (data->mechanism.length >= MINAUTHLEN &&
137*12190SP.Kumar@Sun.COM data->mechanism.length <= MAXAUTHLEN) {
1380Sstevel@tonic-gate elements = kmem_alloc(data->mechanism.length, KM_SLEEP);
1390Sstevel@tonic-gate if (!(copyin(data->mechanism.elements, elements,
1400Sstevel@tonic-gate data->mechanism.length))) {
1410Sstevel@tonic-gate data->mechanism.elements = elements;
1420Sstevel@tonic-gate *kdata = (caddr_t)data;
1430Sstevel@tonic-gate return (0);
144*12190SP.Kumar@Sun.COM }
145*12190SP.Kumar@Sun.COM kmem_free(elements, data->mechanism.length);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate }
148*12190SP.Kumar@Sun.COM *kdata = NULL;
149*12190SP.Kumar@Sun.COM kmem_free(data, sizeof (*data));
150*12190SP.Kumar@Sun.COM
1510Sstevel@tonic-gate return (EFAULT);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate /*
1560Sstevel@tonic-gate * Load AUTH_DES specific data from user space to kernel space.
1570Sstevel@tonic-gate */
1580Sstevel@tonic-gate /*ARGSUSED2*/
1590Sstevel@tonic-gate int
dh_k4_clnt_loadinfo(caddr_t usrdata,caddr_t * kdata,model_t model)1600Sstevel@tonic-gate dh_k4_clnt_loadinfo(caddr_t usrdata, caddr_t *kdata, model_t model)
1610Sstevel@tonic-gate {
1620Sstevel@tonic-gate size_t nlen;
1630Sstevel@tonic-gate int error = 0;
1640Sstevel@tonic-gate char *userbufptr;
1650Sstevel@tonic-gate dh_k4_clntdata_t *data;
1660Sstevel@tonic-gate char netname[MAXNETNAMELEN+1];
1670Sstevel@tonic-gate struct netbuf *syncaddr;
1680Sstevel@tonic-gate struct knetconfig *knconf;
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate /* map opaque data to des specific strucutre */
1710Sstevel@tonic-gate data = kmem_alloc(sizeof (*data), KM_SLEEP);
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1740Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
1750Sstevel@tonic-gate struct des_clnt_data32 data32;
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate if (copyin(usrdata, &data32, sizeof (data32)) == -1) {
1780Sstevel@tonic-gate error = EFAULT;
1790Sstevel@tonic-gate } else {
1800Sstevel@tonic-gate data->syncaddr.maxlen = data32.syncaddr.maxlen;
1810Sstevel@tonic-gate data->syncaddr.len = data32.syncaddr.len;
1820Sstevel@tonic-gate data->syncaddr.buf =
1830Sstevel@tonic-gate (caddr_t)(uintptr_t)data32.syncaddr.buf;
1840Sstevel@tonic-gate data->knconf =
1850Sstevel@tonic-gate (struct knetconfig *)(uintptr_t)data32.knconf;
1860Sstevel@tonic-gate data->netname = (caddr_t)(uintptr_t)data32.netname;
1870Sstevel@tonic-gate data->netnamelen = data32.netnamelen;
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate } else
1900Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
1910Sstevel@tonic-gate if (copyin(usrdata, data, sizeof (*data)))
1920Sstevel@tonic-gate error = EFAULT;
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate if (error == 0) {
1950Sstevel@tonic-gate syncaddr = &data->syncaddr;
196*12190SP.Kumar@Sun.COM if (syncaddr->len < MINAUTHLEN || syncaddr->len > MAXAUTHLEN)
1970Sstevel@tonic-gate error = EINVAL;
1980Sstevel@tonic-gate else {
1990Sstevel@tonic-gate userbufptr = syncaddr->buf;
200*12190SP.Kumar@Sun.COM syncaddr->buf = kmem_alloc(syncaddr->len, KM_SLEEP);
2010Sstevel@tonic-gate syncaddr->maxlen = syncaddr->len;
2020Sstevel@tonic-gate if (copyin(userbufptr, syncaddr->buf, syncaddr->len)) {
2030Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2040Sstevel@tonic-gate syncaddr->buf = NULL;
2050Sstevel@tonic-gate error = EFAULT;
2060Sstevel@tonic-gate } else {
2070Sstevel@tonic-gate (void) copyinstr(data->netname, netname,
2080Sstevel@tonic-gate sizeof (netname), &nlen);
2090Sstevel@tonic-gate if (nlen != 0) {
2100Sstevel@tonic-gate data->netname =
2110Sstevel@tonic-gate kmem_alloc(nlen, KM_SLEEP);
2120Sstevel@tonic-gate bcopy(netname, data->netname, nlen);
2130Sstevel@tonic-gate data->netnamelen = (int)nlen;
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate if (!error) {
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate * Allocate space for a knetconfig structure and
2220Sstevel@tonic-gate * its strings and copy in from user-land.
2230Sstevel@tonic-gate */
2240Sstevel@tonic-gate knconf = kmem_alloc(sizeof (*knconf), KM_SLEEP);
2250Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
2260Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
2270Sstevel@tonic-gate struct knetconfig32 knconf32;
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate if (copyin(data->knconf, &knconf32,
2300Sstevel@tonic-gate sizeof (knconf32)) == -1) {
2310Sstevel@tonic-gate kmem_free(knconf, sizeof (*knconf));
2320Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2330Sstevel@tonic-gate syncaddr->buf = NULL;
2340Sstevel@tonic-gate kmem_free(data->netname, nlen);
2350Sstevel@tonic-gate error = EFAULT;
2360Sstevel@tonic-gate } else {
2370Sstevel@tonic-gate knconf->knc_semantics = knconf32.knc_semantics;
2380Sstevel@tonic-gate knconf->knc_protofmly =
2390Sstevel@tonic-gate (caddr_t)(uintptr_t)knconf32.knc_protofmly;
2400Sstevel@tonic-gate knconf->knc_proto =
2410Sstevel@tonic-gate (caddr_t)(uintptr_t)knconf32.knc_proto;
2420Sstevel@tonic-gate knconf->knc_rdev = expldev(knconf32.knc_rdev);
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate } else
2450Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
2460Sstevel@tonic-gate if (copyin(data->knconf, knconf, sizeof (*knconf))) {
2470Sstevel@tonic-gate kmem_free(knconf, sizeof (*knconf));
2480Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2490Sstevel@tonic-gate syncaddr->buf = NULL;
2500Sstevel@tonic-gate kmem_free(data->netname, nlen);
2510Sstevel@tonic-gate error = EFAULT;
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate if (!error) {
2560Sstevel@tonic-gate size_t nmoved_tmp;
2570Sstevel@tonic-gate char *p, *pf;
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate pf = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
2600Sstevel@tonic-gate p = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
2610Sstevel@tonic-gate error = copyinstr(knconf->knc_protofmly, pf,
2620Sstevel@tonic-gate KNC_STRSIZE, &nmoved_tmp);
2630Sstevel@tonic-gate if (error) {
2640Sstevel@tonic-gate kmem_free(pf, KNC_STRSIZE);
2650Sstevel@tonic-gate kmem_free(p, KNC_STRSIZE);
2660Sstevel@tonic-gate kmem_free(knconf, sizeof (*knconf));
2670Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2680Sstevel@tonic-gate kmem_free(data->netname, nlen);
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate if (!error) {
2720Sstevel@tonic-gate error = copyinstr(knconf->knc_proto,
2730Sstevel@tonic-gate p, KNC_STRSIZE, &nmoved_tmp);
2740Sstevel@tonic-gate if (error) {
2750Sstevel@tonic-gate kmem_free(pf, KNC_STRSIZE);
2760Sstevel@tonic-gate kmem_free(p, KNC_STRSIZE);
2770Sstevel@tonic-gate kmem_free(knconf, sizeof (*knconf));
2780Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2790Sstevel@tonic-gate kmem_free(data->netname, nlen);
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate if (!error) {
2840Sstevel@tonic-gate knconf->knc_protofmly = pf;
2850Sstevel@tonic-gate knconf->knc_proto = p;
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate if (error) {
2900Sstevel@tonic-gate *kdata = NULL;
2910Sstevel@tonic-gate kmem_free(data, sizeof (*data));
2920Sstevel@tonic-gate return (error);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate data->knconf = knconf;
2960Sstevel@tonic-gate *kdata = (caddr_t)data;
2970Sstevel@tonic-gate return (0);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate /*
3010Sstevel@tonic-gate * Free up AUTH_DES specific data.
3020Sstevel@tonic-gate */
3030Sstevel@tonic-gate void
dh_k4_clnt_freeinfo(caddr_t cdata)3040Sstevel@tonic-gate dh_k4_clnt_freeinfo(caddr_t cdata)
3050Sstevel@tonic-gate {
3060Sstevel@tonic-gate dh_k4_clntdata_t *data;
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate data = (dh_k4_clntdata_t *)cdata;
3090Sstevel@tonic-gate if (data->netnamelen > 0) {
3100Sstevel@tonic-gate kmem_free(data->netname, data->netnamelen);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate if (data->syncaddr.buf != NULL) {
3130Sstevel@tonic-gate kmem_free(data->syncaddr.buf, data->syncaddr.len);
3140Sstevel@tonic-gate }
3150Sstevel@tonic-gate if (data->knconf != NULL) {
3160Sstevel@tonic-gate kmem_free(data->knconf->knc_protofmly, KNC_STRSIZE);
3170Sstevel@tonic-gate kmem_free(data->knconf->knc_proto, KNC_STRSIZE);
3180Sstevel@tonic-gate kmem_free(data->knconf, sizeof (*data->knconf));
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate kmem_free(data, sizeof (*data));
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate * Load application auth related data from user land to kernel.
3260Sstevel@tonic-gate * Map opaque data field to dh_k4_clntdata_t for AUTH_DES
3270Sstevel@tonic-gate *
3280Sstevel@tonic-gate */
3290Sstevel@tonic-gate int
sec_clnt_loadinfo(struct sec_data * in,struct sec_data ** out,model_t model)3300Sstevel@tonic-gate sec_clnt_loadinfo(struct sec_data *in, struct sec_data **out, model_t model)
3310Sstevel@tonic-gate {
3320Sstevel@tonic-gate struct sec_data *secdata;
3330Sstevel@tonic-gate int error = 0;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate secdata = kmem_alloc(sizeof (*secdata), KM_SLEEP);
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
3380Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
3390Sstevel@tonic-gate struct sec_data32 sd32;
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate if (copyin(in, &sd32, sizeof (sd32)) == -1) {
3420Sstevel@tonic-gate error = EFAULT;
3430Sstevel@tonic-gate } else {
3440Sstevel@tonic-gate secdata->secmod = sd32.secmod;
3450Sstevel@tonic-gate secdata->rpcflavor = sd32.rpcflavor;
3460Sstevel@tonic-gate secdata->uid = sd32.uid;
3470Sstevel@tonic-gate secdata->flags = sd32.flags;
3480Sstevel@tonic-gate secdata->data = (caddr_t)(uintptr_t)sd32.data;
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate } else
3510Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate if (copyin(in, secdata, sizeof (*secdata)) == -1) {
3540Sstevel@tonic-gate error = EFAULT;
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate /*
3570Sstevel@tonic-gate * Copy in opaque data field per flavor.
3580Sstevel@tonic-gate */
3590Sstevel@tonic-gate if (!error) {
3600Sstevel@tonic-gate switch (secdata->rpcflavor) {
3610Sstevel@tonic-gate case AUTH_NONE:
3620Sstevel@tonic-gate case AUTH_UNIX:
3630Sstevel@tonic-gate case AUTH_LOOPBACK:
3640Sstevel@tonic-gate break;
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate case AUTH_DES:
3670Sstevel@tonic-gate error = dh_k4_clnt_loadinfo(secdata->data,
3680Sstevel@tonic-gate &secdata->data, model);
3690Sstevel@tonic-gate break;
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate case RPCSEC_GSS:
3720Sstevel@tonic-gate error = gss_clnt_loadinfo(secdata->data,
3730Sstevel@tonic-gate &secdata->data, model);
3740Sstevel@tonic-gate break;
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate default:
3770Sstevel@tonic-gate error = EINVAL;
3780Sstevel@tonic-gate break;
3790Sstevel@tonic-gate }
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate if (!error) {
3830Sstevel@tonic-gate *out = secdata;
3840Sstevel@tonic-gate } else {
3850Sstevel@tonic-gate kmem_free(secdata, sizeof (*secdata));
3860Sstevel@tonic-gate *out = (struct sec_data *)NULL;
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate return (error);
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate /*
3930Sstevel@tonic-gate * Null the sec_data index in the cache table, and
3940Sstevel@tonic-gate * free the memory allocated by sec_clnt_loadinfo.
3950Sstevel@tonic-gate */
3960Sstevel@tonic-gate void
sec_clnt_freeinfo(struct sec_data * secdata)3970Sstevel@tonic-gate sec_clnt_freeinfo(struct sec_data *secdata)
3980Sstevel@tonic-gate {
3990Sstevel@tonic-gate switch (secdata->rpcflavor) {
4000Sstevel@tonic-gate case AUTH_DES:
4010Sstevel@tonic-gate purge_authtab(secdata);
4020Sstevel@tonic-gate if (secdata->data)
4030Sstevel@tonic-gate dh_k4_clnt_freeinfo(secdata->data);
4040Sstevel@tonic-gate break;
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate case RPCSEC_GSS:
4070Sstevel@tonic-gate rpc_gss_secpurge((void *)secdata);
4080Sstevel@tonic-gate if (secdata->data) {
4090Sstevel@tonic-gate gss_clntdata_t *gss_data;
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate gss_data = (gss_clntdata_t *)secdata->data;
4120Sstevel@tonic-gate if (gss_data->mechanism.elements) {
4130Sstevel@tonic-gate kmem_free(gss_data->mechanism.elements,
4140Sstevel@tonic-gate gss_data->mechanism.length);
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate kmem_free(secdata->data, sizeof (gss_clntdata_t));
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate break;
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate case AUTH_NONE:
4210Sstevel@tonic-gate case AUTH_UNIX:
4220Sstevel@tonic-gate case AUTH_LOOPBACK:
4230Sstevel@tonic-gate default:
4240Sstevel@tonic-gate break;
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate kmem_free(secdata, sizeof (*secdata));
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate /*
4300Sstevel@tonic-gate * Get an AUTH handle for a RPC client based on the given sec_data.
4310Sstevel@tonic-gate * If an AUTH handle exists for the same sec_data, use that AUTH handle,
4320Sstevel@tonic-gate * otherwise create a new one.
4330Sstevel@tonic-gate */
4340Sstevel@tonic-gate int
sec_clnt_geth(CLIENT * client,struct sec_data * secdata,cred_t * cr,AUTH ** ap)4350Sstevel@tonic-gate sec_clnt_geth(CLIENT *client, struct sec_data *secdata, cred_t *cr, AUTH **ap)
4360Sstevel@tonic-gate {
4370Sstevel@tonic-gate int i;
4380Sstevel@tonic-gate struct desauthent *da;
4390Sstevel@tonic-gate int authflavor;
4400Sstevel@tonic-gate cred_t *savecred;
4410Sstevel@tonic-gate int stat; /* return (errno) status */
4420Sstevel@tonic-gate char gss_svc_name[MAX_GSS_NAME];
4430Sstevel@tonic-gate dh_k4_clntdata_t *desdata;
4440Sstevel@tonic-gate AUTH *auth;
4450Sstevel@tonic-gate gss_clntdata_t *gssdata;
4460Sstevel@tonic-gate zoneid_t zoneid = getzoneid();
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate if ((client == NULL) || (secdata == NULL) || (ap == NULL))
4490Sstevel@tonic-gate return (EINVAL);
4500Sstevel@tonic-gate *ap = (AUTH *)NULL;
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate authflavor = secdata->rpcflavor;
4530Sstevel@tonic-gate for (;;) {
4545302Sth199096 int nlen;
4555302Sth199096 char *netname;
4565302Sth199096
4570Sstevel@tonic-gate switch (authflavor) {
4580Sstevel@tonic-gate case AUTH_NONE:
4598637SVallish.Vaidyeshwara@Sun.COM *ap = (AUTH *) authnone_create();
4608637SVallish.Vaidyeshwara@Sun.COM return ((*ap != NULL) ? 0 : EINTR);
4618637SVallish.Vaidyeshwara@Sun.COM
4620Sstevel@tonic-gate case AUTH_UNIX:
4630Sstevel@tonic-gate *ap = (AUTH *) authkern_create();
4640Sstevel@tonic-gate return ((*ap != NULL) ? 0 : EINTR);
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate case AUTH_LOOPBACK:
4670Sstevel@tonic-gate *ap = (AUTH *) authloopback_create();
4680Sstevel@tonic-gate return ((*ap != NULL) ? 0 : EINTR);
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate case AUTH_DES:
4710Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
4720Sstevel@tonic-gate if (desauthtab == NULL) {
4730Sstevel@tonic-gate desauthtab = kmem_zalloc(clnt_authdes_cachesz *
4740Sstevel@tonic-gate sizeof (struct desauthent), KM_SLEEP);
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate for (da = desauthtab;
4770Sstevel@tonic-gate da < &desauthtab[clnt_authdes_cachesz];
4780Sstevel@tonic-gate da++) {
4790Sstevel@tonic-gate if (da->da_data == secdata &&
4800Sstevel@tonic-gate da->da_uid == crgetuid(cr) &&
4810Sstevel@tonic-gate da->da_zoneid == zoneid &&
4820Sstevel@tonic-gate !da->da_inuse &&
4830Sstevel@tonic-gate da->da_auth != NULL) {
4840Sstevel@tonic-gate da->da_inuse = 1;
4850Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
4860Sstevel@tonic-gate *ap = da->da_auth;
4870Sstevel@tonic-gate return (0);
4880Sstevel@tonic-gate }
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate /*
4930Sstevel@tonic-gate * A better way would be to have a cred paramater to
4940Sstevel@tonic-gate * authdes_create.
4950Sstevel@tonic-gate */
4960Sstevel@tonic-gate savecred = curthread->t_cred;
4970Sstevel@tonic-gate curthread->t_cred = cr;
4985302Sth199096
4995302Sth199096 /*
5005302Sth199096 * Note that authdes_create() expects a
5015302Sth199096 * NUL-terminated string for netname, but
5025302Sth199096 * dh_k4_clntdata_t gives us netname & netnamelen.
5035302Sth199096 *
5045302Sth199096 * We must create a string for authdes_create();
5055302Sth199096 * the latter takes a copy of it, so we may
5065302Sth199096 * immediately free it.
5075302Sth199096 */
5080Sstevel@tonic-gate desdata = (dh_k4_clntdata_t *)secdata->data;
5095302Sth199096 nlen = desdata->netnamelen;
5105302Sth199096 /* must be NUL-terminated */
5115302Sth199096 netname = kmem_zalloc(nlen + 1, KM_SLEEP);
5125302Sth199096 bcopy(desdata->netname, netname, nlen);
5135302Sth199096 stat = authdes_create(netname, authdes_win,
5145302Sth199096 &desdata->syncaddr, desdata->knconf,
5155302Sth199096 (des_block *)NULL,
5165302Sth199096 (secdata->flags & AUTH_F_RPCTIMESYNC) ? 1 : 0,
5175302Sth199096 &auth);
5185302Sth199096 kmem_free(netname, nlen + 1);
5195302Sth199096
5200Sstevel@tonic-gate curthread->t_cred = savecred;
5210Sstevel@tonic-gate *ap = auth;
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate if (stat != 0) {
5240Sstevel@tonic-gate /*
5250Sstevel@tonic-gate * If AUTH_F_TRYNONE is on, try again
5260Sstevel@tonic-gate * with AUTH_NONE. See bug 1180236.
5270Sstevel@tonic-gate */
5280Sstevel@tonic-gate if (secdata->flags & AUTH_F_TRYNONE) {
5290Sstevel@tonic-gate authflavor = AUTH_NONE;
5300Sstevel@tonic-gate continue;
5310Sstevel@tonic-gate } else
5320Sstevel@tonic-gate return (stat);
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate i = clnt_authdes_cachesz;
5360Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
5370Sstevel@tonic-gate do {
5380Sstevel@tonic-gate da = &desauthtab[nextdesvictim++];
5390Sstevel@tonic-gate nextdesvictim %= clnt_authdes_cachesz;
5400Sstevel@tonic-gate } while (da->da_inuse && --i > 0);
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate if (da->da_inuse) {
5430Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
5440Sstevel@tonic-gate /* overflow of des auths */
5450Sstevel@tonic-gate return (stat);
5460Sstevel@tonic-gate }
5470Sstevel@tonic-gate da->da_inuse = 1;
5480Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate if (da->da_auth != NULL)
5510Sstevel@tonic-gate auth_destroy(da->da_auth);
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate da->da_auth = auth;
5540Sstevel@tonic-gate da->da_uid = crgetuid(cr);
5550Sstevel@tonic-gate da->da_zoneid = zoneid;
5560Sstevel@tonic-gate da->da_data = secdata;
5570Sstevel@tonic-gate return (stat);
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate case RPCSEC_GSS:
5600Sstevel@tonic-gate /*
5610Sstevel@tonic-gate * For RPCSEC_GSS, cache is done in rpc_gss_secget().
5620Sstevel@tonic-gate * For every rpc_gss_secget(), it should have
5630Sstevel@tonic-gate * a corresponding rpc_gss_secfree() call.
5640Sstevel@tonic-gate */
5650Sstevel@tonic-gate gssdata = (gss_clntdata_t *)secdata->data;
5660Sstevel@tonic-gate (void) sprintf(gss_svc_name, "%s@%s", gssdata->uname,
5670Sstevel@tonic-gate gssdata->inst);
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate stat = rpc_gss_secget(client, gss_svc_name,
5700Sstevel@tonic-gate &gssdata->mechanism,
5710Sstevel@tonic-gate gssdata->service,
5720Sstevel@tonic-gate gssdata->qop,
5730Sstevel@tonic-gate NULL, NULL,
5740Sstevel@tonic-gate (caddr_t)secdata, cr, &auth);
5750Sstevel@tonic-gate *ap = auth;
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate /* success */
5780Sstevel@tonic-gate if (stat == 0)
5790Sstevel@tonic-gate return (stat);
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate /*
5820Sstevel@tonic-gate * let the caller retry if connection timedout
5830Sstevel@tonic-gate * or reset.
5840Sstevel@tonic-gate */
5850Sstevel@tonic-gate if (stat == ETIMEDOUT || stat == ECONNRESET)
5860Sstevel@tonic-gate return (stat);
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate /*
5890Sstevel@tonic-gate * If AUTH_F_TRYNONE is on, try again
5900Sstevel@tonic-gate * with AUTH_NONE. See bug 1180236.
5910Sstevel@tonic-gate */
5920Sstevel@tonic-gate if (secdata->flags & AUTH_F_TRYNONE) {
5930Sstevel@tonic-gate authflavor = AUTH_NONE;
5940Sstevel@tonic-gate continue;
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate RPCLOG(1, "sec_clnt_geth: rpc_gss_secget"
5985302Sth199096 " failed with %d", stat);
5990Sstevel@tonic-gate return (stat);
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate default:
6020Sstevel@tonic-gate /*
6030Sstevel@tonic-gate * auth create must have failed, try AUTH_NONE
6040Sstevel@tonic-gate * (this relies on AUTH_NONE never failing)
6050Sstevel@tonic-gate */
6060Sstevel@tonic-gate cmn_err(CE_NOTE, "sec_clnt_geth: unknown "
6070Sstevel@tonic-gate "authflavor %d, trying AUTH_NONE", authflavor);
6080Sstevel@tonic-gate authflavor = AUTH_NONE;
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate }
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate void
sec_clnt_freeh(AUTH * auth)6140Sstevel@tonic-gate sec_clnt_freeh(AUTH *auth)
6150Sstevel@tonic-gate {
6160Sstevel@tonic-gate struct desauthent *da;
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate switch (auth->ah_cred.oa_flavor) {
6190Sstevel@tonic-gate case AUTH_NONE: /* XXX: do real AUTH_NONE */
6200Sstevel@tonic-gate case AUTH_UNIX:
6210Sstevel@tonic-gate case AUTH_LOOPBACK:
6220Sstevel@tonic-gate auth_destroy(auth); /* was overflow */
6230Sstevel@tonic-gate break;
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate case AUTH_DES:
6260Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
6270Sstevel@tonic-gate if (desauthtab != NULL) {
6285302Sth199096 for (da = desauthtab;
6295302Sth199096 da < &desauthtab[clnt_authdes_cachesz]; da++) {
6305302Sth199096 if (da->da_auth == auth) {
6315302Sth199096 da->da_inuse = 0;
6325302Sth199096 mutex_exit(&desauthtab_lock);
6335302Sth199096 return;
6345302Sth199096 }
6350Sstevel@tonic-gate }
6360Sstevel@tonic-gate }
6370Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
6380Sstevel@tonic-gate auth_destroy(auth); /* was overflow */
6390Sstevel@tonic-gate break;
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate case RPCSEC_GSS:
6420Sstevel@tonic-gate (void) rpc_gss_secfree(auth);
6430Sstevel@tonic-gate break;
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate default:
6460Sstevel@tonic-gate cmn_err(CE_NOTE, "sec_clnt_freeh: unknown authflavor %d",
6475302Sth199096 auth->ah_cred.oa_flavor);
6480Sstevel@tonic-gate break;
6490Sstevel@tonic-gate }
6500Sstevel@tonic-gate }
6510Sstevel@tonic-gate
6520Sstevel@tonic-gate /*
6530Sstevel@tonic-gate * Revoke the authentication key in the given AUTH handle by setting
6540Sstevel@tonic-gate * it to NULL. If newkey is true, then generate a new key instead of
6550Sstevel@tonic-gate * nulling out the old one. This is necessary for AUTH_DES because
6560Sstevel@tonic-gate * the new key will be used next time the user does a keylogin. If
6570Sstevel@tonic-gate * the zero'd key is used as actual key, then it cannot be revoked
6580Sstevel@tonic-gate * again!
6590Sstevel@tonic-gate */
6600Sstevel@tonic-gate void
revoke_key(AUTH * auth,int newkey)6610Sstevel@tonic-gate revoke_key(AUTH *auth, int newkey)
6620Sstevel@tonic-gate {
6630Sstevel@tonic-gate if (auth == NULL)
6640Sstevel@tonic-gate return;
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate if (newkey) {
6670Sstevel@tonic-gate if (key_gendes(&auth->ah_key) != RPC_SUCCESS) {
6680Sstevel@tonic-gate /* failed to get new key, munge the old one */
6690Sstevel@tonic-gate auth->ah_key.key.high ^= auth->ah_key.key.low;
6700Sstevel@tonic-gate auth->ah_key.key.low += auth->ah_key.key.high;
6710Sstevel@tonic-gate }
6720Sstevel@tonic-gate } else {
6730Sstevel@tonic-gate /* null out old key */
6740Sstevel@tonic-gate auth->ah_key.key.high = 0;
6750Sstevel@tonic-gate auth->ah_key.key.low = 0;
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate }
6780Sstevel@tonic-gate
6790Sstevel@tonic-gate /*
6800Sstevel@tonic-gate * Revoke all rpc credentials (of the selected auth type) for the given uid
6810Sstevel@tonic-gate * from the auth cache. Must be root to do this if the requested uid is not
6820Sstevel@tonic-gate * the effective uid of the requestor.
6830Sstevel@tonic-gate *
6840Sstevel@tonic-gate * Called from nfssys() for backward compatibility, and also
6850Sstevel@tonic-gate * called from krpc_sys().
6860Sstevel@tonic-gate *
6870Sstevel@tonic-gate * AUTH_DES does not refer to the "mechanism" information.
6880Sstevel@tonic-gate * RPCSEC_GSS requires the "mechanism" input.
6890Sstevel@tonic-gate * The input argument, mechanism, is a user-space address and needs
6900Sstevel@tonic-gate * to be copied into the kernel address space.
6910Sstevel@tonic-gate *
6920Sstevel@tonic-gate * Returns error number.
6930Sstevel@tonic-gate */
6940Sstevel@tonic-gate /*ARGSUSED*/
6950Sstevel@tonic-gate int
sec_clnt_revoke(int rpcflavor,uid_t uid,cred_t * cr,void * mechanism,model_t model)6960Sstevel@tonic-gate sec_clnt_revoke(int rpcflavor, uid_t uid, cred_t *cr, void *mechanism,
6970Sstevel@tonic-gate model_t model)
6980Sstevel@tonic-gate {
6990Sstevel@tonic-gate struct desauthent *da;
7000Sstevel@tonic-gate int error = 0;
7010Sstevel@tonic-gate zoneid_t zoneid = getzoneid();
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate if (uid != crgetuid(cr) && secpolicy_nfs(cr) != 0)
7040Sstevel@tonic-gate return (EPERM);
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate switch (rpcflavor) {
7070Sstevel@tonic-gate case AUTH_DES:
7080Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
7090Sstevel@tonic-gate if (desauthtab != NULL) {
7105302Sth199096 for (da = desauthtab;
7115302Sth199096 da < &desauthtab[clnt_authdes_cachesz]; da++) {
7125302Sth199096 if (uid == da->da_uid &&
7135302Sth199096 zoneid == da->da_zoneid)
7145302Sth199096 revoke_key(da->da_auth, 1);
7155302Sth199096 }
7160Sstevel@tonic-gate }
7170Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
7180Sstevel@tonic-gate return (0);
7190Sstevel@tonic-gate
7200Sstevel@tonic-gate case RPCSEC_GSS: {
7210Sstevel@tonic-gate rpc_gss_OID mech;
7220Sstevel@tonic-gate caddr_t elements;
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate if (!mechanism)
7250Sstevel@tonic-gate return (EINVAL);
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate /* copyin the gss mechanism type */
7280Sstevel@tonic-gate mech = kmem_alloc(sizeof (rpc_gss_OID_desc), KM_SLEEP);
7290Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
7300Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
7310Sstevel@tonic-gate gss_OID_desc32 mech32;
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate if (copyin(mechanism, &mech32,
7340Sstevel@tonic-gate sizeof (gss_OID_desc32))) {
7350Sstevel@tonic-gate kmem_free(mech, sizeof (rpc_gss_OID_desc));
7360Sstevel@tonic-gate return (EFAULT);
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate mech->length = mech32.length;
7390Sstevel@tonic-gate mech->elements = (caddr_t)(uintptr_t)mech32.elements;
7400Sstevel@tonic-gate } else
7410Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
7420Sstevel@tonic-gate if (copyin(mechanism, mech, sizeof (rpc_gss_OID_desc))) {
7430Sstevel@tonic-gate kmem_free(mech, sizeof (rpc_gss_OID_desc));
7440Sstevel@tonic-gate return (EFAULT);
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate
747*12190SP.Kumar@Sun.COM if (mech->length < MINAUTHLEN ||
748*12190SP.Kumar@Sun.COM mech->length > MAXAUTHLEN) {
749*12190SP.Kumar@Sun.COM kmem_free(mech, sizeof (rpc_gss_OID_desc));
750*12190SP.Kumar@Sun.COM return (EINVAL);
751*12190SP.Kumar@Sun.COM }
752*12190SP.Kumar@Sun.COM
7530Sstevel@tonic-gate elements = kmem_alloc(mech->length, KM_SLEEP);
7540Sstevel@tonic-gate if (copyin(mech->elements, elements, mech->length)) {
7550Sstevel@tonic-gate kmem_free(elements, mech->length);
7560Sstevel@tonic-gate kmem_free(mech, sizeof (rpc_gss_OID_desc));
7570Sstevel@tonic-gate return (EFAULT);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate mech->elements = elements;
7600Sstevel@tonic-gate
7610Sstevel@tonic-gate error = rpc_gss_revauth(uid, mech);
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate kmem_free(elements, mech->length);
7640Sstevel@tonic-gate kmem_free(mech, sizeof (rpc_gss_OID_desc));
7650Sstevel@tonic-gate
7660Sstevel@tonic-gate return (error);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate default:
7700Sstevel@tonic-gate /* not an auth type with cached creds */
7710Sstevel@tonic-gate return (EINVAL);
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate /*
7760Sstevel@tonic-gate * Since sec_data is the index for the client auth handles
7770Sstevel@tonic-gate * cache table, whenever the sec_data is freed, the index needs
7780Sstevel@tonic-gate * to be nulled.
7790Sstevel@tonic-gate */
7800Sstevel@tonic-gate void
purge_authtab(struct sec_data * secdata)7810Sstevel@tonic-gate purge_authtab(struct sec_data *secdata)
7820Sstevel@tonic-gate {
7830Sstevel@tonic-gate struct desauthent *da;
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate switch (secdata->rpcflavor) {
7860Sstevel@tonic-gate
7870Sstevel@tonic-gate case AUTH_DES:
7880Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
7890Sstevel@tonic-gate if (desauthtab != NULL) {
7905302Sth199096 for (da = desauthtab;
7915302Sth199096 da < &desauthtab[clnt_authdes_cachesz]; da++) {
7925302Sth199096 if (da->da_data == secdata) {
7935302Sth199096 da->da_data = NULL;
7945302Sth199096 da->da_inuse = 0;
7955302Sth199096 }
7960Sstevel@tonic-gate }
7970Sstevel@tonic-gate }
7980Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
7990Sstevel@tonic-gate return;
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate case RPCSEC_GSS:
8020Sstevel@tonic-gate rpc_gss_secpurge((void *)secdata);
8030Sstevel@tonic-gate return;
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate default:
8060Sstevel@tonic-gate return;
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate void
sec_subrinit(void)8110Sstevel@tonic-gate sec_subrinit(void)
8120Sstevel@tonic-gate {
8130Sstevel@tonic-gate authkern_cache = kmem_cache_create("authkern_cache",
8140Sstevel@tonic-gate sizeof (AUTH), 0, authkern_init, NULL, NULL, NULL, NULL, 0);
8158637SVallish.Vaidyeshwara@Sun.COM authnone_cache = kmem_cache_create("authnone_cache",
8168637SVallish.Vaidyeshwara@Sun.COM sizeof (AUTH), 0, authnone_init, NULL, NULL, NULL, NULL, 0);
8170Sstevel@tonic-gate authloopback_cache = kmem_cache_create("authloopback_cache",
8180Sstevel@tonic-gate sizeof (AUTH), 0, authloopback_init, NULL, NULL, NULL, NULL, 0);
8190Sstevel@tonic-gate mutex_init(&desauthtab_lock, NULL, MUTEX_DEFAULT, NULL);
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate /* RPC stuff */
8220Sstevel@tonic-gate mutex_init(&authdes_ops_lock, NULL, MUTEX_DEFAULT, NULL);
8230Sstevel@tonic-gate zone_key_create(&auth_zone_key, auth_zone_init, NULL, auth_zone_fini);
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate /*
8270Sstevel@tonic-gate * Destroys the caches and mutexes previously allocated and initialized
8280Sstevel@tonic-gate * in sec_subrinit().
8290Sstevel@tonic-gate * This routine is called by _init() if mod_install() failed.
8300Sstevel@tonic-gate */
8310Sstevel@tonic-gate void
sec_subrfini(void)8320Sstevel@tonic-gate sec_subrfini(void)
8330Sstevel@tonic-gate {
8340Sstevel@tonic-gate mutex_destroy(&desauthtab_lock);
8350Sstevel@tonic-gate kmem_cache_destroy(authkern_cache);
8368637SVallish.Vaidyeshwara@Sun.COM kmem_cache_destroy(authnone_cache);
8370Sstevel@tonic-gate kmem_cache_destroy(authloopback_cache);
8380Sstevel@tonic-gate
8390Sstevel@tonic-gate /* RPC stuff */
8400Sstevel@tonic-gate mutex_destroy(&authdes_ops_lock);
8410Sstevel@tonic-gate (void) zone_key_delete(auth_zone_key);
8420Sstevel@tonic-gate }
843