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. 245fd03bc0SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 25e3f2c991SKeyur Desai */ 26e3f2c991SKeyur Desai 27bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 28e3f2c991SKeyur Desai #include <smbsrv/smb_vops.h> 29e3f2c991SKeyur Desai #include <smbsrv/smb_fsops.h> 30e3f2c991SKeyur Desai 31e3f2c991SKeyur Desai /* 32e3f2c991SKeyur Desai * Trans2 Query File/Path Information Levels: 33e3f2c991SKeyur Desai * 34e3f2c991SKeyur Desai * SMB_INFO_STANDARD 35e3f2c991SKeyur Desai * SMB_INFO_QUERY_EA_SIZE 36e3f2c991SKeyur Desai * SMB_INFO_QUERY_EAS_FROM_LIST 37e3f2c991SKeyur Desai * SMB_INFO_QUERY_ALL_EAS - not valid for pipes 38e3f2c991SKeyur Desai * SMB_INFO_IS_NAME_VALID - only valid when query is by path 39e3f2c991SKeyur Desai * 40e3f2c991SKeyur Desai * SMB_QUERY_FILE_BASIC_INFO 41e3f2c991SKeyur Desai * SMB_QUERY_FILE_STANDARD_INFO 42e3f2c991SKeyur Desai * SMB_QUERY_FILE_EA_INFO 43e3f2c991SKeyur Desai * SMB_QUERY_FILE_NAME_INFO 44e3f2c991SKeyur Desai * SMB_QUERY_FILE_ALL_INFO 45e3f2c991SKeyur Desai * SMB_QUERY_FILE_ALT_NAME_INFO - not valid for pipes 46e3f2c991SKeyur Desai * SMB_QUERY_FILE_STREAM_INFO - not valid for pipes 47e3f2c991SKeyur Desai * SMB_QUERY_FILE_COMPRESSION_INFO - not valid for pipes 48e3f2c991SKeyur Desai * 49e3f2c991SKeyur Desai * Supported Passthrough levels: 50e3f2c991SKeyur Desai * SMB_FILE_BASIC_INFORMATION 51e3f2c991SKeyur Desai * SMB_FILE_STANDARD_INFORMATION 52e3f2c991SKeyur Desai * SMB_FILE_INTERNAL_INFORMATION 53e3f2c991SKeyur Desai * SMB_FILE_EA_INFORMATION 54cb174861Sjoyce mcintosh * SMB_FILE_ACCESS_INFORMATION - not yet supported when query by path 55e3f2c991SKeyur Desai * SMB_FILE_NAME_INFORMATION 56e3f2c991SKeyur Desai * SMB_FILE_ALL_INFORMATION 57e3f2c991SKeyur Desai * SMB_FILE_ALT_NAME_INFORMATION - not valid for pipes 58e3f2c991SKeyur Desai * SMB_FILE_STREAM_INFORMATION - not valid for pipes 59e3f2c991SKeyur Desai * SMB_FILE_COMPRESSION_INFORMATION - not valid for pipes 609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * SMB_FILE_NETWORK_OPEN_INFORMATION - not valid for pipes 61e3f2c991SKeyur Desai * SMB_FILE_ATTR_TAG_INFORMATION - not valid for pipes 62e3f2c991SKeyur Desai * 63e3f2c991SKeyur Desai * Internal levels representing non trans2 requests 64e3f2c991SKeyur Desai * SMB_QUERY_INFORMATION 65e3f2c991SKeyur Desai * SMB_QUERY_INFORMATION2 66e3f2c991SKeyur Desai */ 67e3f2c991SKeyur Desai 68cb174861Sjoyce mcintosh /* 69cb174861Sjoyce mcintosh * SMB_STREAM_ENCODE_FIXED_SIZE: 70cb174861Sjoyce mcintosh * 2 dwords + 2 quadwords => 4 + 4 + 8 + 8 => 24 71cb174861Sjoyce mcintosh */ 72cb174861Sjoyce mcintosh #define SMB_STREAM_ENCODE_FIXED_SZ 24 73cb174861Sjoyce mcintosh 74*a90cf9f2SGordon Ross /* See smb_queryinfo_t in smb_ktypes.h */ 75e3f2c991SKeyur Desai #define qi_mtime qi_attr.sa_vattr.va_mtime 76e3f2c991SKeyur Desai #define qi_ctime qi_attr.sa_vattr.va_ctime 77e3f2c991SKeyur Desai #define qi_atime qi_attr.sa_vattr.va_atime 78e3f2c991SKeyur Desai #define qi_crtime qi_attr.sa_crtime 79e3f2c991SKeyur Desai 80e3f2c991SKeyur Desai static int smb_query_by_fid(smb_request_t *, smb_xa_t *, uint16_t); 819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_query_by_path(smb_request_t *, smb_xa_t *, uint16_t); 82e3f2c991SKeyur Desai 83e3f2c991SKeyur Desai static int smb_query_fileinfo(smb_request_t *, smb_node_t *, 84e3f2c991SKeyur Desai uint16_t, smb_queryinfo_t *); 85e3f2c991SKeyur Desai static int smb_query_pipeinfo(smb_request_t *, smb_opipe_t *, 86e3f2c991SKeyur Desai uint16_t, smb_queryinfo_t *); 87e3f2c991SKeyur Desai static boolean_t smb_query_pipe_valid_infolev(smb_request_t *, uint16_t); 88e3f2c991SKeyur Desai 89e3f2c991SKeyur Desai static int smb_query_encode_response(smb_request_t *, smb_xa_t *, 90e3f2c991SKeyur Desai uint16_t, smb_queryinfo_t *); 91*a90cf9f2SGordon Ross static boolean_t smb_stream_fits(smb_request_t *, mbuf_chain_t *, 92*a90cf9f2SGordon Ross char *, uint32_t); 93148c5f43SAlan Wright static int smb_query_pathname(smb_request_t *, smb_node_t *, boolean_t, 94148c5f43SAlan Wright smb_queryinfo_t *); 95e3f2c991SKeyur Desai 969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int smb_query_passthru; 97e3f2c991SKeyur Desai 98e3f2c991SKeyur Desai /* 99e3f2c991SKeyur Desai * smb_com_trans2_query_file_information 100e3f2c991SKeyur Desai */ 101e3f2c991SKeyur Desai smb_sdrc_t 102e3f2c991SKeyur Desai smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) 103e3f2c991SKeyur Desai { 104e3f2c991SKeyur Desai uint16_t infolev; 105e3f2c991SKeyur Desai 106e3f2c991SKeyur Desai if (smb_mbc_decodef(&xa->req_param_mb, "ww", 107e3f2c991SKeyur Desai &sr->smb_fid, &infolev) != 0) 108e3f2c991SKeyur Desai return (SDRC_ERROR); 109e3f2c991SKeyur Desai 110e3f2c991SKeyur Desai if (smb_query_by_fid(sr, xa, infolev) != 0) 111e3f2c991SKeyur Desai return (SDRC_ERROR); 112e3f2c991SKeyur Desai 113e3f2c991SKeyur Desai return (SDRC_SUCCESS); 114e3f2c991SKeyur Desai } 115e3f2c991SKeyur Desai 116e3f2c991SKeyur Desai /* 117e3f2c991SKeyur Desai * smb_com_trans2_query_path_information 118e3f2c991SKeyur Desai */ 119e3f2c991SKeyur Desai smb_sdrc_t 120e3f2c991SKeyur Desai smb_com_trans2_query_path_information(smb_request_t *sr, smb_xa_t *xa) 121e3f2c991SKeyur Desai { 122e3f2c991SKeyur Desai uint16_t infolev; 1239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_fqi_t *fqi = &sr->arg.dirop.fqi; 124e3f2c991SKeyur Desai 125f96bd5c8SAlan Wright if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 126e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST, 127e3f2c991SKeyur Desai ERRDOS, ERROR_INVALID_FUNCTION); 128e3f2c991SKeyur Desai return (SDRC_ERROR); 129e3f2c991SKeyur Desai } 130e3f2c991SKeyur Desai 131e3f2c991SKeyur Desai if (smb_mbc_decodef(&xa->req_param_mb, "%w4.u", 1329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States sr, &infolev, &fqi->fq_path.pn_path) != 0) 133e3f2c991SKeyur Desai return (SDRC_ERROR); 134e3f2c991SKeyur Desai 1359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_query_by_path(sr, xa, infolev) != 0) 136e3f2c991SKeyur Desai return (SDRC_ERROR); 137e3f2c991SKeyur Desai 138e3f2c991SKeyur Desai return (SDRC_SUCCESS); 139e3f2c991SKeyur Desai } 140e3f2c991SKeyur Desai 141e3f2c991SKeyur Desai /* 142e3f2c991SKeyur Desai * smb_com_query_information (aka getattr) 143e3f2c991SKeyur Desai */ 144e3f2c991SKeyur Desai smb_sdrc_t 145e3f2c991SKeyur Desai smb_pre_query_information(smb_request_t *sr) 146e3f2c991SKeyur Desai { 147e3f2c991SKeyur Desai int rc; 148e3f2c991SKeyur Desai smb_fqi_t *fqi = &sr->arg.dirop.fqi; 149e3f2c991SKeyur Desai 150e3f2c991SKeyur Desai rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path); 151e3f2c991SKeyur Desai 152e3f2c991SKeyur Desai DTRACE_SMB_2(op__QueryInformation__start, smb_request_t *, sr, 153e3f2c991SKeyur Desai smb_fqi_t *, fqi); 154e3f2c991SKeyur Desai 155e3f2c991SKeyur Desai return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 156e3f2c991SKeyur Desai } 157e3f2c991SKeyur Desai 158e3f2c991SKeyur Desai void 159e3f2c991SKeyur Desai smb_post_query_information(smb_request_t *sr) 160e3f2c991SKeyur Desai { 161e3f2c991SKeyur Desai DTRACE_SMB_1(op__QueryInformation__done, smb_request_t *, sr); 162e3f2c991SKeyur Desai } 163e3f2c991SKeyur Desai 164e3f2c991SKeyur Desai smb_sdrc_t 165e3f2c991SKeyur Desai smb_com_query_information(smb_request_t *sr) 166e3f2c991SKeyur Desai { 167e3f2c991SKeyur Desai uint16_t infolev = SMB_QUERY_INFORMATION; 168e3f2c991SKeyur Desai 169f96bd5c8SAlan Wright if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 170e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 171e3f2c991SKeyur Desai ERRDOS, ERROR_ACCESS_DENIED); 172e3f2c991SKeyur Desai return (SDRC_ERROR); 173e3f2c991SKeyur Desai } 174e3f2c991SKeyur Desai 1759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_query_by_path(sr, NULL, infolev) != 0) 176e3f2c991SKeyur Desai return (SDRC_ERROR); 177e3f2c991SKeyur Desai 178e3f2c991SKeyur Desai return (SDRC_SUCCESS); 179e3f2c991SKeyur Desai } 180e3f2c991SKeyur Desai 181e3f2c991SKeyur Desai /* 182e3f2c991SKeyur Desai * smb_com_query_information2 (aka getattre) 183e3f2c991SKeyur Desai */ 184e3f2c991SKeyur Desai smb_sdrc_t 185e3f2c991SKeyur Desai smb_pre_query_information2(smb_request_t *sr) 186e3f2c991SKeyur Desai { 187e3f2c991SKeyur Desai int rc; 188e3f2c991SKeyur Desai rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid); 189e3f2c991SKeyur Desai 190e3f2c991SKeyur Desai DTRACE_SMB_1(op__QueryInformation2__start, smb_request_t *, sr); 191e3f2c991SKeyur Desai 192e3f2c991SKeyur Desai return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 193e3f2c991SKeyur Desai } 194e3f2c991SKeyur Desai 195e3f2c991SKeyur Desai void 196e3f2c991SKeyur Desai smb_post_query_information2(smb_request_t *sr) 197e3f2c991SKeyur Desai { 198e3f2c991SKeyur Desai DTRACE_SMB_1(op__QueryInformation2__done, smb_request_t *, sr); 199e3f2c991SKeyur Desai } 200e3f2c991SKeyur Desai 201e3f2c991SKeyur Desai smb_sdrc_t 202e3f2c991SKeyur Desai smb_com_query_information2(smb_request_t *sr) 203e3f2c991SKeyur Desai { 204e3f2c991SKeyur Desai uint16_t infolev = SMB_QUERY_INFORMATION2; 205e3f2c991SKeyur Desai 206e3f2c991SKeyur Desai if (smb_query_by_fid(sr, NULL, infolev) != 0) 207e3f2c991SKeyur Desai return (SDRC_ERROR); 208e3f2c991SKeyur Desai 209e3f2c991SKeyur Desai return (SDRC_SUCCESS); 210e3f2c991SKeyur Desai } 211e3f2c991SKeyur Desai 212e3f2c991SKeyur Desai /* 213e3f2c991SKeyur Desai * smb_query_by_fid 214e3f2c991SKeyur Desai * 215e3f2c991SKeyur Desai * Common code for querying file information by open file (or pipe) id. 216e3f2c991SKeyur Desai * Use the id to identify the node / pipe object and request the 217e3f2c991SKeyur Desai * smb_queryinfo_t data for that object. 218e3f2c991SKeyur Desai */ 219e3f2c991SKeyur Desai static int 220e3f2c991SKeyur Desai smb_query_by_fid(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev) 221e3f2c991SKeyur Desai { 222e3f2c991SKeyur Desai int rc; 223e3f2c991SKeyur Desai smb_queryinfo_t *qinfo; 224e3f2c991SKeyur Desai smb_node_t *node; 225e3f2c991SKeyur Desai smb_opipe_t *opipe; 226e3f2c991SKeyur Desai 227e3f2c991SKeyur Desai smbsr_lookup_file(sr); 228e3f2c991SKeyur Desai 229e3f2c991SKeyur Desai if (sr->fid_ofile == NULL) { 230e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 231e3f2c991SKeyur Desai return (-1); 232e3f2c991SKeyur Desai } 233e3f2c991SKeyur Desai 234e3f2c991SKeyur Desai if (infolev == SMB_INFO_IS_NAME_VALID) { 235148c5f43SAlan Wright smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL); 236e3f2c991SKeyur Desai smbsr_release_file(sr); 237e3f2c991SKeyur Desai return (-1); 238e3f2c991SKeyur Desai } 239e3f2c991SKeyur Desai 240e3f2c991SKeyur Desai if ((sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE) && 241e3f2c991SKeyur Desai (!smb_query_pipe_valid_infolev(sr, infolev))) { 242e3f2c991SKeyur Desai smbsr_release_file(sr); 243e3f2c991SKeyur Desai return (-1); 244e3f2c991SKeyur Desai } 245e3f2c991SKeyur Desai 2465fd03bc0SGordon Ross sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 247e3f2c991SKeyur Desai qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP); 248e3f2c991SKeyur Desai 249e3f2c991SKeyur Desai switch (sr->fid_ofile->f_ftype) { 250e3f2c991SKeyur Desai case SMB_FTYPE_DISK: 251e3f2c991SKeyur Desai node = sr->fid_ofile->f_node; 252e3f2c991SKeyur Desai rc = smb_query_fileinfo(sr, node, infolev, qinfo); 253e3f2c991SKeyur Desai break; 254e3f2c991SKeyur Desai case SMB_FTYPE_MESG_PIPE: 255e3f2c991SKeyur Desai opipe = sr->fid_ofile->f_pipe; 256e3f2c991SKeyur Desai rc = smb_query_pipeinfo(sr, opipe, infolev, qinfo); 257e3f2c991SKeyur Desai break; 258e3f2c991SKeyur Desai default: 259e3f2c991SKeyur Desai smbsr_error(sr, 0, ERRDOS, ERRbadfile); 260e3f2c991SKeyur Desai rc = -1; 261e3f2c991SKeyur Desai break; 262e3f2c991SKeyur Desai } 263e3f2c991SKeyur Desai 264e3f2c991SKeyur Desai if (rc == 0) 265e3f2c991SKeyur Desai rc = smb_query_encode_response(sr, xa, infolev, qinfo); 266e3f2c991SKeyur Desai 267e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t)); 268e3f2c991SKeyur Desai smbsr_release_file(sr); 269e3f2c991SKeyur Desai return (rc); 270e3f2c991SKeyur Desai } 271e3f2c991SKeyur Desai 272e3f2c991SKeyur Desai /* 273e3f2c991SKeyur Desai * smb_query_by_path 274e3f2c991SKeyur Desai * 275e3f2c991SKeyur Desai * Common code for querying file information by file name. 276e3f2c991SKeyur Desai * Use the file name to identify the node object and request the 277e3f2c991SKeyur Desai * smb_queryinfo_t data for that node. 278e3f2c991SKeyur Desai * 2799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Path should be set in sr->arg.dirop.fqi.fq_path prior to 2809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * calling smb_query_by_path. 2819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * 282e3f2c991SKeyur Desai * Querying attributes on a named pipe by name is an error and 283e3f2c991SKeyur Desai * is handled in the calling functions so that they can return 284e3f2c991SKeyur Desai * the appropriate error status code (which differs by caller). 285e3f2c991SKeyur Desai */ 286e3f2c991SKeyur Desai static int 2879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_query_by_path(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev) 288e3f2c991SKeyur Desai { 289e3f2c991SKeyur Desai smb_queryinfo_t *qinfo; 290e3f2c991SKeyur Desai smb_node_t *node, *dnode; 2919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_t *pn; 292e3f2c991SKeyur Desai int rc; 293e3f2c991SKeyur Desai 2945fd03bc0SGordon Ross /* 2955fd03bc0SGordon Ross * The function smb_query_fileinfo is used here and in 2965fd03bc0SGordon Ross * smb_query_by_fid. That common function needs this 2975fd03bc0SGordon Ross * one to call it with a NULL fid_ofile, so check here. 2985fd03bc0SGordon Ross * Note: smb_query_by_fid enforces the opposite. 2995fd03bc0SGordon Ross * 3005fd03bc0SGordon Ross * In theory we could ASSERT this, but whether we have 3015fd03bc0SGordon Ross * fid_ofile set here depends on what sequence of SMB 3025fd03bc0SGordon Ross * commands the client has sent in this message, so 3035fd03bc0SGordon Ross * let's be cautious and handle it as an error. 3045fd03bc0SGordon Ross */ 3055fd03bc0SGordon Ross if (sr->fid_ofile != NULL) 3065fd03bc0SGordon Ross return (-1); 3075fd03bc0SGordon Ross 3085fd03bc0SGordon Ross 309e3f2c991SKeyur Desai /* VALID, but not yet supported */ 310e3f2c991SKeyur Desai if (infolev == SMB_FILE_ACCESS_INFORMATION) { 311148c5f43SAlan Wright smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL); 312e3f2c991SKeyur Desai return (-1); 313e3f2c991SKeyur Desai } 314e3f2c991SKeyur Desai 3159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States pn = &sr->arg.dirop.fqi.fq_path; 3169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_init(sr, pn, pn->pn_path); 3179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (!smb_pathname_validate(sr, pn)) 3189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (-1); 319e3f2c991SKeyur Desai 320e3f2c991SKeyur Desai qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP); 321e3f2c991SKeyur Desai 3229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path, 3239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode, 3249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States qinfo->qi_name); 3259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 326e3f2c991SKeyur Desai if (rc == 0) { 327e3f2c991SKeyur Desai rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS, 328e3f2c991SKeyur Desai sr->tid_tree->t_snode, dnode, qinfo->qi_name, &node); 329e3f2c991SKeyur Desai smb_node_release(dnode); 330e3f2c991SKeyur Desai } 331e3f2c991SKeyur Desai 332e3f2c991SKeyur Desai if (rc != 0) { 333e3f2c991SKeyur Desai if (rc == ENOENT) 334e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 335e3f2c991SKeyur Desai ERRDOS, ERROR_FILE_NOT_FOUND); 336e3f2c991SKeyur Desai else 337e3f2c991SKeyur Desai smbsr_errno(sr, rc); 338e3f2c991SKeyur Desai 339e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t)); 340e3f2c991SKeyur Desai return (-1); 341e3f2c991SKeyur Desai } 342e3f2c991SKeyur Desai 3439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) { 3449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); 3459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States kmem_free(qinfo, sizeof (smb_queryinfo_t)); 3469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_release(node); 3479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (-1); 3489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 3499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 350e3f2c991SKeyur Desai rc = smb_query_fileinfo(sr, node, infolev, qinfo); 351e3f2c991SKeyur Desai if (rc != 0) { 352e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t)); 353e3f2c991SKeyur Desai smb_node_release(node); 354e3f2c991SKeyur Desai return (rc); 355e3f2c991SKeyur Desai } 356e3f2c991SKeyur Desai 357e3f2c991SKeyur Desai /* If delete_on_close - NT_STATUS_DELETE_PENDING */ 358e3f2c991SKeyur Desai if (qinfo->qi_delete_on_close) { 359e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_DELETE_PENDING, 360e3f2c991SKeyur Desai ERRDOS, ERROR_ACCESS_DENIED); 361e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t)); 362e3f2c991SKeyur Desai smb_node_release(node); 363e3f2c991SKeyur Desai return (-1); 364e3f2c991SKeyur Desai } 365e3f2c991SKeyur Desai 366e3f2c991SKeyur Desai rc = smb_query_encode_response(sr, xa, infolev, qinfo); 367e3f2c991SKeyur Desai kmem_free(qinfo, sizeof (smb_queryinfo_t)); 368e3f2c991SKeyur Desai smb_node_release(node); 369e3f2c991SKeyur Desai return (rc); 370e3f2c991SKeyur Desai } 371e3f2c991SKeyur Desai 372e3f2c991SKeyur Desai /* 373e3f2c991SKeyur Desai * smb_size32 374e3f2c991SKeyur Desai * Some responses only support 32 bit file sizes. If the file size 375e3f2c991SKeyur Desai * exceeds UINT_MAX (32 bit) we return UINT_MAX in the response. 376e3f2c991SKeyur Desai */ 377e3f2c991SKeyur Desai static uint32_t 378e3f2c991SKeyur Desai smb_size32(u_offset_t size) 379e3f2c991SKeyur Desai { 380e3f2c991SKeyur Desai return ((size > UINT_MAX) ? UINT_MAX : (uint32_t)size); 381e3f2c991SKeyur Desai } 382e3f2c991SKeyur Desai 383e3f2c991SKeyur Desai /* 384e3f2c991SKeyur Desai * smb_query_encode_response 385e3f2c991SKeyur Desai * 386e3f2c991SKeyur Desai * Encode the data from smb_queryinfo_t into client response 387e3f2c991SKeyur Desai */ 388e3f2c991SKeyur Desai int 389e3f2c991SKeyur Desai smb_query_encode_response(smb_request_t *sr, smb_xa_t *xa, 390e3f2c991SKeyur Desai uint16_t infolev, smb_queryinfo_t *qinfo) 391e3f2c991SKeyur Desai { 392e3f2c991SKeyur Desai uint16_t dattr; 393e3f2c991SKeyur Desai u_offset_t datasz, allocsz; 394*a90cf9f2SGordon Ross uint32_t status; 395e3f2c991SKeyur Desai 396e3f2c991SKeyur Desai dattr = qinfo->qi_attr.sa_dosattr & FILE_ATTRIBUTE_MASK; 397e3f2c991SKeyur Desai datasz = qinfo->qi_attr.sa_vattr.va_size; 398e3f2c991SKeyur Desai allocsz = qinfo->qi_attr.sa_allocsz; 399e3f2c991SKeyur Desai 400e3f2c991SKeyur Desai switch (infolev) { 401e3f2c991SKeyur Desai case SMB_QUERY_INFORMATION: 402e3f2c991SKeyur Desai (void) smbsr_encode_result(sr, 10, 0, "bwll10.w", 403e3f2c991SKeyur Desai 10, 404e3f2c991SKeyur Desai dattr, 405e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 406e3f2c991SKeyur Desai smb_size32(datasz), 407e3f2c991SKeyur Desai 0); 408e3f2c991SKeyur Desai break; 409e3f2c991SKeyur Desai 410e3f2c991SKeyur Desai case SMB_QUERY_INFORMATION2: 411e3f2c991SKeyur Desai (void) smbsr_encode_result(sr, 11, 0, "byyyllww", 412e3f2c991SKeyur Desai 11, 413e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec), 414e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec), 415e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 416e3f2c991SKeyur Desai smb_size32(datasz), smb_size32(allocsz), dattr, 0); 417e3f2c991SKeyur Desai break; 418e3f2c991SKeyur Desai 419e3f2c991SKeyur Desai case SMB_FILE_ACCESS_INFORMATION: 420e3f2c991SKeyur Desai ASSERT(sr->fid_ofile); 421e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 422e3f2c991SKeyur Desai sr->fid_ofile->f_granted_access); 423e3f2c991SKeyur Desai break; 424e3f2c991SKeyur Desai 425e3f2c991SKeyur Desai case SMB_INFO_STANDARD: 426e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 427e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, 428e3f2c991SKeyur Desai ((sr->session->native_os == NATIVE_OS_WIN95) ? 429e3f2c991SKeyur Desai "YYYllw" : "yyyllw"), 430e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec), 431e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec), 432e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 433e3f2c991SKeyur Desai smb_size32(datasz), smb_size32(allocsz), dattr); 434e3f2c991SKeyur Desai break; 435e3f2c991SKeyur Desai 436e3f2c991SKeyur Desai case SMB_INFO_QUERY_EA_SIZE: 437e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 438e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, 439e3f2c991SKeyur Desai ((sr->session->native_os == NATIVE_OS_WIN95) ? 440e3f2c991SKeyur Desai "YYYllwl" : "yyyllwl"), 441e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec), 442e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec), 443e3f2c991SKeyur Desai smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 444e3f2c991SKeyur Desai smb_size32(datasz), smb_size32(allocsz), dattr, 0); 445e3f2c991SKeyur Desai break; 446e3f2c991SKeyur Desai 447e3f2c991SKeyur Desai case SMB_INFO_QUERY_ALL_EAS: 448e3f2c991SKeyur Desai case SMB_INFO_QUERY_EAS_FROM_LIST: 449e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 450e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 451e3f2c991SKeyur Desai break; 452e3f2c991SKeyur Desai 453e3f2c991SKeyur Desai case SMB_INFO_IS_NAME_VALID: 454e3f2c991SKeyur Desai break; 455e3f2c991SKeyur Desai 456e3f2c991SKeyur Desai case SMB_QUERY_FILE_BASIC_INFO: 457e3f2c991SKeyur Desai case SMB_FILE_BASIC_INFORMATION: 458e3f2c991SKeyur Desai /* 459e3f2c991SKeyur Desai * NT includes 6 bytes (spec says 4) at the end of this 460e3f2c991SKeyur Desai * response, which are required by NetBench 5.01. 461e3f2c991SKeyur Desai */ 462e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 463e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.", 464e3f2c991SKeyur Desai &qinfo->qi_crtime, 465e3f2c991SKeyur Desai &qinfo->qi_atime, 466e3f2c991SKeyur Desai &qinfo->qi_mtime, 467e3f2c991SKeyur Desai &qinfo->qi_ctime, 468e3f2c991SKeyur Desai dattr); 469e3f2c991SKeyur Desai break; 470e3f2c991SKeyur Desai 471e3f2c991SKeyur Desai case SMB_QUERY_FILE_STANDARD_INFO: 472e3f2c991SKeyur Desai case SMB_FILE_STANDARD_INFORMATION: 473e3f2c991SKeyur Desai /* 2-byte pad at end */ 474e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 475e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "qqlbb2.", 476e3f2c991SKeyur Desai (uint64_t)allocsz, 477e3f2c991SKeyur Desai (uint64_t)datasz, 478e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nlink, 479e3f2c991SKeyur Desai qinfo->qi_delete_on_close, 480*a90cf9f2SGordon Ross qinfo->qi_isdir); 481e3f2c991SKeyur Desai break; 482e3f2c991SKeyur Desai 483e3f2c991SKeyur Desai case SMB_QUERY_FILE_EA_INFO: 484e3f2c991SKeyur Desai case SMB_FILE_EA_INFORMATION: 485e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 486e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 487e3f2c991SKeyur Desai break; 488e3f2c991SKeyur Desai 489e3f2c991SKeyur Desai case SMB_QUERY_FILE_NAME_INFO: 490e3f2c991SKeyur Desai case SMB_FILE_NAME_INFORMATION: 491e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 492e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", sr, 493e3f2c991SKeyur Desai qinfo->qi_namelen, qinfo->qi_name); 494e3f2c991SKeyur Desai break; 495e3f2c991SKeyur Desai 496e3f2c991SKeyur Desai case SMB_QUERY_FILE_ALL_INFO: 497e3f2c991SKeyur Desai case SMB_FILE_ALL_INFORMATION: 498e3f2c991SKeyur Desai /* 499e3f2c991SKeyur Desai * There is a 6-byte pad between Attributes and AllocationSize, 500e3f2c991SKeyur Desai * and a 2-byte pad after the Directory field. 501e3f2c991SKeyur Desai */ 502e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 503e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.qqlbb2.l", 504e3f2c991SKeyur Desai &qinfo->qi_crtime, 505e3f2c991SKeyur Desai &qinfo->qi_atime, 506e3f2c991SKeyur Desai &qinfo->qi_mtime, 507e3f2c991SKeyur Desai &qinfo->qi_ctime, 508e3f2c991SKeyur Desai dattr, 509e3f2c991SKeyur Desai (uint64_t)allocsz, 510e3f2c991SKeyur Desai (uint64_t)datasz, 511e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nlink, 512e3f2c991SKeyur Desai qinfo->qi_delete_on_close, 513*a90cf9f2SGordon Ross qinfo->qi_isdir, 514e3f2c991SKeyur Desai 0); 515e3f2c991SKeyur Desai 516e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", 517e3f2c991SKeyur Desai sr, qinfo->qi_namelen, qinfo->qi_name); 518e3f2c991SKeyur Desai break; 519e3f2c991SKeyur Desai 520e3f2c991SKeyur Desai case SMB_QUERY_FILE_ALT_NAME_INFO: 521e3f2c991SKeyur Desai case SMB_FILE_ALT_NAME_INFORMATION: 522e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 523e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "%lU", sr, 524bbf6f00cSJordan Brown smb_wcequiv_strlen(qinfo->qi_shortname), 525e3f2c991SKeyur Desai qinfo->qi_shortname); 526e3f2c991SKeyur Desai break; 527e3f2c991SKeyur Desai 528e3f2c991SKeyur Desai case SMB_QUERY_FILE_STREAM_INFO: 529e3f2c991SKeyur Desai case SMB_FILE_STREAM_INFORMATION: 530e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 531*a90cf9f2SGordon Ross status = smb_query_stream_info(sr, &xa->rep_data_mb, qinfo); 532*a90cf9f2SGordon Ross if (status) 533*a90cf9f2SGordon Ross smbsr_status(sr, status, 0, 0); 534e3f2c991SKeyur Desai break; 535e3f2c991SKeyur Desai 536e3f2c991SKeyur Desai case SMB_QUERY_FILE_COMPRESSION_INFO: 537e3f2c991SKeyur Desai case SMB_FILE_COMPRESSION_INFORMATION: 538e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 539e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "qwbbb3.", 540e3f2c991SKeyur Desai datasz, 0, 0, 0, 0); 541e3f2c991SKeyur Desai break; 542e3f2c991SKeyur Desai 543e3f2c991SKeyur Desai case SMB_FILE_INTERNAL_INFORMATION: 544e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 545e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "q", 546e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nodeid); 547e3f2c991SKeyur Desai break; 548e3f2c991SKeyur Desai 5499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_FILE_NETWORK_OPEN_INFORMATION: 5509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 5519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTqql4.", 5529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &qinfo->qi_crtime, 5539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &qinfo->qi_atime, 5549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &qinfo->qi_mtime, 5559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &qinfo->qi_ctime, 5569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (uint64_t)allocsz, 5579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (uint64_t)datasz, 5589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (uint32_t)dattr); 5599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 5609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 561e3f2c991SKeyur Desai case SMB_FILE_ATTR_TAG_INFORMATION: 562e3f2c991SKeyur Desai /* 563e3f2c991SKeyur Desai * If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the 564e3f2c991SKeyur Desai * second dword should be the reparse tag. Otherwise 565e3f2c991SKeyur Desai * the tag value should be set to zero. 566e3f2c991SKeyur Desai * We don't support reparse points, so we set the tag 567e3f2c991SKeyur Desai * to zero. 568e3f2c991SKeyur Desai */ 569e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 570e3f2c991SKeyur Desai (void) smb_mbc_encodef(&xa->rep_data_mb, "ll", 571e3f2c991SKeyur Desai (uint32_t)dattr, 0); 572e3f2c991SKeyur Desai break; 573e3f2c991SKeyur Desai 574e3f2c991SKeyur Desai default: 5759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((infolev > 1000) && smb_query_passthru) 5769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, 5779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ERRDOS, ERROR_NOT_SUPPORTED); 5789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States else 579148c5f43SAlan Wright smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL); 580e3f2c991SKeyur Desai return (-1); 581e3f2c991SKeyur Desai } 582e3f2c991SKeyur Desai 583e3f2c991SKeyur Desai return (0); 584e3f2c991SKeyur Desai } 585e3f2c991SKeyur Desai 586e3f2c991SKeyur Desai /* 587e3f2c991SKeyur Desai * smb_encode_stream_info 588e3f2c991SKeyur Desai * 589e3f2c991SKeyur Desai * This function encodes the streams information. 590e3f2c991SKeyur Desai * The following rules about how have been derived from observed NT 591e3f2c991SKeyur Desai * behaviour. 592e3f2c991SKeyur Desai * 593e3f2c991SKeyur Desai * If the target is a file: 594e3f2c991SKeyur Desai * 1. If there are no named streams, the response should still contain 595e3f2c991SKeyur Desai * an entry for the unnamed stream. 596e3f2c991SKeyur Desai * 2. If there are named streams, the response should contain an entry 597e3f2c991SKeyur Desai * for the unnamed stream followed by the entries for the named 598e3f2c991SKeyur Desai * streams. 599e3f2c991SKeyur Desai * 600e3f2c991SKeyur Desai * If the target is a directory: 601e3f2c991SKeyur Desai * 1. If there are no streams, the response is complete. Directories 602e3f2c991SKeyur Desai * do not report the unnamed stream. 603e3f2c991SKeyur Desai * 2. If there are streams, the response should contain entries for 604e3f2c991SKeyur Desai * those streams but there should not be an entry for the unnamed 605e3f2c991SKeyur Desai * stream. 606e3f2c991SKeyur Desai * 607e3f2c991SKeyur Desai * Note that the stream name lengths exclude the null terminator but 608e3f2c991SKeyur Desai * the field lengths (i.e. next offset calculations) need to include 609e3f2c991SKeyur Desai * the null terminator and be padded to a multiple of 8 bytes. The 610e3f2c991SKeyur Desai * last entry does not seem to need any padding. 611e3f2c991SKeyur Desai * 612e3f2c991SKeyur Desai * If an error is encountered when trying to read the stream entries 613e3f2c991SKeyur Desai * (smb_odir_read_streaminfo) it is treated as if there are no [more] 614e3f2c991SKeyur Desai * entries. The entries that have been read so far are returned and 615e3f2c991SKeyur Desai * no error is reported. 616e3f2c991SKeyur Desai * 617cb174861Sjoyce mcintosh * If the response buffer is not large enough to return all of the 618cb174861Sjoyce mcintosh * named stream entries, the entries that do fit are returned and 619cb174861Sjoyce mcintosh * a warning code is set (NT_STATUS_BUFFER_OVERFLOW). The next_offset 620cb174861Sjoyce mcintosh * value in the last returned entry must be 0. 621e3f2c991SKeyur Desai */ 622*a90cf9f2SGordon Ross uint32_t 623*a90cf9f2SGordon Ross smb_query_stream_info(smb_request_t *sr, mbuf_chain_t *mbc, 624*a90cf9f2SGordon Ross smb_queryinfo_t *qinfo) 625e3f2c991SKeyur Desai { 626e3f2c991SKeyur Desai char *stream_name; 627e3f2c991SKeyur Desai uint32_t next_offset; 628e3f2c991SKeyur Desai uint32_t stream_nlen; 629e3f2c991SKeyur Desai uint32_t pad; 630e3f2c991SKeyur Desai u_offset_t datasz, allocsz; 631e3f2c991SKeyur Desai smb_streaminfo_t *sinfo, *sinfo_next; 632e3f2c991SKeyur Desai int rc = 0; 633e3f2c991SKeyur Desai boolean_t done = B_FALSE; 634e3f2c991SKeyur Desai boolean_t eos = B_FALSE; 635e3f2c991SKeyur Desai smb_odir_t *od = NULL; 636*a90cf9f2SGordon Ross uint32_t status = 0; 637e3f2c991SKeyur Desai 638e3f2c991SKeyur Desai smb_node_t *fnode = qinfo->qi_node; 639e3f2c991SKeyur Desai smb_attr_t *attr = &qinfo->qi_attr; 640e3f2c991SKeyur Desai 641e3f2c991SKeyur Desai ASSERT(fnode); 642e3f2c991SKeyur Desai if (SMB_IS_STREAM(fnode)) { 643e3f2c991SKeyur Desai fnode = fnode->n_unode; 644e3f2c991SKeyur Desai ASSERT(fnode); 645e3f2c991SKeyur Desai } 646e3f2c991SKeyur Desai ASSERT(fnode->n_magic == SMB_NODE_MAGIC); 647e3f2c991SKeyur Desai ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING); 648e3f2c991SKeyur Desai 649e3f2c991SKeyur Desai sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP); 650e3f2c991SKeyur Desai sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP); 651e3f2c991SKeyur Desai datasz = attr->sa_vattr.va_size; 652e3f2c991SKeyur Desai allocsz = attr->sa_allocsz; 653e3f2c991SKeyur Desai 654*a90cf9f2SGordon Ross status = smb_odir_openat(sr, fnode, &od); 655*a90cf9f2SGordon Ross switch (status) { 656*a90cf9f2SGordon Ross case 0: 657*a90cf9f2SGordon Ross break; 658*a90cf9f2SGordon Ross case NT_STATUS_NO_SUCH_FILE: 659*a90cf9f2SGordon Ross case NT_STATUS_NOT_SUPPORTED: 660*a90cf9f2SGordon Ross /* No streams. */ 661e3f2c991SKeyur Desai done = B_TRUE; 662*a90cf9f2SGordon Ross break; 663*a90cf9f2SGordon Ross default: 664*a90cf9f2SGordon Ross return (status); 665*a90cf9f2SGordon Ross } 666*a90cf9f2SGordon Ross 667*a90cf9f2SGordon Ross if (!done) { 668*a90cf9f2SGordon Ross rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos); 669*a90cf9f2SGordon Ross if ((rc != 0) || (eos)) 670*a90cf9f2SGordon Ross done = B_TRUE; 671*a90cf9f2SGordon Ross } 672e3f2c991SKeyur Desai 673e3f2c991SKeyur Desai /* If not a directory, encode an entry for the unnamed stream. */ 674*a90cf9f2SGordon Ross if (qinfo->qi_isdir == 0) { 675e3f2c991SKeyur Desai stream_name = "::$DATA"; 676e3f2c991SKeyur Desai stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name); 677cb174861Sjoyce mcintosh next_offset = SMB_STREAM_ENCODE_FIXED_SZ + stream_nlen + 678cb174861Sjoyce mcintosh smb_ascii_or_unicode_null_len(sr); 679cb174861Sjoyce mcintosh 680cb174861Sjoyce mcintosh /* Can unnamed stream fit in response buffer? */ 681*a90cf9f2SGordon Ross if (MBC_ROOM_FOR(mbc, next_offset) == 0) { 682cb174861Sjoyce mcintosh done = B_TRUE; 683*a90cf9f2SGordon Ross status = NT_STATUS_BUFFER_OVERFLOW; 684cb174861Sjoyce mcintosh } else { 685cb174861Sjoyce mcintosh /* Can first named stream fit in rsp buffer? */ 686*a90cf9f2SGordon Ross if (!done && !smb_stream_fits(sr, mbc, sinfo->si_name, 687cb174861Sjoyce mcintosh next_offset)) { 688cb174861Sjoyce mcintosh done = B_TRUE; 689*a90cf9f2SGordon Ross status = NT_STATUS_BUFFER_OVERFLOW; 690cb174861Sjoyce mcintosh } 691e3f2c991SKeyur Desai 692e3f2c991SKeyur Desai if (done) 693e3f2c991SKeyur Desai next_offset = 0; 694e3f2c991SKeyur Desai 695*a90cf9f2SGordon Ross (void) smb_mbc_encodef(mbc, "%llqqu", sr, 696cb174861Sjoyce mcintosh next_offset, stream_nlen, datasz, allocsz, 697cb174861Sjoyce mcintosh stream_name); 698cb174861Sjoyce mcintosh } 699e3f2c991SKeyur Desai } 700e3f2c991SKeyur Desai 701e3f2c991SKeyur Desai /* 702cb174861Sjoyce mcintosh * If there is no next entry, or there is not enough space in 703cb174861Sjoyce mcintosh * the response buffer for the next entry, the next_offset and 704cb174861Sjoyce mcintosh * padding are 0. 705e3f2c991SKeyur Desai */ 706e3f2c991SKeyur Desai while (!done) { 707e3f2c991SKeyur Desai stream_nlen = smb_ascii_or_unicode_strlen(sr, sinfo->si_name); 708e3f2c991SKeyur Desai sinfo_next->si_name[0] = 0; 709e3f2c991SKeyur Desai 710e3f2c991SKeyur Desai rc = smb_odir_read_streaminfo(sr, od, sinfo_next, &eos); 711e3f2c991SKeyur Desai if ((rc != 0) || (eos)) { 712e3f2c991SKeyur Desai done = B_TRUE; 713e3f2c991SKeyur Desai } else { 714cb174861Sjoyce mcintosh next_offset = SMB_STREAM_ENCODE_FIXED_SZ + 715cb174861Sjoyce mcintosh stream_nlen + 716e3f2c991SKeyur Desai smb_ascii_or_unicode_null_len(sr); 717e3f2c991SKeyur Desai pad = smb_pad_align(next_offset, 8); 718e3f2c991SKeyur Desai next_offset += pad; 719cb174861Sjoyce mcintosh 720cb174861Sjoyce mcintosh /* Can next named stream fit in response buffer? */ 721*a90cf9f2SGordon Ross if (!smb_stream_fits(sr, mbc, sinfo_next->si_name, 722cb174861Sjoyce mcintosh next_offset)) { 723cb174861Sjoyce mcintosh done = B_TRUE; 724*a90cf9f2SGordon Ross status = NT_STATUS_BUFFER_OVERFLOW; 725e3f2c991SKeyur Desai } 726cb174861Sjoyce mcintosh } 727cb174861Sjoyce mcintosh 728cb174861Sjoyce mcintosh if (done) { 729cb174861Sjoyce mcintosh next_offset = 0; 730cb174861Sjoyce mcintosh pad = 0; 731cb174861Sjoyce mcintosh } 732cb174861Sjoyce mcintosh 733*a90cf9f2SGordon Ross (void) smb_mbc_encodef(mbc, "%llqqu#.", 734e3f2c991SKeyur Desai sr, next_offset, stream_nlen, 735e3f2c991SKeyur Desai sinfo->si_size, sinfo->si_alloc_size, 736e3f2c991SKeyur Desai sinfo->si_name, pad); 737e3f2c991SKeyur Desai 738e3f2c991SKeyur Desai (void) memcpy(sinfo, sinfo_next, sizeof (smb_streaminfo_t)); 739e3f2c991SKeyur Desai } 740e3f2c991SKeyur Desai 741e3f2c991SKeyur Desai kmem_free(sinfo, sizeof (smb_streaminfo_t)); 742e3f2c991SKeyur Desai kmem_free(sinfo_next, sizeof (smb_streaminfo_t)); 743e3f2c991SKeyur Desai if (od) { 744e3f2c991SKeyur Desai smb_odir_close(od); 745e3f2c991SKeyur Desai smb_odir_release(od); 746e3f2c991SKeyur Desai } 747*a90cf9f2SGordon Ross 748*a90cf9f2SGordon Ross return (status); 749e3f2c991SKeyur Desai } 750e3f2c991SKeyur Desai 751e3f2c991SKeyur Desai /* 752cb174861Sjoyce mcintosh * smb_stream_fits 753cb174861Sjoyce mcintosh * 754cb174861Sjoyce mcintosh * Check if the named stream entry can fit in the response buffer. 755cb174861Sjoyce mcintosh * 756cb174861Sjoyce mcintosh * Required space = 757cb174861Sjoyce mcintosh * offset (size of current entry) 758cb174861Sjoyce mcintosh * + SMB_STREAM_ENCODE_FIXED_SIZE 759cb174861Sjoyce mcintosh * + length of encoded stream name 760cb174861Sjoyce mcintosh * + length of null terminator 761cb174861Sjoyce mcintosh * + alignment padding 762cb174861Sjoyce mcintosh */ 763cb174861Sjoyce mcintosh static boolean_t 764*a90cf9f2SGordon Ross smb_stream_fits(smb_request_t *sr, mbuf_chain_t *mbc, 765*a90cf9f2SGordon Ross char *name, uint32_t offset) 766cb174861Sjoyce mcintosh { 767cb174861Sjoyce mcintosh uint32_t len, pad; 768cb174861Sjoyce mcintosh 769cb174861Sjoyce mcintosh len = SMB_STREAM_ENCODE_FIXED_SZ + 770cb174861Sjoyce mcintosh smb_ascii_or_unicode_strlen(sr, name) + 771cb174861Sjoyce mcintosh smb_ascii_or_unicode_null_len(sr); 772cb174861Sjoyce mcintosh pad = smb_pad_align(len, 8); 773cb174861Sjoyce mcintosh len += pad; 774cb174861Sjoyce mcintosh 775*a90cf9f2SGordon Ross return (MBC_ROOM_FOR(mbc, offset + len) != 0); 776cb174861Sjoyce mcintosh } 777cb174861Sjoyce mcintosh 778cb174861Sjoyce mcintosh /* 779e3f2c991SKeyur Desai * smb_query_fileinfo 780e3f2c991SKeyur Desai * 781e3f2c991SKeyur Desai * Populate smb_queryinfo_t structure for SMB_FTYPE_DISK 782e3f2c991SKeyur Desai * (This should become an smb_ofile / smb_node function.) 783e3f2c991SKeyur Desai */ 784e3f2c991SKeyur Desai int 785e3f2c991SKeyur Desai smb_query_fileinfo(smb_request_t *sr, smb_node_t *node, uint16_t infolev, 786e3f2c991SKeyur Desai smb_queryinfo_t *qinfo) 787e3f2c991SKeyur Desai { 788148c5f43SAlan Wright int rc = 0; 789e3f2c991SKeyur Desai 790cb174861Sjoyce mcintosh /* If shortname required but not supported -> OBJECT_NAME_NOT_FOUND */ 791cb174861Sjoyce mcintosh if ((infolev == SMB_QUERY_FILE_ALT_NAME_INFO) || 792cb174861Sjoyce mcintosh (infolev == SMB_FILE_ALT_NAME_INFORMATION)) { 793cb174861Sjoyce mcintosh if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_SHORTNAMES)) { 794cb174861Sjoyce mcintosh smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 795cb174861Sjoyce mcintosh ERRDOS, ERROR_FILE_NOT_FOUND); 796cb174861Sjoyce mcintosh return (-1); 797cb174861Sjoyce mcintosh } 798cb174861Sjoyce mcintosh } 799cb174861Sjoyce mcintosh 800e3f2c991SKeyur Desai (void) bzero(qinfo, sizeof (smb_queryinfo_t)); 801e3f2c991SKeyur Desai 8025fd03bc0SGordon Ross /* See: smb_query_encode_response */ 8035fd03bc0SGordon Ross qinfo->qi_attr.sa_mask = SMB_AT_ALL; 8045fd03bc0SGordon Ross rc = smb_node_getattr(sr, node, sr->user_cr, sr->fid_ofile, 8055fd03bc0SGordon Ross &qinfo->qi_attr); 8065fd03bc0SGordon Ross if (rc != 0) { 807e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 808e3f2c991SKeyur Desai ERRDOS, ERROR_INTERNAL_ERROR); 809e3f2c991SKeyur Desai return (-1); 810e3f2c991SKeyur Desai } 811e3f2c991SKeyur Desai 812e3f2c991SKeyur Desai qinfo->qi_node = node; 813e3f2c991SKeyur Desai qinfo->qi_delete_on_close = 814e3f2c991SKeyur Desai (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0; 815*a90cf9f2SGordon Ross qinfo->qi_isdir = smb_node_is_dir(node); 816e3f2c991SKeyur Desai 817e3f2c991SKeyur Desai /* 818e3f2c991SKeyur Desai * The number of links reported should be the number of 819e3f2c991SKeyur Desai * non-deleted links. Thus if delete_on_close is set, 820e3f2c991SKeyur Desai * decrement the link count. 821e3f2c991SKeyur Desai */ 822e3f2c991SKeyur Desai if (qinfo->qi_delete_on_close && 823e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nlink > 0) { 824e3f2c991SKeyur Desai --(qinfo->qi_attr.sa_vattr.va_nlink); 825e3f2c991SKeyur Desai } 826e3f2c991SKeyur Desai 827148c5f43SAlan Wright /* 828148c5f43SAlan Wright * populate name, namelen and shortname ONLY for the information 829148c5f43SAlan Wright * levels that require these fields 830148c5f43SAlan Wright */ 831148c5f43SAlan Wright switch (infolev) { 832148c5f43SAlan Wright case SMB_QUERY_FILE_ALL_INFO: 833148c5f43SAlan Wright case SMB_FILE_ALL_INFORMATION: 834148c5f43SAlan Wright rc = smb_query_pathname(sr, node, B_TRUE, qinfo); 835148c5f43SAlan Wright break; 836148c5f43SAlan Wright case SMB_QUERY_FILE_NAME_INFO: 837148c5f43SAlan Wright case SMB_FILE_NAME_INFORMATION: 838148c5f43SAlan Wright rc = smb_query_pathname(sr, node, B_FALSE, qinfo); 839148c5f43SAlan Wright break; 840148c5f43SAlan Wright case SMB_QUERY_FILE_ALT_NAME_INFO: 841148c5f43SAlan Wright case SMB_FILE_ALT_NAME_INFORMATION: 842148c5f43SAlan Wright smb_query_shortname(node, qinfo); 843148c5f43SAlan Wright break; 844148c5f43SAlan Wright default: 845148c5f43SAlan Wright break; 846bbf6f00cSJordan Brown } 847bbf6f00cSJordan Brown 848e3f2c991SKeyur Desai if (rc != 0) { 849e3f2c991SKeyur Desai smbsr_errno(sr, rc); 850e3f2c991SKeyur Desai return (-1); 851e3f2c991SKeyur Desai } 852148c5f43SAlan Wright return (0); 853148c5f43SAlan Wright } 854e3f2c991SKeyur Desai 855e3f2c991SKeyur Desai /* 856148c5f43SAlan Wright * smb_query_pathname 857148c5f43SAlan Wright * 858148c5f43SAlan Wright * Determine the absolute pathname of 'node' within the share. 859148c5f43SAlan Wright * For some levels (e.g. ALL_INFO) the pathname should include the 860148c5f43SAlan Wright * sharename for others (e.g. NAME_INFO) the pathname should be 861148c5f43SAlan Wright * relative to the share. 862148c5f43SAlan Wright * For example if the node represents file "test1.txt" in directory 863148c5f43SAlan Wright * "dir1" on share "share1" 864148c5f43SAlan Wright * - if include_share is TRUE the pathname would be: \share1\dir1\test1.txt 865148c5f43SAlan Wright * - if include_share is FALSE the pathname would be: \dir1\test1.txt 866148c5f43SAlan Wright * 867e3f2c991SKeyur Desai * For some reason NT will not show the security tab in the root 868148c5f43SAlan Wright * directory of a mapped drive unless the filename length is greater 869148c5f43SAlan Wright * than one. So if the length is 1 we set it to 2 to persuade NT to 870148c5f43SAlan Wright * show the tab. It should be safe because of the null terminator. 871e3f2c991SKeyur Desai */ 872148c5f43SAlan Wright static int 873148c5f43SAlan Wright smb_query_pathname(smb_request_t *sr, smb_node_t *node, boolean_t include_share, 874148c5f43SAlan Wright smb_queryinfo_t *qinfo) 875148c5f43SAlan Wright { 876148c5f43SAlan Wright smb_tree_t *tree = sr->tid_tree; 877148c5f43SAlan Wright char *buf = qinfo->qi_name; 878148c5f43SAlan Wright size_t buflen = MAXPATHLEN; 879148c5f43SAlan Wright size_t len; 880148c5f43SAlan Wright int rc; 881148c5f43SAlan Wright 882148c5f43SAlan Wright if (include_share) { 883148c5f43SAlan Wright len = snprintf(buf, buflen, "\\%s", tree->t_sharename); 884148c5f43SAlan Wright if (len == (buflen - 1)) 885148c5f43SAlan Wright return (ENAMETOOLONG); 886148c5f43SAlan Wright 887148c5f43SAlan Wright buf += len; 888148c5f43SAlan Wright buflen -= len; 889148c5f43SAlan Wright } 890148c5f43SAlan Wright 891148c5f43SAlan Wright if (node == tree->t_snode) { 892148c5f43SAlan Wright if (!include_share) 893148c5f43SAlan Wright (void) strlcpy(buf, "\\", buflen); 894148c5f43SAlan Wright return (0); 895148c5f43SAlan Wright } 896148c5f43SAlan Wright 897148c5f43SAlan Wright rc = smb_node_getshrpath(node, tree, buf, buflen); 898148c5f43SAlan Wright if (rc == 0) { 899148c5f43SAlan Wright qinfo->qi_namelen = 900148c5f43SAlan Wright smb_ascii_or_unicode_strlen(sr, qinfo->qi_name); 901e3f2c991SKeyur Desai if (qinfo->qi_namelen == 1) 902e3f2c991SKeyur Desai qinfo->qi_namelen = 2; 903148c5f43SAlan Wright } 904148c5f43SAlan Wright return (rc); 905148c5f43SAlan Wright } 906e3f2c991SKeyur Desai 907e3f2c991SKeyur Desai /* 908148c5f43SAlan Wright * smb_query_shortname 909148c5f43SAlan Wright * 910148c5f43SAlan Wright * If the node is a named stream, use its associated 9119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * unnamed stream name to determine the shortname. 912148c5f43SAlan Wright * If a shortname is required (smb_needs_mangle()), generate it 913148c5f43SAlan Wright * using smb_mangle(), otherwise, convert the original name to 914148c5f43SAlan Wright * upper-case and return it as the alternative name. 915e3f2c991SKeyur Desai */ 916*a90cf9f2SGordon Ross void 917148c5f43SAlan Wright smb_query_shortname(smb_node_t *node, smb_queryinfo_t *qinfo) 918148c5f43SAlan Wright { 919148c5f43SAlan Wright char *namep; 920148c5f43SAlan Wright 9219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (SMB_IS_STREAM(node)) 9229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States namep = node->n_unode->od_name; 9239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States else 9249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States namep = node->od_name; 9259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 926148c5f43SAlan Wright if (smb_needs_mangled(namep)) { 927148c5f43SAlan Wright smb_mangle(namep, qinfo->qi_attr.sa_vattr.va_nodeid, 928148c5f43SAlan Wright qinfo->qi_shortname, SMB_SHORTNAMELEN); 929148c5f43SAlan Wright } else { 930cb174861Sjoyce mcintosh (void) strlcpy(qinfo->qi_shortname, namep, SMB_SHORTNAMELEN); 931bbf6f00cSJordan Brown (void) smb_strupr(qinfo->qi_shortname); 932e3f2c991SKeyur Desai } 933e3f2c991SKeyur Desai } 934e3f2c991SKeyur Desai 935e3f2c991SKeyur Desai /* 936e3f2c991SKeyur Desai * smb_query_pipeinfo 937e3f2c991SKeyur Desai * 938e3f2c991SKeyur Desai * Populate smb_queryinfo_t structure for SMB_FTYPE_MESG_PIPE 939e3f2c991SKeyur Desai * (This should become an smb_opipe function.) 940e3f2c991SKeyur Desai */ 941e3f2c991SKeyur Desai static int 942e3f2c991SKeyur Desai smb_query_pipeinfo(smb_request_t *sr, smb_opipe_t *opipe, uint16_t infolev, 943e3f2c991SKeyur Desai smb_queryinfo_t *qinfo) 944e3f2c991SKeyur Desai { 945e3f2c991SKeyur Desai char *namep = opipe->p_name; 946e3f2c991SKeyur Desai 947e3f2c991SKeyur Desai (void) bzero(qinfo, sizeof (smb_queryinfo_t)); 948e3f2c991SKeyur Desai qinfo->qi_node = NULL; 949e3f2c991SKeyur Desai qinfo->qi_attr.sa_vattr.va_nlink = 1; 950e3f2c991SKeyur Desai qinfo->qi_delete_on_close = 1; 951*a90cf9f2SGordon Ross qinfo->qi_isdir = 0; 952e3f2c991SKeyur Desai 953e3f2c991SKeyur Desai if ((infolev == SMB_INFO_STANDARD) || 954e3f2c991SKeyur Desai (infolev == SMB_INFO_QUERY_EA_SIZE) || 955e3f2c991SKeyur Desai (infolev == SMB_QUERY_INFORMATION2)) { 956e3f2c991SKeyur Desai qinfo->qi_attr.sa_dosattr = 0; 957e3f2c991SKeyur Desai } else { 958e3f2c991SKeyur Desai qinfo->qi_attr.sa_dosattr = FILE_ATTRIBUTE_NORMAL; 959e3f2c991SKeyur Desai } 960e3f2c991SKeyur Desai 961e3f2c991SKeyur Desai /* If the leading \ is missing from the pipe name, add it. */ 962e3f2c991SKeyur Desai if (*namep != '\\') 963e3f2c991SKeyur Desai (void) snprintf(qinfo->qi_name, MAXNAMELEN, "\\%s", namep); 964e3f2c991SKeyur Desai else 965e3f2c991SKeyur Desai (void) strlcpy(qinfo->qi_name, namep, MAXNAMELEN); 966e3f2c991SKeyur Desai 967e3f2c991SKeyur Desai qinfo->qi_namelen= 968e3f2c991SKeyur Desai smb_ascii_or_unicode_strlen(sr, qinfo->qi_name); 969e3f2c991SKeyur Desai 970e3f2c991SKeyur Desai return (0); 971e3f2c991SKeyur Desai } 972e3f2c991SKeyur Desai 973e3f2c991SKeyur Desai /* 974e3f2c991SKeyur Desai * smb_query_pipe_valid_infolev 975e3f2c991SKeyur Desai * 976e3f2c991SKeyur Desai * If the infolev is not valid for a message pipe, the error 977e3f2c991SKeyur Desai * information is set in sr and B_FALSE is returned. 978e3f2c991SKeyur Desai * Otherwise, returns B_TRUE. 979e3f2c991SKeyur Desai */ 980e3f2c991SKeyur Desai static boolean_t 981e3f2c991SKeyur Desai smb_query_pipe_valid_infolev(smb_request_t *sr, uint16_t infolev) 982e3f2c991SKeyur Desai { 983e3f2c991SKeyur Desai switch (infolev) { 984e3f2c991SKeyur Desai case SMB_INFO_QUERY_ALL_EAS: 985e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 986e3f2c991SKeyur Desai ERRDOS, ERROR_ACCESS_DENIED); 987e3f2c991SKeyur Desai return (B_FALSE); 988e3f2c991SKeyur Desai 989e3f2c991SKeyur Desai case SMB_QUERY_FILE_ALT_NAME_INFO: 990e3f2c991SKeyur Desai case SMB_FILE_ALT_NAME_INFORMATION: 991e3f2c991SKeyur Desai case SMB_QUERY_FILE_STREAM_INFO: 992e3f2c991SKeyur Desai case SMB_FILE_STREAM_INFORMATION: 993e3f2c991SKeyur Desai case SMB_QUERY_FILE_COMPRESSION_INFO: 994e3f2c991SKeyur Desai case SMB_FILE_COMPRESSION_INFORMATION: 9959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_FILE_NETWORK_OPEN_INFORMATION: 996e3f2c991SKeyur Desai case SMB_FILE_ATTR_TAG_INFORMATION: 997e3f2c991SKeyur Desai smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 998e3f2c991SKeyur Desai ERRDOS, ERROR_INVALID_PARAMETER); 999e3f2c991SKeyur Desai return (B_FALSE); 1000e3f2c991SKeyur Desai } 1001e3f2c991SKeyur Desai 1002e3f2c991SKeyur Desai return (B_TRUE); 1003e3f2c991SKeyur Desai } 1004