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