1da6c28aamw/*
2da6c28aamw * CDDL HEADER START
3da6c28aamw *
4da6c28aamw * The contents of this file are subject to the terms of the
5da6c28aamw * Common Development and Distribution License (the "License").
6da6c28aamw * You may not use this file except in compliance with the License.
7da6c28aamw *
8da6c28aamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aamw * or http://www.opensolaris.org/os/licensing.
10da6c28aamw * See the License for the specific language governing permissions
11da6c28aamw * and limitations under the License.
12da6c28aamw *
13da6c28aamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aamw *
19da6c28aamw * CDDL HEADER END
20da6c28aamw */
21da6c28aamw/*
22148c5f4Alan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23245d133Matt Barden * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
24da6c28aamw */
25da6c28aamw
26da6c28aamw#include <sys/sid.h>
27dc20a30as#include <sys/nbmlock.h>
28da6c28aamw#include <smbsrv/smb_fsops.h>
2955bf511as#include <smbsrv/smb_kproto.h>
30da6c28aamw#include <acl/acl_common.h>
31dc20a30as#include <sys/fcntl.h>
3255f0a24Gordon Ross#include <sys/filio.h>
33dc20a30as#include <sys/flock.h>
34dc20a30as#include <fs/fs_subr.h>
35da6c28aamw
36faa1795jbextern caller_context_t smb_ct;
37faa1795jb
38eb1d736afshin salek ardakani - Sun Microsystems - Irvine United Statesstatic int smb_fsop_create_stream(smb_request_t *, cred_t *, smb_node_t *,
39037cac0joyce mcintosh    char *, char *, int, smb_attr_t *, smb_node_t **);
40eb1d736afshin salek ardakani - Sun Microsystems - Irvine United States
41eb1d736afshin salek ardakani - Sun Microsystems - Irvine United Statesstatic int smb_fsop_create_file(smb_request_t *, cred_t *, smb_node_t *,
42037cac0joyce mcintosh    char *, int, smb_attr_t *, smb_node_t **);
43eb1d736afshin salek ardakani - Sun Microsystems - Irvine United States
44b819ceaGordon Ross#ifdef	_KERNEL
45eb1d736afshin salek ardakani - Sun Microsystems - Irvine United Statesstatic int smb_fsop_create_with_sd(smb_request_t *, cred_t *, smb_node_t *,
46037cac0joyce mcintosh    char *, smb_attr_t *, smb_node_t **, smb_fssd_t *);
47eb1d736afshin salek ardakani - Sun Microsystems - Irvine United Statesstatic int smb_fsop_sdinherit(smb_request_t *, smb_node_t *, smb_fssd_t *);
48b819ceaGordon Ross#endif	/* _KERNEL */
49da6c28aamw
50da6c28aamw/*
51da6c28aamw * The smb_fsop_* functions have knowledge of CIFS semantics.
52da6c28aamw *
53da6c28aamw * The smb_vop_* functions have minimal knowledge of CIFS semantics and
54da6c28aamw * serve as an interface to the VFS layer.
55da6c28aamw *
56da6c28aamw * Hence, smb_request_t and smb_node_t structures should not be passed
57da6c28aamw * from the smb_fsop_* layer to the smb_vop_* layer.
58da6c28aamw *
59da6c28aamw * In general, CIFS service code should only ever call smb_fsop_*
60da6c28aamw * functions directly, and never smb_vop_* functions directly.
61da6c28aamw *
62da6c28aamw * smb_fsop_* functions should call smb_vop_* functions where possible, instead
63da6c28aamw * of their smb_fsop_* counterparts.  However, there are times when
64da6c28aamw * this cannot be avoided.
65da6c28aamw */
66da6c28aamw
67da6c28aamw/*
68da6c28aamw * Note: Stream names cannot be mangled.
69da6c28aamw */
70da6c28aamw
718c10a86as/*
728c10a86as * smb_fsop_amask_to_omode
738c10a86as *
748c10a86as * Convert the access mask to the open mode (for use
758c10a86as * with the VOP_OPEN call).
768c10a86as *
778c10a86as * Note that opening a file for attribute only access
788c10a86as * will also translate into an FREAD or FWRITE open mode
798c10a86as * (i.e., it's not just for data).
808c10a86as *
818c10a86as * This is needed so that opens are tracked appropriately
828c10a86as * for oplock processing.
838c10a86as */
848c10a86as
85da6c28aamwint
868c10a86assmb_fsop_amask_to_omode(uint32_t access)
87da6c28aamw{
888c10a86as	int mode = 0;
898c10a86as
908c10a86as	if (access & (FILE_READ_DATA | FILE_EXECUTE |
918c10a86as	    FILE_READ_ATTRIBUTES | FILE_READ_EA))
928c10a86as		mode |= FREAD;
93da6c28aamw
948c10a86as	if (access & (FILE_WRITE_DATA | FILE_APPEND_DATA |
958c10a86as	    FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA))
968c10a86as		mode |= FWRITE;
978c10a86as
988c10a86as	if (access & FILE_APPEND_DATA)
998c10a86as		mode |= FAPPEND;
1008c10a86as
1018c10a86as	return (mode);
1028c10a86as}
103da6c28aamw
1048c10a86asint
1058c10a86assmb_fsop_open(smb_node_t *node, int mode, cred_t *cred)
1068c10a86as{
107da6c28aamw	/*
1088c10a86as	 * Assuming that the same vnode is returned as we had before.
1098c10a86as	 * (I.e., with certain types of files or file systems, a
1108c10a86as	 * different vnode might be returned by VOP_OPEN)
111da6c28aamw	 */
1128c10a86as	return (smb_vop_open(&node->vp, mode, cred));
113da6c28aamw}
114da6c28aamw
115c8ec8eejose borregovoid
1168c10a86assmb_fsop_close(smb_node_t *node, int mode, cred_t *cred)
117da6c28aamw{
118c8ec8eejose borrego	smb_vop_close(node->vp, mode, cred);
119da6c28aamw}
120da6c28aamw
121b819ceaGordon Ross#ifdef	_KERNEL
122da6c28aamwstatic int
123eb1d736afshin salek ardakani - Sun Microsystems - Irvine United Statessmb_fsop_create_with_sd(smb_request_t *sr, cred_t *cr,
124eb1d736afshin salek ardakani - Sun Microsystems - Irvine United States    smb_node_t *dnode, char *name,
125037cac0joyce mcintosh    smb_attr_t *attr, smb_node_t **ret_snode, smb_fssd_t *fs_sd)
126da6c28aamw{
127da6c28aamw	vsecattr_t *vsap;
128da6c28aamw	vsecattr_t vsecattr;
129da6c28aamw	smb_attr_t set_attr;
1308622ec4Gordon Ross	acl_t *acl, *dacl, *sacl;
131da6c28aamw	vnode_t *vp;
1328622ec4Gordon Ross	cred_t *kcr = zone_kcred();
133da6c28aamw	int aclbsize = 0;	/* size of acl list in bytes */
134da6c28aamw	int flags = 0;
135da6c28aamw	int rc;
1362c1b14ejose borrego	boolean_t is_dir;
137da6c28aamw
138da6c28aamw	ASSERT(fs_sd);
139da6c28aamw
140c8ec8eejose borrego	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
141da6c28aamw		flags = SMB_IGNORE_CASE;
1428b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	if (SMB_TREE_SUPPORTS_CATIA(sr))
1438b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		flags |= SMB_CATIA;
144da6c28aamw
145da6c28aamw	ASSERT(cr);
146da6c28aamw
147da6c28aamw	is_dir = ((fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) != 0);
148da6c28aamw
149c8ec8eejose borrego	if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_ACLONCREATE)) {
150da6c28aamw		if (fs_sd->sd_secinfo & SMB_ACL_SECINFO) {
151da6c28aamw			dacl = fs_sd->sd_zdacl;
152da6c28aamw			sacl = fs_sd->sd_zsacl;
153da6c28aamw			ASSERT(dacl || sacl);
154da6c28aamw			if (dacl && sacl) {
15555bf511as				acl = smb_fsacl_merge(dacl, sacl);
156da6c28aamw			} else if (dacl) {
157da6c28aamw				acl = dacl;
158da6c28aamw			} else {
159da6c28aamw				acl = sacl;
160da6c28aamw			}
161da6c28aamw
16255bf511as			rc = smb_fsacl_to_vsa(acl, &vsecattr, &aclbsize);
163da6c28aamw
164da6c28aamw			if (dacl && sacl)
165da6c28aamw				acl_free(acl);
166da6c28aamw
1672c1b14ejose borrego			if (rc != 0)
168da6c28aamw				return (rc);
169da6c28aamw
170da6c28aamw			vsap = &vsecattr;
1712c1b14ejose borrego		} else {
172da6c28aamw			vsap = NULL;
1732c1b14ejose borrego		}
174da6c28aamw
175743a77eAlan Wright		/* The tree ACEs may prevent a create */
176743a77eAlan Wright		rc = EACCES;
177da6c28aamw		if (is_dir) {
178743a77eAlan Wright			if (SMB_TREE_HAS_ACCESS(sr, ACE_ADD_SUBDIRECTORY) != 0)
179eb1d736afshin salek ardakani - Sun Microsystems - Irvine United States				rc = smb_vop_mkdir(dnode->vp, name, attr,
180743a77eAlan Wright				    &vp, flags, cr, vsap);
181da6c28aamw		} else {
182743a77eAlan Wright			if (SMB_TREE_HAS_ACCESS(sr, ACE_ADD_FILE) != 0)
183eb1d736afshin salek ardakani - Sun Microsystems - Irvine United States				rc = smb_vop_create(dnode->vp, name, attr,
184743a77eAlan Wright				    &vp, flags, cr, vsap);
185da6c28aamw		}
186da6c28aamw
187da6c28aamw		if (vsap != NULL)
188da6c28aamw			kmem_free(vsap->vsa_aclentp, aclbsize);
189da6c28aamw
190da6c28aamw		if (rc != 0)
191da6c28aamw			return (rc);
192da6c28aamw
193da6c28aamw		set_attr.sa_mask = 0;
194da6c28aamw
195da6c28aamw		/*
196da6c28aamw		 * Ideally we should be able to specify the owner and owning
197da6c28aamw		 * group at create time along with the ACL. Since we cannot
198da6c28aamw		 * do that right now, kcred is passed to smb_vop_setattr so it
199da6c28aamw		 * doesn't fail due to lack of permission.
200da6c28aamw		 */
201da6c28aamw		if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
202da6c28aamw			set_attr.sa_vattr.va_uid = fs_sd->sd_uid;
203da6c28aamw			set_attr.sa_mask |= SMB_AT_UID;
204da6c28aamw		}
205da6c28aamw
206da6c28aamw		if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
207da6c28aamw			set_attr.sa_vattr.va_gid = fs_sd->sd_gid;
208da6c28aamw			set_attr.sa_mask |= SMB_AT_GID;
209da6c28aamw		}
210da6c28aamw
2119660e5cJanice Chang		if (set_attr.sa_mask)
2128622ec4Gordon Ross			rc = smb_vop_setattr(vp, NULL, &set_attr, 0, kcr);
213da6c28aamw
2142c1b14ejose borrego		if (rc == 0) {
2152c1b14ejose borrego			*ret_snode = smb_node_lookup(sr, &sr->arg.open, cr, vp,
216037cac0joyce mcintosh			    name, dnode, NULL);
2172c1b14ejose borrego
2187f667e7jose borrego			if (*ret_snode == NULL)
219