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 2018 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
25 */
26
27 /*
28 * General Structures Layout
29 * -------------------------
30 *
31 * This is a simplified diagram showing the relationship between most of the
32 * main structures.
33 *
34 * +-------------------+
35 * | SMB_INFO |
36 * +-------------------+
37 * |
38 * |
39 * v
40 * +-------------------+ +-------------------+ +-------------------+
41 * | SESSION |<----->| SESSION |......| SESSION |
42 * +-------------------+ +-------------------+ +-------------------+
43 * | |
44 * | |
45 * | v
46 * | +-------------------+ +-------------------+ +-------------------+
47 * | | USER |<--->| USER |...| USER |
48 * | +-------------------+ +-------------------+ +-------------------+
49 * |
50 * |
51 * v
52 * +-------------------+ +-------------------+ +-------------------+
53 * | TREE |<----->| TREE |......| TREE |
54 * +-------------------+ +-------------------+ +-------------------+
55 * | |
56 * | |
57 * | v
58 * | +-------+ +-------+ +-------+
59 * | | OFILE |<----->| OFILE |......| OFILE |
60 * | +-------+ +-------+ +-------+
61 * |
62 * |
63 * v
64 * +-------+ +------+ +------+
65 * | ODIR |<----->| ODIR |......| ODIR |
66 * +-------+ +------+ +------+
67 *
68 *
69 * User State Machine
70 * ------------------
71 *
72 *
73 * | T0: Creation/Allocation
74 * | (1st session setup)
75 * v
76 * +-----------------------------+
77 * | SMB_USER_STATE_LOGGING_ON |<----------+
78 * +-----------------------------+ addl. session setup
79 * | | (more proc. required)
80 * | T2 | ^
81 * | | | T1: (cont.)
82 * | +------->-------?
83 * v | T3: (fail)
84 * +-----------------------------+ v
85 * | SMB_USER_STATE_LOGGED_ON | (logged off)
86 * +-----------------------------+
87 * |
88 * | T4
89 * |
90 * v
91 * +-----------------------------+
92 * | SMB_USER_STATE_LOGGING_OFF |
93 * +-----------------------------+
94 * |
95 * | T5
96 * |
97 * v
98 * +-----------------------------+ T6
99 * | SMB_USER_STATE_LOGGED_OFF |----------> Deletion/Free
100 * +-----------------------------+
101 *
102 * SMB_USER_STATE_LOGGING_ON
103 *
104 * While in this state:
105 * - The user is in the list of users for their session.
106 * - References will be given out ONLY for session setup.
107 * - This user can not access anything yet.
108 *
109 * SMB_USER_STATE_LOGGED_ON
110 *
111 * While in this state:
112 * - The user is in the list of users for their session.
113 * - References will be given out if the user is looked up.
114 * - The user can access files and pipes.
115 *
116 * SMB_USER_STATE_LOGGING_OFF
117 *
118 * While in this state:
119 * - The user is in the list of users for their session.
120 * - References will not be given out if the user is looked up.
121 * - The trees the user connected are being disconnected.
122 * - The resources associated with the user remain.
123 *
124 * SMB_USER_STATE_LOGGED_OFF
125 *
126 * While in this state:
127 * - The user is queued in the list of users of their session.
128 * - References will not be given out if the user is looked up.
129 * - The user has no more trees connected.
130 * - The resources associated with the user remain.
131 *
132 * Transition T0
133 *
134 * First request in an SMB Session Setup sequence creates a
135 * new user object and adds it to the list of users for
136 * this session. User UID is assigned and returned.
137 *
138 * Transition T1
139 *
140 * Subsequent SMB Session Setup requests (on the same UID
141 * assigned in T0) update the state of this user object,
142 * communicating with smbd for the crypto work.
143 *
144 * Transition T2
145 *
146 * If the SMB Session Setup sequence is successful, T2
147 * makes the new user object available for requests.
148 *
149 * Transition T3
150 *
151 * If an Session Setup request gets an error other than
152 * the expected "more processing required", then T3
153 * leads to state "LOGGED_OFF" and then tear-down of the
154 * partially constructed user.
155 *
156 * Transition T4
157 *
158 * Normal SMB User Logoff request, or session tear-down.
159 *
160 * Transition T5
161 *
162 * This transition occurs in smb_user_release(). The resources associated
163 * with the user are deleted as well as the user. For the transition to
164 * occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the
165 * reference count be zero.
166 *
167 * Comments
168 * --------
169 *
170 * The state machine of the user structures is controlled by 3 elements:
171 * - The list of users of the session they belong to.
172 * - The mutex embedded in the structure itself.
173 * - The reference count.
174 *
175 * There's a mutex embedded in the user structure used to protect its fields
176 * and there's a lock embedded in the list of users of a session. To
177 * increment or to decrement the reference count the mutex must be entered.
178 * To insert the user into the list of users of the session and to remove
179 * the user from it, the lock must be entered in RW_WRITER mode.
180 *
181 * Rules of access to a user structure:
182 *
183 * 1) In order to avoid deadlocks, when both (mutex and lock of the session
184 * list) have to be entered, the lock must be entered first. Additionally,
185 * one may NOT flush the deleteq of either the tree list or the ofile list
186 * while the user mutex is held.
187 *
188 * 2) All actions applied to a user require a reference count.
189 *
190 * 3) There are 2 ways of getting a reference count. One is when the user
191 * logs in. The other when the user is looked up.
192 *
193 * It should be noted that the reference count of a user registers the
194 * number of references to the user in other structures (such as an smb
195 * request). The reference count is not incremented in these 2 instances:
196 *
197 * 1) The user is logged in. An user is anchored by their state. If there's
198 * no activity involving a user currently logged in, the reference
199 * count of that user is zero.
200 *
201 * 2) The user is queued in the list of users of the session. The fact of
202 * being queued in that list is NOT registered by incrementing the
203 * reference count.
204 */
205 #include <sys/types.h>
206 #include <sys/sid.h>
207 #include <sys/priv_names.h>
208 #include <smbsrv/smb_kproto.h>
209 #include <smbsrv/smb_door.h>
210
211 #define ADMINISTRATORS_SID "S-1-5-32-544"
212
213 /* Don't leak object addresses */
214 #define SMB_USER_SSNID(u) \
215 ((uintptr_t)&smb_cache_user ^ (uintptr_t)(u))
216
217 static void smb_user_delete(void *);
218 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
219 static void smb_user_auth_logoff(smb_user_t *);
220 static void smb_user_logoff_tq(void *);
221
222 /*
223 * Create a new user.
224 *
225 * For SMB2 and later, session IDs (u_ssnid) need to be unique among all
226 * current and "recent" sessions. The session ID is derived from the
227 * address of the smb_user object (obscured by XOR with a constant).
228 * This adds a 3-bit generation number in the low bits, incremented
229 * when we allocate an smb_user_t from its kmem cache, so it can't
230 * be confused with a (recent) previous incarnation of this object.
231 */
232 smb_user_t *
233 smb_user_new(smb_session_t *session)
234 {
235 smb_user_t *user;
236 uint_t gen; // generation (low 3 bits of ssnid)
237
238 ASSERT(session);
239 ASSERT(session->s_magic == SMB_SESSION_MAGIC);
240
241 user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
242 gen = (user->u_ssnid + 1) & 7;
243 bzero(user, sizeof (smb_user_t));
244
245 user->u_refcnt = 1;
246 user->u_session = session;
247 user->u_server = session->s_server;
248 user->u_logon_time = gethrestime_sec();
249
250 if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid))
251 goto errout;
252 user->u_ssnid = SMB_USER_SSNID(user) + gen;
253
254 mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
255 user->u_state = SMB_USER_STATE_LOGGING_ON;
256 user->u_magic = SMB_USER_MAGIC;
257
258 smb_llist_enter(&session->s_user_list, RW_WRITER);
259 smb_llist_insert_tail(&session->s_user_list, user);
260 smb_llist_exit(&session->s_user_list);
261 smb_server_inc_users(session->s_server);
262
263 return (user);
264
265 errout:
266 if (user->u_uid != 0)
267 smb_idpool_free(&session->s_uid_pool, user->u_uid);
268 kmem_cache_free(smb_cache_user, user);
269 return (NULL);
270 }
271
272 /*
273 * Fill in the details of a user, meaning a transition
274 * from state LOGGING_ON to state LOGGED_ON.
275 */
276 int
277 smb_user_logon(
278 smb_user_t *user,
279 cred_t *cr,
280 char *domain_name,
281 char *account_name,
282 uint32_t flags,
283 uint32_t privileges,
284 uint32_t audit_sid)
285 {
286 ksocket_t authsock = NULL;
287
288 ASSERT(user->u_magic == SMB_USER_MAGIC);
289 ASSERT(cr);
290 ASSERT(account_name);
291 ASSERT(domain_name);
292
293 mutex_enter(&user->u_mutex);
294
295 if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
296 mutex_exit(&user->u_mutex);
297 return (-1);
298 }
299
300 /*
301 * In the transition from LOGGING_ON to LOGGED_ON,
302 * we always have an auth. socket to close.
303 */
304 authsock = user->u_authsock;
305 user->u_authsock = NULL;
306 if (user->u_auth_tmo != NULL) {
307 (void) untimeout(user->u_auth_tmo);
308 user->u_auth_tmo = NULL;
309 }
310
311 user->u_state = SMB_USER_STATE_LOGGED_ON;
312 user->u_flags = flags;
313 user->u_name_len = strlen(account_name) + 1;
314 user->u_domain_len = strlen(domain_name) + 1;
315 user->u_name = smb_mem_strdup(account_name);
316 user->u_domain = smb_mem_strdup(domain_name);
317 user->u_audit_sid = audit_sid;
318
319 smb_user_setcred(user, cr, privileges);
320
321 mutex_exit(&user->u_mutex);
322
323 /* This close can block, so not under the mutex. */
324 if (authsock != NULL)
325 smb_authsock_close(user, authsock);
326
327 return (0);
328 }
329
330 /*
331 * smb_user_logoff
332 *
333 * Change the user state to "logging off" and disconnect trees.
334 * The user list must not be entered or modified here.
335 *
336 * We remain in state "logging off" until the last ref. is gone,
337 * then smb_user_release takes us to state "logged off".
338 */
339 void
340 smb_user_logoff(
341 smb_user_t *user)
342 {
343 ksocket_t authsock = NULL;
344
345 ASSERT(user->u_magic == SMB_USER_MAGIC);
346
347 mutex_enter(&user->u_mutex);
348 ASSERT(user->u_refcnt);
349 switch (user->u_state) {
350 case SMB_USER_STATE_LOGGING_ON:
351 authsock = user->u_authsock;
352 user->u_authsock = NULL;
353 if (user->u_auth_tmo != NULL) {
354 (void) untimeout(user->u_auth_tmo);
355 user->u_auth_tmo = NULL;
356 }
357 user->u_state = SMB_USER_STATE_LOGGING_OFF;
358 mutex_exit(&user->u_mutex);
359 /* This close can block, so not under the mutex. */
360 if (authsock != NULL) {
361 smb_authsock_close(user, authsock);
362 }
363 break;
364
365 case SMB_USER_STATE_LOGGED_ON:
366 /*
367 * The user is moved into a state indicating that the log off
368 * process has started.
369 */
370 user->u_state = SMB_USER_STATE_LOGGING_OFF;
371 mutex_exit(&user->u_mutex);
372 smb_session_disconnect_owned_trees(user->u_session, user);
373 smb_user_auth_logoff(user);
374 break;
375
376 case SMB_USER_STATE_LOGGED_OFF:
377 case SMB_USER_STATE_LOGGING_OFF:
378 mutex_exit(&user->u_mutex);
379 break;
380
381 default:
382 ASSERT(0);
383 mutex_exit(&user->u_mutex);
384 break;
385 }
386 }
387
388 /*
389 * Take a reference on a user. Do not return a reference unless the user is in
390 * the logged-in state.
391 */
392 boolean_t
393 smb_user_hold(smb_user_t *user)
394 {
395 SMB_USER_VALID(user);
396
397 mutex_enter(&user->u_mutex);
398
399 if (user->u_state == SMB_USER_STATE_LOGGED_ON) {
400 user->u_refcnt++;
401 mutex_exit(&user->u_mutex);
402 return (B_TRUE);
403 }
404
405 mutex_exit(&user->u_mutex);
406 return (B_FALSE);
407 }
408
409 /*
410 * Unconditionally take a reference on a user.
411 */
412 void
413 smb_user_hold_internal(smb_user_t *user)
414 {
415 SMB_USER_VALID(user);
416
417 mutex_enter(&user->u_mutex);
418 user->u_refcnt++;
419 mutex_exit(&user->u_mutex);
420 }
421
422 /*
423 * Release a reference on a user. If the reference count falls to
424 * zero and the user has logged off, post the object for deletion.
425 * Object deletion is deferred to avoid modifying a list while an
426 * iteration may be in progress.
427 */
428 void
429 smb_user_release(
430 smb_user_t *user)
431 {
432 smb_session_t *ssn = user->u_session;
433
434 SMB_USER_VALID(user);
435
436 /* flush the tree list delete queue */
437 smb_llist_flush(&ssn->s_tree_list);
438
439 mutex_enter(&user->u_mutex);
440 ASSERT(user->u_refcnt);
441 user->u_refcnt--;
442
443 switch (user->u_state) {
444 case SMB_USER_STATE_LOGGING_OFF:
445 if (user->u_refcnt == 0) {
446 smb_session_t *ssn = user->u_session;
447 user->u_state = SMB_USER_STATE_LOGGED_OFF;
448 smb_llist_post(&ssn->s_user_list, user,
449 smb_user_delete);
450 }
451 break;
452
453 case SMB_USER_STATE_LOGGING_ON:
454 case SMB_USER_STATE_LOGGED_ON:
455 break;
456
457 case SMB_USER_STATE_LOGGED_OFF:
458 default:
459 ASSERT(0);
460 break;
461 }
462 mutex_exit(&user->u_mutex);
463 }
464
465 /*
466 * Timeout handler for user logons that stay too long in
467 * state SMB_USER_STATE_LOGGING_ON. This is setup by a
468 * timeout call in smb_authsock_open, and called in a
469 * callout thread, so schedule a taskq job to do the
470 * real work of logging off this user.
471 */
472 void
473 smb_user_auth_tmo(void *arg)
474 {
475 smb_user_t *user = arg;
476 smb_request_t *sr;
477
478 SMB_USER_VALID(user);
479
480 /*
481 * If we can't allocate a request, it means the
482 * session is being torn down, so nothing to do.
483 */
484 sr = smb_request_alloc(user->u_session, 0);
485 if (sr == NULL)
486 return;
487
488 /*
489 * Check user state, and take a hold if it's
490 * still logging on. If not, we're done.
491 */
492 mutex_enter(&user->u_mutex);
493 if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
494 mutex_exit(&user->u_mutex);
495 smb_request_free(sr);
496 return;
497 }
498 /* smb_user_hold_internal */
499 user->u_refcnt++;
500 mutex_exit(&user->u_mutex);
501
502 /*
503 * The user hold is given to the SR, and released in
504 * smb_user_logoff_tq / smb_request_free
505 */
506 sr->uid_user = user;
507 sr->user_cr = user->u_cred;
508 sr->sr_state = SMB_REQ_STATE_SUBMITTED;
509
510 (void) taskq_dispatch(
511 user->u_server->sv_worker_pool,
512 smb_user_logoff_tq, sr, TQ_SLEEP);
513 }
514
515 /*
516 * Helper for smb_user_auth_tmo()
517 */
518 static void
519 smb_user_logoff_tq(void *arg)
520 {
521 smb_request_t *sr = arg;
522
523 SMB_REQ_VALID(sr);
524
525 mutex_enter(&sr->sr_mutex);
526 sr->sr_worker = curthread;
527 sr->sr_state = SMB_REQ_STATE_ACTIVE;
528 mutex_exit(&sr->sr_mutex);
529
530 smb_user_logoff(sr->uid_user);
531
532 sr->sr_state = SMB_REQ_STATE_COMPLETED;
533 smb_request_free(sr);
534 }
535
536 /*
537 * Determine whether or not the user is an administrator.
538 * Members of the administrators group have administrative rights.
539 */
540 boolean_t
541 smb_user_is_admin(smb_user_t *user)
542 {
543 #ifdef _KERNEL
544 char sidstr[SMB_SID_STRSZ];
545 ksidlist_t *ksidlist;
546 ksid_t ksid1;
547 ksid_t *ksid2;
548 int i;
549 #endif /* _KERNEL */
550 boolean_t rc = B_FALSE;
551
552 ASSERT(user);
553 ASSERT(user->u_cred);
554
555 if (SMB_USER_IS_ADMIN(user))
556 return (B_TRUE);
557
558 #ifdef _KERNEL
559 bzero(&ksid1, sizeof (ksid_t));
560 (void) strlcpy(sidstr, ADMINISTRATORS_SID, SMB_SID_STRSZ);
561 ASSERT(smb_sid_splitstr(sidstr, &ksid1.ks_rid) == 0);
562 ksid1.ks_domain = ksid_lookupdomain(sidstr);
563
564 ksidlist = crgetsidlist(user->u_cred);
565 ASSERT(ksidlist);
566 ASSERT(ksid1.ks_domain);
567 ASSERT(ksid1.ks_domain->kd_name);
568
569 i = 0;
570 ksid2 = crgetsid(user->u_cred, KSID_USER);
571 do {
572 ASSERT(ksid2->ks_domain);
573 ASSERT(ksid2->ks_domain->kd_name);
574
575 if (strcmp(ksid1.ks_domain->kd_name,
576 ksid2->ks_domain->kd_name) == 0 &&
577 ksid1.ks_rid == ksid2->ks_rid) {
578 user->u_flags |= SMB_USER_FLAG_ADMIN;
579 rc = B_TRUE;
580 break;
581 }
582
583 ksid2 = &ksidlist->ksl_sids[i];
584 } while (i++ < ksidlist->ksl_nsid);
585
586 ksid_rele(&ksid1);
587 #endif /* _KERNEL */
588 return (rc);
589 }
590
591 /*
592 * This function should be called with a hold on the user.
593 */
594 boolean_t
595 smb_user_namecmp(smb_user_t *user, const char *name)
596 {
597 char *fq_name;
598 boolean_t match;
599
600 if (smb_strcasecmp(name, user->u_name, 0) == 0)
601 return (B_TRUE);
602
603 fq_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
604
605 (void) snprintf(fq_name, MAXNAMELEN, "%s\\%s",
606 user->u_domain, user->u_name);
607
608 match = (smb_strcasecmp(name, fq_name, 0) == 0);
609 if (!match) {
610 (void) snprintf(fq_name, MAXNAMELEN, "%s@%s",
611 user->u_name, user->u_domain);
612
613 match = (smb_strcasecmp(name, fq_name, 0) == 0);
614 }
615
616 kmem_free(fq_name, MAXNAMELEN);
617 return (match);
618 }
619
620 /*
621 * If the enumeration request is for user data, handle the request
622 * here. Otherwise, pass it on to the trees.
623 *
624 * This function should be called with a hold on the user.
625 */
626 int
627 smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
628 {
629 int rc = 0;
630
631 ASSERT(user);
632 ASSERT(user->u_magic == SMB_USER_MAGIC);
633
634 if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
635 return (smb_user_enum_private(user, svcenum));
636
637 return (rc);
638 }
639
640 /* *************************** Static Functions ***************************** */
641
642 /*
643 * Delete a user. The tree list should be empty.
644 *
645 * Remove the user from the session's user list before freeing resources
646 * associated with the user.
647 */
648 static void
649 smb_user_delete(void *arg)
650 {
651 smb_session_t *session;
652 smb_user_t *user = (smb_user_t *)arg;
653 uint32_t ucount;
654
655 SMB_USER_VALID(user);
656 ASSERT(user->u_refcnt == 0);
657 ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
658 ASSERT(user->u_authsock == NULL);
659 ASSERT(user->u_auth_tmo == NULL);
660
661 session = user->u_session;
662
663 smb_server_dec_users(session->s_server);
664 smb_llist_enter(&session->s_user_list, RW_WRITER);
665 smb_llist_remove(&session->s_user_list, user);
666 smb_idpool_free(&session->s_uid_pool, user->u_uid);
667 ucount = smb_llist_get_count(&session->s_user_list);
668 smb_llist_exit(&session->s_user_list);
669
670 if (ucount == 0) {
671 smb_rwx_rwenter(&session->s_lock, RW_WRITER);
672 session->s_state = SMB_SESSION_STATE_SHUTDOWN;
673 smb_rwx_cvbcast(&session->s_lock);
674 smb_rwx_rwexit(&session->s_lock);
675 }
676
677 /*
678 * This user is no longer on s_user_list, however...
679 *
680 * This is called via smb_llist_post, which means it may run
681 * BEFORE smb_user_release drops u_mutex (if another thread
682 * flushes the delete queue before we do). Synchronize.
683 */
684 mutex_enter(&user->u_mutex);
685 mutex_exit(&user->u_mutex);
686
687 user->u_magic = (uint32_t)~SMB_USER_MAGIC;
688 mutex_destroy(&user->u_mutex);
689 if (user->u_cred)
690 crfree(user->u_cred);
691 if (user->u_privcred)
692 crfree(user->u_privcred);
693 smb_mem_free(user->u_name);
694 smb_mem_free(user->u_domain);
695 kmem_cache_free(smb_cache_user, user);
696 }
697
698 cred_t *
699 smb_user_getcred(smb_user_t *user)
700 {
701 return (user->u_cred);
702 }
703
704 cred_t *
705 smb_user_getprivcred(smb_user_t *user)
706 {
707 return ((user->u_privcred)? user->u_privcred : user->u_cred);
708 }
709
710 #ifdef _KERNEL
711 /*
712 * Assign the user cred and privileges.
713 *
714 * If the user has backup and/or restore privleges, dup the cred
715 * and add those privileges to this new privileged cred.
716 */
717 void
718 smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
719 {
720 cred_t *privcred = NULL;
721
722 ASSERT(cr);
723 crhold(cr);
724
725 if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE))
726 privcred = crdup(cr);
727
728 if (privcred != NULL) {
729 if (privileges & SMB_USER_PRIV_BACKUP) {
730 (void) crsetpriv(privcred, PRIV_FILE_DAC_READ,
731 PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL);
732 }
733
734 if (privileges & SMB_USER_PRIV_RESTORE) {
735 (void) crsetpriv(privcred, PRIV_FILE_DAC_WRITE,
736 PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF,
737 PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY,
738 PRIV_FILE_OWNER, PRIV_FILE_SETID,
739 PRIV_SYS_LINKDIR, PRIV_SYS_MOUNT, NULL);
740 }
741 }
742
743 user->u_cred = cr;
744 user->u_privcred = privcred;
745 user->u_privileges = privileges;
746 }
747 #endif /* _KERNEL */
748
749 /*
750 * Private function to support smb_user_enum.
751 */
752 static int
753 smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum)
754 {
755 uint8_t *pb;
756 uint_t nbytes;
757 int rc;
758
759 if (svcenum->se_nskip > 0) {
760 svcenum->se_nskip--;
761 return (0);
762 }
763
764 if (svcenum->se_nitems >= svcenum->se_nlimit) {
765 svcenum->se_nitems = svcenum->se_nlimit;
766 return (0);
767 }
768
769 pb = &svcenum->se_buf[svcenum->se_bused];
770 rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes);
771 if (rc == 0) {
772 svcenum->se_bavail -= nbytes;
773 svcenum->se_bused += nbytes;
774 svcenum->se_nitems++;
775 }
776
777 return (rc);
778 }
779
780 /*
781 * Encode the NetInfo for a user into a buffer. NetInfo contains
782 * information that is often needed in user space to support RPC
783 * requests.
784 */
785 int
786 smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen,
787 uint32_t *nbytes)
788 {
789 smb_netuserinfo_t info;
790 int rc;
791
792 smb_user_netinfo_init(user, &info);
793 rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes);
794 smb_user_netinfo_fini(&info);
795
796 return (rc);
797 }
798
799 void
800 smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
801 {
802 smb_session_t *session;
803 char *buf;
804
805 ASSERT(user);
806 ASSERT(user->u_domain);
807 ASSERT(user->u_name);
808
809 session = user->u_session;
810 ASSERT(session);
811 ASSERT(session->workstation);
812
813 info->ui_session_id = session->s_kid;
814 info->ui_native_os = session->native_os;
815 info->ui_ipaddr = session->ipaddr;
816 info->ui_numopens = session->s_file_cnt;
817 info->ui_logon_time = user->u_logon_time;
818 info->ui_flags = user->u_flags;
819 info->ui_posix_uid = crgetuid(user->u_cred);
820
821 info->ui_domain_len = user->u_domain_len;
822 info->ui_domain = smb_mem_strdup(user->u_domain);
823
824 info->ui_account_len = user->u_name_len;
825 info->ui_account = smb_mem_strdup(user->u_name);
826
827 buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
828 smb_session_getclient(session, buf, MAXNAMELEN);
829 info->ui_workstation_len = strlen(buf) + 1;
830 info->ui_workstation = smb_mem_strdup(buf);
831 kmem_free(buf, MAXNAMELEN);
832 }
833
834 void
835 smb_user_netinfo_fini(smb_netuserinfo_t *info)
836 {
837 if (info == NULL)
838 return;
839
840 if (info->ui_domain)
841 smb_mem_free(info->ui_domain);
842 if (info->ui_account)
843 smb_mem_free(info->ui_account);
844 if (info->ui_workstation)
845 smb_mem_free(info->ui_workstation);
846
847 bzero(info, sizeof (smb_netuserinfo_t));
848 }
849
850 /*
851 * Tell smbd this user is going away so it can clean up their
852 * audit session, autohome dir, etc.
853 *
854 * Note that when we're shutting down, smbd will already have set
855 * smbd.s_shutting_down and therefore will ignore door calls.
856 * Skip this during shutdown to reduce upcall noise.
857 */
858 static void
859 smb_user_auth_logoff(smb_user_t *user)
860 {
861 smb_server_t *sv = user->u_server;
862 uint32_t audit_sid;
863
864 if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
865 return;
866
867 audit_sid = user->u_audit_sid;
868 (void) smb_kdoor_upcall(sv, SMB_DR_USER_AUTH_LOGOFF,
869 &audit_sid, xdr_uint32_t, NULL, NULL);
870 }
871
872 boolean_t
873 smb_is_same_user(cred_t *cr1, cred_t *cr2)
874 {
875 ksid_t *ks1 = crgetsid(cr1, KSID_USER);
876 ksid_t *ks2 = crgetsid(cr2, KSID_USER);
877
878 return (ks1->ks_rid == ks2->ks_rid &&
879 strcmp(ks1->ks_domain->kd_name, ks2->ks_domain->kd_name) == 0);
880 }