smb_open_andx.c revision 7619:0ad244464731
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
224smb_sdrc_t
225smb_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
242void
243smb_post_open(smb_request_t *sr)
244{
245	DTRACE_SMB_1(op__Open__done, smb_request_t *, sr);
246}
247
248smb_sdrc_t
249smb_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 */
314smb_sdrc_t
315smb_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
353void
354smb_post_open_andx(smb_request_t *sr)
355{
356	DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr);
357}
358
359smb_sdrc_t
360smb_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