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