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 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
25 * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
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 * Tree State Machine
71 * ------------------
72 *
73 * +-----------------------------+ T0
74 * | SMB_TREE_STATE_CONNECTED |<----------- Creation/Allocation
75 * +-----------------------------+
76 * |
77 * | T1
78 * |
79 * v
80 * +------------------------------+
81 * | SMB_TREE_STATE_DISCONNECTING |
82 * +------------------------------+
83 * |
84 * | T2
85 * |
86 * v
87 * +-----------------------------+ T3
88 * | SMB_TREE_STATE_DISCONNECTED |----------> Deletion/Free
89 * +-----------------------------+
90 *
91 * SMB_TREE_STATE_CONNECTED
92 *
93 * While in this state:
94 * - The tree is queued in the list of trees of its user.
95 * - References will be given out if the tree is looked up.
96 * - Files under that tree can be accessed.
97 *
98 * SMB_TREE_STATE_DISCONNECTING
99 *
100 * While in this state:
101 * - The tree is queued in the list of trees of its user.
102 * - References will not be given out if the tree is looked up.
103 * - The files and directories open under the tree are being closed.
104 * - The resources associated with the tree remain.
105 *
106 * SMB_TREE_STATE_DISCONNECTED
107 *
108 * While in this state:
109 * - The tree is queued in the list of trees of its user.
110 * - References will not be given out if the tree is looked up.
111 * - The tree has no more files and directories opened.
112 * - The resources associated with the tree remain.
113 *
114 * Transition T0
115 *
116 * This transition occurs in smb_tree_connect(). A new tree is created and
117 * added to the list of trees of a user.
118 *
119 * Transition T1
120 *
121 * This transition occurs in smb_tree_disconnect().
122 *
123 * Transition T2
124 *
125 * This transition occurs in smb_tree_disconnect()
126 *
127 * Transition T3
128 *
129 * This transition occurs in smb_tree_release(). The resources associated
130 * with the tree are freed as well as the tree structure. For the transition
131 * to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED and the
132 * reference count must be zero.
133 *
134 * Comments
135 * --------
136 *
137 * The state machine of the tree structures is controlled by 3 elements:
138 * - The list of trees of the user it belongs to.
139 * - The mutex embedded in the structure itself.
140 * - The reference count.
141 *
142 * There's a mutex embedded in the tree structure used to protect its fields
143 * and there's a lock embedded in the list of trees of a user. To
144 * increment or to decrement the reference count the mutex must be entered.
145 * To insert the tree into the list of trees of the user and to remove
146 * the tree from it, the lock must be entered in RW_WRITER mode.
147 *
148 * Rules of access to a tree structure:
149 *
150 * 1) In order to avoid deadlocks, when both (mutex and lock of the user
151 * list) have to be entered, the lock must be entered first. Additionally,
152 * when both the (mutex and lock of the ofile list) have to be entered,
153 * the mutex must be entered first. However, the ofile list lock must NOT
154 * be dropped while the mutex is held in such a way that the ofile deleteq
155 * is flushed.
156 *
157 * 2) All actions applied to a tree require a reference count.
158 *
159 * 3) There are 2 ways of getting a reference count: when a tree is
160 * connected and when a tree is looked up.
161 *
162 * It should be noted that the reference count of a tree registers the
163 * number of references to the tree in other structures (such as an smb
164 * request). The reference count is not incremented in these 2 instances:
165 *
166 * 1) The tree is connected. An tree is anchored by its state. If there's
167 * no activity involving a tree currently connected, the reference
168 * count of that tree is zero.
169 *
170 * 2) The tree is queued in the list of trees of the user. The fact of
171 * being queued in that list is NOT registered by incrementing the
172 * reference count.
173 */
174
175 #include <sys/refstr_impl.h>
176 #include <smbsrv/smb_kproto.h>
177 #include <smbsrv/smb_ktypes.h>
178 #include <smbsrv/smb_fsops.h>
179 #include <smbsrv/smb_share.h>
180
181 int smb_tcon_mute = 0;
182
183 uint32_t smb_tree_connect_core(smb_request_t *);
184 uint32_t smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *);
185 uint32_t smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *);
186 uint32_t smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *);
187 static void smb_tree_dealloc(void *);
188 static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
189 static char *smb_tree_get_sharename(char *);
190 static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *);
191 static void smb_tree_get_creation(smb_node_t *, smb_tree_t *);
192 static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
193 static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *);
194 static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
195 static void smb_tree_close_odirs(smb_tree_t *, uint32_t);
196 static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int);
197 static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *);
198 static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *);
199 static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *);
200 static void smb_tree_netinfo_fini(smb_netconnectinfo_t *);
201
202 uint32_t
smb_tree_connect(smb_request_t * sr)203 smb_tree_connect(smb_request_t *sr)
204 {
205 smb_server_t *sv = sr->sr_server;
206 uint32_t status;
207
208 if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) {
209 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
210 }
211
212 status = smb_tree_connect_core(sr);
213 smb_threshold_exit(&sv->sv_tcon_ct);
214 return (status);
215 }
216
217 /*
218 * Lookup the share name dispatch the appropriate stype handler.
219 * Share names are case insensitive so we map the share name to
220 * lower-case as a convenience for internal processing.
221 *
222 * Valid service values are:
223 * A: Disk share
224 * LPT1: Printer
225 * IPC Named pipe (IPC$ is reserved as the named pipe share).
226 * COMM Communications device
227 * ????? Any type of device (wildcard)
228 */
229 uint32_t
smb_tree_connect_core(smb_request_t * sr)230 smb_tree_connect_core(smb_request_t *sr)
231 {
232 smb_arg_tcon_t *tcon = &sr->sr_tcon;
233 smb_kshare_t *si;
234 char *name;
235 uint32_t status;
236
237 (void) smb_strlwr(tcon->path);
238
239 if ((name = smb_tree_get_sharename(tcon->path)) == NULL) {
240 smb_tree_log(sr, tcon->path, "invalid UNC path");
241 return (NT_STATUS_BAD_NETWORK_NAME);
242 }
243
244 si = smb_kshare_lookup(sr->sr_server, name);
245 if (si == NULL) {
246 smb_tree_log(sr, name, "share not found");
247 return (NT_STATUS_BAD_NETWORK_NAME);
248 }
249
250 if (!strcasecmp(SMB_SHARE_PRINT, name)) {
251 smb_kshare_release(sr->sr_server, si);
252 smb_tree_log(sr, name, "access not permitted");
253 return (NT_STATUS_ACCESS_DENIED);
254 }
255
256 /* NB: name points into tcon->path - don't free it. */
257 tcon->name = name;
258 sr->sr_tcon.si = si;
259
260 /*
261 * [MS-SMB2] 3.3.5.7 Receiving an SMB2 TREE_CONNECT Request
262 *
263 * If we support 3.x, RejectUnencryptedAccess is TRUE,
264 * if Tcon.EncryptData is TRUE or global EncryptData is TRUE,
265 * and the connection doesn't support encryption,
266 * return ACCESS_DENIED.
267 *
268 * If RejectUnencryptedAccess is TRUE, we force max_protocol
269 * to at least 3.0. Additionally, if the tree requires encryption,
270 * we don't care what we support, we still enforce encryption.
271 */
272 if ((sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED ||
273 si->shr_encrypt == SMB_CONFIG_REQUIRED) &&
274 (sr->session->srv_cap & SMB2_CAP_ENCRYPTION) == 0) {
275 status = NT_STATUS_ACCESS_DENIED;
276 goto out;
277 }
278
279 switch (si->shr_type & STYPE_MASK) {
280 case STYPE_DISKTREE:
281 status = smb_tree_connect_disk(sr, &sr->sr_tcon);
282 break;
283 case STYPE_IPC:
284 status = smb_tree_connect_ipc(sr, &sr->sr_tcon);
285 break;
286 case STYPE_PRINTQ:
287 status = smb_tree_connect_printq(sr, &sr->sr_tcon);
288 break;
289 default:
290 status = NT_STATUS_BAD_DEVICE_TYPE;
291 break;
292 }
293
294 out:
295 smb_kshare_release(sr->sr_server, si);
296 sr->sr_tcon.si = NULL;
297
298 return (status);
299 }
300
301 /*
302 * Disconnect a tree.
303 *
304 * The "do_exec" arg is obsolete and ignored.
305 */
306 void
smb_tree_disconnect(smb_tree_t * tree,boolean_t do_exec)307 smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec)
308 {
309 _NOTE(ARGUNUSED(do_exec))
310 smb_shr_execinfo_t execinfo;
311
312 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
313
314 mutex_enter(&tree->t_mutex);
315 ASSERT(tree->t_refcnt);
316
317 if (!smb_tree_is_connected_locked(tree)) {
318 mutex_exit(&tree->t_mutex);
319 return;
320 }
321
322 /*
323 * Indicate that the disconnect process has started.
324 */
325 tree->t_state = SMB_TREE_STATE_DISCONNECTING;
326 mutex_exit(&tree->t_mutex);
327
328 /*
329 * The files opened under this tree are closed.
330 */
331 smb_ofile_close_all(tree, 0);
332 /*
333 * The directories opened under this tree are closed.
334 */
335 smb_tree_close_odirs(tree, 0);
336
337 if ((tree->t_execflags & SMB_EXEC_UNMAP) != 0) {
338 smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP);
339 (void) smb_kshare_exec(tree->t_server, &execinfo);
340 }
341 }
342
343 /*
344 * Take a reference on a tree.
345 */
346 boolean_t
smb_tree_hold(smb_tree_t * tree)347 smb_tree_hold(
348 smb_tree_t *tree)
349 {
350 SMB_TREE_VALID(tree);
351
352 mutex_enter(&tree->t_mutex);
353
354 if (smb_tree_is_connected_locked(tree)) {
355 tree->t_refcnt++;
356 mutex_exit(&tree->t_mutex);
357 return (B_TRUE);
358 }
359
360 mutex_exit(&tree->t_mutex);
361 return (B_FALSE);
362 }
363
364 /*
365 * Bump the hold count regardless of the tree state. This is used in
366 * some internal code paths where we've already checked that we had a
367 * valid tree connection, and don't want to deal with the possiblity
368 * that the tree state might have changed to disconnecting after our
369 * original hold was taken. It's correct to continue processing a
370 * request even when new requests cannot lookup that tree anymore.
371 */
372 void
smb_tree_hold_internal(smb_tree_t * tree)373 smb_tree_hold_internal(
374 smb_tree_t *tree)
375 {
376 SMB_TREE_VALID(tree);
377
378 mutex_enter(&tree->t_mutex);
379 tree->t_refcnt++;
380 mutex_exit(&tree->t_mutex);
381 }
382
383 /*
384 * Release a reference on a tree. If the tree is disconnected and the
385 * reference count falls to zero, post the object for deletion.
386 * Object deletion is deferred to avoid modifying a list while an
387 * iteration may be in progress.
388 */
389 void
smb_tree_release(smb_tree_t * tree)390 smb_tree_release(
391 smb_tree_t *tree)
392 {
393 SMB_TREE_VALID(tree);
394
395 /* flush the ofile and odir lists' delete queues */
396 smb_llist_flush(&tree->t_ofile_list);
397 smb_llist_flush(&tree->t_odir_list);
398
399 mutex_enter(&tree->t_mutex);
400 ASSERT(tree->t_refcnt);
401 tree->t_refcnt--;
402
403 switch (tree->t_state) {
404 case SMB_TREE_STATE_DISCONNECTING:
405 if (tree->t_refcnt == 0) {
406 smb_session_t *ssn = tree->t_session;
407 tree->t_state = SMB_TREE_STATE_DISCONNECTED;
408 smb_llist_post(&ssn->s_tree_list, tree,
409 smb_tree_dealloc);
410 }
411 break;
412 case SMB_TREE_STATE_CONNECTED:
413 break;
414 default:
415 ASSERT(0);
416 break;
417 }
418
419 mutex_exit(&tree->t_mutex);
420 }
421
422 /*
423 * Close ofiles and odirs that match pid.
424 */
425 void
smb_tree_close_pid(smb_tree_t * tree,uint32_t pid)426 smb_tree_close_pid(
427 smb_tree_t *tree,
428 uint32_t pid)
429 {
430 ASSERT(tree);
431 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
432
433 smb_ofile_close_all(tree, pid);
434 smb_tree_close_odirs(tree, pid);
435 }
436
437 /*
438 * Check whether or not a tree supports the features identified by flags.
439 */
440 boolean_t
smb_tree_has_feature(smb_tree_t * tree,uint32_t flags)441 smb_tree_has_feature(smb_tree_t *tree, uint32_t flags)
442 {
443 ASSERT(tree);
444 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
445
446 return ((tree->t_flags & flags) == flags);
447 }
448
449 /*
450 * If the enumeration request is for tree data, handle the request
451 * here. Otherwise, pass it on to the ofiles.
452 *
453 * This function should be called with a hold on the tree.
454 */
455 int
smb_tree_enum(smb_tree_t * tree,smb_svcenum_t * svcenum)456 smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
457 {
458 smb_llist_t *of_list;
459 smb_ofile_t *of;
460 int rc = 0;
461
462 if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE)
463 return (smb_tree_enum_private(tree, svcenum));
464
465 of_list = &tree->t_ofile_list;
466 smb_llist_enter(of_list, RW_READER);
467
468 of = smb_llist_head(of_list);
469 while (of) {
470 if (smb_ofile_hold(of)) {
471 rc = smb_ofile_enum(of, svcenum);
472 smb_ofile_release(of);
473 }
474 if (rc != 0)
475 break;
476 of = smb_llist_next(of_list, of);
477 }
478
479 smb_llist_exit(of_list);
480
481 return (rc);
482 }
483
484 /*
485 * Close a file by its unique id.
486 */
487 int
smb_tree_fclose(smb_tree_t * tree,uint32_t uniqid)488 smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid)
489 {
490 smb_ofile_t *of;
491
492 ASSERT(tree);
493 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
494
495 /*
496 * Note that ORPHANED ofiles aren't fclosable, as they have
497 * no session, user, or tree by which they might be found.
498 * They will eventually expire.
499 */
500 if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL)
501 return (ENOENT);
502
503 if (smb_ofile_disallow_fclose(of)) {
504 smb_ofile_release(of);
505 return (EACCES);
506 }
507
508 smb_ofile_close(of, 0);
509 smb_ofile_release(of);
510 return (0);
511 }
512
513 /* *************************** Static Functions ***************************** */
514
515 #define SHARES_DIR ".zfs/shares/"
516
517 /*
518 * Calculates permissions given by the share's ACL to the
519 * user in the passed request. The default is full access.
520 * If any error occurs, full access is granted.
521 *
522 * Using the vnode of the share path find the root directory
523 * of the mounted file system. Then look to see if there is a
524 * .zfs/shares directory and if there is, lookup the file with
525 * the same name as the share name in it. The ACL set for this
526 * file is the share's ACL which is used for access check here.
527 */
528 static uint32_t
smb_tree_acl_access(smb_request_t * sr,const smb_kshare_t * si,vnode_t * pathvp)529 smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp)
530 {
531 smb_user_t *user;
532 cred_t *cred;
533 int rc;
534 vfs_t *vfsp;
535 vnode_t *root = NULL;
536 vnode_t *sharevp = NULL;
537 char *sharepath;
538 struct pathname pnp;
539 size_t size;
540 uint32_t access;
541
542 user = sr->uid_user;
543 cred = user->u_cred;
544 access = ACE_ALL_PERMS;
545
546 if (si->shr_flags & SMB_SHRF_AUTOHOME) {
547 /*
548 * An autohome share owner gets full access to the share.
549 * Everyone else is denied access.
550 */
551 if (si->shr_uid != crgetuid(cred))
552 access = 0;
553
554 return (access);
555 }
556
557 /*
558 * The hold on 'root' is released by the lookuppnvp() that follows
559 */
560 vfsp = pathvp->v_vfsp;
561 if (vfsp != NULL)
562 rc = VFS_ROOT(vfsp, &root);
563 else
564 rc = ENOENT;
565
566 if (rc != 0)
567 return (access);
568
569
570 size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1;
571 sharepath = smb_srm_alloc(sr, size);
572 (void) snprintf(sharepath, size, "%s%s", SHARES_DIR, si->shr_name);
573
574 pn_alloc(&pnp);
575 (void) pn_set(&pnp, sharepath);
576 rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root,
577 zone_kcred());
578 pn_free(&pnp);
579
580 /*
581 * Now get the effective access value based on cred and ACL values.
582 */
583 if (rc == 0) {
584 smb_vop_eaccess(sharevp, (int *)&access, V_ACE_MASK, NULL,
585 cred);
586 VN_RELE(sharevp);
587 }
588
589 return (access);
590 }
591
592 /*
593 * Performs the following access checks for a disk share:
594 *
595 * - No IPC/anonymous user is allowed
596 *
597 * - If user is Guest, guestok property of the share should be
598 * enabled
599 *
600 * - If this is an Admin share, the user should have administrative
601 * privileges
602 *
603 * - Host based access control lists
604 *
605 * - Share ACL
606 *
607 * Returns the access allowed or 0 if access is denied.
608 */
609 static uint32_t
smb_tree_chkaccess(smb_request_t * sr,smb_kshare_t * shr,vnode_t * vp)610 smb_tree_chkaccess(smb_request_t *sr, smb_kshare_t *shr, vnode_t *vp)
611 {
612 smb_user_t *user = sr->uid_user;
613 char *sharename = shr->shr_name;
614 uint32_t host_access;
615 uint32_t acl_access;
616 uint32_t access;
617
618 if (user->u_flags & SMB_USER_FLAG_ANON) {
619 smb_tree_log(sr, sharename, "access denied: IPC only");
620 return (0);
621 }
622
623 if ((user->u_flags & SMB_USER_FLAG_GUEST) &&
624 ((shr->shr_flags & SMB_SHRF_GUEST_OK) == 0)) {
625 smb_tree_log(sr, sharename, "access denied: guest disabled");
626 return (0);
627 }
628
629 if ((shr->shr_flags & SMB_SHRF_ADMIN) && !smb_user_is_admin(user)) {
630 smb_tree_log(sr, sharename, "access denied: not admin");
631 return (0);
632 }
633
634 host_access = smb_kshare_hostaccess(shr, sr->session);
635 if ((host_access & ACE_ALL_PERMS) == 0) {
636 smb_tree_log(sr, sharename, "access denied: host access");
637 return (0);
638 }
639
640 acl_access = smb_tree_acl_access(sr, shr, vp);
641 if ((acl_access & ACE_ALL_PERMS) == 0) {
642 smb_tree_log(sr, sharename, "access denied: share ACL");
643 return (0);
644 }
645
646 access = host_access & acl_access;
647 if ((access & ACE_ALL_PERMS) == 0) {
648 smb_tree_log(sr, sharename, "access denied");
649 return (0);
650 }
651
652 return (access);
653 }
654
655 /* How long should tree connect wait for DH import to complete? */
656 int smb_tcon_import_wait = 20; /* sec. */
657
658 /*
659 * Connect a share for use with files and directories.
660 */
661 uint32_t
smb_tree_connect_disk(smb_request_t * sr,smb_arg_tcon_t * tcon)662 smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon)
663 {
664 char *sharename = tcon->path;
665 const char *any = "?????";
666 smb_user_t *user = sr->uid_user;
667 smb_node_t *snode = NULL;
668 smb_kshare_t *si = tcon->si;
669 char *service = tcon->service;
670 smb_tree_t *tree;
671 int rc;
672 uint32_t access;
673 smb_shr_execinfo_t execinfo;
674 clock_t time;
675
676 ASSERT(user);
677 ASSERT(user->u_cred);
678
679 if (service != NULL &&
680 strcmp(service, any) != 0 &&
681 strcasecmp(service, "A:") != 0) {
682 smb_tree_log(sr, sharename, "invalid service (%s)", service);
683 return (NT_STATUS_BAD_DEVICE_TYPE);
684 }
685
686 /*
687 * Check that the shared directory exists.
688 */
689 snode = si->shr_root_node;
690 if (snode == NULL) {
691 smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
692 return (NT_STATUS_BAD_NETWORK_NAME);
693 }
694
695 if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
696 return (NT_STATUS_ACCESS_DENIED);
697 }
698
699 /*
700 * Wait for DH import of persistent handles to finish.
701 * If we timeout, it's not clear what status to return,
702 * but as the share is not really available yet, let's
703 * return the status for "no such share".
704 */
705 time = SEC_TO_TICK(smb_tcon_import_wait) + ddi_get_lbolt();
706 mutex_enter(&si->shr_mutex);
707 while (si->shr_import_busy != NULL) {
708 if (cv_timedwait(&si->shr_cv, &si->shr_mutex, time) < 0) {
709 mutex_exit(&si->shr_mutex);
710 return (NT_STATUS_BAD_NETWORK_NAME);
711 }
712 }
713 mutex_exit(&si->shr_mutex);
714
715 /*
716 * Set up the OptionalSupport for this share.
717 */
718 tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
719
720 switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
721 case SMB_SHRF_CSC_DISABLED:
722 tcon->optional_support |= SMB_CSC_CACHE_NONE;
723 break;
724 case SMB_SHRF_CSC_AUTO:
725 tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT;
726 break;
727 case SMB_SHRF_CSC_VDO:
728 tcon->optional_support |= SMB_CSC_CACHE_VDO;
729 break;
730 case SMB_SHRF_CSC_MANUAL:
731 default:
732 /*
733 * Default to SMB_CSC_CACHE_MANUAL_REINT.
734 */
735 break;
736 }
737
738 /* ABE support */
739 if (si->shr_flags & SMB_SHRF_ABE)
740 tcon->optional_support |=
741 SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM;
742
743 if (si->shr_flags & SMB_SHRF_DFSROOT)
744 tcon->optional_support |= SMB_SHARE_IS_IN_DFS;
745
746 /* if 'smb' zfs property: shortnames=disabled */
747 if (!smb_shortnames)
748 sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME;
749
750 tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
751
752 if (tree == NULL)
753 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
754
755 if (tree->t_execflags & SMB_EXEC_MAP) {
756 smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP);
757
758 rc = smb_kshare_exec(tree->t_server, &execinfo);
759
760 if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) {
761 /*
762 * Inline parts of: smb_tree_disconnect()
763 * Not using smb_tree_disconnect() for cleanup
764 * here because: we don't want an exec up-call,
765 * and there can't be any opens as we never
766 * returned this TID to the client.
767 */
768 mutex_enter(&tree->t_mutex);
769 tree->t_state = SMB_TREE_STATE_DISCONNECTING;
770 mutex_exit(&tree->t_mutex);
771
772 smb_tree_release(tree);
773 return (NT_STATUS_ACCESS_DENIED);
774 }
775 }
776
777 sr->tid_tree = tree;
778 sr->smb_tid = tree->t_tid;
779
780 return (0);
781 }
782
783 /*
784 * Shares have both a share and host based access control. The access
785 * granted will be minimum permissions based on both hostaccess
786 * (permissions allowed by host based access) and aclaccess (from the
787 * share ACL).
788 */
789 uint32_t
smb_tree_connect_printq(smb_request_t * sr,smb_arg_tcon_t * tcon)790 smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon)
791 {
792 char *sharename = tcon->path;
793 const char *any = "?????";
794 smb_user_t *user = sr->uid_user;
795 smb_node_t *dnode = NULL;
796 smb_node_t *snode = NULL;
797 smb_kshare_t *si = tcon->si;
798 char *service = tcon->service;
799 char last_component[MAXNAMELEN];
800 smb_tree_t *tree;
801 int rc;
802 uint32_t access;
803
804 ASSERT(user);
805 ASSERT(user->u_cred);
806
807 if (sr->sr_server->sv_cfg.skc_print_enable == 0) {
808 smb_tree_log(sr, sharename, "printing disabled");
809 return (NT_STATUS_BAD_NETWORK_NAME);
810 }
811
812 if (service != NULL &&
813 strcmp(service, any) != 0 &&
814 strcasecmp(service, "LPT1:") != 0) {
815 smb_tree_log(sr, sharename, "invalid service (%s)", service);
816 return (NT_STATUS_BAD_DEVICE_TYPE);
817 }
818
819 /*
820 * Check that the shared directory exists.
821 */
822 rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode,
823 last_component);
824 if (rc == 0) {
825 rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS,
826 sr->sr_server->si_root_smb_node, dnode, last_component,
827 &snode);
828
829 smb_node_release(dnode);
830 }
831
832 if (rc) {
833 if (snode)
834 smb_node_release(snode);
835
836 smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
837 return (NT_STATUS_BAD_NETWORK_NAME);
838 }
839
840 if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
841 smb_node_release(snode);
842 return (NT_STATUS_ACCESS_DENIED);
843 }
844
845 tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
846
847 tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
848
849 smb_node_release(snode);
850
851 if (tree == NULL)
852 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
853
854 sr->tid_tree = tree;
855 sr->smb_tid = tree->t_tid;
856
857 return (0);
858 }
859
860 /*
861 * Connect an IPC share for use with named pipes.
862 */
863 uint32_t
smb_tree_connect_ipc(smb_request_t * sr,smb_arg_tcon_t * tcon)864 smb_tree_connect_ipc(smb_request_t *sr, smb_arg_tcon_t *tcon)
865 {
866 char *name = tcon->path;
867 const char *any = "?????";
868 smb_user_t *user = sr->uid_user;
869 smb_tree_t *tree;
870 smb_kshare_t *si = tcon->si;
871 char *service = tcon->service;
872
873 ASSERT(user);
874
875 if (service != NULL &&
876 strcmp(service, any) != 0 &&
877 strcasecmp(service, "IPC") != 0) {
878 smb_tree_log(sr, name, "invalid service (%s)", service);
879 return (NT_STATUS_BAD_DEVICE_TYPE);
880 }
881
882 if ((user->u_flags & SMB_USER_FLAG_ANON) &&
883 sr->sr_cfg->skc_restrict_anon) {
884 smb_tree_log(sr, name, "access denied: restrict anonymous");
885 return (NT_STATUS_ACCESS_DENIED);
886 }
887
888 tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
889
890 tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
891 if (tree == NULL)
892 return (NT_STATUS_INSUFF_SERVER_RESOURCES);
893
894 sr->tid_tree = tree;
895 sr->smb_tid = tree->t_tid;
896
897 return (0);
898 }
899
900 /*
901 * Allocate a tree.
902 */
903 smb_tree_t *
smb_tree_alloc(smb_request_t * sr,const smb_kshare_t * si,smb_node_t * snode,uint32_t access,uint32_t execflags)904 smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
905 smb_node_t *snode, uint32_t access, uint32_t execflags)
906 {
907 smb_session_t *session = sr->session;
908 smb_tree_t *tree;
909 uint32_t stype = si->shr_type;
910 uint16_t tid;
911
912 if (smb_idpool_alloc(&session->s_tid_pool, &tid))
913 return (NULL);
914
915 tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP);
916 bzero(tree, sizeof (smb_tree_t));
917
918 tree->t_session = session;
919 tree->t_server = session->s_server;
920
921 if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
922 if (smb_tree_getattr(si, snode, tree) != 0) {
923 smb_idpool_free(&session->s_tid_pool, tid);
924 kmem_cache_free(smb_cache_tree, tree);
925 return (NULL);
926 }
927 }
928
929 if (smb_idpool_constructor(&tree->t_fid_pool)) {
930 smb_idpool_free(&session->s_tid_pool, tid);
931 kmem_cache_free(smb_cache_tree, tree);
932 return (NULL);
933 }
934
935 if (smb_idpool_constructor(&tree->t_odid_pool)) {
936 smb_idpool_destructor(&tree->t_fid_pool);
937 smb_idpool_free(&session->s_tid_pool, tid);
938 kmem_cache_free(smb_cache_tree, tree);
939 return (NULL);
940 }
941
942 smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
943 offsetof(smb_ofile_t, f_tree_lnd));
944
945 smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
946 offsetof(smb_odir_t, d_lnd));
947
948 (void) strlcpy(tree->t_sharename, si->shr_name,
949 sizeof (tree->t_sharename));
950 (void) strlcpy(tree->t_resource, si->shr_path,
951 sizeof (tree->t_resource));
952
953 mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
954
955 tree->t_refcnt = 1;
956 tree->t_tid = tid;
957 tree->t_res_type = stype;
958 tree->t_state = SMB_TREE_STATE_CONNECTED;
959 tree->t_magic = SMB_TREE_MAGIC;
960 tree->t_access = access;
961 tree->t_connect_time = gethrestime_sec();
962 tree->t_execflags = execflags;
963
964 /* grab a ref for tree->t_owner */
965 smb_user_hold_internal(sr->uid_user);
966 tree->t_owner = sr->uid_user;
967
968 /* if FS is readonly, enforce that here */
969 if (tree->t_flags & SMB_TREE_READONLY)
970 tree->t_access &= ~ACE_ALL_WRITE_PERMS;
971
972 if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
973 smb_node_ref(snode);
974 tree->t_snode = snode;
975 tree->t_acltype = smb_fsop_acltype(snode);
976 }
977
978 smb_llist_enter(&session->s_tree_list, RW_WRITER);
979 smb_llist_insert_head(&session->s_tree_list, tree);
980 smb_llist_exit(&session->s_tree_list);
981 atomic_inc_32(&session->s_tree_cnt);
982 smb_server_inc_trees(session->s_server);
983 return (tree);
984 }
985
986 /*
987 * Deallocate a tree. The open file and open directory lists should be
988 * empty.
989 *
990 * Remove the tree from the user's tree list before freeing resources
991 * associated with the tree.
992 */
993 static void
smb_tree_dealloc(void * arg)994 smb_tree_dealloc(void *arg)
995 {
996 smb_session_t *session;
997 smb_tree_t *tree = (smb_tree_t *)arg;
998
999 SMB_TREE_VALID(tree);
1000 ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
1001 ASSERT(tree->t_refcnt == 0);
1002
1003 smb_server_dec_trees(tree->t_server);
1004
1005 session = tree->t_session;
1006 smb_llist_enter(&session->s_tree_list, RW_WRITER);
1007 smb_llist_remove(&session->s_tree_list, tree);
1008 smb_idpool_free(&session->s_tid_pool, tree->t_tid);
1009 atomic_dec_32(&session->s_tree_cnt);
1010 smb_llist_exit(&session->s_tree_list);
1011
1012 /*
1013 * This tree is no longer on s_tree_list, however...
1014 *
1015 * This is called via smb_llist_post, which means it may run
1016 * BEFORE smb_tree_release drops t_mutex (if another thread
1017 * flushes the delete queue before we do). Synchronize.
1018 */
1019 mutex_enter(&tree->t_mutex);
1020 mutex_exit(&tree->t_mutex);
1021
1022 tree->t_magic = (uint32_t)~SMB_TREE_MAGIC;
1023
1024 if (tree->t_snode)
1025 smb_node_release(tree->t_snode);
1026
1027 mutex_destroy(&tree->t_mutex);
1028 smb_llist_destructor(&tree->t_ofile_list);
1029 smb_llist_destructor(&tree->t_odir_list);
1030 smb_idpool_destructor(&tree->t_fid_pool);
1031 smb_idpool_destructor(&tree->t_odid_pool);
1032
1033 SMB_USER_VALID(tree->t_owner);
1034 smb_user_release(tree->t_owner);
1035
1036 kmem_cache_free(smb_cache_tree, tree);
1037 }
1038
1039 /*
1040 * Determine whether or not a tree is connected.
1041 * This function must be called with the tree mutex held.
1042 */
1043 static boolean_t
smb_tree_is_connected_locked(smb_tree_t * tree)1044 smb_tree_is_connected_locked(smb_tree_t *tree)
1045 {
1046 switch (tree->t_state) {
1047 case SMB_TREE_STATE_CONNECTED:
1048 return (B_TRUE);
1049
1050 case SMB_TREE_STATE_DISCONNECTING:
1051 case SMB_TREE_STATE_DISCONNECTED:
1052 /*
1053 * The tree exists but is being disconnected or destroyed.
1054 */
1055 return (B_FALSE);
1056
1057 default:
1058 ASSERT(0);
1059 return (B_FALSE);
1060 }
1061 }
1062
1063 /*
1064 * Return a pointer to the share name within a share resource path.
1065 *
1066 * The share path may be a Uniform Naming Convention (UNC) string
1067 * (\\server\share) or simply the share name. We validate the UNC
1068 * format but we don't look at the server name.
1069 */
1070 static char *
smb_tree_get_sharename(char * unc_path)1071 smb_tree_get_sharename(char *unc_path)
1072 {
1073 char *sharename = unc_path;
1074
1075 if (sharename[0] == '\\') {
1076 /*
1077 * Looks like a UNC path, validate the format.
1078 */
1079 if (sharename[1] != '\\')
1080 return (NULL);
1081
1082 if ((sharename = strchr(sharename+2, '\\')) == NULL)
1083 return (NULL);
1084
1085 ++sharename;
1086 } else if (strchr(sharename, '\\') != NULL) {
1087 /*
1088 * This should be a share name (no embedded \'s).
1089 */
1090 return (NULL);
1091 }
1092
1093 return (sharename);
1094 }
1095
1096 /*
1097 * Obtain the tree attributes: volume name, typename and flags.
1098 */
1099 static int
smb_tree_getattr(const smb_kshare_t * si,smb_node_t * node,smb_tree_t * tree)1100 smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree)
1101 {
1102 vfs_t *vfsp = SMB_NODE_VFS(node);
1103 vfs_t *realvfsp;
1104 smb_cfg_val_t srv_encrypt;
1105
1106 ASSERT(vfsp);
1107
1108 smb_tree_get_creation(node, tree);
1109 smb_tree_get_volname(vfsp, tree);
1110
1111 /*
1112 * In the case of an lofs mount, we need to ask the (real)
1113 * underlying filesystem about capabilities, where the
1114 * passed in vfs_t will be from lofs.
1115 */
1116 realvfsp = getvfs(&vfsp->vfs_fsid);
1117 if (realvfsp != NULL) {
1118 smb_tree_get_flags(si, realvfsp, tree);
1119 VFS_RELE(realvfsp);
1120 } else {
1121 cmn_err(CE_NOTE, "Failed getting info for share: %s",
1122 si->shr_name);
1123 /* do the best we can without realvfsp */
1124 smb_tree_get_flags(si, vfsp, tree);
1125 }
1126
1127 srv_encrypt = tree->t_session->s_server->sv_cfg.skc_encrypt;
1128 if (tree->t_session->dialect >= SMB_VERS_3_0) {
1129 if (si->shr_encrypt == SMB_CONFIG_REQUIRED ||
1130 srv_encrypt == SMB_CONFIG_REQUIRED)
1131 tree->t_encrypt = SMB_CONFIG_REQUIRED;
1132 else if (si->shr_encrypt == SMB_CONFIG_ENABLED ||
1133 srv_encrypt == SMB_CONFIG_ENABLED)
1134 tree->t_encrypt = SMB_CONFIG_ENABLED;
1135 else
1136 tree->t_encrypt = SMB_CONFIG_DISABLED;
1137 } else
1138 tree->t_encrypt = SMB_CONFIG_DISABLED;
1139
1140 return (0);
1141 }
1142
1143 /*
1144 * File volume creation time
1145 */
1146 static void
smb_tree_get_creation(smb_node_t * node,smb_tree_t * tree)1147 smb_tree_get_creation(smb_node_t *node, smb_tree_t *tree)
1148 {
1149 smb_attr_t attr;
1150 cred_t *kcr = zone_kcred();
1151
1152 bzero(&attr, sizeof (attr));
1153 attr.sa_mask = SMB_AT_CRTIME;
1154 (void) smb_node_getattr(NULL, node, kcr, NULL, &attr);
1155 /* On failure we'll have time zero, which is OK */
1156
1157 tree->t_create_time = attr.sa_crtime;
1158 }
1159
1160 /*
1161 * Extract the volume name.
1162 */
1163 static void
smb_tree_get_volname(vfs_t * vfsp,smb_tree_t * tree)1164 smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
1165 {
1166 #ifdef _FAKE_KERNEL
1167 _NOTE(ARGUNUSED(vfsp))
1168 (void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN);
1169 #else /* _FAKE_KERNEL */
1170 refstr_t *vfs_mntpoint;
1171 const char *s;
1172 char *name;
1173
1174 vfs_mntpoint = vfs_getmntpoint(vfsp);
1175
1176 s = refstr_value(vfs_mntpoint);
1177 s += strspn(s, "/");
1178 (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN);
1179
1180 refstr_rele(vfs_mntpoint);
1181
1182 name = tree->t_volume;
1183 (void) strsep((char **)&name, "/");
1184 #endif /* _FAKE_KERNEL */
1185 }
1186
1187 /*
1188 * Always set "unicode on disk" because we always use utf8 names locally.
1189 * Always set ACL support because the VFS will fake ACLs for file systems
1190 * that don't support them.
1191 *
1192 * Some flags are dependent on the typename, which is also set up here.
1193 * File system types are hardcoded in uts/common/os/vfs_conf.c.
1194 */
1195 static void
smb_tree_get_flags(const smb_kshare_t * si,vfs_t * vfsp,smb_tree_t * tree)1196 smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
1197 {
1198 smb_session_t *ssn = tree->t_session;
1199 struct vfssw *vswp;
1200
1201 typedef struct smb_mtype {
1202 char *mt_name;
1203 size_t mt_namelen;
1204 uint32_t mt_flags;
1205 } smb_mtype_t;
1206
1207 static smb_mtype_t smb_mtype[] = {
1208 #ifdef _FAKE_KERNEL
1209 /* See libfksmbsrv:fake_vfs.c */
1210 { "fake", 3, SMB_TREE_SPARSE},
1211 #endif /* _FAKE_KERNEL */
1212 { "zfs", 3, SMB_TREE_QUOTA | SMB_TREE_SPARSE},
1213 { "ufs", 3, 0 },
1214 { "nfs", 3, SMB_TREE_NFS_MOUNTED },
1215 { "tmpfs", 5, SMB_TREE_NO_EXPORT }
1216 };
1217 smb_mtype_t *mtype;
1218 char *name;
1219 uint32_t flags =
1220 SMB_TREE_SUPPORTS_ACLS |
1221 SMB_TREE_UNICODE_ON_DISK;
1222 int i;
1223
1224 if (si->shr_flags & SMB_SHRF_DFSROOT)
1225 flags |= SMB_TREE_DFSROOT;
1226
1227 if (si->shr_flags & SMB_SHRF_CATIA)
1228 flags |= SMB_TREE_CATIA;
1229
1230 if (si->shr_flags & SMB_SHRF_ABE)
1231 flags |= SMB_TREE_ABE;
1232
1233 if (si->shr_flags & SMB_SHRF_CA)
1234 flags |= SMB_TREE_CA;
1235
1236 if (si->shr_flags & SMB_SHRF_FSO)
1237 flags |= SMB_TREE_FORCE_L2_OPLOCK;
1238
1239 if (ssn->s_cfg.skc_oplock_enable) {
1240 /* if 'smb' zfs property: oplocks=enabled */
1241 flags |= SMB_TREE_OPLOCKS;
1242 }
1243
1244 /* Global config option for now. Later make per-share. */
1245 if (ssn->s_cfg.skc_traverse_mounts)
1246 flags |= SMB_TREE_TRAVERSE_MOUNTS;
1247
1248 /* if 'smb' zfs property: shortnames=enabled */
1249 if (smb_shortnames)
1250 flags |= SMB_TREE_SHORTNAMES;
1251
1252 if (vfsp->vfs_flag & VFS_RDONLY)
1253 flags |= SMB_TREE_READONLY;
1254
1255 if (vfsp->vfs_flag & VFS_XATTR)
1256 flags |= SMB_TREE_STREAMS;
1257
1258 vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp));
1259 if (vswp != NULL) {
1260 name = vswp->vsw_name;
1261 vfs_unrefvfssw(vswp);
1262 } else {
1263 name = "?";
1264 }
1265
1266 for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
1267 mtype = &smb_mtype[i];
1268 if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
1269 flags |= mtype->mt_flags;
1270 }
1271
1272 /*
1273 * SMB_TREE_QUOTA will be on here if the FS is ZFS. We want to
1274 * turn it OFF when the share property says false.
1275 */
1276 if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0)
1277 flags &= ~SMB_TREE_QUOTA;
1278
1279 (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
1280 (void) smb_strupr((char *)tree->t_typename);
1281
1282 if (vfs_has_feature(vfsp, VFSFT_XVATTR))
1283 flags |= SMB_TREE_XVATTR;
1284
1285 if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE))
1286 flags |= SMB_TREE_CASEINSENSITIVE;
1287
1288 if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE))
1289 flags |= SMB_TREE_NO_CASESENSITIVE;
1290
1291 if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS))
1292 flags |= SMB_TREE_DIRENTFLAGS;
1293
1294 if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE))
1295 flags |= SMB_TREE_ACLONCREATE;
1296
1297 if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS))
1298 flags |= SMB_TREE_ACEMASKONACCESS;
1299
1300 DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name);
1301
1302
1303 tree->t_flags = flags;
1304 }
1305
1306 /*
1307 * Report share access result to syslog.
1308 */
1309 static void
smb_tree_log(smb_request_t * sr,const char * sharename,const char * fmt,...)1310 smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...)
1311 {
1312 va_list ap;
1313 char buf[128];
1314 smb_user_t *user = sr->uid_user;
1315
1316 ASSERT(user);
1317
1318 if (smb_tcon_mute)
1319 return;
1320
1321 if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) {
1322 /*
1323 * Only report normal users, i.e. ignore W2K misuse
1324 * of the IPC connection by filtering out internal
1325 * names such as nobody and root.
1326 */
1327 if ((strcmp(user->u_name, "root") == 0) ||
1328 (strcmp(user->u_name, "nobody") == 0)) {
1329 return;
1330 }
1331 }
1332
1333 va_start(ap, fmt);
1334 (void) vsnprintf(buf, 128, fmt, ap);
1335 va_end(ap);
1336
1337 cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s",
1338 user->u_domain, user->u_name, sharename, buf);
1339 }
1340
1341 /*
1342 * smb_tree_lookup_odir
1343 *
1344 * Find the specified odir in the tree's list of odirs, and
1345 * attempt to obtain a hold on the odir.
1346 *
1347 * Returns NULL if odir not found or a hold cannot be obtained.
1348 */
1349 smb_odir_t *
smb_tree_lookup_odir(smb_request_t * sr,uint16_t odid)1350 smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid)
1351 {
1352 smb_odir_t *od;
1353 smb_llist_t *od_list;
1354 smb_tree_t *tree = sr->tid_tree;
1355
1356 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1357
1358 od_list = &tree->t_odir_list;
1359
1360 smb_llist_enter(od_list, RW_READER);
1361 od = smb_llist_head(od_list);
1362 while (od) {
1363 if (od->d_odid == odid)
1364 break;
1365 od = smb_llist_next(od_list, od);
1366 }
1367 if (od == NULL)
1368 goto out;
1369
1370 /*
1371 * Only allow use of a given Search ID with the same UID that
1372 * was used to create it. MS-CIFS 3.3.5.14
1373 */
1374 if (od->d_user != sr->uid_user) {
1375 od = NULL;
1376 goto out;
1377 }
1378 if (!smb_odir_hold(od))
1379 od = NULL;
1380
1381 out:
1382 smb_llist_exit(od_list);
1383 return (od);
1384 }
1385
1386 boolean_t
smb_tree_is_connected(smb_tree_t * tree)1387 smb_tree_is_connected(smb_tree_t *tree)
1388 {
1389 boolean_t rb;
1390
1391 mutex_enter(&tree->t_mutex);
1392 rb = smb_tree_is_connected_locked(tree);
1393 mutex_exit(&tree->t_mutex);
1394 return (rb);
1395 }
1396
1397 /*
1398 * smb_tree_close_odirs
1399 *
1400 * Close all open odirs in the tree's list which were opened by
1401 * the process identified by pid.
1402 * If pid is zero, close all open odirs in the tree's list.
1403 */
1404 static void
smb_tree_close_odirs(smb_tree_t * tree,uint32_t pid)1405 smb_tree_close_odirs(smb_tree_t *tree, uint32_t pid)
1406 {
1407 smb_llist_t *od_list;
1408 smb_odir_t *od;
1409
1410 ASSERT(tree);
1411 ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1412
1413 od_list = &tree->t_odir_list;
1414 smb_llist_enter(od_list, RW_READER);
1415
1416 for (od = smb_llist_head(od_list);
1417 od != NULL;
1418 od = smb_llist_next(od_list, od)) {
1419
1420 ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1421 ASSERT(od->d_tree == tree);
1422
1423 if (pid != 0 && od->d_opened_by_pid != pid)
1424 continue;
1425
1426 if (smb_odir_hold(od)) {
1427 smb_odir_close(od);
1428 smb_odir_release(od);
1429 }
1430 }
1431
1432 smb_llist_exit(od_list);
1433 }
1434
1435 static void
smb_tree_set_execinfo(smb_tree_t * tree,smb_shr_execinfo_t * exec,int exec_type)1436 smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
1437 int exec_type)
1438 {
1439 exec->e_sharename = tree->t_sharename;
1440 exec->e_winname = tree->t_owner->u_name;
1441 exec->e_userdom = tree->t_owner->u_domain;
1442 exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
1443 exec->e_cli_ipaddr = tree->t_session->ipaddr;
1444 exec->e_cli_netbiosname = tree->t_session->workstation;
1445 exec->e_uid = crgetuid(tree->t_owner->u_cred);
1446 exec->e_type = exec_type;
1447 }
1448
1449 /*
1450 * Private function to support smb_tree_enum.
1451 */
1452 static int
smb_tree_enum_private(smb_tree_t * tree,smb_svcenum_t * svcenum)1453 smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum)
1454 {
1455 uint8_t *pb;
1456 uint_t nbytes;
1457 int rc;
1458
1459 if (svcenum->se_nskip > 0) {
1460 svcenum->se_nskip--;
1461 return (0);
1462 }
1463
1464 if (svcenum->se_nitems >= svcenum->se_nlimit) {
1465 svcenum->se_nitems = svcenum->se_nlimit;
1466 return (0);
1467 }
1468
1469 pb = &svcenum->se_buf[svcenum->se_bused];
1470 rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes);
1471 if (rc == 0) {
1472 svcenum->se_bavail -= nbytes;
1473 svcenum->se_bused += nbytes;
1474 svcenum->se_nitems++;
1475 }
1476
1477 return (rc);
1478 }
1479
1480 /*
1481 * Encode connection information into a buffer: connection information
1482 * needed in user space to support RPC requests.
1483 */
1484 static int
smb_tree_netinfo_encode(smb_tree_t * tree,uint8_t * buf,size_t buflen,uint32_t * nbytes)1485 smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
1486 uint32_t *nbytes)
1487 {
1488 smb_netconnectinfo_t info;
1489 int rc;
1490
1491 smb_tree_netinfo_init(tree, &info);
1492 rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes);
1493 smb_tree_netinfo_fini(&info);
1494
1495 return (rc);
1496 }
1497
1498 static void
smb_tree_netinfo_username(smb_tree_t * tree,char ** namestr,uint32_t * namelen)1499 smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen)
1500 {
1501 smb_user_t *user = tree->t_owner;
1502
1503 /*
1504 * u_domain_len and u_name_len include the '\0' in their
1505 * lengths, hence the sum of the two lengths gives us room
1506 * for both the '\\' and '\0' chars.
1507 */
1508 ASSERT(namestr);
1509 ASSERT(namelen);
1510 ASSERT(user->u_domain_len > 0);
1511 ASSERT(user->u_name_len > 0);
1512 *namelen = user->u_domain_len + user->u_name_len;
1513 *namestr = kmem_alloc(*namelen, KM_SLEEP);
1514 (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain,
1515 user->u_name);
1516 }
1517
1518 /*
1519 * Note: ci_numusers should be the number of users connected to
1520 * the share rather than the number of references on the tree but
1521 * we don't have a mechanism to track users/share in smbsrv yet.
1522 */
1523 static void
smb_tree_netinfo_init(smb_tree_t * tree,smb_netconnectinfo_t * info)1524 smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
1525 {
1526 ASSERT(tree);
1527
1528 info->ci_id = tree->t_tid;
1529 info->ci_type = tree->t_res_type;
1530 info->ci_numopens = tree->t_open_files;
1531 info->ci_numusers = tree->t_refcnt;
1532 info->ci_time = gethrestime_sec() - tree->t_connect_time;
1533
1534 info->ci_sharelen = strlen(tree->t_sharename) + 1;
1535 info->ci_share = smb_mem_strdup(tree->t_sharename);
1536
1537 smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen);
1538 }
1539
1540 static void
smb_tree_netinfo_fini(smb_netconnectinfo_t * info)1541 smb_tree_netinfo_fini(smb_netconnectinfo_t *info)
1542 {
1543 if (info == NULL)
1544 return;
1545
1546 if (info->ci_username)
1547 kmem_free(info->ci_username, info->ci_namelen);
1548 if (info->ci_share)
1549 smb_mem_free(info->ci_share);
1550
1551 bzero(info, sizeof (smb_netconnectinfo_t));
1552 }
1553