14bff34e3Sthurlow /*
24bff34e3Sthurlow * CDDL HEADER START
34bff34e3Sthurlow *
44bff34e3Sthurlow * The contents of this file are subject to the terms of the
54bff34e3Sthurlow * Common Development and Distribution License (the "License").
64bff34e3Sthurlow * You may not use this file except in compliance with the License.
74bff34e3Sthurlow *
84bff34e3Sthurlow * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94bff34e3Sthurlow * or http://www.opensolaris.org/os/licensing.
104bff34e3Sthurlow * See the License for the specific language governing permissions
114bff34e3Sthurlow * and limitations under the License.
124bff34e3Sthurlow *
134bff34e3Sthurlow * When distributing Covered Code, include this CDDL HEADER in each
144bff34e3Sthurlow * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154bff34e3Sthurlow * If applicable, add the following below this CDDL HEADER, with the
164bff34e3Sthurlow * fields enclosed by brackets "[]" replaced with your own identifying
174bff34e3Sthurlow * information: Portions Copyright [yyyy] [name of copyright owner]
184bff34e3Sthurlow *
194bff34e3Sthurlow * CDDL HEADER END
204bff34e3Sthurlow */
214bff34e3Sthurlow
224bff34e3Sthurlow /*
23613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
244bff34e3Sthurlow * Use is subject to license terms.
254bff34e3Sthurlow */
264bff34e3Sthurlow
274bff34e3Sthurlow /*
284bff34e3Sthurlow * Password Keychain storage mechanism.
294bff34e3Sthurlow */
304bff34e3Sthurlow
314bff34e3Sthurlow #include <sys/types.h>
324bff34e3Sthurlow #include <sys/param.h>
334bff34e3Sthurlow #include <sys/errno.h>
344bff34e3Sthurlow #include <sys/sysmacros.h>
354bff34e3Sthurlow #include <sys/uio.h>
364bff34e3Sthurlow #include <sys/buf.h>
374bff34e3Sthurlow #include <sys/modctl.h>
384bff34e3Sthurlow #include <sys/open.h>
394bff34e3Sthurlow #include <sys/file.h>
404bff34e3Sthurlow #include <sys/kmem.h>
414bff34e3Sthurlow #include <sys/conf.h>
424bff34e3Sthurlow #include <sys/cmn_err.h>
434bff34e3Sthurlow #include <sys/stat.h>
444bff34e3Sthurlow #include <sys/ddi.h>
454bff34e3Sthurlow #include <sys/sunddi.h>
464bff34e3Sthurlow #include <sys/sunldi.h>
474bff34e3Sthurlow #include <sys/policy.h>
484bff34e3Sthurlow #include <sys/zone.h>
494bff34e3Sthurlow #include <sys/pathname.h>
504bff34e3Sthurlow #include <sys/mount.h>
514bff34e3Sthurlow #include <sys/sdt.h>
524bff34e3Sthurlow #include <fs/fs_subr.h>
534bff34e3Sthurlow #include <sys/devops.h>
544bff34e3Sthurlow #include <sys/thread.h>
554bff34e3Sthurlow #include <sys/mkdev.h>
564bff34e3Sthurlow #include <sys/avl.h>
574bff34e3Sthurlow #include <sys/avl_impl.h>
58613a2f6bSGordon Ross #include <sys/u8_textprep.h>
594bff34e3Sthurlow
604bff34e3Sthurlow #include <netsmb/smb_osdep.h>
614bff34e3Sthurlow
624bff34e3Sthurlow #include <netsmb/smb.h>
634bff34e3Sthurlow #include <netsmb/smb_conn.h>
644bff34e3Sthurlow #include <netsmb/smb_subr.h>
654bff34e3Sthurlow #include <netsmb/smb_dev.h>
664bff34e3Sthurlow #include <netsmb/smb_pass.h>
674bff34e3Sthurlow
684bff34e3Sthurlow /*
694bff34e3Sthurlow * The smb_ptd is a cache of Uid's, User names, passwords and domain names.
704bff34e3Sthurlow * It will be used for storing the password information for a user and will
714bff34e3Sthurlow * be used to for connections without entering the pasword again if its
724bff34e3Sthurlow * already keyed in by the user. Its a kind of Key-Chain mechanism
734bff34e3Sthurlow * implemented by Apple folks.
744bff34e3Sthurlow */
754bff34e3Sthurlow
764bff34e3Sthurlow /*
774bff34e3Sthurlow * Information stored in the nodes:
784bff34e3Sthurlow * UID: Uid of the person who initiated the login request.
794bff34e3Sthurlow * ZoneID: ZoneID of the zone from where the login request is initiated.
804bff34e3Sthurlow * Username: Username in the CIFS server.
814bff34e3Sthurlow * Srvdom: Domain name/ Server name of the CIFS server.
824bff34e3Sthurlow * Password: Password of the user.
834bff34e3Sthurlow * For more information, see smb_pass.h and sys/avl.h
844bff34e3Sthurlow */
854bff34e3Sthurlow
864bff34e3Sthurlow /*
874bff34e3Sthurlow * Information retrieved from the node.
884bff34e3Sthurlow * Node/password information can only be retrived with a call
894bff34e3Sthurlow * to smb_pkey_getpw(). Password never gets copied to the userspace.
904bff34e3Sthurlow * It will be copied to the Kernel data structure smbioc_ossn->ioc_password
914bff34e3Sthurlow * when needed for doing the "Session Setup". All other calls will return
924bff34e3Sthurlow * either a success or a failure.
934bff34e3Sthurlow */
944bff34e3Sthurlow
954bff34e3Sthurlow avl_tree_t smb_ptd; /* AVL password tree descriptor */
964bff34e3Sthurlow unsigned int smb_list_len = 0; /* No. of elements in the tree. */
974bff34e3Sthurlow kmutex_t smb_ptd_lock; /* Mutex lock for controlled access */
984bff34e3Sthurlow
99613a2f6bSGordon Ross int smb_pkey_check(smbioc_pk_t *pk, cred_t *cr);
100613a2f6bSGordon Ross int smb_pkey_deluid(uid_t ioc_uid, cred_t *cr);
101613a2f6bSGordon Ross
1024bff34e3Sthurlow /*
1034bff34e3Sthurlow * This routine is called by AVL tree calls when they want to find a
1044bff34e3Sthurlow * node, find the next position in the tree to add or for deletion.
1054bff34e3Sthurlow * Compare nodes from the tree to find the actual node based on
1064bff34e3Sthurlow * uid/zoneid/username/domainname.
1074bff34e3Sthurlow */
1084bff34e3Sthurlow int
smb_pkey_cmp(const void * a,const void * b)1094bff34e3Sthurlow smb_pkey_cmp(const void *a, const void *b)
1104bff34e3Sthurlow {
1114bff34e3Sthurlow const smb_passid_t *pa = (smb_passid_t *)a;
1124bff34e3Sthurlow const smb_passid_t *pb = (smb_passid_t *)b;
113613a2f6bSGordon Ross int duser, dsrv, error;
1144bff34e3Sthurlow
1154bff34e3Sthurlow ASSERT(MUTEX_HELD(&smb_ptd_lock));
1164bff34e3Sthurlow
1174bff34e3Sthurlow /*
1184bff34e3Sthurlow * The nodes are added sorted on the uid/zoneid/domainname/username
1194bff34e3Sthurlow * We will do this:
1204bff34e3Sthurlow * Compare uid's. The owner who stored the node gets access.
1214bff34e3Sthurlow * Then zoneid to check if the access is from the same zone.
1224bff34e3Sthurlow * Compare usernames.
1234bff34e3Sthurlow * If the above are same, then compare domain/server names.
1244bff34e3Sthurlow */
1254bff34e3Sthurlow if (pa->uid < pb->uid)
1264bff34e3Sthurlow return (-1);
1274bff34e3Sthurlow if (pa->uid > pb->uid)
1284bff34e3Sthurlow return (+1);
1294bff34e3Sthurlow if (pa->zoneid < pb->zoneid)
1304bff34e3Sthurlow return (-1);
1314bff34e3Sthurlow if (pa->zoneid > pb->zoneid)
1324bff34e3Sthurlow return (+1);
133613a2f6bSGordon Ross dsrv = u8_strcmp(pa->srvdom, pb->srvdom, 0,
134613a2f6bSGordon Ross U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error);
1354bff34e3Sthurlow if (dsrv < 0)
1364bff34e3Sthurlow return (-1);
1374bff34e3Sthurlow if (dsrv > 0)
1384bff34e3Sthurlow return (+1);
139613a2f6bSGordon Ross duser = u8_strcmp(pa->username, pb->username, 0,
140613a2f6bSGordon Ross U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error);
1414bff34e3Sthurlow if (duser < 0)
1424bff34e3Sthurlow return (-1);
1434bff34e3Sthurlow if (duser > 0)
1444bff34e3Sthurlow return (+1);
1454bff34e3Sthurlow return (0);
1464bff34e3Sthurlow }
1474bff34e3Sthurlow
1484bff34e3Sthurlow /*
1494bff34e3Sthurlow * Initialization of the code that deals with uid and passwords.
1504bff34e3Sthurlow */
1514bff34e3Sthurlow void
smb_pkey_init()1524bff34e3Sthurlow smb_pkey_init()
1534bff34e3Sthurlow {
1544bff34e3Sthurlow avl_create(&smb_ptd,
1554bff34e3Sthurlow smb_pkey_cmp,
1564bff34e3Sthurlow sizeof (smb_passid_t),
1574bff34e3Sthurlow offsetof(smb_passid_t,
1584bff34e3Sthurlow cpnode));
1594bff34e3Sthurlow mutex_init(&smb_ptd_lock, NULL, MUTEX_DEFAULT, NULL);
1604bff34e3Sthurlow }
1614bff34e3Sthurlow
1624bff34e3Sthurlow /*
1634bff34e3Sthurlow * Destroy the full AVL tree.
164613a2f6bSGordon Ross * Called just before unload.
1654bff34e3Sthurlow */
1664bff34e3Sthurlow void
smb_pkey_fini()1674bff34e3Sthurlow smb_pkey_fini()
1684bff34e3Sthurlow {
169*02d09e03SGordon Ross (void) smb_pkey_deluid((uid_t)-1, kcred);
1704bff34e3Sthurlow avl_destroy(&smb_ptd);
1714bff34e3Sthurlow mutex_destroy(&smb_ptd_lock);
1724bff34e3Sthurlow }
1734bff34e3Sthurlow
1744bff34e3Sthurlow /*
1754bff34e3Sthurlow * Driver unload calls this to ask if we
1764bff34e3Sthurlow * have any stored passwords
1774bff34e3Sthurlow */
1784bff34e3Sthurlow int
smb_pkey_idle()1794bff34e3Sthurlow smb_pkey_idle()
1804bff34e3Sthurlow {
1814bff34e3Sthurlow int n;
1824bff34e3Sthurlow
1834bff34e3Sthurlow mutex_enter(&smb_ptd_lock);
1844bff34e3Sthurlow n = avl_numnodes(&smb_ptd);
1854bff34e3Sthurlow mutex_exit(&smb_ptd_lock);
1864bff34e3Sthurlow
1874bff34e3Sthurlow return ((n) ? EBUSY : 0);
1884bff34e3Sthurlow }
1894bff34e3Sthurlow
190*02d09e03SGordon Ross static void
smb_pkey_delete(smb_passid_t * tmp)191*02d09e03SGordon Ross smb_pkey_delete(smb_passid_t *tmp)
1924bff34e3Sthurlow {
1934bff34e3Sthurlow ASSERT(MUTEX_HELD(&smb_ptd_lock));
1944bff34e3Sthurlow avl_remove(&smb_ptd, tmp);
195613a2f6bSGordon Ross strfree(tmp->srvdom);
196613a2f6bSGordon Ross strfree(tmp->username);
1974bff34e3Sthurlow kmem_free(tmp, sizeof (*tmp));
1984bff34e3Sthurlow }
1994bff34e3Sthurlow
2004bff34e3Sthurlow
2014bff34e3Sthurlow /*
2024bff34e3Sthurlow * Remove a node from the AVL tree identified by cpid.
2034bff34e3Sthurlow */
2044bff34e3Sthurlow int
smb_pkey_del(smbioc_pk_t * pk,cred_t * cr)2054bff34e3Sthurlow smb_pkey_del(smbioc_pk_t *pk, cred_t *cr)
2064bff34e3Sthurlow {
2074bff34e3Sthurlow avl_index_t where;
2084bff34e3Sthurlow smb_passid_t buf, *cpid, *tmp;
2094bff34e3Sthurlow uid_t uid;
2104bff34e3Sthurlow
2114bff34e3Sthurlow tmp = &buf;
2124bff34e3Sthurlow uid = pk->pk_uid;
2134bff34e3Sthurlow if (uid == (uid_t)-1)
2144bff34e3Sthurlow uid = crgetruid(cr);
2154bff34e3Sthurlow else {
2164bff34e3Sthurlow if (secpolicy_smbfs_login(cr, uid))
2174bff34e3Sthurlow return (EPERM);
2184bff34e3Sthurlow }
2194bff34e3Sthurlow tmp->uid = uid;
2204bff34e3Sthurlow tmp->zoneid = getzoneid();
2214bff34e3Sthurlow tmp->srvdom = pk->pk_dom;
2224bff34e3Sthurlow tmp->username = pk->pk_usr;
2234bff34e3Sthurlow
2244bff34e3Sthurlow mutex_enter(&smb_ptd_lock);
2254bff34e3Sthurlow if ((cpid = (smb_passid_t *)avl_find(&smb_ptd,
2264bff34e3Sthurlow tmp, &where)) != NULL) {
227*02d09e03SGordon Ross smb_pkey_delete(cpid);
2284bff34e3Sthurlow }
2294bff34e3Sthurlow mutex_exit(&smb_ptd_lock);
2304bff34e3Sthurlow
2314bff34e3Sthurlow return (0);
2324bff34e3Sthurlow }
2334bff34e3Sthurlow
2344bff34e3Sthurlow /*
2354bff34e3Sthurlow * Delete the entries owned by a particular user
2364bff34e3Sthurlow * based on uid. We go through all the nodes and
2374bff34e3Sthurlow * delete the nodes whereever the uid matches.
2384bff34e3Sthurlow *
2394bff34e3Sthurlow * Also implements "delete all" when uid == -1.
2404bff34e3Sthurlow *
2414bff34e3Sthurlow * You must have privilege to use any uid other
2424bff34e3Sthurlow * than your real uid.
2434bff34e3Sthurlow */
2444bff34e3Sthurlow int
smb_pkey_deluid(uid_t ioc_uid,cred_t * cr)2454bff34e3Sthurlow smb_pkey_deluid(uid_t ioc_uid, cred_t *cr)
2464bff34e3Sthurlow {
2474bff34e3Sthurlow smb_passid_t *cpid, *tmp;
2484bff34e3Sthurlow
2494bff34e3Sthurlow if (secpolicy_smbfs_login(cr, ioc_uid))
2504bff34e3Sthurlow return (EPERM);
2514bff34e3Sthurlow
2524bff34e3Sthurlow mutex_enter(&smb_ptd_lock);
2534bff34e3Sthurlow for (tmp = avl_first(&smb_ptd); tmp != NULL;
2544bff34e3Sthurlow tmp = cpid) {
2554bff34e3Sthurlow cpid = AVL_NEXT(&smb_ptd, tmp);
2564bff34e3Sthurlow if (ioc_uid == (uid_t)-1 ||
2574bff34e3Sthurlow ioc_uid == tmp->uid) {
2584bff34e3Sthurlow /*
2594bff34e3Sthurlow * Delete the node.
2604bff34e3Sthurlow */
261*02d09e03SGordon Ross smb_pkey_delete(tmp);
2624bff34e3Sthurlow }
2634bff34e3Sthurlow }
2644bff34e3Sthurlow mutex_exit(&smb_ptd_lock);
2654bff34e3Sthurlow
2664bff34e3Sthurlow return (0);
2674bff34e3Sthurlow }
2684bff34e3Sthurlow
2694bff34e3Sthurlow /*
2704bff34e3Sthurlow * Add entry or modify existing.
2714bff34e3Sthurlow * Check for existing entry..
2724bff34e3Sthurlow * If present, delete.
2734bff34e3Sthurlow * Now, add the new entry.
2744bff34e3Sthurlow */
2754bff34e3Sthurlow int
smb_pkey_add(smbioc_pk_t * pk,cred_t * cr)2764bff34e3Sthurlow smb_pkey_add(smbioc_pk_t *pk, cred_t *cr)
2774bff34e3Sthurlow {
2784bff34e3Sthurlow avl_tree_t *t = &smb_ptd;
2794bff34e3Sthurlow avl_index_t where;
2804bff34e3Sthurlow smb_passid_t *tmp, *cpid;
2814bff34e3Sthurlow int ret;
2824bff34e3Sthurlow uid_t uid;
2834bff34e3Sthurlow
2844bff34e3Sthurlow uid = pk->pk_uid;
2854bff34e3Sthurlow if (uid == (uid_t)-1)
2864bff34e3Sthurlow uid = crgetruid(cr);
2874bff34e3Sthurlow else {
2884bff34e3Sthurlow if (secpolicy_smbfs_login(cr, uid))
2894bff34e3Sthurlow return (EPERM);
2904bff34e3Sthurlow }
2914bff34e3Sthurlow cpid = kmem_zalloc(sizeof (smb_passid_t), KM_SLEEP);
2924bff34e3Sthurlow cpid->uid = uid;
2934bff34e3Sthurlow cpid->zoneid = getzoneid();
294613a2f6bSGordon Ross cpid->srvdom = strdup(pk->pk_dom);
295613a2f6bSGordon Ross cpid->username = strdup(pk->pk_usr);
296613a2f6bSGordon Ross bcopy(pk->pk_lmhash, cpid->lmhash, SMBIOC_HASH_SZ);
297613a2f6bSGordon Ross bcopy(pk->pk_nthash, cpid->nthash, SMBIOC_HASH_SZ);
2984bff34e3Sthurlow
2994bff34e3Sthurlow /*
3004bff34e3Sthurlow * XXX: Instead of calling smb_pkey_check here,
3014bff34e3Sthurlow * should call avl_find directly, and hold the
3024bff34e3Sthurlow * lock across: avl_find, avl_remove, avl_insert.
3034bff34e3Sthurlow */
3044bff34e3Sthurlow
3054bff34e3Sthurlow /* If it already exists, delete it. */
3064bff34e3Sthurlow ret = smb_pkey_check(pk, cr);
3074bff34e3Sthurlow if (ret == 0) {
308*02d09e03SGordon Ross (void) smb_pkey_del(pk, cr);
3094bff34e3Sthurlow }
3104bff34e3Sthurlow
3114bff34e3Sthurlow mutex_enter(&smb_ptd_lock);
3124bff34e3Sthurlow tmp = (smb_passid_t *)avl_find(t, cpid, &where);
3134bff34e3Sthurlow if (tmp == NULL) {
3144bff34e3Sthurlow avl_insert(t, cpid, where);
3154bff34e3Sthurlow } else {
316613a2f6bSGordon Ross strfree(cpid->srvdom);
317613a2f6bSGordon Ross strfree(cpid->username);
3184bff34e3Sthurlow kmem_free(cpid, sizeof (smb_passid_t));
3194bff34e3Sthurlow }
3204bff34e3Sthurlow mutex_exit(&smb_ptd_lock);
3214bff34e3Sthurlow
3224bff34e3Sthurlow return (0);
3234bff34e3Sthurlow }
3244bff34e3Sthurlow
3254bff34e3Sthurlow /*
3264bff34e3Sthurlow * Determine if a node with uid,zoneid, uname & dname exists in the tree
327613a2f6bSGordon Ross * given the information, and if found, return the hashes.
3284bff34e3Sthurlow */
3294bff34e3Sthurlow int
smb_pkey_check(smbioc_pk_t * pk,cred_t * cr)3304bff34e3Sthurlow smb_pkey_check(smbioc_pk_t *pk, cred_t *cr)
3314bff34e3Sthurlow {
3324bff34e3Sthurlow avl_tree_t *t = &smb_ptd;
3334bff34e3Sthurlow avl_index_t where;
3344bff34e3Sthurlow smb_passid_t *tmp, *cpid;
3354bff34e3Sthurlow int error = ENOENT;
3364bff34e3Sthurlow uid_t uid;
3374bff34e3Sthurlow
3384bff34e3Sthurlow uid = pk->pk_uid;
3394bff34e3Sthurlow if (uid == (uid_t)-1)
3404bff34e3Sthurlow uid = crgetruid(cr);
3414bff34e3Sthurlow else {
3424bff34e3Sthurlow if (secpolicy_smbfs_login(cr, uid))
3434bff34e3Sthurlow return (EPERM);
3444bff34e3Sthurlow }
3454bff34e3Sthurlow cpid = kmem_alloc(sizeof (smb_passid_t), KM_SLEEP);
3464bff34e3Sthurlow cpid->uid = uid;
3474bff34e3Sthurlow cpid->zoneid = getzoneid();
3484bff34e3Sthurlow cpid->srvdom = pk->pk_dom;
3494bff34e3Sthurlow cpid->username = pk->pk_usr;
3504bff34e3Sthurlow
3514bff34e3Sthurlow mutex_enter(&smb_ptd_lock);
3524bff34e3Sthurlow tmp = (smb_passid_t *)avl_find(t, cpid, &where);
3534bff34e3Sthurlow mutex_exit(&smb_ptd_lock);
3544bff34e3Sthurlow
355613a2f6bSGordon Ross if (tmp != NULL) {
356613a2f6bSGordon Ross bcopy(tmp->lmhash, pk->pk_lmhash, SMBIOC_HASH_SZ);
357613a2f6bSGordon Ross bcopy(tmp->nthash, pk->pk_nthash, SMBIOC_HASH_SZ);
358613a2f6bSGordon Ross error = 0;
359613a2f6bSGordon Ross }
360613a2f6bSGordon Ross
3614bff34e3Sthurlow kmem_free(cpid, sizeof (smb_passid_t));
3624bff34e3Sthurlow return (error);
3634bff34e3Sthurlow }
3644bff34e3Sthurlow
365613a2f6bSGordon Ross
3664bff34e3Sthurlow int
smb_pkey_ioctl(int cmd,intptr_t arg,int flags,cred_t * cr)367613a2f6bSGordon Ross smb_pkey_ioctl(int cmd, intptr_t arg, int flags, cred_t *cr)
3684bff34e3Sthurlow {
369613a2f6bSGordon Ross smbioc_pk_t *pk;
370613a2f6bSGordon Ross uid_t uid;
371613a2f6bSGordon Ross int err = 0;
372613a2f6bSGordon Ross
373613a2f6bSGordon Ross pk = kmem_alloc(sizeof (*pk), KM_SLEEP);
374613a2f6bSGordon Ross
375613a2f6bSGordon Ross switch (cmd) {
376613a2f6bSGordon Ross case SMBIOC_PK_ADD:
377613a2f6bSGordon Ross case SMBIOC_PK_DEL:
378613a2f6bSGordon Ross case SMBIOC_PK_CHK:
379613a2f6bSGordon Ross if (ddi_copyin((void *)arg, pk,
380613a2f6bSGordon Ross sizeof (*pk), flags)) {
381613a2f6bSGordon Ross err = EFAULT;
382613a2f6bSGordon Ross goto out;
383613a2f6bSGordon Ross }
384613a2f6bSGordon Ross /* Make strlen (etc) on these safe. */
385613a2f6bSGordon Ross pk->pk_dom[SMBIOC_MAX_NAME-1] = '\0';
386613a2f6bSGordon Ross pk->pk_usr[SMBIOC_MAX_NAME-1] = '\0';
387613a2f6bSGordon Ross break;
388613a2f6bSGordon Ross }
3894bff34e3Sthurlow
390613a2f6bSGordon Ross switch (cmd) {
391613a2f6bSGordon Ross case SMBIOC_PK_ADD:
392613a2f6bSGordon Ross err = smb_pkey_add(pk, cr);
393613a2f6bSGordon Ross break;
3944bff34e3Sthurlow
395613a2f6bSGordon Ross case SMBIOC_PK_DEL:
396613a2f6bSGordon Ross err = smb_pkey_del(pk, cr);
397613a2f6bSGordon Ross break;
3984bff34e3Sthurlow
399613a2f6bSGordon Ross case SMBIOC_PK_CHK:
400613a2f6bSGordon Ross err = smb_pkey_check(pk, cr);
401613a2f6bSGordon Ross /* This is just a hash now. */
402613a2f6bSGordon Ross (void) ddi_copyout(pk, (void *)arg,
403613a2f6bSGordon Ross sizeof (*pk), flags);
404613a2f6bSGordon Ross break;
405613a2f6bSGordon Ross
406613a2f6bSGordon Ross case SMBIOC_PK_DEL_OWNER:
407613a2f6bSGordon Ross uid = crgetruid(cr);
408613a2f6bSGordon Ross err = smb_pkey_deluid(uid, cr);
409613a2f6bSGordon Ross break;
410613a2f6bSGordon Ross
411613a2f6bSGordon Ross case SMBIOC_PK_DEL_EVERYONE:
412613a2f6bSGordon Ross uid = (uid_t)-1;
413613a2f6bSGordon Ross err = smb_pkey_deluid(uid, cr);
414613a2f6bSGordon Ross break;
415613a2f6bSGordon Ross
416613a2f6bSGordon Ross default:
417613a2f6bSGordon Ross err = ENODEV;
4184bff34e3Sthurlow }
4194bff34e3Sthurlow
420613a2f6bSGordon Ross out:
421613a2f6bSGordon Ross kmem_free(pk, sizeof (*pk));
422613a2f6bSGordon Ross return (err);
4234bff34e3Sthurlow }
424