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
165 static boolean_t smb_ofile_is_open_locked(smb_ofile_t *);
166 static smb_ofile_t *smb_ofile_close_and_next(smb_ofile_t *);
167 static void smb_ofile_set_close_attrs(smb_ofile_t *, uint32_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 *
smb_ofile_open(smb_tree_t * tree,smb_node_t * node,uint16_t pid,struct open_param * op,uint16_t ftype,uint32_t uniqid,smb_error_t * err)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
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 */
290 void
smb_ofile_close(smb_ofile_t * of,uint32_t last_wtime)291 smb_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 */
362 void
smb_ofile_close_all(smb_tree_t * tree)363 smb_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 */
386 void
smb_ofile_close_all_by_pid(smb_tree_t * tree,uint16_t pid)387 smb_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 */
416 int
smb_ofile_enum(smb_ofile_t * of,smb_svcenum_t * svcenum)417 smb_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 */
456 boolean_t
smb_ofile_hold(smb_ofile_t * of)457 smb_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 */
480 void
smb_ofile_release(smb_ofile_t * of)481 smb_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 */
517 void
smb_ofile_request_complete(smb_ofile_t * of)518 smb_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 */
541 smb_ofile_t *
smb_ofile_lookup_by_fid(smb_tree_t * tree,uint16_t fid)542 smb_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 */
580 smb_ofile_t *
smb_ofile_lookup_by_uniqid(smb_tree_t * tree,uint32_t uniqid)581 smb_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 */
616 boolean_t
smb_ofile_disallow_fclose(smb_ofile_t * of)617 smb_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 */
648 void
smb_ofile_set_flags(smb_ofile_t * of,uint32_t flags)649 smb_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 */
672 int
smb_ofile_seek(smb_ofile_t * of,ushort_t mode,int32_t off,uint32_t * retoff)673 smb_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 */
740 boolean_t
smb_ofile_is_open(smb_ofile_t * of)741 smb_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 */
759 void
smb_ofile_set_write_time_pending(smb_ofile_t * of)760 smb_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 */
773 boolean_t
smb_ofile_write_time_pending(smb_ofile_t * of)774 smb_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 */
795 void
smb_ofile_set_explicit_times(smb_ofile_t * of,uint32_t what)796 smb_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
804 uint32_t
smb_ofile_explicit_times(smb_ofile_t * of)805 smb_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 */
823 static boolean_t
smb_ofile_is_open_locked(smb_ofile_t * of)824 smb_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 */
853 static void
smb_ofile_set_close_attrs(smb_ofile_t * of,uint32_t last_wtime)854 smb_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 */
890 static smb_ofile_t *
smb_ofile_close_and_next(smb_ofile_t * of)891 smb_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 */
937 void
smb_ofile_delete(void * arg)938 smb_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 */
980 uint32_t
smb_ofile_access(smb_ofile_t * of,cred_t * cr,uint32_t access)981 smb_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 */
1009 boolean_t
smb_ofile_share_check(smb_ofile_t * of)1010 smb_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 */
1022 uint32_t
smb_ofile_open_check(smb_ofile_t * of,uint32_t desired_access,uint32_t share_access)1023 smb_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
1096 uint32_t
smb_ofile_rename_check(smb_ofile_t * of)1097 smb_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
1144 uint32_t
smb_ofile_delete_check(smb_ofile_t * of)1145 smb_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
1167 cred_t *
smb_ofile_getcred(smb_ofile_t * of)1168 smb_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 */
1186 void
smb_ofile_set_delete_on_close(smb_ofile_t * of)1187 smb_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 */
1198 static int
smb_ofile_netinfo_encode(smb_ofile_t * of,uint8_t * buf,size_t buflen,uint32_t * nbytes)1199 smb_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
1214 static int
smb_ofile_netinfo_init(smb_ofile_t * of,smb_netfileinfo_t * fi)1215 smb_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
1281 static void
smb_ofile_netinfo_fini(smb_netfileinfo_t * fi)1282 smb_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 */
1301 void
smb_ofile_set_quota_resume(smb_ofile_t * ofile,char * resume)1302 smb_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
1313 void
smb_ofile_get_quota_resume(smb_ofile_t * ofile,char * buf,int bufsize)1314 smb_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