smb_open_andx.c revision 9343:ef29909f1c11
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 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <smbsrv/smb_vops.h>
27#include <smbsrv/smb_incl.h>
28
29int 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
217smb_sdrc_t
218smb_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
235void
236smb_post_open(smb_request_t *sr)
237{
238	DTRACE_SMB_1(op__Open__done, smb_request_t *, sr);
239}
240
241smb_sdrc_t
242smb_com_open(smb_request_t *sr)
243{
244	struct open_param *op = &sr->arg.open;
245	smb_node_t *node;
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
267	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
268		return (SDRC_ERROR);
269
270	if (op->op_oplock_level == SMB_OPLOCK_NONE) {
271		sr->smb_flg &=
272		    ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY);
273	}
274
275	if (smb_open_dsize_check && op->dsize > UINT_MAX) {
276		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
277		return (SDRC_ERROR);
278	}
279
280	file_attr = op->dattr  & FILE_ATTRIBUTE_MASK;
281	node = sr->fid_ofile->f_node;
282
283	rc = smbsr_encode_result(sr, 7, 0, "bwwllww",
284	    7,
285	    sr->smb_fid,
286	    file_attr,
287	    smb_gmt2local(sr, node->attr.sa_vattr.va_mtime.tv_sec),
288	    (uint32_t)op->dsize,
289	    op->omode,
290	    (uint16_t)0);	/* bcc */
291
292	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
293}
294
295/*
296 * smb_pre_open_andx
297 * For compatibility with windows servers, the search attributes
298 * specified in the request are ignored.
299 */
300smb_sdrc_t
301smb_pre_open_andx(smb_request_t *sr)
302{
303	struct open_param *op = &sr->arg.open;
304	uint16_t flags;
305	uint32_t creation_time;
306	uint16_t file_attr, sattr;
307	int rc;
308
309	bzero(op, sizeof (sr->arg.open));
310
311	rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com,
312	    &sr->andx_off, &flags, &op->omode, &sattr,
313	    &file_attr, &creation_time, &op->ofun, &op->dsize, &op->timeo);
314
315	if (rc == 0) {
316		rc = smbsr_decode_data(sr, "%u", sr, &op->fqi.fq_path.pn_path);
317
318		op->dattr = file_attr;
319
320		if (flags & 2)
321			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
322		else if (flags & 4)
323			op->op_oplock_level = SMB_OPLOCK_BATCH;
324		else
325			op->op_oplock_level = SMB_OPLOCK_NONE;
326
327		if ((creation_time != 0) && (creation_time != UINT_MAX))
328			op->crtime.tv_sec = smb_local2gmt(sr, creation_time);
329		op->crtime.tv_nsec = 0;
330
331		op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
332	}
333
334	DTRACE_SMB_2(op__OpenX__start, smb_request_t *, sr,
335	    struct open_param *, op);
336
337	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
338}
339
340void
341smb_post_open_andx(smb_request_t *sr)
342{
343	DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr);
344}
345
346smb_sdrc_t
347smb_com_open_andx(smb_request_t *sr)
348{
349	struct open_param	*op = &sr->arg.open;
350	uint16_t		file_attr;
351	int rc;
352
353	op->desired_access = smb_omode_to_amask(op->omode);
354	op->share_access = smb_denymode_to_sharemode(op->omode,
355	    op->fqi.fq_path.pn_path);
356
357	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
358		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
359		return (SDRC_ERROR);
360	}
361
362	op->create_options = FILE_NON_DIRECTORY_FILE;
363	if (op->omode & SMB_DA_WRITE_THROUGH)
364		op->create_options |= FILE_WRITE_THROUGH;
365
366	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
367		return (SDRC_ERROR);
368
369	if (smb_open_dsize_check && op->dsize > UINT_MAX) {
370		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
371		return (SDRC_ERROR);
372	}
373
374	if (op->op_oplock_level != SMB_OPLOCK_NONE)
375		op->action_taken |= SMB_OACT_LOCK;
376	else
377		op->action_taken &= ~SMB_OACT_LOCK;
378
379	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
380	if (STYPE_ISDSK(sr->tid_tree->t_res_type)) {
381		smb_node_t *node = sr->fid_ofile->f_node;
382		rc = smbsr_encode_result(sr, 15, 0,
383		    "bb.wwwllwwwwl2.w",
384		    15,
385		    sr->andx_com, VAR_BCC,
386		    sr->smb_fid,
387		    file_attr,
388		    smb_gmt2local(sr, node->attr.sa_vattr.va_mtime.tv_sec),
389		    (uint32_t)op->dsize,
390		    op->omode, op->ftype,
391		    op->devstate,
392		    op->action_taken, op->fileid,
393		    0);
394	} else {
395		rc = smbsr_encode_result(sr, 15, 0,
396		    "bb.wwwllwwwwl2.w",
397		    15,
398		    sr->andx_com, VAR_BCC,
399		    sr->smb_fid,
400		    file_attr,
401		    0L,
402		    0L,
403		    op->omode, op->ftype,
404		    op->devstate,
405		    op->action_taken, op->fileid,
406		    0);
407	}
408
409	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
410}
411
412smb_sdrc_t
413smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa)
414{
415	struct open_param *op = &sr->arg.open;
416	uint32_t	creation_time;
417	uint32_t	alloc_size;
418	uint16_t	flags;
419	uint16_t	file_attr;
420	int		rc;
421
422	bzero(op, sizeof (sr->arg.open));
423
424	rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u",
425	    sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr,
426	    &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path);
427	if (rc != 0)
428		return (SDRC_ERROR);
429
430	if ((creation_time != 0) && (creation_time != UINT_MAX))
431		op->crtime.tv_sec = smb_local2gmt(sr, creation_time);
432	op->crtime.tv_nsec = 0;
433
434	op->dattr = file_attr;
435	op->dsize = alloc_size;
436	op->create_options = FILE_NON_DIRECTORY_FILE;
437
438	op->desired_access = smb_omode_to_amask(op->omode);
439	op->share_access = smb_denymode_to_sharemode(op->omode,
440	    op->fqi.fq_path.pn_path);
441
442	op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
443	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION)
444		op->create_disposition = FILE_CREATE;
445
446	if (op->omode & SMB_DA_WRITE_THROUGH)
447		op->create_options |= FILE_WRITE_THROUGH;
448
449	if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
450		if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
451			op->op_oplock_level = SMB_OPLOCK_BATCH;
452		else
453			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
454	} else {
455		op->op_oplock_level = SMB_OPLOCK_NONE;
456	}
457
458	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
459		return (SDRC_ERROR);
460
461	if (op->op_oplock_level != SMB_OPLOCK_NONE)
462		op->action_taken |= SMB_OACT_LOCK;
463	else
464		op->action_taken &= ~SMB_OACT_LOCK;
465
466	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
467
468	if (!STYPE_ISDSK(sr->tid_tree->t_res_type))
469		op->dsize = 0;
470
471	(void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl",
472	    sr->smb_fid,
473	    file_attr,
474	    (uint32_t)0,	/* creation time */
475	    (uint32_t)op->dsize,
476	    op->omode,
477	    op->ftype,
478	    op->devstate,
479	    op->action_taken,
480	    op->fileid,
481	    (uint16_t)0,	/* EA error offset */
482	    (uint32_t)0);	/* EA list length */
483
484	return (SDRC_SUCCESS);
485}
486