smb_open_andx.c revision 10001:d540bbbe2461
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	smb_attr_t attr;
247	uint16_t file_attr;
248	int rc;
249
250	op->desired_access = smb_omode_to_amask(op->omode);
251	op->share_access = smb_denymode_to_sharemode(op->omode,
252	    op->fqi.fq_path.pn_path);
253	op->crtime.tv_sec = op->crtime.tv_nsec = 0;
254	op->create_disposition = FILE_OPEN;
255	op->create_options = FILE_NON_DIRECTORY_FILE;
256	if (op->omode & SMB_DA_WRITE_THROUGH)
257		op->create_options |= FILE_WRITE_THROUGH;
258
259	if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
260		if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
261			op->op_oplock_level = SMB_OPLOCK_BATCH;
262		else
263			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
264	} else {
265		op->op_oplock_level = SMB_OPLOCK_NONE;
266	}
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_gmt2local(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 */
306smb_sdrc_t
307smb_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 = smb_local2gmt(sr, creation_time);
335		op->crtime.tv_nsec = 0;
336
337		op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
338	}
339
340	DTRACE_SMB_2(op__OpenX__start, smb_request_t *, sr,
341	    struct open_param *, op);
342
343	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
344}
345
346void
347smb_post_open_andx(smb_request_t *sr)
348{
349	DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr);
350}
351
352smb_sdrc_t
353smb_com_open_andx(smb_request_t *sr)
354{
355	struct open_param	*op = &sr->arg.open;
356	uint16_t		file_attr;
357	smb_attr_t		attr;
358	int rc;
359
360	op->desired_access = smb_omode_to_amask(op->omode);
361	op->share_access = smb_denymode_to_sharemode(op->omode,
362	    op->fqi.fq_path.pn_path);
363
364	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
365		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
366		return (SDRC_ERROR);
367	}
368
369	op->create_options = FILE_NON_DIRECTORY_FILE;
370	if (op->omode & SMB_DA_WRITE_THROUGH)
371		op->create_options |= FILE_WRITE_THROUGH;
372
373	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
374		return (SDRC_ERROR);
375
376	if (smb_open_dsize_check && op->dsize > UINT_MAX) {
377		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
378		return (SDRC_ERROR);
379	}
380
381	if (op->op_oplock_level != SMB_OPLOCK_NONE)
382		op->action_taken |= SMB_OACT_LOCK;
383	else
384		op->action_taken &= ~SMB_OACT_LOCK;
385
386	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
387	if (STYPE_ISDSK(sr->tid_tree->t_res_type)) {
388
389		smb_node_t *node = sr->fid_ofile->f_node;
390		if (smb_node_getattr(sr, node, &attr) != 0) {
391			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
392			    ERRDOS, ERROR_INTERNAL_ERROR);
393			return (SDRC_ERROR);
394		}
395
396		rc = smbsr_encode_result(sr, 15, 0,
397		    "bb.wwwllwwwwl2.w",
398		    15,
399		    sr->andx_com, VAR_BCC,
400		    sr->smb_fid,
401		    file_attr,
402		    smb_gmt2local(sr, attr.sa_vattr.va_mtime.tv_sec),
403		    (uint32_t)op->dsize,
404		    op->omode, op->ftype,
405		    op->devstate,
406		    op->action_taken, op->fileid,
407		    0);
408	} else {
409		rc = smbsr_encode_result(sr, 15, 0,
410		    "bb.wwwllwwwwl2.w",
411		    15,
412		    sr->andx_com, VAR_BCC,
413		    sr->smb_fid,
414		    file_attr,
415		    0L,
416		    0L,
417		    op->omode, op->ftype,
418		    op->devstate,
419		    op->action_taken, op->fileid,
420		    0);
421	}
422
423	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
424}
425
426smb_sdrc_t
427smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa)
428{
429	struct open_param *op = &sr->arg.open;
430	uint32_t	creation_time;
431	uint32_t	alloc_size;
432	uint16_t	flags;
433	uint16_t	file_attr;
434	int		rc;
435
436	bzero(op, sizeof (sr->arg.open));
437
438	rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u",
439	    sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr,
440	    &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path);
441	if (rc != 0)
442		return (SDRC_ERROR);
443
444	if ((creation_time != 0) && (creation_time != UINT_MAX))
445		op->crtime.tv_sec = smb_local2gmt(sr, creation_time);
446	op->crtime.tv_nsec = 0;
447
448	op->dattr = file_attr;
449	op->dsize = alloc_size;
450	op->create_options = FILE_NON_DIRECTORY_FILE;
451
452	op->desired_access = smb_omode_to_amask(op->omode);
453	op->share_access = smb_denymode_to_sharemode(op->omode,
454	    op->fqi.fq_path.pn_path);
455
456	op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
457	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION)
458		op->create_disposition = FILE_CREATE;
459
460	if (op->omode & SMB_DA_WRITE_THROUGH)
461		op->create_options |= FILE_WRITE_THROUGH;
462
463	if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
464		if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
465			op->op_oplock_level = SMB_OPLOCK_BATCH;
466		else
467			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
468	} else {
469		op->op_oplock_level = SMB_OPLOCK_NONE;
470	}
471
472	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
473		return (SDRC_ERROR);
474
475	if (op->op_oplock_level != SMB_OPLOCK_NONE)
476		op->action_taken |= SMB_OACT_LOCK;
477	else
478		op->action_taken &= ~SMB_OACT_LOCK;
479
480	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
481
482	if (!STYPE_ISDSK(sr->tid_tree->t_res_type))
483		op->dsize = 0;
484
485	(void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl",
486	    sr->smb_fid,
487	    file_attr,
488	    (uint32_t)0,	/* creation time */
489	    (uint32_t)op->dsize,
490	    op->omode,
491	    op->ftype,
492	    op->devstate,
493	    op->action_taken,
494	    op->fileid,
495	    (uint16_t)0,	/* EA error offset */
496	    (uint32_t)0);	/* EA list length */
497
498	return (SDRC_SUCCESS);
499}
500