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.
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.
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]
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
26 #include <smbsrv/smb_kproto.h>
27 #include <smbsrv/smb_vops.h>
29 int smb_open_dsize_check
= 0;
32 * Client Request Description
33 * ================================== =================================
35 * UCHAR WordCount; Count of parameter words = 15
36 * UCHAR AndXCommand; Secondary (X) command; 0xFF =
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
49 * USHORT OpenFunction; Action to take if file exists
50 * ULONG AllocationSize; Bytes to reserve on create or
52 * ULONG Reserved[2]; Must be 0
53 * USHORT ByteCount; Count of data bytes; min = 1
54 * UCHAR BufferFormat 0x04
57 * Server Response Description
58 * ================================== =================================
60 * UCHAR WordCount; Count of parameter words = 15
61 * UCHAR AndXCommand; Secondary (X) command; 0xFF =
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
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
78 * DesiredAccess describes the access the client desires for the file (see
79 * section 3.6 - Access Mode Encoding).
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
84 * in the response specifies the action as a result of the Open request
85 * (see section 3.9 - Open Action Encoding).
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.
95 * FileType returns the kind of resource actually opened:
97 * Name Value Description
98 * ========================== ====== ==================================
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
107 * If bit0 of Flags is clear, the FileAttributes, LastWriteTime, DataSize,
108 * FileType, and DeviceState have indeterminate values in the response.
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.
116 * The following SMBs may follow SMB_COM_OPEN_ANDX:
118 * SMB_COM_READ SMB_COM_READ_ANDX
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,
127 * Client Request Description
128 * ================================== =================================
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
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
143 * SearchAttributes specifies the type of file desired. The encoding is
144 * described in the "File Attribute Encoding" section.
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".
151 * Server Response Description
152 * ================================== =================================
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
162 * Fid is the handle value which should be used for subsequent file
165 * FileAttributes specifies the type of file obtained. The encoding is
166 * described in the "File Attribute Encoding" section.
168 * GrantedAccess indicates the access permissions actually allowed, and may
169 * have one of the following values:
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
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.
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.
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.
218 smb_pre_open(smb_request_t
*sr
)
220 struct open_param
*op
= &sr
->arg
.open
;
223 bzero(op
, sizeof (sr
->arg
.open
));
225 rc
= smbsr_decode_vwv(sr
, "ww", &op
->omode
, &op
->fqi
.fq_sattr
);
227 rc
= smbsr_decode_data(sr
, "%S", sr
, &op
->fqi
.fq_path
.pn_path
);
229 DTRACE_SMB_2(op__Open__start
, smb_request_t
*, sr
,
230 struct open_param
*, op
);
232 return ((rc
== 0) ? SDRC_SUCCESS
: SDRC_ERROR
);
236 smb_post_open(smb_request_t
*sr
)
238 DTRACE_SMB_1(op__Open__done
, smb_request_t
*, sr
);
242 smb_com_open(smb_request_t
*sr
)
244 struct open_param
*op
= &sr
->arg
.open
;
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
;
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
;
264 op
->op_oplock_level
= SMB_OPLOCK_EXCLUSIVE
;
266 op
->op_oplock_level
= SMB_OPLOCK_NONE
;
268 op
->op_oplock_levelII
= B_FALSE
;
270 if (smb_open_dsize_check
&& op
->dsize
> UINT_MAX
) {
271 smbsr_error(sr
, 0, ERRDOS
, ERRbadaccess
);
275 status
= smb_common_open(sr
);
276 if (status
!= NT_STATUS_SUCCESS
) {
277 smbsr_status(sr
, status
, 0, 0);
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.
288 if (op
->op_oplock_level
== SMB_OPLOCK_NONE
) {
290 ~(SMB_FLAGS_OPLOCK
| SMB_FLAGS_OPLOCK_NOTIFY_ANY
);
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
);
302 rc
= smbsr_encode_result(sr
, 7, 0, "bwwllww",
306 smb_time_gmt_to_local(sr
, attr
.sa_vattr
.va_mtime
.tv_sec
),
309 (uint16_t)0); /* bcc */
312 return (SDRC_SUCCESS
);
315 smb_ofile_close(of
, 0);
321 * For compatibility with windows servers, the search attributes
322 * specified in the request are ignored.
325 smb_pre_open_andx(smb_request_t
*sr
)
327 struct open_param
*op
= &sr
->arg
.open
;
330 uint32_t creation_time
;
331 uint16_t file_attr
, sattr
;
334 bzero(op
, sizeof (sr
->arg
.open
));
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
);
341 rc
= smbsr_decode_data(sr
, "%u", sr
, &op
->fqi
.fq_path
.pn_path
);
343 op
->dattr
= file_attr
;
344 op
->dsize
= alloc_size
;
347 op
->op_oplock_level
= SMB_OPLOCK_EXCLUSIVE
;
349 op
->op_oplock_level
= SMB_OPLOCK_BATCH
;
351 op
->op_oplock_level
= SMB_OPLOCK_NONE
;
353 if ((creation_time
!= 0) && (creation_time
!= UINT_MAX
))
355 smb_time_local_to_gmt(sr
, creation_time
);
356 op
->crtime
.tv_nsec
= 0;
358 op
->create_disposition
= smb_ofun_to_crdisposition(op
->ofun
);
361 DTRACE_SMB_2(op__OpenX__start
, smb_request_t
*, sr
,
362 struct open_param
*, op
);
364 return ((rc
== 0) ? SDRC_SUCCESS
: SDRC_ERROR
);
368 smb_post_open_andx(smb_request_t
*sr
)
370 DTRACE_SMB_1(op__OpenX__done
, smb_request_t
*, sr
);
374 smb_com_open_andx(smb_request_t
*sr
)
376 struct open_param
*op
= &sr
->arg
.open
;
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
);
387 if (op
->create_disposition
> FILE_MAXIMUM_DISPOSITION
) {
388 smbsr_error(sr
, 0, ERRDOS
, ERRbadaccess
);
392 op
->create_options
= FILE_NON_DIRECTORY_FILE
;
393 if (op
->omode
& SMB_DA_WRITE_THROUGH
)
394 op
->create_options
|= FILE_WRITE_THROUGH
;
396 op
->op_oplock_levelII
= B_FALSE
;
398 if (smb_open_dsize_check
&& op
->dsize
> UINT_MAX
) {
399 smbsr_error(sr
, 0, ERRDOS
, ERRbadaccess
);
403 status
= smb_common_open(sr
);
404 if (status
!= NT_STATUS_SUCCESS
) {
405 smbsr_status(sr
, status
, 0, 0);
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.
416 if (op
->op_oplock_level
!= SMB_OPLOCK_NONE
)
417 op
->action_taken
|= SMB_OACT_LOCK
;
419 op
->action_taken
&= ~SMB_OACT_LOCK
;
421 file_attr
= op
->dattr
& FILE_ATTRIBUTE_MASK
;
422 bzero(&attr
, sizeof (attr
));
424 switch (sr
->tid_tree
->t_res_type
& STYPE_MASK
) {
427 attr
.sa_mask
= SMB_AT_MTIME
;
428 rc
= smb_node_getattr(sr
, of
->f_node
, of
->f_cr
, of
, &attr
);
434 rc
= smbsr_encode_result(sr
, 15, 0,
437 sr
->andx_com
, VAR_BCC
,
440 smb_time_gmt_to_local(sr
, attr
.sa_vattr
.va_mtime
.tv_sec
),
442 op
->omode
, op
->ftype
,
444 op
->action_taken
, op
->fileid
,
449 rc
= smbsr_encode_result(sr
, 15, 0,
452 sr
->andx_com
, VAR_BCC
,
457 op
->omode
, op
->ftype
,
459 op
->action_taken
, op
->fileid
,
464 smbsr_error(sr
, NT_STATUS_INVALID_DEVICE_REQUEST
,
465 ERRDOS
, ERROR_INVALID_FUNCTION
);
470 return (SDRC_SUCCESS
);
473 smb_ofile_close(of
, 0);
478 smb_com_trans2_open2(smb_request_t
*sr
, smb_xa_t
*xa
)
480 struct open_param
*op
= &sr
->arg
.open
;
481 uint32_t creation_time
;
488 bzero(op
, sizeof (sr
->arg
.open
));
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
);
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;
500 op
->dattr
= file_attr
;
501 op
->dsize
= alloc_size
;
502 op
->create_options
= FILE_NON_DIRECTORY_FILE
;
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
);
508 op
->create_disposition
= smb_ofun_to_crdisposition(op
->ofun
);
509 if (op
->create_disposition
> FILE_MAXIMUM_DISPOSITION
)
510 op
->create_disposition
= FILE_CREATE
;
512 if (op
->omode
& SMB_DA_WRITE_THROUGH
)
513 op
->create_options
|= FILE_WRITE_THROUGH
;
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
;
519 op
->op_oplock_level
= SMB_OPLOCK_EXCLUSIVE
;
521 op
->op_oplock_level
= SMB_OPLOCK_NONE
;
523 op
->op_oplock_levelII
= B_FALSE
;
525 status
= smb_common_open(sr
);
526 if (status
!= NT_STATUS_SUCCESS
) {
527 smbsr_status(sr
, status
, 0, 0);
531 if (op
->op_oplock_level
!= SMB_OPLOCK_NONE
)
532 op
->action_taken
|= SMB_OACT_LOCK
;
534 op
->action_taken
&= ~SMB_OACT_LOCK
;
536 file_attr
= op
->dattr
& FILE_ATTRIBUTE_MASK
;
538 if (STYPE_ISIPC(sr
->tid_tree
->t_res_type
))
541 (void) smb_mbc_encodef(&xa
->rep_param_mb
, "wwllwwwwlwl",
544 0, /* creation time */
551 (uint16_t)0, /* EA error offset */
552 0); /* EA list length */
554 return (SDRC_SUCCESS
);