xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_open.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * This module provides the common open functionality to the various
30  * open and create SMB interface functions.
31  */
32 
33 #include <smbsrv/smb_incl.h>
34 #include <smbsrv/smb_fsops.h>
35 #include <smbsrv/mlsvc.h>
36 #include <smbsrv/nterror.h>
37 #include <smbsrv/ntstatus.h>
38 #include <smbsrv/smbinfo.h>
39 #include <sys/fcntl.h>
40 
41 extern uint32_t smb_is_executable(char *path);
42 
43 #define	DENY_READ(share_access) ((share_access & FILE_SHARE_READ) == 0)
44 
45 #define	DENY_WRITE(share_access) ((share_access & FILE_SHARE_WRITE) == 0)
46 
47 #define	DENY_DELETE(share_access) ((share_access & FILE_SHARE_DELETE) == 0)
48 
49 #define	DENY_RW(share_access) \
50 	((share_access & (FILE_SHARE_READ | FILE_SHARE_WRITE)) == 0)
51 
52 #define	DENY_ALL(share_access) (share_access == 0)
53 
54 #define	DENY_NONE(share_access) (share_access == FILE_SHARE_ALL)
55 
56 /*
57  * The default stability mode is to perform the write-through
58  * behaviour requested by the client.
59  */
60 int smb_stable_mode = 0;
61 
62 
63 /*
64  * This macro is used to delete a newly created object
65  * if any error happens after creation of object.
66  */
67 #define	SMB_DEL_NEWOBJ(obj) \
68 	if (created) {							\
69 		if (is_dir)						\
70 			(void) smb_fsop_rmdir(sr, sr->user_cr,		\
71 			    obj.dir_snode, obj.last_comp, 0);		\
72 		else							\
73 			(void) smb_fsop_remove(sr, sr->user_cr,		\
74 			    obj.dir_snode, obj.last_comp, 0);		\
75 	}
76 
77 /*
78  * smb_set_stability
79  *
80  * Set the default stability mode. Normal (mode is zero) means perform
81  * the write-through behaviour requested by the client. Synchronous
82  * (mode is non-zero) means journal everything regardless of the write
83  * through behaviour requested by the client.
84  */
85 void
86 smb_set_stability(int mode)
87 {
88 	smb_stable_mode = mode;
89 }
90 
91 /*
92  * smb_access_generic_to_file
93  *
94  * Search MSDN for IoCreateFile to see following mapping.
95  *
96  * GENERIC_READ		STANDARD_RIGHTS_READ, FILE_READ_DATA,
97  *			FILE_READ_ATTRIBUTES and FILE_READ_EA
98  *
99  * GENERIC_WRITE	STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
100  *               FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
101  *
102  * GENERIC_EXECUTE	STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
103  */
104 uint32_t
105 smb_access_generic_to_file(uint32_t desired_access)
106 {
107 	uint32_t access = 0;
108 
109 	if (desired_access & GENERIC_ALL)
110 		return (FILE_ALL_ACCESS & ~SYNCHRONIZE);
111 
112 	if (desired_access & GENERIC_EXECUTE) {
113 		desired_access &= ~GENERIC_EXECUTE;
114 		access |= (STANDARD_RIGHTS_EXECUTE |
115 		    SYNCHRONIZE | FILE_EXECUTE);
116 	}
117 
118 	if (desired_access & GENERIC_WRITE) {
119 		desired_access &= ~GENERIC_WRITE;
120 		access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE);
121 	}
122 
123 	if (desired_access & GENERIC_READ) {
124 		desired_access &= ~GENERIC_READ;
125 		access |= FILE_GENERIC_READ;
126 	}
127 
128 	return (access | desired_access);
129 }
130 
131 /*
132  * smb_omode_to_amask
133  *
134  * This function converts open modes used by Open and Open AndX
135  * commands to desired access bits used by NT Create AndX command.
136  */
137 uint32_t
138 smb_omode_to_amask(uint32_t desired_access)
139 {
140 	switch (desired_access & SMB_DA_ACCESS_MASK) {
141 	case SMB_DA_ACCESS_READ:
142 		return (FILE_GENERIC_READ);
143 
144 	case SMB_DA_ACCESS_WRITE:
145 		return (FILE_GENERIC_WRITE);
146 
147 	case SMB_DA_ACCESS_READ_WRITE:
148 		return (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
149 
150 	case SMB_DA_ACCESS_EXECUTE:
151 		return (FILE_GENERIC_EXECUTE);
152 	}
153 
154 	/* invalid open mode */
155 	return ((uint32_t)SMB_INVALID_AMASK);
156 }
157 
158 /*
159  * smb_denymode_to_sharemode
160  *
161  * This function converts deny modes used by Open and Open AndX
162  * commands to share access bits used by NT Create AndX command.
163  */
164 uint32_t
165 smb_denymode_to_sharemode(uint32_t desired_access, char *fname)
166 {
167 	switch (desired_access & SMB_DA_SHARE_MASK) {
168 	case SMB_DA_SHARE_COMPATIBILITY:
169 		if (smb_is_executable(fname))
170 			return (FILE_SHARE_READ | FILE_SHARE_WRITE);
171 		else {
172 			if ((desired_access &
173 			    SMB_DA_ACCESS_MASK) == SMB_DA_ACCESS_READ)
174 				return (FILE_SHARE_READ);
175 			else
176 				return (FILE_SHARE_NONE);
177 		}
178 
179 	case SMB_DA_SHARE_EXCLUSIVE:
180 		return (FILE_SHARE_NONE);
181 
182 	case SMB_DA_SHARE_DENY_WRITE:
183 		return (FILE_SHARE_READ);
184 
185 	case SMB_DA_SHARE_DENY_READ:
186 		return (FILE_SHARE_WRITE);
187 
188 	case SMB_DA_SHARE_DENY_NONE:
189 		return (FILE_SHARE_READ | FILE_SHARE_WRITE);
190 	}
191 
192 	/* invalid deny mode */
193 	return ((uint32_t)SMB_INVALID_SHAREMODE);
194 }
195 
196 /*
197  * smb_ofun_to_crdisposition
198  *
199  * This function converts open function values used by Open and Open AndX
200  * commands to create disposition values used by NT Create AndX command.
201  */
202 uint32_t
203 smb_ofun_to_crdisposition(uint16_t  ofun)
204 {
205 	static int ofun_cr_map[3][2] =
206 	{
207 		{ -1,			FILE_CREATE },
208 		{ FILE_OPEN,		FILE_OPEN_IF },
209 		{ FILE_OVERWRITE,	FILE_OVERWRITE_IF }
210 	};
211 
212 	int row = ofun & SMB_OFUN_OPEN_MASK;
213 	int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4;
214 
215 	if (row == 3)
216 		return ((uint32_t)SMB_INVALID_CRDISPOSITION);
217 
218 	return (ofun_cr_map[row][col]);
219 }
220 
221 /*
222  * smb_open_share_check
223  *
224  * check file sharing rules for current open request
225  * against the given existing open.
226  *
227  * Returns NT_STATUS_SHARING_VIOLATION if there is any
228  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
229  */
230 uint32_t
231 smb_open_share_check(struct smb_request *sr,
232     struct smb_node *node,
233     struct smb_ofile *open)
234 {
235 	uint32_t desired_access;
236 	uint32_t share_access;
237 
238 	desired_access = sr->arg.open.desired_access;
239 	share_access   = sr->arg.open.share_access;
240 
241 	/*
242 	 * As far as I can tell share modes are not relevant to
243 	 * directories. The check for exclusive access (Deny RW)
244 	 * remains because I don't know whether or not it was here
245 	 * for a reason.
246 	 */
247 	if (node->attr.sa_vattr.va_type == VDIR) {
248 		if (DENY_RW(open->f_share_access) &&
249 		    (node->n_orig_uid != crgetuid(sr->user_cr))) {
250 			return (NT_STATUS_SHARING_VIOLATION);
251 		}
252 
253 		return (NT_STATUS_SUCCESS);
254 	}
255 
256 	/* if it's just meta data */
257 	if ((open->f_granted_access & FILE_DATA_ALL) == 0)
258 		return (NT_STATUS_SUCCESS);
259 
260 	/*
261 	 * Check requested share access against the
262 	 * open granted (desired) access
263 	 */
264 	if (DENY_DELETE(share_access) && (open->f_granted_access & DELETE))
265 		return (NT_STATUS_SHARING_VIOLATION);
266 
267 	if (DENY_READ(share_access) &&
268 	    (open->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE)))
269 		return (NT_STATUS_SHARING_VIOLATION);
270 
271 	if (DENY_WRITE(share_access) &&
272 	    (open->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
273 		return (NT_STATUS_SHARING_VIOLATION);
274 
275 	/* check requested desired access against the open share access */
276 	if (DENY_DELETE(open->f_share_access) && (desired_access & DELETE))
277 		return (NT_STATUS_SHARING_VIOLATION);
278 
279 	if (DENY_READ(open->f_share_access) &&
280 	    (desired_access & (FILE_READ_DATA | FILE_EXECUTE)))
281 		return (NT_STATUS_SHARING_VIOLATION);
282 
283 	if (DENY_WRITE(open->f_share_access) &&
284 	    (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
285 		return (NT_STATUS_SHARING_VIOLATION);
286 
287 	return (NT_STATUS_SUCCESS);
288 }
289 
290 /*
291  * smb_file_share_check
292  *
293  * check file sharing rules for current open request
294  * against all existing opens for a file.
295  *
296  * Returns NT_STATUS_SHARING_VIOLATION if there is any
297  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
298  */
299 uint32_t
300 smb_file_share_check(struct smb_request *sr, struct smb_node *node)
301 {
302 	struct smb_ofile *open;
303 	uint32_t status;
304 
305 	if (node == 0 || node->n_refcnt <= 1)
306 		return (NT_STATUS_SUCCESS);
307 
308 	/* if it's just meta data */
309 	if ((sr->arg.open.desired_access & FILE_DATA_ALL) == 0)
310 		return (NT_STATUS_SUCCESS);
311 
312 	smb_llist_enter(&node->n_ofile_list, RW_READER);
313 	open = smb_llist_head(&node->n_ofile_list);
314 	while (open) {
315 		status = smb_open_share_check(sr, node, open);
316 		if (status == NT_STATUS_SHARING_VIOLATION) {
317 			smb_llist_exit(&node->n_ofile_list);
318 			return (status);
319 		}
320 		open = smb_llist_next(&node->n_ofile_list, open);
321 	}
322 	smb_llist_exit(&node->n_ofile_list);
323 
324 	return (NT_STATUS_SUCCESS);
325 }
326 
327 /*
328  * smb_amask_to_amode
329  * Converts specific read/write access rights of access mask to access
330  * mode flags.
331  */
332 int
333 smb_amask_to_amode(unsigned long amask)
334 {
335 	if ((amask & FILE_READ_DATA) &&
336 	    (amask & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
337 		return (O_RDWR);
338 
339 	if (amask & (FILE_WRITE_DATA | FILE_APPEND_DATA))
340 		return (O_WRONLY);
341 
342 	return (O_RDONLY);
343 }
344 
345 /*
346  * smb_open_subr
347  *
348  * Notes on write-through behaviour. It looks like pre-LM0.12 versions
349  * of the protocol specify the write-through mode when a file is opened,
350  * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose,
351  * SmbWriteAndUnlock) don't need to contain a write-through flag.
352  *
353  * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate)
354  * don't indicate which write-through mode to use. Instead the write
355  * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call
356  * basis.
357  *
358  * We don't care which open call was used to get us here, we just need
359  * to ensure that the write-through mode flag is copied from the open
360  * parameters to the node. We test the omode write-through flag in all
361  * write functions.
362  *
363  * This function will return NT status codes but it also raises errors,
364  * in which case it won't return to the caller. Be careful how you
365  * handle things in here.
366  */
367 uint32_t
368 smb_open_subr(struct smb_request *sr)
369 {
370 	int			created = 0;
371 	struct smb_node		*node = 0;
372 	struct smb_node		*dnode = 0;
373 	struct smb_node		*cur_node;
374 	struct open_param	*op = &sr->arg.open;
375 	int			rc;
376 	struct smb_ofile	*of;
377 	smb_attr_t		new_attr;
378 	int			pathlen;
379 	int			max_requested = 0;
380 	uint32_t		max_allowed;
381 	unsigned int		granted_oplock;
382 	uint32_t		status = NT_STATUS_SUCCESS;
383 	int			is_dir;
384 	smb_error_t		err;
385 	int			is_stream;
386 	int			lookup_flags = SMB_FOLLOW_LINKS;
387 	uint32_t		daccess;
388 
389 	is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
390 
391 	if (is_dir) {
392 		/*
393 		 * The file being created or opened is a directory file.
394 		 * With this flag, the Disposition parameter must be set to
395 		 * one of FILE_CREATE, FILE_OPEN, or FILE_OPEN_IF
396 		 */
397 		if ((op->create_disposition != FILE_CREATE) &&
398 		    (op->create_disposition != FILE_OPEN_IF) &&
399 		    (op->create_disposition != FILE_OPEN)) {
400 			smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER,
401 			    ERRDOS, ERROR_INVALID_ACCESS);
402 			/* invalid open mode */
403 			/* NOTREACHED */
404 		}
405 	}
406 
407 	if (op->desired_access & MAXIMUM_ALLOWED) {
408 		max_requested = 1;
409 		op->desired_access &= ~MAXIMUM_ALLOWED;
410 	}
411 	op->desired_access = smb_access_generic_to_file(op->desired_access);
412 
413 	if (sr->session->s_file_cnt >= SMB_SESSION_OFILE_MAX) {
414 
415 		ASSERT(sr->uid_user);
416 		cmn_err(CE_NOTE, "smbd[%s\\%s]: %s", sr->uid_user->u_domain,
417 		    sr->uid_user->u_name,
418 		    xlate_nt_status(NT_STATUS_TOO_MANY_OPENED_FILES));
419 
420 		smbsr_raise_cifs_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
421 		    ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
422 		/* NOTREACHED */
423 	}
424 
425 	/* This must be NULL at this point */
426 	sr->fid_ofile = NULL;
427 
428 	op->devstate = 0;
429 
430 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
431 	case STYPE_DISKTREE:
432 		break;
433 
434 	case STYPE_IPC:
435 		/*
436 		 * No further processing for IPC, we need to either
437 		 * raise an exception or return success here.
438 		 */
439 		if ((rc = smb_rpc_open(sr)) != 0) {
440 			smbsr_raise_nt_error(sr, rc);
441 			/* NOTREACHED */
442 		} else {
443 			return (NT_STATUS_SUCCESS);
444 		}
445 		break;
446 
447 	default:
448 		smbsr_raise_error(sr, ERRSRV, ERRinvdevice);
449 		/* NOTREACHED */
450 		break;
451 	}
452 
453 	if ((pathlen = strlen(op->fqi.path)) >= MAXPATHLEN) {
454 		smbsr_raise_error(sr, ERRSRV, ERRfilespecs);
455 		/* NOTREACHED */
456 	}
457 
458 	/*
459 	 * Some clients pass null file names; NT interprets this as "\".
460 	 */
461 	if (pathlen == 0) {
462 		op->fqi.path = "\\";
463 		pathlen = 1;
464 	}
465 
466 	op->fqi.srch_attr = op->fqi.srch_attr;
467 
468 	if ((status = smb_validate_object_name(op->fqi.path, is_dir)) != 0) {
469 		smbsr_raise_cifs_error(sr, status, ERRDOS, ERROR_INVALID_NAME);
470 		/* NOTREACHED */
471 	}
472 
473 	cur_node = op->fqi.dir_snode ?
474 	    op->fqi.dir_snode : sr->tid_tree->t_snode;
475 
476 	if (rc = smb_pathname_reduce(sr, sr->user_cr, op->fqi.path,
477 	    sr->tid_tree->t_snode, cur_node, &op->fqi.dir_snode,
478 	    op->fqi.last_comp)) {
479 		smbsr_raise_errno(sr, rc);
480 		/* NOTREACHED */
481 	}
482 
483 	/*
484 	 * If the access mask has only DELETE set (ignore
485 	 * FILE_READ_ATTRIBUTES), then assume that this
486 	 * is a request to delete the link (if a link)
487 	 * and do not follow links.  Otherwise, follow
488 	 * the link to the target.
489 	 */
490 
491 	daccess = op->desired_access & ~FILE_READ_ATTRIBUTES;
492 
493 	if (daccess == DELETE)
494 		lookup_flags &= ~SMB_FOLLOW_LINKS;
495 
496 	rc = smb_fsop_lookup_name(sr, kcred, lookup_flags,
497 	    sr->tid_tree->t_snode, op->fqi.dir_snode, op->fqi.last_comp,
498 	    &op->fqi.last_snode, &op->fqi.last_attr);
499 
500 	if (rc == 0) {
501 		op->fqi.last_comp_was_found = 1;
502 		(void) strcpy(op->fqi.last_comp_od,
503 		    op->fqi.last_snode->od_name);
504 	} else if (rc == ENOENT) {
505 		op->fqi.last_comp_was_found = 0;
506 		op->fqi.last_snode = NULL;
507 		rc = 0;
508 	} else {
509 		smb_node_release(op->fqi.dir_snode);
510 		SMB_NULL_FQI_NODES(op->fqi);
511 		smbsr_raise_errno(sr, rc);
512 		/* NOTREACHED */
513 	}
514 
515 	if (op->fqi.last_comp_was_found) {
516 		node = op->fqi.last_snode;
517 		dnode = op->fqi.dir_snode;
518 
519 		/*
520 		 * Reject this request if the target is a directory
521 		 * and the client has specified that it must not be
522 		 * a directory (required by Lotus Notes).
523 		 */
524 		if ((op->create_options & FILE_NON_DIRECTORY_FILE) &&
525 		    (op->fqi.last_attr.sa_vattr.va_type == VDIR)) {
526 			smb_node_release(node);
527 			smb_node_release(dnode);
528 			SMB_NULL_FQI_NODES(op->fqi);
529 			smbsr_raise_cifs_error(sr,
530 			    NT_STATUS_FILE_IS_A_DIRECTORY,
531 			    ERRDOS, ERROR_ACCESS_DENIED);
532 			/* NOTREACHED */
533 		}
534 
535 		if (op->fqi.last_attr.sa_vattr.va_type == VDIR) {
536 			if ((sr->smb_com == SMB_COM_OPEN_ANDX) ||
537 			    (sr->smb_com == SMB_COM_OPEN)) {
538 				/*
539 				 * Directories cannot be opened
540 				 * with the above commands
541 				 */
542 				smb_node_release(node);
543 				smb_node_release(dnode);
544 				SMB_NULL_FQI_NODES(op->fqi);
545 				smbsr_raise_cifs_error(sr,
546 				    NT_STATUS_FILE_IS_A_DIRECTORY,
547 				    ERRDOS, ERROR_ACCESS_DENIED);
548 				/* NOTREACHED */
549 			}
550 		} else if (op->my_flags & MYF_MUST_BE_DIRECTORY) {
551 			smb_node_release(node);
552 			smb_node_release(dnode);
553 			SMB_NULL_FQI_NODES(op->fqi);
554 			smbsr_raise_cifs_error(sr, NT_STATUS_NOT_A_DIRECTORY,
555 			    ERRDOS, ERROR_DIRECTORY);
556 			/* NOTREACHED */
557 		}
558 
559 		/*
560 		 * No more open should be accepted when "Delete on close"
561 		 * flag is set.
562 		 */
563 		if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
564 			smb_node_release(node);
565 			smb_node_release(dnode);
566 			SMB_NULL_FQI_NODES(op->fqi);
567 			smbsr_raise_cifs_error(sr, NT_STATUS_DELETE_PENDING,
568 			    ERRDOS, ERROR_ACCESS_DENIED);
569 			/* NOTREACHED */
570 		}
571 
572 		/*
573 		 * Specified file already exists so the operation should fail.
574 		 */
575 		if (op->create_disposition == FILE_CREATE) {
576 			smb_node_release(node);
577 			smb_node_release(dnode);
578 			SMB_NULL_FQI_NODES(op->fqi);
579 			smbsr_raise_cifs_error(sr,
580 			    NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS,
581 			    ERROR_ALREADY_EXISTS);
582 			/* NOTREACHED */
583 		}
584 
585 		/*
586 		 * Windows seems to check read-only access before file
587 		 * sharing check.
588 		 */
589 		if (NODE_IS_READONLY(node)) {
590 			/* Files data only */
591 			if (node->attr.sa_vattr.va_type != VDIR) {
592 				if (op->desired_access & (FILE_WRITE_DATA |
593 				    FILE_APPEND_DATA)) {
594 					smb_node_release(node);
595 					smb_node_release(dnode);
596 					SMB_NULL_FQI_NODES(op->fqi);
597 					smbsr_raise_error(sr, ERRDOS,
598 					    ERRnoaccess);
599 					/* NOTREACHED */
600 				}
601 			}
602 		}
603 
604 		status = smb_file_share_check(sr, node);
605 		if (status == NT_STATUS_SHARING_VIOLATION) {
606 			smb_node_release(node);
607 			smb_node_release(dnode);
608 			SMB_NULL_FQI_NODES(op->fqi);
609 			return (status);
610 		}
611 
612 		status = smb_fsop_access(sr, sr->user_cr, node,
613 		    op->desired_access);
614 
615 		if (status != NT_STATUS_SUCCESS) {
616 			smb_node_release(node);
617 			smb_node_release(dnode);
618 			SMB_NULL_FQI_NODES(op->fqi);
619 			if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
620 				smbsr_raise_cifs_error(sr,
621 				    status,
622 				    ERRDOS,
623 				    ERROR_PRIVILEGE_NOT_HELD);
624 			} else {
625 				smbsr_raise_cifs_error(sr,
626 				    NT_STATUS_ACCESS_DENIED,
627 				    ERRDOS,
628 				    ERROR_ACCESS_DENIED);
629 			}
630 		}
631 
632 		/*
633 		 * Break the oplock before share checks. If another client
634 		 * has the file open, this will force a flush or close,
635 		 * which may affect the outcome of any share checking.
636 		 */
637 		if (OPLOCKS_IN_FORCE(node)) {
638 			status = smb_break_oplock(sr, node);
639 
640 			if (status != NT_STATUS_SUCCESS) {
641 				smb_node_release(node);
642 				smb_node_release(dnode);
643 				SMB_NULL_FQI_NODES(op->fqi);
644 				smbsr_raise_cifs_error(sr, status,
645 				    ERRDOS, ERROR_VC_DISCONNECTED);
646 				/* NOTREACHED */
647 			}
648 		}
649 
650 		switch (op->create_disposition) {
651 		case FILE_SUPERSEDE:
652 		case FILE_OVERWRITE_IF:
653 		case FILE_OVERWRITE:
654 			if (node->attr.sa_vattr.va_type == VDIR) {
655 				smb_node_release(node);
656 				smb_node_release(dnode);
657 				SMB_NULL_FQI_NODES(op->fqi);
658 				smbsr_raise_cifs_error(sr,
659 				    NT_STATUS_ACCESS_DENIED, ERRDOS,
660 				    ERROR_ACCESS_DENIED);
661 				/* NOTREACHED */
662 			}
663 
664 			if (node->attr.sa_vattr.va_size != op->dsize) {
665 				node->flags &= ~NODE_FLAGS_SET_SIZE;
666 				new_attr.sa_vattr.va_size = op->dsize;
667 				new_attr.sa_mask = SMB_AT_SIZE;
668 				if ((rc = smb_fsop_setattr(sr, sr->user_cr,
669 				    (&op->fqi)->last_snode, &new_attr,
670 				    &op->fqi.last_attr)) != 0) {
671 					smb_node_release(node);
672 					smb_node_release(dnode);
673 					SMB_NULL_FQI_NODES(op->fqi);
674 					smbsr_raise_errno(sr, rc);
675 					/* NOTREACHED */
676 				}
677 
678 			}
679 
680 			/*
681 			 * If file is being replaced,
682 			 * we should remove existing streams
683 			 */
684 			if (SMB_IS_STREAM(node) == 0)
685 				(void) smb_fsop_remove_streams(sr, sr->user_cr,
686 				    node);
687 
688 			op->action_taken = SMB_OACT_TRUNCATED;
689 			break;
690 
691 		default:
692 			/*
693 			 * FILE_OPEN or FILE_OPEN_IF.
694 			 */
695 			op->action_taken = SMB_OACT_OPENED;
696 			break;
697 		}
698 	} else {
699 
700 		/* Last component was not found. */
701 		dnode = op->fqi.dir_snode;
702 
703 		if ((op->create_disposition == FILE_OPEN) ||
704 		    (op->create_disposition == FILE_OVERWRITE)) {
705 			smb_node_release(dnode);
706 			SMB_NULL_FQI_NODES(op->fqi);
707 
708 			is_stream = smb_stream_parse_name(op->fqi.path,
709 			    NULL, NULL);
710 			/*
711 			 * The requested file not found so the operation should
712 			 * fail with these two dispositions
713 			 */
714 			if (is_stream)
715 				smbsr_raise_cifs_error(sr,
716 				    NT_STATUS_OBJECT_NAME_NOT_FOUND,
717 				    ERRDOS, ERROR_FILE_NOT_FOUND);
718 			else
719 				smbsr_raise_error(sr, ERRDOS, ERRbadfile);
720 			/* NOTREACHED */
721 		}
722 
723 		/*
724 		 * lock the parent dir node in case another create
725 		 * request to the same parent directory comes in.
726 		 */
727 		smb_rwx_rwenter(&dnode->n_lock, RW_WRITER);
728 
729 		bzero(&new_attr, sizeof (new_attr));
730 		if (is_dir == 0) {
731 			new_attr.sa_vattr.va_type = VREG;
732 			new_attr.sa_vattr.va_mode = 0666;
733 			new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE;
734 			rc = smb_fsop_create(sr, sr->user_cr, dnode,
735 			    op->fqi.last_comp, &new_attr,
736 			    &op->fqi.last_snode, &op->fqi.last_attr);
737 			if (rc != 0) {
738 				smb_rwx_rwexit(&dnode->n_lock);
739 				smb_node_release(dnode);
740 				SMB_NULL_FQI_NODES(op->fqi);
741 				smbsr_raise_errno(sr, rc);
742 				/* NOTREACHED */
743 			}
744 
745 			if (op->dsize) {
746 				new_attr.sa_vattr.va_size = op->dsize;
747 				new_attr.sa_mask = SMB_AT_SIZE;
748 				rc = smb_fsop_setattr(sr, sr->user_cr,
749 				    op->fqi.last_snode, &new_attr,
750 				    &op->fqi.last_attr);
751 				if (rc != 0) {
752 					smb_node_release(op->fqi.last_snode);
753 					(void) smb_fsop_remove(sr, sr->user_cr,
754 					    dnode, op->fqi.last_comp, 0);
755 					smb_rwx_rwexit(&dnode->n_lock);
756 					smb_node_release(dnode);
757 					SMB_NULL_FQI_NODES(op->fqi);
758 					smbsr_raise_errno(sr, rc);
759 					/* NOTREACHED */
760 				}
761 			}
762 
763 		} else {
764 			op->dattr |= SMB_FA_DIRECTORY;
765 			new_attr.sa_vattr.va_type = VDIR;
766 			new_attr.sa_vattr.va_mode = 0777;
767 			new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE;
768 			rc = smb_fsop_mkdir(sr, sr->user_cr, dnode,
769 			    op->fqi.last_comp, &new_attr,
770 			    &op->fqi.last_snode, &op->fqi.last_attr);
771 			if (rc != 0) {
772 				smb_rwx_rwexit(&dnode->n_lock);
773 				smb_node_release(dnode);
774 				SMB_NULL_FQI_NODES(op->fqi);
775 				smbsr_raise_errno(sr, rc);
776 				/* NOTREACHED */
777 			}
778 		}
779 
780 		created = 1;
781 		op->action_taken = SMB_OACT_CREATED;
782 	}
783 
784 	if (node == 0) {
785 		node = op->fqi.last_snode;
786 	}
787 
788 	if ((op->fqi.last_attr.sa_vattr.va_type != VREG) &&
789 	    (op->fqi.last_attr.sa_vattr.va_type != VDIR) &&
790 	    (op->fqi.last_attr.sa_vattr.va_type != VLNK)) {
791 		/* not allowed to do this */
792 		SMB_DEL_NEWOBJ(op->fqi);
793 		smb_node_release(node);
794 		if (created)
795 			smb_rwx_rwexit(&dnode->n_lock);
796 		smb_node_release(dnode);
797 		SMB_NULL_FQI_NODES(op->fqi);
798 		smbsr_raise_error(sr, ERRDOS, ERRnoaccess);
799 		/* NOTREACHED */
800 	}
801 
802 	if (max_requested) {
803 		smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
804 		op->desired_access |= max_allowed;
805 	}
806 
807 	/*
808 	 * smb_ofile_open() will copy node to of->node.  Hence
809 	 * the hold on node (i.e. op->fqi.last_snode) will be "transferred"
810 	 * to the "of" structure.
811 	 */
812 
813 	of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op->desired_access,
814 	    op->create_options, op->share_access, SMB_FTYPE_DISK, NULL, 0,
815 	    &err);
816 
817 	if (of == NULL) {
818 		SMB_DEL_NEWOBJ(op->fqi);
819 		smb_node_release(node);
820 		if (created)
821 			smb_rwx_rwexit(&dnode->n_lock);
822 		smb_node_release(dnode);
823 		SMB_NULL_FQI_NODES(op->fqi);
824 		smbsr_raise_cifs_error(sr, err.status, err.errcls, err.errcode);
825 		/* NOTREACHED */
826 	}
827 
828 	/*
829 	 * Propagate the write-through mode from the open params
830 	 * to the node: see the notes in the function header.
831 	 *
832 	 * IR #102318 Mirroring may force synchronous
833 	 * writes regardless of what we specify here.
834 	 */
835 	if (smb_stable_mode || (op->create_options & FILE_WRITE_THROUGH))
836 		node->flags |= NODE_FLAGS_WRITE_THROUGH;
837 
838 	op->fileid = op->fqi.last_attr.sa_vattr.va_nodeid;
839 
840 	if (op->fqi.last_attr.sa_vattr.va_type == VDIR) {
841 		/* We don't oplock directories */
842 		op->my_flags &= ~MYF_OPLOCK_MASK;
843 		op->dsize = 0;
844 	} else {
845 		status = smb_acquire_oplock(sr, of, op->my_flags,
846 		    &granted_oplock);
847 		op->my_flags &= ~MYF_OPLOCK_MASK;
848 
849 		if (status != NT_STATUS_SUCCESS) {
850 			(void) smb_ofile_close(of, 0);
851 			smb_ofile_release(of);
852 			if (created)
853 				smb_rwx_rwexit(&dnode->n_lock);
854 			smb_node_release(dnode);
855 			SMB_NULL_FQI_NODES(op->fqi);
856 
857 			smbsr_raise_cifs_error(sr, status,
858 			    ERRDOS, ERROR_SHARING_VIOLATION);
859 			/* NOTREACHED */
860 		}
861 
862 		op->my_flags |= granted_oplock;
863 		op->dsize = op->fqi.last_attr.sa_vattr.va_size;
864 	}
865 
866 	if (created) {
867 		node->flags |= NODE_FLAGS_CREATED;
868 		/*
869 		 * Clients may set the DOS readonly bit on create but they
870 		 * expect subsequent write operations on the open fid to
871 		 * succeed.  Thus the DOS readonly bit is not set until the
872 		 * file is closed.  The NODE_CREATED_READONLY flag will
873 		 * inhibit other attempts to open the file with write access
874 		 * and act as the indicator to set the DOS readonly bit on
875 		 * close.
876 		 */
877 		if (op->dattr & SMB_FA_READONLY) {
878 			node->flags |= NODE_CREATED_READONLY;
879 			op->dattr &= ~SMB_FA_READONLY;
880 		}
881 		smb_node_set_dosattr(node, op->dattr | SMB_FA_ARCHIVE);
882 		if (op->utime.tv_sec == 0 || op->utime.tv_sec == 0xffffffff)
883 			(void) microtime(&op->utime);
884 		smb_node_set_time(node, NULL, &op->utime, 0, 0, SMB_AT_MTIME);
885 		(void) smb_sync_fsattr(sr, sr->user_cr, node);
886 	} else {
887 		/*
888 		 * If we reach here, it means that file already exists
889 		 * and if create disposition is one of: FILE_SUPERSEDE,
890 		 * FILE_OVERWRITE_IF, or FILE_OVERWRITE it
891 		 * means that client wants to overwrite (or truncate)
892 		 * the existing file. So we should overwrite the dos
893 		 * attributes of destination file with the dos attributes
894 		 * of source file.
895 		 */
896 
897 		switch (op->create_disposition) {
898 		case FILE_SUPERSEDE:
899 		case FILE_OVERWRITE_IF:
900 		case FILE_OVERWRITE:
901 			smb_node_set_dosattr(node,
902 			    op->dattr | SMB_FA_ARCHIVE);
903 			(void) smb_sync_fsattr(sr, sr->user_cr, node);
904 		}
905 		op->utime = *smb_node_get_crtime(node);
906 		op->dattr = smb_node_get_dosattr(node);
907 	}
908 
909 	/*
910 	 * Set up the file type in open_param for the response
911 	 */
912 	op->ftype = SMB_FTYPE_DISK;
913 	sr->smb_fid = of->f_fid;
914 	sr->fid_ofile = of;
915 
916 	if (created) {
917 		smb_rwx_rwexit(&dnode->n_lock);
918 	}
919 	smb_node_release(dnode);
920 	SMB_NULL_FQI_NODES(op->fqi);
921 
922 	return (NT_STATUS_SUCCESS);
923 }
924 
925 /*
926  * smb_validate_object_name
927  *
928  * Very basic file name validation. Directory validation is handed off
929  * to smb_validate_dirname. For filenames, we check for names of the
930  * form "AAAn:". Names that contain three characters, a single digit
931  * and a colon (:) are reserved as DOS device names, i.e. "COM1:".
932  *
933  * Returns NT status codes.
934  */
935 uint32_t
936 smb_validate_object_name(char *path, unsigned int ftype)
937 {
938 	char *filename;
939 
940 	if (path == 0)
941 		return (0);
942 
943 	if (ftype)
944 		return (smb_validate_dirname(path));
945 
946 	/*
947 	 * Basename with backslashes.
948 	 */
949 	if ((filename = strrchr(path, '\\')) != 0)
950 		++filename;
951 	else
952 		filename = path;
953 
954 	if (strlen(filename) == 5 &&
955 	    mts_isdigit(filename[3]) &&
956 	    filename[4] == ':') {
957 		return (NT_STATUS_OBJECT_NAME_INVALID);
958 	}
959 
960 	return (0);
961 }
962 
963 /*
964  * smb_preset_delete_on_close
965  *
966  * Set the DeleteOnClose flag on the smb file. When the file is closed,
967  * the flag will be transferred to the smb node, which will commit the
968  * delete operation and inhibit subsequent open requests.
969  *
970  * When DeleteOnClose is set on an smb_node, the common open code will
971  * reject subsequent open requests for the file. Observation of Windows
972  * 2000 indicates that subsequent opens should be allowed (assuming
973  * there would be no sharing violation) until the file is closed using
974  * the fid on which the DeleteOnClose was requested.
975  */
976 void
977 smb_preset_delete_on_close(smb_ofile_t *file)
978 {
979 	mutex_enter(&file->f_mutex);
980 	file->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE;
981 	mutex_exit(&file->f_mutex);
982 }
983