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