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