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