Print this page
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
SMB-65 SMB server in non-global zones (use zone_kcred())
re #14152 Race between ipmi_submit_driver_request() and kcs_loop() (sync with illumos fix 3902)
SMB-46 File handle leaks exposed by mtime fixes (rm 7815)
re #7815 SMB server delivers old modification time...
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_directory.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_directory.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 - * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
26 26 */
27 27
28 28 #include <smbsrv/smb_kproto.h>
29 29 #include <smbsrv/smbinfo.h>
30 30 #include <smbsrv/smb_fsops.h>
31 31
32 32 /*
33 33 * The create directory message is sent to create a new directory. The
34 34 * appropriate Tid and additional pathname are passed. The directory must
35 35 * not exist for it to be created.
36 36 *
37 37 * Client Request Description
38 38 * ================================== =================================
39 39 * UCHAR WordCount; Count of parameter words = 0
40 40 * USHORT ByteCount; Count of data bytes; min = 2
41 41 * UCHAR BufferFormat; 0x04
42 42 * STRING DirectoryName[]; Directory name
43 43 *
44 44 * Servers require clients to have at least create permission for the
45 45 * subtree containing the directory in order to create a new directory.
46 46 * The creator's access rights to the new directory are be determined by
47 47 * local policy on the server.
48 48 *
49 49 * Server Response Description
50 50 * ================================== =================================
51 51 * UCHAR WordCount; Count of parameter words = 0
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
52 52 * USHORT ByteCount; Count of data bytes = 0
53 53 */
54 54 smb_sdrc_t
55 55 smb_pre_create_directory(smb_request_t *sr)
56 56 {
57 57 int rc;
58 58
59 59 rc = smbsr_decode_data(sr, "%S", sr,
60 60 &sr->arg.dirop.fqi.fq_path.pn_path);
61 61
62 - DTRACE_SMB_2(op__CreateDirectory__start, smb_request_t *, sr,
63 - struct dirop *, &sr->arg.dirop);
62 + DTRACE_SMB_START(op__CreateDirectory, smb_request_t *, sr);
64 63
65 64 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
66 65 }
67 66
68 67 void
69 68 smb_post_create_directory(smb_request_t *sr)
70 69 {
71 - DTRACE_SMB_1(op__CreateDirectory__done, smb_request_t *, sr);
70 + DTRACE_SMB_DONE(op__CreateDirectory, smb_request_t *, sr);
72 71 }
73 72
74 73 smb_sdrc_t
75 74 smb_com_create_directory(smb_request_t *sr)
76 75 {
77 76 int rc = 0;
78 77 smb_pathname_t *pn = &sr->arg.dirop.fqi.fq_path;
79 78
80 79 if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
81 80 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
82 81 ERRDOS, ERROR_ACCESS_DENIED);
83 82 return (SDRC_ERROR);
84 83 }
85 84
86 85 smb_pathname_init(sr, pn, pn->pn_path);
87 86 if (!smb_pathname_validate(sr, pn) ||
88 87 !smb_validate_dirname(sr, pn)) {
89 88 return (SDRC_ERROR);
90 89 }
91 90
92 91 if ((rc = smb_common_create_directory(sr)) != 0) {
93 92 smbsr_errno(sr, rc);
94 93 return (SDRC_ERROR);
95 94 }
96 95
97 96 rc = smbsr_encode_empty_result(sr);
98 97 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
99 98 }
100 99
101 100 /*
102 101 * smb_common_create_directory
103 102 *
104 103 * Currently called from:
105 104 * smb_com_create_directory
106 105 * smb_com_trans2_create_directory
107 106 *
108 107 * Returns errno values.
109 108 */
110 109 int
111 110 smb_common_create_directory(smb_request_t *sr)
112 111 {
113 112 int rc;
114 113 smb_attr_t new_attr;
115 114 smb_fqi_t *fqi;
116 115 smb_node_t *tnode;
117 116
118 117 fqi = &sr->arg.dirop.fqi;
119 118 tnode = sr->tid_tree->t_snode;
120 119
121 120 rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
122 121 tnode, tnode, &fqi->fq_dnode, fqi->fq_last_comp);
123 122 if (rc != 0)
124 123 return (rc);
125 124
126 125 if (smb_is_invalid_filename(fqi->fq_last_comp)) {
127 126 smb_node_release(fqi->fq_dnode);
128 127 return (EILSEQ); /* NT_STATUS_OBJECT_NAME_INVALID */
129 128 }
130 129
131 130 /* lookup node - to ensure that it does NOT exist */
132 131 rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
133 132 tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
134 133 if (rc == 0) {
135 134 smb_node_release(fqi->fq_dnode);
136 135 smb_node_release(fqi->fq_fnode);
137 136 return (EEXIST);
138 137 }
139 138 if (rc != ENOENT) {
140 139 smb_node_release(fqi->fq_dnode);
141 140 return (rc);
142 141 }
143 142
144 143 rc = smb_fsop_access(sr, sr->user_cr, fqi->fq_dnode,
145 144 FILE_ADD_SUBDIRECTORY);
146 145 if (rc != NT_STATUS_SUCCESS) {
147 146 smb_node_release(fqi->fq_dnode);
148 147 return (EACCES);
149 148 }
150 149
151 150 /*
152 151 * Explicitly set sa_dosattr, otherwise the file system may
153 152 * automatically apply FILE_ATTRIBUTE_ARCHIVE which, for
154 153 * compatibility with windows servers, should not be set.
155 154 */
156 155 bzero(&new_attr, sizeof (new_attr));
157 156 new_attr.sa_dosattr = FILE_ATTRIBUTE_DIRECTORY;
158 157 new_attr.sa_vattr.va_type = VDIR;
159 158 new_attr.sa_vattr.va_mode = 0777;
160 159 new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE | SMB_AT_DOSATTR;
161 160
162 161 rc = smb_fsop_mkdir(sr, sr->user_cr, fqi->fq_dnode, fqi->fq_last_comp,
163 162 &new_attr, &fqi->fq_fnode);
164 163 if (rc != 0) {
165 164 smb_node_release(fqi->fq_dnode);
166 165 return (rc);
167 166 }
168 167
169 168 sr->arg.open.create_options = FILE_DIRECTORY_FILE;
170 169
171 170 smb_node_release(fqi->fq_dnode);
172 171 smb_node_release(fqi->fq_fnode);
173 172 return (0);
174 173 }
175 174
176 175 /*
177 176 * The delete directory message is sent to delete an empty directory. The
178 177 * appropriate Tid and additional pathname are passed. The directory must
179 178 * be empty for it to be deleted.
180 179 *
181 180 * NT supports a hidden permission known as File Delete Child (FDC). If
182 181 * the user has FullControl access to a directory, the user is permitted
183 182 * to delete any object in the directory regardless of the permissions
184 183 * on the object.
185 184 *
186 185 * Client Request Description
187 186 * ================================== =================================
188 187 * UCHAR WordCount; Count of parameter words = 0
189 188 * USHORT ByteCount; Count of data bytes; min = 2
190 189 * UCHAR BufferFormat; 0x04
191 190 * STRING DirectoryName[]; Directory name
192 191 *
193 192 * The directory to be deleted cannot be the root of the share specified
194 193 * by Tid.
195 194 *
196 195 * Server Response Description
197 196 * ================================== =================================
198 197 * UCHAR WordCount; Count of parameter words = 0
|
↓ open down ↓ |
117 lines elided |
↑ open up ↑ |
199 198 * USHORT ByteCount; Count of data bytes = 0
200 199 */
201 200 smb_sdrc_t
202 201 smb_pre_delete_directory(smb_request_t *sr)
203 202 {
204 203 int rc;
205 204
206 205 rc = smbsr_decode_data(sr, "%S", sr,
207 206 &sr->arg.dirop.fqi.fq_path.pn_path);
208 207
209 - DTRACE_SMB_2(op__DeleteDirectory__start, smb_request_t *, sr,
210 - struct dirop *, &sr->arg.dirop);
208 + DTRACE_SMB_START(op__DeleteDirectory, smb_request_t *, sr);
211 209
212 210 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
213 211 }
214 212
215 213 void
216 214 smb_post_delete_directory(smb_request_t *sr)
217 215 {
218 - DTRACE_SMB_1(op__DeleteDirectory__done, smb_request_t *, sr);
216 + DTRACE_SMB_DONE(op__DeleteDirectory, smb_request_t *, sr);
219 217 }
220 218
221 219 smb_sdrc_t
222 220 smb_com_delete_directory(smb_request_t *sr)
223 221 {
224 222 int rc;
225 223 uint32_t flags = 0;
226 224 smb_fqi_t *fqi;
227 225 smb_node_t *tnode;
228 226
229 227 if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
230 228 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
231 229 ERRDOS, ERROR_ACCESS_DENIED);
232 230 return (SDRC_ERROR);
233 231 }
234 232
235 233 fqi = &sr->arg.dirop.fqi;
236 234 tnode = sr->tid_tree->t_snode;
237 235
238 236 smb_pathname_init(sr, &fqi->fq_path, fqi->fq_path.pn_path);
239 237 if (!smb_pathname_validate(sr, &fqi->fq_path) ||
240 238 !smb_validate_dirname(sr, &fqi->fq_path)) {
241 239 return (SDRC_ERROR);
242 240 }
243 241
244 242 rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
245 243 tnode, tnode, &fqi->fq_dnode, fqi->fq_last_comp);
246 244
247 245 if (rc != 0) {
248 246 smbsr_errno(sr, rc);
249 247 return (SDRC_ERROR);
250 248 }
251 249
252 250 rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
253 251 tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
254 252 if (rc != 0) {
255 - if (rc == ENOENT)
256 - smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
257 - ERRDOS, ERROR_FILE_NOT_FOUND);
258 - else
259 - smbsr_errno(sr, rc);
253 + smbsr_errno(sr, rc);
260 254 smb_node_release(fqi->fq_dnode);
261 255 return (SDRC_ERROR);
262 256 }
263 257
264 258 /*
265 259 * Delete should fail if this is the root of a share
266 260 * or a DFS link
267 261 */
268 262 if ((fqi->fq_fnode == tnode) || smb_node_is_dfslink(fqi->fq_fnode)) {
269 263 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
270 264 ERRDOS, ERROR_ACCESS_DENIED);
271 265 smb_node_release(fqi->fq_dnode);
272 266 smb_node_release(fqi->fq_fnode);
273 267 return (SDRC_ERROR);
274 268 }
275 269
276 270 if (!smb_node_is_dir(fqi->fq_fnode)) {
277 271 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
278 272 ERRDOS, ERROR_PATH_NOT_FOUND);
279 273 smb_node_release(fqi->fq_dnode);
280 274 smb_node_release(fqi->fq_fnode);
281 275 return (SDRC_ERROR);
282 276 }
283 277
284 278 /*
285 279 * Using kcred because we just want the DOS attrs
286 280 * and don't want access errors for this.
287 281 */
288 282 fqi->fq_fattr.sa_mask = SMB_AT_DOSATTR;
289 283 rc = smb_node_getattr(sr, fqi->fq_fnode, zone_kcred(), NULL,
290 284 &fqi->fq_fattr);
291 285 if (rc != 0) {
292 286 smbsr_errno(sr, rc);
293 287 smb_node_release(fqi->fq_dnode);
294 288 smb_node_release(fqi->fq_fnode);
295 289 return (SDRC_ERROR);
296 290 }
297 291
298 292 if ((fqi->fq_fattr.sa_dosattr & FILE_ATTRIBUTE_READONLY) ||
299 293 (smb_fsop_access(sr, sr->user_cr, fqi->fq_fnode, DELETE)
300 294 != NT_STATUS_SUCCESS)) {
301 295 smbsr_error(sr, NT_STATUS_CANNOT_DELETE,
302 296 ERRDOS, ERROR_ACCESS_DENIED);
303 297 smb_node_release(fqi->fq_dnode);
304 298 smb_node_release(fqi->fq_fnode);
305 299 return (SDRC_ERROR);
306 300 }
307 301
308 302 if (SMB_TREE_SUPPORTS_CATIA(sr))
309 303 flags |= SMB_CATIA;
310 304
311 305 rc = smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
312 306 fqi->fq_fnode->od_name, flags);
313 307
314 308 smb_node_release(fqi->fq_fnode);
315 309 smb_node_release(fqi->fq_dnode);
316 310
317 311 if (rc != 0) {
318 312 if (rc == EEXIST)
319 313 smbsr_error(sr, NT_STATUS_DIRECTORY_NOT_EMPTY,
320 314 ERRDOS, ERROR_DIR_NOT_EMPTY);
321 315 else
322 316 smbsr_errno(sr, rc);
323 317 return (SDRC_ERROR);
324 318 }
325 319
326 320 rc = smbsr_encode_empty_result(sr);
327 321 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
328 322 }
329 323
330 324 /*
331 325 * This SMB is used to verify that a path exists and is a directory. No
332 326 * error is returned if the given path exists and the client has read
333 327 * access to it. Client machines which maintain a concept of a "working
334 328 * directory" will find this useful to verify the validity of a "change
335 329 * working directory" command. Note that the servers do NOT have a concept
336 330 * of working directory for a particular client. The client must always
337 331 * supply full pathnames relative to the Tid in the SMB header.
338 332 *
339 333 * Client Request Description
340 334 * ================================== =================================
341 335 *
342 336 * UCHAR WordCount; Count of parameter words = 0
343 337 * USHORT ByteCount; Count of data bytes; min = 2
344 338 * UCHAR BufferFormat; 0x04
345 339 * STRING DirectoryPath[]; Directory path
346 340 *
347 341 * Server Response Description
348 342 * ================================== =================================
349 343 *
350 344 * UCHAR WordCount; Count of parameter words = 0
351 345 * USHORT ByteCount; Count of data bytes = 0
352 346 *
353 347 * DOS clients, in particular, depend on ERRbadpath if the directory is
|
↓ open down ↓ |
84 lines elided |
↑ open up ↑ |
354 348 * not found.
355 349 */
356 350 smb_sdrc_t
357 351 smb_pre_check_directory(smb_request_t *sr)
358 352 {
359 353 int rc;
360 354
361 355 rc = smbsr_decode_data(sr, "%S", sr,
362 356 &sr->arg.dirop.fqi.fq_path.pn_path);
363 357
364 - DTRACE_SMB_2(op__CheckDirectory__start, smb_request_t *, sr,
365 - struct dirop *, &sr->arg.dirop);
358 + DTRACE_SMB_START(op__CheckDirectory, smb_request_t *, sr);
366 359
367 360 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
368 361 }
369 362
370 363 void
371 364 smb_post_check_directory(smb_request_t *sr)
372 365 {
373 - DTRACE_SMB_1(op__CheckDirectory__done, smb_request_t *, sr);
366 + DTRACE_SMB_DONE(op__CheckDirectory, smb_request_t *, sr);
374 367 }
375 368
376 369 smb_sdrc_t
377 370 smb_com_check_directory(smb_request_t *sr)
378 371 {
379 372 int rc;
380 373 smb_fqi_t *fqi;
381 374 smb_node_t *tnode;
382 375 smb_node_t *node;
383 376 char *path;
384 377 smb_pathname_t *pn;
385 378
386 379 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
387 380 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
388 381 ERROR_ACCESS_DENIED);
389 382 return (SDRC_ERROR);
390 383 }
391 384
392 385 fqi = &sr->arg.dirop.fqi;
393 386 pn = &fqi->fq_path;
394 387
395 388 if (pn->pn_path[0] == '\0') {
396 389 rc = smbsr_encode_empty_result(sr);
397 390 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
398 391 }
399 392
400 393 smb_pathname_init(sr, pn, pn->pn_path);
401 394 if (!smb_pathname_validate(sr, pn) ||
402 395 !smb_validate_dirname(sr, pn)) {
403 396 return (SDRC_ERROR);
404 397 }
405 398
406 399 path = pn->pn_path;
407 400 tnode = sr->tid_tree->t_snode;
408 401
409 402 rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode,
|
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
410 403 &fqi->fq_dnode, fqi->fq_last_comp);
411 404 if (rc != 0) {
412 405 smbsr_errno(sr, rc);
413 406 return (SDRC_ERROR);
414 407 }
415 408
416 409 rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
417 410 tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
418 411 smb_node_release(fqi->fq_dnode);
419 412 if (rc != 0) {
420 - if (rc == ENOENT)
421 - smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
422 - ERRDOS, ERROR_PATH_NOT_FOUND);
423 - else
424 - smbsr_errno(sr, rc);
413 + smbsr_errno(sr, rc);
425 414 return (SDRC_ERROR);
426 415 }
427 416
428 417 node = fqi->fq_fnode;
429 418 if (!smb_node_is_dir(node)) {
430 419 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
431 420 ERRDOS, ERROR_PATH_NOT_FOUND);
432 421 smb_node_release(node);
433 422 return (SDRC_ERROR);
434 423 }
435 424
436 425 if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
437 426 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
438 427 smb_node_release(node);
439 428 return (SDRC_ERROR);
440 429 }
441 430
442 431 rc = smb_fsop_access(sr, sr->user_cr, node, FILE_TRAVERSE);
443 432
444 433 smb_node_release(node);
445 434
446 435 if (rc != 0) {
447 436 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
448 437 ERRDOS, ERROR_ACCESS_DENIED);
449 438 return (SDRC_ERROR);
450 439 }
451 440
452 441 rc = smbsr_encode_empty_result(sr);
453 442 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
454 443 }
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX