xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_open.c (revision a724c049b7e0dd8612bc3aaec84e96e80511050d)
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 2008 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, NULL, op->dattr))) {
552 				rw_exit(&node->n_share_lock);
553 				smb_node_release(node);
554 				smb_node_release(dnode);
555 				SMB_NULL_FQI_NODES(op->fqi);
556 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
557 				    ERRDOS, ERRnoaccess);
558 				return (NT_STATUS_ACCESS_DENIED);
559 			}
560 		}
561 
562 		status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
563 		    op->desired_access, op->share_access);
564 
565 		if (status == NT_STATUS_SHARING_VIOLATION) {
566 			rw_exit(&node->n_share_lock);
567 			smb_node_release(node);
568 			smb_node_release(dnode);
569 			SMB_NULL_FQI_NODES(op->fqi);
570 			return (status);
571 		}
572 
573 		status = smb_fsop_access(sr, sr->user_cr, node,
574 		    op->desired_access);
575 
576 		if (status != NT_STATUS_SUCCESS) {
577 			smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
578 
579 			rw_exit(&node->n_share_lock);
580 			smb_node_release(node);
581 			smb_node_release(dnode);
582 			SMB_NULL_FQI_NODES(op->fqi);
583 
584 			if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
585 				smbsr_error(sr, status,
586 				    ERRDOS, ERROR_PRIVILEGE_NOT_HELD);
587 				return (status);
588 			} else {
589 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
590 				    ERRDOS, ERROR_ACCESS_DENIED);
591 				return (NT_STATUS_ACCESS_DENIED);
592 			}
593 		}
594 
595 		switch (op->create_disposition) {
596 		case FILE_SUPERSEDE:
597 		case FILE_OVERWRITE_IF:
598 		case FILE_OVERWRITE:
599 			if (node->attr.sa_vattr.va_type == VDIR) {
600 				smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
601 				rw_exit(&node->n_share_lock);
602 				smb_node_release(node);
603 				smb_node_release(dnode);
604 				SMB_NULL_FQI_NODES(op->fqi);
605 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
606 				    ERRDOS, ERROR_ACCESS_DENIED);
607 				return (NT_STATUS_ACCESS_DENIED);
608 			}
609 
610 			if (node->attr.sa_vattr.va_size != op->dsize) {
611 				node->flags &= ~NODE_FLAGS_SET_SIZE;
612 				bzero(&new_attr, sizeof (new_attr));
613 				new_attr.sa_vattr.va_size = op->dsize;
614 				new_attr.sa_mask = SMB_AT_SIZE;
615 
616 				rc = smb_fsop_setattr(sr, sr->user_cr,
617 				    node, &new_attr, &op->fqi.last_attr);
618 
619 				if (rc) {
620 					smb_fsop_unshrlock(sr->user_cr, node,
621 					    uniq_fid);
622 					rw_exit(&node->n_share_lock);
623 					smb_node_release(node);
624 					smb_node_release(dnode);
625 					SMB_NULL_FQI_NODES(op->fqi);
626 					smbsr_errno(sr, rc);
627 					return (sr->smb_error.status);
628 				}
629 
630 				op->dsize = op->fqi.last_attr.sa_vattr.va_size;
631 			}
632 
633 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
634 			if (op->dattr & FILE_ATTRIBUTE_READONLY) {
635 				op->created_readonly = B_TRUE;
636 				op->dattr &= ~FILE_ATTRIBUTE_READONLY;
637 			}
638 
639 			smb_node_set_dosattr(node, op->dattr);
640 			(void) smb_sync_fsattr(sr, sr->user_cr, node);
641 
642 			/*
643 			 * If file is being replaced,
644 			 * we should remove existing streams
645 			 */
646 			if (SMB_IS_STREAM(node) == 0)
647 				(void) smb_fsop_remove_streams(sr, sr->user_cr,
648 				    node);
649 
650 			op->action_taken = SMB_OACT_TRUNCATED;
651 			break;
652 
653 		default:
654 			/*
655 			 * FILE_OPEN or FILE_OPEN_IF.
656 			 */
657 			op->action_taken = SMB_OACT_OPENED;
658 			break;
659 		}
660 	} else {
661 
662 		/* Last component was not found. */
663 		dnode = op->fqi.dir_snode;
664 
665 		if (is_dir == 0)
666 			is_stream = smb_is_stream_name(op->fqi.path);
667 
668 		if ((op->create_disposition == FILE_OPEN) ||
669 		    (op->create_disposition == FILE_OVERWRITE)) {
670 			smb_node_release(dnode);
671 			SMB_NULL_FQI_NODES(op->fqi);
672 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
673 			    ERRDOS, ERROR_FILE_NOT_FOUND);
674 			return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
675 		}
676 
677 		/*
678 		 * lock the parent dir node in case another create
679 		 * request to the same parent directory comes in.
680 		 */
681 		smb_rwx_rwenter(&dnode->n_lock, RW_WRITER);
682 
683 		bzero(&new_attr, sizeof (new_attr));
684 		new_attr.sa_dosattr = op->dattr;
685 		new_attr.sa_mask |= SMB_AT_DOSATTR;
686 
687 		/*
688 		 * A file created with the readonly bit should not
689 		 * stop the creator writing to the file until it is
690 		 * closed.  Although the readonly bit will not be set
691 		 * on the file until it is closed, it will be accounted
692 		 * for on other fids and on queries based on the node
693 		 * state.
694 		 */
695 		if (op->dattr & FILE_ATTRIBUTE_READONLY)
696 			new_attr.sa_dosattr &= ~FILE_ATTRIBUTE_READONLY;
697 
698 
699 		if ((op->crtime.tv_sec != 0) &&
700 		    (op->crtime.tv_sec != UINT_MAX)) {
701 
702 			new_attr.sa_mask |= SMB_AT_CRTIME;
703 			new_attr.sa_crtime = op->crtime;
704 		}
705 
706 		if (is_dir == 0) {
707 			new_attr.sa_dosattr |= FILE_ATTRIBUTE_ARCHIVE;
708 			new_attr.sa_vattr.va_type = VREG;
709 			new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR :
710 			    S_IRUSR | S_IRGRP | S_IROTH |
711 			    S_IWUSR | S_IWGRP | S_IWOTH;
712 			new_attr.sa_mask |= SMB_AT_TYPE | SMB_AT_MODE;
713 
714 			if (op->dsize) {
715 				new_attr.sa_vattr.va_size = op->dsize;
716 				new_attr.sa_mask |= SMB_AT_SIZE;
717 			}
718 
719 			rc = smb_fsop_create(sr, sr->user_cr, dnode,
720 			    op->fqi.last_comp, &new_attr,
721 			    &op->fqi.last_snode, &op->fqi.last_attr);
722 
723 			if (rc != 0) {
724 				smb_rwx_rwexit(&dnode->n_lock);
725 				smb_node_release(dnode);
726 				SMB_NULL_FQI_NODES(op->fqi);
727 				smbsr_errno(sr, rc);
728 				return (sr->smb_error.status);
729 			}
730 
731 			node = op->fqi.last_snode;
732 
733 			op->fqi.last_attr = node->attr;
734 
735 			rw_enter(&node->n_share_lock, RW_WRITER);
736 
737 			status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
738 			    op->desired_access, op->share_access);
739 
740 			if (status == NT_STATUS_SHARING_VIOLATION) {
741 				rw_exit(&node->n_share_lock);
742 				SMB_DEL_NEWOBJ(op->fqi);
743 				smb_node_release(node);
744 				smb_node_release(dnode);
745 				SMB_NULL_FQI_NODES(op->fqi);
746 				return (status);
747 			}
748 
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