1/* 2 Unix SMB/CIFS implementation. 3 client trans2 operations 4 Copyright (C) James Myers 2003 5 Copyright (C) Andrew Tridgell 2003 6 Copyright (C) James Peach 2007 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "libcli/raw/libcliraw.h" 24#include "libcli/raw/raw_proto.h" 25#include "librpc/gen_ndr/ndr_security.h" 26 27/* local macros to make the code more readable */ 28#define FINFO_CHECK_MIN_SIZE(size) if (blob->length < (size)) { \ 29 DEBUG(1,("Unexpected FILEINFO reply size %d for level %u - expected min of %d\n", \ 30 (int)blob->length, parms->generic.level, (size))); \ 31 return NT_STATUS_INFO_LENGTH_MISMATCH; \ 32} 33#define FINFO_CHECK_SIZE(size) if (blob->length != (size)) { \ 34 DEBUG(1,("Unexpected FILEINFO reply size %d for level %u - expected %d\n", \ 35 (int)blob->length, parms->generic.level, (size))); \ 36 return NT_STATUS_INFO_LENGTH_MISMATCH; \ 37} 38 39/* 40 parse a stream information structure 41*/ 42NTSTATUS smbcli_parse_stream_info(DATA_BLOB blob, TALLOC_CTX *mem_ctx, 43 struct stream_information *io) 44{ 45 uint32_t ofs = 0; 46 io->num_streams = 0; 47 io->streams = NULL; 48 49 while (blob.length - ofs >= 24) { 50 uint_t n = io->num_streams; 51 uint32_t nlen, len; 52 bool ret; 53 void *vstr; 54 io->streams = 55 talloc_realloc(mem_ctx, io->streams, struct stream_struct, n+1); 56 if (!io->streams) { 57 return NT_STATUS_NO_MEMORY; 58 } 59 nlen = IVAL(blob.data, ofs + 0x04); 60 io->streams[n].size = BVAL(blob.data, ofs + 0x08); 61 io->streams[n].alloc_size = BVAL(blob.data, ofs + 0x10); 62 if (nlen > blob.length - (ofs + 24)) { 63 return NT_STATUS_INFO_LENGTH_MISMATCH; 64 } 65 ret = convert_string_talloc(io->streams, 66 CH_UTF16, CH_UNIX, 67 blob.data+ofs+24, nlen, &vstr, NULL, false); 68 if (!ret) { 69 return NT_STATUS_ILLEGAL_CHARACTER; 70 } 71 io->streams[n].stream_name.s = (const char *)vstr; 72 io->streams[n].stream_name.private_length = nlen; 73 io->num_streams++; 74 len = IVAL(blob.data, ofs); 75 if (len > blob.length - ofs) { 76 return NT_STATUS_INFO_LENGTH_MISMATCH; 77 } 78 if (len == 0) break; 79 ofs += len; 80 } 81 82 return NT_STATUS_OK; 83} 84 85/* 86 parse the fsinfo 'passthru' level replies 87*/ 88NTSTATUS smb_raw_fileinfo_passthru_parse(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 89 enum smb_fileinfo_level level, 90 union smb_fileinfo *parms) 91{ 92 switch (level) { 93 case RAW_FILEINFO_BASIC_INFORMATION: 94 /* some servers return 40 bytes and some 36. w2k3 return 40, so thats 95 what we should do, but we need to accept 36 */ 96 if (blob->length != 36) { 97 FINFO_CHECK_SIZE(40); 98 } 99 parms->basic_info.out.create_time = smbcli_pull_nttime(blob->data, 0); 100 parms->basic_info.out.access_time = smbcli_pull_nttime(blob->data, 8); 101 parms->basic_info.out.write_time = smbcli_pull_nttime(blob->data, 16); 102 parms->basic_info.out.change_time = smbcli_pull_nttime(blob->data, 24); 103 parms->basic_info.out.attrib = IVAL(blob->data, 32); 104 return NT_STATUS_OK; 105 106 case RAW_FILEINFO_STANDARD_INFORMATION: 107 FINFO_CHECK_SIZE(24); 108 parms->standard_info.out.alloc_size = BVAL(blob->data, 0); 109 parms->standard_info.out.size = BVAL(blob->data, 8); 110 parms->standard_info.out.nlink = IVAL(blob->data, 16); 111 parms->standard_info.out.delete_pending = CVAL(blob->data, 20); 112 parms->standard_info.out.directory = CVAL(blob->data, 21); 113 return NT_STATUS_OK; 114 115 case RAW_FILEINFO_EA_INFORMATION: 116 FINFO_CHECK_SIZE(4); 117 parms->ea_info.out.ea_size = IVAL(blob->data, 0); 118 return NT_STATUS_OK; 119 120 case RAW_FILEINFO_NAME_INFORMATION: 121 FINFO_CHECK_MIN_SIZE(4); 122 smbcli_blob_pull_string(NULL, mem_ctx, blob, 123 &parms->name_info.out.fname, 0, 4, STR_UNICODE); 124 return NT_STATUS_OK; 125 126 case RAW_FILEINFO_ALL_INFORMATION: 127 FINFO_CHECK_MIN_SIZE(72); 128 parms->all_info.out.create_time = smbcli_pull_nttime(blob->data, 0); 129 parms->all_info.out.access_time = smbcli_pull_nttime(blob->data, 8); 130 parms->all_info.out.write_time = smbcli_pull_nttime(blob->data, 16); 131 parms->all_info.out.change_time = smbcli_pull_nttime(blob->data, 24); 132 parms->all_info.out.attrib = IVAL(blob->data, 32); 133 parms->all_info.out.alloc_size = BVAL(blob->data, 40); 134 parms->all_info.out.size = BVAL(blob->data, 48); 135 parms->all_info.out.nlink = IVAL(blob->data, 56); 136 parms->all_info.out.delete_pending = CVAL(blob->data, 60); 137 parms->all_info.out.directory = CVAL(blob->data, 61); 138#if 1 139 parms->all_info.out.ea_size = IVAL(blob->data, 64); 140 smbcli_blob_pull_string(NULL, mem_ctx, blob, 141 &parms->all_info.out.fname, 68, 72, STR_UNICODE); 142#else 143 /* this is what the CIFS spec says - and its totally 144 wrong, but its useful having it here so we can 145 quickly adapt to broken servers when running 146 tests */ 147 parms->all_info.out.ea_size = IVAL(blob->data, 72); 148 /* access flags 4 bytes at 76 149 current_position 8 bytes at 80 150 mode 4 bytes at 88 151 alignment 4 bytes at 92 152 */ 153 smbcli_blob_pull_string(NULL, mem_ctx, blob, 154 &parms->all_info.out.fname, 96, 100, STR_UNICODE); 155#endif 156 return NT_STATUS_OK; 157 158 case RAW_FILEINFO_ALT_NAME_INFORMATION: 159 FINFO_CHECK_MIN_SIZE(4); 160 smbcli_blob_pull_string(NULL, mem_ctx, blob, 161 &parms->alt_name_info.out.fname, 0, 4, STR_UNICODE); 162 return NT_STATUS_OK; 163 164 case RAW_FILEINFO_STREAM_INFORMATION: 165 return smbcli_parse_stream_info(*blob, mem_ctx, &parms->stream_info.out); 166 167 case RAW_FILEINFO_INTERNAL_INFORMATION: 168 FINFO_CHECK_SIZE(8); 169 parms->internal_information.out.file_id = BVAL(blob->data, 0); 170 return NT_STATUS_OK; 171 172 case RAW_FILEINFO_ACCESS_INFORMATION: 173 FINFO_CHECK_SIZE(4); 174 parms->access_information.out.access_flags = IVAL(blob->data, 0); 175 return NT_STATUS_OK; 176 177 case RAW_FILEINFO_POSITION_INFORMATION: 178 FINFO_CHECK_SIZE(8); 179 parms->position_information.out.position = BVAL(blob->data, 0); 180 return NT_STATUS_OK; 181 182 case RAW_FILEINFO_MODE_INFORMATION: 183 FINFO_CHECK_SIZE(4); 184 parms->mode_information.out.mode = IVAL(blob->data, 0); 185 return NT_STATUS_OK; 186 187 case RAW_FILEINFO_ALIGNMENT_INFORMATION: 188 FINFO_CHECK_SIZE(4); 189 parms->alignment_information.out.alignment_requirement 190 = IVAL(blob->data, 0); 191 return NT_STATUS_OK; 192 193 case RAW_FILEINFO_COMPRESSION_INFORMATION: 194 FINFO_CHECK_SIZE(16); 195 parms->compression_info.out.compressed_size = BVAL(blob->data, 0); 196 parms->compression_info.out.format = SVAL(blob->data, 8); 197 parms->compression_info.out.unit_shift = CVAL(blob->data, 10); 198 parms->compression_info.out.chunk_shift = CVAL(blob->data, 11); 199 parms->compression_info.out.cluster_shift = CVAL(blob->data, 12); 200 /* 3 bytes of padding */ 201 return NT_STATUS_OK; 202 203 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION: 204 FINFO_CHECK_SIZE(56); 205 parms->network_open_information.out.create_time = smbcli_pull_nttime(blob->data, 0); 206 parms->network_open_information.out.access_time = smbcli_pull_nttime(blob->data, 8); 207 parms->network_open_information.out.write_time = smbcli_pull_nttime(blob->data, 16); 208 parms->network_open_information.out.change_time = smbcli_pull_nttime(blob->data, 24); 209 parms->network_open_information.out.alloc_size = BVAL(blob->data, 32); 210 parms->network_open_information.out.size = BVAL(blob->data, 40); 211 parms->network_open_information.out.attrib = IVAL(blob->data, 48); 212 return NT_STATUS_OK; 213 214 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION: 215 FINFO_CHECK_SIZE(8); 216 parms->attribute_tag_information.out.attrib = IVAL(blob->data, 0); 217 parms->attribute_tag_information.out.reparse_tag = IVAL(blob->data, 4); 218 return NT_STATUS_OK; 219 220 case RAW_FILEINFO_SMB2_ALL_EAS: 221 FINFO_CHECK_MIN_SIZE(4); 222 return ea_pull_list_chained(blob, mem_ctx, 223 &parms->all_eas.out.num_eas, 224 &parms->all_eas.out.eas); 225 226 case RAW_FILEINFO_SMB2_ALL_INFORMATION: 227 FINFO_CHECK_MIN_SIZE(0x64); 228 parms->all_info2.out.create_time = smbcli_pull_nttime(blob->data, 0x00); 229 parms->all_info2.out.access_time = smbcli_pull_nttime(blob->data, 0x08); 230 parms->all_info2.out.write_time = smbcli_pull_nttime(blob->data, 0x10); 231 parms->all_info2.out.change_time = smbcli_pull_nttime(blob->data, 0x18); 232 parms->all_info2.out.attrib = IVAL(blob->data, 0x20); 233 parms->all_info2.out.unknown1 = IVAL(blob->data, 0x24); 234 parms->all_info2.out.alloc_size = BVAL(blob->data, 0x28); 235 parms->all_info2.out.size = BVAL(blob->data, 0x30); 236 parms->all_info2.out.nlink = IVAL(blob->data, 0x38); 237 parms->all_info2.out.delete_pending = CVAL(blob->data, 0x3C); 238 parms->all_info2.out.directory = CVAL(blob->data, 0x3D); 239 /* 0x3E-0x3F padding */ 240 parms->all_info2.out.file_id = BVAL(blob->data, 0x40); 241 parms->all_info2.out.ea_size = IVAL(blob->data, 0x48); 242 parms->all_info2.out.access_mask = IVAL(blob->data, 0x4C); 243 parms->all_info2.out.position = BVAL(blob->data, 0x50); 244 parms->all_info2.out.mode = IVAL(blob->data, 0x58); 245 parms->all_info2.out.alignment_requirement = IVAL(blob->data, 0x5C); 246 smbcli_blob_pull_string(NULL, mem_ctx, blob, 247 &parms->all_info2.out.fname, 0x60, 0x64, STR_UNICODE); 248 return NT_STATUS_OK; 249 250 case RAW_FILEINFO_SEC_DESC: { 251 enum ndr_err_code ndr_err; 252 253 parms->query_secdesc.out.sd = talloc(mem_ctx, struct security_descriptor); 254 NT_STATUS_HAVE_NO_MEMORY(parms->query_secdesc.out.sd); 255 256 ndr_err = ndr_pull_struct_blob(blob, mem_ctx, NULL, 257 parms->query_secdesc.out.sd, 258 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); 259 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 260 return ndr_map_error2ntstatus(ndr_err); 261 } 262 263 return NT_STATUS_OK; 264 } 265 266 default: 267 break; 268 } 269 270 return NT_STATUS_INVALID_LEVEL; 271} 272 273 274/**************************************************************************** 275 Handle qfileinfo/qpathinfo trans2 backend. 276****************************************************************************/ 277static NTSTATUS smb_raw_info_backend(struct smbcli_session *session, 278 TALLOC_CTX *mem_ctx, 279 union smb_fileinfo *parms, 280 DATA_BLOB *blob) 281{ 282 switch (parms->generic.level) { 283 case RAW_FILEINFO_GENERIC: 284 case RAW_FILEINFO_GETATTR: 285 case RAW_FILEINFO_GETATTRE: 286 case RAW_FILEINFO_SEC_DESC: 287 /* not handled here */ 288 return NT_STATUS_INVALID_LEVEL; 289 290 case RAW_FILEINFO_STANDARD: 291 FINFO_CHECK_SIZE(22); 292 parms->standard.out.create_time = raw_pull_dos_date2(session->transport, 293 blob->data + 0); 294 parms->standard.out.access_time = raw_pull_dos_date2(session->transport, 295 blob->data + 4); 296 parms->standard.out.write_time = raw_pull_dos_date2(session->transport, 297 blob->data + 8); 298 parms->standard.out.size = IVAL(blob->data, 12); 299 parms->standard.out.alloc_size = IVAL(blob->data, 16); 300 parms->standard.out.attrib = SVAL(blob->data, 20); 301 return NT_STATUS_OK; 302 303 case RAW_FILEINFO_EA_SIZE: 304 FINFO_CHECK_SIZE(26); 305 parms->ea_size.out.create_time = raw_pull_dos_date2(session->transport, 306 blob->data + 0); 307 parms->ea_size.out.access_time = raw_pull_dos_date2(session->transport, 308 blob->data + 4); 309 parms->ea_size.out.write_time = raw_pull_dos_date2(session->transport, 310 blob->data + 8); 311 parms->ea_size.out.size = IVAL(blob->data, 12); 312 parms->ea_size.out.alloc_size = IVAL(blob->data, 16); 313 parms->ea_size.out.attrib = SVAL(blob->data, 20); 314 parms->ea_size.out.ea_size = IVAL(blob->data, 22); 315 return NT_STATUS_OK; 316 317 case RAW_FILEINFO_EA_LIST: 318 FINFO_CHECK_MIN_SIZE(4); 319 return ea_pull_list(blob, mem_ctx, 320 &parms->ea_list.out.num_eas, 321 &parms->ea_list.out.eas); 322 323 case RAW_FILEINFO_ALL_EAS: 324 FINFO_CHECK_MIN_SIZE(4); 325 return ea_pull_list(blob, mem_ctx, 326 &parms->all_eas.out.num_eas, 327 &parms->all_eas.out.eas); 328 329 case RAW_FILEINFO_IS_NAME_VALID: 330 /* no data! */ 331 FINFO_CHECK_SIZE(0); 332 return NT_STATUS_OK; 333 334 case RAW_FILEINFO_BASIC_INFO: 335 case RAW_FILEINFO_BASIC_INFORMATION: 336 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 337 RAW_FILEINFO_BASIC_INFORMATION, parms); 338 339 case RAW_FILEINFO_STANDARD_INFO: 340 case RAW_FILEINFO_STANDARD_INFORMATION: 341 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 342 RAW_FILEINFO_STANDARD_INFORMATION, parms); 343 344 case RAW_FILEINFO_EA_INFO: 345 case RAW_FILEINFO_EA_INFORMATION: 346 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 347 RAW_FILEINFO_EA_INFORMATION, parms); 348 349 case RAW_FILEINFO_NAME_INFO: 350 case RAW_FILEINFO_NAME_INFORMATION: 351 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 352 RAW_FILEINFO_NAME_INFORMATION, parms); 353 354 case RAW_FILEINFO_ALL_INFO: 355 case RAW_FILEINFO_ALL_INFORMATION: 356 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 357 RAW_FILEINFO_ALL_INFORMATION, parms); 358 359 case RAW_FILEINFO_ALT_NAME_INFO: 360 case RAW_FILEINFO_ALT_NAME_INFORMATION: 361 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 362 RAW_FILEINFO_ALT_NAME_INFORMATION, parms); 363 364 case RAW_FILEINFO_STREAM_INFO: 365 case RAW_FILEINFO_STREAM_INFORMATION: 366 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 367 RAW_FILEINFO_STREAM_INFORMATION, parms); 368 369 case RAW_FILEINFO_INTERNAL_INFORMATION: 370 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 371 RAW_FILEINFO_INTERNAL_INFORMATION, parms); 372 373 case RAW_FILEINFO_ACCESS_INFORMATION: 374 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 375 RAW_FILEINFO_ACCESS_INFORMATION, parms); 376 377 case RAW_FILEINFO_POSITION_INFORMATION: 378 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 379 RAW_FILEINFO_POSITION_INFORMATION, parms); 380 381 case RAW_FILEINFO_MODE_INFORMATION: 382 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 383 RAW_FILEINFO_MODE_INFORMATION, parms); 384 385 case RAW_FILEINFO_ALIGNMENT_INFORMATION: 386 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 387 RAW_FILEINFO_ALIGNMENT_INFORMATION, parms); 388 389 case RAW_FILEINFO_COMPRESSION_INFO: 390 case RAW_FILEINFO_COMPRESSION_INFORMATION: 391 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 392 RAW_FILEINFO_COMPRESSION_INFORMATION, parms); 393 394 case RAW_FILEINFO_UNIX_BASIC: 395 FINFO_CHECK_SIZE(100); 396 parms->unix_basic_info.out.end_of_file = BVAL(blob->data, 0); 397 parms->unix_basic_info.out.num_bytes = BVAL(blob->data, 8); 398 parms->unix_basic_info.out.status_change_time = smbcli_pull_nttime(blob->data, 16); 399 parms->unix_basic_info.out.access_time = smbcli_pull_nttime(blob->data, 24); 400 parms->unix_basic_info.out.change_time = smbcli_pull_nttime(blob->data, 32); 401 parms->unix_basic_info.out.uid = BVAL(blob->data, 40); 402 parms->unix_basic_info.out.gid = BVAL(blob->data, 48); 403 parms->unix_basic_info.out.file_type = IVAL(blob->data, 52); 404 parms->unix_basic_info.out.dev_major = BVAL(blob->data, 60); 405 parms->unix_basic_info.out.dev_minor = BVAL(blob->data, 68); 406 parms->unix_basic_info.out.unique_id = BVAL(blob->data, 76); 407 parms->unix_basic_info.out.permissions = BVAL(blob->data, 84); 408 parms->unix_basic_info.out.nlink = BVAL(blob->data, 92); 409 return NT_STATUS_OK; 410 411 case RAW_FILEINFO_UNIX_INFO2: 412 FINFO_CHECK_SIZE(116); 413 parms->unix_info2.out.end_of_file = BVAL(blob->data, 0); 414 parms->unix_info2.out.num_bytes = BVAL(blob->data, 8); 415 parms->unix_info2.out.status_change_time = smbcli_pull_nttime(blob->data, 16); 416 parms->unix_info2.out.access_time = smbcli_pull_nttime(blob->data, 24); 417 parms->unix_info2.out.change_time = smbcli_pull_nttime(blob->data, 32); 418 parms->unix_info2.out.uid = BVAL(blob->data, 40); 419 parms->unix_info2.out.gid = BVAL(blob->data, 48); 420 parms->unix_info2.out.file_type = IVAL(blob->data, 52); 421 parms->unix_info2.out.dev_major = BVAL(blob->data, 60); 422 parms->unix_info2.out.dev_minor = BVAL(blob->data, 68); 423 parms->unix_info2.out.unique_id = BVAL(blob->data, 76); 424 parms->unix_info2.out.permissions = BVAL(blob->data, 84); 425 parms->unix_info2.out.nlink = BVAL(blob->data, 92); 426 parms->unix_info2.out.create_time = smbcli_pull_nttime(blob->data, 100); 427 parms->unix_info2.out.file_flags = IVAL(blob->data, 108); 428 parms->unix_info2.out.flags_mask = IVAL(blob->data, 112); 429 return NT_STATUS_OK; 430 431 case RAW_FILEINFO_UNIX_LINK: 432 smbcli_blob_pull_string(session, mem_ctx, blob, 433 &parms->unix_link_info.out.link_dest, 0, 4, STR_UNICODE); 434 return NT_STATUS_OK; 435 436 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION: 437 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 438 RAW_FILEINFO_NETWORK_OPEN_INFORMATION, parms); 439 440 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION: 441 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 442 RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION, parms); 443 444 case RAW_FILEINFO_SMB2_ALL_INFORMATION: 445 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 446 RAW_FILEINFO_SMB2_ALL_INFORMATION, parms); 447 448 case RAW_FILEINFO_SMB2_ALL_EAS: 449 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 450 RAW_FILEINFO_SMB2_ALL_EAS, parms); 451 452 } 453 454 return NT_STATUS_INVALID_LEVEL; 455} 456 457 458/**************************************************************************** 459 Very raw query file info - returns param/data blobs - (async send) 460****************************************************************************/ 461static struct smbcli_request *smb_raw_fileinfo_blob_send(struct smbcli_tree *tree, 462 uint16_t fnum, 463 uint16_t info_level, 464 DATA_BLOB data) 465{ 466 struct smb_trans2 tp; 467 uint16_t setup = TRANSACT2_QFILEINFO; 468 struct smbcli_request *req; 469 TALLOC_CTX *mem_ctx = talloc_init("raw_fileinfo"); 470 471 tp.in.max_setup = 0; 472 tp.in.flags = 0; 473 tp.in.timeout = 0; 474 tp.in.setup_count = 1; 475 tp.in.data = data; 476 tp.in.max_param = 2; 477 tp.in.max_data = 0xFFFF; 478 tp.in.setup = &setup; 479 480 tp.in.params = data_blob_talloc(mem_ctx, NULL, 4); 481 if (!tp.in.params.data) { 482 talloc_free(mem_ctx); 483 return NULL; 484 } 485 486 SSVAL(tp.in.params.data, 0, fnum); 487 SSVAL(tp.in.params.data, 2, info_level); 488 489 req = smb_raw_trans2_send(tree, &tp); 490 491 talloc_free(mem_ctx); 492 493 return req; 494} 495 496 497/**************************************************************************** 498 Very raw query file info - returns param/data blobs - (async recv) 499****************************************************************************/ 500static NTSTATUS smb_raw_fileinfo_blob_recv(struct smbcli_request *req, 501 TALLOC_CTX *mem_ctx, 502 DATA_BLOB *blob) 503{ 504 struct smb_trans2 tp; 505 NTSTATUS status = smb_raw_trans2_recv(req, mem_ctx, &tp); 506 if (NT_STATUS_IS_OK(status)) { 507 *blob = tp.out.data; 508 } 509 return status; 510} 511 512/**************************************************************************** 513 Very raw query path info - returns param/data blobs (async send) 514****************************************************************************/ 515static struct smbcli_request *smb_raw_pathinfo_blob_send(struct smbcli_tree *tree, 516 const char *fname, 517 uint16_t info_level, 518 DATA_BLOB data) 519{ 520 struct smb_trans2 tp; 521 uint16_t setup = TRANSACT2_QPATHINFO; 522 struct smbcli_request *req; 523 TALLOC_CTX *mem_ctx = talloc_init("raw_pathinfo"); 524 525 tp.in.max_setup = 0; 526 tp.in.flags = 0; 527 tp.in.timeout = 0; 528 tp.in.setup_count = 1; 529 tp.in.data = data; 530 tp.in.max_param = 2; 531 tp.in.max_data = 0xFFFF; 532 tp.in.setup = &setup; 533 534 tp.in.params = data_blob_talloc(mem_ctx, NULL, 6); 535 if (!tp.in.params.data) { 536 talloc_free(mem_ctx); 537 return NULL; 538 } 539 540 SSVAL(tp.in.params.data, 0, info_level); 541 SIVAL(tp.in.params.data, 2, 0); 542 smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params, 543 fname, STR_TERMINATE); 544 545 req = smb_raw_trans2_send(tree, &tp); 546 547 talloc_free(mem_ctx); 548 549 return req; 550} 551 552/**************************************************************************** 553 send a SMBgetatr (async send) 554****************************************************************************/ 555static struct smbcli_request *smb_raw_getattr_send(struct smbcli_tree *tree, 556 union smb_fileinfo *parms) 557{ 558 struct smbcli_request *req; 559 560 req = smbcli_request_setup(tree, SMBgetatr, 0, 0); 561 if (!req) return NULL; 562 563 smbcli_req_append_ascii4(req, parms->getattr.in.file.path, STR_TERMINATE); 564 565 if (!smbcli_request_send(req)) { 566 smbcli_request_destroy(req); 567 return NULL; 568 } 569 570 return req; 571} 572 573/**************************************************************************** 574 send a SMBgetatr (async recv) 575****************************************************************************/ 576static NTSTATUS smb_raw_getattr_recv(struct smbcli_request *req, 577 union smb_fileinfo *parms) 578{ 579 if (!smbcli_request_receive(req) || 580 smbcli_request_is_error(req)) { 581 return smbcli_request_destroy(req); 582 } 583 584 SMBCLI_CHECK_WCT(req, 10); 585 parms->getattr.out.attrib = SVAL(req->in.vwv, VWV(0)); 586 parms->getattr.out.write_time = raw_pull_dos_date3(req->transport, 587 req->in.vwv + VWV(1)); 588 parms->getattr.out.size = IVAL(req->in.vwv, VWV(3)); 589 590failed: 591 return smbcli_request_destroy(req); 592} 593 594 595/**************************************************************************** 596 Handle SMBgetattrE (async send) 597****************************************************************************/ 598static struct smbcli_request *smb_raw_getattrE_send(struct smbcli_tree *tree, 599 union smb_fileinfo *parms) 600{ 601 struct smbcli_request *req; 602 603 req = smbcli_request_setup(tree, SMBgetattrE, 1, 0); 604 if (!req) return NULL; 605 606 SSVAL(req->out.vwv, VWV(0), parms->getattre.in.file.fnum); 607 if (!smbcli_request_send(req)) { 608 smbcli_request_destroy(req); 609 return NULL; 610 } 611 612 return req; 613} 614 615/**************************************************************************** 616 Handle SMBgetattrE (async send) 617****************************************************************************/ 618static NTSTATUS smb_raw_getattrE_recv(struct smbcli_request *req, 619 union smb_fileinfo *parms) 620{ 621 if (!smbcli_request_receive(req) || 622 smbcli_request_is_error(req)) { 623 return smbcli_request_destroy(req); 624 } 625 626 SMBCLI_CHECK_WCT(req, 11); 627 parms->getattre.out.create_time = raw_pull_dos_date2(req->transport, 628 req->in.vwv + VWV(0)); 629 parms->getattre.out.access_time = raw_pull_dos_date2(req->transport, 630 req->in.vwv + VWV(2)); 631 parms->getattre.out.write_time = raw_pull_dos_date2(req->transport, 632 req->in.vwv + VWV(4)); 633 parms->getattre.out.size = IVAL(req->in.vwv, VWV(6)); 634 parms->getattre.out.alloc_size = IVAL(req->in.vwv, VWV(8)); 635 parms->getattre.out.attrib = SVAL(req->in.vwv, VWV(10)); 636 637failed: 638 return smbcli_request_destroy(req); 639} 640 641 642/**************************************************************************** 643 Query file info (async send) 644****************************************************************************/ 645struct smbcli_request *smb_raw_fileinfo_send(struct smbcli_tree *tree, 646 union smb_fileinfo *parms) 647{ 648 DATA_BLOB data; 649 struct smbcli_request *req; 650 651 /* pass off the non-trans2 level to specialised functions */ 652 if (parms->generic.level == RAW_FILEINFO_GETATTRE) { 653 return smb_raw_getattrE_send(tree, parms); 654 } 655 if (parms->generic.level == RAW_FILEINFO_SEC_DESC) { 656 return smb_raw_query_secdesc_send(tree, parms); 657 } 658 if (parms->generic.level >= RAW_FILEINFO_GENERIC) { 659 return NULL; 660 } 661 662 data = data_blob(NULL, 0); 663 664 if (parms->generic.level == RAW_FILEINFO_EA_LIST) { 665 if (!ea_push_name_list(tree, 666 &data, 667 parms->ea_list.in.num_names, 668 parms->ea_list.in.ea_names)) { 669 return NULL; 670 } 671 } 672 673 req = smb_raw_fileinfo_blob_send(tree, 674 parms->generic.in.file.fnum, 675 parms->generic.level, data); 676 677 data_blob_free(&data); 678 679 return req; 680} 681 682/**************************************************************************** 683 Query file info (async recv) 684****************************************************************************/ 685NTSTATUS smb_raw_fileinfo_recv(struct smbcli_request *req, 686 TALLOC_CTX *mem_ctx, 687 union smb_fileinfo *parms) 688{ 689 DATA_BLOB blob; 690 NTSTATUS status; 691 struct smbcli_session *session = req?req->session:NULL; 692 693 if (parms->generic.level == RAW_FILEINFO_GETATTRE) { 694 return smb_raw_getattrE_recv(req, parms); 695 } 696 if (parms->generic.level == RAW_FILEINFO_SEC_DESC) { 697 return smb_raw_query_secdesc_recv(req, mem_ctx, parms); 698 } 699 if (parms->generic.level == RAW_FILEINFO_GETATTR) { 700 return smb_raw_getattr_recv(req, parms); 701 } 702 703 status = smb_raw_fileinfo_blob_recv(req, mem_ctx, &blob); 704 if (!NT_STATUS_IS_OK(status)) { 705 return status; 706 } 707 708 return smb_raw_info_backend(session, mem_ctx, parms, &blob); 709} 710 711/**************************************************************************** 712 Query file info (sync interface) 713****************************************************************************/ 714_PUBLIC_ NTSTATUS smb_raw_fileinfo(struct smbcli_tree *tree, 715 TALLOC_CTX *mem_ctx, 716 union smb_fileinfo *parms) 717{ 718 struct smbcli_request *req = smb_raw_fileinfo_send(tree, parms); 719 return smb_raw_fileinfo_recv(req, mem_ctx, parms); 720} 721 722/**************************************************************************** 723 Query path info (async send) 724****************************************************************************/ 725_PUBLIC_ struct smbcli_request *smb_raw_pathinfo_send(struct smbcli_tree *tree, 726 union smb_fileinfo *parms) 727{ 728 DATA_BLOB data; 729 struct smbcli_request *req; 730 731 if (parms->generic.level == RAW_FILEINFO_GETATTR) { 732 return smb_raw_getattr_send(tree, parms); 733 } 734 if (parms->generic.level >= RAW_FILEINFO_GENERIC) { 735 return NULL; 736 } 737 738 data = data_blob(NULL, 0); 739 740 if (parms->generic.level == RAW_FILEINFO_EA_LIST) { 741 if (!ea_push_name_list(tree, 742 &data, 743 parms->ea_list.in.num_names, 744 parms->ea_list.in.ea_names)) { 745 return NULL; 746 } 747 } 748 749 req = smb_raw_pathinfo_blob_send(tree, parms->generic.in.file.path, 750 parms->generic.level, data); 751 data_blob_free(&data); 752 753 return req; 754} 755 756/**************************************************************************** 757 Query path info (async recv) 758****************************************************************************/ 759_PUBLIC_ NTSTATUS smb_raw_pathinfo_recv(struct smbcli_request *req, 760 TALLOC_CTX *mem_ctx, 761 union smb_fileinfo *parms) 762{ 763 /* recv is idential to fileinfo */ 764 return smb_raw_fileinfo_recv(req, mem_ctx, parms); 765} 766 767/**************************************************************************** 768 Query path info (sync interface) 769****************************************************************************/ 770_PUBLIC_ NTSTATUS smb_raw_pathinfo(struct smbcli_tree *tree, 771 TALLOC_CTX *mem_ctx, 772 union smb_fileinfo *parms) 773{ 774 struct smbcli_request *req = smb_raw_pathinfo_send(tree, parms); 775 return smb_raw_pathinfo_recv(req, mem_ctx, parms); 776} 777