xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c (revision eb1d736b1c19f6abeee90c921a9320b67fedd016)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
222c2961f8Sjose borrego  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw /*
27da6c28aaSamw  * This command is used to create or open a file or directory.
28da6c28aaSamw  */
29da6c28aaSamw 
30da6c28aaSamw 
31da6c28aaSamw #include <smbsrv/smb_incl.h>
32da6c28aaSamw #include <smbsrv/smb_fsops.h>
33da6c28aaSamw #include <smbsrv/smb_vops.h>
34da6c28aaSamw 
35da6c28aaSamw /*
36da6c28aaSamw  * smb_com_nt_create_andx
37da6c28aaSamw  *
38da6c28aaSamw  * This command is used to create or open a file or directory.
39da6c28aaSamw  *
40da6c28aaSamw  *  Client Request                     Description
41da6c28aaSamw  *  =================================  ==================================
42da6c28aaSamw  *
43da6c28aaSamw  *  UCHAR WordCount;                   Count of parameter words = 24
44da6c28aaSamw  *  UCHAR AndXCommand;                 Secondary command;  0xFF = None
45da6c28aaSamw  *  UCHAR AndXReserved;                Reserved (must be 0)
46da6c28aaSamw  *  USHORT AndXOffset;                 Offset to next command WordCount
47da6c28aaSamw  *  UCHAR Reserved;                    Reserved (must be 0)
48da6c28aaSamw  *  USHORT NameLength;                 Length of Name[] in bytes
49da6c28aaSamw  *  ULONG Flags;                       Create bit set:
50da6c28aaSamw  *                                     0x02 - Request an oplock
51da6c28aaSamw  *                                     0x04 - Request a batch oplock
52da6c28aaSamw  *                                     0x08 - Target of open must be
53da6c28aaSamw  *                                     directory
54da6c28aaSamw  *  ULONG RootDirectoryFid;            If non-zero, open is relative to
55da6c28aaSamw  *                                     this directory
56da6c28aaSamw  *  ACCESS_MASK DesiredAccess;         access desired
57da6c28aaSamw  *  LARGE_INTEGER AllocationSize;      Initial allocation size
58da6c28aaSamw  *  ULONG ExtFileAttributes;           File attributes
59da6c28aaSamw  *  ULONG ShareAccess;                 Type of share access
60da6c28aaSamw  *  ULONG CreateDisposition;           Action to take if file exists or
61da6c28aaSamw  *                                     not
62da6c28aaSamw  *  ULONG CreateOptions;               Options to use if creating a file
63da6c28aaSamw  *  ULONG ImpersonationLevel;          Security QOS information
64da6c28aaSamw  *  UCHAR SecurityFlags;               Security tracking mode flags:
65da6c28aaSamw  *                                     0x1 - SECURITY_CONTEXT_TRACKING
66da6c28aaSamw  *                                     0x2 - SECURITY_EFFECTIVE_ONLY
67da6c28aaSamw  *  USHORT ByteCount;                  Length of byte parameters
68da6c28aaSamw  *  STRING Name[];                     File to open or create
69da6c28aaSamw  *
70da6c28aaSamw  * The DesiredAccess parameter is specified in section 3.7 on  Access Mask
71da6c28aaSamw  * Encoding.
72da6c28aaSamw  *
73da6c28aaSamw  * If no value is specified, it still allows an application to query
74da6c28aaSamw  * attributes without actually accessing the file.
75da6c28aaSamw  *
76da6c28aaSamw  * The ExtFIleAttributes parameter specifies the file attributes and flags
77da6c28aaSamw  * for the file. The parameter's value is the sum of allowed attributes and
78da6c28aaSamw  * flags defined in section 3.11 on  Extended File Attribute Encoding
79da6c28aaSamw  *
80da6c28aaSamw  * The ShareAccess field Specifies how this file can be shared. This
81da6c28aaSamw  * parameter must be some combination of the following values:
82da6c28aaSamw  *
83da6c28aaSamw  * Name              Value      Meaning
84da6c28aaSamw  *                   0          Prevents the file from being shared.
85da6c28aaSamw  * FILE_SHARE_READ   0x00000001 Other open operations can be performed on
86da6c28aaSamw  *                               the file for read access.
87da6c28aaSamw  * FILE_SHARE_WRITE  0x00000002 Other open operations can be performed on
88da6c28aaSamw  *                               the file for write access.
89da6c28aaSamw  * FILE_SHARE_DELETE 0x00000004 Other open operations can be performed on
90da6c28aaSamw  *                               the file for delete access.
91da6c28aaSamw  *
92da6c28aaSamw  * The CreateDisposition parameter can contain one of the following values:
93da6c28aaSamw  *
94da6c28aaSamw  * CREATE_NEW        Creates a new file. The function fails if the
95da6c28aaSamw  *                   specified file already exists.
96da6c28aaSamw  * CREATE_ALWAYS     Creates a new file. The function overwrites the file
97da6c28aaSamw  *                   if it exists.
98da6c28aaSamw  * OPEN_EXISTING     Opens the file. The function fails if the file does
99da6c28aaSamw  *                   not exist.
100da6c28aaSamw  * OPEN_ALWAYS       Opens the file, if it exists. If the file does not
101da6c28aaSamw  *                   exist, act like CREATE_NEW.
102da6c28aaSamw  * TRUNCATE_EXISTING Opens the file. Once opened, the file is truncated so
103da6c28aaSamw  *                   that its size is zero bytes. The calling process must
104da6c28aaSamw  *                   open the file with at least GENERIC_WRITE access. The
105da6c28aaSamw  *                   function fails if the file does not exist.
106da6c28aaSamw  *
107da6c28aaSamw  * The ImpersonationLevel parameter can contain one or more of the
108da6c28aaSamw  * following values:
109da6c28aaSamw  *
110da6c28aaSamw  * SECURITY_ANONYMOUS        Specifies to impersonate the client at the
111da6c28aaSamw  *                           Anonymous impersonation level.
112da6c28aaSamw  * SECURITY_IDENTIFICATION   Specifies to impersonate the client at the
113da6c28aaSamw  *                           Identification impersonation level.
114da6c28aaSamw  * SECURITY_IMPERSONATION    Specifies to impersonate the client at the
115da6c28aaSamw  *                           Impersonation impersonation level.
116da6c28aaSamw  * SECURITY_DELEGATION       Specifies to impersonate the client at the
117da6c28aaSamw  *                           Delegation impersonation level.
118da6c28aaSamw  *
119da6c28aaSamw  * The SecurityFlags parameter can have either of the following two flags
120da6c28aaSamw  * set:
121da6c28aaSamw  *
122da6c28aaSamw  * SECURITY_CONTEXT_TRACKING  Specifies that the security tracking mode is
123da6c28aaSamw  *                            dynamic. If this flag is not specified,
124da6c28aaSamw  *                            Security Tracking Mode is static.
125da6c28aaSamw  * SECURITY_EFFECTIVE_ONLY    Specifies that only the enabled aspects of
126da6c28aaSamw  *                            the client's security context are available
127da6c28aaSamw  *                            to the server. If you do not specify this
128da6c28aaSamw  *                            flag, all aspects of the client's security
129da6c28aaSamw  *                            context are available. This flag allows the
130da6c28aaSamw  *                            client to limit the groups and privileges
131da6c28aaSamw  *                            that a server can use while impersonating the
132da6c28aaSamw  *                            client.
133da6c28aaSamw  *
134da6c28aaSamw  * The response is as follows:
135da6c28aaSamw  *
136da6c28aaSamw  *  Server Response                    Description
137da6c28aaSamw  *  =================================  ==================================
138da6c28aaSamw  *
139da6c28aaSamw  *  UCHAR WordCount;                   Count of parameter words = 26
140da6c28aaSamw  *  UCHAR AndXCommand;  Secondary      0xFF = None
141da6c28aaSamw  *  command;
142da6c28aaSamw  *  UCHAR AndXReserved;                MBZ
143da6c28aaSamw  *  USHORT AndXOffset;                 Offset to next command WordCount
144da6c28aaSamw  *  UCHAR OplockLevel;                 The oplock level granted
145da6c28aaSamw  *                                     0 - No oplock granted
146da6c28aaSamw  *                                     1 - Exclusive oplock granted
147da6c28aaSamw  *                                     2 - Batch oplock granted
148da6c28aaSamw  *                                     3 - Level II oplock granted
149da6c28aaSamw  *  USHORT Fid;                        The file ID
150da6c28aaSamw  *  ULONG CreateAction;                The action taken
151da6c28aaSamw  *  TIME CreationTime;                 The time the file was created
152da6c28aaSamw  *  TIME LastAccessTime;               The time the file was accessed
153da6c28aaSamw  *  TIME LastWriteTime;                The time the file was last written
154da6c28aaSamw  *  TIME ChangeTime;                   The time the file was last changed
155da6c28aaSamw  *  ULONG ExtFileAttributes;           The file attributes
156da6c28aaSamw  *  LARGE_INTEGER AllocationSize;      The number of bytes allocated
157da6c28aaSamw  *  LARGE_INTEGER EndOfFile;           The end of file offset
158da6c28aaSamw  *  USHORT FileType;
159da6c28aaSamw  *  USHORT DeviceState;                state of IPC device (e.g. pipe)
160da6c28aaSamw  *  BOOLEAN Directory;                 TRUE if this is a directory
161da6c28aaSamw  *  USHORT ByteCount;                  = 0
162da6c28aaSamw  *
163da6c28aaSamw  * The following SMBs may follow SMB_COM_NT_CREATE_ANDX:
164da6c28aaSamw  *
165da6c28aaSamw  *    SMB_COM_READ    SMB_COM_READ_ANDX
166da6c28aaSamw  *    SMB_COM_IOCTL
167da6c28aaSamw  */
1687b59d02dSjb150015 smb_sdrc_t
169faa1795aSjb150015 smb_pre_nt_create_andx(smb_request_t *sr)
170da6c28aaSamw {
171da6c28aaSamw 	struct open_param *op = &sr->arg.open;
172faa1795aSjb150015 	uint8_t SecurityFlags;
173da6c28aaSamw 	uint32_t ImpersonationLevel;
174faa1795aSjb150015 	uint16_t NameLength;
175da6c28aaSamw 	int rc;
176da6c28aaSamw 
177faa1795aSjb150015 	bzero(op, sizeof (sr->arg.open));
178da6c28aaSamw 
179da6c28aaSamw 	rc = smbsr_decode_vwv(sr, "5.wlllqlllllb",
180da6c28aaSamw 	    &NameLength,
1812c2961f8Sjose borrego 	    &op->nt_flags,
182faa1795aSjb150015 	    &op->rootdirfid,
183da6c28aaSamw 	    &op->desired_access,
184da6c28aaSamw 	    &op->dsize,
185faa1795aSjb150015 	    &op->dattr,
186da6c28aaSamw 	    &op->share_access,
187da6c28aaSamw 	    &op->create_disposition,
188da6c28aaSamw 	    &op->create_options,
189da6c28aaSamw 	    &ImpersonationLevel,
190da6c28aaSamw 	    &SecurityFlags);
191da6c28aaSamw 
192faa1795aSjb150015 	if (rc == 0) {
193faa1795aSjb150015 		if (NameLength == 0) {
194*eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			op->fqi.fq_path.pn_path = "\\";
195faa1795aSjb150015 		} else if (NameLength >= MAXPATHLEN) {
196faa1795aSjb150015 			smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
197faa1795aSjb150015 			    ERRDOS, ERROR_PATH_NOT_FOUND);
198faa1795aSjb150015 			rc = -1;
199faa1795aSjb150015 		} else {
200faa1795aSjb150015 			rc = smbsr_decode_data(sr, "%#u", sr, NameLength,
201*eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			    &op->fqi.fq_path.pn_path);
202da6c28aaSamw 		}
203da6c28aaSamw 	}
204da6c28aaSamw 
2052c2961f8Sjose borrego 	op->op_oplock_level = SMB_OPLOCK_NONE;
2062c2961f8Sjose borrego 	if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
2072c2961f8Sjose borrego 		if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
2082c2961f8Sjose borrego 			op->op_oplock_level = SMB_OPLOCK_BATCH;
2092c2961f8Sjose borrego 		else
2102c2961f8Sjose borrego 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
211da6c28aaSamw 	}
212da6c28aaSamw 
213faa1795aSjb150015 	DTRACE_SMB_2(op__NtCreateX__start, smb_request_t *, sr,
214faa1795aSjb150015 	    struct open_param *, op);
215faa1795aSjb150015 
216faa1795aSjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
217faa1795aSjb150015 }
218faa1795aSjb150015 
219faa1795aSjb150015 void
220faa1795aSjb150015 smb_post_nt_create_andx(smb_request_t *sr)
221faa1795aSjb150015 {
222faa1795aSjb150015 	DTRACE_SMB_1(op__NtCreateX__done, smb_request_t *, sr);
223faa1795aSjb150015 }
224faa1795aSjb150015 
225faa1795aSjb150015 smb_sdrc_t
226faa1795aSjb150015 smb_com_nt_create_andx(struct smb_request *sr)
227faa1795aSjb150015 {
228faa1795aSjb150015 	struct open_param	*op = &sr->arg.open;
229faa1795aSjb150015 	unsigned char		OplockLevel;
230faa1795aSjb150015 	unsigned char		DirFlag;
231faa1795aSjb150015 	smb_attr_t		new_attr;
232faa1795aSjb150015 	smb_node_t		*node;
233faa1795aSjb150015 	int rc;
234faa1795aSjb150015 
235faa1795aSjb150015 	if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
236faa1795aSjb150015 	    !(op->desired_access & DELETE)) {
2372c2961f8Sjose borrego 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
2382c2961f8Sjose borrego 		    ERRDOS, ERRbadaccess);
2392c2961f8Sjose borrego 		return (SDRC_ERROR);
2402c2961f8Sjose borrego 	}
2412c2961f8Sjose borrego 
2422c2961f8Sjose borrego 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
2432c2961f8Sjose borrego 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
2442c2961f8Sjose borrego 		    ERRDOS, ERRbadaccess);
245faa1795aSjb150015 		return (SDRC_ERROR);
246faa1795aSjb150015 	}
247faa1795aSjb150015 
248faa1795aSjb150015 	if (op->dattr & FILE_FLAG_WRITE_THROUGH)
249da6c28aaSamw 		op->create_options |= FILE_WRITE_THROUGH;
250da6c28aaSamw 
251faa1795aSjb150015 	if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
252da6c28aaSamw 		op->create_options |= FILE_DELETE_ON_CLOSE;
253da6c28aaSamw 
254b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
255b89a8333Snatalie li - Sun Microsystems - Irvine United States 		op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
256b89a8333Snatalie li - Sun Microsystems - Irvine United States 
257b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
258b89a8333Snatalie li - Sun Microsystems - Irvine United States 		sr->user_cr = smb_user_getprivcred(sr->uid_user);
259b89a8333Snatalie li - Sun Microsystems - Irvine United States 
260faa1795aSjb150015 	if (op->rootdirfid == 0) {
261*eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->fqi.fq_dnode = sr->tid_tree->t_snode;
262da6c28aaSamw 	} else {
263faa1795aSjb150015 		sr->smb_fid = (ushort_t)op->rootdirfid;
2642c2961f8Sjose borrego 		smbsr_lookup_file(sr);
265da6c28aaSamw 		if (sr->fid_ofile == NULL) {
266dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
267da6c28aaSamw 			    ERRDOS, ERRbadfid);
268faa1795aSjb150015 			return (SDRC_ERROR);
269da6c28aaSamw 		}
270da6c28aaSamw 
271*eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->fqi.fq_dnode = sr->fid_ofile->f_node;
272da6c28aaSamw 		smbsr_disconnect_file(sr);
273da6c28aaSamw 	}
274da6c28aaSamw 
2757b59d02dSjb150015 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
276faa1795aSjb150015 		return (SDRC_ERROR);
277da6c28aaSamw 
278da6c28aaSamw 	if (STYPE_ISDSK(sr->tid_tree->t_res_type)) {
2792c2961f8Sjose borrego 		switch (op->op_oplock_level) {
2802c2961f8Sjose borrego 		case SMB_OPLOCK_EXCLUSIVE:
281da6c28aaSamw 			OplockLevel = 1;
282da6c28aaSamw 			break;
2832c2961f8Sjose borrego 		case SMB_OPLOCK_BATCH:
284da6c28aaSamw 			OplockLevel = 2;
285da6c28aaSamw 			break;
2862c2961f8Sjose borrego 		case SMB_OPLOCK_LEVEL_II:
287da6c28aaSamw 			OplockLevel = 3;
288da6c28aaSamw 			break;
2892c2961f8Sjose borrego 		case SMB_OPLOCK_NONE:
290da6c28aaSamw 		default:
291da6c28aaSamw 			OplockLevel = 0;
292da6c28aaSamw 			break;
293da6c28aaSamw 		}
294da6c28aaSamw 
295da6c28aaSamw 		if (op->create_options & FILE_DELETE_ON_CLOSE)
2968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_ofile_set_delete_on_close(sr->fid_ofile);
297da6c28aaSamw 
298da6c28aaSamw 		/*
299da6c28aaSamw 		 * Set up the directory flag and ensure that
300da6c28aaSamw 		 * we don't return a stale file size.
301da6c28aaSamw 		 */
302da6c28aaSamw 		node = sr->fid_ofile->f_node;
303da6c28aaSamw 		if (node->attr.sa_vattr.va_type == VDIR) {
304da6c28aaSamw 			DirFlag = 1;
305da6c28aaSamw 			new_attr.sa_vattr.va_size = 0;
306da6c28aaSamw 		} else {
307da6c28aaSamw 			DirFlag = 0;
308da6c28aaSamw 			new_attr.sa_mask = SMB_AT_SIZE;
309da6c28aaSamw 			(void) smb_fsop_getattr(sr, kcred, node, &new_attr);
310da6c28aaSamw 			node->attr.sa_vattr.va_size = new_attr.sa_vattr.va_size;
311da6c28aaSamw 		}
312da6c28aaSamw 
3137b59d02dSjb150015 		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlTTTTlqqwwbw",
314da6c28aaSamw 		    34,
315da6c28aaSamw 		    sr->andx_com,
316da6c28aaSamw 		    0x67,
317da6c28aaSamw 		    OplockLevel,
318da6c28aaSamw 		    sr->smb_fid,
319da6c28aaSamw 		    op->action_taken,
320da6c28aaSamw 		    &node->attr.sa_crtime,
321da6c28aaSamw 		    &node->attr.sa_vattr.va_atime,
322da6c28aaSamw 		    &node->attr.sa_vattr.va_mtime,
323da6c28aaSamw 		    &node->attr.sa_vattr.va_ctime,
324da6c28aaSamw 		    op->dattr & FILE_ATTRIBUTE_MASK,
325da6c28aaSamw 		    new_attr.sa_vattr.va_size,
326da6c28aaSamw 		    new_attr.sa_vattr.va_size,
327da6c28aaSamw 		    op->ftype,
328da6c28aaSamw 		    op->devstate,
329da6c28aaSamw 		    DirFlag,
330da6c28aaSamw 		    0);
331da6c28aaSamw 	} else {
332da6c28aaSamw 		/* Named PIPE */
333da6c28aaSamw 		OplockLevel = 0;
3347b59d02dSjb150015 		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlqqqqlqqwwbw",
335da6c28aaSamw 		    34,
336da6c28aaSamw 		    sr->andx_com,
337da6c28aaSamw 		    0x67,
338da6c28aaSamw 		    OplockLevel,
339da6c28aaSamw 		    sr->smb_fid,
340da6c28aaSamw 		    op->action_taken,
341da6c28aaSamw 		    0LL,
342da6c28aaSamw 		    0LL,
343da6c28aaSamw 		    0LL,
344da6c28aaSamw 		    0LL,
3453db3f65cSamw 		    FILE_ATTRIBUTE_NORMAL,
346da6c28aaSamw 		    0x1000LL,
347da6c28aaSamw 		    0LL,
348da6c28aaSamw 		    op->ftype,
349da6c28aaSamw 		    op->devstate,
350da6c28aaSamw 		    0,
351da6c28aaSamw 		    0);
352da6c28aaSamw 	}
353da6c28aaSamw 
354faa1795aSjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
355da6c28aaSamw }
356