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