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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * This command is used to create or open a file or directory, when EAs
28 * or an SD must be applied to the file. The functionality is similar
29 * to SmbNtCreateAndx with the option to supply extended attributes or
30 * a security descriptor.
31 *
32 * Note: we don't decode the extended attributes because we don't
33 * support them at this time.
34 */
35
36 #include <smbsrv/smb_kproto.h>
37 #include <smbsrv/smb_fsops.h>
38
39 extern int smb_nt_create_enable_extended_response;
40
41 /*
42 * smb_nt_transact_create
43 *
44 * This command is used to create or open a file or directory, when EAs
45 * or an SD must be applied to the file. The request parameter block
46 * encoding, data block encoding and output parameter block encoding are
47 * described in CIFS section 4.2.2.
48 *
49 * The format of the command is SmbNtTransact but it is basically the same
50 * as SmbNtCreateAndx with the option to supply extended attributes or a
51 * security descriptor. For information not defined in CIFS section 4.2.2
52 * see section 4.2.1 (NT_CREATE_ANDX).
53 */
54 smb_sdrc_t
55 smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
56 {
57 struct open_param *op = &sr->arg.open;
58 uint8_t SecurityFlags;
59 uint32_t EaLength;
60 uint32_t ImpersonationLevel;
61 uint32_t NameLength;
62 uint32_t sd_len;
63 uint32_t status;
64 smb_sd_t sd;
65 int rc;
66
67 bzero(op, sizeof (sr->arg.open));
68
69 rc = smb_mbc_decodef(&xa->req_param_mb, "%lllqllllllllb",
70 sr,
71 &op->nt_flags,
72 &op->rootdirfid,
73 &op->desired_access,
74 &op->dsize,
75 &op->dattr,
76 &op->share_access,
77 &op->create_disposition,
78 &op->create_options,
79 &sd_len,
80 &EaLength,
81 &NameLength,
82 &ImpersonationLevel,
83 &SecurityFlags);
84
85 if (rc == 0) {
86 if (NameLength == 0) {
87 op->fqi.fq_path.pn_path = "\\";
88 } else if (NameLength >= SMB_MAXPATHLEN) {
89 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
90 ERRDOS, ERROR_INVALID_NAME);
91 rc = -1;
92 } else {
93 rc = smb_mbc_decodef(&xa->req_param_mb, "%#u",
94 sr, NameLength, &op->fqi.fq_path.pn_path);
95 }
96 }
97
98 op->op_oplock_level = SMB_OPLOCK_NONE;
99 if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
100 if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
101 op->op_oplock_level = SMB_OPLOCK_BATCH;
102 else
103 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
104 }
105
106 if (sd_len) {
107 status = smb_decode_sd(&xa->req_data_mb, &sd);
108 if (status != NT_STATUS_SUCCESS) {
109 smbsr_error(sr, status, 0, 0);
110 return (SDRC_ERROR);
111 }
112 op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP);
113 *op->sd = sd;
114 } else {
115 op->sd = NULL;
116 }
117
118 DTRACE_SMB_2(op__NtTransactCreate__start, smb_request_t *, sr,
119 struct open_param *, op);
120
121 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
122 }
123
124 void
125 smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
126 {
127 smb_sd_t *sd = sr->arg.open.sd;
128
129 DTRACE_SMB_2(op__NtTransactCreate__done, smb_request_t *, sr,
130 smb_xa_t *, xa);
131
132 if (sd) {
133 smb_sd_term(sd);
134 kmem_free(sd, sizeof (smb_sd_t));
135 }
136
137 if (sr->arg.open.dir != NULL) {
138 smb_ofile_release(sr->arg.open.dir);
139 sr->arg.open.dir = NULL;
140 }
141 }
142
143 /*
144 * A lot like smb_com_nt_create_andx
145 */
146 smb_sdrc_t
147 smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
148 {
149 struct open_param *op = &sr->arg.open;
150 smb_attr_t *ap = &op->fqi.fq_fattr;
151 smb_ofile_t *of;
152 int rc;
153 uint8_t DirFlag;
154 uint32_t status;
155
156 if (op->create_options & ~SMB_NTCREATE_VALID_OPTIONS) {
157 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
158 ERRDOS, ERROR_INVALID_PARAMETER);
159 return (SDRC_ERROR);
160 }
161
162 if (op->create_options & FILE_OPEN_BY_FILE_ID) {
163 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
164 ERRDOS, ERROR_NOT_SUPPORTED);
165 return (SDRC_ERROR);
166 }
167
168 if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
169 !(op->desired_access & DELETE)) {
170 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
171 ERRDOS, ERRbadaccess);
172 return (SDRC_ERROR);
173 }
174
175 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
176 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
177 ERRDOS, ERRbadaccess);
178 return (SDRC_ERROR);
179 }
180
181 if (op->dattr & FILE_FLAG_WRITE_THROUGH)
182 op->create_options |= FILE_WRITE_THROUGH;
183
184 if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
185 op->create_options |= FILE_DELETE_ON_CLOSE;
186
187 if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
188 op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
189
190 if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
191 sr->user_cr = smb_user_getprivcred(sr->uid_user);
192
193 if (op->rootdirfid == 0) {
194 op->fqi.fq_dnode = sr->tid_tree->t_snode;
195 } else {
196 op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid);
197 if (op->dir == NULL) {
198 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
199 ERRDOS, ERRbadfid);
200 return (SDRC_ERROR);
201 }
202 op->fqi.fq_dnode = op->dir->f_node;
203 }
204
205 op->op_oplock_levelII = B_TRUE;
206
207 status = smb_common_open(sr);
208 if (status != NT_STATUS_SUCCESS) {
209 smbsr_status(sr, status, 0, 0);
210 return (SDRC_ERROR);
211 }
212
213 /*
214 * NB: after the above smb_common_open() success,
215 * we have a handle allocated (sr->fid_ofile).
216 * If we don't return success, we must close it.
217 */
218 of = sr->fid_ofile;
219
220 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
221 case STYPE_DISKTREE:
222 case STYPE_PRINTQ:
223 if (op->create_options & FILE_DELETE_ON_CLOSE)
224 smb_ofile_set_delete_on_close(of);
225 DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
226 break;
227
228 case STYPE_IPC:
229 DirFlag = 0;
230 break;
231
232 default:
233 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
234 ERRDOS, ERROR_INVALID_FUNCTION);
235 goto errout;
236 }
237
238 if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 &&
239 smb_nt_create_enable_extended_response != 0) {
240 uint32_t MaxAccess = 0;
241 if (of->f_node != NULL) {
242 smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess);
243 }
244 MaxAccess |= of->f_granted_access;
245
246 rc = smb_mbc_encodef(
247 &xa->rep_param_mb, "bbwllTTTTlqqwwb16.qll",
248 op->op_oplock_level, /* (b) */
249 1, /* ResponseType (b) */
250 sr->smb_fid, /* (w) */
251 op->action_taken, /* (l) */
252 0, /* EaErrorOffset (l) */
253 &ap->sa_crtime, /* (T) */
254 &ap->sa_vattr.va_atime, /* (T) */
255 &ap->sa_vattr.va_mtime, /* (T) */
256 &ap->sa_vattr.va_ctime, /* (T) */
257 op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
258 ap->sa_allocsz, /* (q) */
259 ap->sa_vattr.va_size, /* (q) */
260 op->ftype, /* (w) */
261 op->devstate, /* (w) */
262 DirFlag, /* (b) */
263 /* volume guid (16.) */
264 op->fileid, /* (q) */
265 MaxAccess, /* (l) */
266 0); /* guest access (l) */
267 } else {
268 rc = smb_mbc_encodef(
269 &xa->rep_param_mb, "bbwllTTTTlqqwwb",
270 op->op_oplock_level, /* (b) */
271 0, /* ResponseType (b) */
272 sr->smb_fid, /* (w) */
273 op->action_taken, /* (l) */
274 0, /* EaErrorOffset (l) */
275 &ap->sa_crtime, /* (T) */
276 &ap->sa_vattr.va_atime, /* (T) */
277 &ap->sa_vattr.va_mtime, /* (T) */
278 &ap->sa_vattr.va_ctime, /* (T) */
279 op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
280 ap->sa_allocsz, /* (q) */
281 ap->sa_vattr.va_size, /* (q) */
282 op->ftype, /* (w) */
283 op->devstate, /* (w) */
284 DirFlag); /* (b) */
285 }
286
287 if (rc == 0)
288 return (SDRC_SUCCESS);
289
290 errout:
291 smb_ofile_close(of, 0);
292 return (SDRC_ERROR);
293 }