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 */
24
25 /*
26 * This command is used to create or open a file or directory, when EAs
27 * or an SD must be applied to the file. The functionality is similar
28 * to SmbNtCreateAndx with the option to supply extended attributes or
29 * a security descriptor.
30 *
31 * Note: we don't decode the extended attributes because we don't
32 * support them at this time.
33 */
34
35 #include <smbsrv/smb_kproto.h>
36 #include <smbsrv/smb_fsops.h>
37
38 /*
39 * smb_nt_transact_create
40 *
41 * This command is used to create or open a file or directory, when EAs
42 * or an SD must be applied to the file. The request parameter block
43 * encoding, data block encoding and output parameter block encoding are
44 * described in CIFS section 4.2.2.
45 *
46 * The format of the command is SmbNtTransact but it is basically the same
47 * as SmbNtCreateAndx with the option to supply extended attributes or a
48 * security descriptor. For information not defined in CIFS section 4.2.2
49 * see section 4.2.1 (NT_CREATE_ANDX).
50 */
51 smb_sdrc_t
smb_pre_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)52 smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
53 {
54 struct open_param *op = &sr->arg.open;
55 uint8_t SecurityFlags;
56 uint32_t EaLength;
57 uint32_t ImpersonationLevel;
58 uint32_t NameLength;
59 uint32_t sd_len;
60 uint32_t status;
61 smb_sd_t sd;
62 int rc;
63
64 bzero(op, sizeof (sr->arg.open));
65
66 rc = smb_mbc_decodef(&xa->req_param_mb, "%lllqllllllllb",
67 sr,
68 &op->nt_flags,
69 &op->rootdirfid,
70 &op->desired_access,
71 &op->dsize,
72 &op->dattr,
73 &op->share_access,
74 &op->create_disposition,
75 &op->create_options,
76 &sd_len,
77 &EaLength,
78 &NameLength,
79 &ImpersonationLevel,
80 &SecurityFlags);
81
82 if (rc == 0) {
83 if (NameLength == 0) {
84 op->fqi.fq_path.pn_path = "\\";
85 } else if (NameLength >= MAXPATHLEN) {
86 smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
87 ERRDOS, ERROR_PATH_NOT_FOUND);
88 rc = -1;
89 } else {
90 rc = smb_mbc_decodef(&xa->req_param_mb, "%#u",
91 sr, NameLength, &op->fqi.fq_path.pn_path);
92 }
93 }
94
95 op->op_oplock_level = SMB_OPLOCK_NONE;
96 if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
97 if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
98 op->op_oplock_level = SMB_OPLOCK_BATCH;
99 else
100 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
101 }
102
103 if (sd_len) {
104 status = smb_decode_sd(xa, &sd);
105 if (status != NT_STATUS_SUCCESS) {
106 smbsr_error(sr, status, 0, 0);
107 return (SDRC_ERROR);
108 }
109 op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP);
110 *op->sd = sd;
111 } else {
112 op->sd = NULL;
113 }
114
115 DTRACE_SMB_2(op__NtTransactCreate__start, smb_request_t *, sr,
116 struct open_param *, op);
117
118 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
119 }
120
121 void
smb_post_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)122 smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
123 {
124 smb_sd_t *sd = sr->arg.open.sd;
125
126 DTRACE_SMB_2(op__NtTransactCreate__done, smb_request_t *, sr,
127 smb_xa_t *, xa);
128
129 if (sd) {
130 smb_sd_term(sd);
131 kmem_free(sd, sizeof (smb_sd_t));
132 }
133
134 if (sr->arg.open.dir != NULL)
135 smb_ofile_release(sr->arg.open.dir);
136 }
137
138 smb_sdrc_t
smb_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)139 smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
140 {
141 struct open_param *op = &sr->arg.open;
142 uint8_t DirFlag;
143 smb_attr_t attr;
144 smb_node_t *node;
145 uint32_t status;
146
147 if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
148 !(op->desired_access & DELETE)) {
149 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
150 ERRDOS, ERRbadaccess);
151 return (SDRC_ERROR);
152 }
153
154 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
155 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
156 ERRDOS, ERRbadaccess);
157 return (SDRC_ERROR);
158 }
159
160 if (op->dattr & FILE_FLAG_WRITE_THROUGH)
161 op->create_options |= FILE_WRITE_THROUGH;
162
163 if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
164 op->create_options |= FILE_DELETE_ON_CLOSE;
165
166 if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
167 op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
168
169 if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
170 sr->user_cr = smb_user_getprivcred(sr->uid_user);
171
172 if (op->rootdirfid == 0) {
173 op->fqi.fq_dnode = sr->tid_tree->t_snode;
174 } else {
175 op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
176 (uint16_t)op->rootdirfid);
177 if (op->dir == NULL) {
178 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
179 ERRDOS, ERRbadfid);
180 return (SDRC_ERROR);
181 }
182 op->fqi.fq_dnode = op->dir->f_node;
183 }
184
185 op->op_oplock_levelII = B_TRUE;
186
187 status = smb_common_open(sr);
188
189 if (status != NT_STATUS_SUCCESS)
190 return (SDRC_ERROR);
191
192 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
193 case STYPE_DISKTREE:
194 case STYPE_PRINTQ:
195 if (op->create_options & FILE_DELETE_ON_CLOSE)
196 smb_ofile_set_delete_on_close(sr->fid_ofile);
197
198 node = sr->fid_ofile->f_node;
199 DirFlag = smb_node_is_dir(node) ? 1 : 0;
200 if (smb_node_getattr(sr, node, &attr) != 0) {
201 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
202 ERRDOS, ERROR_INTERNAL_ERROR);
203 return (SDRC_ERROR);
204 }
205
206 (void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
207 op->op_oplock_level,
208 sr->smb_fid,
209 op->action_taken,
210 0, /* EaErrorOffset */
211 &attr.sa_crtime,
212 &attr.sa_vattr.va_atime,
213 &attr.sa_vattr.va_mtime,
214 &attr.sa_vattr.va_ctime,
215 op->dattr & FILE_ATTRIBUTE_MASK,
216 attr.sa_allocsz,
217 attr.sa_vattr.va_size,
218 op->ftype,
219 op->devstate,
220 DirFlag);
221 break;
222
223 case STYPE_IPC:
224 bzero(&attr, sizeof (smb_attr_t));
225 (void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
226 0,
227 sr->smb_fid,
228 op->action_taken,
229 0, /* EaErrorOffset */
230 &attr.sa_crtime,
231 &attr.sa_vattr.va_atime,
232 &attr.sa_vattr.va_mtime,
233 &attr.sa_vattr.va_ctime,
234 op->dattr,
235 0x1000LL,
236 0LL,
237 op->ftype,
238 op->devstate,
239 0);
240 break;
241
242 default:
243 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
244 ERRDOS, ERROR_INVALID_FUNCTION);
245 return (SDRC_ERROR);
246 }
247
248 return (SDRC_SUCCESS);
249 }
250