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 2013 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_1(op__QueryInformation__start, smb_request_t *, sr); /* arg.dirop */ 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_1(op__QueryInformation__done, 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_1(op__QueryInformation2__start, 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_1(op__QueryInformation2__done, 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 if (rc == ENOENT) 333 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 334 ERRDOS, ERROR_FILE_NOT_FOUND); 335 else 336 smbsr_errno(sr, rc); 337 338 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 339 return (-1); 340 } 341 342 if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) { 343 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); 344 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 345 smb_node_release(node); 346 return (-1); 347 } 348 349 rc = smb_query_fileinfo(sr, node, infolev, qinfo); 350 if (rc != 0) { 351 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 352 smb_node_release(node); 353 return (rc); 354 } 355 356 /* If delete_on_close - NT_STATUS_DELETE_PENDING */ 357 if (qinfo->qi_delete_on_close) { 358 smbsr_error(sr, NT_STATUS_DELETE_PENDING, 359 ERRDOS, ERROR_ACCESS_DENIED); 360 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 361 smb_node_release(node); 362 return (-1); 363 } 364 365 rc = smb_query_encode_response(sr, xa, infolev, qinfo); 366 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 367 smb_node_release(node); 368 return (rc); 369 } 370 371 /* 372 * smb_size32 373 * Some responses only support 32 bit file sizes. If the file size 374 * exceeds UINT_MAX (32 bit) we return UINT_MAX in the response. 375 */ 376 static uint32_t 377 smb_size32(u_offset_t size) 378 { 379 return ((size > UINT_MAX) ? UINT_MAX : (uint32_t)size); 380 } 381 382 /* 383 * smb_query_encode_response 384 * 385 * Encode the data from smb_queryinfo_t into client response 386 */ 387 int 388 smb_query_encode_response(smb_request_t *sr, smb_xa_t *xa, 389 uint16_t infolev, smb_queryinfo_t *qinfo) 390 { 391 uint16_t dattr; 392 u_offset_t datasz, allocsz; 393 uint32_t status; 394 395 dattr = qinfo->qi_attr.sa_dosattr & FILE_ATTRIBUTE_MASK; 396 datasz = qinfo->qi_attr.sa_vattr.va_size; 397 allocsz = qinfo->qi_attr.sa_allocsz; 398 399 switch (infolev) { 400 case SMB_QUERY_INFORMATION: 401 (void) smbsr_encode_result(sr, 10, 0, "bwll10.w", 402 10, 403 dattr, 404 smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 405 smb_size32(datasz), 406 0); 407 break; 408 409 case SMB_QUERY_INFORMATION2: 410 (void) smbsr_encode_result(sr, 11, 0, "byyyllww", 411 11, 412 smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec), 413 smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec), 414 smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 415 smb_size32(datasz), smb_size32(allocsz), dattr, 0); 416 break; 417 418 case SMB_FILE_ACCESS_INFORMATION: 419 ASSERT(sr->fid_ofile); 420 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 421 sr->fid_ofile->f_granted_access); 422 break; 423 424 case SMB_INFO_STANDARD: 425 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 426 (void) smb_mbc_encodef(&xa->rep_data_mb, 427 ((sr->session->native_os == NATIVE_OS_WIN95) ? 428 "YYYllw" : "yyyllw"), 429 smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec), 430 smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec), 431 smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 432 smb_size32(datasz), smb_size32(allocsz), dattr); 433 break; 434 435 case SMB_INFO_QUERY_EA_SIZE: 436 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 437 (void) smb_mbc_encodef(&xa->rep_data_mb, 438 ((sr->session->native_os == NATIVE_OS_WIN95) ? 439 "YYYllwl" : "yyyllwl"), 440 smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec), 441 smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec), 442 smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 443 smb_size32(datasz), smb_size32(allocsz), dattr, 0); 444 break; 445 446 case SMB_INFO_QUERY_ALL_EAS: 447 case SMB_INFO_QUERY_EAS_FROM_LIST: 448 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 449 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 450 break; 451 452 case SMB_INFO_IS_NAME_VALID: 453 break; 454 455 case SMB_QUERY_FILE_BASIC_INFO: 456 case SMB_FILE_BASIC_INFORMATION: 457 /* 458 * NT includes 6 bytes (spec says 4) at the end of this 459 * response, which are required by NetBench 5.01. 460 */ 461 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 462 (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.", 463 &qinfo->qi_crtime, 464 &qinfo->qi_atime, 465 &qinfo->qi_mtime, 466 &qinfo->qi_ctime, 467 dattr); 468 break; 469 470 case SMB_QUERY_FILE_STANDARD_INFO: 471 case SMB_FILE_STANDARD_INFORMATION: 472 /* 2-byte pad at end */ 473 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 474 (void) smb_mbc_encodef(&xa->rep_data_mb, "qqlbb2.", 475 (uint64_t)allocsz, 476 (uint64_t)datasz, 477 qinfo->qi_attr.sa_vattr.va_nlink, 478 qinfo->qi_delete_on_close, 479 qinfo->qi_isdir); 480 break; 481 482 case SMB_QUERY_FILE_EA_INFO: 483 case SMB_FILE_EA_INFORMATION: 484 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 485 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 486 break; 487 488 case SMB_QUERY_FILE_NAME_INFO: 489 case SMB_FILE_NAME_INFORMATION: 490 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 491 (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", sr, 492 qinfo->qi_namelen, qinfo->qi_name); 493 break; 494 495 case SMB_QUERY_FILE_ALL_INFO: 496 case SMB_FILE_ALL_INFORMATION: 497 /* 498 * There is a 6-byte pad between Attributes and AllocationSize, 499 * and a 2-byte pad after the Directory field. 500 */ 501 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 502 (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.qqlbb2.l", 503 &qinfo->qi_crtime, 504 &qinfo->qi_atime, 505 &qinfo->qi_mtime, 506 &qinfo->qi_ctime, 507 dattr, 508 (uint64_t)allocsz, 509 (uint64_t)datasz, 510 qinfo->qi_attr.sa_vattr.va_nlink, 511 qinfo->qi_delete_on_close, 512 qinfo->qi_isdir, 513 0); 514 515 (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", 516 sr, qinfo->qi_namelen, qinfo->qi_name); 517 break; 518 519 case SMB_QUERY_FILE_ALT_NAME_INFO: 520 case SMB_FILE_ALT_NAME_INFORMATION: 521 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 522 (void) smb_mbc_encodef(&xa->rep_data_mb, "%lU", sr, 523 smb_wcequiv_strlen(qinfo->qi_shortname), 524 qinfo->qi_shortname); 525 break; 526 527 case SMB_QUERY_FILE_STREAM_INFO: 528 case SMB_FILE_STREAM_INFORMATION: 529 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 530 status = smb_query_stream_info(sr, &xa->rep_data_mb, qinfo); 531 if (status) 532 smbsr_status(sr, status, 0, 0); 533 break; 534 535 case SMB_QUERY_FILE_COMPRESSION_INFO: 536 case SMB_FILE_COMPRESSION_INFORMATION: 537 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 538 (void) smb_mbc_encodef(&xa->rep_data_mb, "qwbbb3.", 539 datasz, 0, 0, 0, 0); 540 break; 541 542 case SMB_FILE_INTERNAL_INFORMATION: 543 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 544 (void) smb_mbc_encodef(&xa->rep_data_mb, "q", 545 qinfo->qi_attr.sa_vattr.va_nodeid); 546 break; 547 548 case SMB_FILE_NETWORK_OPEN_INFORMATION: 549 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 550 (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTqql4.", 551 &qinfo->qi_crtime, 552 &qinfo->qi_atime, 553 &qinfo->qi_mtime, 554 &qinfo->qi_ctime, 555 (uint64_t)allocsz, 556 (uint64_t)datasz, 557 (uint32_t)dattr); 558 break; 559 560 case SMB_FILE_ATTR_TAG_INFORMATION: 561 /* 562 * If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the 563 * second dword should be the reparse tag. Otherwise 564 * the tag value should be set to zero. 565 * We don't support reparse points, so we set the tag 566 * to zero. 567 */ 568 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 569 (void) smb_mbc_encodef(&xa->rep_data_mb, "ll", 570 (uint32_t)dattr, 0); 571 break; 572 573 default: 574 if ((infolev > 1000) && smb_query_passthru) 575 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, 576 ERRDOS, ERROR_NOT_SUPPORTED); 577 else 578 smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL); 579 return (-1); 580 } 581 582 return (0); 583 } 584 585 /* 586 * smb_encode_stream_info 587 * 588 * This function encodes the streams information. 589 * The following rules about how have been derived from observed NT 590 * behaviour. 591 * 592 * If the target is a file: 593 * 1. If there are no named streams, the response should still contain 594 * an entry for the unnamed stream. 595 * 2. If there are named streams, the response should contain an entry 596 * for the unnamed stream followed by the entries for the named 597 * streams. 598 * 599 * If the target is a directory: 600 * 1. If there are no streams, the response is complete. Directories 601 * do not report the unnamed stream. 602 * 2. If there are streams, the response should contain entries for 603 * those streams but there should not be an entry for the unnamed 604 * stream. 605 * 606 * Note that the stream name lengths exclude the null terminator but 607 * the field lengths (i.e. next offset calculations) need to include 608 * the null terminator and be padded to a multiple of 8 bytes. The 609 * last entry does not seem to need any padding. 610 * 611 * If an error is encountered when trying to read the stream entries 612 * (smb_odir_read_streaminfo) it is treated as if there are no [more] 613 * entries. The entries that have been read so far are returned and 614 * no error is reported. 615 * 616 * If the response buffer is not large enough to return all of the 617 * named stream entries, the entries that do fit are returned and 618 * a warning code is set (NT_STATUS_BUFFER_OVERFLOW). The next_offset 619 * value in the last returned entry must be 0. 620 */ 621 uint32_t 622 smb_query_stream_info(smb_request_t *sr, mbuf_chain_t *mbc, 623 smb_queryinfo_t *qinfo) 624 { 625 char *stream_name; 626 uint32_t next_offset; 627 uint32_t stream_nlen; 628 uint32_t pad; 629 u_offset_t datasz, allocsz; 630 smb_streaminfo_t *sinfo, *sinfo_next; 631 int rc = 0; 632 boolean_t done = B_FALSE; 633 boolean_t eos = B_FALSE; 634 smb_odir_t *od = NULL; 635 uint32_t status = 0; 636 637 smb_node_t *fnode = qinfo->qi_node; 638 smb_attr_t *attr = &qinfo->qi_attr; 639 640 ASSERT(fnode); 641 if (SMB_IS_STREAM(fnode)) { 642 fnode = fnode->n_unode; 643 ASSERT(fnode); 644 } 645 ASSERT(fnode->n_magic == SMB_NODE_MAGIC); 646 ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING); 647 648 sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP); 649 sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP); 650 datasz = attr->sa_vattr.va_size; 651 allocsz = attr->sa_allocsz; 652 653 status = smb_odir_openat(sr, fnode, &od); 654 switch (status) { 655 case 0: 656 break; 657 case NT_STATUS_NO_SUCH_FILE: 658 case NT_STATUS_NOT_SUPPORTED: 659 /* No streams. */ 660 done = B_TRUE; 661 break; 662 default: 663 return (status); 664 } 665 666 if (!done) { 667 rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos); 668 if ((rc != 0) || (eos)) 669 done = B_TRUE; 670 } 671 672 /* If not a directory, encode an entry for the unnamed stream. */ 673 if (qinfo->qi_isdir == 0) { 674 stream_name = "::$DATA"; 675 stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name); 676 next_offset = SMB_STREAM_ENCODE_FIXED_SZ + stream_nlen + 677 smb_ascii_or_unicode_null_len(sr); 678 679 /* Can unnamed stream fit in response buffer? */ 680 if (MBC_ROOM_FOR(mbc, next_offset) == 0) { 681 done = B_TRUE; 682 status = NT_STATUS_BUFFER_OVERFLOW; 683 } else { 684 /* Can first named stream fit in rsp buffer? */ 685 if (!done && !smb_stream_fits(sr, mbc, sinfo->si_name, 686 next_offset)) { 687 done = B_TRUE; 688 status = NT_STATUS_BUFFER_OVERFLOW; 689 } 690 691 if (done) 692 next_offset = 0; 693 694 (void) smb_mbc_encodef(mbc, "%llqqu", sr, 695 next_offset, stream_nlen, datasz, allocsz, 696 stream_name); 697 } 698 } 699 700 /* 701 * If there is no next entry, or there is not enough space in 702 * the response buffer for the next entry, the next_offset and 703 * padding are 0. 704 */ 705 while (!done) { 706 stream_nlen = smb_ascii_or_unicode_strlen(sr, sinfo->si_name); 707 sinfo_next->si_name[0] = 0; 708 709 rc = smb_odir_read_streaminfo(sr, od, sinfo_next, &eos); 710 if ((rc != 0) || (eos)) { 711 done = B_TRUE; 712 } else { 713 next_offset = SMB_STREAM_ENCODE_FIXED_SZ + 714 stream_nlen + 715 smb_ascii_or_unicode_null_len(sr); 716 pad = smb_pad_align(next_offset, 8); 717 next_offset += pad; 718 719 /* Can next named stream fit in response buffer? */ 720 if (!smb_stream_fits(sr, mbc, sinfo_next->si_name, 721 next_offset)) { 722 done = B_TRUE; 723 status = NT_STATUS_BUFFER_OVERFLOW; 724 } 725 } 726 727 if (done) { 728 next_offset = 0; 729 pad = 0; 730 } 731 732 (void) smb_mbc_encodef(mbc, "%llqqu#.", 733 sr, next_offset, stream_nlen, 734 sinfo->si_size, sinfo->si_alloc_size, 735 sinfo->si_name, pad); 736 737 (void) memcpy(sinfo, sinfo_next, sizeof (smb_streaminfo_t)); 738 } 739 740 kmem_free(sinfo, sizeof (smb_streaminfo_t)); 741 kmem_free(sinfo_next, sizeof (smb_streaminfo_t)); 742 if (od) { 743 smb_odir_close(od); 744 smb_odir_release(od); 745 } 746 747 return (status); 748 } 749 750 /* 751 * smb_stream_fits 752 * 753 * Check if the named stream entry can fit in the response buffer. 754 * 755 * Required space = 756 * offset (size of current entry) 757 * + SMB_STREAM_ENCODE_FIXED_SIZE 758 * + length of encoded stream name 759 * + length of null terminator 760 * + alignment padding 761 */ 762 static boolean_t 763 smb_stream_fits(smb_request_t *sr, mbuf_chain_t *mbc, 764 char *name, uint32_t offset) 765 { 766 uint32_t len, pad; 767 768 len = SMB_STREAM_ENCODE_FIXED_SZ + 769 smb_ascii_or_unicode_strlen(sr, name) + 770 smb_ascii_or_unicode_null_len(sr); 771 pad = smb_pad_align(len, 8); 772 len += pad; 773 774 return (MBC_ROOM_FOR(mbc, offset + len) != 0); 775 } 776 777 /* 778 * smb_query_fileinfo 779 * 780 * Populate smb_queryinfo_t structure for SMB_FTYPE_DISK 781 * (This should become an smb_ofile / smb_node function.) 782 */ 783 int 784 smb_query_fileinfo(smb_request_t *sr, smb_node_t *node, uint16_t infolev, 785 smb_queryinfo_t *qinfo) 786 { 787 int rc = 0; 788 789 /* If shortname required but not supported -> OBJECT_NAME_NOT_FOUND */ 790 if ((infolev == SMB_QUERY_FILE_ALT_NAME_INFO) || 791 (infolev == SMB_FILE_ALT_NAME_INFORMATION)) { 792 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_SHORTNAMES)) { 793 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 794 ERRDOS, ERROR_FILE_NOT_FOUND); 795 return (-1); 796 } 797 } 798 799 (void) bzero(qinfo, sizeof (smb_queryinfo_t)); 800 801 /* See: smb_query_encode_response */ 802 qinfo->qi_attr.sa_mask = SMB_AT_ALL; 803 rc = smb_node_getattr(sr, node, sr->user_cr, sr->fid_ofile, 804 &qinfo->qi_attr); 805 if (rc != 0) { 806 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 807 ERRDOS, ERROR_INTERNAL_ERROR); 808 return (-1); 809 } 810 811 qinfo->qi_node = node; 812 qinfo->qi_delete_on_close = 813 (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0; 814 qinfo->qi_isdir = smb_node_is_dir(node); 815 816 /* 817 * The number of links reported should be the number of 818 * non-deleted links. Thus if delete_on_close is set, 819 * decrement the link count. 820 */ 821 if (qinfo->qi_delete_on_close && 822 qinfo->qi_attr.sa_vattr.va_nlink > 0) { 823 --(qinfo->qi_attr.sa_vattr.va_nlink); 824 } 825 826 /* 827 * populate name, namelen and shortname ONLY for the information 828 * levels that require these fields 829 */ 830 switch (infolev) { 831 case SMB_QUERY_FILE_ALL_INFO: 832 case SMB_FILE_ALL_INFORMATION: 833 rc = smb_query_pathname(sr, node, B_TRUE, qinfo); 834 break; 835 case SMB_QUERY_FILE_NAME_INFO: 836 case SMB_FILE_NAME_INFORMATION: 837 rc = smb_query_pathname(sr, node, B_FALSE, qinfo); 838 break; 839 case SMB_QUERY_FILE_ALT_NAME_INFO: 840 case SMB_FILE_ALT_NAME_INFORMATION: 841 smb_query_shortname(node, qinfo); 842 break; 843 default: 844 break; 845 } 846 847 if (rc != 0) { 848 smbsr_errno(sr, rc); 849 return (-1); 850 } 851 return (0); 852 } 853 854 /* 855 * smb_query_pathname 856 * 857 * Determine the absolute pathname of 'node' within the share. 858 * For some levels (e.g. ALL_INFO) the pathname should include the 859 * sharename for others (e.g. NAME_INFO) the pathname should be 860 * relative to the share. 861 * For example if the node represents file "test1.txt" in directory 862 * "dir1" on share "share1" 863 * - if include_share is TRUE the pathname would be: \share1\dir1\test1.txt 864 * - if include_share is FALSE the pathname would be: \dir1\test1.txt 865 * 866 * For some reason NT will not show the security tab in the root 867 * directory of a mapped drive unless the filename length is greater 868 * than one. So if the length is 1 we set it to 2 to persuade NT to 869 * show the tab. It should be safe because of the null terminator. 870 */ 871 static int 872 smb_query_pathname(smb_request_t *sr, smb_node_t *node, boolean_t include_share, 873 smb_queryinfo_t *qinfo) 874 { 875 smb_tree_t *tree = sr->tid_tree; 876 char *buf = qinfo->qi_name; 877 size_t buflen = MAXPATHLEN; 878 size_t len; 879 int rc; 880 881 if (include_share) { 882 len = snprintf(buf, buflen, "\\%s", tree->t_sharename); 883 if (len == (buflen - 1)) 884 return (ENAMETOOLONG); 885 886 buf += len; 887 buflen -= len; 888 } 889 890 if (node == tree->t_snode) { 891 if (!include_share) 892 (void) strlcpy(buf, "\\", buflen); 893 return (0); 894 } 895 896 rc = smb_node_getshrpath(node, tree, buf, buflen); 897 if (rc == 0) { 898 qinfo->qi_namelen = 899 smb_ascii_or_unicode_strlen(sr, qinfo->qi_name); 900 if (qinfo->qi_namelen == 1) 901 qinfo->qi_namelen = 2; 902 } 903 return (rc); 904 } 905 906 /* 907 * smb_query_shortname 908 * 909 * If the node is a named stream, use its associated 910 * unnamed stream name to determine the shortname. 911 * If a shortname is required (smb_needs_mangle()), generate it 912 * using smb_mangle(), otherwise, convert the original name to 913 * upper-case and return it as the alternative name. 914 */ 915 void 916 smb_query_shortname(smb_node_t *node, smb_queryinfo_t *qinfo) 917 { 918 char *namep; 919 920 if (SMB_IS_STREAM(node)) 921 namep = node->n_unode->od_name; 922 else 923 namep = node->od_name; 924 925 if (smb_needs_mangled(namep)) { 926 smb_mangle(namep, qinfo->qi_attr.sa_vattr.va_nodeid, 927 qinfo->qi_shortname, SMB_SHORTNAMELEN); 928 } else { 929 (void) strlcpy(qinfo->qi_shortname, namep, SMB_SHORTNAMELEN); 930 (void) smb_strupr(qinfo->qi_shortname); 931 } 932 } 933 934 /* 935 * smb_query_pipeinfo 936 * 937 * Populate smb_queryinfo_t structure for SMB_FTYPE_MESG_PIPE 938 * (This should become an smb_opipe function.) 939 */ 940 static int 941 smb_query_pipeinfo(smb_request_t *sr, smb_opipe_t *opipe, uint16_t infolev, 942 smb_queryinfo_t *qinfo) 943 { 944 char *namep = opipe->p_name; 945 946 (void) bzero(qinfo, sizeof (smb_queryinfo_t)); 947 qinfo->qi_node = NULL; 948 qinfo->qi_attr.sa_vattr.va_nlink = 1; 949 qinfo->qi_delete_on_close = 1; 950 qinfo->qi_isdir = 0; 951 952 if ((infolev == SMB_INFO_STANDARD) || 953 (infolev == SMB_INFO_QUERY_EA_SIZE) || 954 (infolev == SMB_QUERY_INFORMATION2)) { 955 qinfo->qi_attr.sa_dosattr = 0; 956 } else { 957 qinfo->qi_attr.sa_dosattr = FILE_ATTRIBUTE_NORMAL; 958 } 959 960 /* If the leading \ is missing from the pipe name, add it. */ 961 if (*namep != '\\') 962 (void) snprintf(qinfo->qi_name, MAXNAMELEN, "\\%s", namep); 963 else 964 (void) strlcpy(qinfo->qi_name, namep, MAXNAMELEN); 965 966 qinfo->qi_namelen= 967 smb_ascii_or_unicode_strlen(sr, qinfo->qi_name); 968 969 return (0); 970 } 971 972 /* 973 * smb_query_pipe_valid_infolev 974 * 975 * If the infolev is not valid for a message pipe, the error 976 * information is set in sr and B_FALSE is returned. 977 * Otherwise, returns B_TRUE. 978 */ 979 static boolean_t 980 smb_query_pipe_valid_infolev(smb_request_t *sr, uint16_t infolev) 981 { 982 switch (infolev) { 983 case SMB_INFO_QUERY_ALL_EAS: 984 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 985 ERRDOS, ERROR_ACCESS_DENIED); 986 return (B_FALSE); 987 988 case SMB_QUERY_FILE_ALT_NAME_INFO: 989 case SMB_FILE_ALT_NAME_INFORMATION: 990 case SMB_QUERY_FILE_STREAM_INFO: 991 case SMB_FILE_STREAM_INFORMATION: 992 case SMB_QUERY_FILE_COMPRESSION_INFO: 993 case SMB_FILE_COMPRESSION_INFORMATION: 994 case SMB_FILE_NETWORK_OPEN_INFORMATION: 995 case SMB_FILE_ATTR_TAG_INFORMATION: 996 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 997 ERRDOS, ERROR_INVALID_PARAMETER); 998 return (B_FALSE); 999 } 1000 1001 return (B_TRUE); 1002 }