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