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 /*
22cb174861Sjoyce mcintosh  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2393bc28dbSGordon Ross  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw /*
27da6c28aaSamw  * This command is used to create or open a file or directory, when EAs
28da6c28aaSamw  * or an SD must be applied to the file. The functionality is similar
29da6c28aaSamw  * to SmbNtCreateAndx with the option to supply extended attributes or
30da6c28aaSamw  * a security descriptor.
31da6c28aaSamw  *
32da6c28aaSamw  * Note: we don't decode the extended attributes because we don't
33da6c28aaSamw  * support them at this time.
34da6c28aaSamw  */
35da6c28aaSamw 
3655bf511dSas #include <smbsrv/smb_kproto.h>
37da6c28aaSamw #include <smbsrv/smb_fsops.h>
38da6c28aaSamw 
39c5f48fa5SGordon Ross extern int smb_nt_create_enable_extended_response;
40c5f48fa5SGordon Ross 
41da6c28aaSamw /*
42da6c28aaSamw  * smb_nt_transact_create
43da6c28aaSamw  *
44da6c28aaSamw  * This command is used to create or open a file or directory, when EAs
45da6c28aaSamw  * or an SD must be applied to the file. The request parameter block
46da6c28aaSamw  * encoding, data block encoding and output parameter block encoding are
47da6c28aaSamw  * described in CIFS section 4.2.2.
48da6c28aaSamw  *
49da6c28aaSamw  * The format of the command is SmbNtTransact but it is basically the same
50da6c28aaSamw  * as SmbNtCreateAndx with the option to supply extended attributes or a
51da6c28aaSamw  * security descriptor. For information not defined in CIFS section 4.2.2
52da6c28aaSamw  * see section 4.2.1 (NT_CREATE_ANDX).
53da6c28aaSamw  */
547b59d02dSjb smb_sdrc_t
smb_pre_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)55faa1795aSjb smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
56da6c28aaSamw {
57da6c28aaSamw 	struct open_param *op = &sr->arg.open;
58faa1795aSjb 	uint8_t SecurityFlags;
59faa1795aSjb 	uint32_t EaLength;
60faa1795aSjb 	uint32_t ImpersonationLevel;
61faa1795aSjb 	uint32_t NameLength;
62faa1795aSjb 	uint32_t sd_len;
63faa1795aSjb 	uint32_t status;
64faa1795aSjb 	smb_sd_t sd;
65da6c28aaSamw 	int rc;
66da6c28aaSamw 
67faa1795aSjb 	bzero(op, sizeof (sr->arg.open));
68faa1795aSjb 
693db3f65cSamw 	rc = smb_mbc_decodef(&xa->req_param_mb, "%lllqllllllllb",
70da6c28aaSamw 	    sr,
712c2961f8Sjose borrego 	    &op->nt_flags,
72faa1795aSjb 	    &op->rootdirfid,
73da6c28aaSamw 	    &op->desired_access,
74da6c28aaSamw 	    &op->dsize,
75faa1795aSjb 	    &op->dattr,
76da6c28aaSamw 	    &op->share_access,
77da6c28aaSamw 	    &op->create_disposition,
78da6c28aaSamw 	    &op->create_options,
79da6c28aaSamw 	    &sd_len,
80da6c28aaSamw 	    &EaLength,
81da6c28aaSamw 	    &NameLength,
82da6c28aaSamw 	    &ImpersonationLevel,
83da6c28aaSamw 	    &SecurityFlags);
84da6c28aaSamw 
85faa1795aSjb 	if (rc == 0) {
86faa1795aSjb 		if (NameLength == 0) {
87eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			op->fqi.fq_path.pn_path = "\\";
88c5f48fa5SGordon Ross 		} else if (NameLength >= SMB_MAXPATHLEN) {
89c5f48fa5SGordon Ross 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
90c5f48fa5SGordon Ross 			    ERRDOS, ERROR_INVALID_NAME);
91faa1795aSjb 			rc = -1;
92faa1795aSjb 		} else {
933db3f65cSamw 			rc = smb_mbc_decodef(&xa->req_param_mb, "%#u",
94eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			    sr, NameLength, &op->fqi.fq_path.pn_path);
95faa1795aSjb 		}
96da6c28aaSamw 	}
97da6c28aaSamw 
982c2961f8Sjose borrego 	op->op_oplock_level = SMB_OPLOCK_NONE;
992c2961f8Sjose borrego 	if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
1002c2961f8Sjose borrego 		if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
1012c2961f8Sjose borrego 			op->op_oplock_level = SMB_OPLOCK_BATCH;
1022c2961f8Sjose borrego 		else
1032c2961f8Sjose borrego 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
104da6c28aaSamw 	}
105da6c28aaSamw 
10655bf511dSas 	if (sd_len) {
107a90cf9f2SGordon Ross 		status = smb_decode_sd(&xa->req_data_mb, &sd);
10855bf511dSas 		if (status != NT_STATUS_SUCCESS) {
109dc20a302Sas 			smbsr_error(sr, status, 0, 0);
110faa1795aSjb 			return (SDRC_ERROR);
111da6c28aaSamw 		}
112e5468186Sas 		op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP);
113e5468186Sas 		*op->sd = sd;
114da6c28aaSamw 	} else {
11555bf511dSas 		op->sd = NULL;
116da6c28aaSamw 	}
117da6c28aaSamw 
11893bc28dbSGordon Ross 	DTRACE_SMB_START(op__NtTransactCreate, smb_request_t *, sr);
119da6c28aaSamw 
120faa1795aSjb 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
121faa1795aSjb }
122da6c28aaSamw 
123faa1795aSjb void
smb_post_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)124faa1795aSjb smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
125faa1795aSjb {
126e5468186Sas 	smb_sd_t *sd = sr->arg.open.sd;
12793bc28dbSGordon Ross 	_NOTE(ARGUNUSED(xa))
128e5468186Sas 
12993bc28dbSGordon Ross 	DTRACE_SMB_DONE(op__NtTransactCreate, smb_request_t *, sr);
130e5468186Sas 
131e5468186Sas 	if (sd) {
132e5468186Sas 		smb_sd_term(sd);
133e5468186Sas 		kmem_free(sd, sizeof (smb_sd_t));
134e5468186Sas 	}
135bbf6f00cSJordan Brown 
136c5f48fa5SGordon Ross 	if (sr->arg.open.dir != NULL) {
137bbf6f00cSJordan Brown 		smb_ofile_release(sr->arg.open.dir);
138c5f48fa5SGordon Ross 		sr->arg.open.dir = NULL;
139c5f48fa5SGordon Ross 	}
140faa1795aSjb }
141da6c28aaSamw 
142c5f48fa5SGordon Ross /*
143c5f48fa5SGordon Ross  * A lot like smb_com_nt_create_andx
144c5f48fa5SGordon Ross  */
145faa1795aSjb smb_sdrc_t
smb_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)146faa1795aSjb smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
147faa1795aSjb {
148c5f48fa5SGordon Ross 	struct open_param	*op = &sr->arg.open;
149c5f48fa5SGordon Ross 	smb_attr_t		*ap = &op->fqi.fq_fattr;
1505fd03bc0SGordon Ross 	smb_ofile_t		*of;
1515fd03bc0SGordon Ross 	int			rc;
152c5f48fa5SGordon Ross 	uint8_t			DirFlag;
153c5f48fa5SGordon Ross 	uint32_t		status;
154c5f48fa5SGordon Ross 
155c5f48fa5SGordon Ross 	if (op->create_options & ~SMB_NTCREATE_VALID_OPTIONS) {
156c5f48fa5SGordon Ross 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
157c5f48fa5SGordon Ross 		    ERRDOS, ERROR_INVALID_PARAMETER);
158c5f48fa5SGordon Ross 		return (SDRC_ERROR);
159c5f48fa5SGordon Ross 	}
160c5f48fa5SGordon Ross 
161c5f48fa5SGordon Ross 	if (op->create_options & FILE_OPEN_BY_FILE_ID) {
162c5f48fa5SGordon Ross 		smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
163c5f48fa5SGordon Ross 		    ERRDOS, ERROR_NOT_SUPPORTED);
164c5f48fa5SGordon Ross 		return (SDRC_ERROR);
165c5f48fa5SGordon Ross 	}
166faa1795aSjb 
167faa1795aSjb 	if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
168faa1795aSjb 	    !(op->desired_access & DELETE)) {
1692c2961f8Sjose borrego 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
1702c2961f8Sjose borrego 		    ERRDOS, ERRbadaccess);
1712c2961f8Sjose borrego 		return (SDRC_ERROR);
1722c2961f8Sjose borrego 	}
1732c2961f8Sjose borrego 
1742c2961f8Sjose borrego 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
1752c2961f8Sjose borrego 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
1762c2961f8Sjose borrego 		    ERRDOS, ERRbadaccess);
177faa1795aSjb 		return (SDRC_ERROR);
178da6c28aaSamw 	}
179da6c28aaSamw 
180faa1795aSjb 	if (op->dattr & FILE_FLAG_WRITE_THROUGH)
181da6c28aaSamw 		op->create_options |= FILE_WRITE_THROUGH;
182da6c28aaSamw 
183faa1795aSjb 	if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
184da6c28aaSamw 		op->create_options |= FILE_DELETE_ON_CLOSE;
185da6c28aaSamw 
186b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
187b89a8333Snatalie li - Sun Microsystems - Irvine United States 		op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
188b89a8333Snatalie li - Sun Microsystems - Irvine United States 
189b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
190b89a8333Snatalie li - Sun Microsystems - Irvine United States 		sr->user_cr = smb_user_getprivcred(sr->uid_user);
191b89a8333Snatalie li - Sun Microsystems - Irvine United States 
192faa1795aSjb 	if (op->rootdirfid == 0) {
193eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->fqi.fq_dnode = sr->tid_tree->t_snode;
194da6c28aaSamw 	} else {
1953b13a1efSThomas Keiser 		op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid);
196bbf6f00cSJordan Brown 		if (op->dir == NULL) {
197faa1795aSjb 			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
198faa1795aSjb 			    ERRDOS, ERRbadfid);
199faa1795aSjb 			return (SDRC_ERROR);
200faa1795aSjb 		}
201bbf6f00cSJordan Brown 		op->fqi.fq_dnode = op->dir->f_node;
202da6c28aaSamw 	}
203da6c28aaSamw 
204a90cf9f2SGordon Ross 	status = smb_common_open(sr);
205a90cf9f2SGordon Ross 	if (status != NT_STATUS_SUCCESS) {
206a90cf9f2SGordon Ross 		smbsr_status(sr, status, 0, 0);
207faa1795aSjb 		return (SDRC_ERROR);
208a90cf9f2SGordon Ross 	}
209*94047d49SGordon Ross 	if (op->op_oplock_level != SMB_OPLOCK_NONE) {
210*94047d49SGordon Ross 		/* Oplock req. in op->op_oplock_level etc. */
211*94047d49SGordon Ross 		smb1_oplock_acquire(sr, B_TRUE);
212*94047d49SGordon Ross 	}
213da6c28aaSamw 
2145fd03bc0SGordon Ross 	/*
2155fd03bc0SGordon Ross 	 * NB: after the above smb_common_open() success,
2165fd03bc0SGordon Ross 	 * we have a handle allocated (sr->fid_ofile).
2175fd03bc0SGordon Ross 	 * If we don't return success, we must close it.
2185fd03bc0SGordon Ross 	 */
2195fd03bc0SGordon Ross 	of = sr->fid_ofile;
2205fd03bc0SGordon Ross 
221f96bd5c8SAlan Wright 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
222f96bd5c8SAlan Wright 	case STYPE_DISKTREE:
223f96bd5c8SAlan Wright 	case STYPE_PRINTQ:
224da6c28aaSamw 		if (op->create_options & FILE_DELETE_ON_CLOSE)
225*94047d49SGordon Ross 			smb_ofile_set_delete_on_close(sr, of);
2265fd03bc0SGordon Ross 		DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
227f96bd5c8SAlan Wright 		break;
228f96bd5c8SAlan Wright 
229f96bd5c8SAlan Wright 	case STYPE_IPC:
230c5f48fa5SGordon Ross 		DirFlag = 0;
231f96bd5c8SAlan Wright 		break;
232f96bd5c8SAlan Wright 
233f96bd5c8SAlan Wright 	default:
234f96bd5c8SAlan Wright 		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
235f96bd5c8SAlan Wright 		    ERRDOS, ERROR_INVALID_FUNCTION);
2365fd03bc0SGordon Ross 		goto errout;
237da6c28aaSamw 	}
238c5f48fa5SGordon Ross 
239c5f48fa5SGordon Ross 	if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 &&
240c5f48fa5SGordon Ross 	    smb_nt_create_enable_extended_response != 0) {
241c5f48fa5SGordon Ross 		uint32_t MaxAccess = 0;
242c5f48fa5SGordon Ross 		if (of->f_node != NULL) {
243c5f48fa5SGordon Ross 			smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess);
244c5f48fa5SGordon Ross 		}
245c5f48fa5SGordon Ross 		MaxAccess |= of->f_granted_access;
246c5f48fa5SGordon Ross 
247c5f48fa5SGordon Ross 		rc = smb_mbc_encodef(
248c5f48fa5SGordon Ross 		    &xa->rep_param_mb, "bbwllTTTTlqqwwb16.qll",
249c5f48fa5SGordon Ross 		    op->op_oplock_level,	/* (b) */
250c5f48fa5SGordon Ross 		    1,		/* ResponseType	   (b) */
251c5f48fa5SGordon Ross 		    sr->smb_fid,		/* (w) */
252c5f48fa5SGordon Ross 		    op->action_taken,		/* (l) */
253c5f48fa5SGordon Ross 		    0,		/* EaErrorOffset   (l) */
254c5f48fa5SGordon Ross 		    &ap->sa_crtime,		/* (T) */
255c5f48fa5SGordon Ross 		    &ap->sa_vattr.va_atime,	/* (T) */
256c5f48fa5SGordon Ross 		    &ap->sa_vattr.va_mtime,	/* (T) */
257c5f48fa5SGordon Ross 		    &ap->sa_vattr.va_ctime,	/* (T) */
258c5f48fa5SGordon Ross 		    op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
259c5f48fa5SGordon Ross 		    ap->sa_allocsz,		/* (q) */
260c5f48fa5SGordon Ross 		    ap->sa_vattr.va_size,	/* (q) */
261c5f48fa5SGordon Ross 		    op->ftype,			/* (w) */
262c5f48fa5SGordon Ross 		    op->devstate,		/* (w) */
263c5f48fa5SGordon Ross 		    DirFlag,			/* (b) */
264c5f48fa5SGordon Ross 		    /* volume guid		  (16.) */
265c5f48fa5SGordon Ross 		    op->fileid,			/* (q) */
266c5f48fa5SGordon Ross 		    MaxAccess,			/* (l) */
267c5f48fa5SGordon Ross 		    0);		/* guest access	   (l) */
268c5f48fa5SGordon Ross 	} else {
269c5f48fa5SGordon Ross 		rc = smb_mbc_encodef(
270c5f48fa5SGordon Ross 		    &xa->rep_param_mb, "bbwllTTTTlqqwwb",
271c5f48fa5SGordon Ross 		    op->op_oplock_level,	/* (b) */
272c5f48fa5SGordon Ross 		    0,		/* ResponseType	   (b) */
273c5f48fa5SGordon Ross 		    sr->smb_fid,		/* (w) */
274c5f48fa5SGordon Ross 		    op->action_taken,		/* (l) */
275c5f48fa5SGordon Ross 		    0,		/* EaErrorOffset   (l) */
276c5f48fa5SGordon Ross 		    &ap->sa_crtime,		/* (T) */
277c5f48fa5SGordon Ross 		    &ap->sa_vattr.va_atime,	/* (T) */
278c5f48fa5SGordon Ross 		    &ap->sa_vattr.va_mtime,	/* (T) */
279c5f48fa5SGordon Ross 		    &ap->sa_vattr.va_ctime,	/* (T) */
280c5f48fa5SGordon Ross 		    op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
281c5f48fa5SGordon Ross 		    ap->sa_allocsz,		/* (q) */
282c5f48fa5SGordon Ross 		    ap->sa_vattr.va_size,	/* (q) */
283c5f48fa5SGordon Ross 		    op->ftype,			/* (w) */
284c5f48fa5SGordon Ross 		    op->devstate,		/* (w) */
285c5f48fa5SGordon Ross 		    DirFlag);			/* (b) */
286c5f48fa5SGordon Ross 	}
287c5f48fa5SGordon Ross 
288c5f48fa5SGordon Ross 	if (rc == 0)
289c5f48fa5SGordon Ross 		return (SDRC_SUCCESS);
290da6c28aaSamw 
2915fd03bc0SGordon Ross errout:
2925fd03bc0SGordon Ross 	smb_ofile_close(of, 0);
2935fd03bc0SGordon Ross 	return (SDRC_ERROR);
294da6c28aaSamw }
295