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