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 399 if ((op->fqi.last_attr.sa_vattr.va_type != VREG) && 400 (op->fqi.last_attr.sa_vattr.va_type != VDIR) && 401 (op->fqi.last_attr.sa_vattr.va_type != VLNK)) { 402 403 smb_node_release(op->fqi.last_snode); 404 smb_node_release(op->fqi.dir_snode); 405 SMB_NULL_FQI_NODES(op->fqi); 406 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, 407 ERRnoaccess); 408 return (NT_STATUS_ACCESS_DENIED); 409 } 410 411 node = op->fqi.last_snode; 412 dnode = op->fqi.dir_snode; 413 414 /* 415 * Enter critical region for share reservations. 416 * (See comments above smb_fsop_shrlock().) 417 */ 418 419 rw_enter(&node->n_share_lock, RW_WRITER); 420 421 /* 422 * Reject this request if the target is a directory 423 * and the client has specified that it must not be 424 * a directory (required by Lotus Notes). 425 */ 426 if ((op->create_options & FILE_NON_DIRECTORY_FILE) && 427 (op->fqi.last_attr.sa_vattr.va_type == VDIR)) { 428 rw_exit(&node->n_share_lock); 429 smb_node_release(node); 430 smb_node_release(dnode); 431 SMB_NULL_FQI_NODES(op->fqi); 432 smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY, 433 ERRDOS, ERROR_ACCESS_DENIED); 434 return (NT_STATUS_FILE_IS_A_DIRECTORY); 435 } 436 437 if (op->fqi.last_attr.sa_vattr.va_type == VDIR) { 438 if ((sr->smb_com == SMB_COM_OPEN_ANDX) || 439 (sr->smb_com == SMB_COM_OPEN)) { 440 /* 441 * Directories cannot be opened 442 * with the above commands 443 */ 444 rw_exit(&node->n_share_lock); 445 smb_node_release(node); 446 smb_node_release(dnode); 447 SMB_NULL_FQI_NODES(op->fqi); 448 smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY, 449 ERRDOS, ERROR_ACCESS_DENIED); 450 return (NT_STATUS_FILE_IS_A_DIRECTORY); 451 } 452 } else if (op->my_flags & MYF_MUST_BE_DIRECTORY) { 453 rw_exit(&node->n_share_lock); 454 smb_node_release(node); 455 smb_node_release(dnode); 456 SMB_NULL_FQI_NODES(op->fqi); 457 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY, 458 ERRDOS, ERROR_DIRECTORY); 459 return (NT_STATUS_NOT_A_DIRECTORY); 460 } 461 462 /* 463 * No more open should be accepted when "Delete on close" 464 * flag is set. 465 */ 466 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 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_DELETE_PENDING, 472 ERRDOS, ERROR_ACCESS_DENIED); 473 return (NT_STATUS_DELETE_PENDING); 474 } 475 476 /* 477 * Specified file already exists so the operation should fail. 478 */ 479 if (op->create_disposition == FILE_CREATE) { 480 rw_exit(&node->n_share_lock); 481 smb_node_release(node); 482 smb_node_release(dnode); 483 SMB_NULL_FQI_NODES(op->fqi); 484 smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION, 485 ERRDOS, ERROR_ALREADY_EXISTS); 486 return (NT_STATUS_OBJECT_NAME_COLLISION); 487 } 488 489 /* 490 * Windows seems to check read-only access before file 491 * sharing check. 492 */ 493 if (NODE_IS_READONLY(node)) { 494 /* Files data only */ 495 if (node->attr.sa_vattr.va_type != VDIR) { 496 if (op->desired_access & (FILE_WRITE_DATA | 497 FILE_APPEND_DATA)) { 498 rw_exit(&node->n_share_lock); 499 smb_node_release(node); 500 smb_node_release(dnode); 501 SMB_NULL_FQI_NODES(op->fqi); 502 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 503 ERRDOS, ERRnoaccess); 504 return (NT_STATUS_ACCESS_DENIED); 505 } 506 } 507 } 508 509 /* 510 * The following check removes the need to check share 511 * reservations again when a truncate is done. 512 */ 513 514 if ((op->create_disposition == FILE_SUPERSEDE) || 515 (op->create_disposition == FILE_OVERWRITE_IF) || 516 (op->create_disposition == FILE_OVERWRITE)) { 517 518 if (!(op->desired_access & 519 (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 520 rw_exit(&node->n_share_lock); 521 smb_node_release(node); 522 smb_node_release(dnode); 523 SMB_NULL_FQI_NODES(op->fqi); 524 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 525 ERRDOS, ERRnoaccess); 526 return (NT_STATUS_ACCESS_DENIED); 527 } 528 } 529 530 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid, 531 op->desired_access, share_access); 532 533 if (status == NT_STATUS_SHARING_VIOLATION) { 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 return (status); 539 } 540 541 status = smb_fsop_access(sr, sr->user_cr, node, 542 op->desired_access); 543 544 if (status != NT_STATUS_SUCCESS) { 545 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); 546 547 rw_exit(&node->n_share_lock); 548 smb_node_release(node); 549 smb_node_release(dnode); 550 SMB_NULL_FQI_NODES(op->fqi); 551 552 if (status == NT_STATUS_PRIVILEGE_NOT_HELD) { 553 smbsr_error(sr, status, 554 ERRDOS, ERROR_PRIVILEGE_NOT_HELD); 555 return (status); 556 } else { 557 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 558 ERRDOS, ERROR_ACCESS_DENIED); 559 return (NT_STATUS_ACCESS_DENIED); 560 } 561 } 562 563 /* 564 * Break the oplock before share checks. If another client 565 * has the file open, this will force a flush or close, 566 * which may affect the outcome of any share checking. 567 */ 568 569 if (OPLOCKS_IN_FORCE(node)) { 570 status = smb_break_oplock(sr, node); 571 572 if (status != NT_STATUS_SUCCESS) { 573 rw_exit(&node->n_share_lock); 574 smb_node_release(node); 575 smb_node_release(dnode); 576 SMB_NULL_FQI_NODES(op->fqi); 577 smbsr_error(sr, status, 578 ERRDOS, ERROR_VC_DISCONNECTED); 579 return (status); 580 } 581 } 582 583 switch (op->create_disposition) { 584 case FILE_SUPERSEDE: 585 case FILE_OVERWRITE_IF: 586 case FILE_OVERWRITE: 587 if (node->attr.sa_vattr.va_type == VDIR) { 588 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); 589 rw_exit(&node->n_share_lock); 590 smb_node_release(node); 591 smb_node_release(dnode); 592 SMB_NULL_FQI_NODES(op->fqi); 593 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 594 ERRDOS, ERROR_ACCESS_DENIED); 595 return (NT_STATUS_ACCESS_DENIED); 596 } 597 598 if (node->attr.sa_vattr.va_size != op->dsize) { 599 node->flags &= ~NODE_FLAGS_SET_SIZE; 600 bzero(&new_attr, sizeof (new_attr)); 601 new_attr.sa_vattr.va_size = op->dsize; 602 new_attr.sa_mask = SMB_AT_SIZE; 603 604 rc = smb_fsop_setattr(sr, sr->user_cr, 605 node, &new_attr, &op->fqi.last_attr); 606 607 if (rc) { 608 smb_fsop_unshrlock(sr->user_cr, node, 609 uniq_fid); 610 rw_exit(&node->n_share_lock); 611 smb_node_release(node); 612 smb_node_release(dnode); 613 SMB_NULL_FQI_NODES(op->fqi); 614 smbsr_errno(sr, rc); 615 return (sr->smb_error.status); 616 } 617 618 op->dsize = op->fqi.last_attr.sa_vattr.va_size; 619 } 620 621 /* 622 * If file is being replaced, 623 * we should remove existing streams 624 */ 625 if (SMB_IS_STREAM(node) == 0) 626 (void) smb_fsop_remove_streams(sr, sr->user_cr, 627 node); 628 629 op->action_taken = SMB_OACT_TRUNCATED; 630 break; 631 632 default: 633 /* 634 * FILE_OPEN or FILE_OPEN_IF. 635 */ 636 op->action_taken = SMB_OACT_OPENED; 637 break; 638 } 639 } else { 640 641 /* Last component was not found. */ 642 dnode = op->fqi.dir_snode; 643 644 if (is_dir == 0) 645 is_stream = smb_stream_parse_name(op->fqi.path, 646 NULL, NULL); 647 648 if ((op->create_disposition == FILE_OPEN) || 649 (op->create_disposition == FILE_OVERWRITE)) { 650 smb_node_release(dnode); 651 SMB_NULL_FQI_NODES(op->fqi); 652 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 653 ERRDOS, ERROR_FILE_NOT_FOUND); 654 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 655 } 656 657 /* 658 * lock the parent dir node in case another create 659 * request to the same parent directory comes in. 660 */ 661 smb_rwx_rwenter(&dnode->n_lock, RW_WRITER); 662 663 bzero(&new_attr, sizeof (new_attr)); 664 if (is_dir == 0) { 665 new_attr.sa_vattr.va_type = VREG; 666 new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR : 667 S_IRUSR | S_IRGRP | S_IROTH | 668 S_IWUSR | S_IWGRP | S_IWOTH; 669 new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE; 670 671 if (op->dsize) { 672 new_attr.sa_vattr.va_size = op->dsize; 673 new_attr.sa_mask |= SMB_AT_SIZE; 674 } 675 676 rc = smb_fsop_create(sr, sr->user_cr, dnode, 677 op->fqi.last_comp, &new_attr, 678 &op->fqi.last_snode, &op->fqi.last_attr); 679 680 if (rc != 0) { 681 smb_rwx_rwexit(&dnode->n_lock); 682 smb_node_release(dnode); 683 SMB_NULL_FQI_NODES(op->fqi); 684 smbsr_errno(sr, rc); 685 return (sr->smb_error.status); 686 } 687 688 /* 689 * A problem with setting the readonly bit at 690 * create time is that this bit will prevent 691 * writes to the file from the same fid (which 692 * should be allowed). 693 * 694 * The solution is to set the bit at close time. 695 * Meanwhile, to prevent racing opens from being 696 * able to write to the file, set share reservations 697 * to prevent write and delete access. 698 */ 699 700 if (op->dattr & SMB_FA_READONLY) 701 share_access &= ~(FILE_SHARE_WRITE | 702 FILE_SHARE_DELETE); 703 704 node = op->fqi.last_snode; 705 706 rw_enter(&node->n_share_lock, RW_WRITER); 707 708 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid, 709 op->desired_access, share_access); 710 711 if (status == NT_STATUS_SHARING_VIOLATION) { 712 rw_exit(&node->n_share_lock); 713 smb_node_release(node); 714 smb_node_release(dnode); 715 SMB_NULL_FQI_NODES(op->fqi); 716 return (status); 717 } 718 719 op->fqi.last_attr = node->attr; 720 721 } else { 722 op->dattr |= SMB_FA_DIRECTORY; 723 new_attr.sa_vattr.va_type = VDIR; 724 new_attr.sa_vattr.va_mode = 0777; 725 new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE; 726 rc = smb_fsop_mkdir(sr, sr->user_cr, dnode, 727 op->fqi.last_comp, &new_attr, 728 &op->fqi.last_snode, &op->fqi.last_attr); 729 if (rc != 0) { 730 smb_rwx_rwexit(&dnode->n_lock); 731 smb_node_release(dnode); 732 SMB_NULL_FQI_NODES(op->fqi); 733 smbsr_errno(sr, rc); 734 return (sr->smb_error.status); 735 } 736 737 node = op->fqi.last_snode; 738 rw_enter(&node->n_share_lock, RW_WRITER); 739 } 740 741 created = 1; 742 op->action_taken = SMB_OACT_CREATED; 743 } 744 745 if (max_requested) { 746 smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed); 747 op->desired_access |= max_allowed; 748 } 749 750 /* 751 * smb_ofile_open() will copy node to of->node. Hence 752 * the hold on node (i.e. op->fqi.last_snode) will be "transferred" 753 * to the "of" structure. 754 */ 755 756 of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op->desired_access, 757 op->create_options, share_access, SMB_FTYPE_DISK, NULL, 0, 758 uniq_fid, &err); 759 760 if (of == NULL) { 761 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); 762 763 SMB_DEL_NEWOBJ(op->fqi); 764 rw_exit(&node->n_share_lock); 765 smb_node_release(node); 766 if (created) 767 smb_rwx_rwexit(&dnode->n_lock); 768 smb_node_release(dnode); 769 SMB_NULL_FQI_NODES(op->fqi); 770 smbsr_error(sr, err.status, err.errcls, err.errcode); 771 return (err.status); 772 } 773 774 /* 775 * Propagate the write-through mode from the open params 776 * to the node: see the notes in the function header. 777 * 778 * IR #102318 Mirroring may force synchronous 779 * writes regardless of what we specify here. 780 */ 781 if (sr->sr_cfg->skc_sync_enable || 782 (op->create_options & FILE_WRITE_THROUGH)) 783 node->flags |= NODE_FLAGS_WRITE_THROUGH; 784 785 op->fileid = op->fqi.last_attr.sa_vattr.va_nodeid; 786 787 if (op->fqi.last_attr.sa_vattr.va_type == VDIR) { 788 /* We don't oplock directories */ 789 op->my_flags &= ~MYF_OPLOCK_MASK; 790 op->dsize = 0; 791 } else { 792 status = smb_acquire_oplock(sr, of, op->my_flags, 793 &granted_oplock); 794 op->my_flags &= ~MYF_OPLOCK_MASK; 795 796 if (status != NT_STATUS_SUCCESS) { 797 rw_exit(&node->n_share_lock); 798 /* 799 * smb_fsop_unshrlock() and smb_fsop_close() 800 * are called from smb_ofile_close() 801 */ 802 (void) smb_ofile_close(of, 0); 803 smb_ofile_release(of); 804 if (created) 805 smb_rwx_rwexit(&dnode->n_lock); 806 807 smb_node_release(dnode); 808 SMB_NULL_FQI_NODES(op->fqi); 809 810 smbsr_error(sr, status, 811 ERRDOS, ERROR_SHARING_VIOLATION); 812 return (status); 813 } 814 815 op->my_flags |= granted_oplock; 816 op->dsize = op->fqi.last_attr.sa_vattr.va_size; 817 } 818 819 if (created) { 820 node->flags |= NODE_FLAGS_CREATED; 821 /* 822 * Clients may set the DOS readonly bit on create but they 823 * expect subsequent write operations on the open fid to 824 * succeed. Thus the DOS readonly bit is not set until 825 * the file is closed. The NODE_CREATED_READONLY flag 826 * will act as the indicator to set the DOS readonly bit on 827 * close. 828 */ 829 if (op->dattr & SMB_FA_READONLY) { 830 node->flags |= NODE_CREATED_READONLY; 831 op->dattr &= ~SMB_FA_READONLY; 832 } 833 smb_node_set_dosattr(node, op->dattr | SMB_FA_ARCHIVE); 834 if (op->utime.tv_sec == 0 || op->utime.tv_sec == UINT_MAX) 835 (void) microtime(&op->utime); 836 smb_node_set_time(node, NULL, &op->utime, 0, 0, SMB_AT_MTIME); 837 (void) smb_sync_fsattr(sr, sr->user_cr, node); 838 } else { 839 /* 840 * If we reach here, it means that file already exists 841 * and if create disposition is one of: FILE_SUPERSEDE, 842 * FILE_OVERWRITE_IF, or FILE_OVERWRITE it 843 * means that client wants to overwrite (or truncate) 844 * the existing file. So we should overwrite the dos 845 * attributes of destination file with the dos attributes 846 * of source file. 847 */ 848 849 switch (op->create_disposition) { 850 case FILE_SUPERSEDE: 851 case FILE_OVERWRITE_IF: 852 case FILE_OVERWRITE: 853 smb_node_set_dosattr(node, 854 op->dattr | SMB_FA_ARCHIVE); 855 (void) smb_sync_fsattr(sr, sr->user_cr, node); 856 } 857 op->utime = *smb_node_get_crtime(node); 858 op->dattr = smb_node_get_dosattr(node); 859 } 860 861 /* 862 * Set up the file type in open_param for the response 863 */ 864 op->ftype = SMB_FTYPE_DISK; 865 sr->smb_fid = of->f_fid; 866 sr->fid_ofile = of; 867 868 rw_exit(&node->n_share_lock); 869 870 if (created) 871 smb_rwx_rwexit(&dnode->n_lock); 872 873 smb_node_release(dnode); 874 SMB_NULL_FQI_NODES(op->fqi); 875 876 return (NT_STATUS_SUCCESS); 877 } 878 879 /* 880 * smb_validate_object_name 881 * 882 * Very basic file name validation. Directory validation is handed off 883 * to smb_validate_dirname. For filenames, we check for names of the 884 * form "AAAn:". Names that contain three characters, a single digit 885 * and a colon (:) are reserved as DOS device names, i.e. "COM1:". 886 * 887 * Returns NT status codes. 888 */ 889 uint32_t 890 smb_validate_object_name(char *path, unsigned int ftype) 891 { 892 char *filename; 893 894 if (path == 0) 895 return (0); 896 897 if (ftype) 898 return (smb_validate_dirname(path)); 899 900 /* 901 * Basename with backslashes. 902 */ 903 if ((filename = strrchr(path, '\\')) != 0) 904 ++filename; 905 else 906 filename = path; 907 908 if (strlen(filename) == 5 && 909 mts_isdigit(filename[3]) && 910 filename[4] == ':') { 911 return (NT_STATUS_OBJECT_NAME_INVALID); 912 } 913 914 return (0); 915 } 916 917 /* 918 * smb_preset_delete_on_close 919 * 920 * Set the DeleteOnClose flag on the smb file. When the file is closed, 921 * the flag will be transferred to the smb node, which will commit the 922 * delete operation and inhibit subsequent open requests. 923 * 924 * When DeleteOnClose is set on an smb_node, the common open code will 925 * reject subsequent open requests for the file. Observation of Windows 926 * 2000 indicates that subsequent opens should be allowed (assuming 927 * there would be no sharing violation) until the file is closed using 928 * the fid on which the DeleteOnClose was requested. 929 */ 930 void 931 smb_preset_delete_on_close(smb_ofile_t *file) 932 { 933 mutex_enter(&file->f_mutex); 934 file->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE; 935 mutex_exit(&file->f_mutex); 936 } 937