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_1(op__Open__start, 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_1(op__Open__done, 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 smb_attr_t attr; 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 op->op_oplock_levelII = B_FALSE; 269 270 if (smb_open_dsize_check && op->dsize > UINT_MAX) { 271 smbsr_error(sr, 0, ERRDOS, ERRbadaccess); 272 return (SDRC_ERROR); 273 } 274 275 status = smb_common_open(sr); 276 if (status != NT_STATUS_SUCCESS) { 277 smbsr_status(sr, status, 0, 0); 278 return (SDRC_ERROR); 279 } 280 281 /* 282 * NB: after the above smb_common_open() success, 283 * we have a handle allocated (sr->fid_ofile). 284 * If we don't return success, we must close it. 285 */ 286 of = sr->fid_ofile; 287 288 if (op->op_oplock_level == SMB_OPLOCK_NONE) { 289 sr->smb_flg &= 290 ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY); 291 } 292 293 file_attr = op->dattr & FILE_ATTRIBUTE_MASK; 294 bzero(&attr, sizeof (attr)); 295 attr.sa_mask = SMB_AT_MTIME; 296 rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr); 297 if (rc != 0) { 298 smbsr_errno(sr, rc); 299 goto errout; 300 } 301 302 rc = smbsr_encode_result(sr, 7, 0, "bwwllww", 303 7, 304 sr->smb_fid, 305 file_attr, 306 smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec), 307 (uint32_t)op->dsize, 308 op->omode, 309 (uint16_t)0); /* bcc */ 310 311 if (rc == 0) 312 return (SDRC_SUCCESS); 313 314 errout: 315 smb_ofile_close(of, 0); 316 return (SDRC_ERROR); 317 } 318 319 int smb_openx_enable_extended_response = 1; 320 321 /* 322 * smb_pre_open_andx 323 * For compatibility with windows servers, the search attributes 324 * specified in the request are ignored. 325 */ 326 smb_sdrc_t 327 smb_pre_open_andx(smb_request_t *sr) 328 { 329 struct open_param *op = &sr->arg.open; 330 uint16_t openx_flags; 331 uint32_t alloc_size; 332 uint32_t creation_time; 333 uint16_t file_attr, sattr; 334 int rc; 335 336 bzero(op, sizeof (sr->arg.open)); 337 338 rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com, 339 &sr->andx_off, &openx_flags, &op->omode, &sattr, 340 &file_attr, &creation_time, &op->ofun, &alloc_size, &op->timeo); 341 342 if (rc == 0) { 343 rc = smbsr_decode_data(sr, "%u", sr, &op->fqi.fq_path.pn_path); 344 345 op->dattr = file_attr; 346 op->dsize = alloc_size; 347 348 /* 349 * The openx_flags use some "extended" flags that 350 * happen to match some of the NtCreateX flags. 351 */ 352 if (openx_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) 353 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 354 else if (openx_flags & NT_CREATE_FLAG_REQUEST_OPBATCH) 355 op->op_oplock_level = SMB_OPLOCK_BATCH; 356 else 357 op->op_oplock_level = SMB_OPLOCK_NONE; 358 if (openx_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) 359 op->nt_flags |= NT_CREATE_FLAG_EXTENDED_RESPONSE; 360 361 if ((creation_time != 0) && (creation_time != UINT_MAX)) 362 op->crtime.tv_sec = 363 smb_time_local_to_gmt(sr, creation_time); 364 op->crtime.tv_nsec = 0; 365 366 op->create_disposition = smb_ofun_to_crdisposition(op->ofun); 367 } 368 369 DTRACE_SMB_1(op__OpenX__start, smb_request_t *, sr); /* arg.open */ 370 371 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 372 } 373 374 void 375 smb_post_open_andx(smb_request_t *sr) 376 { 377 DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr); 378 } 379 380 smb_sdrc_t 381 smb_com_open_andx(smb_request_t *sr) 382 { 383 struct open_param *op = &sr->arg.open; 384 smb_attr_t *ap = &op->fqi.fq_fattr; 385 smb_ofile_t *of; 386 uint32_t status; 387 uint32_t mtime_sec; 388 uint16_t file_attr; 389 int rc; 390 391 op->desired_access = smb_omode_to_amask(op->omode); 392 op->share_access = smb_denymode_to_sharemode(op->omode, 393 op->fqi.fq_path.pn_path); 394 395 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) { 396 smbsr_error(sr, 0, ERRDOS, ERRbadaccess); 397 return (SDRC_ERROR); 398 } 399 400 op->create_options = FILE_NON_DIRECTORY_FILE; 401 if (op->omode & SMB_DA_WRITE_THROUGH) 402 op->create_options |= FILE_WRITE_THROUGH; 403 404 op->op_oplock_levelII = B_FALSE; 405 406 if (smb_open_dsize_check && op->dsize > UINT_MAX) { 407 smbsr_error(sr, 0, ERRDOS, ERRbadaccess); 408 return (SDRC_ERROR); 409 } 410 411 status = smb_common_open(sr); 412 if (status != NT_STATUS_SUCCESS) { 413 smbsr_status(sr, status, 0, 0); 414 return (SDRC_ERROR); 415 } 416 417 /* 418 * NB: after the above smb_common_open() success, 419 * we have a handle allocated (sr->fid_ofile). 420 * If we don't return success, we must close it. 421 */ 422 of = sr->fid_ofile; 423 424 if (op->op_oplock_level != SMB_OPLOCK_NONE) 425 op->action_taken |= SMB_OACT_OPLOCK; 426 else 427 op->action_taken &= ~SMB_OACT_OPLOCK; 428 429 file_attr = op->dattr & FILE_ATTRIBUTE_MASK; 430 mtime_sec = smb_time_gmt_to_local(sr, ap->sa_vattr.va_mtime.tv_sec); 431 432 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 433 case STYPE_DISKTREE: 434 case STYPE_PRINTQ: 435 break; 436 437 case STYPE_IPC: 438 mtime_sec = 0; 439 break; 440 441 default: 442 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST, 443 ERRDOS, ERROR_INVALID_FUNCTION); 444 goto errout; 445 } 446 447 if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 && 448 smb_openx_enable_extended_response != 0) { 449 uint32_t MaxAccess = 0; 450 if (of->f_node != NULL) { 451 smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess); 452 } 453 MaxAccess |= of->f_granted_access; 454 455 rc = smbsr_encode_result( 456 sr, 19, 0, "bb.wwwllwwwwl2.llw", 457 19, /* word count (b) */ 458 sr->andx_com, /* (b.) */ 459 VAR_BCC, /* andx offset (w) */ 460 sr->smb_fid, /* (w) */ 461 file_attr, /* (w) */ 462 mtime_sec, /* (l) */ 463 (uint32_t)op->dsize, /* (l) */ 464 op->omode, /* (w) */ 465 op->ftype, /* (w) */ 466 op->devstate, /* (w) */ 467 op->action_taken, /* (w) */ 468 0, /* legacy fileid (l) */ 469 /* reserved (2.) */ 470 MaxAccess, /* (l) */ 471 0, /* guest access (l) */ 472 0); /* byte count (w) */ 473 474 } else { 475 rc = smbsr_encode_result( 476 sr, 15, 0, "bb.wwwllwwwwl2.w", 477 15, /* word count (b) */ 478 sr->andx_com, /* (b.) */ 479 VAR_BCC, /* andx offset (w) */ 480 sr->smb_fid, /* (w) */ 481 file_attr, /* (w) */ 482 mtime_sec, /* (l) */ 483 (uint32_t)op->dsize, /* (l) */ 484 op->omode, /* (w) */ 485 op->ftype, /* (w) */ 486 op->devstate, /* (w) */ 487 op->action_taken, /* (w) */ 488 0, /* legacy fileid (l) */ 489 /* reserved (2.) */ 490 0); /* byte count (w) */ 491 } 492 493 if (rc == 0) 494 return (SDRC_SUCCESS); 495 496 errout: 497 smb_ofile_close(of, 0); 498 return (SDRC_ERROR); 499 } 500 501 smb_sdrc_t 502 smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa) 503 { 504 struct open_param *op = &sr->arg.open; 505 uint32_t creation_time; 506 uint32_t alloc_size; 507 uint32_t ea_list_size; 508 uint16_t flags; 509 uint16_t file_attr; 510 uint32_t status; 511 int rc; 512 513 bzero(op, sizeof (sr->arg.open)); 514 515 rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u", 516 sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr, 517 &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path); 518 if (rc != 0) 519 return (SDRC_ERROR); 520 521 /* 522 * The data part of this transaction may contain an EA list. 523 * See: SMB_FEA_LIST ExtendedAttributeList 524 * 525 * If we find a non-empty EA list payload, return the special 526 * error that tells the caller this FS does not suport EAs. 527 * 528 * Note: the first word is the size of the whole data segment, 529 * INCLUDING the size of that length word. That means if 530 * the length word specifies a size less than four, it's 531 * invalid (and probably a client trying something fishy). 532 */ 533 rc = smb_mbc_decodef(&xa->req_data_mb, "l", &ea_list_size); 534 if (rc == 0 && ea_list_size > 4) { 535 smbsr_status(sr, NT_STATUS_EAS_NOT_SUPPORTED, 0, 0); 536 return (SDRC_ERROR); 537 } 538 539 if ((creation_time != 0) && (creation_time != UINT_MAX)) 540 op->crtime.tv_sec = smb_time_local_to_gmt(sr, creation_time); 541 op->crtime.tv_nsec = 0; 542 543 op->dattr = file_attr; 544 op->dsize = alloc_size; 545 op->create_options = FILE_NON_DIRECTORY_FILE; 546 547 op->desired_access = smb_omode_to_amask(op->omode); 548 op->share_access = smb_denymode_to_sharemode(op->omode, 549 op->fqi.fq_path.pn_path); 550 551 op->create_disposition = smb_ofun_to_crdisposition(op->ofun); 552 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) 553 op->create_disposition = FILE_CREATE; 554 555 if (op->omode & SMB_DA_WRITE_THROUGH) 556 op->create_options |= FILE_WRITE_THROUGH; 557 558 if (sr->smb_flg & SMB_FLAGS_OPLOCK) { 559 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY) 560 op->op_oplock_level = SMB_OPLOCK_BATCH; 561 else 562 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 563 } else { 564 op->op_oplock_level = SMB_OPLOCK_NONE; 565 } 566 op->op_oplock_levelII = B_FALSE; 567 568 status = smb_common_open(sr); 569 if (status != NT_STATUS_SUCCESS) { 570 smbsr_status(sr, status, 0, 0); 571 return (SDRC_ERROR); 572 } 573 574 if (op->op_oplock_level != SMB_OPLOCK_NONE) 575 op->action_taken |= SMB_OACT_OPLOCK; 576 else 577 op->action_taken &= ~SMB_OACT_OPLOCK; 578 579 file_attr = op->dattr & FILE_ATTRIBUTE_MASK; 580 581 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) 582 op->dsize = 0; 583 584 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl", 585 sr->smb_fid, 586 file_attr, 587 (uint32_t)0, /* creation time */ 588 (uint32_t)op->dsize, 589 op->omode, 590 op->ftype, 591 op->devstate, 592 op->action_taken, 593 op->fileid, 594 (uint16_t)0, /* EA error offset */ 595 (uint32_t)0); /* EA list length */ 596 597 return (SDRC_SUCCESS); 598 }