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 * 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 * | |
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.
185 *
186 * 2) All actions applied to a user require a reference count.
187 *
188 * 3) There are 2 ways of getting a reference count. One is when the user
189 * logs in. The other when the user is looked up.
190 *
191 * It should be noted that the reference count of a user registers the
192 * number of references to the user in other structures (such as an smb
193 * request). The reference count is not incremented in these 2 instances:
194 *
195 * 1) The user is logged in. An user is anchored by their state. If there's
196 * no activity involving a user currently logged in, the reference
197 * count of that user is zero.
198 *
199 * 2) The user is queued in the list of users of the session. The fact of
200 * being queued in that list is NOT registered by incrementing the
201 * reference count.
202 */
203 #include <sys/types.h>
204 #include <sys/sid.h>
205 #include <sys/priv_names.h>
206 #include <smbsrv/smb_kproto.h>
207 #include <smbsrv/smb_door.h>
208
209 #define ADMINISTRATORS_SID "S-1-5-32-544"
210
211 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
212 static void smb_user_auth_logoff(smb_user_t *);
213
214
215 /*
216 * Create a new user.
217 */
218 smb_user_t *
219 smb_user_new(smb_session_t *session)
220 {
221 smb_user_t *user;
222
223 ASSERT(session);
224 ASSERT(session->s_magic == SMB_SESSION_MAGIC);
225
226 user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
227 bzero(user, sizeof (smb_user_t));
228
229 user->u_refcnt = 1;
230 user->u_session = session;
231 user->u_server = session->s_server;
232 user->u_logon_time = gethrestime_sec();
233
234 if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid))
235 goto errout;
236
237 mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
238 user->u_state = SMB_USER_STATE_LOGGING_ON;
239 user->u_magic = SMB_USER_MAGIC;
240
241 smb_llist_enter(&session->s_user_list, RW_WRITER);
242 smb_llist_insert_tail(&session->s_user_list, user);
243 smb_llist_exit(&session->s_user_list);
244 smb_server_inc_users(session->s_server);
245
246 return (user);
247
248 errout:
249 if (user->u_uid != 0)
250 smb_idpool_free(&session->s_uid_pool, user->u_uid);
251 kmem_cache_free(smb_cache_user, user);
252 return (NULL);
253 }
254
255 /*
256 * Fill in the details of a user, meaning a transition
257 * from state LOGGING_ON to state LOGGED_ON.
258 */
259 int
260 smb_user_logon(
261 smb_user_t *user,
262 cred_t *cr,
263 char *domain_name,
264 char *account_name,
265 uint32_t flags,
266 uint32_t privileges,
267 uint32_t audit_sid)
268 {
269
270 ASSERT(user->u_magic == SMB_USER_MAGIC);
271 ASSERT(cr);
272 ASSERT(account_name);
273 ASSERT(domain_name);
274
275 mutex_enter(&user->u_mutex);
276
277 if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
278 mutex_exit(&user->u_mutex);
279 return (-1);
280 }
281
282 smb_authsock_close(user);
283
284 user->u_state = SMB_USER_STATE_LOGGED_ON;
285 user->u_flags = flags;
286 user->u_name_len = strlen(account_name) + 1;
287 user->u_domain_len = strlen(domain_name) + 1;
288 user->u_name = smb_mem_strdup(account_name);
289 user->u_domain = smb_mem_strdup(domain_name);
290 user->u_audit_sid = audit_sid;
291
292 smb_user_setcred(user, cr, privileges);
293
294 mutex_exit(&user->u_mutex);
295
296 return (0);
297 }
298
299 /*
300 * smb_user_logoff
301 *
302 * Change the user state and disconnect trees.
303 * The user list must not be entered or modified here.
304 */
305 void
306 smb_user_logoff(
307 smb_user_t *user)
308 {
309 ASSERT(user->u_magic == SMB_USER_MAGIC);
310
311 mutex_enter(&user->u_mutex);
312 ASSERT(user->u_refcnt);
313 switch (user->u_state) {
314 case SMB_USER_STATE_LOGGING_ON: {
315 smb_authsock_close(user);
316 user->u_state = SMB_USER_STATE_LOGGED_OFF;
317 smb_server_dec_users(user->u_server);
318 break;
319 }
320
321 case SMB_USER_STATE_LOGGED_ON: {
322 /*
323 * The user is moved into a state indicating that the log off
324 * process has started.
325 */
326 user->u_state = SMB_USER_STATE_LOGGING_OFF;
327 mutex_exit(&user->u_mutex);
328 smb_session_disconnect_owned_trees(user->u_session, user);
329 smb_user_auth_logoff(user);
330 mutex_enter(&user->u_mutex);
331 user->u_state = SMB_USER_STATE_LOGGED_OFF;
332 smb_server_dec_users(user->u_server);
333 break;
334 }
335 case SMB_USER_STATE_LOGGED_OFF:
336 case SMB_USER_STATE_LOGGING_OFF:
337 break;
338
339 default:
340 ASSERT(0);
341 break;
342 }
343 mutex_exit(&user->u_mutex);
344 }
345
346 /*
347 * Take a reference on a user. Do not return a reference unless the user is in
348 * the logged-in state.
349 */
350 boolean_t
351 smb_user_hold(smb_user_t *user)
352 {
353 SMB_USER_VALID(user);
354
355 mutex_enter(&user->u_mutex);
356
357 if (user->u_state == SMB_USER_STATE_LOGGED_ON) {
358 user->u_refcnt++;
359 mutex_exit(&user->u_mutex);
360 return (B_TRUE);
361 }
362
363 mutex_exit(&user->u_mutex);
370 void
371 smb_user_hold_internal(smb_user_t *user)
372 {
373 SMB_USER_VALID(user);
374
375 mutex_enter(&user->u_mutex);
376 user->u_refcnt++;
377 mutex_exit(&user->u_mutex);
378 }
379
380 /*
381 * Release a reference on a user. If the reference count falls to
382 * zero and the user has logged off, post the object for deletion.
383 * Object deletion is deferred to avoid modifying a list while an
384 * iteration may be in progress.
385 */
386 void
387 smb_user_release(
388 smb_user_t *user)
389 {
390 ASSERT(user->u_magic == SMB_USER_MAGIC);
391
392 mutex_enter(&user->u_mutex);
393 ASSERT(user->u_refcnt);
394 user->u_refcnt--;
395
396 switch (user->u_state) {
397 case SMB_USER_STATE_LOGGED_OFF:
398 if (user->u_refcnt == 0)
399 smb_session_post_user(user->u_session, user);
400 break;
401
402 case SMB_USER_STATE_LOGGING_ON:
403 case SMB_USER_STATE_LOGGED_ON:
404 case SMB_USER_STATE_LOGGING_OFF:
405 break;
406
407 default:
408 ASSERT(0);
409 break;
410 }
411 mutex_exit(&user->u_mutex);
412 }
413
414 /*
415 * Determine whether or not the user is an administrator.
416 * Members of the administrators group have administrative rights.
417 */
418 boolean_t
419 smb_user_is_admin(smb_user_t *user)
420 {
421 #ifdef _KERNEL
422 char sidstr[SMB_SID_STRSZ];
423 ksidlist_t *ksidlist;
424 ksid_t ksid1;
425 ksid_t *ksid2;
426 int i;
427 #endif /* _KERNEL */
428 boolean_t rc = B_FALSE;
429
430 ASSERT(user);
431 ASSERT(user->u_cred);
432
433 if (SMB_USER_IS_ADMIN(user))
434 return (B_TRUE);
506 {
507 int rc = 0;
508
509 ASSERT(user);
510 ASSERT(user->u_magic == SMB_USER_MAGIC);
511
512 if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
513 return (smb_user_enum_private(user, svcenum));
514
515 return (rc);
516 }
517
518 /* *************************** Static Functions ***************************** */
519
520 /*
521 * Delete a user. The tree list should be empty.
522 *
523 * Remove the user from the session's user list before freeing resources
524 * associated with the user.
525 */
526 void
527 smb_user_delete(void *arg)
528 {
529 smb_session_t *session;
530 smb_user_t *user = (smb_user_t *)arg;
531
532 SMB_USER_VALID(user);
533 ASSERT(user->u_refcnt == 0);
534 ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
535 ASSERT(user->u_authsock == NULL);
536
537 session = user->u_session;
538 smb_llist_enter(&session->s_user_list, RW_WRITER);
539 smb_llist_remove(&session->s_user_list, user);
540 smb_idpool_free(&session->s_uid_pool, user->u_uid);
541 smb_llist_exit(&session->s_user_list);
542
543 mutex_enter(&user->u_mutex);
544 mutex_exit(&user->u_mutex);
545
546 user->u_magic = (uint32_t)~SMB_USER_MAGIC;
547 mutex_destroy(&user->u_mutex);
548 if (user->u_cred)
549 crfree(user->u_cred);
550 if (user->u_privcred)
551 crfree(user->u_privcred);
552 smb_mem_free(user->u_name);
553 smb_mem_free(user->u_domain);
554 kmem_cache_free(smb_cache_user, user);
555 }
556
557 cred_t *
558 smb_user_getcred(smb_user_t *user)
559 {
560 return (user->u_cred);
561 }
562
656 }
657
658 void
659 smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
660 {
661 smb_session_t *session;
662 char *buf;
663
664 ASSERT(user);
665 ASSERT(user->u_domain);
666 ASSERT(user->u_name);
667
668 session = user->u_session;
669 ASSERT(session);
670 ASSERT(session->workstation);
671
672 info->ui_session_id = session->s_kid;
673 info->ui_native_os = session->native_os;
674 info->ui_ipaddr = session->ipaddr;
675 info->ui_numopens = session->s_file_cnt;
676 info->ui_smb_uid = user->u_uid;
677 info->ui_logon_time = user->u_logon_time;
678 info->ui_flags = user->u_flags;
679 info->ui_posix_uid = crgetuid(user->u_cred);
680
681 info->ui_domain_len = user->u_domain_len;
682 info->ui_domain = smb_mem_strdup(user->u_domain);
683
684 info->ui_account_len = user->u_name_len;
685 info->ui_account = smb_mem_strdup(user->u_name);
686
687 buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
688 smb_session_getclient(session, buf, MAXNAMELEN);
689 info->ui_workstation_len = strlen(buf) + 1;
690 info->ui_workstation = smb_mem_strdup(buf);
691 kmem_free(buf, MAXNAMELEN);
692 }
693
694 void
695 smb_user_netinfo_fini(smb_netuserinfo_t *info)
696 {
697 if (info == NULL)
698 return;
699
700 if (info->ui_domain)
701 smb_mem_free(info->ui_domain);
702 if (info->ui_account)
703 smb_mem_free(info->ui_account);
704 if (info->ui_workstation)
705 smb_mem_free(info->ui_workstation);
706
707 bzero(info, sizeof (smb_netuserinfo_t));
708 }
709
710 static void
711 smb_user_auth_logoff(smb_user_t *user)
712 {
713 uint32_t audit_sid = user->u_audit_sid;
714
715 (void) smb_kdoor_upcall(user->u_server, SMB_DR_USER_AUTH_LOGOFF,
716 &audit_sid, xdr_uint32_t, NULL, NULL);
717 }
|
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 * | |
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);
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);
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
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 }
|