4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * CDDL HEADER START
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The contents of this file are subject to the terms of the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Common Development and Distribution License (the "License").
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * You may not use this file except in compliance with the License.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * or http://www.opensolaris.org/os/licensing.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * See the License for the specific language governing permissions
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * and limitations under the License.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * When distributing Covered Code, include this CDDL HEADER in each
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If applicable, add the following below this CDDL HEADER, with the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * fields enclosed by brackets "[]" replaced with your own identifying
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * information: Portions Copyright [yyyy] [name of copyright owner]
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * CDDL HEADER END
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Use is subject to license terms.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Password Keychain storage mechanism.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/types.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/param.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/errno.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/sysmacros.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/uio.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/buf.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/modctl.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/open.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/file.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/kmem.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/conf.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/cmn_err.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/stat.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/ddi.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/sunddi.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/sunldi.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/policy.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/zone.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/pathname.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/mount.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/sdt.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <fs/fs_subr.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/devops.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/thread.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/mkdev.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/avl.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/avl_impl.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/u8_textprep.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_osdep.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_conn.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_subr.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_dev.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_pass.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The smb_ptd is a cache of Uid's, User names, passwords and domain names.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * It will be used for storing the password information for a user and will
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * be used to for connections without entering the pasword again if its
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * already keyed in by the user. Its a kind of Key-Chain mechanism
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * implemented by Apple folks.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Information stored in the nodes:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * UID: Uid of the person who initiated the login request.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ZoneID: ZoneID of the zone from where the login request is initiated.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Username: Username in the CIFS server.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Srvdom: Domain name/ Server name of the CIFS server.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Password: Password of the user.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * For more information, see smb_pass.h and sys/avl.h
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Information retrieved from the node.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Node/password information can only be retrived with a call
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * to smb_pkey_getpw(). Password never gets copied to the userspace.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * It will be copied to the Kernel data structure smbioc_ossn->ioc_password
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * when needed for doing the "Session Setup". All other calls will return
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * either a success or a failure.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowavl_tree_t smb_ptd; /* AVL password tree descriptor */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowunsigned int smb_list_len = 0; /* No. of elements in the tree. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowkmutex_t smb_ptd_lock; /* Mutex lock for controlled access */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint smb_pkey_check(smbioc_pk_t *pk, cred_t *cr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint smb_pkey_deluid(uid_t ioc_uid, cred_t *cr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This routine is called by AVL tree calls when they want to find a
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * node, find the next position in the tree to add or for deletion.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Compare nodes from the tree to find the actual node based on
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * uid/zoneid/username/domainname.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_pkey_cmp(const void *a, const void *b)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const smb_passid_t *pa = (smb_passid_t *)a;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const smb_passid_t *pb = (smb_passid_t *)b;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int duser, dsrv, error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(MUTEX_HELD(&smb_ptd_lock));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The nodes are added sorted on the uid/zoneid/domainname/username
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We will do this:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Compare uid's. The owner who stored the node gets access.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Then zoneid to check if the access is from the same zone.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Compare usernames.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If the above are same, then compare domain/server names.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (pa->uid < pb->uid)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (-1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (pa->uid > pb->uid)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (+1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (pa->zoneid < pb->zoneid)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (-1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (pa->zoneid > pb->zoneid)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (+1);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross dsrv = u8_strcmp(pa->srvdom, pb->srvdom, 0,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dsrv < 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (-1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (dsrv > 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (+1);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross duser = u8_strcmp(pa->username, pb->username, 0,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (duser < 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (-1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (duser > 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (+1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Initialization of the code that deals with uid and passwords.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_pkey_init()
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow avl_create(&smb_ptd,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_pkey_cmp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sizeof (smb_passid_t),
4bff34e37def8a90f9194d81bc345c52ba20086athurlow offsetof(smb_passid_t,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpnode));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_init(&smb_ptd_lock, NULL, MUTEX_DEFAULT, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Destroy the full AVL tree.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Called just before unload.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_pkey_fini()
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross (void) smb_pkey_deluid((uid_t)-1, kcred);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow avl_destroy(&smb_ptd);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_destroy(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Driver unload calls this to ask if we
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * have any stored passwords
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_pkey_idle()
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int n;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_enter(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow n = avl_numnodes(&smb_ptd);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_exit(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return ((n) ? EBUSY : 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Rossstatic void
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Rosssmb_pkey_delete(smb_passid_t *tmp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(MUTEX_HELD(&smb_ptd_lock));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow avl_remove(&smb_ptd, tmp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross strfree(tmp->srvdom);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross strfree(tmp->username);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(tmp, sizeof (*tmp));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Remove a node from the AVL tree identified by cpid.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_pkey_del(smbioc_pk_t *pk, cred_t *cr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow avl_index_t where;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_passid_t buf, *cpid, *tmp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uid_t uid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmp = &buf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uid = pk->pk_uid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (uid == (uid_t)-1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uid = crgetruid(cr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (secpolicy_smbfs_login(cr, uid))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EPERM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmp->uid = uid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmp->zoneid = getzoneid();
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmp->srvdom = pk->pk_dom;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmp->username = pk->pk_usr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_enter(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((cpid = (smb_passid_t *)avl_find(&smb_ptd,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmp, &where)) != NULL) {
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross smb_pkey_delete(cpid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_exit(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Delete the entries owned by a particular user
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * based on uid. We go through all the nodes and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * delete the nodes whereever the uid matches.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Also implements "delete all" when uid == -1.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * You must have privilege to use any uid other
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * than your real uid.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_pkey_deluid(uid_t ioc_uid, cred_t *cr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_passid_t *cpid, *tmp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (secpolicy_smbfs_login(cr, ioc_uid))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EPERM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_enter(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow for (tmp = avl_first(&smb_ptd); tmp != NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmp = cpid) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpid = AVL_NEXT(&smb_ptd, tmp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (ioc_uid == (uid_t)-1 ||
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ioc_uid == tmp->uid) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Delete the node.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross smb_pkey_delete(tmp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_exit(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Add entry or modify existing.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Check for existing entry..
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If present, delete.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Now, add the new entry.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_pkey_add(smbioc_pk_t *pk, cred_t *cr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow avl_tree_t *t = &smb_ptd;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow avl_index_t where;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_passid_t *tmp, *cpid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int ret;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uid_t uid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uid = pk->pk_uid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (uid == (uid_t)-1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uid = crgetruid(cr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (secpolicy_smbfs_login(cr, uid))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EPERM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpid = kmem_zalloc(sizeof (smb_passid_t), KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpid->uid = uid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpid->zoneid = getzoneid();
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cpid->srvdom = strdup(pk->pk_dom);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cpid->username = strdup(pk->pk_usr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bcopy(pk->pk_lmhash, cpid->lmhash, SMBIOC_HASH_SZ);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bcopy(pk->pk_nthash, cpid->nthash, SMBIOC_HASH_SZ);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX: Instead of calling smb_pkey_check here,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * should call avl_find directly, and hold the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * lock across: avl_find, avl_remove, avl_insert.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* If it already exists, delete it. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ret = smb_pkey_check(pk, cr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (ret == 0) {
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross (void) smb_pkey_del(pk, cr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_enter(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmp = (smb_passid_t *)avl_find(t, cpid, &where);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (tmp == NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow avl_insert(t, cpid, where);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross strfree(cpid->srvdom);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross strfree(cpid->username);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(cpid, sizeof (smb_passid_t));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_exit(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Determine if a node with uid,zoneid, uname & dname exists in the tree
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * given the information, and if found, return the hashes.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_pkey_check(smbioc_pk_t *pk, cred_t *cr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow avl_tree_t *t = &smb_ptd;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow avl_index_t where;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_passid_t *tmp, *cpid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error = ENOENT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uid_t uid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uid = pk->pk_uid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (uid == (uid_t)-1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uid = crgetruid(cr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (secpolicy_smbfs_login(cr, uid))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EPERM);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpid = kmem_alloc(sizeof (smb_passid_t), KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpid->uid = uid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpid->zoneid = getzoneid();
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpid->srvdom = pk->pk_dom;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cpid->username = pk->pk_usr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_enter(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmp = (smb_passid_t *)avl_find(t, cpid, &where);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_exit(&smb_ptd_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (tmp != NULL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bcopy(tmp->lmhash, pk->pk_lmhash, SMBIOC_HASH_SZ);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bcopy(tmp->nthash, pk->pk_nthash, SMBIOC_HASH_SZ);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross error = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(cpid, sizeof (smb_passid_t));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_pkey_ioctl(int cmd, intptr_t arg, int flags, cred_t *cr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smbioc_pk_t *pk;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross uid_t uid;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross pk = kmem_alloc(sizeof (*pk), KM_SLEEP);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross switch (cmd) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOC_PK_ADD:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOC_PK_DEL:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOC_PK_CHK:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ddi_copyin((void *)arg, pk,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sizeof (*pk), flags)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = EFAULT;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Make strlen (etc) on these safe. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross pk->pk_dom[SMBIOC_MAX_NAME-1] = '\0';
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross pk->pk_usr[SMBIOC_MAX_NAME-1] = '\0';
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross switch (cmd) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOC_PK_ADD:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_pkey_add(pk, cr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOC_PK_DEL:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_pkey_del(pk, cr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOC_PK_CHK:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_pkey_check(pk, cr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* This is just a hash now. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (void) ddi_copyout(pk, (void *)arg,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sizeof (*pk), flags);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOC_PK_DEL_OWNER:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross uid = crgetruid(cr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_pkey_deluid(uid, cr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOC_PK_DEL_EVERYONE:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross uid = (uid_t)-1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_pkey_deluid(uid, cr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross default:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = ENODEV;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross kmem_free(pk, sizeof (*pk));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}