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