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