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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 #include <smbsrv/smb_kproto.h> 27 #include <smbsrv/smb_fsops.h> 28 #include <smbsrv/smb_vops.h> 29 30 int smb_open_dsize_check = 0; 31 32 /* 33 * Client Request Description 34 * ================================== ================================= 35 * 36 * UCHAR WordCount; Count of parameter words = 15 37 * UCHAR AndXCommand; Secondary (X) command; 0xFF = 38 * none 39 * UCHAR AndXReserved; Reserved (must be 0) 40 * USHORT AndXOffset; Offset to next command WordCount 41 * USHORT Flags; Additional information: bit set- 42 * 0 - return additional info 43 * 1 - exclusive oplock requested 44 * 2 - batch oplock requested 45 * USHORT DesiredAccess; File open mode 46 * USHORT SearchAttributes; 47 * USHORT FileAttributes; 48 * UTIME CreationTime; Creation timestamp for file if it 49 * gets created 50 * USHORT OpenFunction; Action to take if file exists 51 * ULONG AllocationSize; Bytes to reserve on create or 52 * truncate 53 * ULONG Reserved[2]; Must be 0 54 * USHORT ByteCount; Count of data bytes; min = 1 55 * UCHAR BufferFormat 0x04 56 * STRING FileName; 57 * 58 * Server Response Description 59 * ================================== ================================= 60 * 61 * UCHAR WordCount; Count of parameter words = 15 62 * UCHAR AndXCommand; Secondary (X) command; 0xFF = 63 * none 64 * UCHAR AndXReserved; Reserved (must be 0) 65 * USHORT AndXOffset; Offset to next command WordCount 66 * USHORT Fid; File handle 67 * USHORT FileAttributes; 68 * UTIME LastWriteTime; 69 * ULONG DataSize; Current file size 70 * USHORT GrantedAccess; Access permissions actually 71 * allowed 72 * USHORT FileType; Type of file opened 73 * USHORT DeviceState; State of the named pipe 74 * USHORT Action; Action taken 75 * ULONG ServerFid; Server unique file id 76 * USHORT Reserved; Reserved (must be 0) 77 * USHORT ByteCount; Count of data bytes = 0 78 * 79 * DesiredAccess describes the access the client desires for the file (see 80 * section 3.6 - Access Mode Encoding). 81 * 82 * OpenFunction specifies the action to be taken depending on whether or 83 * not the file exists (see section 3.8 - Open Function Encoding). Action 84 * 85 * in the response specifies the action as a result of the Open request 86 * (see section 3.9 - Open Action Encoding). 87 * 88 * SearchAttributes indicates the attributes that the file must have to be 89 * found while searching to see if it exists. The encoding of this field 90 * is described in the "File Attribute Encoding" section elsewhere in this 91 * document. If SearchAttributes is zero then only normal files are 92 * returned. If the system file, hidden or directory attributes are 93 * specified then the search is inclusive -- both the specified type(s) of 94 * files and normal files are returned. 95 * 96 * FileType returns the kind of resource actually opened: 97 * 98 * Name Value Description 99 * ========================== ====== ================================== 100 * 101 * FileTypeDisk 0 Disk file or directory as defined 102 * in the attribute field 103 * FileTypeByteModePipe 1 Named pipe in byte mode 104 * FileTypeMessageModePipe 2 Named pipe in message mode 105 * FileTypePrinter 3 Spooled printer 106 * FileTypeUnknown 0xFFFF Unrecognized resource type 107 * 108 * If bit0 of Flags is clear, the FileAttributes, LastWriteTime, DataSize, 109 * FileType, and DeviceState have indeterminate values in the response. 110 * 111 * This SMB can request an oplock on the opened file. Oplocks are fully 112 * described in the "Oplocks" section elsewhere in this document, and there 113 * is also discussion of oplocks in the SMB_COM_LOCKING_ANDX SMB 114 * description. Bit1 and bit2 of the Flags field are used to request 115 * oplocks during open. 116 * 117 * The following SMBs may follow SMB_COM_OPEN_ANDX: 118 * 119 * SMB_COM_READ SMB_COM_READ_ANDX 120 * SMB_COM_IOCTL 121 */ 122 123 /* 124 * This message is sent to obtain a file handle for a data file. This 125 * returned Fid is used in subsequent client requests such as read, write, 126 * close, etc. 127 * 128 * Client Request Description 129 * ================================== ================================= 130 * 131 * UCHAR WordCount; Count of parameter words = 2 132 * USHORT DesiredAccess; Mode - read/write/share 133 * USHORT SearchAttributes; 134 * USHORT ByteCount; Count of data bytes; min = 2 135 * UCHAR BufferFormat; 0x04 136 * STRING FileName[]; File name 137 * 138 * FileName is the fully qualified file name, relative to the root of the 139 * share specified in the Tid field of the SMB header. If Tid in the SMB 140 * header refers to a print share, this SMB creates a new file which will 141 * be spooled to the printer when closed. In this case, FileName is 142 * ignored. 143 * 144 * SearchAttributes specifies the type of file desired. The encoding is 145 * described in the "File Attribute Encoding" section. 146 * 147 * DesiredAccess controls the mode under which the file is opened, and the 148 * file will be opened only if the client has the appropriate permissions. 149 * The encoding of DesiredAccess is discussed in the section entitled 150 * "Access Mode Encoding". 151 * 152 * Server Response Description 153 * ================================== ================================= 154 * 155 * UCHAR WordCount; Count of parameter words = 7 156 * USHORT Fid; File handle 157 * USHORT FileAttributes; Attributes of opened file 158 * UTIME LastWriteTime; Time file was last written 159 * ULONG DataSize; File size 160 * USHORT GrantedAccess; Access allowed 161 * USHORT ByteCount; Count of data bytes = 0 162 * 163 * Fid is the handle value which should be used for subsequent file 164 * operations. 165 * 166 * FileAttributes specifies the type of file obtained. The encoding is 167 * described in the "File Attribute Encoding" section. 168 * 169 * GrantedAccess indicates the access permissions actually allowed, and may 170 * have one of the following values: 171 * 172 * 0 read-only 173 * 1 write-only 174 * 2 read/write 175 * 176 * File Handles (Fids) are scoped per client. A Pid may reference any Fid 177 * established by itself or any other Pid on the client (so far as the 178 * server is concerned). The actual accesses allowed through the Fid 179 * depends on the open and deny modes specified when the file was opened 180 * (see below). 181 * 182 * The MS-DOS compatibility mode of file open provides exclusion at the 183 * client level. A file open in compatibility mode may be opened (also in 184 * compatibility mode) any number of times for any combination of reading 185 * and writing (subject to the user's permissions) by any Pid on the same 186 * client. If the first client has the file open for writing, then the 187 * file may not be opened in any way by any other client. If the first 188 * client has the file open only for reading, then other clients may open 189 * the file, in compatibility mode, for reading.. The above 190 * notwithstanding, if the filename has an extension of .EXE, .DLL, .SYM, 191 * or .COM other clients are permitted to open the file regardless of 192 * read/write open modes of other compatibility mode opens. However, once 193 * multiple clients have the file open for reading, no client is permitted 194 * to open the file for writing and no other client may open the file in 195 * any mode other than compatibility mode. 196 * 197 * The other file exclusion modes (Deny read/write, Deny write, Deny read, 198 * Deny none) provide exclusion at the file level. A file opened in any 199 * "Deny" mode may be opened again only for the accesses allowed by the 200 * Deny mode (subject to the user's permissions). This is true regardless 201 * of the identity of the second opener -a different client, a Pid from the 202 * same client, or the Pid that already has the file open. For example, if 203 * a file is open in "Deny write" mode a second open may only obtain read 204 * permission to the file. 205 * 206 * Although Fids are available to all Pids on a client, Pids other than the 207 * owner may not have the full access rights specified in the open mode by 208 * the Fid's creator. If the open creating the Fid specified a deny mode, 209 * then any Pid using the Fid, other than the creating Pid, will have only 210 * those access rights determined by "anding" the open mode rights and the 211 * deny mode rights, i.e., the deny mode is checked on all file accesses. 212 * For example, if a file is opened for Read/Write in Deny write mode, then 213 * other clients may only read the file and cannot write; if a file is 214 * opened for Read in Deny read mode, then the other clients can neither 215 * read nor write the file. 216 */ 217 218 smb_sdrc_t 219 smb_pre_open(smb_request_t *sr) 220 { 221 struct open_param *op = &sr->arg.open; 222 int rc; 223 224 bzero(op, sizeof (sr->arg.open)); 225 226 rc = smbsr_decode_vwv(sr, "ww", &op->omode, &op->fqi.fq_sattr); 227 if (rc == 0) 228 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path); 229 230 DTRACE_SMB_START(op__Open, smb_request_t *, sr); /* arg.open */ 231 232 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 233 } 234 235 void 236 smb_post_open(smb_request_t *sr) 237 { 238 DTRACE_SMB_DONE(op__Open, smb_request_t *, sr); 239 } 240 241 smb_sdrc_t 242 smb_com_open(smb_request_t *sr) 243 { 244 struct open_param *op = &sr->arg.open; 245 smb_ofile_t *of; 246 uint32_t mtime_sec; 247 uint32_t status; 248 uint16_t file_attr; 249 int rc; 250 251 op->desired_access = smb_omode_to_amask(op->omode); 252 op->share_access = smb_denymode_to_sharemode(op->omode, 253 op->fqi.fq_path.pn_path); 254 op->crtime.tv_sec = op->crtime.tv_nsec = 0; 255 op->create_disposition = FILE_OPEN; 256 op->create_options = FILE_NON_DIRECTORY_FILE; 257 if (op->omode & SMB_DA_WRITE_THROUGH) 258 op->create_options |= FILE_WRITE_THROUGH; 259 260 if (sr->smb_flg & SMB_FLAGS_OPLOCK) { 261 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY) 262 op->op_oplock_level = SMB_OPLOCK_BATCH; 263 else 264 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 265 } else { 266 op->op_oplock_level = SMB_OPLOCK_NONE; 267 } 268 269 if (smb_open_dsize_check && op->dsize > UINT_MAX) { 270 smbsr_error(sr, 0, ERRDOS, ERRbadaccess); 271 return (SDRC_ERROR); 272 } 273 274 /* 275 * The real open call. Note: this gets attributes into 276 * op->fqi.fq_fattr (SMB_AT_ALL). We need those below. 277 */ 278 status = smb_common_open(sr); 279 if (status != NT_STATUS_SUCCESS) { 280 smbsr_status(sr, status, 0, 0); 281 return (SDRC_ERROR); 282 } 283 if (op->op_oplock_level != SMB_OPLOCK_NONE) { 284 /* Oplock req. in op->op_oplock_level etc. */ 285 smb1_oplock_acquire(sr, B_FALSE); 286 } 287 288 /* 289 * NB: after the above smb_common_open() success, 290 * we have a handle allocated (sr->fid_ofile). 291 * If we don't return success, we must close it. 292 */ 293 of = sr->fid_ofile; 294 295 if (op->op_oplock_level == SMB_OPLOCK_NONE) { 296 sr->smb_flg &= 297 ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY); 298 } 299 300 file_attr = op->dattr & FILE_ATTRIBUTE_MASK; 301 mtime_sec = smb_time_gmt_to_local(sr, 302 op->fqi.fq_fattr.sa_vattr.va_mtime.tv_sec); 303 304 rc = smbsr_encode_result(sr, 7, 0, "bwwllww", 305 7, 306 sr->smb_fid, 307 file_attr, 308 mtime_sec, 309 (uint32_t)op->dsize, 310 op->omode, 311 (uint16_t)0); /* bcc */ 312 313 if (rc == 0) 314 return (SDRC_SUCCESS); 315 316 smb_ofile_close(of, 0); 317 return (SDRC_ERROR); 318 } 319 320 int smb_openx_enable_extended_response = 1; 321 322 /* 323 * smb_pre_open_andx 324 * For compatibility with windows servers, the search attributes 325 * specified in the request are ignored. 326 */ 327 smb_sdrc_t 328 smb_pre_open_andx(smb_request_t *sr) 329 { 330 struct open_param *op = &sr->arg.open; 331 uint16_t openx_flags; 332 uint32_t alloc_size; 333 uint32_t creation_time; 334 uint16_t file_attr, sattr; 335 int rc; 336 337 bzero(op, sizeof (sr->arg.open)); 338 339 rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com, 340 &sr->andx_off, &openx_flags, &op->omode, &sattr, 341 &file_attr, &creation_time, &op->ofun, &alloc_size, &op->timeo); 342 343 if (rc == 0) { 344 rc = smbsr_decode_data(sr, "%u", sr, &op->fqi.fq_path.pn_path); 345 346 op->dattr = file_attr; 347 op->dsize = alloc_size; 348 349 /* 350 * The openx_flags use some "extended" flags that 351 * happen to match some of the NtCreateX flags. 352 */ 353 if (openx_flags & NT_CREATE_FLAG_REQUEST_OPBATCH) 354 op->op_oplock_level = SMB_OPLOCK_BATCH; 355 else if (openx_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) 356 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 357 else 358 op->op_oplock_level = SMB_OPLOCK_NONE; 359 if (openx_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) 360 op->nt_flags |= NT_CREATE_FLAG_EXTENDED_RESPONSE; 361 362 if ((creation_time != 0) && (creation_time != UINT_MAX)) 363 op->crtime.tv_sec = 364 smb_time_local_to_gmt(sr, creation_time); 365 op->crtime.tv_nsec = 0; 366 367 op->create_disposition = smb_ofun_to_crdisposition(op->ofun); 368 } 369 370 DTRACE_SMB_START(op__OpenX, smb_request_t *, sr); /* arg.open */ 371 372 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 373 } 374 375 void 376 smb_post_open_andx(smb_request_t *sr) 377 { 378 DTRACE_SMB_DONE(op__OpenX, smb_request_t *, sr); 379 } 380 381 smb_sdrc_t 382 smb_com_open_andx(smb_request_t *sr) 383 { 384 struct open_param *op = &sr->arg.open; 385 smb_attr_t *ap = &op->fqi.fq_fattr; 386 smb_ofile_t *of; 387 uint32_t status; 388 uint32_t mtime_sec; 389 uint16_t file_attr; 390 int rc; 391 392 op->desired_access = smb_omode_to_amask(op->omode); 393 op->share_access = smb_denymode_to_sharemode(op->omode, 394 op->fqi.fq_path.pn_path); 395 396 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) { 397 smbsr_error(sr, 0, ERRDOS, ERRbadaccess); 398 return (SDRC_ERROR); 399 } 400 401 op->create_options = FILE_NON_DIRECTORY_FILE; 402 if (op->omode & SMB_DA_WRITE_THROUGH) 403 op->create_options |= FILE_WRITE_THROUGH; 404 405 if (smb_open_dsize_check && op->dsize > UINT_MAX) { 406 smbsr_error(sr, 0, ERRDOS, ERRbadaccess); 407 return (SDRC_ERROR); 408 } 409 410 status = smb_common_open(sr); 411 if (status != NT_STATUS_SUCCESS) { 412 smbsr_status(sr, status, 0, 0); 413 return (SDRC_ERROR); 414 } 415 if (op->op_oplock_level != SMB_OPLOCK_NONE) { 416 /* Oplock req. in op->op_oplock_level etc. */ 417 smb1_oplock_acquire(sr, B_FALSE); 418 } 419 420 /* 421 * NB: after the above smb_common_open() success, 422 * we have a handle allocated (sr->fid_ofile). 423 * If we don't return success, we must close it. 424 */ 425 of = sr->fid_ofile; 426 427 if (op->op_oplock_level != SMB_OPLOCK_NONE) 428 op->action_taken |= SMB_OACT_OPLOCK; 429 else 430 op->action_taken &= ~SMB_OACT_OPLOCK; 431 432 file_attr = op->dattr & FILE_ATTRIBUTE_MASK; 433 mtime_sec = smb_time_gmt_to_local(sr, ap->sa_vattr.va_mtime.tv_sec); 434 435 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 436 case STYPE_DISKTREE: 437 case STYPE_PRINTQ: 438 break; 439 440 case STYPE_IPC: 441 mtime_sec = 0; 442 break; 443 444 default: 445 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST, 446 ERRDOS, ERROR_INVALID_FUNCTION); 447 goto errout; 448 } 449 450 if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 && 451 smb_openx_enable_extended_response != 0) { 452 uint32_t MaxAccess = 0; 453 if (of->f_node != NULL) { 454 smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess); 455 } 456 MaxAccess |= of->f_granted_access; 457 458 rc = smbsr_encode_result( 459 sr, 19, 0, "bb.wwwllwwwwl2.llw", 460 19, /* word count (b) */ 461 sr->andx_com, /* (b.) */ 462 VAR_BCC, /* andx offset (w) */ 463 sr->smb_fid, /* (w) */ 464 file_attr, /* (w) */ 465 mtime_sec, /* (l) */ 466 (uint32_t)op->dsize, /* (l) */ 467 op->omode, /* (w) */ 468 op->ftype, /* (w) */ 469 op->devstate, /* (w) */ 470 op->action_taken, /* (w) */ 471 0, /* legacy fileid (l) */ 472 /* reserved (2.) */ 473 MaxAccess, /* (l) */ 474 0, /* guest access (l) */ 475 0); /* byte count (w) */ 476 477 } else { 478 rc = smbsr_encode_result( 479 sr, 15, 0, "bb.wwwllwwwwl2.w", 480 15, /* word count (b) */ 481 sr->andx_com, /* (b.) */ 482 VAR_BCC, /* andx offset (w) */ 483 sr->smb_fid, /* (w) */ 484 file_attr, /* (w) */ 485 mtime_sec, /* (l) */ 486 (uint32_t)op->dsize, /* (l) */ 487 op->omode, /* (w) */ 488 op->ftype, /* (w) */ 489 op->devstate, /* (w) */ 490 op->action_taken, /* (w) */ 491 0, /* legacy fileid (l) */ 492 /* reserved (2.) */ 493 0); /* byte count (w) */ 494 } 495 496 if (rc == 0) 497 return (SDRC_SUCCESS); 498 499 errout: 500 smb_ofile_close(of, 0); 501 return (SDRC_ERROR); 502 } 503 504 smb_sdrc_t 505 smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa) 506 { 507 struct open_param *op = &sr->arg.open; 508 uint32_t creation_time; 509 uint32_t alloc_size; 510 uint32_t ea_list_size; 511 uint16_t flags; 512 uint16_t file_attr; 513 uint32_t status; 514 int rc; 515 516 bzero(op, sizeof (sr->arg.open)); 517 518 rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u", 519 sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr, 520 &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path); 521 if (rc != 0) 522 return (SDRC_ERROR); 523 524 /* 525 * The data part of this transaction may contain an EA list. 526 * See: SMB_FEA_LIST ExtendedAttributeList 527 * 528 * If we find a non-empty EA list payload, return the special 529 * error that tells the caller this FS does not suport EAs. 530 * 531 * Note: the first word is the size of the whole data segment, 532 * INCLUDING the size of that length word. That means if 533 * the length word specifies a size less than four, it's 534 * invalid (and probably a client trying something fishy). 535 */ 536 rc = smb_mbc_decodef(&xa->req_data_mb, "l", &ea_list_size); 537 if (rc == 0 && ea_list_size > 4) { 538 smbsr_status(sr, NT_STATUS_EAS_NOT_SUPPORTED, 0, 0); 539 return (SDRC_ERROR); 540 } 541 542 if ((creation_time != 0) && (creation_time != UINT_MAX)) 543 op->crtime.tv_sec = smb_time_local_to_gmt(sr, creation_time); 544 op->crtime.tv_nsec = 0; 545 546 op->dattr = file_attr; 547 op->dsize = alloc_size; 548 op->create_options = FILE_NON_DIRECTORY_FILE; 549 550 op->desired_access = smb_omode_to_amask(op->omode); 551 op->share_access = smb_denymode_to_sharemode(op->omode, 552 op->fqi.fq_path.pn_path); 553 554 op->create_disposition = smb_ofun_to_crdisposition(op->ofun); 555 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) 556 op->create_disposition = FILE_CREATE; 557 558 if (op->omode & SMB_DA_WRITE_THROUGH) 559 op->create_options |= FILE_WRITE_THROUGH; 560 561 if (sr->smb_flg & SMB_FLAGS_OPLOCK) { 562 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY) 563 op->op_oplock_level = SMB_OPLOCK_BATCH; 564 else 565 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 566 } else { 567 op->op_oplock_level = SMB_OPLOCK_NONE; 568 } 569 570 status = smb_common_open(sr); 571 if (status != NT_STATUS_SUCCESS) { 572 smbsr_status(sr, status, 0, 0); 573 return (SDRC_ERROR); 574 } 575 if (op->op_oplock_level != SMB_OPLOCK_NONE) { 576 /* Oplock req. in op->op_oplock_level etc. */ 577 smb1_oplock_acquire(sr, B_FALSE); 578 } 579 580 if (op->op_oplock_level != SMB_OPLOCK_NONE) 581 op->action_taken |= SMB_OACT_OPLOCK; 582 else 583 op->action_taken &= ~SMB_OACT_OPLOCK; 584 585 file_attr = op->dattr & FILE_ATTRIBUTE_MASK; 586 587 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) 588 op->dsize = 0; 589 590 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl", 591 sr->smb_fid, 592 file_attr, 593 (uint32_t)0, /* creation time */ 594 (uint32_t)op->dsize, 595 op->omode, 596 op->ftype, 597 op->devstate, 598 op->action_taken, 599 op->fileid, 600 (uint16_t)0, /* EA error offset */ 601 (uint32_t)0); /* EA list length */ 602 603 return (SDRC_SUCCESS); 604 } 605