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