xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c (revision 5fd03bc0f2e00e7ba02316c2e08f45d52aab15db)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22cb174861Sjoyce mcintosh  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*5fd03bc0SGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw /*
27da6c28aaSamw  * This command is used to create or open a file or directory, when EAs
28da6c28aaSamw  * or an SD must be applied to the file. The functionality is similar
29da6c28aaSamw  * to SmbNtCreateAndx with the option to supply extended attributes or
30da6c28aaSamw  * a security descriptor.
31da6c28aaSamw  *
32da6c28aaSamw  * Note: we don't decode the extended attributes because we don't
33da6c28aaSamw  * support them at this time.
34da6c28aaSamw  */
35da6c28aaSamw 
3655bf511dSas200622 #include <smbsrv/smb_kproto.h>
37da6c28aaSamw #include <smbsrv/smb_fsops.h>
38da6c28aaSamw 
39da6c28aaSamw /*
40da6c28aaSamw  * smb_nt_transact_create
41da6c28aaSamw  *
42da6c28aaSamw  * This command is used to create or open a file or directory, when EAs
43da6c28aaSamw  * or an SD must be applied to the file. The request parameter block
44da6c28aaSamw  * encoding, data block encoding and output parameter block encoding are
45da6c28aaSamw  * described in CIFS section 4.2.2.
46da6c28aaSamw  *
47da6c28aaSamw  * The format of the command is SmbNtTransact but it is basically the same
48da6c28aaSamw  * as SmbNtCreateAndx with the option to supply extended attributes or a
49da6c28aaSamw  * security descriptor. For information not defined in CIFS section 4.2.2
50da6c28aaSamw  * see section 4.2.1 (NT_CREATE_ANDX).
51da6c28aaSamw  */
527b59d02dSjb150015 smb_sdrc_t
53faa1795aSjb150015 smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
54da6c28aaSamw {
55da6c28aaSamw 	struct open_param *op = &sr->arg.open;
56da6c28aaSamw 	uint8_t SecurityFlags;
57da6c28aaSamw 	uint32_t EaLength;
58da6c28aaSamw 	uint32_t ImpersonationLevel;
59da6c28aaSamw 	uint32_t NameLength;
60faa1795aSjb150015 	uint32_t sd_len;
61faa1795aSjb150015 	uint32_t status;
6255bf511dSas200622 	smb_sd_t sd;
63da6c28aaSamw 	int rc;
64da6c28aaSamw 
65faa1795aSjb150015 	bzero(op, sizeof (sr->arg.open));
66faa1795aSjb150015 
673db3f65cSamw 	rc = smb_mbc_decodef(&xa->req_param_mb, "%lllqllllllllb",
68da6c28aaSamw 	    sr,
692c2961f8Sjose borrego 	    &op->nt_flags,
70faa1795aSjb150015 	    &op->rootdirfid,
71da6c28aaSamw 	    &op->desired_access,
72da6c28aaSamw 	    &op->dsize,
73faa1795aSjb150015 	    &op->dattr,
74da6c28aaSamw 	    &op->share_access,
75da6c28aaSamw 	    &op->create_disposition,
76da6c28aaSamw 	    &op->create_options,
77da6c28aaSamw 	    &sd_len,
78da6c28aaSamw 	    &EaLength,
79da6c28aaSamw 	    &NameLength,
80da6c28aaSamw 	    &ImpersonationLevel,
81da6c28aaSamw 	    &SecurityFlags);
82da6c28aaSamw 
83faa1795aSjb150015 	if (rc == 0) {
84da6c28aaSamw 		if (NameLength == 0) {
85eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			op->fqi.fq_path.pn_path = "\\";
86faa1795aSjb150015 		} else if (NameLength >= MAXPATHLEN) {
87faa1795aSjb150015 			smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
88faa1795aSjb150015 			    ERRDOS, ERROR_PATH_NOT_FOUND);
89faa1795aSjb150015 			rc = -1;
90da6c28aaSamw 		} else {
913db3f65cSamw 			rc = smb_mbc_decodef(&xa->req_param_mb, "%#u",
92eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			    sr, NameLength, &op->fqi.fq_path.pn_path);
93faa1795aSjb150015 		}
94da6c28aaSamw 	}
95da6c28aaSamw 
962c2961f8Sjose borrego 	op->op_oplock_level = SMB_OPLOCK_NONE;
972c2961f8Sjose borrego 	if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
982c2961f8Sjose borrego 		if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
992c2961f8Sjose borrego 			op->op_oplock_level = SMB_OPLOCK_BATCH;
100faa1795aSjb150015 		else
1012c2961f8Sjose borrego 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
102da6c28aaSamw 	}
103da6c28aaSamw 
10455bf511dSas200622 	if (sd_len) {
10555bf511dSas200622 		status = smb_decode_sd(xa, &sd);
10655bf511dSas200622 		if (status != NT_STATUS_SUCCESS) {
107dc20a302Sas200622 			smbsr_error(sr, status, 0, 0);
108faa1795aSjb150015 			return (SDRC_ERROR);
109da6c28aaSamw 		}
110e5468186Sas200622 		op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP);
111e5468186Sas200622 		*op->sd = sd;
112da6c28aaSamw 	} else {
11355bf511dSas200622 		op->sd = NULL;
114da6c28aaSamw 	}
115da6c28aaSamw 
116faa1795aSjb150015 	DTRACE_SMB_2(op__NtTransactCreate__start, smb_request_t *, sr,
117faa1795aSjb150015 	    struct open_param *, op);
118da6c28aaSamw 
119faa1795aSjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
120da6c28aaSamw }
121da6c28aaSamw 
122faa1795aSjb150015 void
123faa1795aSjb150015 smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
124faa1795aSjb150015 {
125e5468186Sas200622 	smb_sd_t *sd = sr->arg.open.sd;
126e5468186Sas200622 
127faa1795aSjb150015 	DTRACE_SMB_2(op__NtTransactCreate__done, smb_request_t *, sr,
128faa1795aSjb150015 	    smb_xa_t *, xa);
129e5468186Sas200622 
130e5468186Sas200622 	if (sd) {
131e5468186Sas200622 		smb_sd_term(sd);
132e5468186Sas200622 		kmem_free(sd, sizeof (smb_sd_t));
133e5468186Sas200622 	}
134bbf6f00cSJordan Brown 
135bbf6f00cSJordan Brown 	if (sr->arg.open.dir != NULL)
136bbf6f00cSJordan Brown 		smb_ofile_release(sr->arg.open.dir);
137faa1795aSjb150015 }
138faa1795aSjb150015 
139faa1795aSjb150015 smb_sdrc_t
140faa1795aSjb150015 smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
141faa1795aSjb150015 {
142faa1795aSjb150015 	struct open_param *op = &sr->arg.open;
143faa1795aSjb150015 	uint8_t			DirFlag;
144037cac00Sjoyce mcintosh 	smb_attr_t		attr;
145*5fd03bc0SGordon Ross 	smb_ofile_t		*of;
146*5fd03bc0SGordon Ross 	int			rc;
147faa1795aSjb150015 
148faa1795aSjb150015 	if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
149faa1795aSjb150015 	    !(op->desired_access & DELETE)) {
1502c2961f8Sjose borrego 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
1512c2961f8Sjose borrego 		    ERRDOS, ERRbadaccess);
1522c2961f8Sjose borrego 		return (SDRC_ERROR);
1532c2961f8Sjose borrego 	}
1542c2961f8Sjose borrego 
1552c2961f8Sjose borrego 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
1562c2961f8Sjose borrego 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
1572c2961f8Sjose borrego 		    ERRDOS, ERRbadaccess);
158faa1795aSjb150015 		return (SDRC_ERROR);
159faa1795aSjb150015 	}
160faa1795aSjb150015 
161faa1795aSjb150015 	if (op->dattr & FILE_FLAG_WRITE_THROUGH)
162da6c28aaSamw 		op->create_options |= FILE_WRITE_THROUGH;
163da6c28aaSamw 
164faa1795aSjb150015 	if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
165da6c28aaSamw 		op->create_options |= FILE_DELETE_ON_CLOSE;
166da6c28aaSamw 
167b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
168b89a8333Snatalie li - Sun Microsystems - Irvine United States 		op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
169b89a8333Snatalie li - Sun Microsystems - Irvine United States 
170b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
171b89a8333Snatalie li - Sun Microsystems - Irvine United States 		sr->user_cr = smb_user_getprivcred(sr->uid_user);
172b89a8333Snatalie li - Sun Microsystems - Irvine United States 
173faa1795aSjb150015 	if (op->rootdirfid == 0) {
174eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->fqi.fq_dnode = sr->tid_tree->t_snode;
175da6c28aaSamw 	} else {
176bbf6f00cSJordan Brown 		op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
177bbf6f00cSJordan Brown 		    (uint16_t)op->rootdirfid);
178bbf6f00cSJordan Brown 		if (op->dir == NULL) {
179faa1795aSjb150015 			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
180faa1795aSjb150015 			    ERRDOS, ERRbadfid);
181faa1795aSjb150015 			return (SDRC_ERROR);
182faa1795aSjb150015 		}
183bbf6f00cSJordan Brown 		op->fqi.fq_dnode = op->dir->f_node;
184da6c28aaSamw 	}
185da6c28aaSamw 
186cb174861Sjoyce mcintosh 	op->op_oplock_levelII = B_TRUE;
187cb174861Sjoyce mcintosh 
188*5fd03bc0SGordon Ross 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
189faa1795aSjb150015 		return (SDRC_ERROR);
190da6c28aaSamw 
191*5fd03bc0SGordon Ross 	/*
192*5fd03bc0SGordon Ross 	 * NB: after the above smb_common_open() success,
193*5fd03bc0SGordon Ross 	 * we have a handle allocated (sr->fid_ofile).
194*5fd03bc0SGordon Ross 	 * If we don't return success, we must close it.
195*5fd03bc0SGordon Ross 	 */
196*5fd03bc0SGordon Ross 	of = sr->fid_ofile;
197*5fd03bc0SGordon Ross 
198f96bd5c8SAlan Wright 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
199f96bd5c8SAlan Wright 	case STYPE_DISKTREE:
200f96bd5c8SAlan Wright 	case STYPE_PRINTQ:
201da6c28aaSamw 		if (op->create_options & FILE_DELETE_ON_CLOSE)
202*5fd03bc0SGordon Ross 			smb_ofile_set_delete_on_close(of);
203da6c28aaSamw 
204*5fd03bc0SGordon Ross 		DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
205*5fd03bc0SGordon Ross 		bzero(&attr, sizeof (attr));
206*5fd03bc0SGordon Ross 		attr.sa_mask = SMB_AT_ALL;
207*5fd03bc0SGordon Ross 		rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
208*5fd03bc0SGordon Ross 		if (rc != 0) {
209*5fd03bc0SGordon Ross 			smbsr_errno(sr, rc);
210*5fd03bc0SGordon Ross 			goto errout;
211da6c28aaSamw 		}
212da6c28aaSamw 
2133db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
214cb174861Sjoyce mcintosh 		    op->op_oplock_level,
215da6c28aaSamw 		    sr->smb_fid,
216da6c28aaSamw 		    op->action_taken,
217da6c28aaSamw 		    0,	/* EaErrorOffset */
218037cac00Sjoyce mcintosh 		    &attr.sa_crtime,
219037cac00Sjoyce mcintosh 		    &attr.sa_vattr.va_atime,
220037cac00Sjoyce mcintosh 		    &attr.sa_vattr.va_mtime,
221037cac00Sjoyce mcintosh 		    &attr.sa_vattr.va_ctime,
222da6c28aaSamw 		    op->dattr & FILE_ATTRIBUTE_MASK,
223e3f2c991SKeyur Desai 		    attr.sa_allocsz,
224037cac00Sjoyce mcintosh 		    attr.sa_vattr.va_size,
225da6c28aaSamw 		    op->ftype,
226da6c28aaSamw 		    op->devstate,
227da6c28aaSamw 		    DirFlag);
228f96bd5c8SAlan Wright 		break;
229f96bd5c8SAlan Wright 
230f96bd5c8SAlan Wright 	case STYPE_IPC:
231037cac00Sjoyce mcintosh 		bzero(&attr, sizeof (smb_attr_t));
2323db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
233da6c28aaSamw 		    0,
234da6c28aaSamw 		    sr->smb_fid,
235da6c28aaSamw 		    op->action_taken,
236da6c28aaSamw 		    0,	/* EaErrorOffset */
237037cac00Sjoyce mcintosh 		    &attr.sa_crtime,
238037cac00Sjoyce mcintosh 		    &attr.sa_vattr.va_atime,
239037cac00Sjoyce mcintosh 		    &attr.sa_vattr.va_mtime,
240037cac00Sjoyce mcintosh 		    &attr.sa_vattr.va_ctime,
241da6c28aaSamw 		    op->dattr,
242da6c28aaSamw 		    0x1000LL,
243da6c28aaSamw 		    0LL,
244da6c28aaSamw 		    op->ftype,
245da6c28aaSamw 		    op->devstate,
246da6c28aaSamw 		    0);
247f96bd5c8SAlan Wright 		break;
248f96bd5c8SAlan Wright 
249f96bd5c8SAlan Wright 	default:
250f96bd5c8SAlan Wright 		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
251f96bd5c8SAlan Wright 		    ERRDOS, ERROR_INVALID_FUNCTION);
252*5fd03bc0SGordon Ross 		goto errout;
253da6c28aaSamw 	}
254*5fd03bc0SGordon Ross 	if (rc == 0)
255faa1795aSjb150015 		return (SDRC_SUCCESS);
256*5fd03bc0SGordon Ross 
257*5fd03bc0SGordon Ross errout:
258*5fd03bc0SGordon Ross 	smb_ofile_close(of, 0);
259*5fd03bc0SGordon Ross 	return (SDRC_ERROR);
260da6c28aaSamw }
261