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