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