17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5b9238976Sth * Common Development and Distribution License (the "License").
6b9238976Sth * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #include <sys/param.h>
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/systm.h>
287c478bd9Sstevel@tonic-gate #include <sys/cred.h>
297c478bd9Sstevel@tonic-gate #include <sys/proc.h>
307c478bd9Sstevel@tonic-gate #include <sys/user.h>
317c478bd9Sstevel@tonic-gate #include <sys/time.h>
327c478bd9Sstevel@tonic-gate #include <sys/buf.h>
337c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
347c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
357c478bd9Sstevel@tonic-gate #include <sys/socket.h>
367c478bd9Sstevel@tonic-gate #include <sys/stat.h>
377c478bd9Sstevel@tonic-gate #include <sys/uio.h>
387c478bd9Sstevel@tonic-gate #include <sys/tiuser.h>
397c478bd9Sstevel@tonic-gate #include <sys/swap.h>
407c478bd9Sstevel@tonic-gate #include <sys/errno.h>
417c478bd9Sstevel@tonic-gate #include <sys/debug.h>
427c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
437c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
447c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
457c478bd9Sstevel@tonic-gate #include <sys/vtrace.h>
467c478bd9Sstevel@tonic-gate #include <sys/session.h>
477c478bd9Sstevel@tonic-gate #include <sys/dnlc.h>
487c478bd9Sstevel@tonic-gate #include <sys/bitmap.h>
497c478bd9Sstevel@tonic-gate #include <sys/thread.h>
507c478bd9Sstevel@tonic-gate #include <sys/policy.h>
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #include <netinet/in.h>
537c478bd9Sstevel@tonic-gate #include <rpc/types.h>
547c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
557c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
567c478bd9Sstevel@tonic-gate #include <rpc/auth_des.h> /* for authdes_create() */
577c478bd9Sstevel@tonic-gate #include <rpc/clnt.h>
587c478bd9Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate #define MAXCLIENTS 16
61*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States
62*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States /*
63*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States * Currently there is no maximum length defined withing the gss
64*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States * specification. Because of security issues the maximum gss
65*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States * authentication length is checked to be under the MAXAUTHLEN
66*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States * defined below. The value was chosen because it will be a safe
67*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States * maximum value for some time. Currently lengths are generally
68*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States * under the 16 byte length
69*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States */
70*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States #define MINAUTHLEN 1 /* minimum gss authentication length */
71*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States #define MAXAUTHLEN 65535 /* maximum gss authentication length */
727c478bd9Sstevel@tonic-gate static int clnt_authdes_cachesz = 64;
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate static uint_t authdes_win = 5*60; /* 5 minutes -- should be mount option */
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate struct kmem_cache *authkern_cache;
777c478bd9Sstevel@tonic-gate
7833f285aeSVallish Vaidyeshwara struct kmem_cache *authnone_cache;
7933f285aeSVallish Vaidyeshwara
807c478bd9Sstevel@tonic-gate struct kmem_cache *authloopback_cache;
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate static struct desauthent {
837c478bd9Sstevel@tonic-gate struct sec_data *da_data;
847c478bd9Sstevel@tonic-gate uid_t da_uid;
857c478bd9Sstevel@tonic-gate zoneid_t da_zoneid;
867c478bd9Sstevel@tonic-gate short da_inuse;
877c478bd9Sstevel@tonic-gate AUTH *da_auth;
887c478bd9Sstevel@tonic-gate } *desauthtab;
897c478bd9Sstevel@tonic-gate static int nextdesvictim;
907c478bd9Sstevel@tonic-gate static kmutex_t desauthtab_lock; /* Lock to protect DES auth cache */
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate /* RPC stuff */
937c478bd9Sstevel@tonic-gate kmutex_t authdes_ops_lock; /* auth_ops initialization in authdes_ops() */
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate static void purge_authtab(struct sec_data *);
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate /* Zone stuff */
987c478bd9Sstevel@tonic-gate zone_key_t auth_zone_key;
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate * Load RPCSEC_GSS specific data from user space to kernel space.
1027c478bd9Sstevel@tonic-gate */
1037c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1047c478bd9Sstevel@tonic-gate static int
gss_clnt_loadinfo(caddr_t usrdata,caddr_t * kdata,model_t model)1057c478bd9Sstevel@tonic-gate gss_clnt_loadinfo(caddr_t usrdata, caddr_t *kdata, model_t model)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate struct gss_clnt_data *data;
1087c478bd9Sstevel@tonic-gate caddr_t elements;
1097c478bd9Sstevel@tonic-gate int error = 0;
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate /* map opaque data to gss specific structure */
1127c478bd9Sstevel@tonic-gate data = kmem_alloc(sizeof (*data), KM_SLEEP);
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1157c478bd9Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
1167c478bd9Sstevel@tonic-gate struct gss_clnt_data32 gd32;
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate if (copyin(usrdata, &gd32, sizeof (gd32)) == -1) {
1197c478bd9Sstevel@tonic-gate error = EFAULT;
1207c478bd9Sstevel@tonic-gate } else {
1217c478bd9Sstevel@tonic-gate data->mechanism.length = gd32.mechanism.length;
1227c478bd9Sstevel@tonic-gate data->mechanism.elements =
123b9238976Sth (caddr_t)(uintptr_t)gd32.mechanism.elements;
1247c478bd9Sstevel@tonic-gate data->service = gd32.service;
1257c478bd9Sstevel@tonic-gate bcopy(gd32.uname, data->uname, sizeof (gd32.uname));
1267c478bd9Sstevel@tonic-gate bcopy(gd32.inst, data->inst, sizeof (gd32.inst));
1277c478bd9Sstevel@tonic-gate bcopy(gd32.realm, data->realm, sizeof (gd32.realm));
1287c478bd9Sstevel@tonic-gate data->qop = gd32.qop;
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate } else
1317c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
1327c478bd9Sstevel@tonic-gate if (copyin(usrdata, data, sizeof (*data)))
1337c478bd9Sstevel@tonic-gate error = EFAULT;
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate if (error == 0) {
136*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States if (data->mechanism.length >= MINAUTHLEN &&
137*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States data->mechanism.length <= MAXAUTHLEN) {
1387c478bd9Sstevel@tonic-gate elements = kmem_alloc(data->mechanism.length, KM_SLEEP);
1397c478bd9Sstevel@tonic-gate if (!(copyin(data->mechanism.elements, elements,
1407c478bd9Sstevel@tonic-gate data->mechanism.length))) {
1417c478bd9Sstevel@tonic-gate data->mechanism.elements = elements;
1427c478bd9Sstevel@tonic-gate *kdata = (caddr_t)data;
1437c478bd9Sstevel@tonic-gate return (0);
144*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States }
145*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States kmem_free(elements, data->mechanism.length);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate }
148*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States *kdata = NULL;
149*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States kmem_free(data, sizeof (*data));
150*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States
1517c478bd9Sstevel@tonic-gate return (EFAULT);
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate /*
1567c478bd9Sstevel@tonic-gate * Load AUTH_DES specific data from user space to kernel space.
1577c478bd9Sstevel@tonic-gate */
1587c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
1597c478bd9Sstevel@tonic-gate int
dh_k4_clnt_loadinfo(caddr_t usrdata,caddr_t * kdata,model_t model)1607c478bd9Sstevel@tonic-gate dh_k4_clnt_loadinfo(caddr_t usrdata, caddr_t *kdata, model_t model)
1617c478bd9Sstevel@tonic-gate {
1627c478bd9Sstevel@tonic-gate size_t nlen;
1637c478bd9Sstevel@tonic-gate int error = 0;
1647c478bd9Sstevel@tonic-gate char *userbufptr;
1657c478bd9Sstevel@tonic-gate dh_k4_clntdata_t *data;
1667c478bd9Sstevel@tonic-gate char netname[MAXNETNAMELEN+1];
1677c478bd9Sstevel@tonic-gate struct netbuf *syncaddr;
1687c478bd9Sstevel@tonic-gate struct knetconfig *knconf;
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate /* map opaque data to des specific strucutre */
1717c478bd9Sstevel@tonic-gate data = kmem_alloc(sizeof (*data), KM_SLEEP);
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1747c478bd9Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
1757c478bd9Sstevel@tonic-gate struct des_clnt_data32 data32;
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate if (copyin(usrdata, &data32, sizeof (data32)) == -1) {
1787c478bd9Sstevel@tonic-gate error = EFAULT;
1797c478bd9Sstevel@tonic-gate } else {
1807c478bd9Sstevel@tonic-gate data->syncaddr.maxlen = data32.syncaddr.maxlen;
1817c478bd9Sstevel@tonic-gate data->syncaddr.len = data32.syncaddr.len;
1827c478bd9Sstevel@tonic-gate data->syncaddr.buf =
1837c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)data32.syncaddr.buf;
1847c478bd9Sstevel@tonic-gate data->knconf =
1857c478bd9Sstevel@tonic-gate (struct knetconfig *)(uintptr_t)data32.knconf;
1867c478bd9Sstevel@tonic-gate data->netname = (caddr_t)(uintptr_t)data32.netname;
1877c478bd9Sstevel@tonic-gate data->netnamelen = data32.netnamelen;
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate } else
1907c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
1917c478bd9Sstevel@tonic-gate if (copyin(usrdata, data, sizeof (*data)))
1927c478bd9Sstevel@tonic-gate error = EFAULT;
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate if (error == 0) {
1957c478bd9Sstevel@tonic-gate syncaddr = &data->syncaddr;
196*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States if (syncaddr->len < MINAUTHLEN || syncaddr->len > MAXAUTHLEN)
1977c478bd9Sstevel@tonic-gate error = EINVAL;
1987c478bd9Sstevel@tonic-gate else {
1997c478bd9Sstevel@tonic-gate userbufptr = syncaddr->buf;
200*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States syncaddr->buf = kmem_alloc(syncaddr->len, KM_SLEEP);
2017c478bd9Sstevel@tonic-gate syncaddr->maxlen = syncaddr->len;
2027c478bd9Sstevel@tonic-gate if (copyin(userbufptr, syncaddr->buf, syncaddr->len)) {
2037c478bd9Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2047c478bd9Sstevel@tonic-gate syncaddr->buf = NULL;
2057c478bd9Sstevel@tonic-gate error = EFAULT;
2067c478bd9Sstevel@tonic-gate } else {
2077c478bd9Sstevel@tonic-gate (void) copyinstr(data->netname, netname,
2087c478bd9Sstevel@tonic-gate sizeof (netname), &nlen);
2097c478bd9Sstevel@tonic-gate if (nlen != 0) {
2107c478bd9Sstevel@tonic-gate data->netname =
2117c478bd9Sstevel@tonic-gate kmem_alloc(nlen, KM_SLEEP);
2127c478bd9Sstevel@tonic-gate bcopy(netname, data->netname, nlen);
2137c478bd9Sstevel@tonic-gate data->netnamelen = (int)nlen;
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate if (!error) {
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate * Allocate space for a knetconfig structure and
2227c478bd9Sstevel@tonic-gate * its strings and copy in from user-land.
2237c478bd9Sstevel@tonic-gate */
2247c478bd9Sstevel@tonic-gate knconf = kmem_alloc(sizeof (*knconf), KM_SLEEP);
2257c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
2267c478bd9Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
2277c478bd9Sstevel@tonic-gate struct knetconfig32 knconf32;
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate if (copyin(data->knconf, &knconf32,
2307c478bd9Sstevel@tonic-gate sizeof (knconf32)) == -1) {
2317c478bd9Sstevel@tonic-gate kmem_free(knconf, sizeof (*knconf));
2327c478bd9Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2337c478bd9Sstevel@tonic-gate syncaddr->buf = NULL;
2347c478bd9Sstevel@tonic-gate kmem_free(data->netname, nlen);
2357c478bd9Sstevel@tonic-gate error = EFAULT;
2367c478bd9Sstevel@tonic-gate } else {
2377c478bd9Sstevel@tonic-gate knconf->knc_semantics = knconf32.knc_semantics;
2387c478bd9Sstevel@tonic-gate knconf->knc_protofmly =
2397c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)knconf32.knc_protofmly;
2407c478bd9Sstevel@tonic-gate knconf->knc_proto =
2417c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)knconf32.knc_proto;
2427c478bd9Sstevel@tonic-gate knconf->knc_rdev = expldev(knconf32.knc_rdev);
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate } else
2457c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
2467c478bd9Sstevel@tonic-gate if (copyin(data->knconf, knconf, sizeof (*knconf))) {
2477c478bd9Sstevel@tonic-gate kmem_free(knconf, sizeof (*knconf));
2487c478bd9Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2497c478bd9Sstevel@tonic-gate syncaddr->buf = NULL;
2507c478bd9Sstevel@tonic-gate kmem_free(data->netname, nlen);
2517c478bd9Sstevel@tonic-gate error = EFAULT;
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate if (!error) {
2567c478bd9Sstevel@tonic-gate size_t nmoved_tmp;
2577c478bd9Sstevel@tonic-gate char *p, *pf;
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate pf = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
2607c478bd9Sstevel@tonic-gate p = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
2617c478bd9Sstevel@tonic-gate error = copyinstr(knconf->knc_protofmly, pf,
2627c478bd9Sstevel@tonic-gate KNC_STRSIZE, &nmoved_tmp);
2637c478bd9Sstevel@tonic-gate if (error) {
2647c478bd9Sstevel@tonic-gate kmem_free(pf, KNC_STRSIZE);
2657c478bd9Sstevel@tonic-gate kmem_free(p, KNC_STRSIZE);
2667c478bd9Sstevel@tonic-gate kmem_free(knconf, sizeof (*knconf));
2677c478bd9Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2687c478bd9Sstevel@tonic-gate kmem_free(data->netname, nlen);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate if (!error) {
2727c478bd9Sstevel@tonic-gate error = copyinstr(knconf->knc_proto,
2737c478bd9Sstevel@tonic-gate p, KNC_STRSIZE, &nmoved_tmp);
2747c478bd9Sstevel@tonic-gate if (error) {
2757c478bd9Sstevel@tonic-gate kmem_free(pf, KNC_STRSIZE);
2767c478bd9Sstevel@tonic-gate kmem_free(p, KNC_STRSIZE);
2777c478bd9Sstevel@tonic-gate kmem_free(knconf, sizeof (*knconf));
2787c478bd9Sstevel@tonic-gate kmem_free(syncaddr->buf, syncaddr->len);
2797c478bd9Sstevel@tonic-gate kmem_free(data->netname, nlen);
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate if (!error) {
2847c478bd9Sstevel@tonic-gate knconf->knc_protofmly = pf;
2857c478bd9Sstevel@tonic-gate knconf->knc_proto = p;
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate if (error) {
2907c478bd9Sstevel@tonic-gate *kdata = NULL;
2917c478bd9Sstevel@tonic-gate kmem_free(data, sizeof (*data));
2927c478bd9Sstevel@tonic-gate return (error);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate data->knconf = knconf;
2967c478bd9Sstevel@tonic-gate *kdata = (caddr_t)data;
2977c478bd9Sstevel@tonic-gate return (0);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate /*
3017c478bd9Sstevel@tonic-gate * Free up AUTH_DES specific data.
3027c478bd9Sstevel@tonic-gate */
3037c478bd9Sstevel@tonic-gate void
dh_k4_clnt_freeinfo(caddr_t cdata)3047c478bd9Sstevel@tonic-gate dh_k4_clnt_freeinfo(caddr_t cdata)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate dh_k4_clntdata_t *data;
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate data = (dh_k4_clntdata_t *)cdata;
3097c478bd9Sstevel@tonic-gate if (data->netnamelen > 0) {
3107c478bd9Sstevel@tonic-gate kmem_free(data->netname, data->netnamelen);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate if (data->syncaddr.buf != NULL) {
3137c478bd9Sstevel@tonic-gate kmem_free(data->syncaddr.buf, data->syncaddr.len);
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate if (data->knconf != NULL) {
3167c478bd9Sstevel@tonic-gate kmem_free(data->knconf->knc_protofmly, KNC_STRSIZE);
3177c478bd9Sstevel@tonic-gate kmem_free(data->knconf->knc_proto, KNC_STRSIZE);
3187c478bd9Sstevel@tonic-gate kmem_free(data->knconf, sizeof (*data->knconf));
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate kmem_free(data, sizeof (*data));
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate /*
3257c478bd9Sstevel@tonic-gate * Load application auth related data from user land to kernel.
3267c478bd9Sstevel@tonic-gate * Map opaque data field to dh_k4_clntdata_t for AUTH_DES
3277c478bd9Sstevel@tonic-gate *
3287c478bd9Sstevel@tonic-gate */
3297c478bd9Sstevel@tonic-gate int
sec_clnt_loadinfo(struct sec_data * in,struct sec_data ** out,model_t model)3307c478bd9Sstevel@tonic-gate sec_clnt_loadinfo(struct sec_data *in, struct sec_data **out, model_t model)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate struct sec_data *secdata;
3337c478bd9Sstevel@tonic-gate int error = 0;
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate secdata = kmem_alloc(sizeof (*secdata), KM_SLEEP);
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
3387c478bd9Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
3397c478bd9Sstevel@tonic-gate struct sec_data32 sd32;
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate if (copyin(in, &sd32, sizeof (sd32)) == -1) {
3427c478bd9Sstevel@tonic-gate error = EFAULT;
3437c478bd9Sstevel@tonic-gate } else {
3447c478bd9Sstevel@tonic-gate secdata->secmod = sd32.secmod;
3457c478bd9Sstevel@tonic-gate secdata->rpcflavor = sd32.rpcflavor;
3467c478bd9Sstevel@tonic-gate secdata->uid = sd32.uid;
3477c478bd9Sstevel@tonic-gate secdata->flags = sd32.flags;
3487c478bd9Sstevel@tonic-gate secdata->data = (caddr_t)(uintptr_t)sd32.data;
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate } else
3517c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate if (copyin(in, secdata, sizeof (*secdata)) == -1) {
3547c478bd9Sstevel@tonic-gate error = EFAULT;
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate /*
3577c478bd9Sstevel@tonic-gate * Copy in opaque data field per flavor.
3587c478bd9Sstevel@tonic-gate */
3597c478bd9Sstevel@tonic-gate if (!error) {
3607c478bd9Sstevel@tonic-gate switch (secdata->rpcflavor) {
3617c478bd9Sstevel@tonic-gate case AUTH_NONE:
3627c478bd9Sstevel@tonic-gate case AUTH_UNIX:
3637c478bd9Sstevel@tonic-gate case AUTH_LOOPBACK:
3647c478bd9Sstevel@tonic-gate break;
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate case AUTH_DES:
3677c478bd9Sstevel@tonic-gate error = dh_k4_clnt_loadinfo(secdata->data,
3687c478bd9Sstevel@tonic-gate &secdata->data, model);
3697c478bd9Sstevel@tonic-gate break;
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate case RPCSEC_GSS:
3727c478bd9Sstevel@tonic-gate error = gss_clnt_loadinfo(secdata->data,
3737c478bd9Sstevel@tonic-gate &secdata->data, model);
3747c478bd9Sstevel@tonic-gate break;
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate default:
3777c478bd9Sstevel@tonic-gate error = EINVAL;
3787c478bd9Sstevel@tonic-gate break;
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate if (!error) {
3837c478bd9Sstevel@tonic-gate *out = secdata;
3847c478bd9Sstevel@tonic-gate } else {
3857c478bd9Sstevel@tonic-gate kmem_free(secdata, sizeof (*secdata));
3867c478bd9Sstevel@tonic-gate *out = (struct sec_data *)NULL;
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate return (error);
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate /*
3937c478bd9Sstevel@tonic-gate * Null the sec_data index in the cache table, and
3947c478bd9Sstevel@tonic-gate * free the memory allocated by sec_clnt_loadinfo.
3957c478bd9Sstevel@tonic-gate */
3967c478bd9Sstevel@tonic-gate void
sec_clnt_freeinfo(struct sec_data * secdata)3977c478bd9Sstevel@tonic-gate sec_clnt_freeinfo(struct sec_data *secdata)
3987c478bd9Sstevel@tonic-gate {
3997c478bd9Sstevel@tonic-gate switch (secdata->rpcflavor) {
4007c478bd9Sstevel@tonic-gate case AUTH_DES:
4017c478bd9Sstevel@tonic-gate purge_authtab(secdata);
4027c478bd9Sstevel@tonic-gate if (secdata->data)
4037c478bd9Sstevel@tonic-gate dh_k4_clnt_freeinfo(secdata->data);
4047c478bd9Sstevel@tonic-gate break;
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate case RPCSEC_GSS:
4077c478bd9Sstevel@tonic-gate rpc_gss_secpurge((void *)secdata);
4087c478bd9Sstevel@tonic-gate if (secdata->data) {
4097c478bd9Sstevel@tonic-gate gss_clntdata_t *gss_data;
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate gss_data = (gss_clntdata_t *)secdata->data;
4127c478bd9Sstevel@tonic-gate if (gss_data->mechanism.elements) {
4137c478bd9Sstevel@tonic-gate kmem_free(gss_data->mechanism.elements,
4147c478bd9Sstevel@tonic-gate gss_data->mechanism.length);
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate kmem_free(secdata->data, sizeof (gss_clntdata_t));
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate break;
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate case AUTH_NONE:
4217c478bd9Sstevel@tonic-gate case AUTH_UNIX:
4227c478bd9Sstevel@tonic-gate case AUTH_LOOPBACK:
4237c478bd9Sstevel@tonic-gate default:
4247c478bd9Sstevel@tonic-gate break;
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate kmem_free(secdata, sizeof (*secdata));
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate * Get an AUTH handle for a RPC client based on the given sec_data.
4317c478bd9Sstevel@tonic-gate * If an AUTH handle exists for the same sec_data, use that AUTH handle,
4327c478bd9Sstevel@tonic-gate * otherwise create a new one.
4337c478bd9Sstevel@tonic-gate */
4347c478bd9Sstevel@tonic-gate int
sec_clnt_geth(CLIENT * client,struct sec_data * secdata,cred_t * cr,AUTH ** ap)4357c478bd9Sstevel@tonic-gate sec_clnt_geth(CLIENT *client, struct sec_data *secdata, cred_t *cr, AUTH **ap)
4367c478bd9Sstevel@tonic-gate {
4377c478bd9Sstevel@tonic-gate int i;
4387c478bd9Sstevel@tonic-gate struct desauthent *da;
4397c478bd9Sstevel@tonic-gate int authflavor;
4407c478bd9Sstevel@tonic-gate cred_t *savecred;
4417c478bd9Sstevel@tonic-gate int stat; /* return (errno) status */
4427c478bd9Sstevel@tonic-gate char gss_svc_name[MAX_GSS_NAME];
4437c478bd9Sstevel@tonic-gate dh_k4_clntdata_t *desdata;
4447c478bd9Sstevel@tonic-gate AUTH *auth;
4457c478bd9Sstevel@tonic-gate gss_clntdata_t *gssdata;
4467c478bd9Sstevel@tonic-gate zoneid_t zoneid = getzoneid();
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate if ((client == NULL) || (secdata == NULL) || (ap == NULL))
4497c478bd9Sstevel@tonic-gate return (EINVAL);
4507c478bd9Sstevel@tonic-gate *ap = (AUTH *)NULL;
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate authflavor = secdata->rpcflavor;
4537c478bd9Sstevel@tonic-gate for (;;) {
454b9238976Sth int nlen;
455b9238976Sth char *netname;
456b9238976Sth
4577c478bd9Sstevel@tonic-gate switch (authflavor) {
4587c478bd9Sstevel@tonic-gate case AUTH_NONE:
45933f285aeSVallish Vaidyeshwara *ap = (AUTH *) authnone_create();
46033f285aeSVallish Vaidyeshwara return ((*ap != NULL) ? 0 : EINTR);
46133f285aeSVallish Vaidyeshwara
4627c478bd9Sstevel@tonic-gate case AUTH_UNIX:
4637c478bd9Sstevel@tonic-gate *ap = (AUTH *) authkern_create();
4647c478bd9Sstevel@tonic-gate return ((*ap != NULL) ? 0 : EINTR);
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate case AUTH_LOOPBACK:
4677c478bd9Sstevel@tonic-gate *ap = (AUTH *) authloopback_create();
4687c478bd9Sstevel@tonic-gate return ((*ap != NULL) ? 0 : EINTR);
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate case AUTH_DES:
4717c478bd9Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
4727c478bd9Sstevel@tonic-gate if (desauthtab == NULL) {
4737c478bd9Sstevel@tonic-gate desauthtab = kmem_zalloc(clnt_authdes_cachesz *
4747c478bd9Sstevel@tonic-gate sizeof (struct desauthent), KM_SLEEP);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate for (da = desauthtab;
4777c478bd9Sstevel@tonic-gate da < &desauthtab[clnt_authdes_cachesz];
4787c478bd9Sstevel@tonic-gate da++) {
4797c478bd9Sstevel@tonic-gate if (da->da_data == secdata &&
4807c478bd9Sstevel@tonic-gate da->da_uid == crgetuid(cr) &&
4817c478bd9Sstevel@tonic-gate da->da_zoneid == zoneid &&
4827c478bd9Sstevel@tonic-gate !da->da_inuse &&
4837c478bd9Sstevel@tonic-gate da->da_auth != NULL) {
4847c478bd9Sstevel@tonic-gate da->da_inuse = 1;
4857c478bd9Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
4867c478bd9Sstevel@tonic-gate *ap = da->da_auth;
4877c478bd9Sstevel@tonic-gate return (0);
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
4917c478bd9Sstevel@tonic-gate
4927c478bd9Sstevel@tonic-gate /*
4937c478bd9Sstevel@tonic-gate * A better way would be to have a cred paramater to
4947c478bd9Sstevel@tonic-gate * authdes_create.
4957c478bd9Sstevel@tonic-gate */
4967c478bd9Sstevel@tonic-gate savecred = curthread->t_cred;
4977c478bd9Sstevel@tonic-gate curthread->t_cred = cr;
498b9238976Sth
499b9238976Sth /*
500b9238976Sth * Note that authdes_create() expects a
501b9238976Sth * NUL-terminated string for netname, but
502b9238976Sth * dh_k4_clntdata_t gives us netname & netnamelen.
503b9238976Sth *
504b9238976Sth * We must create a string for authdes_create();
505b9238976Sth * the latter takes a copy of it, so we may
506b9238976Sth * immediately free it.
507b9238976Sth */
5087c478bd9Sstevel@tonic-gate desdata = (dh_k4_clntdata_t *)secdata->data;
509b9238976Sth nlen = desdata->netnamelen;
510b9238976Sth /* must be NUL-terminated */
511b9238976Sth netname = kmem_zalloc(nlen + 1, KM_SLEEP);
512b9238976Sth bcopy(desdata->netname, netname, nlen);
513b9238976Sth stat = authdes_create(netname, authdes_win,
514b9238976Sth &desdata->syncaddr, desdata->knconf,
515b9238976Sth (des_block *)NULL,
516b9238976Sth (secdata->flags & AUTH_F_RPCTIMESYNC) ? 1 : 0,
517b9238976Sth &auth);
518b9238976Sth kmem_free(netname, nlen + 1);
519b9238976Sth
5207c478bd9Sstevel@tonic-gate curthread->t_cred = savecred;
5217c478bd9Sstevel@tonic-gate *ap = auth;
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate if (stat != 0) {
5247c478bd9Sstevel@tonic-gate /*
5257c478bd9Sstevel@tonic-gate * If AUTH_F_TRYNONE is on, try again
5267c478bd9Sstevel@tonic-gate * with AUTH_NONE. See bug 1180236.
5277c478bd9Sstevel@tonic-gate */
5287c478bd9Sstevel@tonic-gate if (secdata->flags & AUTH_F_TRYNONE) {
5297c478bd9Sstevel@tonic-gate authflavor = AUTH_NONE;
5307c478bd9Sstevel@tonic-gate continue;
5317c478bd9Sstevel@tonic-gate } else
5327c478bd9Sstevel@tonic-gate return (stat);
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate i = clnt_authdes_cachesz;
5367c478bd9Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
5377c478bd9Sstevel@tonic-gate do {
5387c478bd9Sstevel@tonic-gate da = &desauthtab[nextdesvictim++];
5397c478bd9Sstevel@tonic-gate nextdesvictim %= clnt_authdes_cachesz;
5407c478bd9Sstevel@tonic-gate } while (da->da_inuse && --i > 0);
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate if (da->da_inuse) {
5437c478bd9Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
5447c478bd9Sstevel@tonic-gate /* overflow of des auths */
5457c478bd9Sstevel@tonic-gate return (stat);
5467c478bd9Sstevel@tonic-gate }
5477c478bd9Sstevel@tonic-gate da->da_inuse = 1;
5487c478bd9Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate if (da->da_auth != NULL)
5517c478bd9Sstevel@tonic-gate auth_destroy(da->da_auth);
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate da->da_auth = auth;
5547c478bd9Sstevel@tonic-gate da->da_uid = crgetuid(cr);
5557c478bd9Sstevel@tonic-gate da->da_zoneid = zoneid;
5567c478bd9Sstevel@tonic-gate da->da_data = secdata;
5577c478bd9Sstevel@tonic-gate return (stat);
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate case RPCSEC_GSS:
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate * For RPCSEC_GSS, cache is done in rpc_gss_secget().
5627c478bd9Sstevel@tonic-gate * For every rpc_gss_secget(), it should have
5637c478bd9Sstevel@tonic-gate * a corresponding rpc_gss_secfree() call.
5647c478bd9Sstevel@tonic-gate */
5657c478bd9Sstevel@tonic-gate gssdata = (gss_clntdata_t *)secdata->data;
5667c478bd9Sstevel@tonic-gate (void) sprintf(gss_svc_name, "%s@%s", gssdata->uname,
5677c478bd9Sstevel@tonic-gate gssdata->inst);
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate stat = rpc_gss_secget(client, gss_svc_name,
5707c478bd9Sstevel@tonic-gate &gssdata->mechanism,
5717c478bd9Sstevel@tonic-gate gssdata->service,
5727c478bd9Sstevel@tonic-gate gssdata->qop,
5737c478bd9Sstevel@tonic-gate NULL, NULL,
5747c478bd9Sstevel@tonic-gate (caddr_t)secdata, cr, &auth);
5757c478bd9Sstevel@tonic-gate *ap = auth;
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate /* success */
5787c478bd9Sstevel@tonic-gate if (stat == 0)
5797c478bd9Sstevel@tonic-gate return (stat);
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate /*
5827c478bd9Sstevel@tonic-gate * let the caller retry if connection timedout
5837c478bd9Sstevel@tonic-gate * or reset.
5847c478bd9Sstevel@tonic-gate */
5857c478bd9Sstevel@tonic-gate if (stat == ETIMEDOUT || stat == ECONNRESET)
5867c478bd9Sstevel@tonic-gate return (stat);
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate /*
5897c478bd9Sstevel@tonic-gate * If AUTH_F_TRYNONE is on, try again
5907c478bd9Sstevel@tonic-gate * with AUTH_NONE. See bug 1180236.
5917c478bd9Sstevel@tonic-gate */
5927c478bd9Sstevel@tonic-gate if (secdata->flags & AUTH_F_TRYNONE) {
5937c478bd9Sstevel@tonic-gate authflavor = AUTH_NONE;
5947c478bd9Sstevel@tonic-gate continue;
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate RPCLOG(1, "sec_clnt_geth: rpc_gss_secget"
598b9238976Sth " failed with %d", stat);
5997c478bd9Sstevel@tonic-gate return (stat);
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate default:
6027c478bd9Sstevel@tonic-gate /*
6037c478bd9Sstevel@tonic-gate * auth create must have failed, try AUTH_NONE
6047c478bd9Sstevel@tonic-gate * (this relies on AUTH_NONE never failing)
6057c478bd9Sstevel@tonic-gate */
6067c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "sec_clnt_geth: unknown "
6077c478bd9Sstevel@tonic-gate "authflavor %d, trying AUTH_NONE", authflavor);
6087c478bd9Sstevel@tonic-gate authflavor = AUTH_NONE;
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate
6137c478bd9Sstevel@tonic-gate void
sec_clnt_freeh(AUTH * auth)6147c478bd9Sstevel@tonic-gate sec_clnt_freeh(AUTH *auth)
6157c478bd9Sstevel@tonic-gate {
6167c478bd9Sstevel@tonic-gate struct desauthent *da;
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate switch (auth->ah_cred.oa_flavor) {
6197c478bd9Sstevel@tonic-gate case AUTH_NONE: /* XXX: do real AUTH_NONE */
6207c478bd9Sstevel@tonic-gate case AUTH_UNIX:
6217c478bd9Sstevel@tonic-gate case AUTH_LOOPBACK:
6227c478bd9Sstevel@tonic-gate auth_destroy(auth); /* was overflow */
6237c478bd9Sstevel@tonic-gate break;
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate case AUTH_DES:
6267c478bd9Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
6277c478bd9Sstevel@tonic-gate if (desauthtab != NULL) {
628b9238976Sth for (da = desauthtab;
629b9238976Sth da < &desauthtab[clnt_authdes_cachesz]; da++) {
630b9238976Sth if (da->da_auth == auth) {
631b9238976Sth da->da_inuse = 0;
632b9238976Sth mutex_exit(&desauthtab_lock);
633b9238976Sth return;
634b9238976Sth }
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate }
6377c478bd9Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
6387c478bd9Sstevel@tonic-gate auth_destroy(auth); /* was overflow */
6397c478bd9Sstevel@tonic-gate break;
6407c478bd9Sstevel@tonic-gate
6417c478bd9Sstevel@tonic-gate case RPCSEC_GSS:
6427c478bd9Sstevel@tonic-gate (void) rpc_gss_secfree(auth);
6437c478bd9Sstevel@tonic-gate break;
6447c478bd9Sstevel@tonic-gate
6457c478bd9Sstevel@tonic-gate default:
6467c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "sec_clnt_freeh: unknown authflavor %d",
647b9238976Sth auth->ah_cred.oa_flavor);
6487c478bd9Sstevel@tonic-gate break;
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate
6527c478bd9Sstevel@tonic-gate /*
6537c478bd9Sstevel@tonic-gate * Revoke the authentication key in the given AUTH handle by setting
6547c478bd9Sstevel@tonic-gate * it to NULL. If newkey is true, then generate a new key instead of
6557c478bd9Sstevel@tonic-gate * nulling out the old one. This is necessary for AUTH_DES because
6567c478bd9Sstevel@tonic-gate * the new key will be used next time the user does a keylogin. If
6577c478bd9Sstevel@tonic-gate * the zero'd key is used as actual key, then it cannot be revoked
6587c478bd9Sstevel@tonic-gate * again!
6597c478bd9Sstevel@tonic-gate */
6607c478bd9Sstevel@tonic-gate void
revoke_key(AUTH * auth,int newkey)6617c478bd9Sstevel@tonic-gate revoke_key(AUTH *auth, int newkey)
6627c478bd9Sstevel@tonic-gate {
6637c478bd9Sstevel@tonic-gate if (auth == NULL)
6647c478bd9Sstevel@tonic-gate return;
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate if (newkey) {
6677c478bd9Sstevel@tonic-gate if (key_gendes(&auth->ah_key) != RPC_SUCCESS) {
6687c478bd9Sstevel@tonic-gate /* failed to get new key, munge the old one */
6697c478bd9Sstevel@tonic-gate auth->ah_key.key.high ^= auth->ah_key.key.low;
6707c478bd9Sstevel@tonic-gate auth->ah_key.key.low += auth->ah_key.key.high;
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate } else {
6737c478bd9Sstevel@tonic-gate /* null out old key */
6747c478bd9Sstevel@tonic-gate auth->ah_key.key.high = 0;
6757c478bd9Sstevel@tonic-gate auth->ah_key.key.low = 0;
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate /*
6807c478bd9Sstevel@tonic-gate * Revoke all rpc credentials (of the selected auth type) for the given uid
6817c478bd9Sstevel@tonic-gate * from the auth cache. Must be root to do this if the requested uid is not
6827c478bd9Sstevel@tonic-gate * the effective uid of the requestor.
6837c478bd9Sstevel@tonic-gate *
6847c478bd9Sstevel@tonic-gate * Called from nfssys() for backward compatibility, and also
6857c478bd9Sstevel@tonic-gate * called from krpc_sys().
6867c478bd9Sstevel@tonic-gate *
6877c478bd9Sstevel@tonic-gate * AUTH_DES does not refer to the "mechanism" information.
6887c478bd9Sstevel@tonic-gate * RPCSEC_GSS requires the "mechanism" input.
6897c478bd9Sstevel@tonic-gate * The input argument, mechanism, is a user-space address and needs
6907c478bd9Sstevel@tonic-gate * to be copied into the kernel address space.
6917c478bd9Sstevel@tonic-gate *
6927c478bd9Sstevel@tonic-gate * Returns error number.
6937c478bd9Sstevel@tonic-gate */
6947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6957c478bd9Sstevel@tonic-gate int
sec_clnt_revoke(int rpcflavor,uid_t uid,cred_t * cr,void * mechanism,model_t model)6967c478bd9Sstevel@tonic-gate sec_clnt_revoke(int rpcflavor, uid_t uid, cred_t *cr, void *mechanism,
6977c478bd9Sstevel@tonic-gate model_t model)
6987c478bd9Sstevel@tonic-gate {
6997c478bd9Sstevel@tonic-gate struct desauthent *da;
7007c478bd9Sstevel@tonic-gate int error = 0;
7017c478bd9Sstevel@tonic-gate zoneid_t zoneid = getzoneid();
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate if (uid != crgetuid(cr) && secpolicy_nfs(cr) != 0)
7047c478bd9Sstevel@tonic-gate return (EPERM);
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate switch (rpcflavor) {
7077c478bd9Sstevel@tonic-gate case AUTH_DES:
7087c478bd9Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
7097c478bd9Sstevel@tonic-gate if (desauthtab != NULL) {
710b9238976Sth for (da = desauthtab;
711b9238976Sth da < &desauthtab[clnt_authdes_cachesz]; da++) {
712b9238976Sth if (uid == da->da_uid &&
713b9238976Sth zoneid == da->da_zoneid)
714b9238976Sth revoke_key(da->da_auth, 1);
715b9238976Sth }
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
7187c478bd9Sstevel@tonic-gate return (0);
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate case RPCSEC_GSS: {
7217c478bd9Sstevel@tonic-gate rpc_gss_OID mech;
7227c478bd9Sstevel@tonic-gate caddr_t elements;
7237c478bd9Sstevel@tonic-gate
7247c478bd9Sstevel@tonic-gate if (!mechanism)
7257c478bd9Sstevel@tonic-gate return (EINVAL);
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate /* copyin the gss mechanism type */
7287c478bd9Sstevel@tonic-gate mech = kmem_alloc(sizeof (rpc_gss_OID_desc), KM_SLEEP);
7297c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
7307c478bd9Sstevel@tonic-gate if (model != DATAMODEL_NATIVE) {
7317c478bd9Sstevel@tonic-gate gss_OID_desc32 mech32;
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate if (copyin(mechanism, &mech32,
7347c478bd9Sstevel@tonic-gate sizeof (gss_OID_desc32))) {
7357c478bd9Sstevel@tonic-gate kmem_free(mech, sizeof (rpc_gss_OID_desc));
7367c478bd9Sstevel@tonic-gate return (EFAULT);
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate mech->length = mech32.length;
7397c478bd9Sstevel@tonic-gate mech->elements = (caddr_t)(uintptr_t)mech32.elements;
7407c478bd9Sstevel@tonic-gate } else
7417c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
7427c478bd9Sstevel@tonic-gate if (copyin(mechanism, mech, sizeof (rpc_gss_OID_desc))) {
7437c478bd9Sstevel@tonic-gate kmem_free(mech, sizeof (rpc_gss_OID_desc));
7447c478bd9Sstevel@tonic-gate return (EFAULT);
7457c478bd9Sstevel@tonic-gate }
7467c478bd9Sstevel@tonic-gate
747*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States if (mech->length < MINAUTHLEN ||
748*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States mech->length > MAXAUTHLEN) {
749*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States kmem_free(mech, sizeof (rpc_gss_OID_desc));
750*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States return (EINVAL);
751*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States }
752*52056d7bSM Pavan kumar - Sun Microsystems - Menlo Park United States
7537c478bd9Sstevel@tonic-gate elements = kmem_alloc(mech->length, KM_SLEEP);
7547c478bd9Sstevel@tonic-gate if (copyin(mech->elements, elements, mech->length)) {
7557c478bd9Sstevel@tonic-gate kmem_free(elements, mech->length);
7567c478bd9Sstevel@tonic-gate kmem_free(mech, sizeof (rpc_gss_OID_desc));
7577c478bd9Sstevel@tonic-gate return (EFAULT);
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate mech->elements = elements;
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate error = rpc_gss_revauth(uid, mech);
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate kmem_free(elements, mech->length);
7647c478bd9Sstevel@tonic-gate kmem_free(mech, sizeof (rpc_gss_OID_desc));
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate return (error);
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gate default:
7707c478bd9Sstevel@tonic-gate /* not an auth type with cached creds */
7717c478bd9Sstevel@tonic-gate return (EINVAL);
7727c478bd9Sstevel@tonic-gate }
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate /*
7767c478bd9Sstevel@tonic-gate * Since sec_data is the index for the client auth handles
7777c478bd9Sstevel@tonic-gate * cache table, whenever the sec_data is freed, the index needs
7787c478bd9Sstevel@tonic-gate * to be nulled.
7797c478bd9Sstevel@tonic-gate */
7807c478bd9Sstevel@tonic-gate void
purge_authtab(struct sec_data * secdata)7817c478bd9Sstevel@tonic-gate purge_authtab(struct sec_data *secdata)
7827c478bd9Sstevel@tonic-gate {
7837c478bd9Sstevel@tonic-gate struct desauthent *da;
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate switch (secdata->rpcflavor) {
7867c478bd9Sstevel@tonic-gate
7877c478bd9Sstevel@tonic-gate case AUTH_DES:
7887c478bd9Sstevel@tonic-gate mutex_enter(&desauthtab_lock);
7897c478bd9Sstevel@tonic-gate if (desauthtab != NULL) {
790b9238976Sth for (da = desauthtab;
791b9238976Sth da < &desauthtab[clnt_authdes_cachesz]; da++) {
792b9238976Sth if (da->da_data == secdata) {
793b9238976Sth da->da_data = NULL;
794b9238976Sth da->da_inuse = 0;
795b9238976Sth }
7967c478bd9Sstevel@tonic-gate }
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate mutex_exit(&desauthtab_lock);
7997c478bd9Sstevel@tonic-gate return;
8007c478bd9Sstevel@tonic-gate
8017c478bd9Sstevel@tonic-gate case RPCSEC_GSS:
8027c478bd9Sstevel@tonic-gate rpc_gss_secpurge((void *)secdata);
8037c478bd9Sstevel@tonic-gate return;
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate default:
8067c478bd9Sstevel@tonic-gate return;
8077c478bd9Sstevel@tonic-gate }
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate void
sec_subrinit(void)8117c478bd9Sstevel@tonic-gate sec_subrinit(void)
8127c478bd9Sstevel@tonic-gate {
8137c478bd9Sstevel@tonic-gate authkern_cache = kmem_cache_create("authkern_cache",
8147c478bd9Sstevel@tonic-gate sizeof (AUTH), 0, authkern_init, NULL, NULL, NULL, NULL, 0);
81533f285aeSVallish Vaidyeshwara authnone_cache = kmem_cache_create("authnone_cache",
81633f285aeSVallish Vaidyeshwara sizeof (AUTH), 0, authnone_init, NULL, NULL, NULL, NULL, 0);
8177c478bd9Sstevel@tonic-gate authloopback_cache = kmem_cache_create("authloopback_cache",
8187c478bd9Sstevel@tonic-gate sizeof (AUTH), 0, authloopback_init, NULL, NULL, NULL, NULL, 0);
8197c478bd9Sstevel@tonic-gate mutex_init(&desauthtab_lock, NULL, MUTEX_DEFAULT, NULL);
8207c478bd9Sstevel@tonic-gate
8217c478bd9Sstevel@tonic-gate /* RPC stuff */
8227c478bd9Sstevel@tonic-gate mutex_init(&authdes_ops_lock, NULL, MUTEX_DEFAULT, NULL);
8237c478bd9Sstevel@tonic-gate zone_key_create(&auth_zone_key, auth_zone_init, NULL, auth_zone_fini);
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate
8267c478bd9Sstevel@tonic-gate /*
8277c478bd9Sstevel@tonic-gate * Destroys the caches and mutexes previously allocated and initialized
8287c478bd9Sstevel@tonic-gate * in sec_subrinit().
8297c478bd9Sstevel@tonic-gate * This routine is called by _init() if mod_install() failed.
8307c478bd9Sstevel@tonic-gate */
8317c478bd9Sstevel@tonic-gate void
sec_subrfini(void)8327c478bd9Sstevel@tonic-gate sec_subrfini(void)
8337c478bd9Sstevel@tonic-gate {
8347c478bd9Sstevel@tonic-gate mutex_destroy(&desauthtab_lock);
8357c478bd9Sstevel@tonic-gate kmem_cache_destroy(authkern_cache);
83633f285aeSVallish Vaidyeshwara kmem_cache_destroy(authnone_cache);
8377c478bd9Sstevel@tonic-gate kmem_cache_destroy(authloopback_cache);
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate /* RPC stuff */
8407c478bd9Sstevel@tonic-gate mutex_destroy(&authdes_ops_lock);
8417c478bd9Sstevel@tonic-gate (void) zone_key_delete(auth_zone_key);
8427c478bd9Sstevel@tonic-gate }
843