xref: /titanic_44/usr/src/uts/common/fs/smbsrv/smb_ofile.c (revision 5fd03bc0f2e00e7ba02316c2e08f45d52aab15db)
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 2013 Nexenta Systems, Inc.  All rights reserved.
24  */
25 
26 /*
27  * General Structures Layout
28  * -------------------------
29  *
30  * This is a simplified diagram showing the relationship between most of the
31  * main structures.
32  *
33  * +-------------------+
34  * |     SMB_INFO      |
35  * +-------------------+
36  *          |
37  *          |
38  *          v
39  * +-------------------+       +-------------------+      +-------------------+
40  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
41  * +-------------------+       +-------------------+      +-------------------+
42  *          |
43  *          |
44  *          v
45  * +-------------------+       +-------------------+      +-------------------+
46  * |       USER        |<----->|       USER        |......|       USER        |
47  * +-------------------+       +-------------------+      +-------------------+
48  *          |
49  *          |
50  *          v
51  * +-------------------+       +-------------------+      +-------------------+
52  * |       TREE        |<----->|       TREE        |......|       TREE        |
53  * +-------------------+       +-------------------+      +-------------------+
54  *      |         |
55  *      |         |
56  *      |         v
57  *      |     +-------+       +-------+      +-------+
58  *      |     | OFILE |<----->| OFILE |......| OFILE |
59  *      |     +-------+       +-------+      +-------+
60  *      |
61  *      |
62  *      v
63  *  +-------+       +------+      +------+
64  *  | ODIR  |<----->| ODIR |......| ODIR |
65  *  +-------+       +------+      +------+
66  *
67  *
68  * Ofile State Machine
69  * ------------------
70  *
71  *    +-------------------------+	 T0
72  *    |  SMB_OFILE_STATE_OPEN   |<----------- Creation/Allocation
73  *    +-------------------------+
74  *		    |
75  *		    | T1
76  *		    |
77  *		    v
78  *    +-------------------------+
79  *    | SMB_OFILE_STATE_CLOSING |
80  *    +-------------------------+
81  *		    |
82  *		    | T2
83  *		    |
84  *		    v
85  *    +-------------------------+    T3
86  *    | SMB_OFILE_STATE_CLOSED  |----------> Deletion/Free
87  *    +-------------------------+
88  *
89  * SMB_OFILE_STATE_OPEN
90  *
91  *    While in this state:
92  *      - The ofile is queued in the list of ofiles of its tree.
93  *      - References will be given out if the ofile is looked up.
94  *
95  * SMB_OFILE_STATE_CLOSING
96  *
97  *    While in this state:
98  *      - The ofile is queued in the list of ofiles of its tree.
99  *      - References will not be given out if the ofile is looked up.
100  *      - The file is closed and the locks held are being released.
101  *      - The resources associated with the ofile remain.
102  *
103  * SMB_OFILE_STATE_CLOSED
104  *
105  *    While in this state:
106  *      - The ofile is queued in the list of ofiles of its tree.
107  *      - References will not be given out if the ofile is looked up.
108  *      - The resources associated with the ofile remain.
109  *
110  * Transition T0
111  *
112  *    This transition occurs in smb_ofile_open(). A new ofile is created and
113  *    added to the list of ofiles of a tree.
114  *
115  * Transition T1
116  *
117  *    This transition occurs in smb_ofile_close().
118  *
119  * Transition T2
120  *
121  *    This transition occurs in smb_ofile_release(). The resources associated
122  *    with the ofile are freed as well as the ofile structure. For the
123  *    transition to occur, the ofile must be in the SMB_OFILE_STATE_CLOSED
124  *    state and the reference count be zero.
125  *
126  * Comments
127  * --------
128  *
129  *    The state machine of the ofile structures is controlled by 3 elements:
130  *      - The list of ofiles of the tree it belongs to.
131  *      - The mutex embedded in the structure itself.
132  *      - The reference count.
133  *
134  *    There's a mutex embedded in the ofile structure used to protect its fields
135  *    and there's a lock embedded in the list of ofiles of a tree. To
136  *    increment or to decrement the reference count the mutex must be entered.
137  *    To insert the ofile into the list of ofiles of the tree and to remove
138  *    the ofile from it, the lock must be entered in RW_WRITER mode.
139  *
140  *    Rules of access to a ofile structure:
141  *
142  *    1) In order to avoid deadlocks, when both (mutex and lock of the ofile
143  *       list) have to be entered, the lock must be entered first.
144  *
145  *    2) All actions applied to an ofile require a reference count.
146  *
147  *    3) There are 2 ways of getting a reference count. One is when the ofile
148  *       is opened. The other one when the ofile is looked up. This translates
149  *       into 2 functions: smb_ofile_open() and smb_ofile_lookup_by_fid().
150  *
151  *    It should be noted that the reference count of an ofile registers the
152  *    number of references to the ofile in other structures (such as an smb
153  *    request). The reference count is not incremented in these 2 instances:
154  *
155  *    1) The ofile is open. An ofile is anchored by his state. If there's
156  *       no activity involving an ofile currently open, the reference count
157  *       of that ofile is zero.
158  *
159  *    2) The ofile is queued in the list of ofiles of its tree. The fact of
160  *       being queued in that list is NOT registered by incrementing the
161  *       reference count.
162  */
163 #include <smbsrv/smb_kproto.h>
164 #include <smbsrv/smb_fsops.h>
165 
166 static boolean_t smb_ofile_is_open_locked(smb_ofile_t *);
167 static smb_ofile_t *smb_ofile_close_and_next(smb_ofile_t *);
168 static int smb_ofile_netinfo_encode(smb_ofile_t *, uint8_t *, size_t,
169     uint32_t *);
170 static int smb_ofile_netinfo_init(smb_ofile_t *, smb_netfileinfo_t *);
171 static void smb_ofile_netinfo_fini(smb_netfileinfo_t *);
172 
173 /*
174  * smb_ofile_open
175  */
176 smb_ofile_t *
177 smb_ofile_open(
178     smb_tree_t		*tree,
179     smb_node_t		*node,
180     uint16_t		pid,
181     struct open_param	*op,
182     uint16_t		ftype,
183     uint32_t		uniqid,
184     smb_error_t		*err)
185 {
186 	smb_ofile_t	*of;
187 	uint16_t	fid;
188 	smb_attr_t	attr;
189 	int		rc;
190 
191 	if (smb_idpool_alloc(&tree->t_fid_pool, &fid)) {
192 		err->status = NT_STATUS_TOO_MANY_OPENED_FILES;
193 		err->errcls = ERRDOS;
194 		err->errcode = ERROR_TOO_MANY_OPEN_FILES;
195 		return (NULL);
196 	}
197 
198 	of = kmem_cache_alloc(tree->t_server->si_cache_ofile, KM_SLEEP);
199 	bzero(of, sizeof (smb_ofile_t));
200 	of->f_magic = SMB_OFILE_MAGIC;
201 	of->f_refcnt = 1;
202 	of->f_fid = fid;
203 	of->f_uniqid = uniqid;
204 	of->f_opened_by_pid = pid;
205 	of->f_granted_access = op->desired_access;
206 	of->f_share_access = op->share_access;
207 	of->f_create_options = op->create_options;
208 	of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ?
209 	    smb_user_getprivcred(tree->t_user) : tree->t_user->u_cred;
210 	crhold(of->f_cr);
211 	of->f_ftype = ftype;
212 	of->f_server = tree->t_server;
213 	of->f_session = tree->t_user->u_session;
214 	of->f_user = tree->t_user;
215 	of->f_tree = tree;
216 	of->f_node = node;
217 
218 	mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
219 	of->f_state = SMB_OFILE_STATE_OPEN;
220 
221 	if (ftype == SMB_FTYPE_MESG_PIPE) {
222 		of->f_pipe = smb_opipe_alloc(tree->t_server);
223 		smb_server_inc_pipes(of->f_server);
224 	} else {
225 		ASSERT(ftype == SMB_FTYPE_DISK); /* Regular file, not a pipe */
226 		ASSERT(node);
227 
228 		if (of->f_granted_access == FILE_EXECUTE)
229 			of->f_flags |= SMB_OFLAGS_EXECONLY;
230 
231 		bzero(&attr, sizeof (smb_attr_t));
232 		attr.sa_mask = SMB_AT_UID | SMB_AT_DOSATTR;
233 		rc = smb_node_getattr(NULL, node, of->f_cr, NULL, &attr);
234 		if (rc != 0) {
235 			of->f_magic = 0;
236 			mutex_destroy(&of->f_mutex);
237 			crfree(of->f_cr);
238 			smb_idpool_free(&tree->t_fid_pool, of->f_fid);
239 			kmem_cache_free(tree->t_server->si_cache_ofile, of);
240 			err->status = NT_STATUS_INTERNAL_ERROR;
241 			err->errcls = ERRDOS;
242 			err->errcode = ERROR_INTERNAL_ERROR;
243 			return (NULL);
244 		}
245 		if (crgetuid(of->f_cr) == attr.sa_vattr.va_uid) {
246 			/*
247 			 * Add this bit for the file's owner even if it's not
248 			 * specified in the request (Windows behavior).
249 			 */
250 			of->f_granted_access |= FILE_READ_ATTRIBUTES;
251 		}
252 
253 		if (smb_node_is_file(node)) {
254 			of->f_mode =
255 			    smb_fsop_amask_to_omode(of->f_granted_access);
256 			if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) {
257 				of->f_magic = 0;
258 				mutex_destroy(&of->f_mutex);
259 				crfree(of->f_cr);
260 				smb_idpool_free(&tree->t_fid_pool, of->f_fid);
261 				kmem_cache_free(tree->t_server->si_cache_ofile,
262 				    of);
263 				err->status = NT_STATUS_ACCESS_DENIED;
264 				err->errcls = ERRDOS;
265 				err->errcode = ERROR_ACCESS_DENIED;
266 				return (NULL);
267 			}
268 		}
269 
270 		if (tree->t_flags & SMB_TREE_READONLY)
271 			of->f_flags |= SMB_OFLAGS_READONLY;
272 
273 		/*
274 		 * Note that if we created_readonly, that
275 		 * will _not_ yet show in attr.sa_dosattr
276 		 * so creating a readonly file gives the
277 		 * caller a writable handle as it should.
278 		 */
279 		if (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)
280 			of->f_flags |= SMB_OFLAGS_READONLY;
281 
282 		smb_node_inc_open_ofiles(node);
283 		smb_node_add_ofile(node, of);
284 		smb_node_ref(node);
285 		smb_server_inc_files(of->f_server);
286 	}
287 	smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
288 	smb_llist_insert_tail(&tree->t_ofile_list, of);
289 	smb_llist_exit(&tree->t_ofile_list);
290 	atomic_inc_32(&tree->t_open_files);
291 	atomic_inc_32(&of->f_session->s_file_cnt);
292 	return (of);
293 }
294 
295 /*
296  * smb_ofile_close
297  */
298 void
299 smb_ofile_close(smb_ofile_t *of, int32_t mtime_sec)
300 {
301 	timestruc_t now;
302 	uint32_t flags = 0;
303 
304 	SMB_OFILE_VALID(of);
305 
306 	mutex_enter(&of->f_mutex);
307 	ASSERT(of->f_refcnt);
308 	switch (of->f_state) {
309 	case SMB_OFILE_STATE_OPEN: {
310 
311 		of->f_state = SMB_OFILE_STATE_CLOSING;
312 		mutex_exit(&of->f_mutex);
313 
314 		if (of->f_ftype == SMB_FTYPE_MESG_PIPE) {
315 			smb_opipe_close(of);
316 			smb_server_dec_pipes(of->f_server);
317 		} else {
318 			smb_attr_t *pa = &of->f_pending_attr;
319 
320 			/*
321 			 * In here we make changes to of->f_pending_attr
322 			 * while not holding of->f_mutex.  This is OK
323 			 * because we've changed f_state to CLOSING,
324 			 * so no more threads will take this path.
325 			 */
326 			if (mtime_sec != 0) {
327 				pa->sa_vattr.va_mtime.tv_sec = mtime_sec;
328 				pa->sa_mask |= SMB_AT_MTIME;
329 			}
330 
331 			/*
332 			 * If we have ever modified data via this handle
333 			 * (write or truncate) and if the mtime was not
334 			 * set via this handle, update the mtime again
335 			 * during the close.  Windows expects this.
336 			 * [ MS-FSA 2.1.5.4 "Update Timestamps" ]
337 			 */
338 			if (of->f_written &&
339 			    (pa->sa_mask & SMB_AT_MTIME) == 0) {
340 				pa->sa_mask |= SMB_AT_MTIME;
341 				gethrestime(&now);
342 				pa->sa_vattr.va_mtime = now;
343 			}
344 
345 			if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) {
346 				if (smb_tree_has_feature(of->f_tree,
347 				    SMB_TREE_CATIA)) {
348 					flags |= SMB_CATIA;
349 				}
350 				(void) smb_node_set_delete_on_close(of->f_node,
351 				    of->f_cr, flags);
352 			}
353 			smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid);
354 			smb_node_destroy_lock_by_ofile(of->f_node, of);
355 
356 			if (smb_node_is_file(of->f_node)) {
357 				(void) smb_fsop_close(of->f_node, of->f_mode,
358 				    of->f_cr);
359 				smb_oplock_release(of->f_node, of);
360 			}
361 			if (smb_node_dec_open_ofiles(of->f_node) == 0) {
362 				/*
363 				 * Last close. The f_pending_attr has
364 				 * only times (atime,ctime,mtime) so
365 				 * we can borrow it to commit the
366 				 * n_pending_dosattr from the node.
367 				 */
368 				pa->sa_dosattr =
369 				    of->f_node->n_pending_dosattr;
370 				if (pa->sa_dosattr != 0)
371 					pa->sa_mask |= SMB_AT_DOSATTR;
372 				/* Let's leave this zero when not in use. */
373 				of->f_node->n_allocsz = 0;
374 			}
375 			if (pa->sa_mask != 0) {
376 				/*
377 				 * Commit any pending attributes from
378 				 * the ofile we're closing.  Note that
379 				 * we pass NULL as the ofile to setattr
380 				 * so it will write to the file system
381 				 * and not keep anything on the ofile.
382 				 * This clears n_pending_dosattr if
383 				 * there are no opens, otherwise the
384 				 * dosattr will be pending again.
385 				 */
386 				(void) smb_node_setattr(NULL, of->f_node,
387 				    of->f_cr, NULL, pa);
388 			}
389 
390 			/*
391 			 * Cancel any notify change requests that
392 			 * may be using this open instance.
393 			 */
394 			if (of->f_node->n_fcn.fcn_count)
395 				smb_notify_file_closed(of);
396 
397 			smb_server_dec_files(of->f_server);
398 		}
399 		atomic_dec_32(&of->f_tree->t_open_files);
400 
401 		mutex_enter(&of->f_mutex);
402 		ASSERT(of->f_refcnt);
403 		ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
404 		of->f_state = SMB_OFILE_STATE_CLOSED;
405 		break;
406 	}
407 	case SMB_OFILE_STATE_CLOSED:
408 	case SMB_OFILE_STATE_CLOSING:
409 		break;
410 
411 	default:
412 		ASSERT(0);
413 		break;
414 	}
415 	mutex_exit(&of->f_mutex);
416 }
417 
418 /*
419  * smb_ofile_close_all
420  *
421  *
422  */
423 void
424 smb_ofile_close_all(
425     smb_tree_t		*tree)
426 {
427 	smb_ofile_t	*of;
428 
429 	ASSERT(tree);
430 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
431 
432 	smb_llist_enter(&tree->t_ofile_list, RW_READER);
433 	of = smb_llist_head(&tree->t_ofile_list);
434 	while (of) {
435 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
436 		ASSERT(of->f_tree == tree);
437 		of = smb_ofile_close_and_next(of);
438 	}
439 	smb_llist_exit(&tree->t_ofile_list);
440 }
441 
442 /*
443  * smb_ofiles_close_by_pid
444  *
445  *
446  */
447 void
448 smb_ofile_close_all_by_pid(
449     smb_tree_t		*tree,
450     uint16_t		pid)
451 {
452 	smb_ofile_t	*of;
453 
454 	ASSERT(tree);
455 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
456 
457 	smb_llist_enter(&tree->t_ofile_list, RW_READER);
458 	of = smb_llist_head(&tree->t_ofile_list);
459 	while (of) {
460 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
461 		ASSERT(of->f_tree == tree);
462 		if (of->f_opened_by_pid == pid) {
463 			of = smb_ofile_close_and_next(of);
464 		} else {
465 			of = smb_llist_next(&tree->t_ofile_list, of);
466 		}
467 	}
468 	smb_llist_exit(&tree->t_ofile_list);
469 }
470 
471 /*
472  * If the enumeration request is for ofile data, handle it here.
473  * Otherwise, return.
474  *
475  * This function should be called with a hold on the ofile.
476  */
477 int
478 smb_ofile_enum(smb_ofile_t *of, smb_svcenum_t *svcenum)
479 {
480 	uint8_t *pb;
481 	uint_t nbytes;
482 	int rc;
483 
484 	ASSERT(of);
485 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
486 	ASSERT(of->f_refcnt);
487 
488 	if (svcenum->se_type != SMB_SVCENUM_TYPE_FILE)
489 		return (0);
490 
491 	if (svcenum->se_nskip > 0) {
492 		svcenum->se_nskip--;
493 		return (0);
494 	}
495 
496 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
497 		svcenum->se_nitems = svcenum->se_nlimit;
498 		return (0);
499 	}
500 
501 	pb = &svcenum->se_buf[svcenum->se_bused];
502 
503 	rc = smb_ofile_netinfo_encode(of, pb, svcenum->se_bavail,
504 	    &nbytes);
505 	if (rc == 0) {
506 		svcenum->se_bavail -= nbytes;
507 		svcenum->se_bused += nbytes;
508 		svcenum->se_nitems++;
509 	}
510 
511 	return (rc);
512 }
513 
514 /*
515  * Take a reference on an open file.
516  */
517 boolean_t
518 smb_ofile_hold(smb_ofile_t *of)
519 {
520 	ASSERT(of);
521 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
522 
523 	mutex_enter(&of->f_mutex);
524 
525 	if (smb_ofile_is_open_locked(of)) {
526 		of->f_refcnt++;
527 		mutex_exit(&of->f_mutex);
528 		return (B_TRUE);
529 	}
530 
531 	mutex_exit(&of->f_mutex);
532 	return (B_FALSE);
533 }
534 
535 /*
536  * Release a reference on a file.  If the reference count falls to
537  * zero and the file has been closed, post the object for deletion.
538  * Object deletion is deferred to avoid modifying a list while an
539  * iteration may be in progress.
540  */
541 void
542 smb_ofile_release(smb_ofile_t *of)
543 {
544 	SMB_OFILE_VALID(of);
545 
546 	mutex_enter(&of->f_mutex);
547 	ASSERT(of->f_refcnt);
548 	of->f_refcnt--;
549 	switch (of->f_state) {
550 	case SMB_OFILE_STATE_OPEN:
551 	case SMB_OFILE_STATE_CLOSING:
552 		break;
553 
554 	case SMB_OFILE_STATE_CLOSED:
555 		if (of->f_refcnt == 0)
556 			smb_tree_post_ofile(of->f_tree, of);
557 		break;
558 
559 	default:
560 		ASSERT(0);
561 		break;
562 	}
563 	mutex_exit(&of->f_mutex);
564 }
565 
566 /*
567  * smb_ofile_request_complete
568  *
569  * During oplock acquisition, all other oplock requests on the node
570  * are blocked until the acquire request completes and the response
571  * is on the wire.
572  * Call smb_oplock_broadcast to notify the node that the request
573  * has completed.
574  *
575  * THIS MECHANISM RELIES ON THE FACT THAT THE OFILE IS NOT REMOVED
576  * FROM THE SR UNTIL REQUEST COMPLETION (when the sr is destroyed)
577  */
578 void
579 smb_ofile_request_complete(smb_ofile_t *of)
580 {
581 	SMB_OFILE_VALID(of);
582 
583 	switch (of->f_ftype) {
584 	case SMB_FTYPE_DISK:
585 		ASSERT(of->f_node);
586 		smb_oplock_broadcast(of->f_node);
587 		break;
588 	case SMB_FTYPE_MESG_PIPE:
589 		break;
590 	default:
591 		break;
592 	}
593 }
594 
595 /*
596  * smb_ofile_lookup_by_fid
597  *
598  * Find the open file whose fid matches the one specified in the request.
599  * If we can't find the fid or the shares (trees) don't match, we have a
600  * bad fid.
601  */
602 smb_ofile_t *
603 smb_ofile_lookup_by_fid(
604     smb_tree_t		*tree,
605     uint16_t		fid)
606 {
607 	smb_llist_t	*of_list;
608 	smb_ofile_t	*of;
609 
610 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
611 
612 	of_list = &tree->t_ofile_list;
613 
614 	smb_llist_enter(of_list, RW_READER);
615 	of = smb_llist_head(of_list);
616 	while (of) {
617 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
618 		ASSERT(of->f_tree == tree);
619 		if (of->f_fid == fid) {
620 			mutex_enter(&of->f_mutex);
621 			if (of->f_state != SMB_OFILE_STATE_OPEN) {
622 				mutex_exit(&of->f_mutex);
623 				smb_llist_exit(of_list);
624 				return (NULL);
625 			}
626 			of->f_refcnt++;
627 			mutex_exit(&of->f_mutex);
628 			break;
629 		}
630 		of = smb_llist_next(of_list, of);
631 	}
632 	smb_llist_exit(of_list);
633 	return (of);
634 }
635 
636 /*
637  * smb_ofile_lookup_by_uniqid
638  *
639  * Find the open file whose uniqid matches the one specified in the request.
640  */
641 smb_ofile_t *
642 smb_ofile_lookup_by_uniqid(smb_tree_t *tree, uint32_t uniqid)
643 {
644 	smb_llist_t	*of_list;
645 	smb_ofile_t	*of;
646 
647 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
648 
649 	of_list = &tree->t_ofile_list;
650 	smb_llist_enter(of_list, RW_READER);
651 	of = smb_llist_head(of_list);
652 
653 	while (of) {
654 		ASSERT(of->f_magic == SMB_OFILE_MAGIC);
655 		ASSERT(of->f_tree == tree);
656 
657 		if (of->f_uniqid == uniqid) {
658 			if (smb_ofile_hold(of)) {
659 				smb_llist_exit(of_list);
660 				return (of);
661 			}
662 		}
663 
664 		of = smb_llist_next(of_list, of);
665 	}
666 
667 	smb_llist_exit(of_list);
668 	return (NULL);
669 }
670 
671 /*
672  * Disallow NetFileClose on certain ofiles to avoid side-effects.
673  * Closing a tree root is not allowed: use NetSessionDel or NetShareDel.
674  * Closing SRVSVC connections is not allowed because this NetFileClose
675  * request may depend on this ofile.
676  */
677 boolean_t
678 smb_ofile_disallow_fclose(smb_ofile_t *of)
679 {
680 	ASSERT(of);
681 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
682 	ASSERT(of->f_refcnt);
683 
684 	switch (of->f_ftype) {
685 	case SMB_FTYPE_DISK:
686 		ASSERT(of->f_tree);
687 		return (of->f_node == of->f_tree->t_snode);
688 
689 	case SMB_FTYPE_MESG_PIPE:
690 		ASSERT(of->f_pipe);
691 		if (smb_strcasecmp(of->f_pipe->p_name, "SRVSVC", 0) == 0)
692 			return (B_TRUE);
693 		break;
694 	default:
695 		break;
696 	}
697 
698 	return (B_FALSE);
699 }
700 
701 /*
702  * smb_ofile_set_flags
703  *
704  * Return value:
705  *
706  *	Current flags value
707  *
708  */
709 void
710 smb_ofile_set_flags(
711     smb_ofile_t		*of,
712     uint32_t		flags)
713 {
714 	ASSERT(of);
715 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
716 	ASSERT(of->f_refcnt);
717 
718 	mutex_enter(&of->f_mutex);
719 	of->f_flags |= flags;
720 	mutex_exit(&of->f_mutex);
721 }
722 
723 /*
724  * smb_ofile_seek
725  *
726  * Return value:
727  *
728  *	0		Success
729  *	EINVAL		Unknown mode
730  *	EOVERFLOW	offset too big
731  *
732  */
733 int
734 smb_ofile_seek(
735     smb_ofile_t		*of,
736     ushort_t		mode,
737     int32_t		off,
738     uint32_t		*retoff)
739 {
740 	u_offset_t	newoff = 0;
741 	int		rc = 0;
742 	smb_attr_t	attr;
743 
744 	ASSERT(of);
745 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
746 	ASSERT(of->f_refcnt);
747 
748 	mutex_enter(&of->f_mutex);
749 	switch (mode) {
750 	case SMB_SEEK_SET:
751 		if (off < 0)
752 			newoff = 0;
753 		else
754 			newoff = (u_offset_t)off;
755 		break;
756 
757 	case SMB_SEEK_CUR:
758 		if (off < 0 && (-off) > of->f_seek_pos)
759 			newoff = 0;
760 		else
761 			newoff = of->f_seek_pos + (u_offset_t)off;
762 		break;
763 
764 	case SMB_SEEK_END:
765 		bzero(&attr, sizeof (smb_attr_t));
766 		attr.sa_mask |= SMB_AT_SIZE;
767 		rc = smb_fsop_getattr(NULL, kcred, of->f_node, &attr);
768 		if (rc != 0) {
769 			mutex_exit(&of->f_mutex);
770 			return (rc);
771 		}
772 		if (off < 0 && (-off) > attr.sa_vattr.va_size)
773 			newoff = 0;
774 		else
775 			newoff = attr.sa_vattr.va_size + (u_offset_t)off;
776 		break;
777 
778 	default:
779 		mutex_exit(&of->f_mutex);
780 		return (EINVAL);
781 	}
782 
783 	/*
784 	 * See comments at the beginning of smb_seek.c.
785 	 * If the offset is greater than UINT_MAX, we will return an error.
786 	 */
787 
788 	if (newoff > UINT_MAX) {
789 		rc = EOVERFLOW;
790 	} else {
791 		of->f_seek_pos = newoff;
792 		*retoff = (uint32_t)newoff;
793 	}
794 	mutex_exit(&of->f_mutex);
795 	return (rc);
796 }
797 
798 /*
799  * smb_ofile_is_open
800  */
801 boolean_t
802 smb_ofile_is_open(smb_ofile_t *of)
803 {
804 	boolean_t	rc;
805 
806 	SMB_OFILE_VALID(of);
807 
808 	mutex_enter(&of->f_mutex);
809 	rc = smb_ofile_is_open_locked(of);
810 	mutex_exit(&of->f_mutex);
811 	return (rc);
812 }
813 
814 /* *************************** Static Functions ***************************** */
815 
816 /*
817  * Determine whether or not an ofile is open.
818  * This function must be called with the mutex held.
819  */
820 static boolean_t
821 smb_ofile_is_open_locked(smb_ofile_t *of)
822 {
823 	switch (of->f_state) {
824 	case SMB_OFILE_STATE_OPEN:
825 		return (B_TRUE);
826 
827 	case SMB_OFILE_STATE_CLOSING:
828 	case SMB_OFILE_STATE_CLOSED:
829 		return (B_FALSE);
830 
831 	default:
832 		ASSERT(0);
833 		return (B_FALSE);
834 	}
835 }
836 
837 /*
838  * This function closes the file passed in (if appropriate) and returns the
839  * next open file in the list of open files of the tree of the open file passed
840  * in. It requires that the list of open files of the tree be entered in
841  * RW_READER mode before being called.
842  */
843 static smb_ofile_t *
844 smb_ofile_close_and_next(smb_ofile_t *of)
845 {
846 	smb_ofile_t	*next_of;
847 	smb_tree_t	*tree;
848 
849 	ASSERT(of);
850 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
851 
852 	mutex_enter(&of->f_mutex);
853 	switch (of->f_state) {
854 	case SMB_OFILE_STATE_OPEN:
855 		/* The file is still open. */
856 		of->f_refcnt++;
857 		ASSERT(of->f_refcnt);
858 		tree = of->f_tree;
859 		mutex_exit(&of->f_mutex);
860 		smb_llist_exit(&of->f_tree->t_ofile_list);
861 		smb_ofile_close(of, 0);
862 		smb_ofile_release(of);
863 		smb_llist_enter(&tree->t_ofile_list, RW_READER);
864 		next_of = smb_llist_head(&tree->t_ofile_list);
865 		break;
866 	case SMB_OFILE_STATE_CLOSING:
867 	case SMB_OFILE_STATE_CLOSED:
868 		/*
869 		 * The ofile exists but is closed or
870 		 * in the process being closed.
871 		 */
872 		mutex_exit(&of->f_mutex);
873 		next_of = smb_llist_next(&of->f_tree->t_ofile_list, of);
874 		break;
875 	default:
876 		ASSERT(0);
877 		mutex_exit(&of->f_mutex);
878 		next_of = smb_llist_next(&of->f_tree->t_ofile_list, of);
879 		break;
880 	}
881 	return (next_of);
882 }
883 
884 /*
885  * Delete an ofile.
886  *
887  * Remove the ofile from the tree list before freeing resources
888  * associated with the ofile.
889  */
890 void
891 smb_ofile_delete(void *arg)
892 {
893 	smb_tree_t	*tree;
894 	smb_ofile_t	*of = (smb_ofile_t *)arg;
895 
896 	SMB_OFILE_VALID(of);
897 	ASSERT(of->f_refcnt == 0);
898 	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
899 	ASSERT(!SMB_OFILE_OPLOCK_GRANTED(of));
900 
901 	tree = of->f_tree;
902 	smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
903 	smb_llist_remove(&tree->t_ofile_list, of);
904 	smb_idpool_free(&tree->t_fid_pool, of->f_fid);
905 	atomic_dec_32(&tree->t_session->s_file_cnt);
906 	smb_llist_exit(&tree->t_ofile_list);
907 
908 	mutex_enter(&of->f_mutex);
909 	mutex_exit(&of->f_mutex);
910 
911 	if (of->f_ftype == SMB_FTYPE_MESG_PIPE) {
912 		smb_opipe_dealloc(of->f_pipe);
913 		of->f_pipe = NULL;
914 	} else {
915 		ASSERT(of->f_ftype == SMB_FTYPE_DISK);
916 		ASSERT(of->f_node != NULL);
917 		smb_node_rem_ofile(of->f_node, of);
918 		smb_node_release(of->f_node);
919 	}
920 
921 	of->f_magic = (uint32_t)~SMB_OFILE_MAGIC;
922 	mutex_destroy(&of->f_mutex);
923 	crfree(of->f_cr);
924 	kmem_cache_free(of->f_tree->t_server->si_cache_ofile, of);
925 }
926 
927 /*
928  * smb_ofile_access
929  *
930  * This function will check to see if the access requested is granted.
931  * Returns NT status codes.
932  */
933 uint32_t
934 smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access)
935 {
936 
937 	if ((of == NULL) || (cr == kcred))
938 		return (NT_STATUS_SUCCESS);
939 
940 	/*
941 	 * If the request is for something
942 	 * I don't grant it is an error
943 	 */
944 	if (~(of->f_granted_access) & access) {
945 		if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) &&
946 		    (access & ACCESS_SYSTEM_SECURITY)) {
947 			return (NT_STATUS_PRIVILEGE_NOT_HELD);
948 		}
949 		return (NT_STATUS_ACCESS_DENIED);
950 	}
951 
952 	return (NT_STATUS_SUCCESS);
953 }
954 
955 /*
956  * smb_ofile_share_check
957  *
958  * Check if ofile was opened with share access NONE (0).
959  * Returns: B_TRUE  - share access non-zero
960  *          B_FALSE - share access NONE
961  */
962 boolean_t
963 smb_ofile_share_check(smb_ofile_t *of)
964 {
965 	return (!SMB_DENY_ALL(of->f_share_access));
966 }
967 
968 /*
969  * check file sharing rules for current open request
970  * against existing open instances of the same file
971  *
972  * Returns NT_STATUS_SHARING_VIOLATION if there is any
973  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
974  */
975 uint32_t
976 smb_ofile_open_check(smb_ofile_t *of, uint32_t desired_access,
977     uint32_t share_access)
978 {
979 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
980 
981 	mutex_enter(&of->f_mutex);
982 
983 	if (of->f_state != SMB_OFILE_STATE_OPEN) {
984 		mutex_exit(&of->f_mutex);
985 		return (NT_STATUS_INVALID_HANDLE);
986 	}
987 
988 	/* if it's just meta data */
989 	if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
990 		mutex_exit(&of->f_mutex);
991 		return (NT_STATUS_SUCCESS);
992 	}
993 
994 	/*
995 	 * Check requested share access against the
996 	 * open granted (desired) access
997 	 */
998 	if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) {
999 		mutex_exit(&of->f_mutex);
1000 		return (NT_STATUS_SHARING_VIOLATION);
1001 	}
1002 
1003 	if (SMB_DENY_READ(share_access) &&
1004 	    (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1005 		mutex_exit(&of->f_mutex);
1006 		return (NT_STATUS_SHARING_VIOLATION);
1007 	}
1008 
1009 	if (SMB_DENY_WRITE(share_access) &&
1010 	    (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1011 		mutex_exit(&of->f_mutex);
1012 		return (NT_STATUS_SHARING_VIOLATION);
1013 	}
1014 
1015 	/* check requested desired access against the open share access */
1016 	if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) {
1017 		mutex_exit(&of->f_mutex);
1018 		return (NT_STATUS_SHARING_VIOLATION);
1019 	}
1020 
1021 	if (SMB_DENY_READ(of->f_share_access) &&
1022 	    (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1023 		mutex_exit(&of->f_mutex);
1024 		return (NT_STATUS_SHARING_VIOLATION);
1025 	}
1026 
1027 	if (SMB_DENY_WRITE(of->f_share_access) &&
1028 	    (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1029 		mutex_exit(&of->f_mutex);
1030 		return (NT_STATUS_SHARING_VIOLATION);
1031 	}
1032 
1033 	mutex_exit(&of->f_mutex);
1034 	return (NT_STATUS_SUCCESS);
1035 }
1036 
1037 /*
1038  * smb_ofile_rename_check
1039  *
1040  * An open file can be renamed if
1041  *
1042  *  1. isn't opened for data writing or deleting
1043  *
1044  *  2. Opened with "Deny Delete" share mode
1045  *         But not opened for data reading or executing
1046  *         (opened for accessing meta data)
1047  */
1048 
1049 uint32_t
1050 smb_ofile_rename_check(smb_ofile_t *of)
1051 {
1052 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1053 
1054 	mutex_enter(&of->f_mutex);
1055 
1056 	if (of->f_state != SMB_OFILE_STATE_OPEN) {
1057 		mutex_exit(&of->f_mutex);
1058 		return (NT_STATUS_INVALID_HANDLE);
1059 	}
1060 
1061 	if (of->f_granted_access &
1062 	    (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) {
1063 		mutex_exit(&of->f_mutex);
1064 		return (NT_STATUS_SHARING_VIOLATION);
1065 	}
1066 
1067 	if ((of->f_share_access & FILE_SHARE_DELETE) == 0) {
1068 		if (of->f_granted_access &
1069 		    (FILE_READ_DATA | FILE_EXECUTE)) {
1070 			mutex_exit(&of->f_mutex);
1071 			return (NT_STATUS_SHARING_VIOLATION);
1072 		}
1073 	}
1074 
1075 	mutex_exit(&of->f_mutex);
1076 	return (NT_STATUS_SUCCESS);
1077 }
1078 
1079 /*
1080  * smb_ofile_delete_check
1081  *
1082  * An open file can be deleted only if opened for
1083  * accessing meta data. Share modes aren't important
1084  * in this case.
1085  *
1086  * NOTE: there is another mechanism for deleting an
1087  * open file that NT clients usually use.
1088  * That's setting "Delete on close" flag for an open
1089  * file.  In this way the file will be deleted after
1090  * last close. This flag can be set by SmbTrans2SetFileInfo
1091  * with FILE_DISPOSITION_INFO information level.
1092  * For setting this flag, the file should be opened by
1093  * DELETE access in the FID that is passed in the Trans2
1094  * request.
1095  */
1096 
1097 uint32_t
1098 smb_ofile_delete_check(smb_ofile_t *of)
1099 {
1100 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1101 
1102 	mutex_enter(&of->f_mutex);
1103 
1104 	if (of->f_state != SMB_OFILE_STATE_OPEN) {
1105 		mutex_exit(&of->f_mutex);
1106 		return (NT_STATUS_INVALID_HANDLE);
1107 	}
1108 
1109 	if (of->f_granted_access &
1110 	    (FILE_READ_DATA | FILE_WRITE_DATA |
1111 	    FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) {
1112 		mutex_exit(&of->f_mutex);
1113 		return (NT_STATUS_SHARING_VIOLATION);
1114 	}
1115 
1116 	mutex_exit(&of->f_mutex);
1117 	return (NT_STATUS_SUCCESS);
1118 }
1119 
1120 cred_t *
1121 smb_ofile_getcred(smb_ofile_t *of)
1122 {
1123 	return (of->f_cr);
1124 }
1125 
1126 /*
1127  * smb_ofile_set_delete_on_close
1128  *
1129  * Set the DeleteOnClose flag on the smb file. When the file is closed,
1130  * the flag will be transferred to the smb node, which will commit the
1131  * delete operation and inhibit subsequent open requests.
1132  *
1133  * When DeleteOnClose is set on an smb_node, the common open code will
1134  * reject subsequent open requests for the file. Observation of Windows
1135  * 2000 indicates that subsequent opens should be allowed (assuming
1136  * there would be no sharing violation) until the file is closed using
1137  * the fid on which the DeleteOnClose was requested.
1138  */
1139 void
1140 smb_ofile_set_delete_on_close(smb_ofile_t *of)
1141 {
1142 	mutex_enter(&of->f_mutex);
1143 	of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE;
1144 	mutex_exit(&of->f_mutex);
1145 }
1146 
1147 /*
1148  * Encode open file information into a buffer; needed in user space to
1149  * support RPC requests.
1150  */
1151 static int
1152 smb_ofile_netinfo_encode(smb_ofile_t *of, uint8_t *buf, size_t buflen,
1153     uint32_t *nbytes)
1154 {
1155 	smb_netfileinfo_t	fi;
1156 	int			rc;
1157 
1158 	rc = smb_ofile_netinfo_init(of, &fi);
1159 	if (rc == 0) {
1160 		rc = smb_netfileinfo_encode(&fi, buf, buflen, nbytes);
1161 		smb_ofile_netinfo_fini(&fi);
1162 	}
1163 
1164 	return (rc);
1165 }
1166 
1167 static int
1168 smb_ofile_netinfo_init(smb_ofile_t *of, smb_netfileinfo_t *fi)
1169 {
1170 	smb_user_t	*user;
1171 	smb_tree_t	*tree;
1172 	smb_node_t	*node;
1173 	char		*path;
1174 	char		*buf;
1175 	int		rc;
1176 
1177 	ASSERT(of);
1178 	user = of->f_user;
1179 	tree = of->f_tree;
1180 	ASSERT(user);
1181 	ASSERT(tree);
1182 
1183 	buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1184 
1185 	switch (of->f_ftype) {
1186 	case SMB_FTYPE_DISK:
1187 		node = of->f_node;
1188 		ASSERT(node);
1189 
1190 		fi->fi_permissions = of->f_granted_access;
1191 		fi->fi_numlocks = smb_lock_get_lock_count(node, of);
1192 
1193 		path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1194 
1195 		if (node != tree->t_snode) {
1196 			rc = smb_node_getshrpath(node, tree, path, MAXPATHLEN);
1197 			if (rc != 0)
1198 				(void) strlcpy(path, node->od_name, MAXPATHLEN);
1199 		}
1200 
1201 		(void) snprintf(buf, MAXPATHLEN, "%s:%s", tree->t_sharename,
1202 		    path);
1203 		kmem_free(path, MAXPATHLEN);
1204 		break;
1205 
1206 	case SMB_FTYPE_MESG_PIPE:
1207 		ASSERT(of->f_pipe);
1208 
1209 		fi->fi_permissions = FILE_READ_DATA | FILE_WRITE_DATA |
1210 		    FILE_EXECUTE;
1211 		fi->fi_numlocks = 0;
1212 		(void) snprintf(buf, MAXPATHLEN, "\\PIPE\\%s",
1213 		    of->f_pipe->p_name);
1214 		break;
1215 
1216 	default:
1217 		kmem_free(buf, MAXPATHLEN);
1218 		return (-1);
1219 	}
1220 
1221 	fi->fi_fid = of->f_fid;
1222 	fi->fi_uniqid = of->f_uniqid;
1223 	fi->fi_pathlen = strlen(buf) + 1;
1224 	fi->fi_path = smb_mem_strdup(buf);
1225 	kmem_free(buf, MAXPATHLEN);
1226 
1227 	fi->fi_namelen = user->u_domain_len + user->u_name_len + 2;
1228 	fi->fi_username = kmem_alloc(fi->fi_namelen, KM_SLEEP);
1229 	(void) snprintf(fi->fi_username, fi->fi_namelen, "%s\\%s",
1230 	    user->u_domain, user->u_name);
1231 	return (0);
1232 }
1233 
1234 static void
1235 smb_ofile_netinfo_fini(smb_netfileinfo_t *fi)
1236 {
1237 	if (fi == NULL)
1238 		return;
1239 
1240 	if (fi->fi_path)
1241 		smb_mem_free(fi->fi_path);
1242 	if (fi->fi_username)
1243 		kmem_free(fi->fi_username, fi->fi_namelen);
1244 
1245 	bzero(fi, sizeof (smb_netfileinfo_t));
1246 }
1247 
1248 /*
1249  * A query of user and group quotas may span multiple requests.
1250  * f_quota_resume is used to determine where the query should
1251  * be resumed, in a subsequent request. f_quota_resume contains
1252  * the SID of the last quota entry returned to the client.
1253  */
1254 void
1255 smb_ofile_set_quota_resume(smb_ofile_t *ofile, char *resume)
1256 {
1257 	ASSERT(ofile);
1258 	mutex_enter(&ofile->f_mutex);
1259 	if (resume == NULL)
1260 		bzero(ofile->f_quota_resume, SMB_SID_STRSZ);
1261 	else
1262 		(void) strlcpy(ofile->f_quota_resume, resume, SMB_SID_STRSZ);
1263 	mutex_exit(&ofile->f_mutex);
1264 }
1265 
1266 void
1267 smb_ofile_get_quota_resume(smb_ofile_t *ofile, char *buf, int bufsize)
1268 {
1269 	ASSERT(ofile);
1270 	mutex_enter(&ofile->f_mutex);
1271 	(void) strlcpy(buf, ofile->f_quota_resume, bufsize);
1272 	mutex_exit(&ofile->f_mutex);
1273 }
1274