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