xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_user.c (revision aeac2d873b68a43f6650e0d0f021c02f5a653a21)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
24  */
25 
26 /*
27  * General Structures Layout
28  * -------------------------
29  *
30  * This is a simplified diagram showing the relationship between most of the
31  * main structures.
32  *
33  * +-------------------+
34  * |     SMB_INFO      |
35  * +-------------------+
36  *          |
37  *          |
38  *          v
39  * +-------------------+       +-------------------+      +-------------------+
40  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
41  * +-------------------+       +-------------------+      +-------------------+
42  *   |          |
43  *   |          |
44  *   |          v
45  *   |  +-------------------+     +-------------------+   +-------------------+
46  *   |  |       USER        |<--->|       USER        |...|       USER        |
47  *   |  +-------------------+     +-------------------+   +-------------------+
48  *   |
49  *   |
50  *   v
51  * +-------------------+       +-------------------+      +-------------------+
52  * |       TREE        |<----->|       TREE        |......|       TREE        |
53  * +-------------------+       +-------------------+      +-------------------+
54  *      |         |
55  *      |         |
56  *      |         v
57  *      |     +-------+       +-------+      +-------+
58  *      |     | OFILE |<----->| OFILE |......| OFILE |
59  *      |     +-------+       +-------+      +-------+
60  *      |
61  *      |
62  *      v
63  *  +-------+       +------+      +------+
64  *  | ODIR  |<----->| ODIR |......| ODIR |
65  *  +-------+       +------+      +------+
66  *
67  *
68  * User State Machine
69  * ------------------
70  *
71  *
72  *		    | T0:  Creation/Allocation
73  *		    |	   (1st session setup)
74  *		    v
75  *    +-----------------------------+
76  *    |  SMB_USER_STATE_LOGGING_ON  |<----------+
77  *    +-----------------------------+	 addl. session setup
78  *		    |		|	(more proc. required)
79  *		    | T2	|		^
80  *		    |		|		| T1: (cont.)
81  *		    |		+------->-------?
82  *		    v				| T3: (fail)
83  *    +-----------------------------+		v
84  *    |  SMB_USER_STATE_LOGGED_ON   |	    (logged off)
85  *    +-----------------------------+
86  *		    |
87  *		    | T4
88  *		    |
89  *		    v
90  *    +-----------------------------+
91  *    |  SMB_USER_STATE_LOGGING_OFF |
92  *    +-----------------------------+
93  *		    |
94  *		    | T5
95  *		    |
96  *		    v
97  *    +-----------------------------+    T6
98  *    |  SMB_USER_STATE_LOGGED_OFF  |----------> Deletion/Free
99  *    +-----------------------------+
100  *
101  * SMB_USER_STATE_LOGGING_ON
102  *
103  *    While in this state:
104  *      - The user is in the list of users for his session.
105  *      - References will be given out ONLY for session setup.
106  *      - This user can not access anything yet.
107  *
108  * SMB_USER_STATE_LOGGED_ON
109  *
110  *    While in this state:
111  *      - The user is in the list of users for his session.
112  *      - References will be given out if the user is looked up.
113  *      - The user can access files and pipes.
114  *
115  * SMB_USER_STATE_LOGGING_OFF
116  *
117  *    While in this state:
118  *      - The user is in the list of users for his session.
119  *      - References will not be given out if the user is looked up.
120  *      - The trees the user connected are being disconnected.
121  *      - The resources associated with the user remain.
122  *
123  * SMB_USER_STATE_LOGGED_OFF
124  *
125  *    While in this state:
126  *      - The user is queued in the list of users of his session.
127  *      - References will not be given out if the user is looked up.
128  *      - The user has no more trees connected.
129  *      - The resources associated with the user remain.
130  *
131  * Transition T0
132  *
133  *    First request in an SMB Session Setup sequence creates a
134  *    new user object and adds it to the list of users for
135  *    this session.  User UID is assigned and returned.
136  *
137  * Transition T1
138  *
139  *    Subsequent SMB Session Setup requests (on the same UID
140  *    assigned in T0) update the state of this user object,
141  *    communicating with smbd for the crypto work.
142  *
143  * Transition T2
144  *
145  *    If the SMB Session Setup sequence is successful, T2
146  *    makes the new user object available for requests.
147  *
148  * Transition T3
149  *
150  *    If an Session Setup request gets an error other than
151  *    the expected "more processing required", then T3
152  *    leads to state "LOGGED_OFF" and then tear-down of the
153  *    partially constructed user.
154  *
155  * Transition T4
156  *
157  *    Normal SMB User Logoff request, or session tear-down.
158  *
159  * Transition T5
160  *
161  *    This transition occurs in smb_user_release(). The resources associated
162  *    with the user are deleted as well as the user. For the transition to
163  *    occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the
164  *    reference count be zero.
165  *
166  * Comments
167  * --------
168  *
169  *    The state machine of the user structures is controlled by 3 elements:
170  *      - The list of users of the session he belongs to.
171  *      - The mutex embedded in the structure itself.
172  *      - The reference count.
173  *
174  *    There's a mutex embedded in the user structure used to protect its fields
175  *    and there's a lock embedded in the list of users of a session. To
176  *    increment or to decrement the reference count the mutex must be entered.
177  *    To insert the user into the list of users of the session and to remove
178  *    the user from it, the lock must be entered in RW_WRITER mode.
179  *
180  *    Rules of access to a user structure:
181  *
182  *    1) In order to avoid deadlocks, when both (mutex and lock of the session
183  *       list) have to be entered, the lock must be entered first.
184  *
185  *    2) All actions applied to a user require a reference count.
186  *
187  *    3) There are 2 ways of getting a reference count. One is when the user
188  *       logs in. The other when the user is looked up.
189  *
190  *    It should be noted that the reference count of a user registers the
191  *    number of references to the user in other structures (such as an smb
192  *    request). The reference count is not incremented in these 2 instances:
193  *
194  *    1) The user is logged in. An user is anchored by his state. If there's
195  *       no activity involving a user currently logged in, the reference
196  *       count of that user is zero.
197  *
198  *    2) The user is queued in the list of users of the session. The fact of
199  *       being queued in that list is NOT registered by incrementing the
200  *       reference count.
201  */
202 #include <sys/types.h>
203 #include <sys/sid.h>
204 #include <sys/priv_names.h>
205 #include <smbsrv/smb_kproto.h>
206 #include <smbsrv/smb_door.h>
207 
208 #define	ADMINISTRATORS_SID	"S-1-5-32-544"
209 
210 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
211 static void smb_user_auth_logoff(smb_user_t *);
212 
213 
214 /*
215  * Create a new user.
216  */
217 smb_user_t *
218 smb_user_new(smb_session_t *session)
219 {
220 	smb_user_t	*user;
221 
222 	ASSERT(session);
223 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
224 
225 	user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
226 	bzero(user, sizeof (smb_user_t));
227 
228 	user->u_refcnt = 1;
229 	user->u_session = session;
230 	user->u_server = session->s_server;
231 	user->u_logon_time = gethrestime_sec();
232 
233 	if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid))
234 		goto errout;
235 
236 	mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
237 	user->u_state = SMB_USER_STATE_LOGGING_ON;
238 	user->u_magic = SMB_USER_MAGIC;
239 
240 	smb_llist_enter(&session->s_user_list, RW_WRITER);
241 	smb_llist_insert_tail(&session->s_user_list, user);
242 	smb_llist_exit(&session->s_user_list);
243 	smb_server_inc_users(session->s_server);
244 
245 	return (user);
246 
247 errout:
248 	if (user->u_uid != 0)
249 		smb_idpool_free(&session->s_uid_pool, user->u_uid);
250 	kmem_cache_free(smb_cache_user, user);
251 	return (NULL);
252 }
253 
254 /*
255  * Fill in the details of a user, meaning a transition
256  * from state LOGGING_ON to state LOGGED_ON.
257  */
258 int
259 smb_user_logon(
260     smb_user_t		*user,
261     cred_t		*cr,
262     char		*domain_name,
263     char		*account_name,
264     uint32_t		flags,
265     uint32_t		privileges,
266     uint32_t		audit_sid)
267 {
268 
269 	ASSERT(user->u_magic == SMB_USER_MAGIC);
270 	ASSERT(cr);
271 	ASSERT(account_name);
272 	ASSERT(domain_name);
273 
274 	mutex_enter(&user->u_mutex);
275 
276 	if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
277 		mutex_exit(&user->u_mutex);
278 		return (-1);
279 	}
280 
281 	smb_authsock_close(user);
282 
283 	user->u_state = SMB_USER_STATE_LOGGED_ON;
284 	user->u_flags = flags;
285 	user->u_name_len = strlen(account_name) + 1;
286 	user->u_domain_len = strlen(domain_name) + 1;
287 	user->u_name = smb_mem_strdup(account_name);
288 	user->u_domain = smb_mem_strdup(domain_name);
289 	user->u_audit_sid = audit_sid;
290 
291 	smb_user_setcred(user, cr, privileges);
292 
293 	mutex_exit(&user->u_mutex);
294 
295 	return (0);
296 }
297 
298 /*
299  * smb_user_logoff
300  *
301  * Change the user state and disconnect trees.
302  * The user list must not be entered or modified here.
303  */
304 void
305 smb_user_logoff(
306     smb_user_t		*user)
307 {
308 	ASSERT(user->u_magic == SMB_USER_MAGIC);
309 
310 	mutex_enter(&user->u_mutex);
311 	ASSERT(user->u_refcnt);
312 	switch (user->u_state) {
313 	case SMB_USER_STATE_LOGGING_ON: {
314 		smb_authsock_close(user);
315 		user->u_state = SMB_USER_STATE_LOGGED_OFF;
316 		smb_server_dec_users(user->u_server);
317 		break;
318 	}
319 
320 	case SMB_USER_STATE_LOGGED_ON: {
321 		/*
322 		 * The user is moved into a state indicating that the log off
323 		 * process has started.
324 		 */
325 		user->u_state = SMB_USER_STATE_LOGGING_OFF;
326 		mutex_exit(&user->u_mutex);
327 		smb_session_disconnect_owned_trees(user->u_session, user);
328 		smb_user_auth_logoff(user);
329 		mutex_enter(&user->u_mutex);
330 		user->u_state = SMB_USER_STATE_LOGGED_OFF;
331 		smb_server_dec_users(user->u_server);
332 		break;
333 	}
334 	case SMB_USER_STATE_LOGGED_OFF:
335 	case SMB_USER_STATE_LOGGING_OFF:
336 		break;
337 
338 	default:
339 		ASSERT(0);
340 		break;
341 	}
342 	mutex_exit(&user->u_mutex);
343 }
344 
345 /*
346  * Take a reference on a user.  Do not return a reference unless the user is in
347  * the logged-in state.
348  */
349 boolean_t
350 smb_user_hold(smb_user_t *user)
351 {
352 	SMB_USER_VALID(user);
353 
354 	mutex_enter(&user->u_mutex);
355 
356 	if (user->u_state == SMB_USER_STATE_LOGGED_ON) {
357 		user->u_refcnt++;
358 		mutex_exit(&user->u_mutex);
359 		return (B_TRUE);
360 	}
361 
362 	mutex_exit(&user->u_mutex);
363 	return (B_FALSE);
364 }
365 
366 /*
367  * Unconditionally take a reference on a user.
368  */
369 void
370 smb_user_hold_internal(smb_user_t *user)
371 {
372 	SMB_USER_VALID(user);
373 
374 	mutex_enter(&user->u_mutex);
375 	user->u_refcnt++;
376 	mutex_exit(&user->u_mutex);
377 }
378 
379 /*
380  * Release a reference on a user.  If the reference count falls to
381  * zero and the user has logged off, post the object for deletion.
382  * Object deletion is deferred to avoid modifying a list while an
383  * iteration may be in progress.
384  */
385 void
386 smb_user_release(
387     smb_user_t		*user)
388 {
389 	ASSERT(user->u_magic == SMB_USER_MAGIC);
390 
391 	mutex_enter(&user->u_mutex);
392 	ASSERT(user->u_refcnt);
393 	user->u_refcnt--;
394 
395 	switch (user->u_state) {
396 	case SMB_USER_STATE_LOGGED_OFF:
397 		if (user->u_refcnt == 0)
398 			smb_session_post_user(user->u_session, user);
399 		break;
400 
401 	case SMB_USER_STATE_LOGGING_ON:
402 	case SMB_USER_STATE_LOGGED_ON:
403 	case SMB_USER_STATE_LOGGING_OFF:
404 		break;
405 
406 	default:
407 		ASSERT(0);
408 		break;
409 	}
410 	mutex_exit(&user->u_mutex);
411 }
412 
413 /*
414  * Determine whether or not the user is an administrator.
415  * Members of the administrators group have administrative rights.
416  */
417 boolean_t
418 smb_user_is_admin(smb_user_t *user)
419 {
420 #ifdef	_KERNEL
421 	char		sidstr[SMB_SID_STRSZ];
422 	ksidlist_t	*ksidlist;
423 	ksid_t		ksid1;
424 	ksid_t		*ksid2;
425 	int		i;
426 #endif	/* _KERNEL */
427 	boolean_t	rc = B_FALSE;
428 
429 	ASSERT(user);
430 	ASSERT(user->u_cred);
431 
432 	if (SMB_USER_IS_ADMIN(user))
433 		return (B_TRUE);
434 
435 #ifdef	_KERNEL
436 	bzero(&ksid1, sizeof (ksid_t));
437 	(void) strlcpy(sidstr, ADMINISTRATORS_SID, SMB_SID_STRSZ);
438 	ASSERT(smb_sid_splitstr(sidstr, &ksid1.ks_rid) == 0);
439 	ksid1.ks_domain = ksid_lookupdomain(sidstr);
440 
441 	ksidlist = crgetsidlist(user->u_cred);
442 	ASSERT(ksidlist);
443 	ASSERT(ksid1.ks_domain);
444 	ASSERT(ksid1.ks_domain->kd_name);
445 
446 	i = 0;
447 	ksid2 = crgetsid(user->u_cred, KSID_USER);
448 	do {
449 		ASSERT(ksid2->ks_domain);
450 		ASSERT(ksid2->ks_domain->kd_name);
451 
452 		if (strcmp(ksid1.ks_domain->kd_name,
453 		    ksid2->ks_domain->kd_name) == 0 &&
454 		    ksid1.ks_rid == ksid2->ks_rid) {
455 			user->u_flags |= SMB_USER_FLAG_ADMIN;
456 			rc = B_TRUE;
457 			break;
458 		}
459 
460 		ksid2 = &ksidlist->ksl_sids[i];
461 	} while (i++ < ksidlist->ksl_nsid);
462 
463 	ksid_rele(&ksid1);
464 #endif	/* _KERNEL */
465 	return (rc);
466 }
467 
468 /*
469  * This function should be called with a hold on the user.
470  */
471 boolean_t
472 smb_user_namecmp(smb_user_t *user, const char *name)
473 {
474 	char		*fq_name;
475 	boolean_t	match;
476 
477 	if (smb_strcasecmp(name, user->u_name, 0) == 0)
478 		return (B_TRUE);
479 
480 	fq_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
481 
482 	(void) snprintf(fq_name, MAXNAMELEN, "%s\\%s",
483 	    user->u_domain, user->u_name);
484 
485 	match = (smb_strcasecmp(name, fq_name, 0) == 0);
486 	if (!match) {
487 		(void) snprintf(fq_name, MAXNAMELEN, "%s@%s",
488 		    user->u_name, user->u_domain);
489 
490 		match = (smb_strcasecmp(name, fq_name, 0) == 0);
491 	}
492 
493 	kmem_free(fq_name, MAXNAMELEN);
494 	return (match);
495 }
496 
497 /*
498  * If the enumeration request is for user data, handle the request
499  * here.  Otherwise, pass it on to the trees.
500  *
501  * This function should be called with a hold on the user.
502  */
503 int
504 smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
505 {
506 	int		rc = 0;
507 
508 	ASSERT(user);
509 	ASSERT(user->u_magic == SMB_USER_MAGIC);
510 
511 	if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
512 		return (smb_user_enum_private(user, svcenum));
513 
514 	return (rc);
515 }
516 
517 /* *************************** Static Functions ***************************** */
518 
519 /*
520  * Delete a user.  The tree list should be empty.
521  *
522  * Remove the user from the session's user list before freeing resources
523  * associated with the user.
524  */
525 void
526 smb_user_delete(void *arg)
527 {
528 	smb_session_t	*session;
529 	smb_user_t	*user = (smb_user_t *)arg;
530 
531 	SMB_USER_VALID(user);
532 	ASSERT(user->u_refcnt == 0);
533 	ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
534 	ASSERT(user->u_authsock == NULL);
535 
536 	session = user->u_session;
537 	smb_llist_enter(&session->s_user_list, RW_WRITER);
538 	smb_llist_remove(&session->s_user_list, user);
539 	smb_idpool_free(&session->s_uid_pool, user->u_uid);
540 	smb_llist_exit(&session->s_user_list);
541 
542 	mutex_enter(&user->u_mutex);
543 	mutex_exit(&user->u_mutex);
544 
545 	user->u_magic = (uint32_t)~SMB_USER_MAGIC;
546 	mutex_destroy(&user->u_mutex);
547 	if (user->u_cred)
548 		crfree(user->u_cred);
549 	if (user->u_privcred)
550 		crfree(user->u_privcred);
551 	smb_mem_free(user->u_name);
552 	smb_mem_free(user->u_domain);
553 	kmem_cache_free(smb_cache_user, user);
554 }
555 
556 cred_t *
557 smb_user_getcred(smb_user_t *user)
558 {
559 	return (user->u_cred);
560 }
561 
562 cred_t *
563 smb_user_getprivcred(smb_user_t *user)
564 {
565 	return ((user->u_privcred)? user->u_privcred : user->u_cred);
566 }
567 
568 #ifdef	_KERNEL
569 /*
570  * Assign the user cred and privileges.
571  *
572  * If the user has backup and/or restore privleges, dup the cred
573  * and add those privileges to this new privileged cred.
574  */
575 void
576 smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
577 {
578 	cred_t *privcred = NULL;
579 
580 	ASSERT(cr);
581 	crhold(cr);
582 
583 	if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE))
584 		privcred = crdup(cr);
585 
586 	if (privcred != NULL) {
587 		if (privileges & SMB_USER_PRIV_BACKUP) {
588 			(void) crsetpriv(privcred, PRIV_FILE_DAC_READ,
589 			    PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL);
590 		}
591 
592 		if (privileges & SMB_USER_PRIV_RESTORE) {
593 			(void) crsetpriv(privcred, PRIV_FILE_DAC_WRITE,
594 			    PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF,
595 			    PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY,
596 			    PRIV_FILE_OWNER, PRIV_FILE_SETID,
597 			    PRIV_SYS_LINKDIR, PRIV_SYS_MOUNT, NULL);
598 		}
599 	}
600 
601 	user->u_cred = cr;
602 	user->u_privcred = privcred;
603 	user->u_privileges = privileges;
604 }
605 #endif	/* _KERNEL */
606 
607 /*
608  * Private function to support smb_user_enum.
609  */
610 static int
611 smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum)
612 {
613 	uint8_t *pb;
614 	uint_t nbytes;
615 	int rc;
616 
617 	if (svcenum->se_nskip > 0) {
618 		svcenum->se_nskip--;
619 		return (0);
620 	}
621 
622 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
623 		svcenum->se_nitems = svcenum->se_nlimit;
624 		return (0);
625 	}
626 
627 	pb = &svcenum->se_buf[svcenum->se_bused];
628 	rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes);
629 	if (rc == 0) {
630 		svcenum->se_bavail -= nbytes;
631 		svcenum->se_bused += nbytes;
632 		svcenum->se_nitems++;
633 	}
634 
635 	return (rc);
636 }
637 
638 /*
639  * Encode the NetInfo for a user into a buffer.  NetInfo contains
640  * information that is often needed in user space to support RPC
641  * requests.
642  */
643 int
644 smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen,
645     uint32_t *nbytes)
646 {
647 	smb_netuserinfo_t	info;
648 	int			rc;
649 
650 	smb_user_netinfo_init(user, &info);
651 	rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes);
652 	smb_user_netinfo_fini(&info);
653 
654 	return (rc);
655 }
656 
657 void
658 smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
659 {
660 	smb_session_t	*session;
661 	char		*buf;
662 
663 	ASSERT(user);
664 	ASSERT(user->u_domain);
665 	ASSERT(user->u_name);
666 
667 	session = user->u_session;
668 	ASSERT(session);
669 	ASSERT(session->workstation);
670 
671 	info->ui_session_id = session->s_kid;
672 	info->ui_native_os = session->native_os;
673 	info->ui_ipaddr = session->ipaddr;
674 	info->ui_numopens = session->s_file_cnt;
675 	info->ui_smb_uid = user->u_uid;
676 	info->ui_logon_time = user->u_logon_time;
677 	info->ui_flags = user->u_flags;
678 	info->ui_posix_uid = crgetuid(user->u_cred);
679 
680 	info->ui_domain_len = user->u_domain_len;
681 	info->ui_domain = smb_mem_strdup(user->u_domain);
682 
683 	info->ui_account_len = user->u_name_len;
684 	info->ui_account = smb_mem_strdup(user->u_name);
685 
686 	buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
687 	smb_session_getclient(session, buf, MAXNAMELEN);
688 	info->ui_workstation_len = strlen(buf) + 1;
689 	info->ui_workstation = smb_mem_strdup(buf);
690 	kmem_free(buf, MAXNAMELEN);
691 }
692 
693 void
694 smb_user_netinfo_fini(smb_netuserinfo_t *info)
695 {
696 	if (info == NULL)
697 		return;
698 
699 	if (info->ui_domain)
700 		smb_mem_free(info->ui_domain);
701 	if (info->ui_account)
702 		smb_mem_free(info->ui_account);
703 	if (info->ui_workstation)
704 		smb_mem_free(info->ui_workstation);
705 
706 	bzero(info, sizeof (smb_netuserinfo_t));
707 }
708 
709 static void
710 smb_user_auth_logoff(smb_user_t *user)
711 {
712 	uint32_t audit_sid = user->u_audit_sid;
713 
714 	(void) smb_kdoor_upcall(user->u_server, SMB_DR_USER_AUTH_LOGOFF,
715 	    &audit_sid, xdr_uint32_t, NULL, NULL);
716 }
717