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 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <smbsrv/smb_kproto.h> 26 #include <smbsrv/smb_vops.h> 27 #include <smbsrv/smb_fsops.h> 28 29 /* 30 * Trans2 Query File/Path Information Levels: 31 * 32 * SMB_INFO_STANDARD 33 * SMB_INFO_QUERY_EA_SIZE 34 * SMB_INFO_QUERY_EAS_FROM_LIST 35 * SMB_INFO_QUERY_ALL_EAS - not valid for pipes 36 * SMB_INFO_IS_NAME_VALID - only valid when query is by path 37 * 38 * SMB_QUERY_FILE_BASIC_INFO 39 * SMB_QUERY_FILE_STANDARD_INFO 40 * SMB_QUERY_FILE_EA_INFO 41 * SMB_QUERY_FILE_NAME_INFO 42 * SMB_QUERY_FILE_ALL_INFO 43 * SMB_QUERY_FILE_ALT_NAME_INFO - not valid for pipes 44 * SMB_QUERY_FILE_STREAM_INFO - not valid for pipes 45 * SMB_QUERY_FILE_COMPRESSION_INFO - not valid for pipes 46 * 47 * Supported Passthrough levels: 48 * SMB_FILE_BASIC_INFORMATION 49 * SMB_FILE_STANDARD_INFORMATION 50 * SMB_FILE_INTERNAL_INFORMATION 51 * SMB_FILE_EA_INFORMATION 52 * SMB_FILE_ACCESS_INFORMATION - not yet supported quen query by path 53 * SMB_FILE_NAME_INFORMATION 54 * SMB_FILE_ALL_INFORMATION 55 * SMB_FILE_ALT_NAME_INFORMATION - not valid for pipes 56 * SMB_FILE_STREAM_INFORMATION - not valid for pipes 57 * SMB_FILE_COMPRESSION_INFORMATION - not valid for pipes 58 * SMB_FILE_NETWORK_OPEN_INFORMATION - not valid for pipes 59 * SMB_FILE_ATTR_TAG_INFORMATION - not valid for pipes 60 * 61 * Internal levels representing non trans2 requests 62 * SMB_QUERY_INFORMATION 63 * SMB_QUERY_INFORMATION2 64 */ 65 66 typedef struct smb_queryinfo { 67 smb_node_t *qi_node; /* NULL for pipes */ 68 smb_attr_t qi_attr; 69 boolean_t qi_delete_on_close; 70 uint32_t qi_namelen; 71 char qi_name83[SMB_SHORTNAMELEN]; 72 char qi_shortname[SMB_SHORTNAMELEN]; 73 char qi_name[MAXPATHLEN]; 74 } smb_queryinfo_t; 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 void smb_encode_stream_info(smb_request_t *, smb_xa_t *, 92 smb_queryinfo_t *); 93 static int smb_query_pathname(smb_tree_t *, smb_node_t *, boolean_t, 94 char *, size_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_2(op__QueryInformation__start, smb_request_t *, sr, 153 smb_fqi_t *, fqi); 154 155 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 156 } 157 158 void 159 smb_post_query_information(smb_request_t *sr) 160 { 161 DTRACE_SMB_1(op__QueryInformation__done, smb_request_t *, sr); 162 } 163 164 smb_sdrc_t 165 smb_com_query_information(smb_request_t *sr) 166 { 167 uint16_t infolev = SMB_QUERY_INFORMATION; 168 169 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 170 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 171 ERRDOS, ERROR_ACCESS_DENIED); 172 return (SDRC_ERROR); 173 } 174 175 if (smb_query_by_path(sr, NULL, infolev) != 0) 176 return (SDRC_ERROR); 177 178 return (SDRC_SUCCESS); 179 } 180 181 /* 182 * smb_com_query_information2 (aka getattre) 183 */ 184 smb_sdrc_t 185 smb_pre_query_information2(smb_request_t *sr) 186 { 187 int rc; 188 rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid); 189 190 DTRACE_SMB_1(op__QueryInformation2__start, smb_request_t *, sr); 191 192 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 193 } 194 195 void 196 smb_post_query_information2(smb_request_t *sr) 197 { 198 DTRACE_SMB_1(op__QueryInformation2__done, smb_request_t *, sr); 199 } 200 201 smb_sdrc_t 202 smb_com_query_information2(smb_request_t *sr) 203 { 204 uint16_t infolev = SMB_QUERY_INFORMATION2; 205 206 if (smb_query_by_fid(sr, NULL, infolev) != 0) 207 return (SDRC_ERROR); 208 209 return (SDRC_SUCCESS); 210 } 211 212 /* 213 * smb_query_by_fid 214 * 215 * Common code for querying file information by open file (or pipe) id. 216 * Use the id to identify the node / pipe object and request the 217 * smb_queryinfo_t data for that object. 218 */ 219 static int 220 smb_query_by_fid(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev) 221 { 222 int rc; 223 smb_queryinfo_t *qinfo; 224 smb_node_t *node; 225 smb_opipe_t *opipe; 226 227 smbsr_lookup_file(sr); 228 229 if (sr->fid_ofile == NULL) { 230 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 231 return (-1); 232 } 233 234 if (infolev == SMB_INFO_IS_NAME_VALID) { 235 smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); 236 smbsr_release_file(sr); 237 return (-1); 238 } 239 240 if ((sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE) && 241 (!smb_query_pipe_valid_infolev(sr, infolev))) { 242 smbsr_release_file(sr); 243 return (-1); 244 } 245 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 /* VALID, but not yet supported */ 294 if (infolev == SMB_FILE_ACCESS_INFORMATION) { 295 smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); 296 return (-1); 297 } 298 299 pn = &sr->arg.dirop.fqi.fq_path; 300 smb_pathname_init(sr, pn, pn->pn_path); 301 if (!smb_pathname_validate(sr, pn)) 302 return (-1); 303 304 qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP); 305 306 rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path, 307 sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode, 308 qinfo->qi_name); 309 310 if (rc == 0) { 311 rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS, 312 sr->tid_tree->t_snode, dnode, qinfo->qi_name, &node); 313 smb_node_release(dnode); 314 } 315 316 if (rc != 0) { 317 if (rc == ENOENT) 318 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 319 ERRDOS, ERROR_FILE_NOT_FOUND); 320 else 321 smbsr_errno(sr, rc); 322 323 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 324 return (-1); 325 } 326 327 if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) { 328 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); 329 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 330 smb_node_release(node); 331 return (-1); 332 } 333 334 rc = smb_query_fileinfo(sr, node, infolev, qinfo); 335 if (rc != 0) { 336 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 337 smb_node_release(node); 338 return (rc); 339 } 340 341 /* If delete_on_close - NT_STATUS_DELETE_PENDING */ 342 if (qinfo->qi_delete_on_close) { 343 smbsr_error(sr, NT_STATUS_DELETE_PENDING, 344 ERRDOS, ERROR_ACCESS_DENIED); 345 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 346 smb_node_release(node); 347 return (-1); 348 } 349 350 rc = smb_query_encode_response(sr, xa, infolev, qinfo); 351 kmem_free(qinfo, sizeof (smb_queryinfo_t)); 352 smb_node_release(node); 353 return (rc); 354 } 355 356 /* 357 * smb_size32 358 * Some responses only support 32 bit file sizes. If the file size 359 * exceeds UINT_MAX (32 bit) we return UINT_MAX in the response. 360 */ 361 static uint32_t 362 smb_size32(u_offset_t size) 363 { 364 return ((size > UINT_MAX) ? UINT_MAX : (uint32_t)size); 365 } 366 367 /* 368 * smb_query_encode_response 369 * 370 * Encode the data from smb_queryinfo_t into client response 371 */ 372 int 373 smb_query_encode_response(smb_request_t *sr, smb_xa_t *xa, 374 uint16_t infolev, smb_queryinfo_t *qinfo) 375 { 376 uint16_t dattr; 377 u_offset_t datasz, allocsz; 378 uint32_t isdir; 379 380 dattr = qinfo->qi_attr.sa_dosattr & FILE_ATTRIBUTE_MASK; 381 datasz = qinfo->qi_attr.sa_vattr.va_size; 382 allocsz = qinfo->qi_attr.sa_allocsz; 383 isdir = ((dattr & FILE_ATTRIBUTE_DIRECTORY) != 0); 384 385 switch (infolev) { 386 case SMB_QUERY_INFORMATION: 387 (void) smbsr_encode_result(sr, 10, 0, "bwll10.w", 388 10, 389 dattr, 390 smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 391 smb_size32(datasz), 392 0); 393 break; 394 395 case SMB_QUERY_INFORMATION2: 396 (void) smbsr_encode_result(sr, 11, 0, "byyyllww", 397 11, 398 smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec), 399 smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec), 400 smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 401 smb_size32(datasz), smb_size32(allocsz), dattr, 0); 402 break; 403 404 case SMB_FILE_ACCESS_INFORMATION: 405 ASSERT(sr->fid_ofile); 406 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 407 sr->fid_ofile->f_granted_access); 408 break; 409 410 case SMB_INFO_STANDARD: 411 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 412 (void) smb_mbc_encodef(&xa->rep_data_mb, 413 ((sr->session->native_os == NATIVE_OS_WIN95) ? 414 "YYYllw" : "yyyllw"), 415 smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec), 416 smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec), 417 smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 418 smb_size32(datasz), smb_size32(allocsz), dattr); 419 break; 420 421 case SMB_INFO_QUERY_EA_SIZE: 422 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 423 (void) smb_mbc_encodef(&xa->rep_data_mb, 424 ((sr->session->native_os == NATIVE_OS_WIN95) ? 425 "YYYllwl" : "yyyllwl"), 426 smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec), 427 smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec), 428 smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec), 429 smb_size32(datasz), smb_size32(allocsz), dattr, 0); 430 break; 431 432 case SMB_INFO_QUERY_ALL_EAS: 433 case SMB_INFO_QUERY_EAS_FROM_LIST: 434 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 435 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 436 break; 437 438 case SMB_INFO_IS_NAME_VALID: 439 break; 440 441 case SMB_QUERY_FILE_BASIC_INFO: 442 case SMB_FILE_BASIC_INFORMATION: 443 /* 444 * NT includes 6 bytes (spec says 4) at the end of this 445 * response, which are required by NetBench 5.01. 446 */ 447 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 448 (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.", 449 &qinfo->qi_crtime, 450 &qinfo->qi_atime, 451 &qinfo->qi_mtime, 452 &qinfo->qi_ctime, 453 dattr); 454 break; 455 456 case SMB_QUERY_FILE_STANDARD_INFO: 457 case SMB_FILE_STANDARD_INFORMATION: 458 /* 2-byte pad at end */ 459 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 460 (void) smb_mbc_encodef(&xa->rep_data_mb, "qqlbb2.", 461 (uint64_t)allocsz, 462 (uint64_t)datasz, 463 qinfo->qi_attr.sa_vattr.va_nlink, 464 qinfo->qi_delete_on_close, 465 (uint8_t)isdir); 466 break; 467 468 case SMB_QUERY_FILE_EA_INFO: 469 case SMB_FILE_EA_INFORMATION: 470 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 471 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 472 break; 473 474 case SMB_QUERY_FILE_NAME_INFO: 475 case SMB_FILE_NAME_INFORMATION: 476 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 477 (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", sr, 478 qinfo->qi_namelen, qinfo->qi_name); 479 break; 480 481 case SMB_QUERY_FILE_ALL_INFO: 482 case SMB_FILE_ALL_INFORMATION: 483 /* 484 * There is a 6-byte pad between Attributes and AllocationSize, 485 * and a 2-byte pad after the Directory field. 486 */ 487 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 488 (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.qqlbb2.l", 489 &qinfo->qi_crtime, 490 &qinfo->qi_atime, 491 &qinfo->qi_mtime, 492 &qinfo->qi_ctime, 493 dattr, 494 (uint64_t)allocsz, 495 (uint64_t)datasz, 496 qinfo->qi_attr.sa_vattr.va_nlink, 497 qinfo->qi_delete_on_close, 498 isdir, 499 0); 500 501 (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", 502 sr, qinfo->qi_namelen, qinfo->qi_name); 503 break; 504 505 case SMB_QUERY_FILE_ALT_NAME_INFO: 506 case SMB_FILE_ALT_NAME_INFORMATION: 507 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 508 (void) smb_mbc_encodef(&xa->rep_data_mb, "%lU", sr, 509 smb_wcequiv_strlen(qinfo->qi_shortname), 510 qinfo->qi_shortname); 511 break; 512 513 case SMB_QUERY_FILE_STREAM_INFO: 514 case SMB_FILE_STREAM_INFORMATION: 515 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 516 smb_encode_stream_info(sr, xa, qinfo); 517 break; 518 519 case SMB_QUERY_FILE_COMPRESSION_INFO: 520 case SMB_FILE_COMPRESSION_INFORMATION: 521 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 522 (void) smb_mbc_encodef(&xa->rep_data_mb, "qwbbb3.", 523 datasz, 0, 0, 0, 0); 524 break; 525 526 case SMB_FILE_INTERNAL_INFORMATION: 527 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 528 (void) smb_mbc_encodef(&xa->rep_data_mb, "q", 529 qinfo->qi_attr.sa_vattr.va_nodeid); 530 break; 531 532 case SMB_FILE_NETWORK_OPEN_INFORMATION: 533 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 534 (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTqql4.", 535 &qinfo->qi_crtime, 536 &qinfo->qi_atime, 537 &qinfo->qi_mtime, 538 &qinfo->qi_ctime, 539 (uint64_t)allocsz, 540 (uint64_t)datasz, 541 (uint32_t)dattr); 542 break; 543 544 case SMB_FILE_ATTR_TAG_INFORMATION: 545 /* 546 * If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the 547 * second dword should be the reparse tag. Otherwise 548 * the tag value should be set to zero. 549 * We don't support reparse points, so we set the tag 550 * to zero. 551 */ 552 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 553 (void) smb_mbc_encodef(&xa->rep_data_mb, "ll", 554 (uint32_t)dattr, 0); 555 break; 556 557 default: 558 if ((infolev > 1000) && smb_query_passthru) 559 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, 560 ERRDOS, ERROR_NOT_SUPPORTED); 561 else 562 smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); 563 return (-1); 564 } 565 566 return (0); 567 } 568 569 /* 570 * smb_encode_stream_info 571 * 572 * This function encodes the streams information. 573 * The following rules about how have been derived from observed NT 574 * behaviour. 575 * 576 * If the target is a file: 577 * 1. If there are no named streams, the response should still contain 578 * an entry for the unnamed stream. 579 * 2. If there are named streams, the response should contain an entry 580 * for the unnamed stream followed by the entries for the named 581 * streams. 582 * 583 * If the target is a directory: 584 * 1. If there are no streams, the response is complete. Directories 585 * do not report the unnamed stream. 586 * 2. If there are streams, the response should contain entries for 587 * those streams but there should not be an entry for the unnamed 588 * stream. 589 * 590 * Note that the stream name lengths exclude the null terminator but 591 * the field lengths (i.e. next offset calculations) need to include 592 * the null terminator and be padded to a multiple of 8 bytes. The 593 * last entry does not seem to need any padding. 594 * 595 * If an error is encountered when trying to read the stream entries 596 * (smb_odir_read_streaminfo) it is treated as if there are no [more] 597 * entries. The entries that have been read so far are returned and 598 * no error is reported. 599 * 600 * Offset calculation: 601 * 2 dwords + 2 quadwords => 4 + 4 + 8 + 8 => 24 602 */ 603 static void 604 smb_encode_stream_info(smb_request_t *sr, smb_xa_t *xa, smb_queryinfo_t *qinfo) 605 { 606 char *stream_name; 607 uint32_t next_offset; 608 uint32_t stream_nlen; 609 uint32_t pad; 610 u_offset_t datasz, allocsz; 611 boolean_t is_dir; 612 smb_streaminfo_t *sinfo, *sinfo_next; 613 int rc = 0; 614 boolean_t done = B_FALSE; 615 boolean_t eos = B_FALSE; 616 uint16_t odid; 617 smb_odir_t *od = NULL; 618 619 smb_node_t *fnode = qinfo->qi_node; 620 smb_attr_t *attr = &qinfo->qi_attr; 621 622 ASSERT(fnode); 623 if (SMB_IS_STREAM(fnode)) { 624 fnode = fnode->n_unode; 625 ASSERT(fnode); 626 } 627 ASSERT(fnode->n_magic == SMB_NODE_MAGIC); 628 ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING); 629 630 sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP); 631 sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP); 632 is_dir = ((attr->sa_dosattr & FILE_ATTRIBUTE_DIRECTORY) != 0); 633 datasz = attr->sa_vattr.va_size; 634 allocsz = attr->sa_allocsz; 635 636 odid = smb_odir_openat(sr, fnode); 637 if (odid != 0) 638 od = smb_tree_lookup_odir(sr->tid_tree, odid); 639 if (od != NULL) 640 rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos); 641 642 if ((od == NULL) || (rc != 0) || (eos)) 643 done = B_TRUE; 644 645 /* If not a directory, encode an entry for the unnamed stream. */ 646 if (!is_dir) { 647 stream_name = "::$DATA"; 648 stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name); 649 650 if (done) 651 next_offset = 0; 652 else 653 next_offset = 24 + stream_nlen + 654 smb_ascii_or_unicode_null_len(sr); 655 656 (void) smb_mbc_encodef(&xa->rep_data_mb, "%llqqu", sr, 657 next_offset, stream_nlen, datasz, allocsz, stream_name); 658 } 659 660 /* 661 * Since last packet does not have a pad we need to check 662 * for the next stream before we encode the current one 663 */ 664 while (!done) { 665 stream_nlen = smb_ascii_or_unicode_strlen(sr, sinfo->si_name); 666 sinfo_next->si_name[0] = 0; 667 668 rc = smb_odir_read_streaminfo(sr, od, sinfo_next, &eos); 669 if ((rc != 0) || (eos)) { 670 done = B_TRUE; 671 next_offset = 0; 672 pad = 0; 673 } else { 674 next_offset = 24 + stream_nlen + 675 smb_ascii_or_unicode_null_len(sr); 676 pad = smb_pad_align(next_offset, 8); 677 next_offset += pad; 678 } 679 (void) smb_mbc_encodef(&xa->rep_data_mb, "%llqqu#.", 680 sr, next_offset, stream_nlen, 681 sinfo->si_size, sinfo->si_alloc_size, 682 sinfo->si_name, pad); 683 684 (void) memcpy(sinfo, sinfo_next, sizeof (smb_streaminfo_t)); 685 } 686 687 kmem_free(sinfo, sizeof (smb_streaminfo_t)); 688 kmem_free(sinfo_next, sizeof (smb_streaminfo_t)); 689 if (od) { 690 smb_odir_close(od); 691 smb_odir_release(od); 692 } 693 } 694 695 /* 696 * smb_query_pathname 697 * 698 * Determine the absolute pathname of 'node' within the share. 699 * For some levels (e.g. ALL_INFO) the pathname should include the 700 * sharename for others (e.g. NAME_INFO) the pathname should be 701 * relative to the share. 702 * For example if the node represents file "test1.txt" in directory 703 * "dir1" on share "share1" 704 * - if include_share is TRUE the pathname would be: \share1\dir1\test1.txt 705 * - if include_share is FALSE the pathname would be: \dir1\test1.txt 706 */ 707 static int 708 smb_query_pathname(smb_tree_t *tree, smb_node_t *node, boolean_t include_share, 709 char *buf, size_t buflen) 710 { 711 char *sharename = tree->t_sharename; 712 int rc; 713 size_t len; 714 715 if (include_share) { 716 len = snprintf(buf, buflen, "\\%s", sharename); 717 if (len == (buflen - 1)) 718 return (ENAMETOOLONG); 719 720 buf += len; 721 buflen -= len; 722 } 723 724 if (node == tree->t_snode) { 725 if (!include_share) 726 (void) strlcpy(buf, "\\", buflen); 727 return (0); 728 } 729 730 rc = smb_node_getshrpath(node, tree, buf, buflen); 731 return (rc); 732 } 733 734 /* 735 * smb_query_fileinfo 736 * 737 * Populate smb_queryinfo_t structure for SMB_FTYPE_DISK 738 * (This should become an smb_ofile / smb_node function.) 739 */ 740 int 741 smb_query_fileinfo(smb_request_t *sr, smb_node_t *node, uint16_t infolev, 742 smb_queryinfo_t *qinfo) 743 { 744 int rc; 745 boolean_t include_sharename = B_FALSE; 746 char *namep; 747 748 (void) bzero(qinfo, sizeof (smb_queryinfo_t)); 749 750 if (smb_node_getattr(sr, node, &qinfo->qi_attr) != 0) { 751 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 752 ERRDOS, ERROR_INTERNAL_ERROR); 753 return (-1); 754 } 755 756 qinfo->qi_node = node; 757 qinfo->qi_delete_on_close = 758 (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0; 759 760 /* 761 * The number of links reported should be the number of 762 * non-deleted links. Thus if delete_on_close is set, 763 * decrement the link count. 764 */ 765 if (qinfo->qi_delete_on_close && 766 qinfo->qi_attr.sa_vattr.va_nlink > 0) { 767 --(qinfo->qi_attr.sa_vattr.va_nlink); 768 } 769 770 /* populate name, namelen and shortname */ 771 772 /* ALL_INFO levels include the sharename in the name field */ 773 if ((infolev == SMB_QUERY_FILE_ALL_INFO) || 774 (infolev == SMB_FILE_ALL_INFORMATION)) { 775 include_sharename = B_TRUE; 776 } 777 778 rc = smb_query_pathname(sr->tid_tree, node, include_sharename, 779 qinfo->qi_name, MAXPATHLEN); 780 if (rc != 0) { 781 smbsr_errno(sr, rc); 782 return (-1); 783 } 784 785 qinfo->qi_namelen = smb_ascii_or_unicode_strlen(sr, qinfo->qi_name); 786 787 /* 788 * For some reason NT will not show the security tab in the root 789 * directory of a mapped drive unless the filename length is 790 * greater than one. So we hack the length here to persuade NT 791 * to show the tab. It should be safe because of the null 792 * terminator character. 793 */ 794 if (qinfo->qi_namelen == 1) 795 qinfo->qi_namelen = 2; 796 797 /* 798 * If the node is an named stream, use its associated 799 * unnamed stream name to determine the shortname. 800 * If the shortname is generated by smb_mangle_name() 801 * it will be returned as the alternative name. 802 * Otherwise, convert the original name to upper-case 803 * and return it as the alternative name. 804 */ 805 if (SMB_IS_STREAM(node)) 806 namep = node->n_unode->od_name; 807 else 808 namep = node->od_name; 809 810 (void) smb_mangle_name(qinfo->qi_attr.sa_vattr.va_nodeid, 811 namep, qinfo->qi_shortname, qinfo->qi_name83, 0); 812 if (*qinfo->qi_shortname == 0) { 813 (void) strlcpy(qinfo->qi_shortname, namep, 814 SMB_SHORTNAMELEN); 815 (void) smb_strupr(qinfo->qi_shortname); 816 } 817 818 return (0); 819 } 820 821 /* 822 * smb_query_pipeinfo 823 * 824 * Populate smb_queryinfo_t structure for SMB_FTYPE_MESG_PIPE 825 * (This should become an smb_opipe function.) 826 */ 827 static int 828 smb_query_pipeinfo(smb_request_t *sr, smb_opipe_t *opipe, uint16_t infolev, 829 smb_queryinfo_t *qinfo) 830 { 831 char *namep = opipe->p_name; 832 833 (void) bzero(qinfo, sizeof (smb_queryinfo_t)); 834 qinfo->qi_node = NULL; 835 qinfo->qi_attr.sa_vattr.va_nlink = 1; 836 qinfo->qi_delete_on_close = 1; 837 838 if ((infolev == SMB_INFO_STANDARD) || 839 (infolev == SMB_INFO_QUERY_EA_SIZE) || 840 (infolev == SMB_QUERY_INFORMATION2)) { 841 qinfo->qi_attr.sa_dosattr = 0; 842 } else { 843 qinfo->qi_attr.sa_dosattr = FILE_ATTRIBUTE_NORMAL; 844 } 845 846 /* If the leading \ is missing from the pipe name, add it. */ 847 if (*namep != '\\') 848 (void) snprintf(qinfo->qi_name, MAXNAMELEN, "\\%s", namep); 849 else 850 (void) strlcpy(qinfo->qi_name, namep, MAXNAMELEN); 851 852 qinfo->qi_namelen= 853 smb_ascii_or_unicode_strlen(sr, qinfo->qi_name); 854 855 return (0); 856 } 857 858 /* 859 * smb_query_pipe_valid_infolev 860 * 861 * If the infolev is not valid for a message pipe, the error 862 * information is set in sr and B_FALSE is returned. 863 * Otherwise, returns B_TRUE. 864 */ 865 static boolean_t 866 smb_query_pipe_valid_infolev(smb_request_t *sr, uint16_t infolev) 867 { 868 switch (infolev) { 869 case SMB_INFO_QUERY_ALL_EAS: 870 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 871 ERRDOS, ERROR_ACCESS_DENIED); 872 return (B_FALSE); 873 874 case SMB_QUERY_FILE_ALT_NAME_INFO: 875 case SMB_FILE_ALT_NAME_INFORMATION: 876 case SMB_QUERY_FILE_STREAM_INFO: 877 case SMB_FILE_STREAM_INFORMATION: 878 case SMB_QUERY_FILE_COMPRESSION_INFO: 879 case SMB_FILE_COMPRESSION_INFORMATION: 880 case SMB_FILE_NETWORK_OPEN_INFORMATION: 881 case SMB_FILE_ATTR_TAG_INFORMATION: 882 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 883 ERRDOS, ERROR_INVALID_PARAMETER); 884 return (B_FALSE); 885 } 886 887 return (B_TRUE); 888 } 889