xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_open.c (revision 3589c4f01c20349ca65899d209cdc0c17a641433)
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,
543 			    SMB_SESSION_GET_ID(sr->session), B_FALSE);
544 
545 		smb_node_wrlock(node);
546 
547 		if ((op->create_disposition == FILE_SUPERSEDE) ||
548 		    (op->create_disposition == FILE_OVERWRITE_IF) ||
549 		    (op->create_disposition == FILE_OVERWRITE)) {
550 
551 			if ((!(op->desired_access &
552 			    (FILE_WRITE_DATA | FILE_APPEND_DATA |
553 			    FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA))) ||
554 			    (!smb_sattr_check(node->attr.sa_dosattr,
555 			    op->dattr))) {
556 				smb_node_unlock(node);
557 				smb_node_release(node);
558 				smb_node_release(dnode);
559 				SMB_NULL_FQI_NODES(op->fqi);
560 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
561 				    ERRDOS, ERRnoaccess);
562 				return (NT_STATUS_ACCESS_DENIED);
563 			}
564 		}
565 
566 		status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
567 		    op->desired_access, op->share_access);
568 
569 		if (status == NT_STATUS_SHARING_VIOLATION) {
570 			smb_node_unlock(node);
571 			smb_node_release(node);
572 			smb_node_release(dnode);
573 			SMB_NULL_FQI_NODES(op->fqi);
574 			return (status);
575 		}
576 
577 		status = smb_fsop_access(sr, sr->user_cr, node,
578 		    op->desired_access);
579 
580 		if (status != NT_STATUS_SUCCESS) {
581 			smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
582 
583 			smb_node_unlock(node);
584 			smb_node_release(node);
585 			smb_node_release(dnode);
586 			SMB_NULL_FQI_NODES(op->fqi);
587 
588 			if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
589 				smbsr_error(sr, status,
590 				    ERRDOS, ERROR_PRIVILEGE_NOT_HELD);
591 				return (status);
592 			} else {
593 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
594 				    ERRDOS, ERROR_ACCESS_DENIED);
595 				return (NT_STATUS_ACCESS_DENIED);
596 			}
597 		}
598 
599 		switch (op->create_disposition) {
600 		case FILE_SUPERSEDE:
601 		case FILE_OVERWRITE_IF:
602 		case FILE_OVERWRITE:
603 			if (node->attr.sa_vattr.va_type == VDIR) {
604 				smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
605 				smb_node_unlock(node);
606 				smb_node_release(node);
607 				smb_node_release(dnode);
608 				SMB_NULL_FQI_NODES(op->fqi);
609 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
610 				    ERRDOS, ERROR_ACCESS_DENIED);
611 				return (NT_STATUS_ACCESS_DENIED);
612 			}
613 
614 			if (node->attr.sa_vattr.va_size != op->dsize) {
615 				node->flags &= ~NODE_FLAGS_SET_SIZE;
616 				bzero(&new_attr, sizeof (new_attr));
617 				new_attr.sa_vattr.va_size = op->dsize;
618 				new_attr.sa_mask = SMB_AT_SIZE;
619 
620 				rc = smb_fsop_setattr(sr, sr->user_cr,
621 				    node, &new_attr, &op->fqi.last_attr);
622 
623 				if (rc) {
624 					smb_fsop_unshrlock(sr->user_cr, node,
625 					    uniq_fid);
626 					smb_node_unlock(node);
627 					smb_node_release(node);
628 					smb_node_release(dnode);
629 					SMB_NULL_FQI_NODES(op->fqi);
630 					smbsr_errno(sr, rc);
631 					return (sr->smb_error.status);
632 				}
633 
634 				op->dsize = op->fqi.last_attr.sa_vattr.va_size;
635 			}
636 
637 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
638 			if (op->dattr & FILE_ATTRIBUTE_READONLY) {
639 				op->created_readonly = B_TRUE;
640 				op->dattr &= ~FILE_ATTRIBUTE_READONLY;
641 			}
642 
643 			smb_node_set_dosattr(node, op->dattr);
644 			(void) smb_sync_fsattr(sr, sr->user_cr, node);
645 
646 			/*
647 			 * If file is being replaced,
648 			 * we should remove existing streams
649 			 */
650 			if (SMB_IS_STREAM(node) == 0)
651 				(void) smb_fsop_remove_streams(sr, sr->user_cr,
652 				    node);
653 
654 			op->action_taken = SMB_OACT_TRUNCATED;
655 			break;
656 
657 		default:
658 			/*
659 			 * FILE_OPEN or FILE_OPEN_IF.
660 			 */
661 			op->action_taken = SMB_OACT_OPENED;
662 			break;
663 		}
664 	} else {
665 		/* Last component was not found. */
666 		dnode = op->fqi.dir_snode;
667 
668 		if (is_dir == 0)
669 			is_stream = smb_is_stream_name(op->fqi.path);
670 
671 		if ((op->create_disposition == FILE_OPEN) ||
672 		    (op->create_disposition == FILE_OVERWRITE)) {
673 			smb_node_release(dnode);
674 			SMB_NULL_FQI_NODES(op->fqi);
675 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
676 			    ERRDOS, ERROR_FILE_NOT_FOUND);
677 			return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
678 		}
679 
680 		if ((is_dir == 0) && (!is_stream) &&
681 		    smb_is_invalid_filename(op->fqi.last_comp)) {
682 			smb_node_release(dnode);
683 			SMB_NULL_FQI_NODES(op->fqi);
684 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
685 			    ERRDOS, ERROR_INVALID_NAME);
686 			return (NT_STATUS_OBJECT_NAME_INVALID);
687 		}
688 
689 		/*
690 		 * lock the parent dir node in case another create
691 		 * request to the same parent directory comes in.
692 		 */
693 		smb_node_wrlock(dnode);
694 
695 		bzero(&new_attr, sizeof (new_attr));
696 		new_attr.sa_dosattr = op->dattr;
697 		new_attr.sa_mask |= SMB_AT_DOSATTR;
698 
699 		/*
700 		 * A file created with the readonly bit should not
701 		 * stop the creator writing to the file until it is
702 		 * closed.  Although the readonly bit will not be set
703 		 * on the file until it is closed, it will be accounted
704 		 * for on other fids and on queries based on the node
705 		 * state.
706 		 */
707 		if (op->dattr & FILE_ATTRIBUTE_READONLY)
708 			new_attr.sa_dosattr &= ~FILE_ATTRIBUTE_READONLY;
709 
710 
711 		if ((op->crtime.tv_sec != 0) &&
712 		    (op->crtime.tv_sec != UINT_MAX)) {
713 
714 			new_attr.sa_mask |= SMB_AT_CRTIME;
715 			new_attr.sa_crtime = op->crtime;
716 		}
717 
718 		if (is_dir == 0) {
719 			new_attr.sa_dosattr |= FILE_ATTRIBUTE_ARCHIVE;
720 			new_attr.sa_vattr.va_type = VREG;
721 			new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR :
722 			    S_IRUSR | S_IRGRP | S_IROTH |
723 			    S_IWUSR | S_IWGRP | S_IWOTH;
724 			new_attr.sa_mask |= SMB_AT_TYPE | SMB_AT_MODE;
725 
726 			if (op->dsize) {
727 				new_attr.sa_vattr.va_size = op->dsize;
728 				new_attr.sa_mask |= SMB_AT_SIZE;
729 			}
730 
731 			rc = smb_fsop_create(sr, sr->user_cr, dnode,
732 			    op->fqi.last_comp, &new_attr,
733 			    &op->fqi.last_snode, &op->fqi.last_attr);
734 
735 			if (rc != 0) {
736 				smb_node_unlock(dnode);
737 				smb_node_release(dnode);
738 				SMB_NULL_FQI_NODES(op->fqi);
739 				smbsr_errno(sr, rc);
740 				return (sr->smb_error.status);
741 			}
742 
743 			node = op->fqi.last_snode;
744 
745 			op->fqi.last_attr = node->attr;
746 
747 			smb_node_wrlock(node);
748 
749 			status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
750 			    op->desired_access, op->share_access);
751 
752 			if (status == NT_STATUS_SHARING_VIOLATION) {
753 				smb_node_unlock(node);
754 				SMB_DEL_NEWOBJ(op->fqi);
755 				smb_node_release(node);
756 				smb_node_unlock(dnode);
757 				smb_node_release(dnode);
758 				SMB_NULL_FQI_NODES(op->fqi);
759 				return (status);
760 			}
761 		} else {
762 			op->dattr |= FILE_ATTRIBUTE_DIRECTORY;
763 			new_attr.sa_vattr.va_type = VDIR;
764 			new_attr.sa_vattr.va_mode = 0777;
765 			new_attr.sa_mask |= SMB_AT_TYPE | SMB_AT_MODE;
766 
767 			rc = smb_fsop_mkdir(sr, sr->user_cr, dnode,
768 			    op->fqi.last_comp, &new_attr,
769 			    &op->fqi.last_snode, &op->fqi.last_attr);
770 			if (rc != 0) {
771 				smb_node_unlock(dnode);
772 				smb_node_release(dnode);
773 				SMB_NULL_FQI_NODES(op->fqi);
774 				smbsr_errno(sr, rc);
775 				return (sr->smb_error.status);
776 			}
777 
778 			node = op->fqi.last_snode;
779 			smb_node_wrlock(node);
780 		}
781 
782 		created = 1;
783 		op->action_taken = SMB_OACT_CREATED;
784 		node->flags |= NODE_FLAGS_CREATED;
785 
786 		if (op->dattr & FILE_ATTRIBUTE_READONLY) {
787 			op->created_readonly = B_TRUE;
788 			op->dattr &= ~FILE_ATTRIBUTE_READONLY;
789 		}
790 	}
791 
792 	op->dattr = smb_node_get_dosattr(node);
793 
794 	if (max_requested) {
795 		smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
796 		op->desired_access |= max_allowed;
797 	}
798 
799 	/*
800 	 * if last_write time was in request and is not 0 or -1,
801 	 * use it as file's mtime
802 	 */
803 	if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
804 		smb_node_set_time(node, NULL, &op->mtime, NULL, NULL,
805 		    SMB_AT_MTIME);
806 		(void) smb_sync_fsattr(sr, sr->user_cr, node);
807 	}
808 
809 	/*
810 	 * smb_ofile_open() will copy node to of->node.  Hence
811 	 * the hold on node (i.e. op->fqi.last_snode) will be "transferred"
812 	 * to the "of" structure.
813 	 */
814 
815 	of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op, SMB_FTYPE_DISK,
816 	    uniq_fid, &err);
817 
818 	if (of == NULL) {
819 		smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
820 
821 		SMB_DEL_NEWOBJ(op->fqi);
822 		smb_node_unlock(node);
823 		smb_node_release(node);
824 		if (created)
825 			smb_node_unlock(dnode);
826 		smb_node_release(dnode);
827 		SMB_NULL_FQI_NODES(op->fqi);
828 		smbsr_error(sr, err.status, err.errcls, err.errcode);
829 		return (err.status);
830 	}
831 
832 	/*
833 	 * Propagate the write-through mode from the open params
834 	 * to the node: see the notes in the function header.
835 	 */
836 	if (sr->sr_cfg->skc_sync_enable ||
837 	    (op->create_options & FILE_WRITE_THROUGH))
838 		node->flags |= NODE_FLAGS_WRITE_THROUGH;
839 
840 	op->fileid = op->fqi.last_attr.sa_vattr.va_nodeid;
841 
842 	/*
843 	 * Set up the file type in open_param for the response
844 	 */
845 	op->ftype = SMB_FTYPE_DISK;
846 	sr->smb_fid = of->f_fid;
847 	sr->fid_ofile = of;
848 
849 	smb_node_unlock(node);
850 
851 	if (created)
852 		smb_node_unlock(dnode);
853 
854 	if (op->fqi.last_attr.sa_vattr.va_type == VREG) {
855 		smb_oplock_acquire(node, of, op);
856 		op->dsize = op->fqi.last_attr.sa_vattr.va_size;
857 	} else { /* VDIR or VLNK */
858 		op->op_oplock_level = SMB_OPLOCK_NONE;
859 		op->dsize = 0;
860 	}
861 
862 	smb_node_release(dnode);
863 	SMB_NULL_FQI_NODES(op->fqi);
864 
865 	return (NT_STATUS_SUCCESS);
866 }
867 
868 /*
869  * smb_validate_object_name
870  *
871  * Very basic file name validation.
872  * Directory validation is handed off to smb_validate_dirname.
873  * For filenames, we check for names of the form "AAAn:". Names that
874  * contain three characters, a single digit and a colon (:) are reserved
875  * as DOS device names, i.e. "COM1:".
876  * Stream name validation is handed off to smb_validate_stream_name
877  *
878  * Returns NT status codes.
879  */
880 uint32_t
881 smb_validate_object_name(char *path, unsigned int ftype)
882 {
883 	char *filename;
884 
885 	if (path == 0)
886 		return (0);
887 
888 	if (ftype)
889 		return (smb_validate_dirname(path));
890 
891 	/*
892 	 * Basename with backslashes.
893 	 */
894 	if ((filename = strrchr(path, '\\')) != 0)
895 		++filename;
896 	else
897 		filename = path;
898 
899 	if (strlen(filename) == 5 &&
900 	    mts_isdigit(filename[3]) &&
901 	    filename[4] == ':') {
902 		return (NT_STATUS_OBJECT_NAME_INVALID);
903 	}
904 
905 	if (smb_is_stream_name(path))
906 		return (smb_validate_stream_name(path));
907 
908 	return (0);
909 }
910 
911 /*
912  * smb_preset_delete_on_close
913  *
914  * Set the DeleteOnClose flag on the smb file. When the file is closed,
915  * the flag will be transferred to the smb node, which will commit the
916  * delete operation and inhibit subsequent open requests.
917  *
918  * When DeleteOnClose is set on an smb_node, the common open code will
919  * reject subsequent open requests for the file. Observation of Windows
920  * 2000 indicates that subsequent opens should be allowed (assuming
921  * there would be no sharing violation) until the file is closed using
922  * the fid on which the DeleteOnClose was requested.
923  */
924 void
925 smb_preset_delete_on_close(smb_ofile_t *file)
926 {
927 	mutex_enter(&file->f_mutex);
928 	file->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE;
929 	mutex_exit(&file->f_mutex);
930 }
931