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