xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_nt_create_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 /*
26  * This command is used to create or open a file or directory.
27  */
28 
29 
30 #include <smbsrv/smb_kproto.h>
31 #include <smbsrv/smb_fsops.h>
32 #include <smbsrv/smb_vops.h>
33 
34 /*
35  * smb_com_nt_create_andx
36  *
37  * This command is used to create or open a file or directory.
38  *
39  *  Client Request                     Description
40  *  =================================  ==================================
41  *
42  *  UCHAR WordCount;                   Count of parameter words = 24
43  *  UCHAR AndXCommand;                 Secondary command;  0xFF = None
44  *  UCHAR AndXReserved;                Reserved (must be 0)
45  *  USHORT AndXOffset;                 Offset to next command WordCount
46  *  UCHAR Reserved;                    Reserved (must be 0)
47  *  USHORT NameLength;                 Length of Name[] in bytes
48  *  ULONG Flags;                       Create bit set:
49  *                                     0x02 - Request an oplock
50  *                                     0x04 - Request a batch oplock
51  *                                     0x08 - Target of open must be
52  *                                     directory
53  *  ULONG RootDirectoryFid;            If non-zero, open is relative to
54  *                                     this directory
55  *  ACCESS_MASK DesiredAccess;         access desired
56  *  LARGE_INTEGER AllocationSize;      Initial allocation size
57  *  ULONG ExtFileAttributes;           File attributes
58  *  ULONG ShareAccess;                 Type of share access
59  *  ULONG CreateDisposition;           Action to take if file exists or
60  *                                     not
61  *  ULONG CreateOptions;               Options to use if creating a file
62  *  ULONG ImpersonationLevel;          Security QOS information
63  *  UCHAR SecurityFlags;               Security tracking mode flags:
64  *                                     0x1 - SECURITY_CONTEXT_TRACKING
65  *                                     0x2 - SECURITY_EFFECTIVE_ONLY
66  *  USHORT ByteCount;                  Length of byte parameters
67  *  STRING Name[];                     File to open or create
68  *
69  * The DesiredAccess parameter is specified in section 3.7 on  Access Mask
70  * Encoding.
71  *
72  * If no value is specified, it still allows an application to query
73  * attributes without actually accessing the file.
74  *
75  * The ExtFIleAttributes parameter specifies the file attributes and flags
76  * for the file. The parameter's value is the sum of allowed attributes and
77  * flags defined in section 3.11 on  Extended File Attribute Encoding
78  *
79  * The ShareAccess field Specifies how this file can be shared. This
80  * parameter must be some combination of the following values:
81  *
82  * Name              Value      Meaning
83  *                   0          Prevents the file from being shared.
84  * FILE_SHARE_READ   0x00000001 Other open operations can be performed on
85  *                               the file for read access.
86  * FILE_SHARE_WRITE  0x00000002 Other open operations can be performed on
87  *                               the file for write access.
88  * FILE_SHARE_DELETE 0x00000004 Other open operations can be performed on
89  *                               the file for delete access.
90  *
91  * The CreateDisposition parameter can contain one of the following values:
92  *
93  * CREATE_NEW        Creates a new file. The function fails if the
94  *                   specified file already exists.
95  * CREATE_ALWAYS     Creates a new file. The function overwrites the file
96  *                   if it exists.
97  * OPEN_EXISTING     Opens the file. The function fails if the file does
98  *                   not exist.
99  * OPEN_ALWAYS       Opens the file, if it exists. If the file does not
100  *                   exist, act like CREATE_NEW.
101  * TRUNCATE_EXISTING Opens the file. Once opened, the file is truncated so
102  *                   that its size is zero bytes. The calling process must
103  *                   open the file with at least GENERIC_WRITE access. The
104  *                   function fails if the file does not exist.
105  *
106  * The ImpersonationLevel parameter can contain one or more of the
107  * following values:
108  *
109  * SECURITY_ANONYMOUS        Specifies to impersonate the client at the
110  *                           Anonymous impersonation level.
111  * SECURITY_IDENTIFICATION   Specifies to impersonate the client at the
112  *                           Identification impersonation level.
113  * SECURITY_IMPERSONATION    Specifies to impersonate the client at the
114  *                           Impersonation impersonation level.
115  * SECURITY_DELEGATION       Specifies to impersonate the client at the
116  *                           Delegation impersonation level.
117  *
118  * The SecurityFlags parameter can have either of the following two flags
119  * set:
120  *
121  * SECURITY_CONTEXT_TRACKING  Specifies that the security tracking mode is
122  *                            dynamic. If this flag is not specified,
123  *                            Security Tracking Mode is static.
124  * SECURITY_EFFECTIVE_ONLY    Specifies that only the enabled aspects of
125  *                            the client's security context are available
126  *                            to the server. If you do not specify this
127  *                            flag, all aspects of the client's security
128  *                            context are available. This flag allows the
129  *                            client to limit the groups and privileges
130  *                            that a server can use while impersonating the
131  *                            client.
132  *
133  * The response is as follows:
134  *
135  *  Server Response                    Description
136  *  =================================  ==================================
137  *
138  *  UCHAR WordCount;                   Count of parameter words = 26
139  *  UCHAR AndXCommand;  Secondary      0xFF = None
140  *  command;
141  *  UCHAR AndXReserved;                MBZ
142  *  USHORT AndXOffset;                 Offset to next command WordCount
143  *  UCHAR OplockLevel;                 The oplock level granted
144  *                                     0 - No oplock granted
145  *                                     1 - Exclusive oplock granted
146  *                                     2 - Batch oplock granted
147  *                                     3 - Level II oplock granted
148  *  USHORT Fid;                        The file ID
149  *  ULONG CreateAction;                The action taken
150  *  TIME CreationTime;                 The time the file was created
151  *  TIME LastAccessTime;               The time the file was accessed
152  *  TIME LastWriteTime;                The time the file was last written
153  *  TIME ChangeTime;                   The time the file was last changed
154  *  ULONG ExtFileAttributes;           The file attributes
155  *  LARGE_INTEGER AllocationSize;      The number of bytes allocated
156  *  LARGE_INTEGER EndOfFile;           The end of file offset
157  *  USHORT FileType;
158  *  USHORT DeviceState;                state of IPC device (e.g. pipe)
159  *  BOOLEAN Directory;                 TRUE if this is a directory
160  *  USHORT ByteCount;                  = 0
161  *
162  * The following SMBs may follow SMB_COM_NT_CREATE_ANDX:
163  *
164  *    SMB_COM_READ    SMB_COM_READ_ANDX
165  *    SMB_COM_IOCTL
166  */
167 smb_sdrc_t
168 smb_pre_nt_create_andx(smb_request_t *sr)
169 {
170 	struct open_param *op = &sr->arg.open;
171 	uint8_t SecurityFlags;
172 	uint32_t ImpersonationLevel;
173 	uint16_t NameLength;
174 	int rc;
175 
176 	bzero(op, sizeof (sr->arg.open));
177 
178 	rc = smbsr_decode_vwv(sr, "5.wlllqlllllb",
179 	    &NameLength,
180 	    &op->nt_flags,
181 	    &op->rootdirfid,
182 	    &op->desired_access,
183 	    &op->dsize,
184 	    &op->dattr,
185 	    &op->share_access,
186 	    &op->create_disposition,
187 	    &op->create_options,
188 	    &ImpersonationLevel,
189 	    &SecurityFlags);
190 
191 	if (rc == 0) {
192 		if (NameLength == 0) {
193 			op->fqi.fq_path.pn_path = "\\";
194 		} else if (NameLength >= MAXPATHLEN) {
195 			smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
196 			    ERRDOS, ERROR_PATH_NOT_FOUND);
197 			rc = -1;
198 		} else {
199 			rc = smbsr_decode_data(sr, "%#u", sr, NameLength,
200 			    &op->fqi.fq_path.pn_path);
201 		}
202 	}
203 
204 	op->op_oplock_level = SMB_OPLOCK_NONE;
205 	if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
206 		if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
207 			op->op_oplock_level = SMB_OPLOCK_BATCH;
208 		else
209 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
210 	}
211 
212 	DTRACE_SMB_2(op__NtCreateX__start, smb_request_t *, sr,
213 	    struct open_param *, op);
214 
215 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
216 }
217 
218 void
219 smb_post_nt_create_andx(smb_request_t *sr)
220 {
221 	DTRACE_SMB_1(op__NtCreateX__done, smb_request_t *, sr);
222 
223 	if (sr->arg.open.dir != NULL) {
224 		smb_ofile_release(sr->arg.open.dir);
225 		sr->arg.open.dir = NULL;
226 	}
227 }
228 
229 smb_sdrc_t
230 smb_com_nt_create_andx(struct smb_request *sr)
231 {
232 	struct open_param	*op = &sr->arg.open;
233 	unsigned char		DirFlag;
234 	smb_attr_t		attr;
235 	smb_node_t		*node;
236 	int rc;
237 
238 	if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
239 	    !(op->desired_access & DELETE)) {
240 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
241 		    ERRDOS, ERRbadaccess);
242 		return (SDRC_ERROR);
243 	}
244 
245 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
246 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
247 		    ERRDOS, ERRbadaccess);
248 		return (SDRC_ERROR);
249 	}
250 
251 	if (op->dattr & FILE_FLAG_WRITE_THROUGH)
252 		op->create_options |= FILE_WRITE_THROUGH;
253 
254 	if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
255 		op->create_options |= FILE_DELETE_ON_CLOSE;
256 
257 	if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
258 		op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
259 
260 	if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
261 		sr->user_cr = smb_user_getprivcred(sr->uid_user);
262 
263 	if (op->rootdirfid == 0) {
264 		op->fqi.fq_dnode = sr->tid_tree->t_snode;
265 	} else {
266 		op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
267 		    (uint16_t)op->rootdirfid);
268 		if (op->dir == NULL) {
269 			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
270 			    ERRDOS, ERRbadfid);
271 			return (SDRC_ERROR);
272 		}
273 		op->fqi.fq_dnode = op->dir->f_node;
274 	}
275 
276 	op->op_oplock_levelII = B_TRUE;
277 
278 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
279 		return (SDRC_ERROR);
280 
281 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
282 	case STYPE_DISKTREE:
283 	case STYPE_PRINTQ:
284 		if (op->create_options & FILE_DELETE_ON_CLOSE)
285 			smb_ofile_set_delete_on_close(sr->fid_ofile);
286 
287 		node = sr->fid_ofile->f_node;
288 		DirFlag = smb_node_is_dir(node) ? 1 : 0;
289 		if (smb_node_getattr(sr, node, &attr) != 0) {
290 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
291 			    ERRDOS, ERROR_INTERNAL_ERROR);
292 			return (SDRC_ERROR);
293 		}
294 
295 		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlTTTTlqqwwbw",
296 		    34,
297 		    sr->andx_com,
298 		    0x67,
299 		    op->op_oplock_level,
300 		    sr->smb_fid,
301 		    op->action_taken,
302 		    &attr.sa_crtime,
303 		    &attr.sa_vattr.va_atime,
304 		    &attr.sa_vattr.va_mtime,
305 		    &attr.sa_vattr.va_ctime,
306 		    op->dattr & FILE_ATTRIBUTE_MASK,
307 		    attr.sa_allocsz,
308 		    attr.sa_vattr.va_size,
309 		    op->ftype,
310 		    op->devstate,
311 		    DirFlag,
312 		    0);
313 		break;
314 
315 	case STYPE_IPC:
316 		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlqqqqlqqwwbw",
317 		    34,
318 		    sr->andx_com,
319 		    0x67,
320 		    0,
321 		    sr->smb_fid,
322 		    op->action_taken,
323 		    0LL,
324 		    0LL,
325 		    0LL,
326 		    0LL,
327 		    FILE_ATTRIBUTE_NORMAL,
328 		    0x1000LL,
329 		    0LL,
330 		    op->ftype,
331 		    op->devstate,
332 		    0,
333 		    0);
334 		break;
335 
336 	default:
337 		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
338 		    ERRDOS, ERROR_INVALID_FUNCTION);
339 		return (SDRC_ERROR);
340 	}
341 
342 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
343 }
344