5917 User-mode SMB server
[unleashed.git] / usr / src / uts / common / fs / smbsrv / smb_common_open.c
blob6e217c51edd09fd1fecc88a3dedd3785650f3967
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
28 * This module provides the common open functionality to the various
29 * open and create SMB interface functions.
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>
41 volatile uint32_t smb_fids = 0;
42 #define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_fids)
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 *);
53 * smb_access_generic_to_file
55 * Search MSDN for IoCreateFile to see following mapping.
57 * GENERIC_READ STANDARD_RIGHTS_READ, FILE_READ_DATA,
58 * FILE_READ_ATTRIBUTES and FILE_READ_EA
60 * GENERIC_WRITE STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
61 * FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
63 * GENERIC_EXECUTE STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
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.
69 uint32_t
70 smb_access_generic_to_file(uint32_t desired_access)
72 uint32_t access = READ_CONTROL;
74 if (desired_access & GENERIC_ALL)
75 return (FILE_ALL_ACCESS & ~SYNCHRONIZE);
77 if (desired_access & GENERIC_EXECUTE) {
78 desired_access &= ~GENERIC_EXECUTE;
79 access |= (STANDARD_RIGHTS_EXECUTE |
80 SYNCHRONIZE | FILE_EXECUTE);
83 if (desired_access & GENERIC_WRITE) {
84 desired_access &= ~GENERIC_WRITE;
85 access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE);
88 if (desired_access & GENERIC_READ) {
89 desired_access &= ~GENERIC_READ;
90 access |= FILE_GENERIC_READ;
93 return (access | desired_access);
97 * smb_omode_to_amask
99 * This function converts open modes used by Open and Open AndX
100 * commands to desired access bits used by NT Create AndX command.
102 uint32_t
103 smb_omode_to_amask(uint32_t desired_access)
105 switch (desired_access & SMB_DA_ACCESS_MASK) {
106 case SMB_DA_ACCESS_READ:
107 return (FILE_GENERIC_READ);
109 case SMB_DA_ACCESS_WRITE:
110 return (FILE_GENERIC_WRITE);
112 case SMB_DA_ACCESS_READ_WRITE:
113 return (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
115 case SMB_DA_ACCESS_EXECUTE:
116 return (FILE_GENERIC_EXECUTE);
118 default:
119 return (FILE_GENERIC_ALL);
124 * smb_denymode_to_sharemode
126 * This function converts deny modes used by Open and Open AndX
127 * commands to share access bits used by NT Create AndX command.
129 uint32_t
130 smb_denymode_to_sharemode(uint32_t desired_access, char *fname)
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);
137 return (FILE_SHARE_ALL);
139 case SMB_DA_SHARE_EXCLUSIVE:
140 return (FILE_SHARE_NONE);
142 case SMB_DA_SHARE_DENY_WRITE:
143 return (FILE_SHARE_READ);
145 case SMB_DA_SHARE_DENY_READ:
146 return (FILE_SHARE_WRITE);
148 case SMB_DA_SHARE_DENY_NONE:
149 default:
150 return (FILE_SHARE_READ | FILE_SHARE_WRITE);
155 * smb_ofun_to_crdisposition
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.
160 uint32_t
161 smb_ofun_to_crdisposition(uint16_t ofun)
163 static int ofun_cr_map[3][2] =
165 { -1, FILE_CREATE },
166 { FILE_OPEN, FILE_OPEN_IF },
167 { FILE_OVERWRITE, FILE_OVERWRITE_IF }
170 int row = ofun & SMB_OFUN_OPEN_MASK;
171 int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4;
173 if (row == 3)
174 return (FILE_MAXIMUM_DISPOSITION + 1);
176 return (ofun_cr_map[row][col]);
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.
184 uint32_t
185 smb_common_open(smb_request_t *sr)
187 smb_arg_open_t *parg;
188 uint32_t status = NT_STATUS_SUCCESS;
189 int count;
191 parg = kmem_alloc(sizeof (*parg), KM_SLEEP);
192 bcopy(&sr->arg.open, parg, sizeof (*parg));
194 for (count = 0; count <= 4; count++) {
195 if (count != 0)
196 delay(MSEC_TO_TICK(400));
198 status = smb_open_subr(sr);
199 if (status != NT_STATUS_SHARING_VIOLATION)
200 break;
202 bcopy(parg, &sr->arg.open, sizeof (*parg));
205 if (status == NT_STATUS_SHARING_VIOLATION) {
206 smbsr_error(sr, NT_STATUS_SHARING_VIOLATION,
207 ERRDOS, ERROR_SHARING_VIOLATION);
210 if (status == NT_STATUS_NO_SUCH_FILE) {
211 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
212 ERRDOS, ERROR_FILE_NOT_FOUND);
215 kmem_free(parg, sizeof (*parg));
216 return (status);
220 * smb_open_subr
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.
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.
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.
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.
241 * The following rules apply when processing a file open request:
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.
247 * - Share checks must take place prior to access checks for correct
248 * Windows semantics and to prevent unnecessary NFS delegation recalls.
250 * - Oplocks must be acquired after open to ensure the correct
251 * synchronization with NFS delegation and FEM installation.
253 * DOS readonly bit rules
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.
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.
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
273 * In the current implementation, the file size cannot be changed (except for
274 * the exceptions in #1 and #2, above).
277 * DOS attribute rules
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.
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.
288 * 1. Creating a new file
289 * - The request attributes + FILE_ATTRIBUTE_ARCHIVE are applied to the file.
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.
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.
300 * 4. Opening an existing file or directory
301 * The request attributes are ignored.
303 static uint32_t
304 smb_open_subr(smb_request_t *sr)
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;
326 is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
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
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);
343 if (op->desired_access & MAXIMUM_ALLOWED) {
344 max_requested = 1;
345 op->desired_access &= ~MAXIMUM_ALLOWED;
347 op->desired_access = smb_access_generic_to_file(op->desired_access);
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);
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);
359 /* This must be NULL at this point */
360 sr->fid_ofile = NULL;
362 op->devstate = 0;
364 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
365 case STYPE_DISKTREE:
366 case STYPE_PRINTQ:
367 break;
369 case STYPE_IPC:
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);
378 * No further processing for IPC, we need to either
379 * raise an exception or return success here.
381 if ((status = smb_opipe_open(sr)) != NT_STATUS_SUCCESS)
382 smbsr_error(sr, status, 0, 0);
384 smb_threshold_exit(&sv->sv_opipe_ct);
385 return (status);
387 default:
388 smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
389 ERRDOS, ERROR_BAD_DEV_TYPE);
390 return (NT_STATUS_BAD_DEVICE_TYPE);
393 smb_pathname_init(sr, pn, pn->pn_path);
394 if (!smb_pathname_validate(sr, pn))
395 return (sr->smb_error.status);
397 if (strlen(pn->pn_path) >= MAXPATHLEN) {
398 smbsr_error(sr, 0, ERRSRV, ERRfilespecs);
399 return (NT_STATUS_NAME_TOO_LONG);
402 if (is_dir) {
403 if (!smb_validate_dirname(sr, pn))
404 return (sr->smb_error.status);
405 } else {
406 if (!smb_validate_object_name(sr, pn))
407 return (sr->smb_error.status);
410 cur_node = op->fqi.fq_dnode ?
411 op->fqi.fq_dnode : sr->tid_tree->t_snode;
414 * if no path or filename are specified the stream should be
415 * created on cur_node
417 if (!is_dir && !pn->pn_pname && !pn->pn_fname && pn->pn_sname) {
419 * Can't currently handle a stream on the tree root.
420 * If a stream is being opened return "not found", otherwise
421 * return "access denied".
423 if (cur_node == sr->tid_tree->t_snode) {
424 if (op->create_disposition == FILE_OPEN) {
425 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
426 ERRDOS, ERROR_FILE_NOT_FOUND);
427 return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
429 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
430 ERROR_ACCESS_DENIED);
431 return (NT_STATUS_ACCESS_DENIED);
434 (void) snprintf(op->fqi.fq_last_comp,
435 sizeof (op->fqi.fq_last_comp),
436 "%s%s", cur_node->od_name, pn->pn_sname);
438 op->fqi.fq_dnode = cur_node->n_dnode;
439 smb_node_ref(op->fqi.fq_dnode);
440 } else {
441 rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
442 sr->tid_tree->t_snode, cur_node, &op->fqi.fq_dnode,
443 op->fqi.fq_last_comp);
444 if (rc != 0) {
445 smbsr_errno(sr, rc);
446 return (sr->smb_error.status);
451 * If the access mask has only DELETE set (ignore
452 * FILE_READ_ATTRIBUTES), then assume that this
453 * is a request to delete the link (if a link)
454 * and do not follow links. Otherwise, follow
455 * the link to the target.
457 if ((op->desired_access & ~FILE_READ_ATTRIBUTES) == DELETE)
458 lookup_flags &= ~SMB_FOLLOW_LINKS;
460 rc = smb_fsop_lookup_name(sr, zone_kcred(), lookup_flags,
461 sr->tid_tree->t_snode, op->fqi.fq_dnode, op->fqi.fq_last_comp,
462 &op->fqi.fq_fnode);
464 if (rc == 0) {
465 last_comp_found = B_TRUE;
467 * Need the DOS attributes below, where we
468 * check the search attributes (sattr).
470 op->fqi.fq_fattr.sa_mask = SMB_AT_DOSATTR;
471 rc = smb_node_getattr(sr, op->fqi.fq_fnode, zone_kcred(),
472 NULL, &op->fqi.fq_fattr);
473 if (rc != 0) {
474 smb_node_release(op->fqi.fq_fnode);
475 smb_node_release(op->fqi.fq_dnode);
476 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
477 ERRDOS, ERROR_INTERNAL_ERROR);
478 return (sr->smb_error.status);
480 } else if (rc == ENOENT) {
481 last_comp_found = B_FALSE;
482 op->fqi.fq_fnode = NULL;
483 rc = 0;
484 } else {
485 smb_node_release(op->fqi.fq_dnode);
486 smbsr_errno(sr, rc);
487 return (sr->smb_error.status);
492 * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
493 * which is used to uniquely identify open instances for the
494 * VFS share reservation and POSIX locks.
497 uniq_fid = SMB_UNIQ_FID();
499 if (last_comp_found) {
501 node = op->fqi.fq_fnode;
502 dnode = op->fqi.fq_dnode;
504 if (!smb_node_is_file(node) && !smb_node_is_dir(node) &&
505 !smb_node_is_symlink(node)) {
506 smb_node_release(node);
507 smb_node_release(dnode);
508 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
509 ERRnoaccess);
510 return (NT_STATUS_ACCESS_DENIED);
514 * Reject this request if either:
515 * - the target IS a directory and the client requires that
516 * it must NOT be (required by Lotus Notes)
517 * - the target is NOT a directory and client requires that
518 * it MUST be.
520 if (smb_node_is_dir(node)) {
521 if (op->create_options & FILE_NON_DIRECTORY_FILE) {
522 smb_node_release(node);
523 smb_node_release(dnode);
524 smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY,
525 ERRDOS, ERROR_ACCESS_DENIED);
526 return (NT_STATUS_FILE_IS_A_DIRECTORY);
528 } else {
529 if ((op->create_options & FILE_DIRECTORY_FILE) ||
530 (op->nt_flags & NT_CREATE_FLAG_OPEN_TARGET_DIR)) {
531 smb_node_release(node);
532 smb_node_release(dnode);
533 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
534 ERRDOS, ERROR_DIRECTORY);
535 return (NT_STATUS_NOT_A_DIRECTORY);
540 * No more open should be accepted when "Delete on close"
541 * flag is set.
543 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
544 smb_node_release(node);
545 smb_node_release(dnode);
546 smbsr_error(sr, NT_STATUS_DELETE_PENDING,
547 ERRDOS, ERROR_ACCESS_DENIED);
548 return (NT_STATUS_DELETE_PENDING);
552 * Specified file already exists so the operation should fail.
554 if (op->create_disposition == FILE_CREATE) {
555 smb_node_release(node);
556 smb_node_release(dnode);
557 smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION,
558 ERRDOS, ERROR_FILE_EXISTS);
559 return (NT_STATUS_OBJECT_NAME_COLLISION);
563 * Windows seems to check read-only access before file
564 * sharing check.
566 * Check to see if the file is currently readonly (irrespective
567 * of whether this open will make it readonly).
569 if (SMB_PATHFILE_IS_READONLY(sr, node)) {
570 /* Files data only */
571 if (!smb_node_is_dir(node)) {
572 if (op->desired_access & (FILE_WRITE_DATA |
573 FILE_APPEND_DATA)) {
574 smb_node_release(node);
575 smb_node_release(dnode);
576 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
577 ERRDOS, ERRnoaccess);
578 return (NT_STATUS_ACCESS_DENIED);
583 if ((op->create_disposition == FILE_SUPERSEDE) ||
584 (op->create_disposition == FILE_OVERWRITE_IF) ||
585 (op->create_disposition == FILE_OVERWRITE)) {
587 if (!smb_sattr_check(op->fqi.fq_fattr.sa_dosattr,
588 op->dattr)) {
589 smb_node_release(node);
590 smb_node_release(dnode);
591 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
592 ERRDOS, ERRnoaccess);
593 return (NT_STATUS_ACCESS_DENIED);
596 if (smb_node_is_dir(node)) {
597 smb_node_release(node);
598 smb_node_release(dnode);
599 return (NT_STATUS_ACCESS_DENIED);
603 /* MS-FSA 2.1.5.1.2 */
604 if (op->create_disposition == FILE_SUPERSEDE)
605 op->desired_access |= DELETE;
606 if ((op->create_disposition == FILE_OVERWRITE_IF) ||
607 (op->create_disposition == FILE_OVERWRITE))
608 op->desired_access |= FILE_WRITE_DATA;
610 status = smb_fsop_access(sr, sr->user_cr, node,
611 op->desired_access);
612 if (status != NT_STATUS_SUCCESS) {
613 smb_node_release(node);
614 smb_node_release(dnode);
616 if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
617 smbsr_error(sr, status,
618 ERRDOS, ERROR_PRIVILEGE_NOT_HELD);
619 return (status);
620 } else {
621 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
622 ERRDOS, ERROR_ACCESS_DENIED);
623 return (NT_STATUS_ACCESS_DENIED);
627 if (max_requested) {
628 smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
629 op->desired_access |= max_allowed;
633 * Oplock break is done prior to sharing checks as the break
634 * may cause other clients to close the file which would
635 * affect the sharing checks. This may block, so set the
636 * file opening count before oplock stuff.
638 smb_node_inc_opening_count(node);
639 smb_open_oplock_break(sr, node);
641 smb_node_wrlock(node);
644 * Check for sharing violations
646 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
647 op->desired_access, op->share_access);
648 if (status == NT_STATUS_SHARING_VIOLATION) {
649 smb_node_unlock(node);
650 smb_node_dec_opening_count(node);
651 smb_node_release(node);
652 smb_node_release(dnode);
653 return (status);
657 * Go ahead with modifications as necessary.
659 switch (op->create_disposition) {
660 case FILE_SUPERSEDE:
661 case FILE_OVERWRITE_IF:
662 case FILE_OVERWRITE:
663 op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
664 /* Don't apply readonly bit until smb_ofile_close */
665 if (op->dattr & FILE_ATTRIBUTE_READONLY) {
666 op->created_readonly = B_TRUE;
667 op->dattr &= ~FILE_ATTRIBUTE_READONLY;
670 bzero(&new_attr, sizeof (new_attr));
671 new_attr.sa_dosattr = op->dattr;
672 new_attr.sa_vattr.va_size = op->dsize;
673 new_attr.sa_mask = SMB_AT_DOSATTR | SMB_AT_SIZE;
674 rc = smb_fsop_setattr(sr, sr->user_cr, node, &new_attr);
675 if (rc != 0) {
676 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
677 smb_node_unlock(node);
678 smb_node_dec_opening_count(node);
679 smb_node_release(node);
680 smb_node_release(dnode);
681 smbsr_errno(sr, rc);
682 return (sr->smb_error.status);
686 * If file is being replaced, remove existing streams
688 if (SMB_IS_STREAM(node) == 0) {
689 rc = smb_fsop_remove_streams(sr, sr->user_cr,
690 node);
691 if (rc != 0) {
692 smb_fsop_unshrlock(sr->user_cr, node,
693 uniq_fid);
694 smb_node_unlock(node);
695 smb_node_dec_opening_count(node);
696 smb_node_release(node);
697 smb_node_release(dnode);
698 return (sr->smb_error.status);
702 op->action_taken = SMB_OACT_TRUNCATED;
703 break;
705 default:
707 * FILE_OPEN or FILE_OPEN_IF.
709 op->action_taken = SMB_OACT_OPENED;
710 break;
712 } else {
713 /* Last component was not found. */
714 dnode = op->fqi.fq_dnode;
716 if (is_dir == 0)
717 is_stream = smb_is_stream_name(pn->pn_path);
719 if ((op->create_disposition == FILE_OPEN) ||
720 (op->create_disposition == FILE_OVERWRITE)) {
721 smb_node_release(dnode);
722 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
723 ERRDOS, ERROR_FILE_NOT_FOUND);
724 return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
727 if (pn->pn_fname && smb_is_invalid_filename(pn->pn_fname)) {
728 smb_node_release(dnode);
729 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
730 ERRDOS, ERROR_INVALID_NAME);
731 return (NT_STATUS_OBJECT_NAME_INVALID);
735 * lock the parent dir node in case another create
736 * request to the same parent directory comes in.
738 smb_node_wrlock(dnode);
740 /* Don't apply readonly bit until smb_ofile_close */
741 if (op->dattr & FILE_ATTRIBUTE_READONLY) {
742 op->dattr &= ~FILE_ATTRIBUTE_READONLY;
743 op->created_readonly = B_TRUE;
746 bzero(&new_attr, sizeof (new_attr));
747 if ((op->crtime.tv_sec != 0) &&
748 (op->crtime.tv_sec != UINT_MAX)) {
750 new_attr.sa_mask |= SMB_AT_CRTIME;
751 new_attr.sa_crtime = op->crtime;
754 if (is_dir == 0) {
755 op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
756 new_attr.sa_dosattr = op->dattr;
757 new_attr.sa_vattr.va_type = VREG;
758 new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR :
759 S_IRUSR | S_IRGRP | S_IROTH |
760 S_IWUSR | S_IWGRP | S_IWOTH;
761 new_attr.sa_mask |=
762 SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
764 if (op->dsize) {
765 new_attr.sa_vattr.va_size = op->dsize;
766 new_attr.sa_mask |= SMB_AT_SIZE;
769 rc = smb_fsop_create(sr, sr->user_cr, dnode,
770 op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
772 if (rc != 0) {
773 smb_node_unlock(dnode);
774 smb_node_release(dnode);
775 smbsr_errno(sr, rc);
776 return (sr->smb_error.status);
779 node = op->fqi.fq_fnode;
780 smb_node_inc_opening_count(node);
781 smb_node_wrlock(node);
783 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
784 op->desired_access, op->share_access);
786 if (status == NT_STATUS_SHARING_VIOLATION) {
787 smb_node_unlock(node);
788 smb_node_dec_opening_count(node);
789 smb_delete_new_object(sr);
790 smb_node_release(node);
791 smb_node_unlock(dnode);
792 smb_node_release(dnode);
793 return (status);
795 } else {
796 op->dattr |= FILE_ATTRIBUTE_DIRECTORY;
797 new_attr.sa_dosattr = op->dattr;
798 new_attr.sa_vattr.va_type = VDIR;
799 new_attr.sa_vattr.va_mode = 0777;
800 new_attr.sa_mask |=
801 SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
803 rc = smb_fsop_mkdir(sr, sr->user_cr, dnode,
804 op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
805 if (rc != 0) {
806 smb_node_unlock(dnode);
807 smb_node_release(dnode);
808 smbsr_errno(sr, rc);
809 return (sr->smb_error.status);
812 node = op->fqi.fq_fnode;
813 smb_node_inc_opening_count(node);
814 smb_node_wrlock(node);
817 created = B_TRUE;
818 op->action_taken = SMB_OACT_CREATED;
820 if (max_requested) {
821 smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
822 op->desired_access |= max_allowed;
826 status = NT_STATUS_SUCCESS;
828 of = smb_ofile_open(sr, node, sr->smb_pid, op, SMB_FTYPE_DISK, uniq_fid,
829 &err);
830 if (of == NULL) {
831 smbsr_error(sr, err.status, err.errcls, err.errcode);
832 status = err.status;
835 if (status == NT_STATUS_SUCCESS) {
836 if (!smb_tree_is_connected(sr->tid_tree)) {
837 smbsr_error(sr, 0, ERRSRV, ERRinvnid);
838 status = NT_STATUS_UNSUCCESSFUL;
843 * This MUST be done after ofile creation, so that explicitly
844 * set timestamps can be remembered on the ofile, and the
845 * readonly flag will be stored "pending" on the node.
847 if (status == NT_STATUS_SUCCESS) {
848 if ((rc = smb_set_open_attributes(sr, of)) != 0) {
849 smbsr_errno(sr, rc);
850 status = sr->smb_error.status;
854 if (status == NT_STATUS_SUCCESS) {
856 * We've already done access checks above,
857 * and want this call to succeed even when
858 * !(desired_access & FILE_READ_ATTRIBUTES),
859 * so pass kcred here.
861 op->fqi.fq_fattr.sa_mask = SMB_AT_ALL;
862 rc = smb_node_getattr(sr, node, zone_kcred(), of,
863 &op->fqi.fq_fattr);
864 if (rc != 0) {
865 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
866 ERRDOS, ERROR_INTERNAL_ERROR);
867 status = NT_STATUS_INTERNAL_ERROR;
872 * smb_fsop_unshrlock is a no-op if node is a directory
873 * smb_fsop_unshrlock is done in smb_ofile_close
875 if (status != NT_STATUS_SUCCESS) {
876 if (of == NULL) {
877 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
878 } else {
879 smb_ofile_close(of, 0);
880 smb_ofile_release(of);
882 if (created)
883 smb_delete_new_object(sr);
884 smb_node_unlock(node);
885 smb_node_dec_opening_count(node);
886 smb_node_release(node);
887 if (created)
888 smb_node_unlock(dnode);
889 smb_node_release(dnode);
890 return (status);
894 * Propagate the write-through mode from the open params
895 * to the node: see the notes in the function header.
897 if (sr->sr_cfg->skc_sync_enable ||
898 (op->create_options & FILE_WRITE_THROUGH))
899 node->flags |= NODE_FLAGS_WRITE_THROUGH;
902 * Set up the fileid and dosattr in open_param for response
904 op->fileid = op->fqi.fq_fattr.sa_vattr.va_nodeid;
905 op->dattr = op->fqi.fq_fattr.sa_dosattr;
908 * Set up the file type in open_param for the response
910 op->ftype = SMB_FTYPE_DISK;
911 sr->smb_fid = of->f_fid;
912 sr->fid_ofile = of;
914 if (smb_node_is_file(node)) {
915 smb_oplock_acquire(sr, node, of);
916 op->dsize = op->fqi.fq_fattr.sa_vattr.va_size;
917 } else {
918 /* directory or symlink */
919 op->op_oplock_level = SMB_OPLOCK_NONE;
920 op->dsize = 0;
923 smb_node_dec_opening_count(node);
925 smb_node_unlock(node);
926 if (created)
927 smb_node_unlock(dnode);
929 smb_node_release(node);
930 smb_node_release(dnode);
932 return (NT_STATUS_SUCCESS);
936 * smb_open_oplock_break
938 * If the node has an ofile opened with share access none,
939 * (smb_node_share_check = FALSE) only break BATCH oplock.
940 * Otherwise:
941 * If overwriting, break to SMB_OPLOCK_NONE, else
942 * If opening for anything other than attribute access,
943 * break oplock to LEVEL_II.
945 static void
946 smb_open_oplock_break(smb_request_t *sr, smb_node_t *node)
948 smb_arg_open_t *op = &sr->sr_open;
949 uint32_t flags = 0;
951 if (!smb_node_share_check(node))
952 flags |= SMB_OPLOCK_BREAK_BATCH;
954 if (smb_open_overwrite(op)) {
955 flags |= SMB_OPLOCK_BREAK_TO_NONE;
956 (void) smb_oplock_break(sr, node, flags);
957 } else if (!smb_open_attr_only(op)) {
958 flags |= SMB_OPLOCK_BREAK_TO_LEVEL_II;
959 (void) smb_oplock_break(sr, node, flags);
964 * smb_open_attr_only
966 * Determine if file is being opened for attribute access only.
967 * This is used to determine whether it is necessary to break
968 * existing oplocks on the file.
970 static boolean_t
971 smb_open_attr_only(smb_arg_open_t *op)
973 if (((op->desired_access & ~(FILE_READ_ATTRIBUTES |
974 FILE_WRITE_ATTRIBUTES | SYNCHRONIZE | READ_CONTROL)) == 0) &&
975 (op->create_disposition != FILE_SUPERSEDE) &&
976 (op->create_disposition != FILE_OVERWRITE)) {
977 return (B_TRUE);
979 return (B_FALSE);
982 static boolean_t
983 smb_open_overwrite(smb_arg_open_t *op)
985 if ((op->create_disposition == FILE_SUPERSEDE) ||
986 (op->create_disposition == FILE_OVERWRITE_IF) ||
987 (op->create_disposition == FILE_OVERWRITE)) {
988 return (B_TRUE);
990 return (B_FALSE);
994 * smb_set_open_attributes
996 * Last write time:
997 * - If the last_write time specified in the open params is not 0 or -1,
998 * use it as file's mtime. This will be considered an explicitly set
999 * timestamps, not reset by subsequent writes.
1001 * DOS attributes
1002 * - If we created_readonly, we now store the real DOS attributes
1003 * (including the readonly bit) so subsequent opens will see it.
1005 * Both are stored "pending" rather than in the file system.
1007 * Returns: errno
1009 static int
1010 smb_set_open_attributes(smb_request_t *sr, smb_ofile_t *of)
1012 smb_attr_t attr;
1013 smb_arg_open_t *op = &sr->sr_open;
1014 smb_node_t *node = of->f_node;
1015 int rc = 0;
1017 bzero(&attr, sizeof (smb_attr_t));
1019 if (op->created_readonly) {
1020 attr.sa_dosattr = op->dattr | FILE_ATTRIBUTE_READONLY;
1021 attr.sa_mask |= SMB_AT_DOSATTR;
1024 if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
1025 attr.sa_vattr.va_mtime = op->mtime;
1026 attr.sa_mask |= SMB_AT_MTIME;
1030 * Used to have code here to set mtime, ctime, atime
1031 * when the open op->create_disposition is any of:
1032 * FILE_SUPERSEDE, FILE_OVERWRITE_IF, FILE_OVERWRITE.
1033 * We know that in those cases we will have set the
1034 * file size, in which case the file system will
1035 * update those times, so we don't have to.
1037 * However, keep track of the fact that we modified
1038 * the file via this handle, so we can do the evil,
1039 * gratuitious mtime update on close that Windows
1040 * clients appear to expect.
1042 if (op->action_taken == SMB_OACT_TRUNCATED)
1043 of->f_written = B_TRUE;
1045 if (attr.sa_mask != 0)
1046 rc = smb_node_setattr(sr, node, of->f_cr, of, &attr);
1048 return (rc);
1052 * This function is used to delete a newly created object (file or
1053 * directory) if an error occurs after creation of the object.
1055 static void
1056 smb_delete_new_object(smb_request_t *sr)
1058 smb_arg_open_t *op = &sr->sr_open;
1059 smb_fqi_t *fqi = &(op->fqi);
1060 uint32_t flags = 0;
1062 if (SMB_TREE_IS_CASEINSENSITIVE(sr))
1063 flags |= SMB_IGNORE_CASE;
1064 if (SMB_TREE_SUPPORTS_CATIA(sr))
1065 flags |= SMB_CATIA;
1067 if (op->create_options & FILE_DIRECTORY_FILE)
1068 (void) smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
1069 fqi->fq_last_comp, flags);
1070 else
1071 (void) smb_fsop_remove(sr, sr->user_cr, fqi->fq_dnode,
1072 fqi->fq_last_comp, flags);