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
smb_pre_open(smb_request_t * sr)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
smb_post_open(smb_request_t * sr)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
smb_com_open(smb_request_t * sr)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
smb_pre_open_andx(smb_request_t * sr)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
smb_post_open_andx(smb_request_t * sr)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
smb_com_open_andx(smb_request_t * sr)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
smb_com_trans2_open2(smb_request_t * sr,smb_xa_t * xa)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