1*adee6784SGordon Ross /*
2*adee6784SGordon Ross  * Copyright (c) 2000-2001 Boris Popov
3*adee6784SGordon Ross  * All rights reserved.
4*adee6784SGordon Ross  *
5*adee6784SGordon Ross  * Redistribution and use in source and binary forms, with or without
6*adee6784SGordon Ross  * modification, are permitted provided that the following conditions
7*adee6784SGordon Ross  * are met:
8*adee6784SGordon Ross  * 1. Redistributions of source code must retain the above copyright
9*adee6784SGordon Ross  *    notice, this list of conditions and the following disclaimer.
10*adee6784SGordon Ross  * 2. Redistributions in binary form must reproduce the above copyright
11*adee6784SGordon Ross  *    notice, this list of conditions and the following disclaimer in the
12*adee6784SGordon Ross  *    documentation and/or other materials provided with the distribution.
13*adee6784SGordon Ross  * 3. All advertising materials mentioning features or use of this software
14*adee6784SGordon Ross  *    must display the following acknowledgement:
15*adee6784SGordon Ross  *    This product includes software developed by Boris Popov.
16*adee6784SGordon Ross  * 4. Neither the name of the author nor the names of any co-contributors
17*adee6784SGordon Ross  *    may be used to endorse or promote products derived from this software
18*adee6784SGordon Ross  *    without specific prior written permission.
19*adee6784SGordon Ross  *
20*adee6784SGordon Ross  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21*adee6784SGordon Ross  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*adee6784SGordon Ross  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*adee6784SGordon Ross  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24*adee6784SGordon Ross  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25*adee6784SGordon Ross  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26*adee6784SGordon Ross  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*adee6784SGordon Ross  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28*adee6784SGordon Ross  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29*adee6784SGordon Ross  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30*adee6784SGordon Ross  * SUCH DAMAGE.
31*adee6784SGordon Ross  */
32*adee6784SGordon Ross 
33*adee6784SGordon Ross /*
34*adee6784SGordon Ross  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
35*adee6784SGordon Ross  * Use is subject to license terms.
36*adee6784SGordon Ross  *
37*adee6784SGordon Ross  * Copyright (c) 2011 - 2013 Apple Inc. All rights reserved.
38*adee6784SGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
39*adee6784SGordon Ross  */
40*adee6784SGordon Ross 
41*adee6784SGordon Ross #include <sys/param.h>
42*adee6784SGordon Ross #include <sys/systm.h>
43*adee6784SGordon Ross #include <sys/inttypes.h>
44*adee6784SGordon Ross #include <sys/time.h>
45*adee6784SGordon Ross #include <sys/vnode.h>
46*adee6784SGordon Ross #include <sys/sunddi.h>
47*adee6784SGordon Ross #include <sys/cmn_err.h>
48*adee6784SGordon Ross 
49*adee6784SGordon Ross #include <netsmb/smb_osdep.h>
50*adee6784SGordon Ross 
51*adee6784SGordon Ross #include <netsmb/smb.h>
52*adee6784SGordon Ross #include <netsmb/smb2.h>
53*adee6784SGordon Ross #include <netsmb/smb_conn.h>
54*adee6784SGordon Ross #include <netsmb/smb_subr.h>
55*adee6784SGordon Ross #include <netsmb/smb_rq.h>
56*adee6784SGordon Ross #include <netsmb/smb2_rq.h>
57*adee6784SGordon Ross 
58*adee6784SGordon Ross #include <smbfs/smbfs.h>
59*adee6784SGordon Ross #include <smbfs/smbfs_node.h>
60*adee6784SGordon Ross #include <smbfs/smbfs_subr.h>
61*adee6784SGordon Ross 
62*adee6784SGordon Ross 
63*adee6784SGordon Ross /*
64*adee6784SGordon Ross  * Todo: locking over-the-wire
65*adee6784SGordon Ross  */
66*adee6784SGordon Ross #if 0	// todo
67*adee6784SGordon Ross 
68*adee6784SGordon Ross int
69*adee6784SGordon Ross smbfs_smb2_locking(struct smbnode *np, int op, uint32_t pid,
70*adee6784SGordon Ross 	offset_t start, uint64_t len, int largelock,
71*adee6784SGordon Ross 	struct smb_cred *scrp, uint32_t timeout)
72*adee6784SGordon Ross {
73*adee6784SGordon Ross 	return (ENOTSUP);
74*adee6784SGordon Ross }
75*adee6784SGordon Ross 
76*adee6784SGordon Ross #endif	// todo
77*adee6784SGordon Ross 
78*adee6784SGordon Ross /*
79*adee6784SGordon Ross  * Helper for smbfs_getattr_otw
80*adee6784SGordon Ross  * used when we don't have an open FID
81*adee6784SGordon Ross  *
82*adee6784SGordon Ross  * For SMB2 we need to do an attribute-only open.  The
83*adee6784SGordon Ross  * data returned by open gets us everything we need, so
84*adee6784SGordon Ross  * just close the handle and we're done.
85*adee6784SGordon Ross  */
86*adee6784SGordon Ross int
smbfs_smb2_getpattr(struct smbnode * np,struct smbfattr * fap,struct smb_cred * scrp)87*adee6784SGordon Ross smbfs_smb2_getpattr(
88*adee6784SGordon Ross 	struct smbnode *np,
89*adee6784SGordon Ross 	struct smbfattr *fap,
90*adee6784SGordon Ross 	struct smb_cred *scrp)
91*adee6784SGordon Ross {
92*adee6784SGordon Ross 	smb_fh_t tmp_fh;
93*adee6784SGordon Ross 	struct smb_share *ssp = np->n_mount->smi_share;
94*adee6784SGordon Ross 	uint32_t rights = (STD_RIGHT_READ_CONTROL_ACCESS |
95*adee6784SGordon Ross 	    SA_RIGHT_FILE_READ_ATTRIBUTES);
96*adee6784SGordon Ross 	int error;
97*adee6784SGordon Ross 
98*adee6784SGordon Ross 	bzero(&tmp_fh, sizeof (tmp_fh));
99*adee6784SGordon Ross 	error = smbfs_smb_ntcreatex(np,
100*adee6784SGordon Ross 	    NULL, 0, 0,	/* name nmlen xattr */
101*adee6784SGordon Ross 	    rights, SMB_EFA_NORMAL,
102*adee6784SGordon Ross 	    NTCREATEX_SHARE_ACCESS_ALL,
103*adee6784SGordon Ross 	    NTCREATEX_DISP_OPEN,
104*adee6784SGordon Ross 	    0, /* create options */
105*adee6784SGordon Ross 	    scrp, &tmp_fh,
106*adee6784SGordon Ross 	    NULL, fap);
107*adee6784SGordon Ross 	if (error == 0) {
108*adee6784SGordon Ross 		(void) smb_smb_close(ssp, &tmp_fh, scrp);
109*adee6784SGordon Ross 	}
110*adee6784SGordon Ross 
111*adee6784SGordon Ross 	return (error);
112*adee6784SGordon Ross }
113*adee6784SGordon Ross 
114*adee6784SGordon Ross /*
115*adee6784SGordon Ross  * Common SMB2 query file info
116*adee6784SGordon Ross  */
117*adee6784SGordon Ross static int
smbfs_smb2_query_info(struct smb_share * ssp,smb2fid_t * fid,struct mdchain * info_mdp,uint32_t * iolen,uint8_t type,uint8_t level,uint32_t addl_info,struct smb_cred * scrp)118*adee6784SGordon Ross smbfs_smb2_query_info(struct smb_share *ssp, smb2fid_t *fid,
119*adee6784SGordon Ross 	struct mdchain *info_mdp, uint32_t *iolen,
120*adee6784SGordon Ross 	uint8_t type, uint8_t level, uint32_t addl_info,
121*adee6784SGordon Ross 	struct smb_cred *scrp)
122*adee6784SGordon Ross {
123*adee6784SGordon Ross 	struct smb_rq *rqp = NULL;
124*adee6784SGordon Ross 	struct mbchain *mbp;
125*adee6784SGordon Ross 	struct mdchain *mdp;
126*adee6784SGordon Ross 	uint32_t dlen = 0;
127*adee6784SGordon Ross 	uint16_t doff = 0;
128*adee6784SGordon Ross 	uint16_t ssize = 0;
129*adee6784SGordon Ross 	int error;
130*adee6784SGordon Ross 
131*adee6784SGordon Ross 	error = smb_rq_alloc(SSTOCP(ssp), SMB2_QUERY_INFO, scrp, &rqp);
132*adee6784SGordon Ross 	if (error)
133*adee6784SGordon Ross 		goto out;
134*adee6784SGordon Ross 
135*adee6784SGordon Ross 	/*
136*adee6784SGordon Ross 	 * Build the SMB 2 Query Info req.
137*adee6784SGordon Ross 	 */
138*adee6784SGordon Ross 	smb_rq_getrequest(rqp, &mbp);
139*adee6784SGordon Ross 	mb_put_uint16le(mbp, 41);		// struct size
140*adee6784SGordon Ross 	mb_put_uint8(mbp, type);
141*adee6784SGordon Ross 	mb_put_uint8(mbp, level);
142*adee6784SGordon Ross 	mb_put_uint32le(mbp, *iolen);		// out buf len
143*adee6784SGordon Ross 	mb_put_uint16le(mbp, 0);		// in buf off
144*adee6784SGordon Ross 	mb_put_uint16le(mbp, 0);		// reserved
145*adee6784SGordon Ross 	mb_put_uint32le(mbp, 0);		// in buf len
146*adee6784SGordon Ross 	mb_put_uint32le(mbp, addl_info);
147*adee6784SGordon Ross 	mb_put_uint32le(mbp, 0);		// flags
148*adee6784SGordon Ross 	mb_put_uint64le(mbp, fid->fid_persistent);
149*adee6784SGordon Ross 	mb_put_uint64le(mbp, fid->fid_volatile);
150*adee6784SGordon Ross 
151*adee6784SGordon Ross 	error = smb2_rq_simple(rqp);
152*adee6784SGordon Ross 	if (error) {
153*adee6784SGordon Ross 		if (rqp->sr_error == NT_STATUS_INVALID_PARAMETER)
154*adee6784SGordon Ross 			error = ENOTSUP;
155*adee6784SGordon Ross 		goto out;
156*adee6784SGordon Ross 	}
157*adee6784SGordon Ross 
158*adee6784SGordon Ross 	/*
159*adee6784SGordon Ross 	 * Parse SMB 2 Query Info response
160*adee6784SGordon Ross 	 */
161*adee6784SGordon Ross 	smb_rq_getreply(rqp, &mdp);
162*adee6784SGordon Ross 
163*adee6784SGordon Ross 	/* Check structure size is 9 */
164*adee6784SGordon Ross 	md_get_uint16le(mdp, &ssize);
165*adee6784SGordon Ross 	if (ssize != 9) {
166*adee6784SGordon Ross 		error = EBADRPC;
167*adee6784SGordon Ross 		goto out;
168*adee6784SGordon Ross 	}
169*adee6784SGordon Ross 
170*adee6784SGordon Ross 	/* Get data off, len */
171*adee6784SGordon Ross 	md_get_uint16le(mdp, &doff);
172*adee6784SGordon Ross 	md_get_uint32le(mdp, &dlen);
173*adee6784SGordon Ross 	*iolen = dlen;
174*adee6784SGordon Ross 
175*adee6784SGordon Ross 	/*
176*adee6784SGordon Ross 	 * Skip ahead to the payload, as needed.
177*adee6784SGordon Ross 	 * Current offset is SMB2_HDRLEN + 8.
178*adee6784SGordon Ross 	 */
179*adee6784SGordon Ross 	if (dlen != 0) {
180*adee6784SGordon Ross 		mblk_t *m = NULL;
181*adee6784SGordon Ross 		int skip = (int)doff - (SMB2_HDRLEN + 8);
182*adee6784SGordon Ross 		if (skip < 0) {
183*adee6784SGordon Ross 			error = EBADRPC;
184*adee6784SGordon Ross 			goto out;
185*adee6784SGordon Ross 		}
186*adee6784SGordon Ross 		if (skip > 0) {
187*adee6784SGordon Ross 			md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
188*adee6784SGordon Ross 		}
189*adee6784SGordon Ross 		error = md_get_mbuf(mdp, dlen, &m);
190*adee6784SGordon Ross 		if (error)
191*adee6784SGordon Ross 			goto out;
192*adee6784SGordon Ross 		md_initm(info_mdp, m);
193*adee6784SGordon Ross 	}
194*adee6784SGordon Ross 
195*adee6784SGordon Ross out:
196*adee6784SGordon Ross 	smb_rq_done(rqp);
197*adee6784SGordon Ross 
198*adee6784SGordon Ross 	return (error);
199*adee6784SGordon Ross }
200*adee6784SGordon Ross 
201*adee6784SGordon Ross 
202*adee6784SGordon Ross /*
203*adee6784SGordon Ross  * Get FileAllInformation for an open file
204*adee6784SGordon Ross  * and parse into *fap
205*adee6784SGordon Ross  */
206*adee6784SGordon Ross int
smbfs_smb2_qfileinfo(struct smb_share * ssp,smb2fid_t * fid,struct smbfattr * fap,struct smb_cred * scrp)207*adee6784SGordon Ross smbfs_smb2_qfileinfo(struct smb_share *ssp, smb2fid_t *fid,
208*adee6784SGordon Ross 	struct smbfattr *fap, struct smb_cred *scrp)
209*adee6784SGordon Ross {
210*adee6784SGordon Ross 	struct mdchain info_mdc, *mdp = &info_mdc;
211*adee6784SGordon Ross 	uint32_t iolen = 1024;
212*adee6784SGordon Ross 	int error;
213*adee6784SGordon Ross 
214*adee6784SGordon Ross 	bzero(mdp, sizeof (*mdp));
215*adee6784SGordon Ross 
216*adee6784SGordon Ross 	error = smbfs_smb2_query_info(ssp, fid, mdp, &iolen,
217*adee6784SGordon Ross 	    SMB2_0_INFO_FILE, FileAllInformation, 0, scrp);
218*adee6784SGordon Ross 	if (error)
219*adee6784SGordon Ross 		goto out;
220*adee6784SGordon Ross 
221*adee6784SGordon Ross 	error = smbfs_decode_file_all_info(ssp, mdp, fap);
222*adee6784SGordon Ross 
223*adee6784SGordon Ross out:
224*adee6784SGordon Ross 	md_done(mdp);
225*adee6784SGordon Ross 
226*adee6784SGordon Ross 	return (error);
227*adee6784SGordon Ross }
228*adee6784SGordon Ross 
229*adee6784SGordon Ross /*
230*adee6784SGordon Ross  * Get some SMB2_0_INFO_FILESYSTEM info
231*adee6784SGordon Ross  *
232*adee6784SGordon Ross  * Note: This can be called during mount.  We don't have any
233*adee6784SGordon Ross  * smbfs_node_t or pathname, so do our own attr. open on
234*adee6784SGordon Ross  * the root of the share to get a handle for this request.
235*adee6784SGordon Ross  */
236*adee6784SGordon Ross static int
smbfs_smb2_query_fs_info(struct smb_share * ssp,struct mdchain * mdp,uint8_t level,struct smb_cred * scrp)237*adee6784SGordon Ross smbfs_smb2_query_fs_info(struct smb_share *ssp, struct mdchain *mdp,
238*adee6784SGordon Ross 	uint8_t level, struct smb_cred *scrp)
239*adee6784SGordon Ross {
240*adee6784SGordon Ross 	smb2fid_t fid;
241*adee6784SGordon Ross 	uint32_t iolen = 1024;
242*adee6784SGordon Ross 	boolean_t opened = B_FALSE;
243*adee6784SGordon Ross 	int error;
244*adee6784SGordon Ross 
245*adee6784SGordon Ross 	/*
246*adee6784SGordon Ross 	 * Need a FID for smb2, and this is called during mount
247*adee6784SGordon Ross 	 * so "go behind" the usual open/close functions.
248*adee6784SGordon Ross 	 */
249*adee6784SGordon Ross 	error = smb2_smb_ntcreate(
250*adee6784SGordon Ross 	    ssp, NULL,	// name
251*adee6784SGordon Ross 	    NULL, NULL, // create ctx in, out
252*adee6784SGordon Ross 	    0,	/* NTCREATEX_FLAGS... */
253*adee6784SGordon Ross 	    SA_RIGHT_FILE_READ_ATTRIBUTES,
254*adee6784SGordon Ross 	    SMB_EFA_NORMAL,
255*adee6784SGordon Ross 	    NTCREATEX_SHARE_ACCESS_ALL,
256*adee6784SGordon Ross 	    NTCREATEX_DISP_OPEN,
257*adee6784SGordon Ross 	    0, /* create options */
258*adee6784SGordon Ross 	    NTCREATEX_IMPERSONATION_IMPERSONATION,
259*adee6784SGordon Ross 	    scrp, &fid, NULL, NULL);
260*adee6784SGordon Ross 	if (error != 0)
261*adee6784SGordon Ross 		goto out;
262*adee6784SGordon Ross 	opened = B_TRUE;
263*adee6784SGordon Ross 
264*adee6784SGordon Ross 	error = smbfs_smb2_query_info(ssp, &fid, mdp, &iolen,
265*adee6784SGordon Ross 	    SMB2_0_INFO_FILESYSTEM, level, 0, scrp);
266*adee6784SGordon Ross 
267*adee6784SGordon Ross out:
268*adee6784SGordon Ross 	if (opened)
269*adee6784SGordon Ross 		(void) smb2_smb_close(ssp, &fid, scrp);
270*adee6784SGordon Ross 
271*adee6784SGordon Ross 	return (error);
272*adee6784SGordon Ross }
273*adee6784SGordon Ross 
274*adee6784SGordon Ross /*
275*adee6784SGordon Ross  * Get FileFsAttributeInformation and
276*adee6784SGordon Ross  * parse into *info
277*adee6784SGordon Ross  */
278*adee6784SGordon Ross int
smbfs_smb2_qfsattr(struct smb_share * ssp,struct smb_fs_attr_info * info,struct smb_cred * scrp)279*adee6784SGordon Ross smbfs_smb2_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *info,
280*adee6784SGordon Ross 	struct smb_cred *scrp)
281*adee6784SGordon Ross {
282*adee6784SGordon Ross 	struct mdchain info_mdc, *mdp = &info_mdc;
283*adee6784SGordon Ross 	int error;
284*adee6784SGordon Ross 
285*adee6784SGordon Ross 	bzero(mdp, sizeof (*mdp));
286*adee6784SGordon Ross 
287*adee6784SGordon Ross 	error = smbfs_smb2_query_fs_info(ssp, mdp,
288*adee6784SGordon Ross 	    FileFsAttributeInformation, scrp);
289*adee6784SGordon Ross 	if (error)
290*adee6784SGordon Ross 		goto out;
291*adee6784SGordon Ross 	error = smbfs_decode_fs_attr_info(ssp, mdp, info);
292*adee6784SGordon Ross 
293*adee6784SGordon Ross out:
294*adee6784SGordon Ross 	md_done(mdp);
295*adee6784SGordon Ross 
296*adee6784SGordon Ross 	return (error);
297*adee6784SGordon Ross }
298*adee6784SGordon Ross 
299*adee6784SGordon Ross /*
300*adee6784SGordon Ross  * Get FileFsFullSizeInformation and
301*adee6784SGordon Ross  * parse into *info
302*adee6784SGordon Ross  */
303*adee6784SGordon Ross int
smbfs_smb2_statfs(struct smb_share * ssp,struct smb_fs_size_info * info,struct smb_cred * scrp)304*adee6784SGordon Ross smbfs_smb2_statfs(struct smb_share *ssp,
305*adee6784SGordon Ross 	struct smb_fs_size_info *info,
306*adee6784SGordon Ross 	struct smb_cred *scrp)
307*adee6784SGordon Ross {
308*adee6784SGordon Ross 	struct mdchain info_mdc, *mdp = &info_mdc;
309*adee6784SGordon Ross 	int error;
310*adee6784SGordon Ross 
311*adee6784SGordon Ross 	bzero(mdp, sizeof (*mdp));
312*adee6784SGordon Ross 
313*adee6784SGordon Ross 	error = smbfs_smb2_query_fs_info(ssp, mdp,
314*adee6784SGordon Ross 	    FileFsFullSizeInformation, scrp);
315*adee6784SGordon Ross 	if (error)
316*adee6784SGordon Ross 		goto out;
317*adee6784SGordon Ross 
318*adee6784SGordon Ross 	md_get_uint64le(mdp, &info->total_units);
319*adee6784SGordon Ross 	md_get_uint64le(mdp, &info->caller_avail);
320*adee6784SGordon Ross 	md_get_uint64le(mdp, &info->actual_avail);
321*adee6784SGordon Ross 
322*adee6784SGordon Ross 	md_get_uint32le(mdp, &info->sect_per_unit);
323*adee6784SGordon Ross 	error = md_get_uint32le(mdp, &info->bytes_per_sect);
324*adee6784SGordon Ross 
325*adee6784SGordon Ross out:
326*adee6784SGordon Ross 	md_done(mdp);
327*adee6784SGordon Ross 
328*adee6784SGordon Ross 	return (error);
329*adee6784SGordon Ross }
330*adee6784SGordon Ross 
331*adee6784SGordon Ross int
smbfs_smb2_flush(struct smb_share * ssp,smb2fid_t * fid,struct smb_cred * scrp)332*adee6784SGordon Ross smbfs_smb2_flush(struct smb_share *ssp, smb2fid_t *fid,
333*adee6784SGordon Ross 	struct smb_cred *scrp)
334*adee6784SGordon Ross {
335*adee6784SGordon Ross 	struct smb_rq *rqp;
336*adee6784SGordon Ross 	struct mbchain *mbp;
337*adee6784SGordon Ross 	int error;
338*adee6784SGordon Ross 
339*adee6784SGordon Ross 	error = smb_rq_alloc(SSTOCP(ssp), SMB2_FLUSH, scrp, &rqp);
340*adee6784SGordon Ross 	if (error)
341*adee6784SGordon Ross 		return (error);
342*adee6784SGordon Ross 
343*adee6784SGordon Ross 	/*
344*adee6784SGordon Ross 	 * Build the SMB 2 Flush Request
345*adee6784SGordon Ross 	 */
346*adee6784SGordon Ross 	smb_rq_getrequest(rqp, &mbp);
347*adee6784SGordon Ross 	mb_put_uint16le(mbp, 24);	/* struct size */
348*adee6784SGordon Ross 	mb_put_uint16le(mbp, 0);	/* reserved */
349*adee6784SGordon Ross 	mb_put_uint32le(mbp, 0);	/* reserved */
350*adee6784SGordon Ross 
351*adee6784SGordon Ross 	mb_put_uint64le(mbp, fid->fid_persistent);
352*adee6784SGordon Ross 	mb_put_uint64le(mbp, fid->fid_volatile);
353*adee6784SGordon Ross 
354*adee6784SGordon Ross 	rqp->sr_flags |= SMBR_NORECONNECT;
355*adee6784SGordon Ross 	error = smb2_rq_simple(rqp);
356*adee6784SGordon Ross 	smb_rq_done(rqp);
357*adee6784SGordon Ross 
358*adee6784SGordon Ross 	return (error);
359*adee6784SGordon Ross }
360*adee6784SGordon Ross 
361*adee6784SGordon Ross /*
362*adee6784SGordon Ross  * Set file info via an open handle.
363*adee6784SGordon Ross  * Caller provides payload, info level.
364*adee6784SGordon Ross  */
365*adee6784SGordon Ross static int
smbfs_smb2_set_info(struct smb_share * ssp,smb2fid_t * fid,struct mbchain * info_mbp,uint8_t type,uint8_t level,uint32_t addl_info,struct smb_cred * scrp)366*adee6784SGordon Ross smbfs_smb2_set_info(struct smb_share *ssp, smb2fid_t *fid,
367*adee6784SGordon Ross 	struct mbchain *info_mbp, uint8_t type, uint8_t level,
368*adee6784SGordon Ross 	uint32_t addl_info, struct smb_cred *scrp)
369*adee6784SGordon Ross {
370*adee6784SGordon Ross 	struct smb_rq *rqp = NULL;
371*adee6784SGordon Ross 	struct mbchain *mbp;
372*adee6784SGordon Ross 	uint32_t *buffer_lenp;
373*adee6784SGordon Ross 	int base, len;
374*adee6784SGordon Ross 	int error;
375*adee6784SGordon Ross 
376*adee6784SGordon Ross 	error = smb_rq_alloc(SSTOCP(ssp), SMB2_SET_INFO, scrp, &rqp);
377*adee6784SGordon Ross 	if (error)
378*adee6784SGordon Ross 		goto out;
379*adee6784SGordon Ross 
380*adee6784SGordon Ross 	/*
381*adee6784SGordon Ross 	 * Build the SMB 2 Set Info req.
382*adee6784SGordon Ross 	 */
383*adee6784SGordon Ross 	smb_rq_getrequest(rqp, &mbp);
384*adee6784SGordon Ross 	mb_put_uint16le(mbp, 33);		// struct size
385*adee6784SGordon Ross 	mb_put_uint8(mbp, type);
386*adee6784SGordon Ross 	mb_put_uint8(mbp, level);
387*adee6784SGordon Ross 	buffer_lenp = mb_reserve(mbp, sizeof (uint32_t));
388*adee6784SGordon Ross 	mb_put_uint16le(mbp, SMB2_HDRLEN + 32);	// Buffer Offset
389*adee6784SGordon Ross 	mb_put_uint16le(mbp, 0);		// Reserved
390*adee6784SGordon Ross 	mb_put_uint32le(mbp, addl_info);	// Additional Info
391*adee6784SGordon Ross 
392*adee6784SGordon Ross 	mb_put_uint64le(mbp, fid->fid_persistent);
393*adee6784SGordon Ross 	mb_put_uint64le(mbp, fid->fid_volatile);
394*adee6784SGordon Ross 
395*adee6784SGordon Ross 	/*
396*adee6784SGordon Ross 	 * Now the payload
397*adee6784SGordon Ross 	 */
398*adee6784SGordon Ross 	base = mbp->mb_count;
399*adee6784SGordon Ross 	error = mb_put_mbchain(mbp, info_mbp);
400*adee6784SGordon Ross 	if (error)
401*adee6784SGordon Ross 		goto out;
402*adee6784SGordon Ross 	len = mbp->mb_count - base;
403*adee6784SGordon Ross 	*buffer_lenp = htolel(len);
404*adee6784SGordon Ross 	if (error)
405*adee6784SGordon Ross 		goto out;
406*adee6784SGordon Ross 
407*adee6784SGordon Ross 	/*
408*adee6784SGordon Ross 	 * Run the request.
409*adee6784SGordon Ross 	 * Don't care about the (empty) reply.
410*adee6784SGordon Ross 	 */
411*adee6784SGordon Ross 	error = smb2_rq_simple(rqp);
412*adee6784SGordon Ross 
413*adee6784SGordon Ross out:
414*adee6784SGordon Ross 	smb_rq_done(rqp);
415*adee6784SGordon Ross 
416*adee6784SGordon Ross 	return (error);
417*adee6784SGordon Ross }
418*adee6784SGordon Ross 
419*adee6784SGordon Ross int
smbfs_smb2_seteof(struct smb_share * ssp,smb2fid_t * fid,uint64_t newsize,struct smb_cred * scrp)420*adee6784SGordon Ross smbfs_smb2_seteof(struct smb_share *ssp, smb2fid_t *fid,
421*adee6784SGordon Ross 	uint64_t newsize, struct smb_cred *scrp)
422*adee6784SGordon Ross {
423*adee6784SGordon Ross 	struct mbchain data_mb, *mbp = &data_mb;
424*adee6784SGordon Ross 	uint8_t level = FileEndOfFileInformation;
425*adee6784SGordon Ross 	int error;
426*adee6784SGordon Ross 
427*adee6784SGordon Ross 	mb_init(mbp);
428*adee6784SGordon Ross 	mb_put_uint64le(mbp, newsize);
429*adee6784SGordon Ross 	error = smbfs_smb2_set_info(ssp, fid, mbp,
430*adee6784SGordon Ross 	    SMB2_0_INFO_FILE, level, 0, scrp);
431*adee6784SGordon Ross 	mb_done(mbp);
432*adee6784SGordon Ross 
433*adee6784SGordon Ross 	return (error);
434*adee6784SGordon Ross }
435*adee6784SGordon Ross 
436*adee6784SGordon Ross int
smbfs_smb2_setdisp(struct smb_share * ssp,smb2fid_t * fid,uint8_t newdisp,struct smb_cred * scrp)437*adee6784SGordon Ross smbfs_smb2_setdisp(struct smb_share *ssp, smb2fid_t *fid,
438*adee6784SGordon Ross 	uint8_t newdisp, struct smb_cred *scrp)
439*adee6784SGordon Ross {
440*adee6784SGordon Ross 	struct mbchain data_mb, *mbp = &data_mb;
441*adee6784SGordon Ross 	uint8_t level = FileDispositionInformation;
442*adee6784SGordon Ross 	int error;
443*adee6784SGordon Ross 
444*adee6784SGordon Ross 	mb_init(mbp);
445*adee6784SGordon Ross 	mb_put_uint8(mbp, newdisp);
446*adee6784SGordon Ross 	error = smbfs_smb2_set_info(ssp, fid, mbp,
447*adee6784SGordon Ross 	    SMB2_0_INFO_FILE,  level, 0, scrp);
448*adee6784SGordon Ross 	mb_done(mbp);
449*adee6784SGordon Ross 
450*adee6784SGordon Ross 	return (error);
451*adee6784SGordon Ross }
452*adee6784SGordon Ross 
453*adee6784SGordon Ross /*
454*adee6784SGordon Ross  * Set FileBasicInformation on an open handle
455*adee6784SGordon Ross  * Caller builds the mbchain.
456*adee6784SGordon Ross  */
457*adee6784SGordon Ross int
smbfs_smb2_setfattr(struct smb_share * ssp,smb2fid_t * fid,struct mbchain * mbp,struct smb_cred * scrp)458*adee6784SGordon Ross smbfs_smb2_setfattr(struct smb_share *ssp, smb2fid_t *fid,
459*adee6784SGordon Ross 	struct mbchain *mbp, struct smb_cred *scrp)
460*adee6784SGordon Ross {
461*adee6784SGordon Ross 	uint8_t level = FileBasicInformation;
462*adee6784SGordon Ross 	int error;
463*adee6784SGordon Ross 
464*adee6784SGordon Ross 	error = smbfs_smb2_set_info(ssp, fid, mbp,
465*adee6784SGordon Ross 	    SMB2_0_INFO_FILE,  level, 0, scrp);
466*adee6784SGordon Ross 	return (error);
467*adee6784SGordon Ross }
468*adee6784SGordon Ross 
469*adee6784SGordon Ross /*
470*adee6784SGordon Ross  * Build a FileRenameInformation and call setinfo
471*adee6784SGordon Ross  */
472*adee6784SGordon Ross int
smbfs_smb2_rename(struct smbnode * np,struct smbnode * tdnp,const char * tname,int tnlen,int overwrite,smb2fid_t * fid,struct smb_cred * scrp)473*adee6784SGordon Ross smbfs_smb2_rename(struct smbnode *np, struct smbnode *tdnp,
474*adee6784SGordon Ross 	const char *tname, int tnlen, int overwrite,
475*adee6784SGordon Ross 	smb2fid_t *fid, struct smb_cred *scrp)
476*adee6784SGordon Ross {
477*adee6784SGordon Ross 	struct smb_share *ssp = np->n_mount->smi_share;
478*adee6784SGordon Ross 	struct mbchain data_mb, *mbp = &data_mb;
479*adee6784SGordon Ross 	uint32_t *name_lenp;
480*adee6784SGordon Ross 	uint8_t level = FileRenameInformation;
481*adee6784SGordon Ross 	int base, len;
482*adee6784SGordon Ross 	int error;
483*adee6784SGordon Ross 
484*adee6784SGordon Ross 	mb_init(mbp);
485*adee6784SGordon Ross 
486*adee6784SGordon Ross 	mb_put_uint32le(mbp, (overwrite & 1));
487*adee6784SGordon Ross 	mb_put_uint32le(mbp, 0);		// reserved
488*adee6784SGordon Ross 	mb_put_uint64le(mbp, 0);		// Root Dir
489*adee6784SGordon Ross 	name_lenp = mb_reserve(mbp, 4);
490*adee6784SGordon Ross 
491*adee6784SGordon Ross 	/* Target name (full path) */
492*adee6784SGordon Ross 	base = mbp->mb_count;
493*adee6784SGordon Ross 	if (tnlen > 0) {
494*adee6784SGordon Ross 		error = smbfs_fullpath(mbp, SSTOVC(ssp),
495*adee6784SGordon Ross 		    tdnp, tname, tnlen, '\\');
496*adee6784SGordon Ross 		if (error)
497*adee6784SGordon Ross 			goto out;
498*adee6784SGordon Ross 	}
499*adee6784SGordon Ross 	len = mbp->mb_count - base;
500*adee6784SGordon Ross 	*name_lenp = htolel(len);
501*adee6784SGordon Ross 
502*adee6784SGordon Ross 	error = smbfs_smb2_set_info(ssp, fid, mbp,
503*adee6784SGordon Ross 	    SMB2_0_INFO_FILE,  level, 0, scrp);
504*adee6784SGordon Ross 
505*adee6784SGordon Ross out:
506*adee6784SGordon Ross 	mb_done(mbp);
507*adee6784SGordon Ross 
508*adee6784SGordon Ross 	return (error);
509*adee6784SGordon Ross }
510*adee6784SGordon Ross 
511*adee6784SGordon Ross /*
512*adee6784SGordon Ross  * Later servers have maxtransact at a megabyte or more,
513*adee6784SGordon Ross  * but we don't want to buffer up that much data, so use
514*adee6784SGordon Ross  * the lesser of that or 64k.
515*adee6784SGordon Ross  */
516*adee6784SGordon Ross #define	SMBFS_QDIR_MAX_BUF	(1<<16)
517*adee6784SGordon Ross 
518*adee6784SGordon Ross /*
519*adee6784SGordon Ross  * SMB2 query directory
520*adee6784SGordon Ross  */
521*adee6784SGordon Ross static int
smbfs_smb2_qdir(struct smbfs_fctx * ctx)522*adee6784SGordon Ross smbfs_smb2_qdir(struct smbfs_fctx *ctx)
523*adee6784SGordon Ross {
524*adee6784SGordon Ross 	smb_fh_t *fhp = ctx->f_fhp;
525*adee6784SGordon Ross 	smb_share_t *ssp = ctx->f_ssp;
526*adee6784SGordon Ross 	smb_vc_t *vcp = SSTOVC(ssp);
527*adee6784SGordon Ross 	struct smb_rq *rqp;
528*adee6784SGordon Ross 	struct mbchain *mbp;
529*adee6784SGordon Ross 	struct mdchain *mdp;
530*adee6784SGordon Ross 	uint16_t *name_lenp;
531*adee6784SGordon Ross 	uint8_t level, flags;
532*adee6784SGordon Ross 	uint16_t ssize = 0;
533*adee6784SGordon Ross 	uint16_t obuf_off = 0;
534*adee6784SGordon Ross 	uint32_t obuf_len = 0;
535*adee6784SGordon Ross 	uint32_t obuf_req;
536*adee6784SGordon Ross 	int error;
537*adee6784SGordon Ross 
538*adee6784SGordon Ross 	level = (uint8_t)ctx->f_infolevel;
539*adee6784SGordon Ross 	flags = 0;
540*adee6784SGordon Ross 	if (ctx->f_flags & SMBFS_RDD_FINDSINGLE)
541*adee6784SGordon Ross 		flags |= SMB2_QDIR_FLAG_SINGLE;
542*adee6784SGordon Ross 	if (ctx->f_flags & SMBFS_RDD_FINDFIRST)
543*adee6784SGordon Ross 		ctx->f_rkey = 0;
544*adee6784SGordon Ross 	else
545*adee6784SGordon Ross 		flags |= SMB2_QDIR_FLAG_INDEX;
546*adee6784SGordon Ross 
547*adee6784SGordon Ross 	obuf_req = SMBFS_QDIR_MAX_BUF;
548*adee6784SGordon Ross 	if (obuf_req > vcp->vc_sopt.sv2_maxtransact)
549*adee6784SGordon Ross 		obuf_req = vcp->vc_sopt.sv2_maxtransact;
550*adee6784SGordon Ross 
551*adee6784SGordon Ross 	if (ctx->f_rq) {
552*adee6784SGordon Ross 		smb_rq_done(ctx->f_rq);
553*adee6784SGordon Ross 		ctx->f_rq = NULL;
554*adee6784SGordon Ross 	}
555*adee6784SGordon Ross 	error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB2_QUERY_DIRECTORY,
556*adee6784SGordon Ross 	    ctx->f_scred, &rqp);
557*adee6784SGordon Ross 	if (error)
558*adee6784SGordon Ross 		return (error);
559*adee6784SGordon Ross 	ctx->f_rq = rqp;
560*adee6784SGordon Ross 
561*adee6784SGordon Ross 	/*
562*adee6784SGordon Ross 	 * Build an SMB2 Query Dir req.
563*adee6784SGordon Ross 	 */
564*adee6784SGordon Ross 	smb_rq_getrequest(rqp, &mbp);
565*adee6784SGordon Ross 
566*adee6784SGordon Ross 	mb_put_uint16le(mbp, 33);			/* Struct size */
567*adee6784SGordon Ross 	mb_put_uint8(mbp, level);
568*adee6784SGordon Ross 	mb_put_uint8(mbp, flags);
569*adee6784SGordon Ross 	mb_put_uint32le(mbp, ctx->f_rkey);		/* FileIndex */
570*adee6784SGordon Ross 
571*adee6784SGordon Ross 	mb_put_uint64le(mbp, fhp->fh_fid2.fid_persistent);
572*adee6784SGordon Ross 	mb_put_uint64le(mbp, fhp->fh_fid2.fid_volatile);
573*adee6784SGordon Ross 
574*adee6784SGordon Ross 	mb_put_uint16le(mbp, 96);
575*adee6784SGordon Ross 	name_lenp = mb_reserve(mbp, sizeof (uint16_t));	/* FileNameLen */
576*adee6784SGordon Ross 	mb_put_uint32le(mbp, obuf_req);			/* Output Buf Len */
577*adee6784SGordon Ross 
578*adee6784SGordon Ross 	/* Add in the name if any */
579*adee6784SGordon Ross 	if (ctx->f_wclen > 0) {
580*adee6784SGordon Ross 		int base, len;
581*adee6784SGordon Ross 
582*adee6784SGordon Ross 		/* Put the match pattern. */
583*adee6784SGordon Ross 		base = mbp->mb_count;
584*adee6784SGordon Ross 		error = smb_put_dmem(mbp, vcp,
585*adee6784SGordon Ross 		    ctx->f_wildcard, ctx->f_wclen,
586*adee6784SGordon Ross 		    SMB_CS_NONE, NULL);
587*adee6784SGordon Ross 		if (error)
588*adee6784SGordon Ross 			return (error);
589*adee6784SGordon Ross 
590*adee6784SGordon Ross 		/* Update the FileNameLen */
591*adee6784SGordon Ross 		len = mbp->mb_count - base;
592*adee6784SGordon Ross 		*name_lenp = htoles(len);
593*adee6784SGordon Ross 	} else {
594*adee6784SGordon Ross 		/* Empty string */
595*adee6784SGordon Ross 		mb_put_uint16le(mbp, 0);
596*adee6784SGordon Ross 		*name_lenp = 0;
597*adee6784SGordon Ross 	}
598*adee6784SGordon Ross 
599*adee6784SGordon Ross 	error = smb2_rq_simple(rqp);
600*adee6784SGordon Ross 	if (error != 0)
601*adee6784SGordon Ross 		goto out;
602*adee6784SGordon Ross 
603*adee6784SGordon Ross 	/*
604*adee6784SGordon Ross 	 * Parse the SMB2 Query Dir response
605*adee6784SGordon Ross 	 */
606*adee6784SGordon Ross 	smb_rq_getreply(rqp, &mdp);
607*adee6784SGordon Ross 
608*adee6784SGordon Ross 	/* Check structure size is 9 */
609*adee6784SGordon Ross 	md_get_uint16le(mdp, &ssize);
610*adee6784SGordon Ross 	if (ssize != 9) {
611*adee6784SGordon Ross 		error = EBADRPC;
612*adee6784SGordon Ross 		goto out;
613*adee6784SGordon Ross 	}
614*adee6784SGordon Ross 
615*adee6784SGordon Ross 	/* Get output buffer offset, length */
616*adee6784SGordon Ross 	md_get_uint16le(mdp, &obuf_off);
617*adee6784SGordon Ross 	md_get_uint32le(mdp, &obuf_len);
618*adee6784SGordon Ross 
619*adee6784SGordon Ross 	/*
620*adee6784SGordon Ross 	 * After read at EOF we'll have just one word:
621*adee6784SGordon Ross 	 * NextEntryOffset == 0  Allow some padding.
622*adee6784SGordon Ross 	 */
623*adee6784SGordon Ross 	if (obuf_len < 8) {
624*adee6784SGordon Ross 		error = ENOENT;
625*adee6784SGordon Ross 		goto out;
626*adee6784SGordon Ross 	}
627*adee6784SGordon Ross 
628*adee6784SGordon Ross 	/*
629*adee6784SGordon Ross 	 * If this reply is shorter than requested by 1k
630*adee6784SGordon Ross 	 * or more, we must have reached EOF.
631*adee6784SGordon Ross 	 */
632*adee6784SGordon Ross 	if ((obuf_len + 1024) < obuf_req)
633*adee6784SGordon Ross 		ctx->f_flags |= SMBFS_RDD_EOF;
634*adee6784SGordon Ross 
635*adee6784SGordon Ross 	/*
636*adee6784SGordon Ross 	 * Have data. Put the payload in ctx->f_mdchain
637*adee6784SGordon Ross 	 * Current offset is SMB2_HDRLEN + 8.
638*adee6784SGordon Ross 	 */
639*adee6784SGordon Ross 	{
640*adee6784SGordon Ross 		mblk_t *m = NULL;
641*adee6784SGordon Ross 		int skip = (int)obuf_off - (SMB2_HDRLEN + 8);
642*adee6784SGordon Ross 		if (skip < 0) {
643*adee6784SGordon Ross 			error = EBADRPC;
644*adee6784SGordon Ross 			goto out;
645*adee6784SGordon Ross 		}
646*adee6784SGordon Ross 		if (skip > 0) {
647*adee6784SGordon Ross 			md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
648*adee6784SGordon Ross 		}
649*adee6784SGordon Ross 		error = md_get_mbuf(mdp, obuf_len, &m);
650*adee6784SGordon Ross 		if (error)
651*adee6784SGordon Ross 			goto out;
652*adee6784SGordon Ross 		md_done(&ctx->f_mdchain);
653*adee6784SGordon Ross 		md_initm(&ctx->f_mdchain, m);
654*adee6784SGordon Ross 	}
655*adee6784SGordon Ross 
656*adee6784SGordon Ross 	/*
657*adee6784SGordon Ross 	 * SMB2 Query Directory does not provie an EntryCount.
658*adee6784SGordon Ross 	 * Instead, we'll advance f_eofs (entry offset)
659*adee6784SGordon Ross 	 * through the range [0..f_left]
660*adee6784SGordon Ross 	 */
661*adee6784SGordon Ross 	ctx->f_left = obuf_len;
662*adee6784SGordon Ross 	ctx->f_eofs = 0;
663*adee6784SGordon Ross 	return (0);
664*adee6784SGordon Ross 
665*adee6784SGordon Ross out:
666*adee6784SGordon Ross 	if (error != 0) {
667*adee6784SGordon Ross 		/*
668*adee6784SGordon Ross 		 * Failed parsing the FindFirst or FindNext response.
669*adee6784SGordon Ross 		 * Force this directory listing closed, otherwise the
670*adee6784SGordon Ross 		 * calling process may hang in an infinite loop.
671*adee6784SGordon Ross 		 */
672*adee6784SGordon Ross 		ctx->f_left = 0;
673*adee6784SGordon Ross 		ctx->f_eofs = 0;
674*adee6784SGordon Ross 		ctx->f_flags |= SMBFS_RDD_EOF;
675*adee6784SGordon Ross 	}
676*adee6784SGordon Ross 
677*adee6784SGordon Ross 	return (error);
678*adee6784SGordon Ross }
679*adee6784SGordon Ross 
680*adee6784SGordon Ross int
smbfs_smb2_findopen(struct smbfs_fctx * ctx,struct smbnode * dnp,const char * wildcard,int wclen,uint32_t attr)681*adee6784SGordon Ross smbfs_smb2_findopen(struct smbfs_fctx *ctx, struct smbnode *dnp,
682*adee6784SGordon Ross     const char *wildcard, int wclen, uint32_t attr)
683*adee6784SGordon Ross {
684*adee6784SGordon Ross 	smb_fh_t *fhp = NULL;
685*adee6784SGordon Ross 	uint32_t rights =
686*adee6784SGordon Ross 	    STD_RIGHT_READ_CONTROL_ACCESS |
687*adee6784SGordon Ross 	    SA_RIGHT_FILE_READ_ATTRIBUTES |
688*adee6784SGordon Ross 	    SA_RIGHT_FILE_READ_DATA;
689*adee6784SGordon Ross 	int error;
690*adee6784SGordon Ross 
691*adee6784SGordon Ross 	/*
692*adee6784SGordon Ross 	 * Set f_type no matter what, so cleanup will call
693*adee6784SGordon Ross 	 * smbfs_smb2_findclose, error or not.
694*adee6784SGordon Ross 	 */
695*adee6784SGordon Ross 	ctx->f_type = ft_SMB2;
696*adee6784SGordon Ross 	ASSERT(ctx->f_dnp == dnp);
697*adee6784SGordon Ross 
698*adee6784SGordon Ross 	/*
699*adee6784SGordon Ross 	 * Get a file handle on the directory
700*adee6784SGordon Ross 	 */
701*adee6784SGordon Ross 	error = smb_fh_create(ctx->f_ssp, &fhp);
702*adee6784SGordon Ross 	if (error != 0)
703*adee6784SGordon Ross 		goto errout;
704*adee6784SGordon Ross 
705*adee6784SGordon Ross 	error = smbfs_smb_ntcreatex(dnp,
706*adee6784SGordon Ross 	    NULL, 0, 0,	/* name nmlen xattr */
707*adee6784SGordon Ross 	    rights, SMB_EFA_NORMAL,
708*adee6784SGordon Ross 	    NTCREATEX_SHARE_ACCESS_ALL,
709*adee6784SGordon Ross 	    NTCREATEX_DISP_OPEN,
710*adee6784SGordon Ross 	    0, /* create options */
711*adee6784SGordon Ross 	    ctx->f_scred, fhp,
712*adee6784SGordon Ross 	    NULL, NULL); /* cr_act_p fa_p */
713*adee6784SGordon Ross 	if (error != 0)
714*adee6784SGordon Ross 		goto errout;
715*adee6784SGordon Ross 
716*adee6784SGordon Ross 	fhp->fh_rights = rights;
717*adee6784SGordon Ross 	smb_fh_opened(fhp);
718*adee6784SGordon Ross 	ctx->f_fhp = fhp;
719*adee6784SGordon Ross 
720*adee6784SGordon Ross 	ctx->f_namesz = SMB_MAXFNAMELEN + 1;
721*adee6784SGordon Ross 	ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP);
722*adee6784SGordon Ross 	ctx->f_infolevel = FileFullDirectoryInformation;
723*adee6784SGordon Ross 	ctx->f_attrmask = attr;
724*adee6784SGordon Ross 	ctx->f_wildcard = wildcard;
725*adee6784SGordon Ross 	ctx->f_wclen = wclen;
726*adee6784SGordon Ross 
727*adee6784SGordon Ross 	return (0);
728*adee6784SGordon Ross 
729*adee6784SGordon Ross errout:
730*adee6784SGordon Ross 	if (fhp != NULL)
731*adee6784SGordon Ross 		smb_fh_rele(fhp);
732*adee6784SGordon Ross 	return (error);
733*adee6784SGordon Ross }
734*adee6784SGordon Ross 
735*adee6784SGordon Ross int
smbfs_smb2_findclose(struct smbfs_fctx * ctx)736*adee6784SGordon Ross smbfs_smb2_findclose(struct smbfs_fctx *ctx)
737*adee6784SGordon Ross {
738*adee6784SGordon Ross 	smb_fh_t *fhp = NULL;
739*adee6784SGordon Ross 
740*adee6784SGordon Ross 	if ((fhp = ctx->f_fhp) != NULL) {
741*adee6784SGordon Ross 		ctx->f_fhp = NULL;
742*adee6784SGordon Ross 		smb_fh_rele(fhp);
743*adee6784SGordon Ross 	}
744*adee6784SGordon Ross 	if (ctx->f_name)
745*adee6784SGordon Ross 		kmem_free(ctx->f_name, ctx->f_namesz);
746*adee6784SGordon Ross 	if (ctx->f_rq)
747*adee6784SGordon Ross 		smb_rq_done(ctx->f_rq);
748*adee6784SGordon Ross 	md_done(&ctx->f_mdchain);
749*adee6784SGordon Ross 
750*adee6784SGordon Ross 	return (0);
751*adee6784SGordon Ross }
752*adee6784SGordon Ross 
753*adee6784SGordon Ross /*
754*adee6784SGordon Ross  * Get a buffer of directory entries (if we don't already have
755*adee6784SGordon Ross  * some remaining in the current buffer) then decode one.
756*adee6784SGordon Ross  */
757*adee6784SGordon Ross int
smbfs_smb2_findnext(struct smbfs_fctx * ctx,uint16_t limit)758*adee6784SGordon Ross smbfs_smb2_findnext(struct smbfs_fctx *ctx, uint16_t limit)
759*adee6784SGordon Ross {
760*adee6784SGordon Ross 	int error;
761*adee6784SGordon Ross 
762*adee6784SGordon Ross 	/*
763*adee6784SGordon Ross 	 * If we've scanned to the end of the current buffer
764*adee6784SGordon Ross 	 * try to read anohther buffer of dir entries.
765*adee6784SGordon Ross 	 * Treat anything less than 8 bytes as an "empty"
766*adee6784SGordon Ross 	 * buffer to ensure we can read something.
767*adee6784SGordon Ross 	 * (There may be up to 8 bytes of padding.)
768*adee6784SGordon Ross 	 */
769*adee6784SGordon Ross 	if ((ctx->f_eofs + 8) > ctx->f_left) {
770*adee6784SGordon Ross 		/* Scanned the whole buffer. */
771*adee6784SGordon Ross 		if (ctx->f_flags & SMBFS_RDD_EOF)
772*adee6784SGordon Ross 			return (ENOENT);
773*adee6784SGordon Ross 		ctx->f_limit = limit;
774*adee6784SGordon Ross 		error = smbfs_smb2_qdir(ctx);
775*adee6784SGordon Ross 		if (error)
776*adee6784SGordon Ross 			return (error);
777*adee6784SGordon Ross 		ctx->f_otws++;
778*adee6784SGordon Ross 	}
779*adee6784SGordon Ross 
780*adee6784SGordon Ross 	/*
781*adee6784SGordon Ross 	 * Decode one entry
782*adee6784SGordon Ross 	 */
783*adee6784SGordon Ross 	error = smbfs_decode_dirent(ctx);
784*adee6784SGordon Ross 
785*adee6784SGordon Ross 	return (error);
786*adee6784SGordon Ross }
787*adee6784SGordon Ross 
788*adee6784SGordon Ross 
789*adee6784SGordon Ross /*
790*adee6784SGordon Ross  * Helper for smbfs_xa_get_streaminfo
791*adee6784SGordon Ross  * Query stream info
792*adee6784SGordon Ross  */
793*adee6784SGordon Ross int
smbfs_smb2_get_streaminfo(smbnode_t * np,struct mdchain * mdp,struct smb_cred * scrp)794*adee6784SGordon Ross smbfs_smb2_get_streaminfo(smbnode_t *np, struct mdchain *mdp,
795*adee6784SGordon Ross 	struct smb_cred *scrp)
796*adee6784SGordon Ross {
797*adee6784SGordon Ross 	smb_share_t *ssp = np->n_mount->smi_share;
798*adee6784SGordon Ross 	smb_fh_t *fhp = NULL;
799*adee6784SGordon Ross 	uint32_t rights =
800*adee6784SGordon Ross 	    STD_RIGHT_READ_CONTROL_ACCESS |
801*adee6784SGordon Ross 	    SA_RIGHT_FILE_READ_ATTRIBUTES;
802*adee6784SGordon Ross 	uint32_t iolen = INT16_MAX;
803*adee6784SGordon Ross 	int error;
804*adee6784SGordon Ross 
805*adee6784SGordon Ross 	/*
806*adee6784SGordon Ross 	 * Get a file handle on the object
807*adee6784SGordon Ross 	 * with read attr. rights.
808*adee6784SGordon Ross 	 */
809*adee6784SGordon Ross 	error = smb_fh_create(ssp, &fhp);
810*adee6784SGordon Ross 	if (error != 0)
811*adee6784SGordon Ross 		goto out;
812*adee6784SGordon Ross 	error = smbfs_smb_ntcreatex(np,
813*adee6784SGordon Ross 	    NULL, 0, 0,	/* name nmlen xattr */
814*adee6784SGordon Ross 	    rights, SMB_EFA_NORMAL,
815*adee6784SGordon Ross 	    NTCREATEX_SHARE_ACCESS_ALL,
816*adee6784SGordon Ross 	    NTCREATEX_DISP_OPEN,
817*adee6784SGordon Ross 	    0, /* create options */
818*adee6784SGordon Ross 	    scrp, fhp, NULL, NULL);
819*adee6784SGordon Ross 	if (error != 0)
820*adee6784SGordon Ross 		goto out;
821*adee6784SGordon Ross 
822*adee6784SGordon Ross 	smb_fh_opened(fhp);
823*adee6784SGordon Ross 
824*adee6784SGordon Ross 	/*
825*adee6784SGordon Ross 	 * Query stream info
826*adee6784SGordon Ross 	 */
827*adee6784SGordon Ross 	error = smbfs_smb2_query_info(ssp, &fhp->fh_fid2, mdp, &iolen,
828*adee6784SGordon Ross 	    SMB2_0_INFO_FILE, FileStreamInformation, 0, scrp);
829*adee6784SGordon Ross 
830*adee6784SGordon Ross out:
831*adee6784SGordon Ross 	if (fhp != NULL)
832*adee6784SGordon Ross 		smb_fh_rele(fhp);
833*adee6784SGordon Ross 	return (error);
834*adee6784SGordon Ross }
835*adee6784SGordon Ross 
836*adee6784SGordon Ross 
837*adee6784SGordon Ross /*
838*adee6784SGordon Ross  * OTW function to Get a security descriptor (SD).
839*adee6784SGordon Ross  *
840*adee6784SGordon Ross  * The *reslen param is bufsize(in) / length(out)
841*adee6784SGordon Ross  * Note: On success, this fills in mdp->md_top,
842*adee6784SGordon Ross  * which the caller should free.
843*adee6784SGordon Ross  */
844*adee6784SGordon Ross int
smbfs_smb2_getsec(struct smb_share * ssp,smb2fid_t * fid,uint32_t selector,mblk_t ** res,uint32_t * reslen,struct smb_cred * scrp)845*adee6784SGordon Ross smbfs_smb2_getsec(struct smb_share *ssp, smb2fid_t *fid,
846*adee6784SGordon Ross 	uint32_t selector, mblk_t **res, uint32_t *reslen,
847*adee6784SGordon Ross 	struct smb_cred *scrp)
848*adee6784SGordon Ross {
849*adee6784SGordon Ross 	struct mdchain info_mdc, *mdp = &info_mdc;
850*adee6784SGordon Ross 	int error;
851*adee6784SGordon Ross 
852*adee6784SGordon Ross 	bzero(mdp, sizeof (*mdp));
853*adee6784SGordon Ross 
854*adee6784SGordon Ross 	error = smbfs_smb2_query_info(ssp, fid, mdp, reslen,
855*adee6784SGordon Ross 	    SMB2_0_INFO_SECURITY, 0, selector, scrp);
856*adee6784SGordon Ross 	if (error)
857*adee6784SGordon Ross 		goto out;
858*adee6784SGordon Ross 
859*adee6784SGordon Ross 	if (mdp->md_top == NULL) {
860*adee6784SGordon Ross 		error = EBADRPC;
861*adee6784SGordon Ross 		goto out;
862*adee6784SGordon Ross 	}
863*adee6784SGordon Ross 	*res = mdp->md_top;
864*adee6784SGordon Ross 	mdp->md_top = NULL;
865*adee6784SGordon Ross 
866*adee6784SGordon Ross out:
867*adee6784SGordon Ross 	md_done(mdp);
868*adee6784SGordon Ross 	return (error);
869*adee6784SGordon Ross }
870*adee6784SGordon Ross 
871*adee6784SGordon Ross 
872*adee6784SGordon Ross /*
873*adee6784SGordon Ross  * OTW function to Set a security descriptor (SD).
874*adee6784SGordon Ross  * Caller data are carried in an mbchain_t.
875*adee6784SGordon Ross  *
876*adee6784SGordon Ross  * Note: This normally consumes mbp->mb_top, and clears
877*adee6784SGordon Ross  * that pointer when it does.
878*adee6784SGordon Ross  */
879*adee6784SGordon Ross int
smbfs_smb2_setsec(struct smb_share * ssp,smb2fid_t * fid,uint32_t selector,mblk_t ** mp,struct smb_cred * scrp)880*adee6784SGordon Ross smbfs_smb2_setsec(struct smb_share *ssp, smb2fid_t *fid,
881*adee6784SGordon Ross 	uint32_t selector, mblk_t **mp, struct smb_cred *scrp)
882*adee6784SGordon Ross {
883*adee6784SGordon Ross 	struct mbchain info_mbp, *mbp = &info_mbp;
884*adee6784SGordon Ross 	int error;
885*adee6784SGordon Ross 
886*adee6784SGordon Ross 	ASSERT(*mp != NULL);
887*adee6784SGordon Ross 	mb_initm(mbp, *mp);
888*adee6784SGordon Ross 	*mp = NULL; /* consumed */
889*adee6784SGordon Ross 
890*adee6784SGordon Ross 	error = smbfs_smb2_set_info(ssp, fid, mbp,
891*adee6784SGordon Ross 	    SMB2_0_INFO_SECURITY, 0, selector, scrp);
892*adee6784SGordon Ross 
893*adee6784SGordon Ross 	mb_done(mbp);
894*adee6784SGordon Ross 
895*adee6784SGordon Ross 	return (error);
896*adee6784SGordon Ross }
897