xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_open_andx.c (revision b6805bf78d2bbbeeaea8909a05623587b42d58b3)
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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <smbsrv/smb_kproto.h>
26 #include <smbsrv/smb_vops.h>
27 
28 int smb_open_dsize_check = 0;
29 
30 /*
31  *  Client Request                     Description
32  *  ================================== =================================
33  *
34  *  UCHAR WordCount;                   Count of parameter words = 15
35  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
36  *                                      none
37  *  UCHAR AndXReserved;                Reserved (must be 0)
38  *  USHORT AndXOffset;                 Offset to next command WordCount
39  *  USHORT Flags;                      Additional information: bit set-
40  *                                      0 - return additional info
41  *                                      1 - exclusive oplock requested
42  *                                      2 - batch oplock requested
43  *  USHORT DesiredAccess;              File open mode
44  *  USHORT SearchAttributes;
45  *  USHORT FileAttributes;
46  *  UTIME CreationTime;                Creation timestamp for file if it
47  *                                      gets created
48  *  USHORT OpenFunction;               Action to take if file exists
49  *  ULONG AllocationSize;              Bytes to reserve on create or
50  *                                      truncate
51  *  ULONG Reserved[2];                 Must be 0
52  *  USHORT ByteCount;                  Count of data bytes;    min = 1
53  *  UCHAR BufferFormat                 0x04
54  *  STRING FileName;
55  *
56  *  Server Response                    Description
57  *  ================================== =================================
58  *
59  *  UCHAR WordCount;                   Count of parameter words = 15
60  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
61  *                                      none
62  *  UCHAR AndXReserved;                Reserved (must be 0)
63  *  USHORT AndXOffset;                 Offset to next command WordCount
64  *  USHORT Fid;                        File handle
65  *  USHORT FileAttributes;
66  *  UTIME LastWriteTime;
67  *  ULONG DataSize;                    Current file size
68  *  USHORT GrantedAccess;              Access permissions actually
69  *                                      allowed
70  *  USHORT FileType;                   Type of file opened
71  *  USHORT DeviceState;                State of the named pipe
72  *  USHORT Action;                     Action taken
73  *  ULONG ServerFid;                   Server unique file id
74  *  USHORT Reserved;                   Reserved (must be 0)
75  *  USHORT ByteCount;                  Count of data bytes = 0
76  *
77  * DesiredAccess describes the access the client desires for the file (see
78  * section 3.6 -  Access Mode Encoding).
79  *
80  * OpenFunction specifies the action to be taken depending on whether or
81  * not the file exists (see section 3.8 -  Open Function Encoding).  Action
82  *
83  * in the response specifies the action as a result of the Open request
84  * (see section 3.9 -  Open Action Encoding).
85  *
86  * SearchAttributes indicates the attributes that the file must have to be
87  * found while searching to see if it exists.  The encoding of this field
88  * is described in the "File Attribute Encoding" section elsewhere in this
89  * document.  If SearchAttributes is zero then only normal files are
90  * returned.  If the system file, hidden or directory attributes are
91  * specified then the search is inclusive -- both the specified type(s) of
92  * files and normal files are returned.
93  *
94  * FileType returns the kind of resource actually opened:
95  *
96  *  Name                       Value  Description
97  *  ========================== ====== ==================================
98  *
99  *  FileTypeDisk               0      Disk file or directory as defined
100  *                                     in the attribute field
101  *  FileTypeByteModePipe       1      Named pipe in byte mode
102  *  FileTypeMessageModePipe    2      Named pipe in message mode
103  *  FileTypePrinter            3      Spooled printer
104  *  FileTypeUnknown            0xFFFF Unrecognized resource type
105  *
106  * If bit0 of Flags is clear, the FileAttributes, LastWriteTime, DataSize,
107  * FileType, and DeviceState have indeterminate values in the response.
108  *
109  * This SMB can request an oplock on the opened file.  Oplocks are fully
110  * described in the "Oplocks" section elsewhere in this document, and there
111  * is also discussion of oplocks in the SMB_COM_LOCKING_ANDX SMB
112  * description.  Bit1 and bit2 of the Flags field are used to request
113  * oplocks during open.
114  *
115  * The following SMBs may follow SMB_COM_OPEN_ANDX:
116  *
117  *    SMB_COM_READ    SMB_COM_READ_ANDX
118  *    SMB_COM_IOCTL
119  */
120 
121 /*
122  * This message is sent to obtain a file handle for a data file.  This
123  * returned Fid is used in subsequent client requests such as read, write,
124  * close, etc.
125  *
126  * Client Request                     Description
127  * ================================== =================================
128  *
129  * UCHAR WordCount;                   Count of parameter words = 2
130  * USHORT DesiredAccess;              Mode - read/write/share
131  * USHORT SearchAttributes;
132  * USHORT ByteCount;                  Count of data bytes;    min = 2
133  * UCHAR BufferFormat;                0x04
134  * STRING FileName[];                 File name
135  *
136  * FileName is the fully qualified file name, relative to the root of the
137  * share specified in the Tid field of the SMB header.  If Tid in the SMB
138  * header refers to a print share, this SMB creates a new file which will
139  * be spooled to the printer when closed.  In this case, FileName is
140  * ignored.
141  *
142  * SearchAttributes specifies the type of file desired.  The encoding is
143  * described in the "File Attribute Encoding" section.
144  *
145  * DesiredAccess controls the mode under which the file is opened, and the
146  * file will be opened only if the client has the appropriate permissions.
147  * The encoding of DesiredAccess is discussed in the section entitled
148  * "Access Mode Encoding".
149  *
150  * Server Response                    Description
151  * ================================== =================================
152  *
153  * UCHAR WordCount;                   Count of parameter words = 7
154  * USHORT Fid;                        File handle
155  * USHORT FileAttributes;             Attributes of opened file
156  * UTIME LastWriteTime;               Time file was last written
157  * ULONG DataSize;                    File size
158  * USHORT GrantedAccess;              Access allowed
159  * USHORT ByteCount;                  Count of data bytes = 0
160  *
161  * Fid is the handle value which should be used for subsequent file
162  * operations.
163  *
164  * FileAttributes specifies the type of file obtained.  The encoding is
165  * described in the "File Attribute Encoding" section.
166  *
167  * GrantedAccess indicates the access permissions actually allowed, and may
168  * have one of the following values:
169  *
170  *    0  read-only
171  *    1  write-only
172  *    2 read/write
173  *
174  * File Handles (Fids) are scoped per client.  A Pid may reference any Fid
175  * established by itself or any other Pid on the client (so far as the
176  * server is concerned).  The actual accesses allowed through the Fid
177  * depends on the open and deny modes specified when the file was opened
178  * (see below).
179  *
180  * The MS-DOS compatibility mode of file open provides exclusion at the
181  * client level.  A file open in compatibility mode may be opened (also in
182  * compatibility mode) any number of times for any combination of reading
183  * and writing (subject to the user's permissions) by any Pid on the same
184  * client.  If the first client has the file open for writing, then the
185  * file may not be opened in any way by any other client.  If the first
186  * client has the file open only for reading, then other clients may open
187  * the file, in compatibility mode, for reading..  The above
188  * notwithstanding, if the filename has an extension of .EXE, .DLL, .SYM,
189  * or .COM other clients are permitted to open the file regardless of
190  * read/write open modes of other compatibility mode opens.  However, once
191  * multiple clients have the file open for reading, no client is permitted
192  * to open the file for writing and no other client may open the file in
193  * any mode other than compatibility mode.
194  *
195  * The other file exclusion modes (Deny read/write, Deny write, Deny read,
196  * Deny none) provide exclusion at the file level.  A file opened in any
197  * "Deny" mode may be opened again only for the accesses allowed by the
198  * Deny mode (subject to the user's permissions).  This is true regardless
199  * of the identity of the second opener -a different client, a Pid from the
200  * same client, or the Pid that already has the file open.  For example, if
201  * a file is open in "Deny write" mode a second open may only obtain read
202  * permission to the file.
203  *
204  * Although Fids are available to all Pids on a client, Pids other than the
205  * owner may not have the full access rights specified in the open mode by
206  * the Fid's creator.  If the open creating the Fid specified a deny mode,
207  * then any Pid using the Fid, other than the creating Pid, will have only
208  * those access rights determined by "anding" the open mode rights and the
209  * deny mode rights, i.e., the deny mode is checked on all file accesses.
210  * For example, if a file is opened for Read/Write in Deny write mode, then
211  * other clients may only read the file and cannot write; if a file is
212  * opened for Read in Deny read mode, then the other clients can neither
213  * read nor write the file.
214  */
215 
216 smb_sdrc_t
217 smb_pre_open(smb_request_t *sr)
218 {
219 	struct open_param *op = &sr->arg.open;
220 	int rc;
221 
222 	bzero(op, sizeof (sr->arg.open));
223 
224 	rc = smbsr_decode_vwv(sr, "ww", &op->omode, &op->fqi.fq_sattr);
225 	if (rc == 0)
226 		rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
227 
228 	DTRACE_SMB_2(op__Open__start, smb_request_t *, sr,
229 	    struct open_param *, op);
230 
231 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
232 }
233 
234 void
235 smb_post_open(smb_request_t *sr)
236 {
237 	DTRACE_SMB_1(op__Open__done, smb_request_t *, sr);
238 }
239 
240 smb_sdrc_t
241 smb_com_open(smb_request_t *sr)
242 {
243 	struct open_param *op = &sr->arg.open;
244 	smb_node_t *node;
245 	smb_attr_t attr;
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 	op->op_oplock_levelII = B_FALSE;
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_time_gmt_to_local(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  */
306 smb_sdrc_t
307 smb_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 =
335 			    smb_time_local_to_gmt(sr, creation_time);
336 		op->crtime.tv_nsec = 0;
337 
338 		op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
339 	}
340 
341 	DTRACE_SMB_2(op__OpenX__start, smb_request_t *, sr,
342 	    struct open_param *, op);
343 
344 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
345 }
346 
347 void
348 smb_post_open_andx(smb_request_t *sr)
349 {
350 	DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr);
351 }
352 
353 smb_sdrc_t
354 smb_com_open_andx(smb_request_t *sr)
355 {
356 	struct open_param	*op = &sr->arg.open;
357 	smb_node_t		*node;
358 	uint16_t		file_attr;
359 	smb_attr_t		attr;
360 	int rc;
361 
362 	op->desired_access = smb_omode_to_amask(op->omode);
363 	op->share_access = smb_denymode_to_sharemode(op->omode,
364 	    op->fqi.fq_path.pn_path);
365 
366 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
367 		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
368 		return (SDRC_ERROR);
369 	}
370 
371 	op->create_options = FILE_NON_DIRECTORY_FILE;
372 	if (op->omode & SMB_DA_WRITE_THROUGH)
373 		op->create_options |= FILE_WRITE_THROUGH;
374 
375 	op->op_oplock_levelII = B_FALSE;
376 
377 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
378 		return (SDRC_ERROR);
379 
380 	if (smb_open_dsize_check && op->dsize > UINT_MAX) {
381 		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
382 		return (SDRC_ERROR);
383 	}
384 
385 	if (op->op_oplock_level != SMB_OPLOCK_NONE)
386 		op->action_taken |= SMB_OACT_LOCK;
387 	else
388 		op->action_taken &= ~SMB_OACT_LOCK;
389 
390 	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
391 
392 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
393 	case STYPE_DISKTREE:
394 	case STYPE_PRINTQ:
395 		node = sr->fid_ofile->f_node;
396 		if (smb_node_getattr(sr, node, &attr) != 0) {
397 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
398 			    ERRDOS, ERROR_INTERNAL_ERROR);
399 			return (SDRC_ERROR);
400 		}
401 
402 		rc = smbsr_encode_result(sr, 15, 0,
403 		    "bb.wwwllwwwwl2.w",
404 		    15,
405 		    sr->andx_com, VAR_BCC,
406 		    sr->smb_fid,
407 		    file_attr,
408 		    smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec),
409 		    (uint32_t)op->dsize,
410 		    op->omode, op->ftype,
411 		    op->devstate,
412 		    op->action_taken, op->fileid,
413 		    0);
414 		break;
415 
416 	case STYPE_IPC:
417 		rc = smbsr_encode_result(sr, 15, 0,
418 		    "bb.wwwllwwwwl2.w",
419 		    15,
420 		    sr->andx_com, VAR_BCC,
421 		    sr->smb_fid,
422 		    file_attr,
423 		    0L,
424 		    0L,
425 		    op->omode, op->ftype,
426 		    op->devstate,
427 		    op->action_taken, op->fileid,
428 		    0);
429 		break;
430 
431 	default:
432 		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
433 		    ERRDOS, ERROR_INVALID_FUNCTION);
434 		return (SDRC_ERROR);
435 	}
436 
437 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
438 }
439 
440 smb_sdrc_t
441 smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa)
442 {
443 	struct open_param *op = &sr->arg.open;
444 	uint32_t	creation_time;
445 	uint32_t	alloc_size;
446 	uint16_t	flags;
447 	uint16_t	file_attr;
448 	int		rc;
449 
450 	bzero(op, sizeof (sr->arg.open));
451 
452 	rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u",
453 	    sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr,
454 	    &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path);
455 	if (rc != 0)
456 		return (SDRC_ERROR);
457 
458 	if ((creation_time != 0) && (creation_time != UINT_MAX))
459 		op->crtime.tv_sec = smb_time_local_to_gmt(sr, creation_time);
460 	op->crtime.tv_nsec = 0;
461 
462 	op->dattr = file_attr;
463 	op->dsize = alloc_size;
464 	op->create_options = FILE_NON_DIRECTORY_FILE;
465 
466 	op->desired_access = smb_omode_to_amask(op->omode);
467 	op->share_access = smb_denymode_to_sharemode(op->omode,
468 	    op->fqi.fq_path.pn_path);
469 
470 	op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
471 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION)
472 		op->create_disposition = FILE_CREATE;
473 
474 	if (op->omode & SMB_DA_WRITE_THROUGH)
475 		op->create_options |= FILE_WRITE_THROUGH;
476 
477 	if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
478 		if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
479 			op->op_oplock_level = SMB_OPLOCK_BATCH;
480 		else
481 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
482 	} else {
483 		op->op_oplock_level = SMB_OPLOCK_NONE;
484 	}
485 	op->op_oplock_levelII = B_FALSE;
486 
487 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
488 		return (SDRC_ERROR);
489 
490 	if (op->op_oplock_level != SMB_OPLOCK_NONE)
491 		op->action_taken |= SMB_OACT_LOCK;
492 	else
493 		op->action_taken &= ~SMB_OACT_LOCK;
494 
495 	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
496 
497 	if (STYPE_ISIPC(sr->tid_tree->t_res_type))
498 		op->dsize = 0;
499 
500 	(void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl",
501 	    sr->smb_fid,
502 	    file_attr,
503 	    (uint32_t)0,	/* creation time */
504 	    (uint32_t)op->dsize,
505 	    op->omode,
506 	    op->ftype,
507 	    op->devstate,
508 	    op->action_taken,
509 	    op->fileid,
510 	    (uint16_t)0,	/* EA error offset */
511 	    (uint32_t)0);	/* EA list length */
512 
513 	return (SDRC_SUCCESS);
514 }
515