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 2016 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_2(op__Open__start, smb_request_t *, sr, 231 struct open_param *, op); 232 233 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 234 } 235 236 void 237 smb_post_open(smb_request_t *sr) 238 { 239 DTRACE_SMB_1(op__Open__done, smb_request_t *, sr); 240 } 241 242 smb_sdrc_t 243 smb_com_open(smb_request_t *sr) 244 { 245 struct open_param *op = &sr->arg.open; 246 smb_ofile_t *of; 247 smb_attr_t attr; 248 uint32_t status; 249 uint16_t file_attr; 250 int rc; 251 252 op->desired_access = smb_omode_to_amask(op->omode); 253 op->share_access = smb_denymode_to_sharemode(op->omode, 254 op->fqi.fq_path.pn_path); 255 op->crtime.tv_sec = op->crtime.tv_nsec = 0; 256 op->create_disposition = FILE_OPEN; 257 op->create_options = FILE_NON_DIRECTORY_FILE; 258 if (op->omode & SMB_DA_WRITE_THROUGH) 259 op->create_options |= FILE_WRITE_THROUGH; 260 261 if (sr->smb_flg & SMB_FLAGS_OPLOCK) { 262 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY) 263 op->op_oplock_level = SMB_OPLOCK_BATCH; 264 else 265 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 266 } else { 267 op->op_oplock_level = SMB_OPLOCK_NONE; 268 } 269 op->op_oplock_levelII = B_FALSE; 270 271 if (smb_open_dsize_check && op->dsize > UINT_MAX) { 272 smbsr_error(sr, 0, ERRDOS, ERRbadaccess); 273 return (SDRC_ERROR); 274 } 275 276 status = smb_common_open(sr); 277 if (status != NT_STATUS_SUCCESS) { 278 smbsr_status(sr, status, 0, 0); 279 return (SDRC_ERROR); 280 } 281 282 /* 283 * NB: after the above smb_common_open() success, 284 * we have a handle allocated (sr->fid_ofile). 285 * If we don't return success, we must close it. 286 */ 287 of = sr->fid_ofile; 288 289 if (op->op_oplock_level == SMB_OPLOCK_NONE) { 290 sr->smb_flg &= 291 ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY); 292 } 293 294 file_attr = op->dattr & FILE_ATTRIBUTE_MASK; 295 bzero(&attr, sizeof (attr)); 296 attr.sa_mask = SMB_AT_MTIME; 297 rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr); 298 if (rc != 0) { 299 smbsr_errno(sr, rc); 300 goto errout; 301 } 302 303 rc = smbsr_encode_result(sr, 7, 0, "bwwllww", 304 7, 305 sr->smb_fid, 306 file_attr, 307 smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec), 308 (uint32_t)op->dsize, 309 op->omode, 310 (uint16_t)0); /* bcc */ 311 312 if (rc == 0) 313 return (SDRC_SUCCESS); 314 315 errout: 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_OPLOCK) 354 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 355 else if (openx_flags & NT_CREATE_FLAG_REQUEST_OPBATCH) 356 op->op_oplock_level = SMB_OPLOCK_BATCH; 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_2(op__OpenX__start, smb_request_t *, sr, 371 struct open_param *, op); 372 373 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 374 } 375 376 void 377 smb_post_open_andx(smb_request_t *sr) 378 { 379 DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr); 380 } 381 382 smb_sdrc_t 383 smb_com_open_andx(smb_request_t *sr) 384 { 385 struct open_param *op = &sr->arg.open; 386 smb_attr_t *ap = &op->fqi.fq_fattr; 387 smb_ofile_t *of; 388 uint32_t status; 389 uint32_t mtime_sec; 390 uint16_t file_attr; 391 int rc; 392 393 op->desired_access = smb_omode_to_amask(op->omode); 394 op->share_access = smb_denymode_to_sharemode(op->omode, 395 op->fqi.fq_path.pn_path); 396 397 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) { 398 smbsr_error(sr, 0, ERRDOS, ERRbadaccess); 399 return (SDRC_ERROR); 400 } 401 402 op->create_options = FILE_NON_DIRECTORY_FILE; 403 if (op->omode & SMB_DA_WRITE_THROUGH) 404 op->create_options |= FILE_WRITE_THROUGH; 405 406 op->op_oplock_levelII = B_FALSE; 407 408 if (smb_open_dsize_check && op->dsize > UINT_MAX) { 409 smbsr_error(sr, 0, ERRDOS, ERRbadaccess); 410 return (SDRC_ERROR); 411 } 412 413 status = smb_common_open(sr); 414 if (status != NT_STATUS_SUCCESS) { 415 smbsr_status(sr, status, 0, 0); 416 return (SDRC_ERROR); 417 } 418 419 /* 420 * NB: after the above smb_common_open() success, 421 * we have a handle allocated (sr->fid_ofile). 422 * If we don't return success, we must close it. 423 */ 424 of = sr->fid_ofile; 425 426 if (op->op_oplock_level != SMB_OPLOCK_NONE) 427 op->action_taken |= SMB_OACT_OPLOCK; 428 else 429 op->action_taken &= ~SMB_OACT_OPLOCK; 430 431 file_attr = op->dattr & FILE_ATTRIBUTE_MASK; 432 mtime_sec = smb_time_gmt_to_local(sr, ap->sa_vattr.va_mtime.tv_sec); 433 434 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 435 case STYPE_DISKTREE: 436 case STYPE_PRINTQ: 437 break; 438 439 case STYPE_IPC: 440 mtime_sec = 0; 441 break; 442 443 default: 444 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST, 445 ERRDOS, ERROR_INVALID_FUNCTION); 446 goto errout; 447 } 448 449 if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 && 450 smb_openx_enable_extended_response != 0) { 451 uint32_t MaxAccess = 0; 452 if (of->f_node != NULL) { 453 smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess); 454 } 455 MaxAccess |= of->f_granted_access; 456 457 rc = smbsr_encode_result( 458 sr, 19, 0, "bb.wwwllwwwwl2.llw", 459 19, /* word count (b) */ 460 sr->andx_com, /* (b.) */ 461 VAR_BCC, /* andx offset (w) */ 462 sr->smb_fid, /* (w) */ 463 file_attr, /* (w) */ 464 mtime_sec, /* (l) */ 465 (uint32_t)op->dsize, /* (l) */ 466 op->omode, /* (w) */ 467 op->ftype, /* (w) */ 468 op->devstate, /* (w) */ 469 op->action_taken, /* (w) */ 470 0, /* legacy fileid (l) */ 471 /* reserved (2.) */ 472 MaxAccess, /* (l) */ 473 0, /* guest access (l) */ 474 0); /* byte count (w) */ 475 476 } else { 477 rc = smbsr_encode_result( 478 sr, 15, 0, "bb.wwwllwwwwl2.w", 479 15, /* word count (b) */ 480 sr->andx_com, /* (b.) */ 481 VAR_BCC, /* andx offset (w) */ 482 sr->smb_fid, /* (w) */ 483 file_attr, /* (w) */ 484 mtime_sec, /* (l) */ 485 (uint32_t)op->dsize, /* (l) */ 486 op->omode, /* (w) */ 487 op->ftype, /* (w) */ 488 op->devstate, /* (w) */ 489 op->action_taken, /* (w) */ 490 0, /* legacy fileid (l) */ 491 /* reserved (2.) */ 492 0); /* byte count (w) */ 493 } 494 495 if (rc == 0) 496 return (SDRC_SUCCESS); 497 498 errout: 499 smb_ofile_close(of, 0); 500 return (SDRC_ERROR); 501 } 502 503 smb_sdrc_t 504 smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa) 505 { 506 struct open_param *op = &sr->arg.open; 507 uint32_t creation_time; 508 uint32_t alloc_size; 509 uint32_t ea_list_size; 510 uint16_t flags; 511 uint16_t file_attr; 512 uint32_t status; 513 int rc; 514 515 bzero(op, sizeof (sr->arg.open)); 516 517 rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u", 518 sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr, 519 &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path); 520 if (rc != 0) 521 return (SDRC_ERROR); 522 523 /* 524 * The data part of this transaction may contain an EA list. 525 * See: SMB_FEA_LIST ExtendedAttributeList 526 * 527 * If we find a non-empty EA list payload, return the special 528 * error that tells the caller this FS does not suport EAs. 529 * 530 * Note: the first word is the size of the whole data segment, 531 * INCLUDING the size of that length word. That means if 532 * the length word specifies a size less than four, it's 533 * invalid (and probably a client trying something fishy). 534 */ 535 rc = smb_mbc_decodef(&xa->req_data_mb, "l", &ea_list_size); 536 if (rc == 0 && ea_list_size > 4) { 537 smbsr_status(sr, NT_STATUS_EAS_NOT_SUPPORTED, 0, 0); 538 return (SDRC_ERROR); 539 } 540 541 if ((creation_time != 0) && (creation_time != UINT_MAX)) 542 op->crtime.tv_sec = smb_time_local_to_gmt(sr, creation_time); 543 op->crtime.tv_nsec = 0; 544 545 op->dattr = file_attr; 546 op->dsize = alloc_size; 547 op->create_options = FILE_NON_DIRECTORY_FILE; 548 549 op->desired_access = smb_omode_to_amask(op->omode); 550 op->share_access = smb_denymode_to_sharemode(op->omode, 551 op->fqi.fq_path.pn_path); 552 553 op->create_disposition = smb_ofun_to_crdisposition(op->ofun); 554 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) 555 op->create_disposition = FILE_CREATE; 556 557 if (op->omode & SMB_DA_WRITE_THROUGH) 558 op->create_options |= FILE_WRITE_THROUGH; 559 560 if (sr->smb_flg & SMB_FLAGS_OPLOCK) { 561 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY) 562 op->op_oplock_level = SMB_OPLOCK_BATCH; 563 else 564 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 565 } else { 566 op->op_oplock_level = SMB_OPLOCK_NONE; 567 } 568 op->op_oplock_levelII = B_FALSE; 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 576 if (op->op_oplock_level != SMB_OPLOCK_NONE) 577 op->action_taken |= SMB_OACT_OPLOCK; 578 else 579 op->action_taken &= ~SMB_OACT_OPLOCK; 580 581 file_attr = op->dattr & FILE_ATTRIBUTE_MASK; 582 583 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) 584 op->dsize = 0; 585 586 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl", 587 sr->smb_fid, 588 file_attr, 589 (uint32_t)0, /* creation time */ 590 (uint32_t)op->dsize, 591 op->omode, 592 op->ftype, 593 op->devstate, 594 op->action_taken, 595 op->fileid, 596 (uint16_t)0, /* EA error offset */ 597 (uint32_t)0); /* EA list length */ 598 599 return (SDRC_SUCCESS); 600 }