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