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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This module provides the common open functionality to the various 30 * open and create SMB interface functions. 31 */ 32 33 #include <smbsrv/smb_incl.h> 34 #include <smbsrv/smb_fsops.h> 35 #include <smbsrv/mlsvc.h> 36 #include <smbsrv/nterror.h> 37 #include <smbsrv/ntstatus.h> 38 #include <smbsrv/smbinfo.h> 39 #include <sys/fcntl.h> 40 41 extern uint32_t smb_is_executable(char *path); 42 43 #define DENY_READ(share_access) ((share_access & FILE_SHARE_READ) == 0) 44 45 #define DENY_WRITE(share_access) ((share_access & FILE_SHARE_WRITE) == 0) 46 47 #define DENY_DELETE(share_access) ((share_access & FILE_SHARE_DELETE) == 0) 48 49 #define DENY_RW(share_access) \ 50 ((share_access & (FILE_SHARE_READ | FILE_SHARE_WRITE)) == 0) 51 52 #define DENY_ALL(share_access) (share_access == 0) 53 54 #define DENY_NONE(share_access) (share_access == FILE_SHARE_ALL) 55 56 /* 57 * The default stability mode is to perform the write-through 58 * behaviour requested by the client. 59 */ 60 int smb_stable_mode = 0; 61 62 63 /* 64 * This macro is used to delete a newly created object 65 * if any error happens after creation of object. 66 */ 67 #define SMB_DEL_NEWOBJ(obj) \ 68 if (created) { \ 69 if (is_dir) \ 70 (void) smb_fsop_rmdir(sr, sr->user_cr, \ 71 obj.dir_snode, obj.last_comp, 0); \ 72 else \ 73 (void) smb_fsop_remove(sr, sr->user_cr, \ 74 obj.dir_snode, obj.last_comp, 0); \ 75 } 76 77 /* 78 * smb_set_stability 79 * 80 * Set the default stability mode. Normal (mode is zero) means perform 81 * the write-through behaviour requested by the client. Synchronous 82 * (mode is non-zero) means journal everything regardless of the write 83 * through behaviour requested by the client. 84 */ 85 void 86 smb_set_stability(int mode) 87 { 88 smb_stable_mode = mode; 89 } 90 91 /* 92 * smb_access_generic_to_file 93 * 94 * Search MSDN for IoCreateFile to see following mapping. 95 * 96 * GENERIC_READ STANDARD_RIGHTS_READ, FILE_READ_DATA, 97 * FILE_READ_ATTRIBUTES and FILE_READ_EA 98 * 99 * GENERIC_WRITE STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA, 100 * FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA 101 * 102 * GENERIC_EXECUTE STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE. 103 */ 104 uint32_t 105 smb_access_generic_to_file(uint32_t desired_access) 106 { 107 uint32_t access = 0; 108 109 if (desired_access & GENERIC_ALL) 110 return (FILE_ALL_ACCESS & ~SYNCHRONIZE); 111 112 if (desired_access & GENERIC_EXECUTE) { 113 desired_access &= ~GENERIC_EXECUTE; 114 access |= (STANDARD_RIGHTS_EXECUTE | 115 SYNCHRONIZE | FILE_EXECUTE); 116 } 117 118 if (desired_access & GENERIC_WRITE) { 119 desired_access &= ~GENERIC_WRITE; 120 access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE); 121 } 122 123 if (desired_access & GENERIC_READ) { 124 desired_access &= ~GENERIC_READ; 125 access |= FILE_GENERIC_READ; 126 } 127 128 return (access | desired_access); 129 } 130 131 /* 132 * smb_omode_to_amask 133 * 134 * This function converts open modes used by Open and Open AndX 135 * commands to desired access bits used by NT Create AndX command. 136 */ 137 uint32_t 138 smb_omode_to_amask(uint32_t desired_access) 139 { 140 switch (desired_access & SMB_DA_ACCESS_MASK) { 141 case SMB_DA_ACCESS_READ: 142 return (FILE_GENERIC_READ); 143 144 case SMB_DA_ACCESS_WRITE: 145 return (FILE_GENERIC_WRITE); 146 147 case SMB_DA_ACCESS_READ_WRITE: 148 return (FILE_GENERIC_READ | FILE_GENERIC_WRITE); 149 150 case SMB_DA_ACCESS_EXECUTE: 151 return (FILE_GENERIC_EXECUTE); 152 } 153 154 /* invalid open mode */ 155 return ((uint32_t)SMB_INVALID_AMASK); 156 } 157 158 /* 159 * smb_denymode_to_sharemode 160 * 161 * This function converts deny modes used by Open and Open AndX 162 * commands to share access bits used by NT Create AndX command. 163 */ 164 uint32_t 165 smb_denymode_to_sharemode(uint32_t desired_access, char *fname) 166 { 167 switch (desired_access & SMB_DA_SHARE_MASK) { 168 case SMB_DA_SHARE_COMPATIBILITY: 169 if (smb_is_executable(fname)) 170 return (FILE_SHARE_READ | FILE_SHARE_WRITE); 171 else { 172 if ((desired_access & 173 SMB_DA_ACCESS_MASK) == SMB_DA_ACCESS_READ) 174 return (FILE_SHARE_READ); 175 else 176 return (FILE_SHARE_NONE); 177 } 178 179 case SMB_DA_SHARE_EXCLUSIVE: 180 return (FILE_SHARE_NONE); 181 182 case SMB_DA_SHARE_DENY_WRITE: 183 return (FILE_SHARE_READ); 184 185 case SMB_DA_SHARE_DENY_READ: 186 return (FILE_SHARE_WRITE); 187 188 case SMB_DA_SHARE_DENY_NONE: 189 return (FILE_SHARE_READ | FILE_SHARE_WRITE); 190 } 191 192 /* invalid deny mode */ 193 return ((uint32_t)SMB_INVALID_SHAREMODE); 194 } 195 196 /* 197 * smb_ofun_to_crdisposition 198 * 199 * This function converts open function values used by Open and Open AndX 200 * commands to create disposition values used by NT Create AndX command. 201 */ 202 uint32_t 203 smb_ofun_to_crdisposition(uint16_t ofun) 204 { 205 static int ofun_cr_map[3][2] = 206 { 207 { -1, FILE_CREATE }, 208 { FILE_OPEN, FILE_OPEN_IF }, 209 { FILE_OVERWRITE, FILE_OVERWRITE_IF } 210 }; 211 212 int row = ofun & SMB_OFUN_OPEN_MASK; 213 int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4; 214 215 if (row == 3) 216 return ((uint32_t)SMB_INVALID_CRDISPOSITION); 217 218 return (ofun_cr_map[row][col]); 219 } 220 221 /* 222 * smb_open_share_check 223 * 224 * check file sharing rules for current open request 225 * against the given existing open. 226 * 227 * Returns NT_STATUS_SHARING_VIOLATION if there is any 228 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 229 */ 230 uint32_t 231 smb_open_share_check(struct smb_request *sr, 232 struct smb_node *node, 233 struct smb_ofile *open) 234 { 235 uint32_t desired_access; 236 uint32_t share_access; 237 238 desired_access = sr->arg.open.desired_access; 239 share_access = sr->arg.open.share_access; 240 241 /* 242 * As far as I can tell share modes are not relevant to 243 * directories. The check for exclusive access (Deny RW) 244 * remains because I don't know whether or not it was here 245 * for a reason. 246 */ 247 if (node->attr.sa_vattr.va_type == VDIR) { 248 if (DENY_RW(open->f_share_access) && 249 (node->n_orig_uid != crgetuid(sr->user_cr))) { 250 return (NT_STATUS_SHARING_VIOLATION); 251 } 252 253 return (NT_STATUS_SUCCESS); 254 } 255 256 /* if it's just meta data */ 257 if ((open->f_granted_access & FILE_DATA_ALL) == 0) 258 return (NT_STATUS_SUCCESS); 259 260 /* 261 * Check requested share access against the 262 * open granted (desired) access 263 */ 264 if (DENY_DELETE(share_access) && (open->f_granted_access & DELETE)) 265 return (NT_STATUS_SHARING_VIOLATION); 266 267 if (DENY_READ(share_access) && 268 (open->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) 269 return (NT_STATUS_SHARING_VIOLATION); 270 271 if (DENY_WRITE(share_access) && 272 (open->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) 273 return (NT_STATUS_SHARING_VIOLATION); 274 275 /* check requested desired access against the open share access */ 276 if (DENY_DELETE(open->f_share_access) && (desired_access & DELETE)) 277 return (NT_STATUS_SHARING_VIOLATION); 278 279 if (DENY_READ(open->f_share_access) && 280 (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) 281 return (NT_STATUS_SHARING_VIOLATION); 282 283 if (DENY_WRITE(open->f_share_access) && 284 (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) 285 return (NT_STATUS_SHARING_VIOLATION); 286 287 return (NT_STATUS_SUCCESS); 288 } 289 290 /* 291 * smb_file_share_check 292 * 293 * check file sharing rules for current open request 294 * against all existing opens for a file. 295 * 296 * Returns NT_STATUS_SHARING_VIOLATION if there is any 297 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 298 */ 299 uint32_t 300 smb_file_share_check(struct smb_request *sr, struct smb_node *node) 301 { 302 struct smb_ofile *open; 303 uint32_t status; 304 305 if (node == 0 || node->n_refcnt <= 1) 306 return (NT_STATUS_SUCCESS); 307 308 /* if it's just meta data */ 309 if ((sr->arg.open.desired_access & FILE_DATA_ALL) == 0) 310 return (NT_STATUS_SUCCESS); 311 312 smb_llist_enter(&node->n_ofile_list, RW_READER); 313 open = smb_llist_head(&node->n_ofile_list); 314 while (open) { 315 status = smb_open_share_check(sr, node, open); 316 if (status == NT_STATUS_SHARING_VIOLATION) { 317 smb_llist_exit(&node->n_ofile_list); 318 return (status); 319 } 320 open = smb_llist_next(&node->n_ofile_list, open); 321 } 322 smb_llist_exit(&node->n_ofile_list); 323 324 return (NT_STATUS_SUCCESS); 325 } 326 327 /* 328 * smb_amask_to_amode 329 * Converts specific read/write access rights of access mask to access 330 * mode flags. 331 */ 332 int 333 smb_amask_to_amode(unsigned long amask) 334 { 335 if ((amask & FILE_READ_DATA) && 336 (amask & (FILE_WRITE_DATA | FILE_APPEND_DATA))) 337 return (O_RDWR); 338 339 if (amask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) 340 return (O_WRONLY); 341 342 return (O_RDONLY); 343 } 344 345 /* 346 * smb_open_subr 347 * 348 * Notes on write-through behaviour. It looks like pre-LM0.12 versions 349 * of the protocol specify the write-through mode when a file is opened, 350 * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose, 351 * SmbWriteAndUnlock) don't need to contain a write-through flag. 352 * 353 * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate) 354 * don't indicate which write-through mode to use. Instead the write 355 * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call 356 * basis. 357 * 358 * We don't care which open call was used to get us here, we just need 359 * to ensure that the write-through mode flag is copied from the open 360 * parameters to the node. We test the omode write-through flag in all 361 * write functions. 362 * 363 * This function will return NT status codes but it also raises errors, 364 * in which case it won't return to the caller. Be careful how you 365 * handle things in here. 366 */ 367 uint32_t 368 smb_open_subr(struct smb_request *sr) 369 { 370 int created = 0; 371 struct smb_node *node = 0; 372 struct smb_node *dnode = 0; 373 struct smb_node *cur_node; 374 struct open_param *op = &sr->arg.open; 375 int rc; 376 struct smb_ofile *of; 377 smb_attr_t new_attr; 378 int pathlen; 379 int max_requested = 0; 380 uint32_t max_allowed; 381 unsigned int granted_oplock; 382 uint32_t status = NT_STATUS_SUCCESS; 383 int is_dir; 384 smb_error_t err; 385 int is_stream; 386 int lookup_flags = SMB_FOLLOW_LINKS; 387 uint32_t daccess; 388 389 is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0; 390 391 if (is_dir) { 392 /* 393 * The file being created or opened is a directory file. 394 * With this flag, the Disposition parameter must be set to 395 * one of FILE_CREATE, FILE_OPEN, or FILE_OPEN_IF 396 */ 397 if ((op->create_disposition != FILE_CREATE) && 398 (op->create_disposition != FILE_OPEN_IF) && 399 (op->create_disposition != FILE_OPEN)) { 400 smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER, 401 ERRDOS, ERROR_INVALID_ACCESS); 402 /* invalid open mode */ 403 /* NOTREACHED */ 404 } 405 } 406 407 if (op->desired_access & MAXIMUM_ALLOWED) { 408 max_requested = 1; 409 op->desired_access &= ~MAXIMUM_ALLOWED; 410 } 411 op->desired_access = smb_access_generic_to_file(op->desired_access); 412 413 if (sr->session->s_file_cnt >= SMB_SESSION_OFILE_MAX) { 414 415 ASSERT(sr->uid_user); 416 cmn_err(CE_NOTE, "smbd[%s\\%s]: %s", sr->uid_user->u_domain, 417 sr->uid_user->u_name, 418 xlate_nt_status(NT_STATUS_TOO_MANY_OPENED_FILES)); 419 420 smbsr_raise_cifs_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES, 421 ERRDOS, ERROR_TOO_MANY_OPEN_FILES); 422 /* NOTREACHED */ 423 } 424 425 /* This must be NULL at this point */ 426 sr->fid_ofile = NULL; 427 428 op->devstate = 0; 429 430 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 431 case STYPE_DISKTREE: 432 break; 433 434 case STYPE_IPC: 435 /* 436 * No further processing for IPC, we need to either 437 * raise an exception or return success here. 438 */ 439 if ((rc = smb_rpc_open(sr)) != 0) { 440 smbsr_raise_nt_error(sr, rc); 441 /* NOTREACHED */ 442 } else { 443 return (NT_STATUS_SUCCESS); 444 } 445 break; 446 447 default: 448 smbsr_raise_error(sr, ERRSRV, ERRinvdevice); 449 /* NOTREACHED */ 450 break; 451 } 452 453 if ((pathlen = strlen(op->fqi.path)) >= MAXPATHLEN) { 454 smbsr_raise_error(sr, ERRSRV, ERRfilespecs); 455 /* NOTREACHED */ 456 } 457 458 /* 459 * Some clients pass null file names; NT interprets this as "\". 460 */ 461 if (pathlen == 0) { 462 op->fqi.path = "\\"; 463 pathlen = 1; 464 } 465 466 op->fqi.srch_attr = op->fqi.srch_attr; 467 468 if ((status = smb_validate_object_name(op->fqi.path, is_dir)) != 0) { 469 smbsr_raise_cifs_error(sr, status, ERRDOS, ERROR_INVALID_NAME); 470 /* NOTREACHED */ 471 } 472 473 cur_node = op->fqi.dir_snode ? 474 op->fqi.dir_snode : sr->tid_tree->t_snode; 475 476 if (rc = smb_pathname_reduce(sr, sr->user_cr, op->fqi.path, 477 sr->tid_tree->t_snode, cur_node, &op->fqi.dir_snode, 478 op->fqi.last_comp)) { 479 smbsr_raise_errno(sr, rc); 480 /* NOTREACHED */ 481 } 482 483 /* 484 * If the access mask has only DELETE set (ignore 485 * FILE_READ_ATTRIBUTES), then assume that this 486 * is a request to delete the link (if a link) 487 * and do not follow links. Otherwise, follow 488 * the link to the target. 489 */ 490 491 daccess = op->desired_access & ~FILE_READ_ATTRIBUTES; 492 493 if (daccess == DELETE) 494 lookup_flags &= ~SMB_FOLLOW_LINKS; 495 496 rc = smb_fsop_lookup_name(sr, kcred, lookup_flags, 497 sr->tid_tree->t_snode, op->fqi.dir_snode, op->fqi.last_comp, 498 &op->fqi.last_snode, &op->fqi.last_attr); 499 500 if (rc == 0) { 501 op->fqi.last_comp_was_found = 1; 502 (void) strcpy(op->fqi.last_comp_od, 503 op->fqi.last_snode->od_name); 504 } else if (rc == ENOENT) { 505 op->fqi.last_comp_was_found = 0; 506 op->fqi.last_snode = NULL; 507 rc = 0; 508 } else { 509 smb_node_release(op->fqi.dir_snode); 510 SMB_NULL_FQI_NODES(op->fqi); 511 smbsr_raise_errno(sr, rc); 512 /* NOTREACHED */ 513 } 514 515 if (op->fqi.last_comp_was_found) { 516 node = op->fqi.last_snode; 517 dnode = op->fqi.dir_snode; 518 519 /* 520 * Reject this request if the target is a directory 521 * and the client has specified that it must not be 522 * a directory (required by Lotus Notes). 523 */ 524 if ((op->create_options & FILE_NON_DIRECTORY_FILE) && 525 (op->fqi.last_attr.sa_vattr.va_type == VDIR)) { 526 smb_node_release(node); 527 smb_node_release(dnode); 528 SMB_NULL_FQI_NODES(op->fqi); 529 smbsr_raise_cifs_error(sr, 530 NT_STATUS_FILE_IS_A_DIRECTORY, 531 ERRDOS, ERROR_ACCESS_DENIED); 532 /* NOTREACHED */ 533 } 534 535 if (op->fqi.last_attr.sa_vattr.va_type == VDIR) { 536 if ((sr->smb_com == SMB_COM_OPEN_ANDX) || 537 (sr->smb_com == SMB_COM_OPEN)) { 538 /* 539 * Directories cannot be opened 540 * with the above commands 541 */ 542 smb_node_release(node); 543 smb_node_release(dnode); 544 SMB_NULL_FQI_NODES(op->fqi); 545 smbsr_raise_cifs_error(sr, 546 NT_STATUS_FILE_IS_A_DIRECTORY, 547 ERRDOS, ERROR_ACCESS_DENIED); 548 /* NOTREACHED */ 549 } 550 } else if (op->my_flags & MYF_MUST_BE_DIRECTORY) { 551 smb_node_release(node); 552 smb_node_release(dnode); 553 SMB_NULL_FQI_NODES(op->fqi); 554 smbsr_raise_cifs_error(sr, NT_STATUS_NOT_A_DIRECTORY, 555 ERRDOS, ERROR_DIRECTORY); 556 /* NOTREACHED */ 557 } 558 559 /* 560 * No more open should be accepted when "Delete on close" 561 * flag is set. 562 */ 563 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 564 smb_node_release(node); 565 smb_node_release(dnode); 566 SMB_NULL_FQI_NODES(op->fqi); 567 smbsr_raise_cifs_error(sr, NT_STATUS_DELETE_PENDING, 568 ERRDOS, ERROR_ACCESS_DENIED); 569 /* NOTREACHED */ 570 } 571 572 /* 573 * Specified file already exists so the operation should fail. 574 */ 575 if (op->create_disposition == FILE_CREATE) { 576 smb_node_release(node); 577 smb_node_release(dnode); 578 SMB_NULL_FQI_NODES(op->fqi); 579 smbsr_raise_cifs_error(sr, 580 NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS, 581 ERROR_ALREADY_EXISTS); 582 /* NOTREACHED */ 583 } 584 585 /* 586 * Windows seems to check read-only access before file 587 * sharing check. 588 */ 589 if (NODE_IS_READONLY(node)) { 590 /* Files data only */ 591 if (node->attr.sa_vattr.va_type != VDIR) { 592 if (op->desired_access & (FILE_WRITE_DATA | 593 FILE_APPEND_DATA)) { 594 smb_node_release(node); 595 smb_node_release(dnode); 596 SMB_NULL_FQI_NODES(op->fqi); 597 smbsr_raise_error(sr, ERRDOS, 598 ERRnoaccess); 599 /* NOTREACHED */ 600 } 601 } 602 } 603 604 status = smb_file_share_check(sr, node); 605 if (status == NT_STATUS_SHARING_VIOLATION) { 606 smb_node_release(node); 607 smb_node_release(dnode); 608 SMB_NULL_FQI_NODES(op->fqi); 609 return (status); 610 } 611 612 status = smb_fsop_access(sr, sr->user_cr, node, 613 op->desired_access); 614 615 if (status != NT_STATUS_SUCCESS) { 616 smb_node_release(node); 617 smb_node_release(dnode); 618 SMB_NULL_FQI_NODES(op->fqi); 619 if (status == NT_STATUS_PRIVILEGE_NOT_HELD) { 620 smbsr_raise_cifs_error(sr, 621 status, 622 ERRDOS, 623 ERROR_PRIVILEGE_NOT_HELD); 624 } else { 625 smbsr_raise_cifs_error(sr, 626 NT_STATUS_ACCESS_DENIED, 627 ERRDOS, 628 ERROR_ACCESS_DENIED); 629 } 630 } 631 632 /* 633 * Break the oplock before share checks. If another client 634 * has the file open, this will force a flush or close, 635 * which may affect the outcome of any share checking. 636 */ 637 if (OPLOCKS_IN_FORCE(node)) { 638 status = smb_break_oplock(sr, node); 639 640 if (status != NT_STATUS_SUCCESS) { 641 smb_node_release(node); 642 smb_node_release(dnode); 643 SMB_NULL_FQI_NODES(op->fqi); 644 smbsr_raise_cifs_error(sr, status, 645 ERRDOS, ERROR_VC_DISCONNECTED); 646 /* NOTREACHED */ 647 } 648 } 649 650 switch (op->create_disposition) { 651 case FILE_SUPERSEDE: 652 case FILE_OVERWRITE_IF: 653 case FILE_OVERWRITE: 654 if (node->attr.sa_vattr.va_type == VDIR) { 655 smb_node_release(node); 656 smb_node_release(dnode); 657 SMB_NULL_FQI_NODES(op->fqi); 658 smbsr_raise_cifs_error(sr, 659 NT_STATUS_ACCESS_DENIED, ERRDOS, 660 ERROR_ACCESS_DENIED); 661 /* NOTREACHED */ 662 } 663 664 if (node->attr.sa_vattr.va_size != op->dsize) { 665 node->flags &= ~NODE_FLAGS_SET_SIZE; 666 new_attr.sa_vattr.va_size = op->dsize; 667 new_attr.sa_mask = SMB_AT_SIZE; 668 if ((rc = smb_fsop_setattr(sr, sr->user_cr, 669 (&op->fqi)->last_snode, &new_attr, 670 &op->fqi.last_attr)) != 0) { 671 smb_node_release(node); 672 smb_node_release(dnode); 673 SMB_NULL_FQI_NODES(op->fqi); 674 smbsr_raise_errno(sr, rc); 675 /* NOTREACHED */ 676 } 677 678 } 679 680 /* 681 * If file is being replaced, 682 * we should remove existing streams 683 */ 684 if (SMB_IS_STREAM(node) == 0) 685 (void) smb_fsop_remove_streams(sr, sr->user_cr, 686 node); 687 688 op->action_taken = SMB_OACT_TRUNCATED; 689 break; 690 691 default: 692 /* 693 * FILE_OPEN or FILE_OPEN_IF. 694 */ 695 op->action_taken = SMB_OACT_OPENED; 696 break; 697 } 698 } else { 699 700 /* Last component was not found. */ 701 dnode = op->fqi.dir_snode; 702 703 if ((op->create_disposition == FILE_OPEN) || 704 (op->create_disposition == FILE_OVERWRITE)) { 705 smb_node_release(dnode); 706 SMB_NULL_FQI_NODES(op->fqi); 707 708 is_stream = smb_stream_parse_name(op->fqi.path, 709 NULL, NULL); 710 /* 711 * The requested file not found so the operation should 712 * fail with these two dispositions 713 */ 714 if (is_stream) 715 smbsr_raise_cifs_error(sr, 716 NT_STATUS_OBJECT_NAME_NOT_FOUND, 717 ERRDOS, ERROR_FILE_NOT_FOUND); 718 else 719 smbsr_raise_error(sr, ERRDOS, ERRbadfile); 720 /* NOTREACHED */ 721 } 722 723 /* 724 * lock the parent dir node in case another create 725 * request to the same parent directory comes in. 726 */ 727 smb_rwx_rwenter(&dnode->n_lock, RW_WRITER); 728 729 bzero(&new_attr, sizeof (new_attr)); 730 if (is_dir == 0) { 731 new_attr.sa_vattr.va_type = VREG; 732 new_attr.sa_vattr.va_mode = 0666; 733 new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE; 734 rc = smb_fsop_create(sr, sr->user_cr, dnode, 735 op->fqi.last_comp, &new_attr, 736 &op->fqi.last_snode, &op->fqi.last_attr); 737 if (rc != 0) { 738 smb_rwx_rwexit(&dnode->n_lock); 739 smb_node_release(dnode); 740 SMB_NULL_FQI_NODES(op->fqi); 741 smbsr_raise_errno(sr, rc); 742 /* NOTREACHED */ 743 } 744 745 if (op->dsize) { 746 new_attr.sa_vattr.va_size = op->dsize; 747 new_attr.sa_mask = SMB_AT_SIZE; 748 rc = smb_fsop_setattr(sr, sr->user_cr, 749 op->fqi.last_snode, &new_attr, 750 &op->fqi.last_attr); 751 if (rc != 0) { 752 smb_node_release(op->fqi.last_snode); 753 (void) smb_fsop_remove(sr, sr->user_cr, 754 dnode, op->fqi.last_comp, 0); 755 smb_rwx_rwexit(&dnode->n_lock); 756 smb_node_release(dnode); 757 SMB_NULL_FQI_NODES(op->fqi); 758 smbsr_raise_errno(sr, rc); 759 /* NOTREACHED */ 760 } 761 } 762 763 } else { 764 op->dattr |= SMB_FA_DIRECTORY; 765 new_attr.sa_vattr.va_type = VDIR; 766 new_attr.sa_vattr.va_mode = 0777; 767 new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE; 768 rc = smb_fsop_mkdir(sr, sr->user_cr, dnode, 769 op->fqi.last_comp, &new_attr, 770 &op->fqi.last_snode, &op->fqi.last_attr); 771 if (rc != 0) { 772 smb_rwx_rwexit(&dnode->n_lock); 773 smb_node_release(dnode); 774 SMB_NULL_FQI_NODES(op->fqi); 775 smbsr_raise_errno(sr, rc); 776 /* NOTREACHED */ 777 } 778 } 779 780 created = 1; 781 op->action_taken = SMB_OACT_CREATED; 782 } 783 784 if (node == 0) { 785 node = op->fqi.last_snode; 786 } 787 788 if ((op->fqi.last_attr.sa_vattr.va_type != VREG) && 789 (op->fqi.last_attr.sa_vattr.va_type != VDIR) && 790 (op->fqi.last_attr.sa_vattr.va_type != VLNK)) { 791 /* not allowed to do this */ 792 SMB_DEL_NEWOBJ(op->fqi); 793 smb_node_release(node); 794 if (created) 795 smb_rwx_rwexit(&dnode->n_lock); 796 smb_node_release(dnode); 797 SMB_NULL_FQI_NODES(op->fqi); 798 smbsr_raise_error(sr, ERRDOS, ERRnoaccess); 799 /* NOTREACHED */ 800 } 801 802 if (max_requested) { 803 smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed); 804 op->desired_access |= max_allowed; 805 } 806 807 /* 808 * smb_ofile_open() will copy node to of->node. Hence 809 * the hold on node (i.e. op->fqi.last_snode) will be "transferred" 810 * to the "of" structure. 811 */ 812 813 of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op->desired_access, 814 op->create_options, op->share_access, SMB_FTYPE_DISK, NULL, 0, 815 &err); 816 817 if (of == NULL) { 818 SMB_DEL_NEWOBJ(op->fqi); 819 smb_node_release(node); 820 if (created) 821 smb_rwx_rwexit(&dnode->n_lock); 822 smb_node_release(dnode); 823 SMB_NULL_FQI_NODES(op->fqi); 824 smbsr_raise_cifs_error(sr, err.status, err.errcls, err.errcode); 825 /* NOTREACHED */ 826 } 827 828 /* 829 * Propagate the write-through mode from the open params 830 * to the node: see the notes in the function header. 831 * 832 * IR #102318 Mirroring may force synchronous 833 * writes regardless of what we specify here. 834 */ 835 if (smb_stable_mode || (op->create_options & FILE_WRITE_THROUGH)) 836 node->flags |= NODE_FLAGS_WRITE_THROUGH; 837 838 op->fileid = op->fqi.last_attr.sa_vattr.va_nodeid; 839 840 if (op->fqi.last_attr.sa_vattr.va_type == VDIR) { 841 /* We don't oplock directories */ 842 op->my_flags &= ~MYF_OPLOCK_MASK; 843 op->dsize = 0; 844 } else { 845 status = smb_acquire_oplock(sr, of, op->my_flags, 846 &granted_oplock); 847 op->my_flags &= ~MYF_OPLOCK_MASK; 848 849 if (status != NT_STATUS_SUCCESS) { 850 (void) smb_ofile_close(of, 0); 851 smb_ofile_release(of); 852 if (created) 853 smb_rwx_rwexit(&dnode->n_lock); 854 smb_node_release(dnode); 855 SMB_NULL_FQI_NODES(op->fqi); 856 857 smbsr_raise_cifs_error(sr, status, 858 ERRDOS, ERROR_SHARING_VIOLATION); 859 /* NOTREACHED */ 860 } 861 862 op->my_flags |= granted_oplock; 863 op->dsize = op->fqi.last_attr.sa_vattr.va_size; 864 } 865 866 if (created) { 867 node->flags |= NODE_FLAGS_CREATED; 868 /* 869 * Clients may set the DOS readonly bit on create but they 870 * expect subsequent write operations on the open fid to 871 * succeed. Thus the DOS readonly bit is not set until the 872 * file is closed. The NODE_CREATED_READONLY flag will 873 * inhibit other attempts to open the file with write access 874 * and act as the indicator to set the DOS readonly bit on 875 * close. 876 */ 877 if (op->dattr & SMB_FA_READONLY) { 878 node->flags |= NODE_CREATED_READONLY; 879 op->dattr &= ~SMB_FA_READONLY; 880 } 881 smb_node_set_dosattr(node, op->dattr | SMB_FA_ARCHIVE); 882 if (op->utime.tv_sec == 0 || op->utime.tv_sec == UINT_MAX) 883 (void) microtime(&op->utime); 884 smb_node_set_time(node, NULL, &op->utime, 0, 0, SMB_AT_MTIME); 885 (void) smb_sync_fsattr(sr, sr->user_cr, node); 886 } else { 887 /* 888 * If we reach here, it means that file already exists 889 * and if create disposition is one of: FILE_SUPERSEDE, 890 * FILE_OVERWRITE_IF, or FILE_OVERWRITE it 891 * means that client wants to overwrite (or truncate) 892 * the existing file. So we should overwrite the dos 893 * attributes of destination file with the dos attributes 894 * of source file. 895 */ 896 897 switch (op->create_disposition) { 898 case FILE_SUPERSEDE: 899 case FILE_OVERWRITE_IF: 900 case FILE_OVERWRITE: 901 smb_node_set_dosattr(node, 902 op->dattr | SMB_FA_ARCHIVE); 903 (void) smb_sync_fsattr(sr, sr->user_cr, node); 904 } 905 op->utime = *smb_node_get_crtime(node); 906 op->dattr = smb_node_get_dosattr(node); 907 } 908 909 /* 910 * Set up the file type in open_param for the response 911 */ 912 op->ftype = SMB_FTYPE_DISK; 913 sr->smb_fid = of->f_fid; 914 sr->fid_ofile = of; 915 916 if (created) { 917 smb_rwx_rwexit(&dnode->n_lock); 918 } 919 smb_node_release(dnode); 920 SMB_NULL_FQI_NODES(op->fqi); 921 922 return (NT_STATUS_SUCCESS); 923 } 924 925 /* 926 * smb_validate_object_name 927 * 928 * Very basic file name validation. Directory validation is handed off 929 * to smb_validate_dirname. For filenames, we check for names of the 930 * form "AAAn:". Names that contain three characters, a single digit 931 * and a colon (:) are reserved as DOS device names, i.e. "COM1:". 932 * 933 * Returns NT status codes. 934 */ 935 uint32_t 936 smb_validate_object_name(char *path, unsigned int ftype) 937 { 938 char *filename; 939 940 if (path == 0) 941 return (0); 942 943 if (ftype) 944 return (smb_validate_dirname(path)); 945 946 /* 947 * Basename with backslashes. 948 */ 949 if ((filename = strrchr(path, '\\')) != 0) 950 ++filename; 951 else 952 filename = path; 953 954 if (strlen(filename) == 5 && 955 mts_isdigit(filename[3]) && 956 filename[4] == ':') { 957 return (NT_STATUS_OBJECT_NAME_INVALID); 958 } 959 960 return (0); 961 } 962 963 /* 964 * smb_preset_delete_on_close 965 * 966 * Set the DeleteOnClose flag on the smb file. When the file is closed, 967 * the flag will be transferred to the smb node, which will commit the 968 * delete operation and inhibit subsequent open requests. 969 * 970 * When DeleteOnClose is set on an smb_node, the common open code will 971 * reject subsequent open requests for the file. Observation of Windows 972 * 2000 indicates that subsequent opens should be allowed (assuming 973 * there would be no sharing violation) until the file is closed using 974 * the fid on which the DeleteOnClose was requested. 975 */ 976 void 977 smb_preset_delete_on_close(smb_ofile_t *file) 978 { 979 mutex_enter(&file->f_mutex); 980 file->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE; 981 mutex_exit(&file->f_mutex); 982 } 983