1*4bff34e3Sthurlow /*
2*4bff34e3Sthurlow  * CDDL HEADER START
3*4bff34e3Sthurlow  *
4*4bff34e3Sthurlow  * The contents of this file are subject to the terms of the
5*4bff34e3Sthurlow  * Common Development and Distribution License (the "License").
6*4bff34e3Sthurlow  * You may not use this file except in compliance with the License.
7*4bff34e3Sthurlow  *
8*4bff34e3Sthurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4bff34e3Sthurlow  * or http://www.opensolaris.org/os/licensing.
10*4bff34e3Sthurlow  * See the License for the specific language governing permissions
11*4bff34e3Sthurlow  * and limitations under the License.
12*4bff34e3Sthurlow  *
13*4bff34e3Sthurlow  * When distributing Covered Code, include this CDDL HEADER in each
14*4bff34e3Sthurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4bff34e3Sthurlow  * If applicable, add the following below this CDDL HEADER, with the
16*4bff34e3Sthurlow  * fields enclosed by brackets "[]" replaced with your own identifying
17*4bff34e3Sthurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4bff34e3Sthurlow  *
19*4bff34e3Sthurlow  * CDDL HEADER END
20*4bff34e3Sthurlow  */
21*4bff34e3Sthurlow 
22*4bff34e3Sthurlow /*
23*4bff34e3Sthurlow  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*4bff34e3Sthurlow  * Use is subject to license terms.
25*4bff34e3Sthurlow  */
26*4bff34e3Sthurlow 
27*4bff34e3Sthurlow #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*4bff34e3Sthurlow 
29*4bff34e3Sthurlow /*
30*4bff34e3Sthurlow  * Password Keychain storage mechanism.
31*4bff34e3Sthurlow  */
32*4bff34e3Sthurlow 
33*4bff34e3Sthurlow #include <sys/types.h>
34*4bff34e3Sthurlow #include <sys/param.h>
35*4bff34e3Sthurlow #include <sys/errno.h>
36*4bff34e3Sthurlow #include <sys/sysmacros.h>
37*4bff34e3Sthurlow #include <sys/uio.h>
38*4bff34e3Sthurlow #include <sys/buf.h>
39*4bff34e3Sthurlow #include <sys/modctl.h>
40*4bff34e3Sthurlow #include <sys/open.h>
41*4bff34e3Sthurlow #include <sys/file.h>
42*4bff34e3Sthurlow #include <sys/kmem.h>
43*4bff34e3Sthurlow #include <sys/conf.h>
44*4bff34e3Sthurlow #include <sys/cmn_err.h>
45*4bff34e3Sthurlow #include <sys/stat.h>
46*4bff34e3Sthurlow #include <sys/ddi.h>
47*4bff34e3Sthurlow #include <sys/sunddi.h>
48*4bff34e3Sthurlow #include <sys/sunldi.h>
49*4bff34e3Sthurlow #include <sys/policy.h>
50*4bff34e3Sthurlow #include <sys/zone.h>
51*4bff34e3Sthurlow #include <sys/pathname.h>
52*4bff34e3Sthurlow #include <sys/mount.h>
53*4bff34e3Sthurlow #include <sys/sdt.h>
54*4bff34e3Sthurlow #include <fs/fs_subr.h>
55*4bff34e3Sthurlow #include <sys/devops.h>
56*4bff34e3Sthurlow #include <sys/thread.h>
57*4bff34e3Sthurlow #include <sys/mkdev.h>
58*4bff34e3Sthurlow #include <sys/avl.h>
59*4bff34e3Sthurlow #include <sys/avl_impl.h>
60*4bff34e3Sthurlow 
61*4bff34e3Sthurlow #include <netsmb/smb_osdep.h>
62*4bff34e3Sthurlow 
63*4bff34e3Sthurlow #include <netsmb/smb.h>
64*4bff34e3Sthurlow #include <netsmb/smb_conn.h>
65*4bff34e3Sthurlow #include <netsmb/smb_subr.h>
66*4bff34e3Sthurlow #include <netsmb/smb_dev.h>
67*4bff34e3Sthurlow #include <netsmb/smb_pass.h>
68*4bff34e3Sthurlow 
69*4bff34e3Sthurlow /*
70*4bff34e3Sthurlow  * The smb_ptd is a cache of Uid's, User names, passwords and domain names.
71*4bff34e3Sthurlow  * It will be used for storing the password information for a user and will
72*4bff34e3Sthurlow  * be used to for connections without entering the pasword again if its
73*4bff34e3Sthurlow  * already keyed in by the user. Its a kind of Key-Chain mechanism
74*4bff34e3Sthurlow  * implemented by Apple folks.
75*4bff34e3Sthurlow  */
76*4bff34e3Sthurlow 
77*4bff34e3Sthurlow /*
78*4bff34e3Sthurlow  * Information stored in the nodes:
79*4bff34e3Sthurlow  * UID:  Uid of the person who initiated the login request.
80*4bff34e3Sthurlow  * ZoneID: ZoneID of the zone from where the login request is initiated.
81*4bff34e3Sthurlow  * Username: Username in the CIFS server.
82*4bff34e3Sthurlow  * Srvdom: Domain name/ Server name of the CIFS server.
83*4bff34e3Sthurlow  * Password: Password of the user.
84*4bff34e3Sthurlow  * For more information, see smb_pass.h and sys/avl.h
85*4bff34e3Sthurlow  */
86*4bff34e3Sthurlow 
87*4bff34e3Sthurlow /*
88*4bff34e3Sthurlow  * Information retrieved from the node.
89*4bff34e3Sthurlow  * Node/password information can only be retrived with a call
90*4bff34e3Sthurlow  * to smb_pkey_getpw(). Password never gets copied to the userspace.
91*4bff34e3Sthurlow  * It will be copied to the Kernel data structure smbioc_ossn->ioc_password
92*4bff34e3Sthurlow  * when needed for doing the "Session Setup". All other calls will return
93*4bff34e3Sthurlow  * either a success or a failure.
94*4bff34e3Sthurlow  */
95*4bff34e3Sthurlow 
96*4bff34e3Sthurlow avl_tree_t smb_ptd; /* AVL password tree descriptor */
97*4bff34e3Sthurlow unsigned int smb_list_len = 0;	/* No. of elements in the tree. */
98*4bff34e3Sthurlow kmutex_t smb_ptd_lock; 	/* Mutex lock for controlled access */
99*4bff34e3Sthurlow 
100*4bff34e3Sthurlow /*
101*4bff34e3Sthurlow  * This routine is called by AVL tree calls when they want to find a
102*4bff34e3Sthurlow  * node, find the next position in the tree to add or for deletion.
103*4bff34e3Sthurlow  * Compare nodes from the tree to find the actual node based on
104*4bff34e3Sthurlow  * uid/zoneid/username/domainname.
105*4bff34e3Sthurlow  */
106*4bff34e3Sthurlow int
107*4bff34e3Sthurlow smb_pkey_cmp(const void *a, const void *b)
108*4bff34e3Sthurlow {
109*4bff34e3Sthurlow 	const smb_passid_t *pa = (smb_passid_t *)a;
110*4bff34e3Sthurlow 	const smb_passid_t *pb = (smb_passid_t *)b;
111*4bff34e3Sthurlow 	int duser, dsrv;
112*4bff34e3Sthurlow 
113*4bff34e3Sthurlow 	ASSERT(MUTEX_HELD(&smb_ptd_lock));
114*4bff34e3Sthurlow 
115*4bff34e3Sthurlow 	/*
116*4bff34e3Sthurlow 	 * The nodes are added sorted on the uid/zoneid/domainname/username
117*4bff34e3Sthurlow 	 * We will do this:
118*4bff34e3Sthurlow 	 * Compare uid's. The owner who stored the node gets access.
119*4bff34e3Sthurlow 	 * Then zoneid to check if the access is from the same zone.
120*4bff34e3Sthurlow 	 * Compare usernames.
121*4bff34e3Sthurlow 	 * If the above are same, then compare domain/server names.
122*4bff34e3Sthurlow 	 */
123*4bff34e3Sthurlow 	if (pa->uid < pb->uid)
124*4bff34e3Sthurlow 		return (-1);
125*4bff34e3Sthurlow 	if (pa->uid > pb->uid)
126*4bff34e3Sthurlow 		return (+1);
127*4bff34e3Sthurlow 	if (pa->zoneid < pb->zoneid)
128*4bff34e3Sthurlow 		return (-1);
129*4bff34e3Sthurlow 	if (pa->zoneid > pb->zoneid)
130*4bff34e3Sthurlow 		return (+1);
131*4bff34e3Sthurlow 	dsrv = strcasecmp(pa->srvdom, pb->srvdom);
132*4bff34e3Sthurlow 	if (dsrv < 0)
133*4bff34e3Sthurlow 		return (-1);
134*4bff34e3Sthurlow 	if (dsrv > 0)
135*4bff34e3Sthurlow 		return (+1);
136*4bff34e3Sthurlow 	duser = strcasecmp(pa->username, pb->username);
137*4bff34e3Sthurlow 	if (duser < 0)
138*4bff34e3Sthurlow 		return (-1);
139*4bff34e3Sthurlow 	if (duser > 0)
140*4bff34e3Sthurlow 		return (+1);
141*4bff34e3Sthurlow 	return (0);
142*4bff34e3Sthurlow }
143*4bff34e3Sthurlow 
144*4bff34e3Sthurlow /*
145*4bff34e3Sthurlow  * Initialization of the code that deals with uid and passwords.
146*4bff34e3Sthurlow  */
147*4bff34e3Sthurlow void
148*4bff34e3Sthurlow smb_pkey_init()
149*4bff34e3Sthurlow {
150*4bff34e3Sthurlow 	avl_create(&smb_ptd,
151*4bff34e3Sthurlow 	    smb_pkey_cmp,
152*4bff34e3Sthurlow 	    sizeof (smb_passid_t),
153*4bff34e3Sthurlow 	    offsetof(smb_passid_t,
154*4bff34e3Sthurlow 	    cpnode));
155*4bff34e3Sthurlow 	mutex_init(&smb_ptd_lock, NULL, MUTEX_DEFAULT, NULL);
156*4bff34e3Sthurlow }
157*4bff34e3Sthurlow 
158*4bff34e3Sthurlow /*
159*4bff34e3Sthurlow  * Destroy the full AVL tree.
160*4bff34e3Sthurlow  */
161*4bff34e3Sthurlow void
162*4bff34e3Sthurlow smb_pkey_fini()
163*4bff34e3Sthurlow {
164*4bff34e3Sthurlow 	smb_pkey_deluid((uid_t)-1, CRED());
165*4bff34e3Sthurlow 	avl_destroy(&smb_ptd);
166*4bff34e3Sthurlow 	mutex_destroy(&smb_ptd_lock);
167*4bff34e3Sthurlow }
168*4bff34e3Sthurlow 
169*4bff34e3Sthurlow /*
170*4bff34e3Sthurlow  * Driver unload calls this to ask if we
171*4bff34e3Sthurlow  * have any stored passwords
172*4bff34e3Sthurlow  */
173*4bff34e3Sthurlow int
174*4bff34e3Sthurlow smb_pkey_idle()
175*4bff34e3Sthurlow {
176*4bff34e3Sthurlow 	int n;
177*4bff34e3Sthurlow 
178*4bff34e3Sthurlow 	mutex_enter(&smb_ptd_lock);
179*4bff34e3Sthurlow 	n = avl_numnodes(&smb_ptd);
180*4bff34e3Sthurlow 	mutex_exit(&smb_ptd_lock);
181*4bff34e3Sthurlow 
182*4bff34e3Sthurlow 	return ((n) ? EBUSY : 0);
183*4bff34e3Sthurlow }
184*4bff34e3Sthurlow 
185*4bff34e3Sthurlow int
186*4bff34e3Sthurlow smb_node_delete(smb_passid_t *tmp)
187*4bff34e3Sthurlow {
188*4bff34e3Sthurlow 	ASSERT(MUTEX_HELD(&smb_ptd_lock));
189*4bff34e3Sthurlow 	avl_remove(&smb_ptd, tmp);
190*4bff34e3Sthurlow 	smb_strfree(tmp->srvdom);
191*4bff34e3Sthurlow 	smb_strfree(tmp->username);
192*4bff34e3Sthurlow 	kmem_free(tmp, sizeof (*tmp));
193*4bff34e3Sthurlow 	return (0);
194*4bff34e3Sthurlow }
195*4bff34e3Sthurlow 
196*4bff34e3Sthurlow 
197*4bff34e3Sthurlow /*
198*4bff34e3Sthurlow  * Remove a node from the AVL tree identified by cpid.
199*4bff34e3Sthurlow  */
200*4bff34e3Sthurlow int
201*4bff34e3Sthurlow smb_pkey_del(smbioc_pk_t *pk, cred_t *cr)
202*4bff34e3Sthurlow {
203*4bff34e3Sthurlow 	avl_index_t where;
204*4bff34e3Sthurlow 	smb_passid_t buf, *cpid, *tmp;
205*4bff34e3Sthurlow 	uid_t uid;
206*4bff34e3Sthurlow 
207*4bff34e3Sthurlow 	tmp = &buf;
208*4bff34e3Sthurlow 	uid = pk->pk_uid;
209*4bff34e3Sthurlow 	if (uid == (uid_t)-1)
210*4bff34e3Sthurlow 		uid = crgetruid(cr);
211*4bff34e3Sthurlow 	else {
212*4bff34e3Sthurlow 		if (secpolicy_smbfs_login(cr, uid))
213*4bff34e3Sthurlow 			return (EPERM);
214*4bff34e3Sthurlow 	}
215*4bff34e3Sthurlow 	tmp->uid = uid;
216*4bff34e3Sthurlow 	tmp->zoneid = getzoneid();
217*4bff34e3Sthurlow 	tmp->srvdom = pk->pk_dom;
218*4bff34e3Sthurlow 	tmp->username = pk->pk_usr;
219*4bff34e3Sthurlow 
220*4bff34e3Sthurlow 	mutex_enter(&smb_ptd_lock);
221*4bff34e3Sthurlow 	if ((cpid = (smb_passid_t *)avl_find(&smb_ptd,
222*4bff34e3Sthurlow 	    tmp, &where)) != NULL) {
223*4bff34e3Sthurlow 		smb_node_delete(cpid);
224*4bff34e3Sthurlow 	}
225*4bff34e3Sthurlow 	mutex_exit(&smb_ptd_lock);
226*4bff34e3Sthurlow 
227*4bff34e3Sthurlow 	return (0);
228*4bff34e3Sthurlow }
229*4bff34e3Sthurlow 
230*4bff34e3Sthurlow /*
231*4bff34e3Sthurlow  * Delete the entries owned by a particular user
232*4bff34e3Sthurlow  * based on uid. We go through all the nodes and
233*4bff34e3Sthurlow  * delete the nodes whereever the uid matches.
234*4bff34e3Sthurlow  *
235*4bff34e3Sthurlow  * Also implements "delete all" when uid == -1.
236*4bff34e3Sthurlow  *
237*4bff34e3Sthurlow  * You must have privilege to use any uid other
238*4bff34e3Sthurlow  * than your real uid.
239*4bff34e3Sthurlow  */
240*4bff34e3Sthurlow int
241*4bff34e3Sthurlow smb_pkey_deluid(uid_t ioc_uid, cred_t *cr)
242*4bff34e3Sthurlow {
243*4bff34e3Sthurlow 	smb_passid_t *cpid, *tmp;
244*4bff34e3Sthurlow 
245*4bff34e3Sthurlow 	if (secpolicy_smbfs_login(cr, ioc_uid))
246*4bff34e3Sthurlow 		return (EPERM);
247*4bff34e3Sthurlow 
248*4bff34e3Sthurlow 	mutex_enter(&smb_ptd_lock);
249*4bff34e3Sthurlow 	for (tmp = avl_first(&smb_ptd); tmp != NULL;
250*4bff34e3Sthurlow 	    tmp = cpid) {
251*4bff34e3Sthurlow 		cpid = AVL_NEXT(&smb_ptd, tmp);
252*4bff34e3Sthurlow 		if (ioc_uid == (uid_t)-1 ||
253*4bff34e3Sthurlow 		    ioc_uid == tmp->uid) {
254*4bff34e3Sthurlow 			/*
255*4bff34e3Sthurlow 			 * Delete the node.
256*4bff34e3Sthurlow 			 */
257*4bff34e3Sthurlow 			smb_node_delete(tmp);
258*4bff34e3Sthurlow 		}
259*4bff34e3Sthurlow 	}
260*4bff34e3Sthurlow 	mutex_exit(&smb_ptd_lock);
261*4bff34e3Sthurlow 
262*4bff34e3Sthurlow 	return (0);
263*4bff34e3Sthurlow }
264*4bff34e3Sthurlow 
265*4bff34e3Sthurlow /*
266*4bff34e3Sthurlow  * Add entry or modify existing.
267*4bff34e3Sthurlow  * Check for existing entry..
268*4bff34e3Sthurlow  * If present, delete.
269*4bff34e3Sthurlow  * Now, add the new entry.
270*4bff34e3Sthurlow  */
271*4bff34e3Sthurlow int
272*4bff34e3Sthurlow smb_pkey_add(smbioc_pk_t *pk, cred_t *cr)
273*4bff34e3Sthurlow {
274*4bff34e3Sthurlow 	avl_tree_t *t = &smb_ptd;
275*4bff34e3Sthurlow 	avl_index_t	where;
276*4bff34e3Sthurlow 	smb_passid_t *tmp, *cpid;
277*4bff34e3Sthurlow 	int ret;
278*4bff34e3Sthurlow 	uid_t uid;
279*4bff34e3Sthurlow 
280*4bff34e3Sthurlow 	uid = pk->pk_uid;
281*4bff34e3Sthurlow 	if (uid == (uid_t)-1)
282*4bff34e3Sthurlow 		uid = crgetruid(cr);
283*4bff34e3Sthurlow 	else {
284*4bff34e3Sthurlow 		if (secpolicy_smbfs_login(cr, uid))
285*4bff34e3Sthurlow 			return (EPERM);
286*4bff34e3Sthurlow 	}
287*4bff34e3Sthurlow 	cpid = kmem_zalloc(sizeof (smb_passid_t), KM_SLEEP);
288*4bff34e3Sthurlow 	cpid->uid = uid;
289*4bff34e3Sthurlow 	cpid->zoneid = getzoneid();
290*4bff34e3Sthurlow 	cpid->srvdom = smb_strdup(pk->pk_dom);
291*4bff34e3Sthurlow 	cpid->username = smb_strdup(pk->pk_usr);
292*4bff34e3Sthurlow 	smb_oldlm_hash(pk->pk_pass, cpid->lmhash);
293*4bff34e3Sthurlow 	smb_ntlmv1hash(pk->pk_pass, cpid->nthash);
294*4bff34e3Sthurlow 
295*4bff34e3Sthurlow 	/*
296*4bff34e3Sthurlow 	 * XXX: Instead of calling smb_pkey_check here,
297*4bff34e3Sthurlow 	 * should call avl_find directly, and hold the
298*4bff34e3Sthurlow 	 * lock across: avl_find, avl_remove, avl_insert.
299*4bff34e3Sthurlow 	 */
300*4bff34e3Sthurlow 
301*4bff34e3Sthurlow 	/* If it already exists, delete it. */
302*4bff34e3Sthurlow 	ret = smb_pkey_check(pk, cr);
303*4bff34e3Sthurlow 	if (ret == 0) {
304*4bff34e3Sthurlow 		smb_pkey_del(pk, cr);
305*4bff34e3Sthurlow 	}
306*4bff34e3Sthurlow 
307*4bff34e3Sthurlow 	mutex_enter(&smb_ptd_lock);
308*4bff34e3Sthurlow 	tmp = (smb_passid_t *)avl_find(t, cpid, &where);
309*4bff34e3Sthurlow 	if (tmp == NULL) {
310*4bff34e3Sthurlow 		avl_insert(t, cpid, where);
311*4bff34e3Sthurlow 	} else {
312*4bff34e3Sthurlow 		smb_strfree(cpid->srvdom);
313*4bff34e3Sthurlow 		smb_strfree(cpid->username);
314*4bff34e3Sthurlow 		kmem_free(cpid, sizeof (smb_passid_t));
315*4bff34e3Sthurlow 	}
316*4bff34e3Sthurlow 	mutex_exit(&smb_ptd_lock);
317*4bff34e3Sthurlow 
318*4bff34e3Sthurlow 	return (0);
319*4bff34e3Sthurlow }
320*4bff34e3Sthurlow 
321*4bff34e3Sthurlow /*
322*4bff34e3Sthurlow  * Determine if a node with uid,zoneid, uname & dname exists in the tree
323*4bff34e3Sthurlow  * given the information.  Does NOT return the stored password.
324*4bff34e3Sthurlow  */
325*4bff34e3Sthurlow int
326*4bff34e3Sthurlow smb_pkey_check(smbioc_pk_t *pk, cred_t *cr)
327*4bff34e3Sthurlow {
328*4bff34e3Sthurlow 	avl_tree_t *t = &smb_ptd;
329*4bff34e3Sthurlow 	avl_index_t	where;
330*4bff34e3Sthurlow 	smb_passid_t *tmp, *cpid;
331*4bff34e3Sthurlow 	int error = ENOENT;
332*4bff34e3Sthurlow 	uid_t uid;
333*4bff34e3Sthurlow 
334*4bff34e3Sthurlow 	uid = pk->pk_uid;
335*4bff34e3Sthurlow 	if (uid == (uid_t)-1)
336*4bff34e3Sthurlow 		uid = crgetruid(cr);
337*4bff34e3Sthurlow 	else {
338*4bff34e3Sthurlow 		if (secpolicy_smbfs_login(cr, uid))
339*4bff34e3Sthurlow 			return (EPERM);
340*4bff34e3Sthurlow 	}
341*4bff34e3Sthurlow 	cpid = kmem_alloc(sizeof (smb_passid_t), KM_SLEEP);
342*4bff34e3Sthurlow 	cpid->uid = uid;
343*4bff34e3Sthurlow 	cpid->zoneid = getzoneid();
344*4bff34e3Sthurlow 	cpid->srvdom = pk->pk_dom;
345*4bff34e3Sthurlow 	cpid->username = pk->pk_usr;
346*4bff34e3Sthurlow 
347*4bff34e3Sthurlow 	mutex_enter(&smb_ptd_lock);
348*4bff34e3Sthurlow 	tmp = (smb_passid_t *)avl_find(t, cpid, &where);
349*4bff34e3Sthurlow 	if (tmp != NULL)
350*4bff34e3Sthurlow 		error = 0;
351*4bff34e3Sthurlow 	mutex_exit(&smb_ptd_lock);
352*4bff34e3Sthurlow 
353*4bff34e3Sthurlow 	kmem_free(cpid, sizeof (smb_passid_t));
354*4bff34e3Sthurlow 	return (error);
355*4bff34e3Sthurlow }
356*4bff34e3Sthurlow 
357*4bff34e3Sthurlow /*
358*4bff34e3Sthurlow  * Interface function between the keychain mechanism and SMB password
359*4bff34e3Sthurlow  * handling during Session Setup.  Internal form of smb_pkey_check().
360*4bff34e3Sthurlow  * Copies the password hashes into the VC.
361*4bff34e3Sthurlow  */
362*4bff34e3Sthurlow int
363*4bff34e3Sthurlow smb_pkey_getpwh(struct smb_vc *vcp, cred_t *cr)
364*4bff34e3Sthurlow {
365*4bff34e3Sthurlow 	avl_tree_t *t = &smb_ptd;
366*4bff34e3Sthurlow 	avl_index_t	where;
367*4bff34e3Sthurlow 	smb_passid_t *tmp, *cpid;
368*4bff34e3Sthurlow 	int error = ENOENT;
369*4bff34e3Sthurlow 
370*4bff34e3Sthurlow 	cpid = kmem_alloc(sizeof (smb_passid_t), KM_SLEEP);
371*4bff34e3Sthurlow 	cpid->uid = crgetruid(cr);
372*4bff34e3Sthurlow 	cpid->zoneid = getzoneid();
373*4bff34e3Sthurlow 	cpid->username = vcp->vc_username;
374*4bff34e3Sthurlow 
375*4bff34e3Sthurlow 	if (vcp->vc_vopt & SMBVOPT_KC_DOMAIN)
376*4bff34e3Sthurlow 		cpid->srvdom = vcp->vc_domain;
377*4bff34e3Sthurlow 	else
378*4bff34e3Sthurlow 		cpid->srvdom = vcp->vc_srvname;
379*4bff34e3Sthurlow 
380*4bff34e3Sthurlow 	mutex_enter(&smb_ptd_lock);
381*4bff34e3Sthurlow 	tmp = (smb_passid_t *)avl_find(t, cpid, &where);
382*4bff34e3Sthurlow 	if (tmp != NULL) {
383*4bff34e3Sthurlow 		bcopy(tmp->lmhash, vcp->vc_lmhash, SMB_PWH_MAX);
384*4bff34e3Sthurlow 		bcopy(tmp->nthash, vcp->vc_nthash, SMB_PWH_MAX);
385*4bff34e3Sthurlow 		error = 0;
386*4bff34e3Sthurlow 	}
387*4bff34e3Sthurlow 	mutex_exit(&smb_ptd_lock);
388*4bff34e3Sthurlow 
389*4bff34e3Sthurlow 	kmem_free(cpid, sizeof (smb_passid_t));
390*4bff34e3Sthurlow 	return (error);
391*4bff34e3Sthurlow }
392