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.
2393bc28dbSGordon Ross * Copyright 2017 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
3655bf511dSas #include <smbsrv/smb_kproto.h>
37da6c28aaSamw #include <smbsrv/smb_fsops.h>
38da6c28aaSamw
39c5f48fa5SGordon Ross extern int smb_nt_create_enable_extended_response;
40c5f48fa5SGordon Ross
41da6c28aaSamw /*
42da6c28aaSamw * smb_nt_transact_create
43da6c28aaSamw *
44da6c28aaSamw * This command is used to create or open a file or directory, when EAs
45da6c28aaSamw * or an SD must be applied to the file. The request parameter block
46da6c28aaSamw * encoding, data block encoding and output parameter block encoding are
47da6c28aaSamw * described in CIFS section 4.2.2.
48da6c28aaSamw *
49da6c28aaSamw * The format of the command is SmbNtTransact but it is basically the same
50da6c28aaSamw * as SmbNtCreateAndx with the option to supply extended attributes or a
51da6c28aaSamw * security descriptor. For information not defined in CIFS section 4.2.2
52da6c28aaSamw * see section 4.2.1 (NT_CREATE_ANDX).
53da6c28aaSamw */
547b59d02dSjb smb_sdrc_t
smb_pre_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)55faa1795aSjb smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
56da6c28aaSamw {
57da6c28aaSamw struct open_param *op = &sr->arg.open;
58faa1795aSjb uint8_t SecurityFlags;
59faa1795aSjb uint32_t EaLength;
60faa1795aSjb uint32_t ImpersonationLevel;
61faa1795aSjb uint32_t NameLength;
62faa1795aSjb uint32_t sd_len;
63faa1795aSjb uint32_t status;
64faa1795aSjb smb_sd_t sd;
65da6c28aaSamw int rc;
66da6c28aaSamw
67faa1795aSjb bzero(op, sizeof (sr->arg.open));
68faa1795aSjb
693db3f65cSamw rc = smb_mbc_decodef(&xa->req_param_mb, "%lllqllllllllb",
70da6c28aaSamw sr,
712c2961f8Sjose borrego &op->nt_flags,
72faa1795aSjb &op->rootdirfid,
73da6c28aaSamw &op->desired_access,
74da6c28aaSamw &op->dsize,
75faa1795aSjb &op->dattr,
76da6c28aaSamw &op->share_access,
77da6c28aaSamw &op->create_disposition,
78da6c28aaSamw &op->create_options,
79da6c28aaSamw &sd_len,
80da6c28aaSamw &EaLength,
81da6c28aaSamw &NameLength,
82da6c28aaSamw &ImpersonationLevel,
83da6c28aaSamw &SecurityFlags);
84da6c28aaSamw
85faa1795aSjb if (rc == 0) {
86faa1795aSjb if (NameLength == 0) {
87eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States op->fqi.fq_path.pn_path = "\\";
88c5f48fa5SGordon Ross } else if (NameLength >= SMB_MAXPATHLEN) {
89c5f48fa5SGordon Ross smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
90c5f48fa5SGordon Ross ERRDOS, ERROR_INVALID_NAME);
91faa1795aSjb rc = -1;
92faa1795aSjb } else {
933db3f65cSamw rc = smb_mbc_decodef(&xa->req_param_mb, "%#u",
94eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States sr, NameLength, &op->fqi.fq_path.pn_path);
95faa1795aSjb }
96da6c28aaSamw }
97da6c28aaSamw
982c2961f8Sjose borrego op->op_oplock_level = SMB_OPLOCK_NONE;
992c2961f8Sjose borrego if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
1002c2961f8Sjose borrego if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
1012c2961f8Sjose borrego op->op_oplock_level = SMB_OPLOCK_BATCH;
1022c2961f8Sjose borrego else
1032c2961f8Sjose borrego op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
104da6c28aaSamw }
105da6c28aaSamw
10655bf511dSas if (sd_len) {
107a90cf9f2SGordon Ross status = smb_decode_sd(&xa->req_data_mb, &sd);
10855bf511dSas if (status != NT_STATUS_SUCCESS) {
109dc20a302Sas smbsr_error(sr, status, 0, 0);
110faa1795aSjb return (SDRC_ERROR);
111da6c28aaSamw }
112e5468186Sas op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP);
113e5468186Sas *op->sd = sd;
114da6c28aaSamw } else {
11555bf511dSas op->sd = NULL;
116da6c28aaSamw }
117da6c28aaSamw
11893bc28dbSGordon Ross DTRACE_SMB_START(op__NtTransactCreate, smb_request_t *, sr);
119da6c28aaSamw
120faa1795aSjb return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
121faa1795aSjb }
122da6c28aaSamw
123faa1795aSjb void
smb_post_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)124faa1795aSjb smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
125faa1795aSjb {
126e5468186Sas smb_sd_t *sd = sr->arg.open.sd;
12793bc28dbSGordon Ross _NOTE(ARGUNUSED(xa))
128e5468186Sas
12993bc28dbSGordon Ross DTRACE_SMB_DONE(op__NtTransactCreate, smb_request_t *, sr);
130e5468186Sas
131e5468186Sas if (sd) {
132e5468186Sas smb_sd_term(sd);
133e5468186Sas kmem_free(sd, sizeof (smb_sd_t));
134e5468186Sas }
135bbf6f00cSJordan Brown
136c5f48fa5SGordon Ross if (sr->arg.open.dir != NULL) {
137bbf6f00cSJordan Brown smb_ofile_release(sr->arg.open.dir);
138c5f48fa5SGordon Ross sr->arg.open.dir = NULL;
139c5f48fa5SGordon Ross }
140faa1795aSjb }
141da6c28aaSamw
142c5f48fa5SGordon Ross /*
143c5f48fa5SGordon Ross * A lot like smb_com_nt_create_andx
144c5f48fa5SGordon Ross */
145faa1795aSjb smb_sdrc_t
smb_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)146faa1795aSjb smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
147faa1795aSjb {
148c5f48fa5SGordon Ross struct open_param *op = &sr->arg.open;
149c5f48fa5SGordon Ross smb_attr_t *ap = &op->fqi.fq_fattr;
1505fd03bc0SGordon Ross smb_ofile_t *of;
1515fd03bc0SGordon Ross int rc;
152c5f48fa5SGordon Ross uint8_t DirFlag;
153c5f48fa5SGordon Ross uint32_t status;
154c5f48fa5SGordon Ross
155c5f48fa5SGordon Ross if (op->create_options & ~SMB_NTCREATE_VALID_OPTIONS) {
156c5f48fa5SGordon Ross smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
157c5f48fa5SGordon Ross ERRDOS, ERROR_INVALID_PARAMETER);
158c5f48fa5SGordon Ross return (SDRC_ERROR);
159c5f48fa5SGordon Ross }
160c5f48fa5SGordon Ross
161c5f48fa5SGordon Ross if (op->create_options & FILE_OPEN_BY_FILE_ID) {
162c5f48fa5SGordon Ross smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
163c5f48fa5SGordon Ross ERRDOS, ERROR_NOT_SUPPORTED);
164c5f48fa5SGordon Ross return (SDRC_ERROR);
165c5f48fa5SGordon Ross }
166faa1795aSjb
167faa1795aSjb if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
168faa1795aSjb !(op->desired_access & DELETE)) {
1692c2961f8Sjose borrego smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
1702c2961f8Sjose borrego ERRDOS, ERRbadaccess);
1712c2961f8Sjose borrego return (SDRC_ERROR);
1722c2961f8Sjose borrego }
1732c2961f8Sjose borrego
1742c2961f8Sjose borrego if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
1752c2961f8Sjose borrego smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
1762c2961f8Sjose borrego ERRDOS, ERRbadaccess);
177faa1795aSjb return (SDRC_ERROR);
178da6c28aaSamw }
179da6c28aaSamw
180faa1795aSjb if (op->dattr & FILE_FLAG_WRITE_THROUGH)
181da6c28aaSamw op->create_options |= FILE_WRITE_THROUGH;
182da6c28aaSamw
183faa1795aSjb if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
184da6c28aaSamw op->create_options |= FILE_DELETE_ON_CLOSE;
185da6c28aaSamw
186b89a8333Snatalie li - Sun Microsystems - Irvine United States if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
187b89a8333Snatalie li - Sun Microsystems - Irvine United States op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
188b89a8333Snatalie li - Sun Microsystems - Irvine United States
189b89a8333Snatalie li - Sun Microsystems - Irvine United States if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
190b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_user_getprivcred(sr->uid_user);
191b89a8333Snatalie li - Sun Microsystems - Irvine United States
192faa1795aSjb if (op->rootdirfid == 0) {
193eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States op->fqi.fq_dnode = sr->tid_tree->t_snode;
194da6c28aaSamw } else {
1953b13a1efSThomas Keiser op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid);
196bbf6f00cSJordan Brown if (op->dir == NULL) {
197faa1795aSjb smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
198faa1795aSjb ERRDOS, ERRbadfid);
199faa1795aSjb return (SDRC_ERROR);
200faa1795aSjb }
201bbf6f00cSJordan Brown op->fqi.fq_dnode = op->dir->f_node;
202da6c28aaSamw }
203da6c28aaSamw
204a90cf9f2SGordon Ross status = smb_common_open(sr);
205a90cf9f2SGordon Ross if (status != NT_STATUS_SUCCESS) {
206a90cf9f2SGordon Ross smbsr_status(sr, status, 0, 0);
207faa1795aSjb return (SDRC_ERROR);
208a90cf9f2SGordon Ross }
209*94047d49SGordon Ross if (op->op_oplock_level != SMB_OPLOCK_NONE) {
210*94047d49SGordon Ross /* Oplock req. in op->op_oplock_level etc. */
211*94047d49SGordon Ross smb1_oplock_acquire(sr, B_TRUE);
212*94047d49SGordon Ross }
213da6c28aaSamw
2145fd03bc0SGordon Ross /*
2155fd03bc0SGordon Ross * NB: after the above smb_common_open() success,
2165fd03bc0SGordon Ross * we have a handle allocated (sr->fid_ofile).
2175fd03bc0SGordon Ross * If we don't return success, we must close it.
2185fd03bc0SGordon Ross */
2195fd03bc0SGordon Ross of = sr->fid_ofile;
2205fd03bc0SGordon Ross
221f96bd5c8SAlan Wright switch (sr->tid_tree->t_res_type & STYPE_MASK) {
222f96bd5c8SAlan Wright case STYPE_DISKTREE:
223f96bd5c8SAlan Wright case STYPE_PRINTQ:
224da6c28aaSamw if (op->create_options & FILE_DELETE_ON_CLOSE)
225*94047d49SGordon Ross smb_ofile_set_delete_on_close(sr, of);
2265fd03bc0SGordon Ross DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
227f96bd5c8SAlan Wright break;
228f96bd5c8SAlan Wright
229f96bd5c8SAlan Wright case STYPE_IPC:
230c5f48fa5SGordon Ross DirFlag = 0;
231f96bd5c8SAlan Wright break;
232f96bd5c8SAlan Wright
233f96bd5c8SAlan Wright default:
234f96bd5c8SAlan Wright smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
235f96bd5c8SAlan Wright ERRDOS, ERROR_INVALID_FUNCTION);
2365fd03bc0SGordon Ross goto errout;
237da6c28aaSamw }
238c5f48fa5SGordon Ross
239c5f48fa5SGordon Ross if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 &&
240c5f48fa5SGordon Ross smb_nt_create_enable_extended_response != 0) {
241c5f48fa5SGordon Ross uint32_t MaxAccess = 0;
242c5f48fa5SGordon Ross if (of->f_node != NULL) {
243c5f48fa5SGordon Ross smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess);
244c5f48fa5SGordon Ross }
245c5f48fa5SGordon Ross MaxAccess |= of->f_granted_access;
246c5f48fa5SGordon Ross
247c5f48fa5SGordon Ross rc = smb_mbc_encodef(
248c5f48fa5SGordon Ross &xa->rep_param_mb, "bbwllTTTTlqqwwb16.qll",
249c5f48fa5SGordon Ross op->op_oplock_level, /* (b) */
250c5f48fa5SGordon Ross 1, /* ResponseType (b) */
251c5f48fa5SGordon Ross sr->smb_fid, /* (w) */
252c5f48fa5SGordon Ross op->action_taken, /* (l) */
253c5f48fa5SGordon Ross 0, /* EaErrorOffset (l) */
254c5f48fa5SGordon Ross &ap->sa_crtime, /* (T) */
255c5f48fa5SGordon Ross &ap->sa_vattr.va_atime, /* (T) */
256c5f48fa5SGordon Ross &ap->sa_vattr.va_mtime, /* (T) */
257c5f48fa5SGordon Ross &ap->sa_vattr.va_ctime, /* (T) */
258c5f48fa5SGordon Ross op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
259c5f48fa5SGordon Ross ap->sa_allocsz, /* (q) */
260c5f48fa5SGordon Ross ap->sa_vattr.va_size, /* (q) */
261c5f48fa5SGordon Ross op->ftype, /* (w) */
262c5f48fa5SGordon Ross op->devstate, /* (w) */
263c5f48fa5SGordon Ross DirFlag, /* (b) */
264c5f48fa5SGordon Ross /* volume guid (16.) */
265c5f48fa5SGordon Ross op->fileid, /* (q) */
266c5f48fa5SGordon Ross MaxAccess, /* (l) */
267c5f48fa5SGordon Ross 0); /* guest access (l) */
268c5f48fa5SGordon Ross } else {
269c5f48fa5SGordon Ross rc = smb_mbc_encodef(
270c5f48fa5SGordon Ross &xa->rep_param_mb, "bbwllTTTTlqqwwb",
271c5f48fa5SGordon Ross op->op_oplock_level, /* (b) */
272c5f48fa5SGordon Ross 0, /* ResponseType (b) */
273c5f48fa5SGordon Ross sr->smb_fid, /* (w) */
274c5f48fa5SGordon Ross op->action_taken, /* (l) */
275c5f48fa5SGordon Ross 0, /* EaErrorOffset (l) */
276c5f48fa5SGordon Ross &ap->sa_crtime, /* (T) */
277c5f48fa5SGordon Ross &ap->sa_vattr.va_atime, /* (T) */
278c5f48fa5SGordon Ross &ap->sa_vattr.va_mtime, /* (T) */
279c5f48fa5SGordon Ross &ap->sa_vattr.va_ctime, /* (T) */
280c5f48fa5SGordon Ross op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
281c5f48fa5SGordon Ross ap->sa_allocsz, /* (q) */
282c5f48fa5SGordon Ross ap->sa_vattr.va_size, /* (q) */
283c5f48fa5SGordon Ross op->ftype, /* (w) */
284c5f48fa5SGordon Ross op->devstate, /* (w) */
285c5f48fa5SGordon Ross DirFlag); /* (b) */
286c5f48fa5SGordon Ross }
287c5f48fa5SGordon Ross
288c5f48fa5SGordon Ross if (rc == 0)
289c5f48fa5SGordon Ross return (SDRC_SUCCESS);
290da6c28aaSamw
2915fd03bc0SGordon Ross errout:
2925fd03bc0SGordon Ross smb_ofile_close(of, 0);
2935fd03bc0SGordon Ross return (SDRC_ERROR);
294da6c28aaSamw }
295