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 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * This module provides the common open functionality to the various
28 * open and create SMB interface functions.
29 */
30
31 #include <sys/types.h>
32 #include <sys/cmn_err.h>
33 #include <sys/fcntl.h>
34 #include <sys/nbmlock.h>
35 #include <smbsrv/string.h>
36 #include <smbsrv/smb_kproto.h>
37 #include <smbsrv/smb_fsops.h>
38 #include <smbsrv/smbinfo.h>
39
40 volatile uint32_t smb_fids = 0;
41
42 static uint32_t smb_open_subr(smb_request_t *);
43 extern uint32_t smb_is_executable(char *);
44 static void smb_delete_new_object(smb_request_t *);
45 static int smb_set_open_timestamps(smb_request_t *, smb_ofile_t *, boolean_t);
46 static void smb_open_oplock_break(smb_request_t *, smb_node_t *);
47 static boolean_t smb_open_attr_only(smb_arg_open_t *);
48 static boolean_t smb_open_overwrite(smb_arg_open_t *);
49
50 /*
51 * smb_access_generic_to_file
52 *
53 * Search MSDN for IoCreateFile to see following mapping.
54 *
55 * GENERIC_READ STANDARD_RIGHTS_READ, FILE_READ_DATA,
56 * FILE_READ_ATTRIBUTES and FILE_READ_EA
57 *
58 * GENERIC_WRITE STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
59 * FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
60 *
61 * GENERIC_EXECUTE STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
62 */
63 uint32_t
smb_access_generic_to_file(uint32_t desired_access)64 smb_access_generic_to_file(uint32_t desired_access)
65 {
66 uint32_t access = 0;
67
68 if (desired_access & GENERIC_ALL)
69 return (FILE_ALL_ACCESS & ~SYNCHRONIZE);
70
71 if (desired_access & GENERIC_EXECUTE) {
72 desired_access &= ~GENERIC_EXECUTE;
73 access |= (STANDARD_RIGHTS_EXECUTE |
74 SYNCHRONIZE | FILE_EXECUTE);
75 }
76
77 if (desired_access & GENERIC_WRITE) {
78 desired_access &= ~GENERIC_WRITE;
79 access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE);
80 }
81
82 if (desired_access & GENERIC_READ) {
83 desired_access &= ~GENERIC_READ;
84 access |= FILE_GENERIC_READ;
85 }
86
87 return (access | desired_access);
88 }
89
90 /*
91 * smb_omode_to_amask
92 *
93 * This function converts open modes used by Open and Open AndX
94 * commands to desired access bits used by NT Create AndX command.
95 */
96 uint32_t
smb_omode_to_amask(uint32_t desired_access)97 smb_omode_to_amask(uint32_t desired_access)
98 {
99 switch (desired_access & SMB_DA_ACCESS_MASK) {
100 case SMB_DA_ACCESS_READ:
101 return (FILE_GENERIC_READ);
102
103 case SMB_DA_ACCESS_WRITE:
104 return (FILE_GENERIC_WRITE);
105
106 case SMB_DA_ACCESS_READ_WRITE:
107 return (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
108
109 case SMB_DA_ACCESS_EXECUTE:
110 return (FILE_GENERIC_EXECUTE);
111
112 default:
113 return (FILE_GENERIC_ALL);
114 }
115 }
116
117 /*
118 * smb_denymode_to_sharemode
119 *
120 * This function converts deny modes used by Open and Open AndX
121 * commands to share access bits used by NT Create AndX command.
122 */
123 uint32_t
smb_denymode_to_sharemode(uint32_t desired_access,char * fname)124 smb_denymode_to_sharemode(uint32_t desired_access, char *fname)
125 {
126 switch (desired_access & SMB_DA_SHARE_MASK) {
127 case SMB_DA_SHARE_COMPATIBILITY:
128 if (smb_is_executable(fname))
129 return (FILE_SHARE_READ | FILE_SHARE_WRITE);
130
131 return (FILE_SHARE_ALL);
132
133 case SMB_DA_SHARE_EXCLUSIVE:
134 return (FILE_SHARE_NONE);
135
136 case SMB_DA_SHARE_DENY_WRITE:
137 return (FILE_SHARE_READ);
138
139 case SMB_DA_SHARE_DENY_READ:
140 return (FILE_SHARE_WRITE);
141
142 case SMB_DA_SHARE_DENY_NONE:
143 default:
144 return (FILE_SHARE_READ | FILE_SHARE_WRITE);
145 }
146 }
147
148 /*
149 * smb_ofun_to_crdisposition
150 *
151 * This function converts open function values used by Open and Open AndX
152 * commands to create disposition values used by NT Create AndX command.
153 */
154 uint32_t
smb_ofun_to_crdisposition(uint16_t ofun)155 smb_ofun_to_crdisposition(uint16_t ofun)
156 {
157 static int ofun_cr_map[3][2] =
158 {
159 { -1, FILE_CREATE },
160 { FILE_OPEN, FILE_OPEN_IF },
161 { FILE_OVERWRITE, FILE_OVERWRITE_IF }
162 };
163
164 int row = ofun & SMB_OFUN_OPEN_MASK;
165 int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4;
166
167 if (row == 3)
168 return (FILE_MAXIMUM_DISPOSITION + 1);
169
170 return (ofun_cr_map[row][col]);
171 }
172
173 /*
174 * Retry opens to avoid spurious sharing violations, due to timing
175 * issues between closes and opens. The client that already has the
176 * file open may be in the process of closing it.
177 */
178 uint32_t
smb_common_open(smb_request_t * sr)179 smb_common_open(smb_request_t *sr)
180 {
181 smb_arg_open_t *parg;
182 uint32_t status = NT_STATUS_SUCCESS;
183 int count;
184
185 parg = kmem_alloc(sizeof (*parg), KM_SLEEP);
186 bcopy(&sr->arg.open, parg, sizeof (*parg));
187
188 for (count = 0; count <= 4; count++) {
189 if (count != 0)
190 delay(MSEC_TO_TICK(400));
191
192 status = smb_open_subr(sr);
193 if (status != NT_STATUS_SHARING_VIOLATION)
194 break;
195
196 bcopy(parg, &sr->arg.open, sizeof (*parg));
197 }
198
199 if (status == NT_STATUS_SHARING_VIOLATION) {
200 smbsr_error(sr, NT_STATUS_SHARING_VIOLATION,
201 ERRDOS, ERROR_SHARING_VIOLATION);
202 }
203
204 if (status == NT_STATUS_NO_SUCH_FILE) {
205 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
206 ERRDOS, ERROR_FILE_NOT_FOUND);
207 }
208
209 kmem_free(parg, sizeof (*parg));
210 return (status);
211 }
212
213 /*
214 * smb_open_subr
215 *
216 * Notes on write-through behaviour. It looks like pre-LM0.12 versions
217 * of the protocol specify the write-through mode when a file is opened,
218 * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose,
219 * SmbWriteAndUnlock) don't need to contain a write-through flag.
220 *
221 * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate)
222 * don't indicate which write-through mode to use. Instead the write
223 * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call
224 * basis.
225 *
226 * We don't care which open call was used to get us here, we just need
227 * to ensure that the write-through mode flag is copied from the open
228 * parameters to the node. We test the omode write-through flag in all
229 * write functions.
230 *
231 * This function will return NT status codes but it also raises errors,
232 * in which case it won't return to the caller. Be careful how you
233 * handle things in here.
234 *
235 * The following rules apply when processing a file open request:
236 *
237 * - Oplocks must be broken prior to share checking as the break may
238 * cause other clients to close the file, which would affect sharing
239 * checks.
240 *
241 * - Share checks must take place prior to access checks for correct
242 * Windows semantics and to prevent unnecessary NFS delegation recalls.
243 *
244 * - Oplocks must be acquired after open to ensure the correct
245 * synchronization with NFS delegation and FEM installation.
246 *
247 * DOS readonly bit rules
248 *
249 * 1. The creator of a readonly file can write to/modify the size of the file
250 * using the original create fid, even though the file will appear as readonly
251 * to all other fids and via a CIFS getattr call.
252 * The readonly bit therefore cannot be set in the filesystem until the file
253 * is closed (smb_ofile_close). It is accounted for via ofile and node flags.
254 *
255 * 2. A setinfo operation (using either an open fid or a path) to set/unset
256 * readonly will be successful regardless of whether a creator of a readonly
257 * file has an open fid (and has the special privilege mentioned in #1,
258 * above). I.e., the creator of a readonly fid holding that fid will no longer
259 * have a special privilege.
260 *
261 * 3. The DOS readonly bit affects only data and some metadata.
262 * The following metadata can be changed regardless of the readonly bit:
263 * - security descriptors
264 * - DOS attributes
265 * - timestamps
266 *
267 * In the current implementation, the file size cannot be changed (except for
268 * the exceptions in #1 and #2, above).
269 *
270 *
271 * DOS attribute rules
272 *
273 * These rules are specific to creating / opening files and directories.
274 * How the attribute value (specifically ZERO or FILE_ATTRIBUTE_NORMAL)
275 * should be interpreted may differ in other requests.
276 *
277 * - An attribute value equal to ZERO or FILE_ATTRIBUTE_NORMAL means that the
278 * file's attributes should be cleared.
279 * - If FILE_ATTRIBUTE_NORMAL is specified with any other attributes,
280 * FILE_ATTRIBUTE_NORMAL is ignored.
281 *
282 * 1. Creating a new file
283 * - The request attributes + FILE_ATTRIBUTE_ARCHIVE are applied to the file.
284 *
285 * 2. Creating a new directory
286 * - The request attributes + FILE_ATTRIBUTE_DIRECTORY are applied to the file.
287 * - FILE_ATTRIBUTE_ARCHIVE does not get set.
288 *
289 * 3. Overwriting an existing file
290 * - the request attributes are used as search attributes. If the existing
291 * file does not meet the search criteria access is denied.
292 * - otherwise, applies attributes + FILE_ATTRIBUTE_ARCHIVE.
293 *
294 * 4. Opening an existing file or directory
295 * The request attributes are ignored.
296 */
297 static uint32_t
smb_open_subr(smb_request_t * sr)298 smb_open_subr(smb_request_t *sr)
299 {
300 boolean_t created = B_FALSE;
301 boolean_t last_comp_found = B_FALSE;
302 smb_node_t *node = NULL;
303 smb_node_t *dnode = NULL;
304 smb_node_t *cur_node = NULL;
305 smb_arg_open_t *op = &sr->sr_open;
306 int rc;
307 smb_ofile_t *of;
308 smb_attr_t new_attr;
309 int max_requested = 0;
310 uint32_t max_allowed;
311 uint32_t status = NT_STATUS_SUCCESS;
312 int is_dir;
313 smb_error_t err;
314 boolean_t is_stream = B_FALSE;
315 int lookup_flags = SMB_FOLLOW_LINKS;
316 uint32_t uniq_fid;
317 smb_pathname_t *pn = &op->fqi.fq_path;
318 smb_server_t *sv = sr->sr_server;
319
320 is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
321
322 /*
323 * If the object being created or opened is a directory
324 * the Disposition parameter must be one of FILE_CREATE,
325 * FILE_OPEN, or FILE_OPEN_IF
326 */
327 if (is_dir) {
328 if ((op->create_disposition != FILE_CREATE) &&
329 (op->create_disposition != FILE_OPEN_IF) &&
330 (op->create_disposition != FILE_OPEN)) {
331 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
332 ERRDOS, ERROR_INVALID_ACCESS);
333 return (NT_STATUS_INVALID_PARAMETER);
334 }
335 }
336
337 if (op->desired_access & MAXIMUM_ALLOWED) {
338 max_requested = 1;
339 op->desired_access &= ~MAXIMUM_ALLOWED;
340 }
341 op->desired_access = smb_access_generic_to_file(op->desired_access);
342
343 if (sr->session->s_file_cnt >= SMB_SESSION_OFILE_MAX) {
344 ASSERT(sr->uid_user);
345 cmn_err(CE_NOTE, "smbsrv[%s\\%s]: TOO_MANY_OPENED_FILES",
346 sr->uid_user->u_domain, sr->uid_user->u_name);
347
348 smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
349 ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
350 return (NT_STATUS_TOO_MANY_OPENED_FILES);
351 }
352
353 /* This must be NULL at this point */
354 sr->fid_ofile = NULL;
355
356 op->devstate = 0;
357
358 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
359 case STYPE_DISKTREE:
360 case STYPE_PRINTQ:
361 break;
362
363 case STYPE_IPC:
364
365 if ((rc = smb_threshold_enter(&sv->sv_opipe_ct)) != 0) {
366 status = RPC_NT_SERVER_TOO_BUSY;
367 smbsr_error(sr, status, 0, 0);
368 return (status);
369 }
370
371 /*
372 * No further processing for IPC, we need to either
373 * raise an exception or return success here.
374 */
375 if ((status = smb_opipe_open(sr)) != NT_STATUS_SUCCESS)
376 smbsr_error(sr, status, 0, 0);
377
378 smb_threshold_exit(&sv->sv_opipe_ct, sv);
379 return (status);
380
381 default:
382 smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
383 ERRDOS, ERROR_BAD_DEV_TYPE);
384 return (NT_STATUS_BAD_DEVICE_TYPE);
385 }
386
387 smb_pathname_init(sr, pn, pn->pn_path);
388 if (!smb_pathname_validate(sr, pn))
389 return (sr->smb_error.status);
390
391 if (strlen(pn->pn_path) >= MAXPATHLEN) {
392 smbsr_error(sr, 0, ERRSRV, ERRfilespecs);
393 return (NT_STATUS_NAME_TOO_LONG);
394 }
395
396 if (is_dir) {
397 if (!smb_validate_dirname(sr, pn))
398 return (sr->smb_error.status);
399 } else {
400 if (!smb_validate_object_name(sr, pn))
401 return (sr->smb_error.status);
402 }
403
404 cur_node = op->fqi.fq_dnode ?
405 op->fqi.fq_dnode : sr->tid_tree->t_snode;
406
407 /*
408 * if no path or filename are specified the stream should be
409 * created on cur_node
410 */
411 if (!is_dir && !pn->pn_pname && !pn->pn_fname && pn->pn_sname) {
412 /*
413 * Can't currently handle a stream on the tree root.
414 * If a stream is being opened return "not found", otherwise
415 * return "access denied".
416 */
417 if (cur_node == sr->tid_tree->t_snode) {
418 if (op->create_disposition == FILE_OPEN) {
419 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
420 ERRDOS, ERROR_FILE_NOT_FOUND);
421 return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
422 }
423 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
424 ERROR_ACCESS_DENIED);
425 return (NT_STATUS_ACCESS_DENIED);
426 }
427
428 (void) snprintf(op->fqi.fq_last_comp,
429 sizeof (op->fqi.fq_last_comp),
430 "%s%s", cur_node->od_name, pn->pn_sname);
431
432 op->fqi.fq_dnode = cur_node->n_dnode;
433 smb_node_ref(op->fqi.fq_dnode);
434 } else {
435 if (rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
436 sr->tid_tree->t_snode, cur_node, &op->fqi.fq_dnode,
437 op->fqi.fq_last_comp)) {
438 smbsr_errno(sr, rc);
439 return (sr->smb_error.status);
440 }
441 }
442
443 /*
444 * If the access mask has only DELETE set (ignore
445 * FILE_READ_ATTRIBUTES), then assume that this
446 * is a request to delete the link (if a link)
447 * and do not follow links. Otherwise, follow
448 * the link to the target.
449 */
450 if ((op->desired_access & ~FILE_READ_ATTRIBUTES) == DELETE)
451 lookup_flags &= ~SMB_FOLLOW_LINKS;
452
453 rc = smb_fsop_lookup_name(sr, kcred, lookup_flags,
454 sr->tid_tree->t_snode, op->fqi.fq_dnode, op->fqi.fq_last_comp,
455 &op->fqi.fq_fnode);
456
457 if (rc == 0) {
458 last_comp_found = B_TRUE;
459 rc = smb_node_getattr(sr, op->fqi.fq_fnode,
460 &op->fqi.fq_fattr);
461 if (rc != 0) {
462 smb_node_release(op->fqi.fq_fnode);
463 smb_node_release(op->fqi.fq_dnode);
464 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
465 ERRDOS, ERROR_INTERNAL_ERROR);
466 return (sr->smb_error.status);
467 }
468 } else if (rc == ENOENT) {
469 last_comp_found = B_FALSE;
470 op->fqi.fq_fnode = NULL;
471 rc = 0;
472 } else {
473 smb_node_release(op->fqi.fq_dnode);
474 smbsr_errno(sr, rc);
475 return (sr->smb_error.status);
476 }
477
478
479 /*
480 * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
481 * which is used to uniquely identify open instances for the
482 * VFS share reservation and POSIX locks.
483 */
484
485 uniq_fid = SMB_UNIQ_FID();
486
487 if (last_comp_found) {
488
489 node = op->fqi.fq_fnode;
490 dnode = op->fqi.fq_dnode;
491
492 if (!smb_node_is_file(node) && !smb_node_is_dir(node) &&
493 !smb_node_is_symlink(node)) {
494 smb_node_release(node);
495 smb_node_release(dnode);
496 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
497 ERRnoaccess);
498 return (NT_STATUS_ACCESS_DENIED);
499 }
500
501 /*
502 * Reject this request if either:
503 * - the target IS a directory and the client requires that
504 * it must NOT be (required by Lotus Notes)
505 * - the target is NOT a directory and client requires that
506 * it MUST be.
507 */
508 if (smb_node_is_dir(node)) {
509 if (op->create_options & FILE_NON_DIRECTORY_FILE) {
510 smb_node_release(node);
511 smb_node_release(dnode);
512 smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY,
513 ERRDOS, ERROR_ACCESS_DENIED);
514 return (NT_STATUS_FILE_IS_A_DIRECTORY);
515 }
516 } else {
517 if ((op->create_options & FILE_DIRECTORY_FILE) ||
518 (op->nt_flags & NT_CREATE_FLAG_OPEN_TARGET_DIR)) {
519 smb_node_release(node);
520 smb_node_release(dnode);
521 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
522 ERRDOS, ERROR_DIRECTORY);
523 return (NT_STATUS_NOT_A_DIRECTORY);
524 }
525 }
526
527 /*
528 * No more open should be accepted when "Delete on close"
529 * flag is set.
530 */
531 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
532 smb_node_release(node);
533 smb_node_release(dnode);
534 smbsr_error(sr, NT_STATUS_DELETE_PENDING,
535 ERRDOS, ERROR_ACCESS_DENIED);
536 return (NT_STATUS_DELETE_PENDING);
537 }
538
539 /*
540 * Specified file already exists so the operation should fail.
541 */
542 if (op->create_disposition == FILE_CREATE) {
543 smb_node_release(node);
544 smb_node_release(dnode);
545 smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION,
546 ERRDOS, ERROR_FILE_EXISTS);
547 return (NT_STATUS_OBJECT_NAME_COLLISION);
548 }
549
550 /*
551 * Windows seems to check read-only access before file
552 * sharing check.
553 *
554 * Check to see if the file is currently readonly (irrespective
555 * of whether this open will make it readonly).
556 */
557 if (SMB_PATHFILE_IS_READONLY(sr, node)) {
558 /* Files data only */
559 if (!smb_node_is_dir(node)) {
560 if (op->desired_access & (FILE_WRITE_DATA |
561 FILE_APPEND_DATA)) {
562 smb_node_release(node);
563 smb_node_release(dnode);
564 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
565 ERRDOS, ERRnoaccess);
566 return (NT_STATUS_ACCESS_DENIED);
567 }
568 }
569 }
570
571 /*
572 * Oplock break is done prior to sharing checks as the break
573 * may cause other clients to close the file which would
574 * affect the sharing checks.
575 */
576 smb_node_inc_opening_count(node);
577 smb_open_oplock_break(sr, node);
578
579 smb_node_wrlock(node);
580
581 if ((op->create_disposition == FILE_SUPERSEDE) ||
582 (op->create_disposition == FILE_OVERWRITE_IF) ||
583 (op->create_disposition == FILE_OVERWRITE)) {
584
585 if ((!(op->desired_access &
586 (FILE_WRITE_DATA | FILE_APPEND_DATA |
587 FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA))) ||
588 (!smb_sattr_check(op->fqi.fq_fattr.sa_dosattr,
589 op->dattr))) {
590 smb_node_unlock(node);
591 smb_node_dec_opening_count(node);
592 smb_node_release(node);
593 smb_node_release(dnode);
594 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
595 ERRDOS, ERRnoaccess);
596 return (NT_STATUS_ACCESS_DENIED);
597 }
598 }
599
600 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
601 op->desired_access, op->share_access);
602
603 if (status == NT_STATUS_SHARING_VIOLATION) {
604 smb_node_unlock(node);
605 smb_node_dec_opening_count(node);
606 smb_node_release(node);
607 smb_node_release(dnode);
608 return (status);
609 }
610
611 status = smb_fsop_access(sr, sr->user_cr, node,
612 op->desired_access);
613
614 if (status != NT_STATUS_SUCCESS) {
615 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
616
617 smb_node_unlock(node);
618 smb_node_dec_opening_count(node);
619 smb_node_release(node);
620 smb_node_release(dnode);
621
622 if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
623 smbsr_error(sr, status,
624 ERRDOS, ERROR_PRIVILEGE_NOT_HELD);
625 return (status);
626 } else {
627 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
628 ERRDOS, ERROR_ACCESS_DENIED);
629 return (NT_STATUS_ACCESS_DENIED);
630 }
631 }
632
633 switch (op->create_disposition) {
634 case FILE_SUPERSEDE:
635 case FILE_OVERWRITE_IF:
636 case FILE_OVERWRITE:
637 if (smb_node_is_dir(node)) {
638 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
639 smb_node_unlock(node);
640 smb_node_dec_opening_count(node);
641 smb_node_release(node);
642 smb_node_release(dnode);
643 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
644 ERRDOS, ERROR_ACCESS_DENIED);
645 return (NT_STATUS_ACCESS_DENIED);
646 }
647
648 op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
649 /* Don't apply readonly bit until smb_ofile_close */
650 if (op->dattr & FILE_ATTRIBUTE_READONLY) {
651 op->created_readonly = B_TRUE;
652 op->dattr &= ~FILE_ATTRIBUTE_READONLY;
653 }
654
655 bzero(&new_attr, sizeof (new_attr));
656 new_attr.sa_dosattr = op->dattr;
657 new_attr.sa_vattr.va_size = op->dsize;
658 new_attr.sa_mask = SMB_AT_DOSATTR | SMB_AT_SIZE;
659 rc = smb_fsop_setattr(sr, sr->user_cr, node, &new_attr);
660 if (rc != 0) {
661 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
662 smb_node_unlock(node);
663 smb_node_dec_opening_count(node);
664 smb_node_release(node);
665 smb_node_release(dnode);
666 smbsr_errno(sr, rc);
667 return (sr->smb_error.status);
668 }
669
670 /*
671 * If file is being replaced, remove existing streams
672 */
673 if (SMB_IS_STREAM(node) == 0) {
674 rc = smb_fsop_remove_streams(sr, sr->user_cr,
675 node);
676 if (rc != 0) {
677 smb_fsop_unshrlock(sr->user_cr, node,
678 uniq_fid);
679 smb_node_unlock(node);
680 smb_node_dec_opening_count(node);
681 smb_node_release(node);
682 smb_node_release(dnode);
683 return (sr->smb_error.status);
684 }
685 }
686
687 op->action_taken = SMB_OACT_TRUNCATED;
688 break;
689
690 default:
691 /*
692 * FILE_OPEN or FILE_OPEN_IF.
693 */
694 op->action_taken = SMB_OACT_OPENED;
695 break;
696 }
697 } else {
698 /* Last component was not found. */
699 dnode = op->fqi.fq_dnode;
700
701 if (is_dir == 0)
702 is_stream = smb_is_stream_name(pn->pn_path);
703
704 if ((op->create_disposition == FILE_OPEN) ||
705 (op->create_disposition == FILE_OVERWRITE)) {
706 smb_node_release(dnode);
707 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
708 ERRDOS, ERROR_FILE_NOT_FOUND);
709 return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
710 }
711
712 if (pn->pn_fname && smb_is_invalid_filename(pn->pn_fname)) {
713 smb_node_release(dnode);
714 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
715 ERRDOS, ERROR_INVALID_NAME);
716 return (NT_STATUS_OBJECT_NAME_INVALID);
717 }
718
719 /*
720 * lock the parent dir node in case another create
721 * request to the same parent directory comes in.
722 */
723 smb_node_wrlock(dnode);
724
725 /* Don't apply readonly bit until smb_ofile_close */
726 if (op->dattr & FILE_ATTRIBUTE_READONLY) {
727 op->dattr &= ~FILE_ATTRIBUTE_READONLY;
728 op->created_readonly = B_TRUE;
729 }
730
731 bzero(&new_attr, sizeof (new_attr));
732 if ((op->crtime.tv_sec != 0) &&
733 (op->crtime.tv_sec != UINT_MAX)) {
734
735 new_attr.sa_mask |= SMB_AT_CRTIME;
736 new_attr.sa_crtime = op->crtime;
737 }
738
739 if (is_dir == 0) {
740 op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
741 new_attr.sa_dosattr = op->dattr;
742 new_attr.sa_vattr.va_type = VREG;
743 new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR :
744 S_IRUSR | S_IRGRP | S_IROTH |
745 S_IWUSR | S_IWGRP | S_IWOTH;
746 new_attr.sa_mask |=
747 SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
748
749 if (op->dsize) {
750 new_attr.sa_vattr.va_size = op->dsize;
751 new_attr.sa_mask |= SMB_AT_SIZE;
752 }
753
754 rc = smb_fsop_create(sr, sr->user_cr, dnode,
755 op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
756
757 if (rc != 0) {
758 smb_node_unlock(dnode);
759 smb_node_release(dnode);
760 smbsr_errno(sr, rc);
761 return (sr->smb_error.status);
762 }
763
764 node = op->fqi.fq_fnode;
765 smb_node_inc_opening_count(node);
766 smb_node_wrlock(node);
767
768 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
769 op->desired_access, op->share_access);
770
771 if (status == NT_STATUS_SHARING_VIOLATION) {
772 smb_node_unlock(node);
773 smb_node_dec_opening_count(node);
774 smb_delete_new_object(sr);
775 smb_node_release(node);
776 smb_node_unlock(dnode);
777 smb_node_release(dnode);
778 return (status);
779 }
780 } else {
781 op->dattr |= FILE_ATTRIBUTE_DIRECTORY;
782 new_attr.sa_dosattr = op->dattr;
783 new_attr.sa_vattr.va_type = VDIR;
784 new_attr.sa_vattr.va_mode = 0777;
785 new_attr.sa_mask |=
786 SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
787
788 rc = smb_fsop_mkdir(sr, sr->user_cr, dnode,
789 op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
790 if (rc != 0) {
791 smb_node_unlock(dnode);
792 smb_node_release(dnode);
793 smbsr_errno(sr, rc);
794 return (sr->smb_error.status);
795 }
796
797 node = op->fqi.fq_fnode;
798 smb_node_inc_opening_count(node);
799 smb_node_wrlock(node);
800 }
801
802 created = B_TRUE;
803 op->action_taken = SMB_OACT_CREATED;
804 }
805
806 if (max_requested) {
807 smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
808 op->desired_access |= max_allowed;
809 }
810
811 status = NT_STATUS_SUCCESS;
812
813 of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op, SMB_FTYPE_DISK,
814 uniq_fid, &err);
815 if (of == NULL) {
816 smbsr_error(sr, err.status, err.errcls, err.errcode);
817 status = err.status;
818 }
819
820 if (status == NT_STATUS_SUCCESS) {
821 if (!smb_tree_is_connected(sr->tid_tree)) {
822 smbsr_error(sr, 0, ERRSRV, ERRinvnid);
823 status = NT_STATUS_UNSUCCESSFUL;
824 }
825 }
826
827 /*
828 * This MUST be done after ofile creation, so that explicitly
829 * set timestamps can be remembered on the ofile.
830 */
831 if (status == NT_STATUS_SUCCESS) {
832 if ((rc = smb_set_open_timestamps(sr, of, created)) != 0) {
833 smbsr_errno(sr, rc);
834 status = sr->smb_error.status;
835 }
836 }
837
838 if (status == NT_STATUS_SUCCESS) {
839 if (smb_node_getattr(sr, node, &op->fqi.fq_fattr) != 0) {
840 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
841 ERRDOS, ERROR_INTERNAL_ERROR);
842 status = NT_STATUS_INTERNAL_ERROR;
843 }
844 }
845
846 /*
847 * smb_fsop_unshrlock is a no-op if node is a directory
848 * smb_fsop_unshrlock is done in smb_ofile_close
849 */
850 if (status != NT_STATUS_SUCCESS) {
851 if (of == NULL) {
852 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
853 } else {
854 smb_ofile_close(of, 0);
855 smb_ofile_release(of);
856 }
857 if (created)
858 smb_delete_new_object(sr);
859 smb_node_unlock(node);
860 smb_node_dec_opening_count(node);
861 smb_node_release(node);
862 if (created)
863 smb_node_unlock(dnode);
864 smb_node_release(dnode);
865 return (status);
866 }
867
868 /*
869 * Propagate the write-through mode from the open params
870 * to the node: see the notes in the function header.
871 */
872 if (sr->sr_cfg->skc_sync_enable ||
873 (op->create_options & FILE_WRITE_THROUGH))
874 node->flags |= NODE_FLAGS_WRITE_THROUGH;
875
876 /*
877 * Set up the fileid and dosattr in open_param for response
878 */
879 op->fileid = op->fqi.fq_fattr.sa_vattr.va_nodeid;
880 op->dattr = op->fqi.fq_fattr.sa_dosattr;
881
882 /*
883 * Set up the file type in open_param for the response
884 */
885 op->ftype = SMB_FTYPE_DISK;
886 sr->smb_fid = of->f_fid;
887 sr->fid_ofile = of;
888
889 if (smb_node_is_file(node)) {
890 smb_oplock_acquire(sr, node, of);
891 op->dsize = op->fqi.fq_fattr.sa_vattr.va_size;
892 } else {
893 /* directory or symlink */
894 op->op_oplock_level = SMB_OPLOCK_NONE;
895 op->dsize = 0;
896 }
897
898 smb_node_dec_opening_count(node);
899
900 smb_node_unlock(node);
901 if (created)
902 smb_node_unlock(dnode);
903
904 smb_node_release(node);
905 smb_node_release(dnode);
906
907 return (NT_STATUS_SUCCESS);
908 }
909
910 /*
911 * smb_open_oplock_break
912 *
913 * If the node has an ofile opened with share access none,
914 * (smb_node_share_check = FALSE) only break BATCH oplock.
915 * Otherwise:
916 * If overwriting, break to SMB_OPLOCK_NONE, else
917 * If opening for anything other than attribute access,
918 * break oplock to LEVEL_II.
919 */
920 static void
smb_open_oplock_break(smb_request_t * sr,smb_node_t * node)921 smb_open_oplock_break(smb_request_t *sr, smb_node_t *node)
922 {
923 smb_arg_open_t *op = &sr->sr_open;
924 uint32_t flags = 0;
925
926 if (!smb_node_share_check(node))
927 flags |= SMB_OPLOCK_BREAK_BATCH;
928
929 if (smb_open_overwrite(op)) {
930 flags |= SMB_OPLOCK_BREAK_TO_NONE;
931 (void) smb_oplock_break(sr, node, flags);
932 } else if (!smb_open_attr_only(op)) {
933 flags |= SMB_OPLOCK_BREAK_TO_LEVEL_II;
934 (void) smb_oplock_break(sr, node, flags);
935 }
936 }
937
938 /*
939 * smb_open_attr_only
940 *
941 * Determine if file is being opened for attribute access only.
942 * This is used to determine whether it is necessary to break
943 * existing oplocks on the file.
944 */
945 static boolean_t
smb_open_attr_only(smb_arg_open_t * op)946 smb_open_attr_only(smb_arg_open_t *op)
947 {
948 if (((op->desired_access & ~(FILE_READ_ATTRIBUTES |
949 FILE_WRITE_ATTRIBUTES | SYNCHRONIZE)) == 0) &&
950 (op->create_disposition != FILE_SUPERSEDE) &&
951 (op->create_disposition != FILE_OVERWRITE)) {
952 return (B_TRUE);
953 }
954 return (B_FALSE);
955 }
956
957 static boolean_t
smb_open_overwrite(smb_arg_open_t * op)958 smb_open_overwrite(smb_arg_open_t *op)
959 {
960 if ((op->create_disposition == FILE_SUPERSEDE) ||
961 (op->create_disposition == FILE_OVERWRITE_IF) ||
962 (op->create_disposition == FILE_OVERWRITE)) {
963 return (B_TRUE);
964 }
965 return (B_FALSE);
966 }
967 /*
968 * smb_set_open_timestamps
969 *
970 * Last write time:
971 * - If the last_write time specified in the open params is not 0 or -1,
972 * use it as file's mtime. This will be considered an explicitly set
973 * timestamps, not reset by subsequent writes.
974 *
975 * Opening existing file (not directory):
976 * - If opening an existing file for overwrite set initial ATIME, MTIME
977 * & CTIME to now. (This is achieved by setting them as pending then forcing
978 * an smb_node_setattr() to apply pending times.)
979 *
980 * - Note If opening an existing file NOT for overwrite, windows would
981 * set the atime on file close, however setting the atime would cause
982 * the ARCHIVE attribute to be set, which does not occur on windows,
983 * so we do not do the atime update.
984 *
985 * Returns: errno
986 */
987 static int
smb_set_open_timestamps(smb_request_t * sr,smb_ofile_t * of,boolean_t created)988 smb_set_open_timestamps(smb_request_t *sr, smb_ofile_t *of, boolean_t created)
989 {
990 int rc = 0;
991 smb_arg_open_t *op = &sr->sr_open;
992 smb_node_t *node = of->f_node;
993 boolean_t existing_file, set_times;
994 smb_attr_t attr;
995
996 bzero(&attr, sizeof (smb_attr_t));
997 set_times = B_FALSE;
998
999 if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
1000 attr.sa_mask = SMB_AT_MTIME;
1001 attr.sa_vattr.va_mtime = op->mtime;
1002 set_times = B_TRUE;
1003 }
1004
1005 existing_file = !(created || smb_node_is_dir(node));
1006 if (existing_file) {
1007 switch (op->create_disposition) {
1008 case FILE_SUPERSEDE:
1009 case FILE_OVERWRITE_IF:
1010 case FILE_OVERWRITE:
1011 smb_ofile_set_write_time_pending(of);
1012 set_times = B_TRUE;
1013 break;
1014 default:
1015 break;
1016 }
1017 }
1018
1019 if (set_times)
1020 rc = smb_node_setattr(sr, node, sr->user_cr, of, &attr);
1021
1022 return (rc);
1023 }
1024
1025 /*
1026 * This function is used to delete a newly created object (file or
1027 * directory) if an error occurs after creation of the object.
1028 */
1029 static void
smb_delete_new_object(smb_request_t * sr)1030 smb_delete_new_object(smb_request_t *sr)
1031 {
1032 smb_arg_open_t *op = &sr->sr_open;
1033 smb_fqi_t *fqi = &(op->fqi);
1034 uint32_t flags = 0;
1035
1036 if (SMB_TREE_IS_CASEINSENSITIVE(sr))
1037 flags |= SMB_IGNORE_CASE;
1038 if (SMB_TREE_SUPPORTS_CATIA(sr))
1039 flags |= SMB_CATIA;
1040
1041 if (op->create_options & FILE_DIRECTORY_FILE)
1042 (void) smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
1043 fqi->fq_last_comp, flags);
1044 else
1045 (void) smb_fsop_remove(sr, sr->user_cr, fqi->fq_dnode,
1046 fqi->fq_last_comp, flags);
1047 }
1048