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