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