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