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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This module provides the common open functionality to the various 28 * open and create SMB interface functions. 29 */ 30 31 #include <smbsrv/smb_incl.h> 32 #include <smbsrv/smb_fsops.h> 33 #include <smbsrv/nterror.h> 34 #include <smbsrv/ntstatus.h> 35 #include <smbsrv/smbinfo.h> 36 #include <sys/fcntl.h> 37 #include <sys/nbmlock.h> 38 39 volatile uint32_t smb_fids = 0; 40 41 static uint32_t smb_open_subr(smb_request_t *); 42 extern uint32_t smb_is_executable(char *); 43 static void smb_delete_new_object(smb_request_t *); 44 45 static char *smb_pathname_strdup(smb_request_t *, const char *); 46 static char *smb_pathname_strcat(char *, const char *); 47 48 /* 49 * smb_access_generic_to_file 50 * 51 * Search MSDN for IoCreateFile to see following mapping. 52 * 53 * GENERIC_READ STANDARD_RIGHTS_READ, FILE_READ_DATA, 54 * FILE_READ_ATTRIBUTES and FILE_READ_EA 55 * 56 * GENERIC_WRITE STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA, 57 * FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA 58 * 59 * GENERIC_EXECUTE STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE. 60 */ 61 uint32_t 62 smb_access_generic_to_file(uint32_t desired_access) 63 { 64 uint32_t access = 0; 65 66 if (desired_access & GENERIC_ALL) 67 return (FILE_ALL_ACCESS & ~SYNCHRONIZE); 68 69 if (desired_access & GENERIC_EXECUTE) { 70 desired_access &= ~GENERIC_EXECUTE; 71 access |= (STANDARD_RIGHTS_EXECUTE | 72 SYNCHRONIZE | FILE_EXECUTE); 73 } 74 75 if (desired_access & GENERIC_WRITE) { 76 desired_access &= ~GENERIC_WRITE; 77 access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE); 78 } 79 80 if (desired_access & GENERIC_READ) { 81 desired_access &= ~GENERIC_READ; 82 access |= FILE_GENERIC_READ; 83 } 84 85 return (access | desired_access); 86 } 87 88 /* 89 * smb_omode_to_amask 90 * 91 * This function converts open modes used by Open and Open AndX 92 * commands to desired access bits used by NT Create AndX command. 93 */ 94 uint32_t 95 smb_omode_to_amask(uint32_t desired_access) 96 { 97 switch (desired_access & SMB_DA_ACCESS_MASK) { 98 case SMB_DA_ACCESS_READ: 99 return (FILE_GENERIC_READ); 100 101 case SMB_DA_ACCESS_WRITE: 102 return (FILE_GENERIC_WRITE); 103 104 case SMB_DA_ACCESS_READ_WRITE: 105 return (FILE_GENERIC_READ | FILE_GENERIC_WRITE); 106 107 case SMB_DA_ACCESS_EXECUTE: 108 return (FILE_GENERIC_EXECUTE); 109 110 default: 111 return (FILE_GENERIC_ALL); 112 } 113 } 114 115 /* 116 * smb_denymode_to_sharemode 117 * 118 * This function converts deny modes used by Open and Open AndX 119 * commands to share access bits used by NT Create AndX command. 120 */ 121 uint32_t 122 smb_denymode_to_sharemode(uint32_t desired_access, char *fname) 123 { 124 switch (desired_access & SMB_DA_SHARE_MASK) { 125 case SMB_DA_SHARE_COMPATIBILITY: 126 if (smb_is_executable(fname)) 127 return (FILE_SHARE_READ | FILE_SHARE_WRITE); 128 129 return (FILE_SHARE_ALL); 130 131 case SMB_DA_SHARE_EXCLUSIVE: 132 return (FILE_SHARE_NONE); 133 134 case SMB_DA_SHARE_DENY_WRITE: 135 return (FILE_SHARE_READ); 136 137 case SMB_DA_SHARE_DENY_READ: 138 return (FILE_SHARE_WRITE); 139 140 case SMB_DA_SHARE_DENY_NONE: 141 default: 142 return (FILE_SHARE_READ | FILE_SHARE_WRITE); 143 } 144 } 145 146 /* 147 * smb_ofun_to_crdisposition 148 * 149 * This function converts open function values used by Open and Open AndX 150 * commands to create disposition values used by NT Create AndX command. 151 */ 152 uint32_t 153 smb_ofun_to_crdisposition(uint16_t ofun) 154 { 155 static int ofun_cr_map[3][2] = 156 { 157 { -1, FILE_CREATE }, 158 { FILE_OPEN, FILE_OPEN_IF }, 159 { FILE_OVERWRITE, FILE_OVERWRITE_IF } 160 }; 161 162 int row = ofun & SMB_OFUN_OPEN_MASK; 163 int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4; 164 165 if (row == 3) 166 return (FILE_MAXIMUM_DISPOSITION + 1); 167 168 return (ofun_cr_map[row][col]); 169 } 170 171 /* 172 * Retry opens to avoid spurious sharing violations, due to timing 173 * issues between closes and opens. The client that already has the 174 * file open may be in the process of closing it. 175 */ 176 uint32_t 177 smb_common_open(smb_request_t *sr) 178 { 179 uint32_t status = NT_STATUS_SUCCESS; 180 int count; 181 182 for (count = 0; count <= 4; count++) { 183 if (count) 184 delay(MSEC_TO_TICK(400)); 185 186 status = smb_open_subr(sr); 187 if (status != NT_STATUS_SHARING_VIOLATION) 188 break; 189 } 190 191 if (status == NT_STATUS_SHARING_VIOLATION) { 192 smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, 193 ERRDOS, ERROR_SHARING_VIOLATION); 194 } 195 196 if (status == NT_STATUS_NO_SUCH_FILE) { 197 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 198 ERRDOS, ERROR_FILE_NOT_FOUND); 199 } 200 201 return (status); 202 } 203 204 /* 205 * smb_open_subr 206 * 207 * Notes on write-through behaviour. It looks like pre-LM0.12 versions 208 * of the protocol specify the write-through mode when a file is opened, 209 * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose, 210 * SmbWriteAndUnlock) don't need to contain a write-through flag. 211 * 212 * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate) 213 * don't indicate which write-through mode to use. Instead the write 214 * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call 215 * basis. 216 * 217 * We don't care which open call was used to get us here, we just need 218 * to ensure that the write-through mode flag is copied from the open 219 * parameters to the node. We test the omode write-through flag in all 220 * write functions. 221 * 222 * This function will return NT status codes but it also raises errors, 223 * in which case it won't return to the caller. Be careful how you 224 * handle things in here. 225 * 226 * The following rules apply when processing a file open request: 227 * 228 * - Oplocks must be broken prior to share checking to prevent open 229 * starvation due to batch oplocks. Checking share reservations first 230 * could potentially result in unnecessary open failures due to 231 * open/close batching on the client. 232 * 233 * - Share checks must take place prior to access checks for correct 234 * Windows semantics and to prevent unnecessary NFS delegation recalls. 235 * 236 * - Oplocks must be acquired after open to ensure the correct 237 * synchronization with NFS delegation and FEM installation. 238 * 239 * 240 * DOS readonly bit rules 241 * 242 * 1. The creator of a readonly file can write to/modify the size of the file 243 * using the original create fid, even though the file will appear as readonly 244 * to all other fids and via a CIFS getattr call. 245 * 246 * 2. A setinfo operation (using either an open fid or a path) to set/unset 247 * readonly will be successful regardless of whether a creator of a readonly 248 * file has an open fid (and has the special privilege mentioned in #1, 249 * above). I.e., the creator of a readonly fid holding that fid will no longer 250 * have a special privilege. 251 * 252 * 3. The DOS readonly bit affects only data and some metadata. 253 * The following metadata can be changed regardless of the readonly bit: 254 * - security descriptors 255 * - DOS attributes 256 * - timestamps 257 * 258 * In the current implementation, the file size cannot be changed (except for 259 * the exceptions in #1 and #2, above). 260 * 261 * 262 * DOS attribute rules 263 * 264 * These rules are specific to creating / opening files and directories. 265 * How the attribute value (specifically ZERO or FILE_ATTRIBUTE_NORMAL) 266 * should be interpreted may differ in other requests. 267 * 268 * - An attribute value equal to ZERO or FILE_ATTRIBUTE_NORMAL means that the 269 * file's attributes should be cleared. 270 * - If FILE_ATTRIBUTE_NORMAL is specified with any other attributes, 271 * FILE_ATTRIBUTE_NORMAL is ignored. 272 * 273 * 1. Creating a new file 274 * - The request attributes + FILE_ATTRIBUTE_ARCHIVE are applied to the file. 275 * 276 * 2. Creating a new directory 277 * - The request attributes + FILE_ATTRIBUTE_DIRECTORY are applied to the file. 278 * - FILE_ATTRIBUTE_ARCHIVE does not get set. 279 * 280 * 3. Overwriting an existing file 281 * - the request attributes are used as search attributes. If the existing 282 * file does not meet the search criteria access is denied. 283 * - otherwise, applies attributes + FILE_ATTRIBUTE_ARCHIVE. 284 * 285 * 4. Opening an existing file or directory 286 * The request attributes are ignored. 287 */ 288 static uint32_t 289 smb_open_subr(smb_request_t *sr) 290 { 291 boolean_t created = B_FALSE; 292 boolean_t last_comp_found = B_FALSE; 293 smb_node_t *node = NULL; 294 smb_node_t *dnode = NULL; 295 smb_node_t *cur_node = NULL; 296 open_param_t *op = &sr->arg.open; 297 int rc; 298 smb_ofile_t *of; 299 smb_attr_t new_attr; 300 int pathlen; 301 int max_requested = 0; 302 uint32_t max_allowed; 303 uint32_t status = NT_STATUS_SUCCESS; 304 int is_dir; 305 smb_error_t err; 306 boolean_t is_stream = B_FALSE; 307 int lookup_flags = SMB_FOLLOW_LINKS; 308 uint32_t daccess; 309 uint32_t uniq_fid; 310 smb_pathname_t *pn = &op->fqi.fq_path; 311 312 is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0; 313 314 if (is_dir) { 315 /* 316 * The object being created or opened is a directory, 317 * and the Disposition parameter must be one of 318 * FILE_CREATE, FILE_OPEN, or FILE_OPEN_IF 319 */ 320 if ((op->create_disposition != FILE_CREATE) && 321 (op->create_disposition != FILE_OPEN_IF) && 322 (op->create_disposition != FILE_OPEN)) { 323 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 324 ERRDOS, ERROR_INVALID_ACCESS); 325 return (NT_STATUS_INVALID_PARAMETER); 326 } 327 } 328 329 if (op->desired_access & MAXIMUM_ALLOWED) { 330 max_requested = 1; 331 op->desired_access &= ~MAXIMUM_ALLOWED; 332 } 333 op->desired_access = smb_access_generic_to_file(op->desired_access); 334 335 if (sr->session->s_file_cnt >= SMB_SESSION_OFILE_MAX) { 336 ASSERT(sr->uid_user); 337 cmn_err(CE_NOTE, "smbd[%s\\%s]: %s", sr->uid_user->u_domain, 338 sr->uid_user->u_name, 339 xlate_nt_status(NT_STATUS_TOO_MANY_OPENED_FILES)); 340 341 smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES, 342 ERRDOS, ERROR_TOO_MANY_OPEN_FILES); 343 return (NT_STATUS_TOO_MANY_OPENED_FILES); 344 } 345 346 /* This must be NULL at this point */ 347 sr->fid_ofile = NULL; 348 349 op->devstate = 0; 350 351 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 352 case STYPE_DISKTREE: 353 break; 354 355 case STYPE_IPC: 356 /* 357 * No further processing for IPC, we need to either 358 * raise an exception or return success here. 359 */ 360 if ((status = smb_opipe_open(sr)) != NT_STATUS_SUCCESS) 361 smbsr_error(sr, status, 0, 0); 362 return (status); 363 364 default: 365 smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 366 ERRDOS, ERROR_BAD_DEV_TYPE); 367 return (NT_STATUS_BAD_DEVICE_TYPE); 368 } 369 370 if ((pathlen = strlen(pn->pn_path)) >= MAXPATHLEN) { 371 smbsr_error(sr, 0, ERRSRV, ERRfilespecs); 372 return (NT_STATUS_NAME_TOO_LONG); 373 } 374 375 /* 376 * Some clients pass null file names; NT interprets this as "\". 377 */ 378 if (pathlen == 0) { 379 pn->pn_path = "\\"; 380 pathlen = 1; 381 } 382 383 smb_pathname_setup(sr, pn); 384 385 if (is_dir) 386 status = smb_validate_dirname(pn->pn_path); 387 else 388 status = smb_validate_object_name(pn); 389 390 if (status != NT_STATUS_SUCCESS) { 391 smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); 392 return (status); 393 } 394 395 cur_node = op->fqi.fq_dnode ? 396 op->fqi.fq_dnode : sr->tid_tree->t_snode; 397 398 /* 399 * if no path or filename are specified the stream should be 400 * created on cur_node 401 */ 402 if (!is_dir && !pn->pn_pname && !pn->pn_fname && pn->pn_sname) { 403 404 /* can't currently create a stream on the tree root */ 405 if (cur_node == sr->tid_tree->t_snode) { 406 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, 407 ERROR_ACCESS_DENIED); 408 return (NT_STATUS_ACCESS_DENIED); 409 } 410 411 (void) snprintf(op->fqi.fq_last_comp, 412 sizeof (op->fqi.fq_last_comp), 413 "%s%s", cur_node->od_name, pn->pn_sname); 414 415 op->fqi.fq_dnode = cur_node->dir_snode; 416 smb_node_ref(op->fqi.fq_dnode); 417 } else { 418 if (rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path, 419 sr->tid_tree->t_snode, cur_node, &op->fqi.fq_dnode, 420 op->fqi.fq_last_comp)) { 421 smbsr_errno(sr, rc); 422 return (sr->smb_error.status); 423 } 424 } 425 426 /* 427 * If the access mask has only DELETE set (ignore 428 * FILE_READ_ATTRIBUTES), then assume that this 429 * is a request to delete the link (if a link) 430 * and do not follow links. Otherwise, follow 431 * the link to the target. 432 */ 433 daccess = op->desired_access & ~FILE_READ_ATTRIBUTES; 434 435 if (daccess == DELETE) 436 lookup_flags &= ~SMB_FOLLOW_LINKS; 437 438 rc = smb_fsop_lookup_name(sr, kcred, lookup_flags, 439 sr->tid_tree->t_snode, op->fqi.fq_dnode, op->fqi.fq_last_comp, 440 &op->fqi.fq_fnode, &op->fqi.fq_fattr); 441 442 if (rc == 0) { 443 last_comp_found = B_TRUE; 444 (void) strcpy(op->fqi.fq_od_name, 445 op->fqi.fq_fnode->od_name); 446 } else if (rc == ENOENT) { 447 last_comp_found = B_FALSE; 448 op->fqi.fq_fnode = NULL; 449 rc = 0; 450 } else { 451 smb_node_release(op->fqi.fq_dnode); 452 SMB_NULL_FQI_NODES(op->fqi); 453 smbsr_errno(sr, rc); 454 return (sr->smb_error.status); 455 } 456 457 /* 458 * The uniq_fid is a CIFS-server-wide unique identifier for an ofile 459 * which is used to uniquely identify open instances for the 460 * VFS share reservation and POSIX locks. 461 */ 462 463 uniq_fid = SMB_UNIQ_FID(); 464 465 if (last_comp_found) { 466 467 if ((op->fqi.fq_fattr.sa_vattr.va_type != VREG) && 468 (op->fqi.fq_fattr.sa_vattr.va_type != VDIR) && 469 (op->fqi.fq_fattr.sa_vattr.va_type != VLNK)) { 470 471 smb_node_release(op->fqi.fq_fnode); 472 smb_node_release(op->fqi.fq_dnode); 473 SMB_NULL_FQI_NODES(op->fqi); 474 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, 475 ERRnoaccess); 476 return (NT_STATUS_ACCESS_DENIED); 477 } 478 479 node = op->fqi.fq_fnode; 480 dnode = op->fqi.fq_dnode; 481 482 /* 483 * Reject this request if either: 484 * - the target IS a directory and the client requires that 485 * it must NOT be (required by Lotus Notes) 486 * - the target is NOT a directory and client requires that 487 * it MUST be. 488 */ 489 if (op->fqi.fq_fattr.sa_vattr.va_type == VDIR) { 490 if (op->create_options & FILE_NON_DIRECTORY_FILE) { 491 smb_node_release(node); 492 smb_node_release(dnode); 493 SMB_NULL_FQI_NODES(op->fqi); 494 smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY, 495 ERRDOS, ERROR_ACCESS_DENIED); 496 return (NT_STATUS_FILE_IS_A_DIRECTORY); 497 } 498 } else { 499 if ((op->create_options & FILE_DIRECTORY_FILE) || 500 (op->nt_flags & NT_CREATE_FLAG_OPEN_TARGET_DIR)) { 501 smb_node_release(node); 502 smb_node_release(dnode); 503 SMB_NULL_FQI_NODES(op->fqi); 504 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY, 505 ERRDOS, ERROR_DIRECTORY); 506 return (NT_STATUS_NOT_A_DIRECTORY); 507 } 508 } 509 510 /* 511 * No more open should be accepted when "Delete on close" 512 * flag is set. 513 */ 514 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 515 smb_node_release(node); 516 smb_node_release(dnode); 517 SMB_NULL_FQI_NODES(op->fqi); 518 smbsr_error(sr, NT_STATUS_DELETE_PENDING, 519 ERRDOS, ERROR_ACCESS_DENIED); 520 return (NT_STATUS_DELETE_PENDING); 521 } 522 523 /* 524 * Specified file already exists so the operation should fail. 525 */ 526 if (op->create_disposition == FILE_CREATE) { 527 smb_node_release(node); 528 smb_node_release(dnode); 529 SMB_NULL_FQI_NODES(op->fqi); 530 smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION, 531 ERRDOS, ERROR_FILE_EXISTS); 532 return (NT_STATUS_OBJECT_NAME_COLLISION); 533 } 534 535 /* 536 * Windows seems to check read-only access before file 537 * sharing check. 538 * 539 * Check to see if the file is currently readonly (irrespective 540 * of whether this open will make it readonly). 541 */ 542 if (SMB_PATHFILE_IS_READONLY(sr, node)) { 543 /* Files data only */ 544 if (node->attr.sa_vattr.va_type != VDIR) { 545 if (op->desired_access & (FILE_WRITE_DATA | 546 FILE_APPEND_DATA)) { 547 smb_node_release(node); 548 smb_node_release(dnode); 549 SMB_NULL_FQI_NODES(op->fqi); 550 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 551 ERRDOS, ERRnoaccess); 552 return (NT_STATUS_ACCESS_DENIED); 553 } 554 } 555 } 556 557 if (smb_oplock_conflict(node, sr->session, op)) 558 (void) smb_oplock_break(node, sr->session, B_FALSE); 559 560 smb_node_wrlock(node); 561 562 if ((op->create_disposition == FILE_SUPERSEDE) || 563 (op->create_disposition == FILE_OVERWRITE_IF) || 564 (op->create_disposition == FILE_OVERWRITE)) { 565 566 if ((!(op->desired_access & 567 (FILE_WRITE_DATA | FILE_APPEND_DATA | 568 FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA))) || 569 (!smb_sattr_check(node->attr.sa_dosattr, 570 op->dattr))) { 571 smb_node_unlock(node); 572 smb_node_release(node); 573 smb_node_release(dnode); 574 SMB_NULL_FQI_NODES(op->fqi); 575 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 576 ERRDOS, ERRnoaccess); 577 return (NT_STATUS_ACCESS_DENIED); 578 } 579 } 580 581 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid, 582 op->desired_access, op->share_access); 583 584 if (status == NT_STATUS_SHARING_VIOLATION) { 585 smb_node_unlock(node); 586 smb_node_release(node); 587 smb_node_release(dnode); 588 SMB_NULL_FQI_NODES(op->fqi); 589 return (status); 590 } 591 592 status = smb_fsop_access(sr, sr->user_cr, node, 593 op->desired_access); 594 595 if (status != NT_STATUS_SUCCESS) { 596 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); 597 598 smb_node_unlock(node); 599 smb_node_release(node); 600 smb_node_release(dnode); 601 SMB_NULL_FQI_NODES(op->fqi); 602 603 if (status == NT_STATUS_PRIVILEGE_NOT_HELD) { 604 smbsr_error(sr, status, 605 ERRDOS, ERROR_PRIVILEGE_NOT_HELD); 606 return (status); 607 } else { 608 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 609 ERRDOS, ERROR_ACCESS_DENIED); 610 return (NT_STATUS_ACCESS_DENIED); 611 } 612 } 613 614 switch (op->create_disposition) { 615 case FILE_SUPERSEDE: 616 case FILE_OVERWRITE_IF: 617 case FILE_OVERWRITE: 618 if (node->attr.sa_vattr.va_type == VDIR) { 619 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); 620 smb_node_unlock(node); 621 smb_node_release(node); 622 smb_node_release(dnode); 623 SMB_NULL_FQI_NODES(op->fqi); 624 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 625 ERRDOS, ERROR_ACCESS_DENIED); 626 return (NT_STATUS_ACCESS_DENIED); 627 } 628 629 if (node->attr.sa_vattr.va_size != op->dsize) { 630 node->flags &= ~NODE_FLAGS_SET_SIZE; 631 bzero(&new_attr, sizeof (new_attr)); 632 new_attr.sa_vattr.va_size = op->dsize; 633 new_attr.sa_mask = SMB_AT_SIZE; 634 635 rc = smb_fsop_setattr(sr, sr->user_cr, 636 node, &new_attr, &op->fqi.fq_fattr); 637 638 if (rc) { 639 smb_fsop_unshrlock(sr->user_cr, node, 640 uniq_fid); 641 smb_node_unlock(node); 642 smb_node_release(node); 643 smb_node_release(dnode); 644 SMB_NULL_FQI_NODES(op->fqi); 645 smbsr_errno(sr, rc); 646 return (sr->smb_error.status); 647 } 648 649 op->dsize = op->fqi.fq_fattr.sa_vattr.va_size; 650 } 651 652 op->dattr |= FILE_ATTRIBUTE_ARCHIVE; 653 if (op->dattr & FILE_ATTRIBUTE_READONLY) { 654 op->created_readonly = B_TRUE; 655 op->dattr &= ~FILE_ATTRIBUTE_READONLY; 656 } 657 658 smb_node_set_dosattr(node, op->dattr); 659 (void) smb_sync_fsattr(sr, sr->user_cr, node); 660 661 /* 662 * If file is being replaced, 663 * we should remove existing streams 664 */ 665 if (SMB_IS_STREAM(node) == 0) { 666 if (smb_fsop_remove_streams(sr, sr->user_cr, 667 node) != 0) { 668 smb_fsop_unshrlock(sr->user_cr, node, 669 uniq_fid); 670 smb_node_unlock(node); 671 smb_node_release(node); 672 smb_node_release(dnode); 673 SMB_NULL_FQI_NODES(op->fqi); 674 return (sr->smb_error.status); 675 } 676 } 677 678 op->action_taken = SMB_OACT_TRUNCATED; 679 break; 680 681 default: 682 /* 683 * FILE_OPEN or FILE_OPEN_IF. 684 */ 685 op->action_taken = SMB_OACT_OPENED; 686 break; 687 } 688 } else { 689 /* Last component was not found. */ 690 dnode = op->fqi.fq_dnode; 691 692 if (is_dir == 0) 693 is_stream = smb_is_stream_name(pn->pn_path); 694 695 if ((op->create_disposition == FILE_OPEN) || 696 (op->create_disposition == FILE_OVERWRITE)) { 697 smb_node_release(dnode); 698 SMB_NULL_FQI_NODES(op->fqi); 699 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 700 ERRDOS, ERROR_FILE_NOT_FOUND); 701 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 702 } 703 704 if ((is_dir == 0) && (!is_stream) && 705 smb_is_invalid_filename(op->fqi.fq_last_comp)) { 706 smb_node_release(dnode); 707 SMB_NULL_FQI_NODES(op->fqi); 708 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID, 709 ERRDOS, ERROR_INVALID_NAME); 710 return (NT_STATUS_OBJECT_NAME_INVALID); 711 } 712 713 /* 714 * lock the parent dir node in case another create 715 * request to the same parent directory comes in. 716 */ 717 smb_node_wrlock(dnode); 718 719 bzero(&new_attr, sizeof (new_attr)); 720 new_attr.sa_dosattr = op->dattr; 721 new_attr.sa_mask |= SMB_AT_DOSATTR; 722 723 /* 724 * A file created with the readonly bit should not 725 * stop the creator writing to the file until it is 726 * closed. Although the readonly bit will not be set 727 * on the file until it is closed, it will be accounted 728 * for on other fids and on queries based on the node 729 * state. 730 */ 731 if (op->dattr & FILE_ATTRIBUTE_READONLY) 732 new_attr.sa_dosattr &= ~FILE_ATTRIBUTE_READONLY; 733 734 735 if ((op->crtime.tv_sec != 0) && 736 (op->crtime.tv_sec != UINT_MAX)) { 737 738 new_attr.sa_mask |= SMB_AT_CRTIME; 739 new_attr.sa_crtime = op->crtime; 740 } 741 742 if (is_dir == 0) { 743 new_attr.sa_dosattr |= FILE_ATTRIBUTE_ARCHIVE; 744 new_attr.sa_vattr.va_type = VREG; 745 new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR : 746 S_IRUSR | S_IRGRP | S_IROTH | 747 S_IWUSR | S_IWGRP | S_IWOTH; 748 new_attr.sa_mask |= SMB_AT_TYPE | SMB_AT_MODE; 749 750 if (op->dsize) { 751 new_attr.sa_vattr.va_size = op->dsize; 752 new_attr.sa_mask |= SMB_AT_SIZE; 753 } 754 755 rc = smb_fsop_create(sr, sr->user_cr, dnode, 756 op->fqi.fq_last_comp, &new_attr, 757 &op->fqi.fq_fnode, &op->fqi.fq_fattr); 758 759 if (rc != 0) { 760 smb_node_unlock(dnode); 761 smb_node_release(dnode); 762 SMB_NULL_FQI_NODES(op->fqi); 763 smbsr_errno(sr, rc); 764 return (sr->smb_error.status); 765 } 766 767 node = op->fqi.fq_fnode; 768 769 op->fqi.fq_fattr = node->attr; 770 771 smb_node_wrlock(node); 772 773 status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid, 774 op->desired_access, op->share_access); 775 776 if (status == NT_STATUS_SHARING_VIOLATION) { 777 smb_node_unlock(node); 778 if (created) 779 smb_delete_new_object(sr); 780 smb_node_release(node); 781 smb_node_unlock(dnode); 782 smb_node_release(dnode); 783 SMB_NULL_FQI_NODES(op->fqi); 784 return (status); 785 } 786 } else { 787 op->dattr |= FILE_ATTRIBUTE_DIRECTORY; 788 new_attr.sa_vattr.va_type = VDIR; 789 new_attr.sa_vattr.va_mode = 0777; 790 new_attr.sa_mask |= SMB_AT_TYPE | SMB_AT_MODE; 791 792 rc = smb_fsop_mkdir(sr, sr->user_cr, dnode, 793 op->fqi.fq_last_comp, &new_attr, 794 &op->fqi.fq_fnode, &op->fqi.fq_fattr); 795 if (rc != 0) { 796 smb_node_unlock(dnode); 797 smb_node_release(dnode); 798 SMB_NULL_FQI_NODES(op->fqi); 799 smbsr_errno(sr, rc); 800 return (sr->smb_error.status); 801 } 802 803 node = op->fqi.fq_fnode; 804 smb_node_wrlock(node); 805 } 806 807 created = B_TRUE; 808 op->action_taken = SMB_OACT_CREATED; 809 node->flags |= NODE_FLAGS_CREATED; 810 811 if (op->dattr & FILE_ATTRIBUTE_READONLY) { 812 op->created_readonly = B_TRUE; 813 op->dattr &= ~FILE_ATTRIBUTE_READONLY; 814 } 815 } 816 817 op->dattr = smb_node_get_dosattr(node); 818 819 if (max_requested) { 820 smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed); 821 op->desired_access |= max_allowed; 822 } 823 824 /* 825 * if last_write time was in request and is not 0 or -1, 826 * use it as file's mtime 827 */ 828 if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) { 829 smb_node_set_time(node, NULL, &op->mtime, NULL, NULL, 830 SMB_AT_MTIME); 831 (void) smb_sync_fsattr(sr, sr->user_cr, node); 832 } 833 834 of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op, SMB_FTYPE_DISK, 835 uniq_fid, &err); 836 837 if (of == NULL) { 838 smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); 839 if (created) 840 smb_delete_new_object(sr); 841 smb_node_unlock(node); 842 smb_node_release(node); 843 if (created) 844 smb_node_unlock(dnode); 845 smb_node_release(dnode); 846 SMB_NULL_FQI_NODES(op->fqi); 847 smbsr_error(sr, err.status, err.errcls, err.errcode); 848 return (err.status); 849 } 850 851 if (!smb_tree_is_connected(sr->tid_tree)) { 852 smb_ofile_close(of, 0); 853 smb_ofile_release(of); 854 if (created) 855 smb_delete_new_object(sr); 856 smb_node_unlock(node); 857 smb_node_release(node); 858 if (created) 859 smb_node_unlock(dnode); 860 smb_node_release(dnode); 861 SMB_NULL_FQI_NODES(op->fqi); 862 smbsr_error(sr, 0, ERRSRV, ERRinvnid); 863 return (NT_STATUS_UNSUCCESSFUL); 864 } 865 866 /* 867 * Propagate the write-through mode from the open params 868 * to the node: see the notes in the function header. 869 */ 870 if (sr->sr_cfg->skc_sync_enable || 871 (op->create_options & FILE_WRITE_THROUGH)) 872 node->flags |= NODE_FLAGS_WRITE_THROUGH; 873 874 op->fileid = op->fqi.fq_fattr.sa_vattr.va_nodeid; 875 876 /* 877 * Set up the file type in open_param for the response 878 */ 879 op->ftype = SMB_FTYPE_DISK; 880 sr->smb_fid = of->f_fid; 881 sr->fid_ofile = of; 882 883 smb_node_unlock(node); 884 if (created) 885 smb_node_unlock(dnode); 886 887 if (op->fqi.fq_fattr.sa_vattr.va_type == VREG) { 888 smb_oplock_acquire(node, of, op); 889 op->dsize = op->fqi.fq_fattr.sa_vattr.va_size; 890 } else { /* VDIR or VLNK */ 891 op->op_oplock_level = SMB_OPLOCK_NONE; 892 op->dsize = 0; 893 } 894 895 smb_node_release(node); 896 smb_node_release(dnode); 897 SMB_NULL_FQI_NODES(op->fqi); 898 899 return (NT_STATUS_SUCCESS); 900 } 901 902 /* 903 * smb_validate_object_name 904 * 905 * Very basic file name validation. 906 * For filenames, we check for names of the form "AAAn:". Names that 907 * contain three characters, a single digit and a colon (:) are reserved 908 * as DOS device names, i.e. "COM1:". 909 * Stream name validation is handed off to smb_validate_stream_name 910 * 911 * Returns NT status codes. 912 */ 913 uint32_t 914 smb_validate_object_name(smb_pathname_t *pn) 915 { 916 if (pn->pn_fname && 917 strlen(pn->pn_fname) == 5 && 918 mts_isdigit(pn->pn_fname[3]) && 919 pn->pn_fname[4] == ':') { 920 return (NT_STATUS_OBJECT_NAME_INVALID); 921 } 922 923 if (pn->pn_sname) 924 return (smb_validate_stream_name(pn)); 925 926 return (NT_STATUS_SUCCESS); 927 } 928 929 930 /* 931 * This function is used to delete a newly created object (file or 932 * directory) if an error occurs after creation of the object. 933 */ 934 static void 935 smb_delete_new_object(smb_request_t *sr) 936 { 937 open_param_t *op = &sr->arg.open; 938 smb_fqi_t *fqi = &(op->fqi); 939 uint32_t flags = 0; 940 941 if (SMB_TREE_IS_CASEINSENSITIVE(sr)) 942 flags |= SMB_IGNORE_CASE; 943 if (SMB_TREE_SUPPORTS_CATIA(sr)) 944 flags |= SMB_CATIA; 945 946 if (op->create_options & FILE_DIRECTORY_FILE) 947 (void) smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode, 948 fqi->fq_last_comp, flags); 949 else 950 (void) smb_fsop_remove(sr, sr->user_cr, fqi->fq_dnode, 951 fqi->fq_last_comp, flags); 952 } 953 954 /* 955 * smb_pathname_setup 956 * Parse path: pname/fname:sname:stype 957 * 958 * Elements of the smb_pathname_t structure are allocated using 959 * smbsr_malloc and will thus be free'd when the sr is destroyed. 960 * 961 * Eliminate duplicate slashes in pn->pn_path. 962 * Populate pn structure elements with the individual elements 963 * of pn->pn_path. pn->pn_sname will contain the whole stream name 964 * including the stream type and preceding colon: :sname:%DATA 965 * pn_stype will point to the stream type within pn_sname. 966 * 967 * If any element is missing the pointer in pn will be NULL. 968 */ 969 void 970 smb_pathname_setup(smb_request_t *sr, smb_pathname_t *pn) 971 { 972 char *pname, *fname, *sname; 973 int len; 974 975 (void) strcanon(pn->pn_path, "/\\"); 976 977 pname = pn->pn_path; 978 fname = strrchr(pn->pn_path, '\\'); 979 980 if (fname) { 981 if (fname == pname) 982 pname = NULL; 983 else { 984 *fname = '\0'; 985 pn->pn_pname = 986 smb_pathname_strdup(sr, pname); 987 *fname = '\\'; 988 } 989 ++fname; 990 } else { 991 fname = pname; 992 pn->pn_pname = NULL; 993 } 994 995 if (!smb_is_stream_name(fname)) { 996 pn->pn_fname = 997 smb_pathname_strdup(sr, fname); 998 return; 999 } 1000 1001 /* sname can't be NULL smb_is_stream_name checks this */ 1002 sname = strchr(fname, ':'); 1003 if (sname == fname) 1004 fname = NULL; 1005 else { 1006 *sname = '\0'; 1007 pn->pn_fname = 1008 smb_pathname_strdup(sr, fname); 1009 *sname = ':'; 1010 } 1011 1012 pn->pn_sname = smb_pathname_strdup(sr, sname); 1013 pn->pn_stype = strchr(pn->pn_sname + 1, ':'); 1014 if (pn->pn_stype) { 1015 (void) utf8_strupr(pn->pn_stype); 1016 } else { 1017 len = strlen(pn->pn_sname); 1018 pn->pn_sname = smb_pathname_strcat(pn->pn_sname, ":$DATA"); 1019 pn->pn_stype = pn->pn_sname + len; 1020 } 1021 ++pn->pn_stype; 1022 } 1023 1024 /* 1025 * smb_pathname_strdup 1026 * 1027 * Duplicate NULL terminated string s. 1028 * The new string buffer is allocated using smbsr_malloc and 1029 * will thus be free'd when the sr is destroyed. 1030 */ 1031 static char * 1032 smb_pathname_strdup(smb_request_t *sr, const char *s) 1033 { 1034 char *s2; 1035 size_t n; 1036 1037 n = strlen(s) + 1; 1038 s2 = (char *)smbsr_malloc(&sr->request_storage, n); 1039 (void) strlcpy(s2, s, n); 1040 return (s2); 1041 } 1042 1043 /* 1044 * smb_pathname_strcat 1045 * 1046 * Reallocate NULL terminated string s1 to accommodate 1047 * concatenating NULL terminated string s2. 1048 * Append s2 and return resulting NULL terminated string. 1049 * 1050 * The string buffer is reallocated using smbsr_realloc 1051 * and will thus be free'd when the sr is destroyed. 1052 */ 1053 static char * 1054 smb_pathname_strcat(char *s1, const char *s2) 1055 { 1056 size_t n; 1057 1058 n = strlen(s1) + strlen(s2) + 1; 1059 s1 = smbsr_realloc(s1, n); 1060 (void) strlcat(s1, s2, n); 1061 return (s1); 1062 } 1063