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 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 #include <smbsrv/smb_kproto.h>
27 #include <smbsrv/smb_vops.h>
28
29 int 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
217 smb_sdrc_t
smb_pre_open(smb_request_t * sr)218 smb_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
235 void
smb_post_open(smb_request_t * sr)236 smb_post_open(smb_request_t *sr)
237 {
238 DTRACE_SMB_1(op__Open__done, smb_request_t *, sr);
239 }
240
241 smb_sdrc_t
smb_com_open(smb_request_t * sr)242 smb_com_open(smb_request_t *sr)
243 {
244 struct open_param *op = &sr->arg.open;
245 smb_ofile_t *of;
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 op->op_oplock_levelII = B_FALSE;
268
269 if (smb_open_dsize_check && op->dsize > UINT_MAX) {
270 smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
271 return (SDRC_ERROR);
272 }
273
274 if (smb_common_open(sr) != NT_STATUS_SUCCESS)
275 return (SDRC_ERROR);
276
277 /*
278 * NB: after the above smb_common_open() success,
279 * we have a handle allocated (sr->fid_ofile).
280 * If we don't return success, we must close it.
281 */
282 of = sr->fid_ofile;
283
284 if (op->op_oplock_level == SMB_OPLOCK_NONE) {
285 sr->smb_flg &=
286 ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY);
287 }
288
289 file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
290 bzero(&attr, sizeof (attr));
291 attr.sa_mask = SMB_AT_MTIME;
292 rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
293 if (rc != 0) {
294 smbsr_errno(sr, rc);
295 goto errout;
296 }
297
298 rc = smbsr_encode_result(sr, 7, 0, "bwwllww",
299 7,
300 sr->smb_fid,
301 file_attr,
302 smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec),
303 (uint32_t)op->dsize,
304 op->omode,
305 (uint16_t)0); /* bcc */
306
307 if (rc == 0)
308 return (SDRC_SUCCESS);
309
310 errout:
311 smb_ofile_close(of, 0);
312 return (SDRC_ERROR);
313 }
314
315 /*
316 * smb_pre_open_andx
317 * For compatibility with windows servers, the search attributes
318 * specified in the request are ignored.
319 */
320 smb_sdrc_t
smb_pre_open_andx(smb_request_t * sr)321 smb_pre_open_andx(smb_request_t *sr)
322 {
323 struct open_param *op = &sr->arg.open;
324 uint16_t flags;
325 uint32_t creation_time;
326 uint16_t file_attr, sattr;
327 int rc;
328
329 bzero(op, sizeof (sr->arg.open));
330
331 rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com,
332 &sr->andx_off, &flags, &op->omode, &sattr,
333 &file_attr, &creation_time, &op->ofun, &op->dsize, &op->timeo);
334
335 if (rc == 0) {
336 rc = smbsr_decode_data(sr, "%u", sr, &op->fqi.fq_path.pn_path);
337
338 op->dattr = file_attr;
339
340 if (flags & 2)
341 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
342 else if (flags & 4)
343 op->op_oplock_level = SMB_OPLOCK_BATCH;
344 else
345 op->op_oplock_level = SMB_OPLOCK_NONE;
346
347 if ((creation_time != 0) && (creation_time != UINT_MAX))
348 op->crtime.tv_sec =
349 smb_time_local_to_gmt(sr, creation_time);
350 op->crtime.tv_nsec = 0;
351
352 op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
353 }
354
355 DTRACE_SMB_2(op__OpenX__start, smb_request_t *, sr,
356 struct open_param *, op);
357
358 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
359 }
360
361 void
smb_post_open_andx(smb_request_t * sr)362 smb_post_open_andx(smb_request_t *sr)
363 {
364 DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr);
365 }
366
367 smb_sdrc_t
smb_com_open_andx(smb_request_t * sr)368 smb_com_open_andx(smb_request_t *sr)
369 {
370 struct open_param *op = &sr->arg.open;
371 smb_ofile_t *of;
372 uint16_t file_attr;
373 smb_attr_t attr;
374 int rc;
375
376 op->desired_access = smb_omode_to_amask(op->omode);
377 op->share_access = smb_denymode_to_sharemode(op->omode,
378 op->fqi.fq_path.pn_path);
379
380 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
381 smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
382 return (SDRC_ERROR);
383 }
384
385 op->create_options = FILE_NON_DIRECTORY_FILE;
386 if (op->omode & SMB_DA_WRITE_THROUGH)
387 op->create_options |= FILE_WRITE_THROUGH;
388
389 op->op_oplock_levelII = B_FALSE;
390
391 if (smb_open_dsize_check && op->dsize > UINT_MAX) {
392 smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
393 return (SDRC_ERROR);
394 }
395
396 if (smb_common_open(sr) != NT_STATUS_SUCCESS)
397 return (SDRC_ERROR);
398
399 /*
400 * NB: after the above smb_common_open() success,
401 * we have a handle allocated (sr->fid_ofile).
402 * If we don't return success, we must close it.
403 */
404 of = sr->fid_ofile;
405
406 if (op->op_oplock_level != SMB_OPLOCK_NONE)
407 op->action_taken |= SMB_OACT_LOCK;
408 else
409 op->action_taken &= ~SMB_OACT_LOCK;
410
411 file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
412 bzero(&attr, sizeof (attr));
413
414 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
415 case STYPE_DISKTREE:
416 case STYPE_PRINTQ:
417 attr.sa_mask = SMB_AT_MTIME;
418 rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
419 if (rc != 0) {
420 smbsr_errno(sr, rc);
421 goto errout;
422 }
423
424 rc = smbsr_encode_result(sr, 15, 0,
425 "bb.wwwllwwwwl2.w",
426 15,
427 sr->andx_com, VAR_BCC,
428 sr->smb_fid,
429 file_attr,
430 smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec),
431 (uint32_t)op->dsize,
432 op->omode, op->ftype,
433 op->devstate,
434 op->action_taken, op->fileid,
435 0);
436 break;
437
438 case STYPE_IPC:
439 rc = smbsr_encode_result(sr, 15, 0,
440 "bb.wwwllwwwwl2.w",
441 15,
442 sr->andx_com, VAR_BCC,
443 sr->smb_fid,
444 file_attr,
445 0L,
446 0L,
447 op->omode, op->ftype,
448 op->devstate,
449 op->action_taken, op->fileid,
450 0);
451 break;
452
453 default:
454 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
455 ERRDOS, ERROR_INVALID_FUNCTION);
456 goto errout;
457 }
458
459 if (rc == 0)
460 return (SDRC_SUCCESS);
461
462 errout:
463 smb_ofile_close(of, 0);
464 return (SDRC_ERROR);
465 }
466
467 smb_sdrc_t
smb_com_trans2_open2(smb_request_t * sr,smb_xa_t * xa)468 smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa)
469 {
470 struct open_param *op = &sr->arg.open;
471 uint32_t creation_time;
472 uint32_t alloc_size;
473 uint16_t flags;
474 uint16_t file_attr;
475 int rc;
476
477 bzero(op, sizeof (sr->arg.open));
478
479 rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u",
480 sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr,
481 &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path);
482 if (rc != 0)
483 return (SDRC_ERROR);
484
485 if ((creation_time != 0) && (creation_time != UINT_MAX))
486 op->crtime.tv_sec = smb_time_local_to_gmt(sr, creation_time);
487 op->crtime.tv_nsec = 0;
488
489 op->dattr = file_attr;
490 op->dsize = alloc_size;
491 op->create_options = FILE_NON_DIRECTORY_FILE;
492
493 op->desired_access = smb_omode_to_amask(op->omode);
494 op->share_access = smb_denymode_to_sharemode(op->omode,
495 op->fqi.fq_path.pn_path);
496
497 op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
498 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION)
499 op->create_disposition = FILE_CREATE;
500
501 if (op->omode & SMB_DA_WRITE_THROUGH)
502 op->create_options |= FILE_WRITE_THROUGH;
503
504 if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
505 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
506 op->op_oplock_level = SMB_OPLOCK_BATCH;
507 else
508 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
509 } else {
510 op->op_oplock_level = SMB_OPLOCK_NONE;
511 }
512 op->op_oplock_levelII = B_FALSE;
513
514 if (smb_common_open(sr) != NT_STATUS_SUCCESS)
515 return (SDRC_ERROR);
516
517 if (op->op_oplock_level != SMB_OPLOCK_NONE)
518 op->action_taken |= SMB_OACT_LOCK;
519 else
520 op->action_taken &= ~SMB_OACT_LOCK;
521
522 file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
523
524 if (STYPE_ISIPC(sr->tid_tree->t_res_type))
525 op->dsize = 0;
526
527 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl",
528 sr->smb_fid,
529 file_attr,
530 (uint32_t)0, /* creation time */
531 (uint32_t)op->dsize,
532 op->omode,
533 op->ftype,
534 op->devstate,
535 op->action_taken,
536 op->fileid,
537 (uint16_t)0, /* EA error offset */
538 (uint32_t)0); /* EA list length */
539
540 return (SDRC_SUCCESS);
541 }
542