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