1e3f2c991SKeyur Desai /*
2e3f2c991SKeyur Desai * CDDL HEADER START
3e3f2c991SKeyur Desai *
4e3f2c991SKeyur Desai * The contents of this file are subject to the terms of the
5e3f2c991SKeyur Desai * Common Development and Distribution License (the "License").
6e3f2c991SKeyur Desai * You may not use this file except in compliance with the License.
7e3f2c991SKeyur Desai *
8e3f2c991SKeyur Desai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e3f2c991SKeyur Desai * or http://www.opensolaris.org/os/licensing.
10e3f2c991SKeyur Desai * See the License for the specific language governing permissions
11e3f2c991SKeyur Desai * and limitations under the License.
12e3f2c991SKeyur Desai *
13e3f2c991SKeyur Desai * When distributing Covered Code, include this CDDL HEADER in each
14e3f2c991SKeyur Desai * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15e3f2c991SKeyur Desai * If applicable, add the following below this CDDL HEADER, with the
16e3f2c991SKeyur Desai * fields enclosed by brackets "[]" replaced with your own identifying
17e3f2c991SKeyur Desai * information: Portions Copyright [yyyy] [name of copyright owner]
18e3f2c991SKeyur Desai *
19e3f2c991SKeyur Desai * CDDL HEADER END
20e3f2c991SKeyur Desai */
21148c5f43SAlan Wright
22e3f2c991SKeyur Desai /*
23c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2456a2adb6SPrashanth Badari * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
25*bf4554a2SGordon Ross * Copyright 2022 RackTop Systems, Inc.
26e3f2c991SKeyur Desai */
27e3f2c991SKeyur Desai
28bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
29e3f2c991SKeyur Desai #include <smbsrv/smb_vops.h>
30e3f2c991SKeyur Desai #include <smbsrv/smb_fsops.h>
31e3f2c991SKeyur Desai
32e3f2c991SKeyur Desai /*
33e3f2c991SKeyur Desai * Trans2 Query File/Path Information Levels:
34e3f2c991SKeyur Desai *
35e3f2c991SKeyur Desai * SMB_INFO_STANDARD
36e3f2c991SKeyur Desai * SMB_INFO_QUERY_EA_SIZE
37e3f2c991SKeyur Desai * SMB_INFO_QUERY_EAS_FROM_LIST
38e3f2c991SKeyur Desai * SMB_INFO_QUERY_ALL_EAS - not valid for pipes
39e3f2c991SKeyur Desai * SMB_INFO_IS_NAME_VALID - only valid when query is by path
40e3f2c991SKeyur Desai *
41e3f2c991SKeyur Desai * SMB_QUERY_FILE_BASIC_INFO
42e3f2c991SKeyur Desai * SMB_QUERY_FILE_STANDARD_INFO
43e3f2c991SKeyur Desai * SMB_QUERY_FILE_EA_INFO
44e3f2c991SKeyur Desai * SMB_QUERY_FILE_NAME_INFO
45e3f2c991SKeyur Desai * SMB_QUERY_FILE_ALL_INFO
46e3f2c991SKeyur Desai * SMB_QUERY_FILE_ALT_NAME_INFO - not valid for pipes
47e3f2c991SKeyur Desai * SMB_QUERY_FILE_STREAM_INFO - not valid for pipes
48e3f2c991SKeyur Desai * SMB_QUERY_FILE_COMPRESSION_INFO - not valid for pipes
49e3f2c991SKeyur Desai *
50e3f2c991SKeyur Desai * Supported Passthrough levels:
51e3f2c991SKeyur Desai * SMB_FILE_BASIC_INFORMATION
52e3f2c991SKeyur Desai * SMB_FILE_STANDARD_INFORMATION
53e3f2c991SKeyur Desai * SMB_FILE_INTERNAL_INFORMATION
54e3f2c991SKeyur Desai * SMB_FILE_EA_INFORMATION
55cb174861Sjoyce mcintosh * SMB_FILE_ACCESS_INFORMATION - not yet supported when query by path
56e3f2c991SKeyur Desai * SMB_FILE_NAME_INFORMATION
57e3f2c991SKeyur Desai * SMB_FILE_ALL_INFORMATION
58e3f2c991SKeyur Desai * SMB_FILE_ALT_NAME_INFORMATION - not valid for pipes
59e3f2c991SKeyur Desai * SMB_FILE_STREAM_INFORMATION - not valid for pipes
60e3f2c991SKeyur Desai * SMB_FILE_COMPRESSION_INFORMATION - not valid for pipes
619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * SMB_FILE_NETWORK_OPEN_INFORMATION - not valid for pipes
62e3f2c991SKeyur Desai * SMB_FILE_ATTR_TAG_INFORMATION - not valid for pipes
63e3f2c991SKeyur Desai *
64e3f2c991SKeyur Desai * Internal levels representing non trans2 requests
65e3f2c991SKeyur Desai * SMB_QUERY_INFORMATION
66e3f2c991SKeyur Desai * SMB_QUERY_INFORMATION2
67e3f2c991SKeyur Desai */
68e3f2c991SKeyur Desai
69cb174861Sjoyce mcintosh /*
70cb174861Sjoyce mcintosh * SMB_STREAM_ENCODE_FIXED_SIZE:
71cb174861Sjoyce mcintosh * 2 dwords + 2 quadwords => 4 + 4 + 8 + 8 => 24
72cb174861Sjoyce mcintosh */
73cb174861Sjoyce mcintosh #define SMB_STREAM_ENCODE_FIXED_SZ 24
74cb174861Sjoyce mcintosh
75a90cf9f2SGordon Ross /* See smb_queryinfo_t in smb_ktypes.h */
76e3f2c991SKeyur Desai #define qi_mtime qi_attr.sa_vattr.va_mtime
77e3f2c991SKeyur Desai #define qi_ctime qi_attr.sa_vattr.va_ctime
78e3f2c991SKeyur Desai #define qi_atime qi_attr.sa_vattr.va_atime
79e3f2c991SKeyur Desai #define qi_crtime qi_attr.sa_crtime
80e3f2c991SKeyur Desai
81e3f2c991SKeyur Desai static int smb_query_by_fid(smb_request_t *, smb_xa_t *, uint16_t);
829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_query_by_path(smb_request_t *, smb_xa_t *, uint16_t);
83e3f2c991SKeyur Desai
84e3f2c991SKeyur Desai static int smb_query_fileinfo(smb_request_t *, smb_node_t *,
85e3f2c991SKeyur Desai uint16_t, smb_queryinfo_t *);
86e3f2c991SKeyur Desai static int smb_query_pipeinfo(smb_request_t *, smb_opipe_t *,
87e3f2c991SKeyur Desai uint16_t, smb_queryinfo_t *);
88e3f2c991SKeyur Desai static boolean_t smb_query_pipe_valid_infolev(smb_request_t *, uint16_t);
89e3f2c991SKeyur Desai
90e3f2c991SKeyur Desai static int smb_query_encode_response(smb_request_t *, smb_xa_t *,
91e3f2c991SKeyur Desai uint16_t, smb_queryinfo_t *);
92148c5f43SAlan Wright static int smb_query_pathname(smb_request_t *, smb_node_t *, boolean_t,
93148c5f43SAlan Wright smb_queryinfo_t *);
94e3f2c991SKeyur Desai
959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int smb_query_passthru;
96e3f2c991SKeyur Desai
97e3f2c991SKeyur Desai /*
98e3f2c991SKeyur Desai * smb_com_trans2_query_file_information
99e3f2c991SKeyur Desai */
100e3f2c991SKeyur Desai smb_sdrc_t
smb_com_trans2_query_file_information(struct smb_request * sr,struct smb_xa * xa)101e3f2c991SKeyur Desai smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa)
102e3f2c991SKeyur Desai {
103e3f2c991SKeyur Desai uint16_t infolev;
104e3f2c991SKeyur Desai
105e3f2c991SKeyur Desai if (smb_mbc_decodef(&xa->req_param_mb, "ww",
106e3f2c991SKeyur Desai &sr->smb_fid, &infolev) != 0)
107e3f2c991SKeyur Desai return (SDRC_ERROR);
108e3f2c991SKeyur Desai
109e3f2c991SKeyur Desai if (smb_query_by_fid(sr, xa, infolev) != 0)
110e3f2c991SKeyur Desai return (SDRC_ERROR);
111e3f2c991SKeyur Desai
112e3f2c991SKeyur Desai return (SDRC_SUCCESS);
113e3f2c991SKeyur Desai }
114e3f2c991SKeyur Desai
115e3f2c991SKeyur Desai /*
116e3f2c991SKeyur Desai * smb_com_trans2_query_path_information
117e3f2c991SKeyur Desai */
118e3f2c991SKeyur Desai smb_sdrc_t
smb_com_trans2_query_path_information(smb_request_t * sr,smb_xa_t * xa)119e3f2c991SKeyur Desai smb_com_trans2_query_path_information(smb_request_t *sr, smb_xa_t *xa)
120e3f2c991SKeyur Desai {
121e3f2c991SKeyur Desai uint16_t infolev;
1229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_fqi_t *fqi = &sr->arg.dirop.fqi;
123e3f2c991SKeyur Desai
124f96bd5c8SAlan Wright if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
125e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
126e3f2c991SKeyur Desai ERRDOS, ERROR_INVALID_FUNCTION);
127e3f2c991SKeyur Desai return (SDRC_ERROR);
128e3f2c991SKeyur Desai }
129e3f2c991SKeyur Desai
130e3f2c991SKeyur Desai if (smb_mbc_decodef(&xa->req_param_mb, "%w4.u",
1319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States sr, &infolev, &fqi->fq_path.pn_path) != 0)
132e3f2c991SKeyur Desai return (SDRC_ERROR);
133e3f2c991SKeyur Desai
1349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_query_by_path(sr, xa, infolev) != 0)
135e3f2c991SKeyur Desai return (SDRC_ERROR);
136e3f2c991SKeyur Desai
137e3f2c991SKeyur Desai return (SDRC_SUCCESS);
138e3f2c991SKeyur Desai }
139e3f2c991SKeyur Desai
140e3f2c991SKeyur Desai /*
141e3f2c991SKeyur Desai * smb_com_query_information (aka getattr)
142e3f2c991SKeyur Desai */
143e3f2c991SKeyur Desai smb_sdrc_t
smb_pre_query_information(smb_request_t * sr)144e3f2c991SKeyur Desai smb_pre_query_information(smb_request_t *sr)
145e3f2c991SKeyur Desai {
146e3f2c991SKeyur Desai int rc;
147e3f2c991SKeyur Desai smb_fqi_t *fqi = &sr->arg.dirop.fqi;
148e3f2c991SKeyur Desai
149e3f2c991SKeyur Desai rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path);
150e3f2c991SKeyur Desai
15193bc28dbSGordon Ross DTRACE_SMB_START(op__QueryInformation, smb_request_t *, sr);
152e3f2c991SKeyur Desai
153e3f2c991SKeyur Desai return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
154e3f2c991SKeyur Desai }
155e3f2c991SKeyur Desai
156e3f2c991SKeyur Desai void
smb_post_query_information(smb_request_t * sr)157e3f2c991SKeyur Desai smb_post_query_information(smb_request_t *sr)
158e3f2c991SKeyur Desai {
15993bc28dbSGordon Ross DTRACE_SMB_DONE(op__QueryInformation, smb_request_t *, sr);
160e3f2c991SKeyur Desai }
161e3f2c991SKeyur Desai
162e3f2c991SKeyur Desai smb_sdrc_t
smb_com_query_information(smb_request_t * sr)163e3f2c991SKeyur Desai smb_com_query_information(smb_request_t *sr)
164e3f2c991SKeyur Desai {
165e3f2c991SKeyur Desai uint16_t infolev = SMB_QUERY_INFORMATION;
166e3f2c991SKeyur Desai
167f96bd5c8SAlan Wright if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
168e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
169e3f2c991SKeyur Desai ERRDOS, ERROR_ACCESS_DENIED);
170e3f2c991SKeyur Desai return (SDRC_ERROR);
171e3f2c991SKeyur Desai }
172e3f2c991SKeyur Desai
1739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_query_by_path(sr, NULL, infolev) != 0)
174e3f2c991SKeyur Desai return (SDRC_ERROR);
175e3f2c991SKeyur Desai
176e3f2c991SKeyur Desai return (SDRC_SUCCESS);
177e3f2c991SKeyur Desai }
178e3f2c991SKeyur Desai
179e3f2c991SKeyur Desai /*
180e3f2c991SKeyur Desai * smb_com_query_information2 (aka getattre)
181e3f2c991SKeyur Desai */
182e3f2c991SKeyur Desai smb_sdrc_t
smb_pre_query_information2(smb_request_t * sr)183e3f2c991SKeyur Desai smb_pre_query_information2(smb_request_t *sr)
184e3f2c991SKeyur Desai {
185e3f2c991SKeyur Desai int rc;
186e3f2c991SKeyur Desai rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
187e3f2c991SKeyur Desai
18893bc28dbSGordon Ross DTRACE_SMB_START(op__QueryInformation2, smb_request_t *, sr);
189e3f2c991SKeyur Desai
190e3f2c991SKeyur Desai return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
191e3f2c991SKeyur Desai }
192e3f2c991SKeyur Desai
193e3f2c991SKeyur Desai void
smb_post_query_information2(smb_request_t * sr)194e3f2c991SKeyur Desai smb_post_query_information2(smb_request_t *sr)
195e3f2c991SKeyur Desai {
19693bc28dbSGordon Ross DTRACE_SMB_DONE(op__QueryInformation2, smb_request_t *, sr);
197e3f2c991SKeyur Desai }
198e3f2c991SKeyur Desai
199e3f2c991SKeyur Desai smb_sdrc_t
smb_com_query_information2(smb_request_t * sr)200e3f2c991SKeyur Desai smb_com_query_information2(smb_request_t *sr)
201e3f2c991SKeyur Desai {
202e3f2c991SKeyur Desai uint16_t infolev = SMB_QUERY_INFORMATION2;
203e3f2c991SKeyur Desai
204e3f2c991SKeyur Desai if (smb_query_by_fid(sr, NULL, infolev) != 0)
205e3f2c991SKeyur Desai return (SDRC_ERROR);
206e3f2c991SKeyur Desai
207e3f2c991SKeyur Desai return (SDRC_SUCCESS);
208e3f2c991SKeyur Desai }
209e3f2c991SKeyur Desai
210e3f2c991SKeyur Desai /*
211e3f2c991SKeyur Desai * smb_query_by_fid
212e3f2c991SKeyur Desai *
213e3f2c991SKeyur Desai * Common code for querying file information by open file (or pipe) id.
214e3f2c991SKeyur Desai * Use the id to identify the node / pipe object and request the
215e3f2c991SKeyur Desai * smb_queryinfo_t data for that object.
216e3f2c991SKeyur Desai */
217e3f2c991SKeyur Desai static int
smb_query_by_fid(smb_request_t * sr,smb_xa_t * xa,uint16_t infolev)218e3f2c991SKeyur Desai smb_query_by_fid(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
219e3f2c991SKeyur Desai {
220e3f2c991SKeyur Desai int rc;
221e3f2c991SKeyur Desai smb_queryinfo_t *qinfo;
222e3f2c991SKeyur Desai smb_node_t *node;
223e3f2c991SKeyur Desai smb_opipe_t *opipe;
224e3f2c991SKeyur Desai
225e3f2c991SKeyur Desai smbsr_lookup_file(sr);
226e3f2c991SKeyur Desai
227e3f2c991SKeyur Desai if (sr->fid_ofile == NULL) {
228e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
229e3f2c991SKeyur Desai return (-1);
230e3f2c991SKeyur Desai }
231e3f2c991SKeyur Desai
232e3f2c991SKeyur Desai if (infolev == SMB_INFO_IS_NAME_VALID) {
233148c5f43SAlan Wright smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
234e3f2c991SKeyur Desai smbsr_release_file(sr);
235e3f2c991SKeyur Desai return (-1);
236e3f2c991SKeyur Desai }
237e3f2c991SKeyur Desai
238e3f2c991SKeyur Desai if ((sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE) &&
239e3f2c991SKeyur Desai (!smb_query_pipe_valid_infolev(sr, infolev))) {
240e3f2c991SKeyur Desai smbsr_release_file(sr);
241e3f2c991SKeyur Desai return (-1);
242e3f2c991SKeyur Desai }
243e3f2c991SKeyur Desai
2445fd03bc0SGordon Ross sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
245e3f2c991SKeyur Desai qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
246e3f2c991SKeyur Desai
247e3f2c991SKeyur Desai switch (sr->fid_ofile->f_ftype) {
248e3f2c991SKeyur Desai case SMB_FTYPE_DISK:
249e3f2c991SKeyur Desai node = sr->fid_ofile->f_node;
250e3f2c991SKeyur Desai rc = smb_query_fileinfo(sr, node, infolev, qinfo);
251e3f2c991SKeyur Desai break;
252e3f2c991SKeyur Desai case SMB_FTYPE_MESG_PIPE:
253e3f2c991SKeyur Desai opipe = sr->fid_ofile->f_pipe;
254e3f2c991SKeyur Desai rc = smb_query_pipeinfo(sr, opipe, infolev, qinfo);
255e3f2c991SKeyur Desai break;
256e3f2c991SKeyur Desai default:
257e3f2c991SKeyur Desai smbsr_error(sr, 0, ERRDOS, ERRbadfile);
258e3f2c991SKeyur Desai rc = -1;
259e3f2c991SKeyur Desai break;
260e3f2c991SKeyur Desai }
261e3f2c991SKeyur Desai
262e3f2c991SKeyur Desai if (rc == 0)
263e3f2c991SKeyur Desai rc = smb_query_encode_response(sr, xa, infolev, qinfo);
264e3f2c991SKeyur Desai
265e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t));
266e3f2c991SKeyur Desai smbsr_release_file(sr);
267e3f2c991SKeyur Desai return (rc);
268e3f2c991SKeyur Desai }
269e3f2c991SKeyur Desai
270e3f2c991SKeyur Desai /*
271e3f2c991SKeyur Desai * smb_query_by_path
272e3f2c991SKeyur Desai *
273e3f2c991SKeyur Desai * Common code for querying file information by file name.
274e3f2c991SKeyur Desai * Use the file name to identify the node object and request the
275e3f2c991SKeyur Desai * smb_queryinfo_t data for that node.
276e3f2c991SKeyur Desai *
2779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Path should be set in sr->arg.dirop.fqi.fq_path prior to
2789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * calling smb_query_by_path.
2799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
280e3f2c991SKeyur Desai * Querying attributes on a named pipe by name is an error and
281e3f2c991SKeyur Desai * is handled in the calling functions so that they can return
282e3f2c991SKeyur Desai * the appropriate error status code (which differs by caller).
283e3f2c991SKeyur Desai */
284e3f2c991SKeyur Desai static int
smb_query_by_path(smb_request_t * sr,smb_xa_t * xa,uint16_t infolev)2859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_query_by_path(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
286e3f2c991SKeyur Desai {
287e3f2c991SKeyur Desai smb_queryinfo_t *qinfo;
288e3f2c991SKeyur Desai smb_node_t *node, *dnode;
2899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_t *pn;
290e3f2c991SKeyur Desai int rc;
291e3f2c991SKeyur Desai
2925fd03bc0SGordon Ross /*
2935fd03bc0SGordon Ross * The function smb_query_fileinfo is used here and in
2945fd03bc0SGordon Ross * smb_query_by_fid. That common function needs this
2955fd03bc0SGordon Ross * one to call it with a NULL fid_ofile, so check here.
2965fd03bc0SGordon Ross * Note: smb_query_by_fid enforces the opposite.
2975fd03bc0SGordon Ross *
2985fd03bc0SGordon Ross * In theory we could ASSERT this, but whether we have
2995fd03bc0SGordon Ross * fid_ofile set here depends on what sequence of SMB
3005fd03bc0SGordon Ross * commands the client has sent in this message, so
3015fd03bc0SGordon Ross * let's be cautious and handle it as an error.
3025fd03bc0SGordon Ross */
3035fd03bc0SGordon Ross if (sr->fid_ofile != NULL)
3045fd03bc0SGordon Ross return (-1);
3055fd03bc0SGordon Ross
3065fd03bc0SGordon Ross
307e3f2c991SKeyur Desai /* VALID, but not yet supported */
308e3f2c991SKeyur Desai if (infolev == SMB_FILE_ACCESS_INFORMATION) {
309148c5f43SAlan Wright smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
310e3f2c991SKeyur Desai return (-1);
311e3f2c991SKeyur Desai }
312e3f2c991SKeyur Desai
3139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States pn = &sr->arg.dirop.fqi.fq_path;
3149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_init(sr, pn, pn->pn_path);
3159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (!smb_pathname_validate(sr, pn))
3169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (-1);
317e3f2c991SKeyur Desai
318e3f2c991SKeyur Desai qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
319e3f2c991SKeyur Desai
3209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
3219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode,
3229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States qinfo->qi_name);
3239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
324e3f2c991SKeyur Desai if (rc == 0) {
325e3f2c991SKeyur Desai rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS,
326e3f2c991SKeyur Desai sr->tid_tree->t_snode, dnode, qinfo->qi_name, &node);
327e3f2c991SKeyur Desai smb_node_release(dnode);
328e3f2c991SKeyur Desai }
329e3f2c991SKeyur Desai
330e3f2c991SKeyur Desai if (rc != 0) {
331e3f2c991SKeyur Desai smbsr_errno(sr, rc);
332e3f2c991SKeyur Desai
333e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t));
334e3f2c991SKeyur Desai return (-1);
335e3f2c991SKeyur Desai }
336e3f2c991SKeyur Desai
3379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
3389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States kmem_free(qinfo, sizeof (smb_queryinfo_t));
3409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_release(node);
3419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (-1);
3429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
3439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
344e3f2c991SKeyur Desai rc = smb_query_fileinfo(sr, node, infolev, qinfo);
345e3f2c991SKeyur Desai if (rc != 0) {
346e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t));
347e3f2c991SKeyur Desai smb_node_release(node);
348e3f2c991SKeyur Desai return (rc);
349e3f2c991SKeyur Desai }
350e3f2c991SKeyur Desai
351e3f2c991SKeyur Desai /* If delete_on_close - NT_STATUS_DELETE_PENDING */
352e3f2c991SKeyur Desai if (qinfo->qi_delete_on_close) {
353e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_DELETE_PENDING,
354e3f2c991SKeyur Desai ERRDOS, ERROR_ACCESS_DENIED);
355e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t));
356e3f2c991SKeyur Desai smb_node_release(node);
357e3f2c991SKeyur Desai return (-1);
358e3f2c991SKeyur Desai }
359e3f2c991SKeyur Desai
360e3f2c991SKeyur Desai rc = smb_query_encode_response(sr, xa, infolev, qinfo);
361e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t));
362e3f2c991SKeyur Desai smb_node_release(node);
363e3f2c991SKeyur Desai return (rc);
364e3f2c991SKeyur Desai }
365e3f2c991SKeyur Desai
366e3f2c991SKeyur Desai /*
367e3f2c991SKeyur Desai * smb_size32
368e3f2c991SKeyur Desai * Some responses only support 32 bit file sizes. If the file size
369e3f2c991SKeyur Desai * exceeds UINT_MAX (32 bit) we return UINT_MAX in the response.
370e3f2c991SKeyur Desai */
371e3f2c991SKeyur Desai static uint32_t
smb_size32(u_offset_t size)372e3f2c991SKeyur Desai smb_size32(u_offset_t size)
373e3f2c991SKeyur Desai {
374e3f2c991SKeyur Desai return ((size > UINT_MAX) ? UINT_MAX : (uint32_t)size);
375e3f2c991SKeyur Desai }
376e3f2c991SKeyur Desai
377e3f2c991SKeyur Desai /*
378e3f2c991SKeyur Desai * smb_query_encode_response
379e3f2c991SKeyur Desai *
380e3f2c991SKeyur Desai * Encode the data from smb_queryinfo_t into client response
381e3f2c991SKeyur Desai */
382e3f2c991SKeyur Desai int
smb_query_encode_response(smb_request_t * sr,smb_xa_t * xa,uint16_t infolev,smb_queryinfo_t * qinfo)383e3f2c991SKeyur Desai smb_query_encode_response(smb_request_t *sr, smb_xa_t *xa,
384e3f2c991SKeyur Desai uint16_t infolev, smb_queryinfo_t *qinfo)
385e3f2c991SKeyur Desai {
386e3f2c991SKeyur Desai uint16_t dattr;
387e3f2c991SKeyur Desai u_offset_t datasz, allocsz;
388a90cf9f2SGordon Ross uint32_t status;
389e3f2c991SKeyur Desai
390e3f2c991SKeyur Desai dattr = qinfo->qi_attr.sa_dosattr & FILE_ATTRIBUTE_MASK;
391e3f2c991SKeyur Desai datasz = qinfo->qi_attr.sa_vattr.va_size;
392e3f2c991SKeyur Desai allocsz = qinfo->qi_attr.sa_allocsz;
393e3f2c991SKeyur Desai
394e3f2c991SKeyur Desai switch (infolev) {
395e3f2c991SKeyur Desai case SMB_QUERY_INFORMATION:
396e3f2c991SKeyur Desai (void) smbsr_encode_result(sr, 10, 0, "bwll10.w",
397e3f2c991SKeyur Desai 10,
398e3f2c991SKeyur Desai dattr,
399e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
400e3f2c991SKeyur Desai smb_size32(datasz),
401e3f2c991SKeyur Desai 0);
402e3f2c991SKeyur Desai break;
403e3f2c991SKeyur Desai
404e3f2c991SKeyur Desai case SMB_QUERY_INFORMATION2:
405e3f2c991SKeyur Desai (void) smbsr_encode_result(sr, 11, 0, "byyyllww",
406e3f2c991SKeyur Desai 11,
407e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
408e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
409e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
410e3f2c991SKeyur Desai smb_size32(datasz), smb_size32(allocsz), dattr, 0);
411e3f2c991SKeyur Desai break;
412e3f2c991SKeyur Desai
413e3f2c991SKeyur Desai case SMB_FILE_ACCESS_INFORMATION:
414e3f2c991SKeyur Desai ASSERT(sr->fid_ofile);
415e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "l",
416e3f2c991SKeyur Desai sr->fid_ofile->f_granted_access);
417e3f2c991SKeyur Desai break;
418e3f2c991SKeyur Desai
419e3f2c991SKeyur Desai case SMB_INFO_STANDARD:
420e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
421e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb,
422e3f2c991SKeyur Desai ((sr->session->native_os == NATIVE_OS_WIN95) ?
423e3f2c991SKeyur Desai "YYYllw" : "yyyllw"),
424e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
425e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
426e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
427e3f2c991SKeyur Desai smb_size32(datasz), smb_size32(allocsz), dattr);
428e3f2c991SKeyur Desai break;
429e3f2c991SKeyur Desai
430e3f2c991SKeyur Desai case SMB_INFO_QUERY_EA_SIZE:
431e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
432e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb,
433e3f2c991SKeyur Desai ((sr->session->native_os == NATIVE_OS_WIN95) ?
434e3f2c991SKeyur Desai "YYYllwl" : "yyyllwl"),
435e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
436e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
437e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
438e3f2c991SKeyur Desai smb_size32(datasz), smb_size32(allocsz), dattr, 0);
439e3f2c991SKeyur Desai break;
440e3f2c991SKeyur Desai
441e3f2c991SKeyur Desai case SMB_INFO_QUERY_ALL_EAS:
442e3f2c991SKeyur Desai case SMB_INFO_QUERY_EAS_FROM_LIST:
443e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
444e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
445e3f2c991SKeyur Desai break;
446e3f2c991SKeyur Desai
447e3f2c991SKeyur Desai case SMB_INFO_IS_NAME_VALID:
448e3f2c991SKeyur Desai break;
449e3f2c991SKeyur Desai
450e3f2c991SKeyur Desai case SMB_QUERY_FILE_BASIC_INFO:
451e3f2c991SKeyur Desai case SMB_FILE_BASIC_INFORMATION:
452e3f2c991SKeyur Desai /*
453e3f2c991SKeyur Desai * NT includes 6 bytes (spec says 4) at the end of this
454e3f2c991SKeyur Desai * response, which are required by NetBench 5.01.
455e3f2c991SKeyur Desai */
456e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
457e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.",
458e3f2c991SKeyur Desai &qinfo->qi_crtime,
459e3f2c991SKeyur Desai &qinfo->qi_atime,
460e3f2c991SKeyur Desai &qinfo->qi_mtime,
461e3f2c991SKeyur Desai &qinfo->qi_ctime,
462e3f2c991SKeyur Desai dattr);
463e3f2c991SKeyur Desai break;
464e3f2c991SKeyur Desai
465e3f2c991SKeyur Desai case SMB_QUERY_FILE_STANDARD_INFO:
466e3f2c991SKeyur Desai case SMB_FILE_STANDARD_INFORMATION:
467e3f2c991SKeyur Desai /* 2-byte pad at end */
468e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
469e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "qqlbb2.",
470e3f2c991SKeyur Desai (uint64_t)allocsz,
471e3f2c991SKeyur Desai (uint64_t)datasz,
472e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nlink,
473e3f2c991SKeyur Desai qinfo->qi_delete_on_close,
474a90cf9f2SGordon Ross qinfo->qi_isdir);
475e3f2c991SKeyur Desai break;
476e3f2c991SKeyur Desai
477e3f2c991SKeyur Desai case SMB_QUERY_FILE_EA_INFO:
478e3f2c991SKeyur Desai case SMB_FILE_EA_INFORMATION:
479e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
480e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
481e3f2c991SKeyur Desai break;
482e3f2c991SKeyur Desai
483e3f2c991SKeyur Desai case SMB_QUERY_FILE_NAME_INFO:
484e3f2c991SKeyur Desai case SMB_FILE_NAME_INFORMATION:
485e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
486e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", sr,
487e3f2c991SKeyur Desai qinfo->qi_namelen, qinfo->qi_name);
488e3f2c991SKeyur Desai break;
489e3f2c991SKeyur Desai
490e3f2c991SKeyur Desai case SMB_QUERY_FILE_ALL_INFO:
491e3f2c991SKeyur Desai case SMB_FILE_ALL_INFORMATION:
492e3f2c991SKeyur Desai /*
493e3f2c991SKeyur Desai * There is a 6-byte pad between Attributes and AllocationSize,
494e3f2c991SKeyur Desai * and a 2-byte pad after the Directory field.
495e3f2c991SKeyur Desai */
496e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
497e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.qqlbb2.l",
498e3f2c991SKeyur Desai &qinfo->qi_crtime,
499e3f2c991SKeyur Desai &qinfo->qi_atime,
500e3f2c991SKeyur Desai &qinfo->qi_mtime,
501e3f2c991SKeyur Desai &qinfo->qi_ctime,
502e3f2c991SKeyur Desai dattr,
503e3f2c991SKeyur Desai (uint64_t)allocsz,
504e3f2c991SKeyur Desai (uint64_t)datasz,
505e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nlink,
506e3f2c991SKeyur Desai qinfo->qi_delete_on_close,
507a90cf9f2SGordon Ross qinfo->qi_isdir,
508e3f2c991SKeyur Desai 0);
509e3f2c991SKeyur Desai
510e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu",
511e3f2c991SKeyur Desai sr, qinfo->qi_namelen, qinfo->qi_name);
512e3f2c991SKeyur Desai break;
513e3f2c991SKeyur Desai
514e3f2c991SKeyur Desai case SMB_QUERY_FILE_ALT_NAME_INFO:
515e3f2c991SKeyur Desai case SMB_FILE_ALT_NAME_INFORMATION:
516e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
517e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "%lU", sr,
518bbf6f00cSJordan Brown smb_wcequiv_strlen(qinfo->qi_shortname),
519e3f2c991SKeyur Desai qinfo->qi_shortname);
520e3f2c991SKeyur Desai break;
521e3f2c991SKeyur Desai
522e3f2c991SKeyur Desai case SMB_QUERY_FILE_STREAM_INFO:
523e3f2c991SKeyur Desai case SMB_FILE_STREAM_INFORMATION:
524e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
525a90cf9f2SGordon Ross status = smb_query_stream_info(sr, &xa->rep_data_mb, qinfo);
526a90cf9f2SGordon Ross if (status)
527a90cf9f2SGordon Ross smbsr_status(sr, status, 0, 0);
528e3f2c991SKeyur Desai break;
529e3f2c991SKeyur Desai
530e3f2c991SKeyur Desai case SMB_QUERY_FILE_COMPRESSION_INFO:
531e3f2c991SKeyur Desai case SMB_FILE_COMPRESSION_INFORMATION:
532e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
533e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "qwbbb3.",
534e3f2c991SKeyur Desai datasz, 0, 0, 0, 0);
535e3f2c991SKeyur Desai break;
536e3f2c991SKeyur Desai
537e3f2c991SKeyur Desai case SMB_FILE_INTERNAL_INFORMATION:
538e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
539e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "q",
540e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nodeid);
541e3f2c991SKeyur Desai break;
542e3f2c991SKeyur Desai
5439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_FILE_NETWORK_OPEN_INFORMATION:
5449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
5459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTqql4.",
5469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &qinfo->qi_crtime,
5479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &qinfo->qi_atime,
5489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &qinfo->qi_mtime,
5499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &qinfo->qi_ctime,
5509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (uint64_t)allocsz,
5519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (uint64_t)datasz,
5529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (uint32_t)dattr);
5539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break;
5549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
555e3f2c991SKeyur Desai case SMB_FILE_ATTR_TAG_INFORMATION:
556e3f2c991SKeyur Desai /*
557e3f2c991SKeyur Desai * If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the
558e3f2c991SKeyur Desai * second dword should be the reparse tag. Otherwise
559e3f2c991SKeyur Desai * the tag value should be set to zero.
560e3f2c991SKeyur Desai * We don't support reparse points, so we set the tag
561e3f2c991SKeyur Desai * to zero.
562e3f2c991SKeyur Desai */
563e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
564e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "ll",
565e3f2c991SKeyur Desai (uint32_t)dattr, 0);
566e3f2c991SKeyur Desai break;
567e3f2c991SKeyur Desai
568e3f2c991SKeyur Desai default:
5699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((infolev > 1000) && smb_query_passthru)
5709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
5719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ERRDOS, ERROR_NOT_SUPPORTED);
5729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States else
573148c5f43SAlan Wright smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
574e3f2c991SKeyur Desai return (-1);
575e3f2c991SKeyur Desai }
576e3f2c991SKeyur Desai
577e3f2c991SKeyur Desai return (0);
578e3f2c991SKeyur Desai }
579e3f2c991SKeyur Desai
580e3f2c991SKeyur Desai /*
581e3f2c991SKeyur Desai * smb_encode_stream_info
582e3f2c991SKeyur Desai *
583e3f2c991SKeyur Desai * This function encodes the streams information.
584e3f2c991SKeyur Desai * The following rules about how have been derived from observed NT
585e3f2c991SKeyur Desai * behaviour.
586e3f2c991SKeyur Desai *
587e3f2c991SKeyur Desai * If the target is a file:
588e3f2c991SKeyur Desai * 1. If there are no named streams, the response should still contain
589e3f2c991SKeyur Desai * an entry for the unnamed stream.
590e3f2c991SKeyur Desai * 2. If there are named streams, the response should contain an entry
591e3f2c991SKeyur Desai * for the unnamed stream followed by the entries for the named
592e3f2c991SKeyur Desai * streams.
593e3f2c991SKeyur Desai *
594e3f2c991SKeyur Desai * If the target is a directory:
595e3f2c991SKeyur Desai * 1. If there are no streams, the response is complete. Directories
596e3f2c991SKeyur Desai * do not report the unnamed stream.
597e3f2c991SKeyur Desai * 2. If there are streams, the response should contain entries for
598e3f2c991SKeyur Desai * those streams but there should not be an entry for the unnamed
599e3f2c991SKeyur Desai * stream.
600e3f2c991SKeyur Desai *
601*bf4554a2SGordon Ross * Note that the stream names are NOT null terminated, and the lengths
602*bf4554a2SGordon Ross * reflect that. Entries are aligned on 8-byte boundaries with padding
603*bf4554a2SGordon Ross * and the "next offset" tells where the next entry begins.
604e3f2c991SKeyur Desai *
605e3f2c991SKeyur Desai * If an error is encountered when trying to read the stream entries
606e3f2c991SKeyur Desai * (smb_odir_read_streaminfo) it is treated as if there are no [more]
607e3f2c991SKeyur Desai * entries. The entries that have been read so far are returned and
608e3f2c991SKeyur Desai * no error is reported.
609e3f2c991SKeyur Desai *
610cb174861Sjoyce mcintosh * If the response buffer is not large enough to return all of the
611cb174861Sjoyce mcintosh * named stream entries, the entries that do fit are returned and
612cb174861Sjoyce mcintosh * a warning code is set (NT_STATUS_BUFFER_OVERFLOW). The next_offset
613cb174861Sjoyce mcintosh * value in the last returned entry must be 0.
614e3f2c991SKeyur Desai */
615a90cf9f2SGordon Ross uint32_t
smb_query_stream_info(smb_request_t * sr,mbuf_chain_t * mbc,smb_queryinfo_t * qinfo)616a90cf9f2SGordon Ross smb_query_stream_info(smb_request_t *sr, mbuf_chain_t *mbc,
617a90cf9f2SGordon Ross smb_queryinfo_t *qinfo)
618e3f2c991SKeyur Desai {
619e3f2c991SKeyur Desai char *stream_name;
620e3f2c991SKeyur Desai uint32_t stream_nlen;
621*bf4554a2SGordon Ross smb_streaminfo_t *sinfo;
622e3f2c991SKeyur Desai int rc = 0;
623*bf4554a2SGordon Ross int prev_ent_off;
624*bf4554a2SGordon Ross int cur_ent_off;
625e3f2c991SKeyur Desai smb_odir_t *od = NULL;
626a90cf9f2SGordon Ross uint32_t status = 0;
627e3f2c991SKeyur Desai smb_node_t *fnode = qinfo->qi_node;
628e3f2c991SKeyur Desai
629e3f2c991SKeyur Desai ASSERT(fnode);
630e3f2c991SKeyur Desai if (SMB_IS_STREAM(fnode)) {
631e3f2c991SKeyur Desai fnode = fnode->n_unode;
632e3f2c991SKeyur Desai ASSERT(fnode);
633e3f2c991SKeyur Desai }
634e3f2c991SKeyur Desai ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
635e3f2c991SKeyur Desai ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
636e3f2c991SKeyur Desai
637*bf4554a2SGordon Ross sinfo = smb_srm_alloc(sr, sizeof (smb_streaminfo_t));
638*bf4554a2SGordon Ross
639*bf4554a2SGordon Ross /*
640*bf4554a2SGordon Ross * Keep track of where the last entry starts so we can
641*bf4554a2SGordon Ross * come back and poke the NextEntryOffset field. Also,
642*bf4554a2SGordon Ross * after enumeration finishes, the caller uses this to
643*bf4554a2SGordon Ross * poke the last entry again with zero to mark it as
644*bf4554a2SGordon Ross * the end of the enumeration.
645*bf4554a2SGordon Ross */
646*bf4554a2SGordon Ross ASSERT(mbc->chain_offset == 0);
647*bf4554a2SGordon Ross cur_ent_off = prev_ent_off = 0;
648*bf4554a2SGordon Ross
649*bf4554a2SGordon Ross /*
650*bf4554a2SGordon Ross * If the unnamed stream is a file, encode an entry for
651*bf4554a2SGordon Ross * the unnamed stream. Note we can't generally get the
652*bf4554a2SGordon Ross * size or allocsize from qi_attr because those may be
653*bf4554a2SGordon Ross * from one of the named streams. Get the sizes.
654*bf4554a2SGordon Ross */
655*bf4554a2SGordon Ross if (smb_node_is_file(fnode)) {
656*bf4554a2SGordon Ross smb_attr_t attr;
657*bf4554a2SGordon Ross uint64_t datasz, allocsz;
658*bf4554a2SGordon Ross
659*bf4554a2SGordon Ross bzero(&attr, sizeof (attr));
660*bf4554a2SGordon Ross attr.sa_mask = SMB_AT_SIZE | SMB_AT_ALLOCSZ;
661*bf4554a2SGordon Ross rc = smb_node_getattr(sr, fnode, sr->user_cr, NULL, &attr);
662*bf4554a2SGordon Ross if (rc != 0) {
663*bf4554a2SGordon Ross status = smb_errno2status(rc);
664*bf4554a2SGordon Ross goto out;
665*bf4554a2SGordon Ross }
666*bf4554a2SGordon Ross
667*bf4554a2SGordon Ross stream_name = "::$DATA";
668*bf4554a2SGordon Ross stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name);
669*bf4554a2SGordon Ross datasz = attr.sa_vattr.va_size;
670*bf4554a2SGordon Ross allocsz = attr.sa_allocsz;
671*bf4554a2SGordon Ross /* Leave NextEntryOffset=0, set later. */
672*bf4554a2SGordon Ross rc = smb_mbc_encodef(mbc, "%llqq#u", sr,
673*bf4554a2SGordon Ross 0, stream_nlen, datasz, allocsz,
674*bf4554a2SGordon Ross stream_nlen, stream_name);
675*bf4554a2SGordon Ross if (rc != 0) {
676*bf4554a2SGordon Ross /* Ran out of room. */
677*bf4554a2SGordon Ross status = NT_STATUS_BUFFER_OVERFLOW;
678*bf4554a2SGordon Ross goto out;
679*bf4554a2SGordon Ross }
680*bf4554a2SGordon Ross }
681e3f2c991SKeyur Desai
68256a2adb6SPrashanth Badari status = smb_odir_openat(sr, fnode, &od, B_TRUE);
683a90cf9f2SGordon Ross switch (status) {
684a90cf9f2SGordon Ross case 0:
685a90cf9f2SGordon Ross break;
686d2488fe8SGordon Ross case NT_STATUS_OBJECT_NAME_NOT_FOUND:
687a90cf9f2SGordon Ross case NT_STATUS_NO_SUCH_FILE:
688a90cf9f2SGordon Ross case NT_STATUS_NOT_SUPPORTED:
689a90cf9f2SGordon Ross /* No streams. */
690d2488fe8SGordon Ross status = 0;
691*bf4554a2SGordon Ross goto out;
692a90cf9f2SGordon Ross default:
693*bf4554a2SGordon Ross goto out;
694a90cf9f2SGordon Ross }
695a90cf9f2SGordon Ross
696*bf4554a2SGordon Ross for (;;) {
697*bf4554a2SGordon Ross boolean_t eos = B_FALSE;
698a90cf9f2SGordon Ross rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
699*bf4554a2SGordon Ross if ((rc != 0) || (eos)) {
700*bf4554a2SGordon Ross status = 0;
701*bf4554a2SGordon Ross break; // normal termination
702e3f2c991SKeyur Desai }
703e3f2c991SKeyur Desai
704e3f2c991SKeyur Desai /*
705*bf4554a2SGordon Ross * We have a directory entry to process.
706*bf4554a2SGordon Ross * Align before encoding.
707e3f2c991SKeyur Desai */
708*bf4554a2SGordon Ross rc = smb_mbc_put_align(mbc, 8);
709*bf4554a2SGordon Ross if (rc != 0) {
710a90cf9f2SGordon Ross status = NT_STATUS_BUFFER_OVERFLOW;
711*bf4554a2SGordon Ross break;
712e3f2c991SKeyur Desai }
713*bf4554a2SGordon Ross cur_ent_off = mbc->chain_offset;
714cb174861Sjoyce mcintosh
715*bf4554a2SGordon Ross /*
716*bf4554a2SGordon Ross * Encode it.
717*bf4554a2SGordon Ross */
718*bf4554a2SGordon Ross stream_name = sinfo->si_name;
719*bf4554a2SGordon Ross stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name);
720*bf4554a2SGordon Ross /* Leave NextEntryOffset=0, set later. */
721*bf4554a2SGordon Ross rc = smb_mbc_encodef(mbc, "%llqq#u", sr,
722*bf4554a2SGordon Ross 0, stream_nlen,
723e3f2c991SKeyur Desai sinfo->si_size, sinfo->si_alloc_size,
724*bf4554a2SGordon Ross stream_nlen, stream_name);
725*bf4554a2SGordon Ross if (rc != 0) {
726*bf4554a2SGordon Ross status = NT_STATUS_BUFFER_OVERFLOW;
727*bf4554a2SGordon Ross break;
728e3f2c991SKeyur Desai }
729e3f2c991SKeyur Desai
730*bf4554a2SGordon Ross /*
731*bf4554a2SGordon Ross * We succeeded encoding the current entry, so
732*bf4554a2SGordon Ross * fill in NextEntryOffset in the previous entry.
733*bf4554a2SGordon Ross * When listing streams on a file, we're always at
734*bf4554a2SGordon Ross * the 2nd or later entry due to "::$DATA" above.
735*bf4554a2SGordon Ross * However, when listing streams on a directory,
736*bf4554a2SGordon Ross * there might not be previous entry.
737*bf4554a2SGordon Ross */
738*bf4554a2SGordon Ross if (cur_ent_off > 0) {
739*bf4554a2SGordon Ross (void) smb_mbc_poke(mbc, prev_ent_off, "l",
740*bf4554a2SGordon Ross cur_ent_off - prev_ent_off);
741*bf4554a2SGordon Ross }
742*bf4554a2SGordon Ross prev_ent_off = cur_ent_off;
743*bf4554a2SGordon Ross }
744*bf4554a2SGordon Ross
745*bf4554a2SGordon Ross out:
746e3f2c991SKeyur Desai if (od) {
747e3f2c991SKeyur Desai smb_odir_close(od);
748e3f2c991SKeyur Desai smb_odir_release(od);
749e3f2c991SKeyur Desai }
750a90cf9f2SGordon Ross
751a90cf9f2SGordon Ross return (status);
752e3f2c991SKeyur Desai }
753e3f2c991SKeyur Desai
754e3f2c991SKeyur Desai /*
755e3f2c991SKeyur Desai * smb_query_fileinfo
756e3f2c991SKeyur Desai *
757e3f2c991SKeyur Desai * Populate smb_queryinfo_t structure for SMB_FTYPE_DISK
758e3f2c991SKeyur Desai * (This should become an smb_ofile / smb_node function.)
759e3f2c991SKeyur Desai */
760e3f2c991SKeyur Desai int
smb_query_fileinfo(smb_request_t * sr,smb_node_t * node,uint16_t infolev,smb_queryinfo_t * qinfo)761e3f2c991SKeyur Desai smb_query_fileinfo(smb_request_t *sr, smb_node_t *node, uint16_t infolev,
762e3f2c991SKeyur Desai smb_queryinfo_t *qinfo)
763e3f2c991SKeyur Desai {
764148c5f43SAlan Wright int rc = 0;
765e3f2c991SKeyur Desai
766cb174861Sjoyce mcintosh /* If shortname required but not supported -> OBJECT_NAME_NOT_FOUND */
767cb174861Sjoyce mcintosh if ((infolev == SMB_QUERY_FILE_ALT_NAME_INFO) ||
768cb174861Sjoyce mcintosh (infolev == SMB_FILE_ALT_NAME_INFORMATION)) {
769cb174861Sjoyce mcintosh if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_SHORTNAMES)) {
770cb174861Sjoyce mcintosh smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
771cb174861Sjoyce mcintosh ERRDOS, ERROR_FILE_NOT_FOUND);
772cb174861Sjoyce mcintosh return (-1);
773cb174861Sjoyce mcintosh }
774cb174861Sjoyce mcintosh }
775cb174861Sjoyce mcintosh
776e3f2c991SKeyur Desai (void) bzero(qinfo, sizeof (smb_queryinfo_t));
777e3f2c991SKeyur Desai
7785fd03bc0SGordon Ross /* See: smb_query_encode_response */
7795fd03bc0SGordon Ross qinfo->qi_attr.sa_mask = SMB_AT_ALL;
7805fd03bc0SGordon Ross rc = smb_node_getattr(sr, node, sr->user_cr, sr->fid_ofile,
7815fd03bc0SGordon Ross &qinfo->qi_attr);
7825fd03bc0SGordon Ross if (rc != 0) {
783e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
784e3f2c991SKeyur Desai ERRDOS, ERROR_INTERNAL_ERROR);
785e3f2c991SKeyur Desai return (-1);
786e3f2c991SKeyur Desai }
787e3f2c991SKeyur Desai
788e3f2c991SKeyur Desai qinfo->qi_node = node;
789e3f2c991SKeyur Desai qinfo->qi_delete_on_close =
790e3f2c991SKeyur Desai (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0;
791a90cf9f2SGordon Ross qinfo->qi_isdir = smb_node_is_dir(node);
792e3f2c991SKeyur Desai
793e3f2c991SKeyur Desai /*
794e3f2c991SKeyur Desai * The number of links reported should be the number of
795e3f2c991SKeyur Desai * non-deleted links. Thus if delete_on_close is set,
796e3f2c991SKeyur Desai * decrement the link count.
797e3f2c991SKeyur Desai */
798e3f2c991SKeyur Desai if (qinfo->qi_delete_on_close &&
799e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nlink > 0) {
800e3f2c991SKeyur Desai --(qinfo->qi_attr.sa_vattr.va_nlink);
801e3f2c991SKeyur Desai }
802e3f2c991SKeyur Desai
803148c5f43SAlan Wright /*
804148c5f43SAlan Wright * populate name, namelen and shortname ONLY for the information
805148c5f43SAlan Wright * levels that require these fields
806148c5f43SAlan Wright */
807148c5f43SAlan Wright switch (infolev) {
808148c5f43SAlan Wright case SMB_QUERY_FILE_ALL_INFO:
809148c5f43SAlan Wright case SMB_FILE_ALL_INFORMATION:
810148c5f43SAlan Wright rc = smb_query_pathname(sr, node, B_TRUE, qinfo);
811148c5f43SAlan Wright break;
812148c5f43SAlan Wright case SMB_QUERY_FILE_NAME_INFO:
813148c5f43SAlan Wright case SMB_FILE_NAME_INFORMATION:
814148c5f43SAlan Wright rc = smb_query_pathname(sr, node, B_FALSE, qinfo);
815148c5f43SAlan Wright break;
816148c5f43SAlan Wright case SMB_QUERY_FILE_ALT_NAME_INFO:
817148c5f43SAlan Wright case SMB_FILE_ALT_NAME_INFORMATION:
818148c5f43SAlan Wright smb_query_shortname(node, qinfo);
819148c5f43SAlan Wright break;
820148c5f43SAlan Wright default:
821148c5f43SAlan Wright break;
822bbf6f00cSJordan Brown }
823bbf6f00cSJordan Brown
824e3f2c991SKeyur Desai if (rc != 0) {
825e3f2c991SKeyur Desai smbsr_errno(sr, rc);
826e3f2c991SKeyur Desai return (-1);
827e3f2c991SKeyur Desai }
828148c5f43SAlan Wright return (0);
829148c5f43SAlan Wright }
830e3f2c991SKeyur Desai
831e3f2c991SKeyur Desai /*
832148c5f43SAlan Wright * smb_query_pathname
833148c5f43SAlan Wright *
834148c5f43SAlan Wright * Determine the absolute pathname of 'node' within the share.
835148c5f43SAlan Wright * For some levels (e.g. ALL_INFO) the pathname should include the
836148c5f43SAlan Wright * sharename for others (e.g. NAME_INFO) the pathname should be
837148c5f43SAlan Wright * relative to the share.
838148c5f43SAlan Wright * For example if the node represents file "test1.txt" in directory
839148c5f43SAlan Wright * "dir1" on share "share1"
840148c5f43SAlan Wright * - if include_share is TRUE the pathname would be: \share1\dir1\test1.txt
841148c5f43SAlan Wright * - if include_share is FALSE the pathname would be: \dir1\test1.txt
842148c5f43SAlan Wright *
843e3f2c991SKeyur Desai * For some reason NT will not show the security tab in the root
844148c5f43SAlan Wright * directory of a mapped drive unless the filename length is greater
845148c5f43SAlan Wright * than one. So if the length is 1 we set it to 2 to persuade NT to
846148c5f43SAlan Wright * show the tab. It should be safe because of the null terminator.
847e3f2c991SKeyur Desai */
848148c5f43SAlan Wright static int
smb_query_pathname(smb_request_t * sr,smb_node_t * node,boolean_t include_share,smb_queryinfo_t * qinfo)849148c5f43SAlan Wright smb_query_pathname(smb_request_t *sr, smb_node_t *node, boolean_t include_share,
850148c5f43SAlan Wright smb_queryinfo_t *qinfo)
851148c5f43SAlan Wright {
852148c5f43SAlan Wright smb_tree_t *tree = sr->tid_tree;
853148c5f43SAlan Wright char *buf = qinfo->qi_name;
854148c5f43SAlan Wright size_t buflen = MAXPATHLEN;
855148c5f43SAlan Wright size_t len;
856148c5f43SAlan Wright int rc;
857148c5f43SAlan Wright
858148c5f43SAlan Wright if (include_share) {
859148c5f43SAlan Wright len = snprintf(buf, buflen, "\\%s", tree->t_sharename);
860148c5f43SAlan Wright if (len == (buflen - 1))
861148c5f43SAlan Wright return (ENAMETOOLONG);
862148c5f43SAlan Wright
863148c5f43SAlan Wright buf += len;
864148c5f43SAlan Wright buflen -= len;
865148c5f43SAlan Wright }
866148c5f43SAlan Wright
867148c5f43SAlan Wright if (node == tree->t_snode) {
868148c5f43SAlan Wright if (!include_share)
869148c5f43SAlan Wright (void) strlcpy(buf, "\\", buflen);
870148c5f43SAlan Wright return (0);
871148c5f43SAlan Wright }
872148c5f43SAlan Wright
873148c5f43SAlan Wright rc = smb_node_getshrpath(node, tree, buf, buflen);
874148c5f43SAlan Wright if (rc == 0) {
875148c5f43SAlan Wright qinfo->qi_namelen =
876148c5f43SAlan Wright smb_ascii_or_unicode_strlen(sr, qinfo->qi_name);
877e3f2c991SKeyur Desai if (qinfo->qi_namelen == 1)
878e3f2c991SKeyur Desai qinfo->qi_namelen = 2;
879148c5f43SAlan Wright }
880148c5f43SAlan Wright return (rc);
881148c5f43SAlan Wright }
882e3f2c991SKeyur Desai
883e3f2c991SKeyur Desai /*
884148c5f43SAlan Wright * smb_query_shortname
885148c5f43SAlan Wright *
886148c5f43SAlan Wright * If the node is a named stream, use its associated
8879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * unnamed stream name to determine the shortname.
888148c5f43SAlan Wright * If a shortname is required (smb_needs_mangle()), generate it
889148c5f43SAlan Wright * using smb_mangle(), otherwise, convert the original name to
890148c5f43SAlan Wright * upper-case and return it as the alternative name.
891e3f2c991SKeyur Desai */
892a90cf9f2SGordon Ross void
smb_query_shortname(smb_node_t * node,smb_queryinfo_t * qinfo)893148c5f43SAlan Wright smb_query_shortname(smb_node_t *node, smb_queryinfo_t *qinfo)
894148c5f43SAlan Wright {
895148c5f43SAlan Wright char *namep;
896148c5f43SAlan Wright
8979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (SMB_IS_STREAM(node))
8989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States namep = node->n_unode->od_name;
8999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States else
9009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States namep = node->od_name;
9019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
902148c5f43SAlan Wright if (smb_needs_mangled(namep)) {
903148c5f43SAlan Wright smb_mangle(namep, qinfo->qi_attr.sa_vattr.va_nodeid,
904148c5f43SAlan Wright qinfo->qi_shortname, SMB_SHORTNAMELEN);
905148c5f43SAlan Wright } else {
906cb174861Sjoyce mcintosh (void) strlcpy(qinfo->qi_shortname, namep, SMB_SHORTNAMELEN);
907bbf6f00cSJordan Brown (void) smb_strupr(qinfo->qi_shortname);
908e3f2c991SKeyur Desai }
909e3f2c991SKeyur Desai }
910e3f2c991SKeyur Desai
911e3f2c991SKeyur Desai /*
912e3f2c991SKeyur Desai * smb_query_pipeinfo
913e3f2c991SKeyur Desai *
914e3f2c991SKeyur Desai * Populate smb_queryinfo_t structure for SMB_FTYPE_MESG_PIPE
915e3f2c991SKeyur Desai * (This should become an smb_opipe function.)
916e3f2c991SKeyur Desai */
917e3f2c991SKeyur Desai static int
smb_query_pipeinfo(smb_request_t * sr,smb_opipe_t * opipe,uint16_t infolev,smb_queryinfo_t * qinfo)918e3f2c991SKeyur Desai smb_query_pipeinfo(smb_request_t *sr, smb_opipe_t *opipe, uint16_t infolev,
919e3f2c991SKeyur Desai smb_queryinfo_t *qinfo)
920e3f2c991SKeyur Desai {
921e3f2c991SKeyur Desai char *namep = opipe->p_name;
922e3f2c991SKeyur Desai
923e3f2c991SKeyur Desai (void) bzero(qinfo, sizeof (smb_queryinfo_t));
924e3f2c991SKeyur Desai qinfo->qi_node = NULL;
925e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nlink = 1;
926e3f2c991SKeyur Desai qinfo->qi_delete_on_close = 1;
927a90cf9f2SGordon Ross qinfo->qi_isdir = 0;
928e3f2c991SKeyur Desai
929e3f2c991SKeyur Desai if ((infolev == SMB_INFO_STANDARD) ||
930e3f2c991SKeyur Desai (infolev == SMB_INFO_QUERY_EA_SIZE) ||
931e3f2c991SKeyur Desai (infolev == SMB_QUERY_INFORMATION2)) {
932e3f2c991SKeyur Desai qinfo->qi_attr.sa_dosattr = 0;
933e3f2c991SKeyur Desai } else {
934e3f2c991SKeyur Desai qinfo->qi_attr.sa_dosattr = FILE_ATTRIBUTE_NORMAL;
935e3f2c991SKeyur Desai }
936e3f2c991SKeyur Desai
937e3f2c991SKeyur Desai /* If the leading \ is missing from the pipe name, add it. */
938e3f2c991SKeyur Desai if (*namep != '\\')
939e3f2c991SKeyur Desai (void) snprintf(qinfo->qi_name, MAXNAMELEN, "\\%s", namep);
940e3f2c991SKeyur Desai else
941e3f2c991SKeyur Desai (void) strlcpy(qinfo->qi_name, namep, MAXNAMELEN);
942e3f2c991SKeyur Desai
943e3f2c991SKeyur Desai qinfo->qi_namelen=
944e3f2c991SKeyur Desai smb_ascii_or_unicode_strlen(sr, qinfo->qi_name);
945e3f2c991SKeyur Desai
946e3f2c991SKeyur Desai return (0);
947e3f2c991SKeyur Desai }
948e3f2c991SKeyur Desai
949e3f2c991SKeyur Desai /*
950e3f2c991SKeyur Desai * smb_query_pipe_valid_infolev
951e3f2c991SKeyur Desai *
952e3f2c991SKeyur Desai * If the infolev is not valid for a message pipe, the error
953e3f2c991SKeyur Desai * information is set in sr and B_FALSE is returned.
954e3f2c991SKeyur Desai * Otherwise, returns B_TRUE.
955e3f2c991SKeyur Desai */
956e3f2c991SKeyur Desai static boolean_t
smb_query_pipe_valid_infolev(smb_request_t * sr,uint16_t infolev)957e3f2c991SKeyur Desai smb_query_pipe_valid_infolev(smb_request_t *sr, uint16_t infolev)
958e3f2c991SKeyur Desai {
959e3f2c991SKeyur Desai switch (infolev) {
960e3f2c991SKeyur Desai case SMB_INFO_QUERY_ALL_EAS:
961e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
962e3f2c991SKeyur Desai ERRDOS, ERROR_ACCESS_DENIED);
963e3f2c991SKeyur Desai return (B_FALSE);
964e3f2c991SKeyur Desai
965e3f2c991SKeyur Desai case SMB_QUERY_FILE_ALT_NAME_INFO:
966e3f2c991SKeyur Desai case SMB_FILE_ALT_NAME_INFORMATION:
967e3f2c991SKeyur Desai case SMB_QUERY_FILE_STREAM_INFO:
968e3f2c991SKeyur Desai case SMB_FILE_STREAM_INFORMATION:
969e3f2c991SKeyur Desai case SMB_QUERY_FILE_COMPRESSION_INFO:
970e3f2c991SKeyur Desai case SMB_FILE_COMPRESSION_INFORMATION:
9719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_FILE_NETWORK_OPEN_INFORMATION:
972e3f2c991SKeyur Desai case SMB_FILE_ATTR_TAG_INFORMATION:
973e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
974e3f2c991SKeyur Desai ERRDOS, ERROR_INVALID_PARAMETER);
975e3f2c991SKeyur Desai return (B_FALSE);
976e3f2c991SKeyur Desai }
977e3f2c991SKeyur Desai
978e3f2c991SKeyur Desai return (B_TRUE);
979e3f2c991SKeyur Desai }
980