1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * This module provides the common open functionality to the various
29 * open and create SMB interface functions.
30 */
31
32 #include <sys/types.h>
33 #include <sys/cmn_err.h>
34 #include <sys/fcntl.h>
35 #include <sys/nbmlock.h>
36 #include <smbsrv/string.h>
37 #include <smbsrv/smb_kproto.h>
38 #include <smbsrv/smb_fsops.h>
39 #include <smbsrv/smbinfo.h>
40
41 static volatile uint32_t smb_fids = 0;
42 #define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_fids)
43
44 static uint32_t smb_open_subr(smb_request_t *);
45 extern uint32_t smb_is_executable(char *);
46 static void smb_delete_new_object(smb_request_t *);
47 static int smb_set_open_attributes(smb_request_t *, smb_ofile_t *);
48 static void smb_open_oplock_break(smb_request_t *, smb_node_t *);
49 static boolean_t smb_open_attr_only(smb_arg_open_t *);
50 static boolean_t smb_open_overwrite(smb_arg_open_t *);
51
52 /*
53 * smb_access_generic_to_file
54 *
55 * Search MSDN for IoCreateFile to see following mapping.
56 *
57 * GENERIC_READ STANDARD_RIGHTS_READ, FILE_READ_DATA,
58 * FILE_READ_ATTRIBUTES and FILE_READ_EA
59 *
60 * GENERIC_WRITE STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
61 * FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
62 *
63 * GENERIC_EXECUTE STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
64 *
65 * Careful, we have to emulate some Windows behavior here.
66 * When requested access == zero, you get READ_CONTROL.
67 * MacOS 10.7 depends on this.
68 */
69 uint32_t
smb_access_generic_to_file(uint32_t desired_access)70 smb_access_generic_to_file(uint32_t desired_access)
71 {
72 uint32_t access = READ_CONTROL;
73
74 if (desired_access & GENERIC_ALL)
75 return (FILE_ALL_ACCESS & ~SYNCHRONIZE);
76
77 if (desired_access & GENERIC_EXECUTE) {
78 desired_access &= ~GENERIC_EXECUTE;
79 access |= (STANDARD_RIGHTS_EXECUTE |
80 SYNCHRONIZE | FILE_EXECUTE);
81 }
82
83 if (desired_access & GENERIC_WRITE) {
84 desired_access &= ~GENERIC_WRITE;
85 access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE);
86 }
87
88 if (desired_access & GENERIC_READ) {
89 desired_access &= ~GENERIC_READ;
90 access |= FILE_GENERIC_READ;
91 }
92
93 return (access | desired_access);
94 }
95
96 /*
97 * smb_omode_to_amask
98 *
99 * This function converts open modes used by Open and Open AndX
100 * commands to desired access bits used by NT Create AndX command.
101 */
102 uint32_t
smb_omode_to_amask(uint32_t desired_access)103 smb_omode_to_amask(uint32_t desired_access)
104 {
105 switch (desired_access & SMB_DA_ACCESS_MASK) {
106 case SMB_DA_ACCESS_READ:
107 return (FILE_GENERIC_READ);
108
109 case SMB_DA_ACCESS_WRITE:
110 return (FILE_GENERIC_WRITE);
111
112 case SMB_DA_ACCESS_READ_WRITE:
113 return (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
114
115 case SMB_DA_ACCESS_EXECUTE:
116 return (FILE_GENERIC_EXECUTE);
117
118 default:
119 return (FILE_GENERIC_ALL);
120 }
121 }
122
123 /*
124 * smb_denymode_to_sharemode
125 *
126 * This function converts deny modes used by Open and Open AndX
127 * commands to share access bits used by NT Create AndX command.
128 */
129 uint32_t
smb_denymode_to_sharemode(uint32_t desired_access,char * fname)130 smb_denymode_to_sharemode(uint32_t desired_access, char *fname)
131 {
132 switch (desired_access & SMB_DA_SHARE_MASK) {
133 case SMB_DA_SHARE_COMPATIBILITY:
134 if (smb_is_executable(fname))
135 return (FILE_SHARE_READ | FILE_SHARE_WRITE);
136
137 return (FILE_SHARE_ALL);
138
139 case SMB_DA_SHARE_EXCLUSIVE:
140 return (FILE_SHARE_NONE);
141
142 case SMB_DA_SHARE_DENY_WRITE:
143 return (FILE_SHARE_READ);
144
145 case SMB_DA_SHARE_DENY_READ:
146 return (FILE_SHARE_WRITE);
147
148 case SMB_DA_SHARE_DENY_NONE:
149 default:
150 return (FILE_SHARE_READ | FILE_SHARE_WRITE);
151 }
152 }
153
154 /*
155 * smb_ofun_to_crdisposition
156 *
157 * This function converts open function values used by Open and Open AndX
158 * commands to create disposition values used by NT Create AndX command.
159 */
160 uint32_t
smb_ofun_to_crdisposition(uint16_t ofun)161 smb_ofun_to_crdisposition(uint16_t ofun)
162 {
163 static int ofun_cr_map[3][2] =
164 {
165 { -1, FILE_CREATE },
166 { FILE_OPEN, FILE_OPEN_IF },
167 { FILE_OVERWRITE, FILE_OVERWRITE_IF }
168 };
169
170 int row = ofun & SMB_OFUN_OPEN_MASK;
171 int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4;
172
173 if (row == 3)
174 return (FILE_MAXIMUM_DISPOSITION + 1);
175
176 return (ofun_cr_map[row][col]);
177 }
178
179 /*
180 * Retry opens to avoid spurious sharing violations, due to timing
181 * issues between closes and opens. The client that already has the
182 * file open may be in the process of closing it.
183 */
184 uint32_t
smb_common_open(smb_request_t * sr)185 smb_common_open(smb_request_t *sr)
186 {
187 smb_arg_open_t *parg;
188 uint32_t status = NT_STATUS_SUCCESS;
189 int count;
190
191 parg = kmem_alloc(sizeof (*parg), KM_SLEEP);
192 bcopy(&sr->arg.open, parg, sizeof (*parg));
193
194 for (count = 0; count <= 4; count++) {
195 if (count != 0)
196 delay(MSEC_TO_TICK(400));
197
198 status = smb_open_subr(sr);
199 if (status != NT_STATUS_SHARING_VIOLATION)
200 break;
201
202 bcopy(parg, &sr->arg.open, sizeof (*parg));
203 }
204
205 if (status == NT_STATUS_SHARING_VIOLATION) {
206 smbsr_error(sr, NT_STATUS_SHARING_VIOLATION,
207 ERRDOS, ERROR_SHARING_VIOLATION);
208 }
209
210 if (status == NT_STATUS_NO_SUCH_FILE) {
211 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
212 ERRDOS, ERROR_FILE_NOT_FOUND);
213 }
214
215 kmem_free(parg, sizeof (*parg));
216 return (status);
217 }
218
219 /*
220 * smb_open_subr
221 *
222 * Notes on write-through behaviour. It looks like pre-LM0.12 versions
223 * of the protocol specify the write-through mode when a file is opened,
224 * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose,
225 * SmbWriteAndUnlock) don't need to contain a write-through flag.
226 *
227 * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate)
228 * don't indicate which write-through mode to use. Instead the write
229 * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call
230 * basis.
231 *
232 * We don't care which open call was used to get us here, we just need
233 * to ensure that the write-through mode flag is copied from the open
234 * parameters to the node. We test the omode write-through flag in all
235 * write functions.
236 *
237 * This function will return NT status codes but it also raises errors,
238 * in which case it won't return to the caller. Be careful how you
239 * handle things in here.
240 *
241 * The following rules apply when processing a file open request:
242 *
243 * - Oplocks must be broken prior to share checking as the break may
244 * cause other clients to close the file, which would affect sharing
245 * checks.
246 *
247 * - Share checks must take place prior to access checks for correct
248 * Windows semantics and to prevent unnecessary NFS delegation recalls.
249 *
250 * - Oplocks must be acquired after open to ensure the correct
251 * synchronization with NFS delegation and FEM installation.
252 *
253 * DOS readonly bit rules
254 *
255 * 1. The creator of a readonly file can write to/modify the size of the file
256 * using the original create fid, even though the file will appear as readonly
257 * to all other fids and via a CIFS getattr call.
258 * The readonly bit therefore cannot be set in the filesystem until the file
259 * is closed (smb_ofile_close). It is accounted for via ofile and node flags.
260 *
261 * 2. A setinfo operation (using either an open fid or a path) to set/unset
262 * readonly will be successful regardless of whether a creator of a readonly
263 * file has an open fid (and has the special privilege mentioned in #1,
264 * above). I.e., the creator of a readonly fid holding that fid will no longer
265 * have a special privilege.
266 *
267 * 3. The DOS readonly bit affects only data and some metadata.
268 * The following metadata can be changed regardless of the readonly bit:
269 * - security descriptors
270 * - DOS attributes
271 * - timestamps
272 *
273 * In the current implementation, the file size cannot be changed (except for
274 * the exceptions in #1 and #2, above).
275 *
276 *
277 * DOS attribute rules
278 *
279 * These rules are specific to creating / opening files and directories.
280 * How the attribute value (specifically ZERO or FILE_ATTRIBUTE_NORMAL)
281 * should be interpreted may differ in other requests.
282 *
283 * - An attribute value equal to ZERO or FILE_ATTRIBUTE_NORMAL means that the
284 * file's attributes should be cleared.
285 * - If FILE_ATTRIBUTE_NORMAL is specified with any other attributes,
286 * FILE_ATTRIBUTE_NORMAL is ignored.
287 *
288 * 1. Creating a new file
289 * - The request attributes + FILE_ATTRIBUTE_ARCHIVE are applied to the file.
290 *
291 * 2. Creating a new directory
292 * - The request attributes + FILE_ATTRIBUTE_DIRECTORY are applied to the file.
293 * - FILE_ATTRIBUTE_ARCHIVE does not get set.
294 *
295 * 3. Overwriting an existing file
296 * - the request attributes are used as search attributes. If the existing
297 * file does not meet the search criteria access is denied.
298 * - otherwise, applies attributes + FILE_ATTRIBUTE_ARCHIVE.
299 *
300 * 4. Opening an existing file or directory
301 * The request attributes are ignored.
302 */
303 static uint32_t
smb_open_subr(smb_request_t * sr)304 smb_open_subr(smb_request_t *sr)
305 {
306 boolean_t created = B_FALSE;
307 boolean_t last_comp_found = B_FALSE;
308 smb_node_t *node = NULL;
309 smb_node_t *dnode = NULL;
310 smb_node_t *cur_node = NULL;
311 smb_arg_open_t *op = &sr->sr_open;
312 int rc;
313 smb_ofile_t *of;
314 smb_attr_t new_attr;
315 int max_requested = 0;
316 uint32_t max_allowed;
317 uint32_t status = NT_STATUS_SUCCESS;
318 int is_dir;
319 smb_error_t err;
320 boolean_t is_stream = B_FALSE;
321 int lookup_flags = SMB_FOLLOW_LINKS;
322 uint32_t uniq_fid;
323 smb_pathname_t *pn = &op->fqi.fq_path;
324 smb_server_t *sv = sr->sr_server;
325
326 is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
327
328 /*
329 * If the object being created or opened is a directory
330 * the Disposition parameter must be one of FILE_CREATE,
331 * FILE_OPEN, or FILE_OPEN_IF
332 */
333 if (is_dir) {
334 if ((op->create_disposition != FILE_CREATE) &&
335 (op->create_disposition != FILE_OPEN_IF) &&
336 (op->create_disposition != FILE_OPEN)) {
337 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
338 ERRDOS, ERROR_INVALID_ACCESS);
339 return (NT_STATUS_INVALID_PARAMETER);
340 }
341 }
342
343 if (op->desired_access & MAXIMUM_ALLOWED) {
344 max_requested = 1;
345 op->desired_access &= ~MAXIMUM_ALLOWED;
346 }
347 op->desired_access = smb_access_generic_to_file(op->desired_access);
348
349 if (sr->session->s_file_cnt >= SMB_SESSION_OFILE_MAX) {
350 ASSERT(sr->uid_user);
351 cmn_err(CE_NOTE, "smbsrv[%s\\%s]: TOO_MANY_OPENED_FILES",
352 sr->uid_user->u_domain, sr->uid_user->u_name);
353
354 smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
355 ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
356 return (NT_STATUS_TOO_MANY_OPENED_FILES);
357 }
358
359 /* This must be NULL at this point */
360 sr->fid_ofile = NULL;
361
362 op->devstate = 0;
363
364 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
365 case STYPE_DISKTREE:
366 case STYPE_PRINTQ:
367 break;
368
369 case STYPE_IPC:
370
371 if ((rc = smb_threshold_enter(&sv->sv_opipe_ct)) != 0) {
372 status = RPC_NT_SERVER_TOO_BUSY;
373 smbsr_error(sr, status, 0, 0);
374 return (status);
375 }
376
377 /*
378 * No further processing for IPC, we need to either
379 * raise an exception or return success here.
380 */
381 uniq_fid = SMB_UNIQ_FID();
382 status = smb_opipe_open(sr, uniq_fid);
383 if (status != NT_STATUS_SUCCESS)
384 smbsr_error(sr, status, 0, 0);
385
386 smb_threshold_exit(&sv->sv_opipe_ct);
387 return (status);
388
389 default:
390 smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
391 ERRDOS, ERROR_BAD_DEV_TYPE);
392 return (NT_STATUS_BAD_DEVICE_TYPE);
393 }
394
395 smb_pathname_init(sr, pn, pn->pn_path);
396 if (!smb_pathname_validate(sr, pn))
397 return (sr->smb_error.status);
398
399 if (strlen(pn->pn_path) >= MAXPATHLEN) {
400 smbsr_error(sr, 0, ERRSRV, ERRfilespecs);
401 return (NT_STATUS_NAME_TOO_LONG);
402 }
403
404 if (is_dir) {
405 if (!smb_validate_dirname(sr, pn))
406 return (sr->smb_error.status);
407 } else {
408 if (!smb_validate_object_name(sr, pn))
409 return (sr->smb_error.status);
410 }
411
412 cur_node = op->fqi.fq_dnode ?
413 op->fqi.fq_dnode : sr->tid_tree->t_snode;
414
415 /*
416 * if no path or filename are specified the stream should be
417 * created on cur_node
418 */
419 if (!is_dir && !pn->pn_pname && !pn->pn_fname && pn->pn_sname) {
420 /*
421 * Can't currently handle a stream on the tree root.
422 * If a stream is being opened return "not found", otherwise
423 * return "access denied".
424 */
425 if (cur_node == sr->tid_tree->t_snode) {
426 if (op->create_disposition == FILE_OPEN) {
427 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
428 ERRDOS, ERROR_FILE_NOT_FOUND);
429 return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
430 }
431 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
432 ERROR_ACCESS_DENIED);
433 return (NT_STATUS_ACCESS_DENIED);
434 }
435
436 (void) snprintf(op->fqi.fq_last_comp,
437 sizeof (op->fqi.fq_last_comp),
438 "%s%s", cur_node->od_name, pn->pn_sname);
439
440 op->fqi.fq_dnode = cur_node->n_dnode;
441 smb_node_ref(op->fqi.fq_dnode);
442 } else {
443 rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
444 sr->tid_tree->t_snode, cur_node, &op->fqi.fq_dnode,
445 op->fqi.fq_last_comp);
446 if (rc != 0) {
447 smbsr_errno(sr, rc);
448 return (sr->smb_error.status);
449 }
450 }
451
452 /*
453 * If the access mask has only DELETE set (ignore
454 * FILE_READ_ATTRIBUTES), then assume that this
455 * is a request to delete the link (if a link)
456 * and do not follow links. Otherwise, follow
457 * the link to the target.
458 */
459 if ((op->desired_access & ~FILE_READ_ATTRIBUTES) == DELETE)
460 lookup_flags &= ~SMB_FOLLOW_LINKS;
461
462 rc = smb_fsop_lookup_name(sr, zone_kcred(), lookup_flags,
463 sr->tid_tree->t_snode, op->fqi.fq_dnode, op->fqi.fq_last_comp,
464 &op->fqi.fq_fnode);
465
466 if (rc == 0) {
467 last_comp_found = B_TRUE;
468 /*
469 * Need the DOS attributes below, where we
470 * check the search attributes (sattr).
471 */
472 op->fqi.fq_fattr.sa_mask = SMB_AT_DOSATTR;
473 rc = smb_node_getattr(sr, op->fqi.fq_fnode, zone_kcred(),
474 NULL, &op->fqi.fq_fattr);
475 if (rc != 0) {
476 smb_node_release(op->fqi.fq_fnode);
477 smb_node_release(op->fqi.fq_dnode);
478 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
479 ERRDOS, ERROR_INTERNAL_ERROR);
480 return (sr->smb_error.status);
481 }
482 } else if (rc == ENOENT) {
483 last_comp_found = B_FALSE;
484 op->fqi.fq_fnode = NULL;
485 rc = 0;
486 } else {
487 smb_node_release(op->fqi.fq_dnode);
488 smbsr_errno(sr, rc);
489 return (sr->smb_error.status);
490 }
491
492
493 /*
494 * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
495 * which is used to uniquely identify open instances for the
496 * VFS share reservation and POSIX locks.
497 */
498
499 uniq_fid = SMB_UNIQ_FID();
500
501 if (last_comp_found) {
502
503 node = op->fqi.fq_fnode;
504 dnode = op->fqi.fq_dnode;
505
506 if (!smb_node_is_file(node) && !smb_node_is_dir(node) &&
507 !smb_node_is_symlink(node)) {
508 smb_node_release(node);
509 smb_node_release(dnode);
510 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
511 ERRnoaccess);
512 return (NT_STATUS_ACCESS_DENIED);
513 }
514
515 /*
516 * Reject this request if either:
517 * - the target IS a directory and the client requires that
518 * it must NOT be (required by Lotus Notes)
519 * - the target is NOT a directory and client requires that
520 * it MUST be.
521 */
522 if (smb_node_is_dir(node)) {
523 if (op->create_options & FILE_NON_DIRECTORY_FILE) {
524 smb_node_release(node);
525 smb_node_release(dnode);
526 smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY,
527 ERRDOS, ERROR_ACCESS_DENIED);
528 return (NT_STATUS_FILE_IS_A_DIRECTORY);
529 }
530 } else {
531 if ((op->create_options & FILE_DIRECTORY_FILE) ||
532 (op->nt_flags & NT_CREATE_FLAG_OPEN_TARGET_DIR)) {
533 smb_node_release(node);
534 smb_node_release(dnode);
535 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
536 ERRDOS, ERROR_DIRECTORY);
537 return (NT_STATUS_NOT_A_DIRECTORY);
538 }
539 }
540
541 /*
542 * No more open should be accepted when "Delete on close"
543 * flag is set.
544 */
545 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
546 smb_node_release(node);
547 smb_node_release(dnode);
548 smbsr_error(sr, NT_STATUS_DELETE_PENDING,
549 ERRDOS, ERROR_ACCESS_DENIED);
550 return (NT_STATUS_DELETE_PENDING);
551 }
552
553 /*
554 * Specified file already exists so the operation should fail.
555 */
556 if (op->create_disposition == FILE_CREATE) {
557 smb_node_release(node);
558 smb_node_release(dnode);
559 smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION,
560 ERRDOS, ERROR_FILE_EXISTS);
561 return (NT_STATUS_OBJECT_NAME_COLLISION);
562 }
563
564 /*
565 * Windows seems to check read-only access before file
566 * sharing check.
567 *
568 * Check to see if the file is currently readonly (irrespective
569 * of whether this open will make it readonly).
570 */
571 if (SMB_PATHFILE_IS_READONLY(sr, node)) {
572 /* Files data only */
573 if (!smb_node_is_dir(node)) {
574 if (op->desired_access & (FILE_WRITE_DATA |
575 FILE_APPEND_DATA)) {
576 smb_node_release(node);
577 smb_node_release(dnode);
578 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
579 ERRDOS, ERRnoaccess);
580 return (NT_STATUS_ACCESS_DENIED);
581 }
582 }
583 }
584
585 if ((op->create_disposition == FILE_SUPERSEDE) ||
586 (op->create_disposition == FILE_OVERWRITE_IF) ||
587 (op->create_disposition == FILE_OVERWRITE)) {
588
589 if (!smb_sattr_check(op->fqi.fq_fattr.sa_dosattr,
590 op->dattr)) {
591 smb_node_release(node);
592 smb_node_release(dnode);
593 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
594 ERRDOS, ERRnoaccess);
595 return (NT_STATUS_ACCESS_DENIED);
596 }
597
598 if (smb_node_is_dir(node)) {
599 smb_node_release(node);
600 smb_node_release(dnode);
601 return (NT_STATUS_ACCESS_DENIED);
602 }
603 }
604
605 /* MS-FSA 2.1.5.1.2 */
606 if (op->create_disposition == FILE_SUPERSEDE)
607 op->desired_access |= DELETE;
608 if ((op->create_disposition == FILE_OVERWRITE_IF) ||
609 (op->create_disposition == FILE_OVERWRITE))
610 op->desired_access |= FILE_WRITE_DATA;
611
612 status = smb_fsop_access(sr, sr->user_cr, node,
613 op->desired_access);
614 if (status != NT_STATUS_SUCCESS) {
615 smb_node_release(node);
616 smb_node_release(dnode);
617
618 if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
619 smbsr_error(sr, status,
620 ERRDOS, ERROR_PRIVILEGE_NOT_HELD);
621 return (status);
622 } else {
623 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
624 ERRDOS, ERROR_ACCESS_DENIED);
625 return (NT_STATUS_ACCESS_DENIED);
626 }
627 }
628
629 if (max_requested) {
630 smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
631 op->desired_access |= max_allowed;
632 }
633
634 /*
635 * Oplock break is done prior to sharing checks as the break
636 * may cause other clients to close the file which would
637 * affect the sharing checks. This may block, so set the
638 * file opening count before oplock stuff.
639 */
640 smb_node_inc_opening_count(node);
641 smb_open_oplock_break(sr, node);
642
643 smb_node_wrlock(node);
644
645 /*
646 * Check for sharing violations
647 */
648 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
649 op->desired_access, op->share_access);
650 if (status == NT_STATUS_SHARING_VIOLATION) {
651 smb_node_unlock(node);
652 smb_node_dec_opening_count(node);
653 smb_node_release(node);
654 smb_node_release(dnode);
655 return (status);
656 }
657
658 /*
659 * Go ahead with modifications as necessary.
660 */
661 switch (op->create_disposition) {
662 case FILE_SUPERSEDE:
663 case FILE_OVERWRITE_IF:
664 case FILE_OVERWRITE:
665 op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
666 /* Don't apply readonly bit until smb_ofile_close */
667 if (op->dattr & FILE_ATTRIBUTE_READONLY) {
668 op->created_readonly = B_TRUE;
669 op->dattr &= ~FILE_ATTRIBUTE_READONLY;
670 }
671
672 bzero(&new_attr, sizeof (new_attr));
673 new_attr.sa_dosattr = op->dattr;
674 new_attr.sa_vattr.va_size = op->dsize;
675 new_attr.sa_mask = SMB_AT_DOSATTR | SMB_AT_SIZE;
676 rc = smb_fsop_setattr(sr, sr->user_cr, node, &new_attr);
677 if (rc != 0) {
678 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
679 smb_node_unlock(node);
680 smb_node_dec_opening_count(node);
681 smb_node_release(node);
682 smb_node_release(dnode);
683 smbsr_errno(sr, rc);
684 return (sr->smb_error.status);
685 }
686
687 /*
688 * If file is being replaced, remove existing streams
689 */
690 if (SMB_IS_STREAM(node) == 0) {
691 rc = smb_fsop_remove_streams(sr, sr->user_cr,
692 node);
693 if (rc != 0) {
694 smb_fsop_unshrlock(sr->user_cr, node,
695 uniq_fid);
696 smb_node_unlock(node);
697 smb_node_dec_opening_count(node);
698 smb_node_release(node);
699 smb_node_release(dnode);
700 return (sr->smb_error.status);
701 }
702 }
703
704 op->action_taken = SMB_OACT_TRUNCATED;
705 break;
706
707 default:
708 /*
709 * FILE_OPEN or FILE_OPEN_IF.
710 */
711 op->action_taken = SMB_OACT_OPENED;
712 break;
713 }
714 } else {
715 /* Last component was not found. */
716 dnode = op->fqi.fq_dnode;
717
718 if (is_dir == 0)
719 is_stream = smb_is_stream_name(pn->pn_path);
720
721 if ((op->create_disposition == FILE_OPEN) ||
722 (op->create_disposition == FILE_OVERWRITE)) {
723 smb_node_release(dnode);
724 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
725 ERRDOS, ERROR_FILE_NOT_FOUND);
726 return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
727 }
728
729 if (pn->pn_fname && smb_is_invalid_filename(pn->pn_fname)) {
730 smb_node_release(dnode);
731 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
732 ERRDOS, ERROR_INVALID_NAME);
733 return (NT_STATUS_OBJECT_NAME_INVALID);
734 }
735
736 /*
737 * lock the parent dir node in case another create
738 * request to the same parent directory comes in.
739 */
740 smb_node_wrlock(dnode);
741
742 /* Don't apply readonly bit until smb_ofile_close */
743 if (op->dattr & FILE_ATTRIBUTE_READONLY) {
744 op->dattr &= ~FILE_ATTRIBUTE_READONLY;
745 op->created_readonly = B_TRUE;
746 }
747
748 bzero(&new_attr, sizeof (new_attr));
749 if ((op->crtime.tv_sec != 0) &&
750 (op->crtime.tv_sec != UINT_MAX)) {
751
752 new_attr.sa_mask |= SMB_AT_CRTIME;
753 new_attr.sa_crtime = op->crtime;
754 }
755
756 if (is_dir == 0) {
757 op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
758 new_attr.sa_dosattr = op->dattr;
759 new_attr.sa_vattr.va_type = VREG;
760 new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR :
761 S_IRUSR | S_IRGRP | S_IROTH |
762 S_IWUSR | S_IWGRP | S_IWOTH;
763 new_attr.sa_mask |=
764 SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
765
766 if (op->dsize) {
767 new_attr.sa_vattr.va_size = op->dsize;
768 new_attr.sa_mask |= SMB_AT_SIZE;
769 }
770
771 rc = smb_fsop_create(sr, sr->user_cr, dnode,
772 op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
773
774 if (rc != 0) {
775 smb_node_unlock(dnode);
776 smb_node_release(dnode);
777 smbsr_errno(sr, rc);
778 return (sr->smb_error.status);
779 }
780
781 node = op->fqi.fq_fnode;
782 smb_node_inc_opening_count(node);
783 smb_node_wrlock(node);
784
785 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
786 op->desired_access, op->share_access);
787
788 if (status == NT_STATUS_SHARING_VIOLATION) {
789 smb_node_unlock(node);
790 smb_node_dec_opening_count(node);
791 smb_delete_new_object(sr);
792 smb_node_release(node);
793 smb_node_unlock(dnode);
794 smb_node_release(dnode);
795 return (status);
796 }
797 } else {
798 op->dattr |= FILE_ATTRIBUTE_DIRECTORY;
799 new_attr.sa_dosattr = op->dattr;
800 new_attr.sa_vattr.va_type = VDIR;
801 new_attr.sa_vattr.va_mode = 0777;
802 new_attr.sa_mask |=
803 SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
804
805 rc = smb_fsop_mkdir(sr, sr->user_cr, dnode,
806 op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
807 if (rc != 0) {
808 smb_node_unlock(dnode);
809 smb_node_release(dnode);
810 smbsr_errno(sr, rc);
811 return (sr->smb_error.status);
812 }
813
814 node = op->fqi.fq_fnode;
815 smb_node_inc_opening_count(node);
816 smb_node_wrlock(node);
817 }
818
819 created = B_TRUE;
820 op->action_taken = SMB_OACT_CREATED;
821
822 if (max_requested) {
823 smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
824 op->desired_access |= max_allowed;
825 }
826 }
827
828 status = NT_STATUS_SUCCESS;
829
830 of = smb_ofile_open(sr, node, op, SMB_FTYPE_DISK, uniq_fid,
831 &err);
832 if (of == NULL) {
833 smbsr_error(sr, err.status, err.errcls, err.errcode);
834 status = err.status;
835 }
836
837 /*
838 * We might have blocked in smb_ofile_open long enough so a
839 * tree disconnect might have happened. In that case, we've
840 * just added an ofile to a tree that's disconnecting, and
841 * need to undo that to avoid interfering with tear-down of
842 * the tree connection.
843 */
844 if (status == NT_STATUS_SUCCESS &&
845 !smb_tree_is_connected(sr->tid_tree)) {
846 smbsr_error(sr, 0, ERRSRV, ERRinvnid);
847 status = NT_STATUS_INVALID_PARAMETER;
848 }
849
850 /*
851 * This MUST be done after ofile creation, so that explicitly
852 * set timestamps can be remembered on the ofile, and the
853 * readonly flag will be stored "pending" on the node.
854 */
855 if (status == NT_STATUS_SUCCESS) {
856 if ((rc = smb_set_open_attributes(sr, of)) != 0) {
857 smbsr_errno(sr, rc);
858 status = sr->smb_error.status;
859 }
860 }
861
862 if (status == NT_STATUS_SUCCESS) {
863 /*
864 * We've already done access checks above,
865 * and want this call to succeed even when
866 * !(desired_access & FILE_READ_ATTRIBUTES),
867 * so pass kcred here.
868 */
869 op->fqi.fq_fattr.sa_mask = SMB_AT_ALL;
870 rc = smb_node_getattr(sr, node, zone_kcred(), of,
871 &op->fqi.fq_fattr);
872 if (rc != 0) {
873 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
874 ERRDOS, ERROR_INTERNAL_ERROR);
875 status = NT_STATUS_INTERNAL_ERROR;
876 }
877 }
878
879 /*
880 * smb_fsop_unshrlock is a no-op if node is a directory
881 * smb_fsop_unshrlock is done in smb_ofile_close
882 */
883 if (status != NT_STATUS_SUCCESS) {
884 if (of == NULL) {
885 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
886 } else {
887 smb_ofile_close(of, 0);
888 smb_ofile_release(of);
889 }
890 if (created)
891 smb_delete_new_object(sr);
892 smb_node_unlock(node);
893 smb_node_dec_opening_count(node);
894 smb_node_release(node);
895 if (created)
896 smb_node_unlock(dnode);
897 smb_node_release(dnode);
898 return (status);
899 }
900
901 /*
902 * Propagate the write-through mode from the open params
903 * to the node: see the notes in the function header.
904 */
905 if (sr->sr_cfg->skc_sync_enable ||
906 (op->create_options & FILE_WRITE_THROUGH))
907 node->flags |= NODE_FLAGS_WRITE_THROUGH;
908
909 /*
910 * Set up the fileid and dosattr in open_param for response
911 */
912 op->fileid = op->fqi.fq_fattr.sa_vattr.va_nodeid;
913 op->dattr = op->fqi.fq_fattr.sa_dosattr;
914
915 /*
916 * Set up the file type in open_param for the response
917 */
918 op->ftype = SMB_FTYPE_DISK;
919 sr->smb_fid = of->f_fid;
920 sr->fid_ofile = of;
921
922 if (smb_node_is_file(node)) {
923 smb_oplock_acquire(sr, node, of);
924 op->dsize = op->fqi.fq_fattr.sa_vattr.va_size;
925 } else {
926 /* directory or symlink */
927 op->op_oplock_level = SMB_OPLOCK_NONE;
928 op->dsize = 0;
929 }
930
931 smb_node_dec_opening_count(node);
932
933 smb_node_unlock(node);
934 if (created)
935 smb_node_unlock(dnode);
936
937 smb_node_release(node);
938 smb_node_release(dnode);
939
940 return (NT_STATUS_SUCCESS);
941 }
942
943 /*
944 * smb_open_oplock_break
945 *
946 * If the node has an ofile opened with share access none,
947 * (smb_node_share_check = FALSE) only break BATCH oplock.
948 * Otherwise:
949 * If overwriting, break to SMB_OPLOCK_NONE, else
950 * If opening for anything other than attribute access,
951 * break oplock to LEVEL_II.
952 */
953 static void
smb_open_oplock_break(smb_request_t * sr,smb_node_t * node)954 smb_open_oplock_break(smb_request_t *sr, smb_node_t *node)
955 {
956 smb_arg_open_t *op = &sr->sr_open;
957 uint32_t flags = 0;
958
959 if (!smb_node_share_check(node))
960 flags |= SMB_OPLOCK_BREAK_BATCH;
961
962 if (smb_open_overwrite(op)) {
963 flags |= SMB_OPLOCK_BREAK_TO_NONE;
964 (void) smb_oplock_break(sr, node, flags);
965 } else if (!smb_open_attr_only(op)) {
966 flags |= SMB_OPLOCK_BREAK_TO_LEVEL_II;
967 (void) smb_oplock_break(sr, node, flags);
968 }
969 }
970
971 /*
972 * smb_open_attr_only
973 *
974 * Determine if file is being opened for attribute access only.
975 * This is used to determine whether it is necessary to break
976 * existing oplocks on the file.
977 */
978 static boolean_t
smb_open_attr_only(smb_arg_open_t * op)979 smb_open_attr_only(smb_arg_open_t *op)
980 {
981 if (((op->desired_access & ~(FILE_READ_ATTRIBUTES |
982 FILE_WRITE_ATTRIBUTES | SYNCHRONIZE | READ_CONTROL)) == 0) &&
983 (op->create_disposition != FILE_SUPERSEDE) &&
984 (op->create_disposition != FILE_OVERWRITE)) {
985 return (B_TRUE);
986 }
987 return (B_FALSE);
988 }
989
990 static boolean_t
smb_open_overwrite(smb_arg_open_t * op)991 smb_open_overwrite(smb_arg_open_t *op)
992 {
993 if ((op->create_disposition == FILE_SUPERSEDE) ||
994 (op->create_disposition == FILE_OVERWRITE_IF) ||
995 (op->create_disposition == FILE_OVERWRITE)) {
996 return (B_TRUE);
997 }
998 return (B_FALSE);
999 }
1000
1001 /*
1002 * smb_set_open_attributes
1003 *
1004 * Last write time:
1005 * - If the last_write time specified in the open params is not 0 or -1,
1006 * use it as file's mtime. This will be considered an explicitly set
1007 * timestamps, not reset by subsequent writes.
1008 *
1009 * DOS attributes
1010 * - If we created_readonly, we now store the real DOS attributes
1011 * (including the readonly bit) so subsequent opens will see it.
1012 *
1013 * Both are stored "pending" rather than in the file system.
1014 *
1015 * Returns: errno
1016 */
1017 static int
smb_set_open_attributes(smb_request_t * sr,smb_ofile_t * of)1018 smb_set_open_attributes(smb_request_t *sr, smb_ofile_t *of)
1019 {
1020 smb_attr_t attr;
1021 smb_arg_open_t *op = &sr->sr_open;
1022 smb_node_t *node = of->f_node;
1023 int rc = 0;
1024
1025 bzero(&attr, sizeof (smb_attr_t));
1026
1027 if (op->created_readonly) {
1028 attr.sa_dosattr = op->dattr | FILE_ATTRIBUTE_READONLY;
1029 attr.sa_mask |= SMB_AT_DOSATTR;
1030 }
1031
1032 if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
1033 attr.sa_vattr.va_mtime = op->mtime;
1034 attr.sa_mask |= SMB_AT_MTIME;
1035 }
1036
1037 /*
1038 * Used to have code here to set mtime, ctime, atime
1039 * when the open op->create_disposition is any of:
1040 * FILE_SUPERSEDE, FILE_OVERWRITE_IF, FILE_OVERWRITE.
1041 * We know that in those cases we will have set the
1042 * file size, in which case the file system will
1043 * update those times, so we don't have to.
1044 *
1045 * However, keep track of the fact that we modified
1046 * the file via this handle, so we can do the evil,
1047 * gratuitious mtime update on close that Windows
1048 * clients appear to expect.
1049 */
1050 if (op->action_taken == SMB_OACT_TRUNCATED)
1051 of->f_written = B_TRUE;
1052
1053 if (attr.sa_mask != 0)
1054 rc = smb_node_setattr(sr, node, of->f_cr, of, &attr);
1055
1056 return (rc);
1057 }
1058
1059 /*
1060 * This function is used to delete a newly created object (file or
1061 * directory) if an error occurs after creation of the object.
1062 */
1063 static void
smb_delete_new_object(smb_request_t * sr)1064 smb_delete_new_object(smb_request_t *sr)
1065 {
1066 smb_arg_open_t *op = &sr->sr_open;
1067 smb_fqi_t *fqi = &(op->fqi);
1068 uint32_t flags = 0;
1069
1070 if (SMB_TREE_IS_CASEINSENSITIVE(sr))
1071 flags |= SMB_IGNORE_CASE;
1072 if (SMB_TREE_SUPPORTS_CATIA(sr))
1073 flags |= SMB_CATIA;
1074
1075 if (op->create_options & FILE_DIRECTORY_FILE)
1076 (void) smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
1077 fqi->fq_last_comp, flags);
1078 else
1079 (void) smb_fsop_remove(sr, sr->user_cr, fqi->fq_dnode,
1080 fqi->fq_last_comp, flags);
1081 }
1082