1/* 2 Unix SMB/CIFS implementation. 3 client file operations 4 Copyright (C) Andrew Tridgell 1994-1998 5 Copyright (C) Jeremy Allison 2001-2002 6 Copyright (C) James Myers 2003 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#define SETUP_REQUEST(cmd, wct, buflen) do { \ 28 req = smbcli_request_setup(tree, cmd, wct, buflen); \ 29 if (!req) return NULL; \ 30} while (0) 31 32/** 33 Return a string representing a CIFS attribute for a file. 34**/ 35char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib) 36{ 37 int i, len; 38 const struct { 39 char c; 40 uint16_t attr; 41 } attr_strs[] = { 42 {'V', FILE_ATTRIBUTE_VOLUME}, 43 {'D', FILE_ATTRIBUTE_DIRECTORY}, 44 {'A', FILE_ATTRIBUTE_ARCHIVE}, 45 {'H', FILE_ATTRIBUTE_HIDDEN}, 46 {'S', FILE_ATTRIBUTE_SYSTEM}, 47 {'N', FILE_ATTRIBUTE_NORMAL}, 48 {'R', FILE_ATTRIBUTE_READONLY}, 49 {'d', FILE_ATTRIBUTE_DEVICE}, 50 {'t', FILE_ATTRIBUTE_TEMPORARY}, 51 {'s', FILE_ATTRIBUTE_SPARSE}, 52 {'r', FILE_ATTRIBUTE_REPARSE_POINT}, 53 {'c', FILE_ATTRIBUTE_COMPRESSED}, 54 {'o', FILE_ATTRIBUTE_OFFLINE}, 55 {'n', FILE_ATTRIBUTE_NONINDEXED}, 56 {'e', FILE_ATTRIBUTE_ENCRYPTED} 57 }; 58 char *ret; 59 60 ret = talloc_array(mem_ctx, char, ARRAY_SIZE(attr_strs)+1); 61 if (!ret) { 62 return NULL; 63 } 64 65 for (len=i=0; i<ARRAY_SIZE(attr_strs); i++) { 66 if (attrib & attr_strs[i].attr) { 67 ret[len++] = attr_strs[i].c; 68 } 69 } 70 71 ret[len] = 0; 72 73 talloc_set_name_const(ret, ret); 74 75 return ret; 76} 77 78/**************************************************************************** 79 Rename a file - async interface 80****************************************************************************/ 81struct smbcli_request *smb_raw_rename_send(struct smbcli_tree *tree, 82 union smb_rename *parms) 83{ 84 struct smbcli_request *req = NULL; 85 struct smb_nttrans nt; 86 TALLOC_CTX *mem_ctx; 87 88 switch (parms->generic.level) { 89 case RAW_RENAME_RENAME: 90 SETUP_REQUEST(SMBmv, 1, 0); 91 SSVAL(req->out.vwv, VWV(0), parms->rename.in.attrib); 92 smbcli_req_append_ascii4(req, parms->rename.in.pattern1, STR_TERMINATE); 93 smbcli_req_append_ascii4(req, parms->rename.in.pattern2, STR_TERMINATE); 94 break; 95 96 case RAW_RENAME_NTRENAME: 97 SETUP_REQUEST(SMBntrename, 4, 0); 98 SSVAL(req->out.vwv, VWV(0), parms->ntrename.in.attrib); 99 SSVAL(req->out.vwv, VWV(1), parms->ntrename.in.flags); 100 SIVAL(req->out.vwv, VWV(2), parms->ntrename.in.cluster_size); 101 smbcli_req_append_ascii4(req, parms->ntrename.in.old_name, STR_TERMINATE); 102 smbcli_req_append_ascii4(req, parms->ntrename.in.new_name, STR_TERMINATE); 103 break; 104 105 case RAW_RENAME_NTTRANS: 106 107 mem_ctx = talloc_new(tree); 108 109 nt.in.max_setup = 0; 110 nt.in.max_param = 0; 111 nt.in.max_data = 0; 112 nt.in.setup_count = 0; 113 nt.in.setup = NULL; 114 nt.in.function = NT_TRANSACT_RENAME; 115 nt.in.params = data_blob_talloc(mem_ctx, NULL, 4); 116 nt.in.data = data_blob(NULL, 0); 117 118 SSVAL(nt.in.params.data, VWV(0), parms->nttrans.in.file.fnum); 119 SSVAL(nt.in.params.data, VWV(1), parms->nttrans.in.flags); 120 121 smbcli_blob_append_string(tree->session, mem_ctx, 122 &nt.in.params, parms->nttrans.in.new_name, 123 STR_TERMINATE); 124 125 req = smb_raw_nttrans_send(tree, &nt); 126 talloc_free(mem_ctx); 127 return req; 128 } 129 130 if (!smbcli_request_send(req)) { 131 smbcli_request_destroy(req); 132 return NULL; 133 } 134 135 return req; 136} 137 138/**************************************************************************** 139 Rename a file - sync interface 140****************************************************************************/ 141_PUBLIC_ NTSTATUS smb_raw_rename(struct smbcli_tree *tree, 142 union smb_rename *parms) 143{ 144 struct smbcli_request *req = smb_raw_rename_send(tree, parms); 145 return smbcli_request_simple_recv(req); 146} 147 148 149/**************************************************************************** 150 Delete a file - async interface 151****************************************************************************/ 152struct smbcli_request *smb_raw_unlink_send(struct smbcli_tree *tree, 153 union smb_unlink *parms) 154{ 155 struct smbcli_request *req; 156 157 SETUP_REQUEST(SMBunlink, 1, 0); 158 159 SSVAL(req->out.vwv, VWV(0), parms->unlink.in.attrib); 160 smbcli_req_append_ascii4(req, parms->unlink.in.pattern, STR_TERMINATE); 161 162 if (!smbcli_request_send(req)) { 163 smbcli_request_destroy(req); 164 return NULL; 165 } 166 return req; 167} 168 169/* 170 delete a file - sync interface 171*/ 172_PUBLIC_ NTSTATUS smb_raw_unlink(struct smbcli_tree *tree, 173 union smb_unlink *parms) 174{ 175 struct smbcli_request *req = smb_raw_unlink_send(tree, parms); 176 return smbcli_request_simple_recv(req); 177} 178 179 180/**************************************************************************** 181 create a directory using TRANSACT2_MKDIR - async interface 182****************************************************************************/ 183static struct smbcli_request *smb_raw_t2mkdir_send(struct smbcli_tree *tree, 184 union smb_mkdir *parms) 185{ 186 struct smb_trans2 t2; 187 uint16_t setup = TRANSACT2_MKDIR; 188 TALLOC_CTX *mem_ctx; 189 struct smbcli_request *req; 190 uint16_t data_total; 191 192 mem_ctx = talloc_init("t2mkdir"); 193 194 data_total = ea_list_size(parms->t2mkdir.in.num_eas, parms->t2mkdir.in.eas); 195 196 t2.in.max_param = 2; 197 t2.in.max_data = 0; 198 t2.in.max_setup = 0; 199 t2.in.flags = 0; 200 t2.in.timeout = 0; 201 t2.in.setup_count = 1; 202 t2.in.setup = &setup; 203 t2.in.params = data_blob_talloc(mem_ctx, NULL, 4); 204 t2.in.data = data_blob_talloc(mem_ctx, NULL, data_total); 205 206 SIVAL(t2.in.params.data, VWV(0), 0); /* reserved */ 207 208 smbcli_blob_append_string(tree->session, mem_ctx, 209 &t2.in.params, parms->t2mkdir.in.path, STR_TERMINATE); 210 211 ea_put_list(t2.in.data.data, parms->t2mkdir.in.num_eas, parms->t2mkdir.in.eas); 212 213 req = smb_raw_trans2_send(tree, &t2); 214 215 talloc_free(mem_ctx); 216 217 return req; 218} 219 220/**************************************************************************** 221 Create a directory - async interface 222****************************************************************************/ 223struct smbcli_request *smb_raw_mkdir_send(struct smbcli_tree *tree, 224 union smb_mkdir *parms) 225{ 226 struct smbcli_request *req; 227 228 if (parms->generic.level == RAW_MKDIR_T2MKDIR) { 229 return smb_raw_t2mkdir_send(tree, parms); 230 } 231 232 if (parms->generic.level != RAW_MKDIR_MKDIR) { 233 return NULL; 234 } 235 236 SETUP_REQUEST(SMBmkdir, 0, 0); 237 238 smbcli_req_append_ascii4(req, parms->mkdir.in.path, STR_TERMINATE); 239 240 if (!smbcli_request_send(req)) { 241 return NULL; 242 } 243 244 return req; 245} 246 247/**************************************************************************** 248 Create a directory - sync interface 249****************************************************************************/ 250_PUBLIC_ NTSTATUS smb_raw_mkdir(struct smbcli_tree *tree, 251 union smb_mkdir *parms) 252{ 253 struct smbcli_request *req = smb_raw_mkdir_send(tree, parms); 254 return smbcli_request_simple_recv(req); 255} 256 257/**************************************************************************** 258 Remove a directory - async interface 259****************************************************************************/ 260struct smbcli_request *smb_raw_rmdir_send(struct smbcli_tree *tree, 261 struct smb_rmdir *parms) 262{ 263 struct smbcli_request *req; 264 265 SETUP_REQUEST(SMBrmdir, 0, 0); 266 267 smbcli_req_append_ascii4(req, parms->in.path, STR_TERMINATE); 268 269 if (!smbcli_request_send(req)) { 270 smbcli_request_destroy(req); 271 return NULL; 272 } 273 274 return req; 275} 276 277/**************************************************************************** 278 Remove a directory - sync interface 279****************************************************************************/ 280_PUBLIC_ NTSTATUS smb_raw_rmdir(struct smbcli_tree *tree, 281 struct smb_rmdir *parms) 282{ 283 struct smbcli_request *req = smb_raw_rmdir_send(tree, parms); 284 return smbcli_request_simple_recv(req); 285} 286 287 288/* 289 Open a file using TRANSACT2_OPEN - async recv 290*/ 291static NTSTATUS smb_raw_nttrans_create_recv(struct smbcli_request *req, 292 TALLOC_CTX *mem_ctx, 293 union smb_open *parms) 294{ 295 NTSTATUS status; 296 struct smb_nttrans nt; 297 uint8_t *params; 298 299 status = smb_raw_nttrans_recv(req, mem_ctx, &nt); 300 if (!NT_STATUS_IS_OK(status)) return status; 301 302 if (nt.out.params.length < 69) { 303 return NT_STATUS_INVALID_PARAMETER; 304 } 305 306 params = nt.out.params.data; 307 308 parms->ntcreatex.out.oplock_level = CVAL(params, 0); 309 parms->ntcreatex.out.file.fnum = SVAL(params, 2); 310 parms->ntcreatex.out.create_action = IVAL(params, 4); 311 parms->ntcreatex.out.create_time = smbcli_pull_nttime(params, 12); 312 parms->ntcreatex.out.access_time = smbcli_pull_nttime(params, 20); 313 parms->ntcreatex.out.write_time = smbcli_pull_nttime(params, 28); 314 parms->ntcreatex.out.change_time = smbcli_pull_nttime(params, 36); 315 parms->ntcreatex.out.attrib = IVAL(params, 44); 316 parms->ntcreatex.out.alloc_size = BVAL(params, 48); 317 parms->ntcreatex.out.size = BVAL(params, 56); 318 parms->ntcreatex.out.file_type = SVAL(params, 64); 319 parms->ntcreatex.out.ipc_state = SVAL(params, 66); 320 parms->ntcreatex.out.is_directory = CVAL(params, 68); 321 322 return NT_STATUS_OK; 323} 324 325 326/* 327 Open a file using NTTRANS CREATE - async send 328*/ 329static struct smbcli_request *smb_raw_nttrans_create_send(struct smbcli_tree *tree, 330 union smb_open *parms) 331{ 332 struct smb_nttrans nt; 333 uint8_t *params; 334 TALLOC_CTX *mem_ctx = talloc_new(tree); 335 uint16_t fname_len; 336 DATA_BLOB sd_blob, ea_blob; 337 struct smbcli_request *req; 338 339 nt.in.max_setup = 0; 340 nt.in.max_param = 101; 341 nt.in.max_data = 0; 342 nt.in.setup_count = 0; 343 nt.in.function = NT_TRANSACT_CREATE; 344 nt.in.setup = NULL; 345 346 sd_blob = data_blob(NULL, 0); 347 ea_blob = data_blob(NULL, 0); 348 349 if (parms->ntcreatex.in.sec_desc) { 350 enum ndr_err_code ndr_err; 351 ndr_err = ndr_push_struct_blob(&sd_blob, mem_ctx, NULL, 352 parms->ntcreatex.in.sec_desc, 353 (ndr_push_flags_fn_t)ndr_push_security_descriptor); 354 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 355 talloc_free(mem_ctx); 356 return NULL; 357 } 358 } 359 360 if (parms->ntcreatex.in.ea_list) { 361 uint32_t ea_size = ea_list_size_chained(parms->ntcreatex.in.ea_list->num_eas, 362 parms->ntcreatex.in.ea_list->eas, 4); 363 ea_blob = data_blob_talloc(mem_ctx, NULL, ea_size); 364 if (ea_blob.data == NULL) { 365 return NULL; 366 } 367 ea_put_list_chained(ea_blob.data, 368 parms->ntcreatex.in.ea_list->num_eas, 369 parms->ntcreatex.in.ea_list->eas, 4); 370 } 371 372 nt.in.params = data_blob_talloc(mem_ctx, NULL, 53); 373 if (nt.in.params.data == NULL) { 374 talloc_free(mem_ctx); 375 return NULL; 376 } 377 378 /* build the parameter section */ 379 params = nt.in.params.data; 380 381 SIVAL(params, 0, parms->ntcreatex.in.flags); 382 SIVAL(params, 4, parms->ntcreatex.in.root_fid); 383 SIVAL(params, 8, parms->ntcreatex.in.access_mask); 384 SBVAL(params, 12, parms->ntcreatex.in.alloc_size); 385 SIVAL(params, 20, parms->ntcreatex.in.file_attr); 386 SIVAL(params, 24, parms->ntcreatex.in.share_access); 387 SIVAL(params, 28, parms->ntcreatex.in.open_disposition); 388 SIVAL(params, 32, parms->ntcreatex.in.create_options); 389 SIVAL(params, 36, sd_blob.length); 390 SIVAL(params, 40, ea_blob.length); 391 SIVAL(params, 48, parms->ntcreatex.in.impersonation); 392 SCVAL(params, 52, parms->ntcreatex.in.security_flags); 393 394 /* the empty string first forces the correct alignment */ 395 smbcli_blob_append_string(tree->session, mem_ctx, &nt.in.params,"", 0); 396 fname_len = smbcli_blob_append_string(tree->session, mem_ctx, &nt.in.params, 397 parms->ntcreatex.in.fname, STR_TERMINATE); 398 399 SIVAL(nt.in.params.data, 44, fname_len); 400 401 /* build the data section */ 402 nt.in.data = data_blob_talloc(mem_ctx, NULL, sd_blob.length + ea_blob.length); 403 memcpy(nt.in.data.data, sd_blob.data, sd_blob.length); 404 memcpy(nt.in.data.data+sd_blob.length, ea_blob.data, ea_blob.length); 405 406 /* send the request on its way */ 407 req = smb_raw_nttrans_send(tree, &nt); 408 409 talloc_free(mem_ctx); 410 411 return req; 412} 413 414 415/**************************************************************************** 416 Open a file using TRANSACT2_OPEN - async send 417****************************************************************************/ 418static struct smbcli_request *smb_raw_t2open_send(struct smbcli_tree *tree, 419 union smb_open *parms) 420{ 421 struct smb_trans2 t2; 422 uint16_t setup = TRANSACT2_OPEN; 423 TALLOC_CTX *mem_ctx = talloc_init("smb_raw_t2open"); 424 struct smbcli_request *req; 425 uint16_t list_size; 426 427 list_size = ea_list_size(parms->t2open.in.num_eas, parms->t2open.in.eas); 428 429 t2.in.max_param = 30; 430 t2.in.max_data = 0; 431 t2.in.max_setup = 0; 432 t2.in.flags = 0; 433 t2.in.timeout = 0; 434 t2.in.setup_count = 1; 435 t2.in.setup = &setup; 436 t2.in.params = data_blob_talloc(mem_ctx, NULL, 28); 437 t2.in.data = data_blob_talloc(mem_ctx, NULL, list_size); 438 439 SSVAL(t2.in.params.data, VWV(0), parms->t2open.in.flags); 440 SSVAL(t2.in.params.data, VWV(1), parms->t2open.in.open_mode); 441 SSVAL(t2.in.params.data, VWV(2), parms->t2open.in.search_attrs); 442 SSVAL(t2.in.params.data, VWV(3), parms->t2open.in.file_attrs); 443 raw_push_dos_date(tree->session->transport, 444 t2.in.params.data, VWV(4), parms->t2open.in.write_time); 445 SSVAL(t2.in.params.data, VWV(6), parms->t2open.in.open_func); 446 SIVAL(t2.in.params.data, VWV(7), parms->t2open.in.size); 447 SIVAL(t2.in.params.data, VWV(9), parms->t2open.in.timeout); 448 SIVAL(t2.in.params.data, VWV(11), 0); 449 SSVAL(t2.in.params.data, VWV(13), 0); 450 451 smbcli_blob_append_string(tree->session, mem_ctx, 452 &t2.in.params, parms->t2open.in.fname, 453 STR_TERMINATE); 454 455 ea_put_list(t2.in.data.data, parms->t2open.in.num_eas, parms->t2open.in.eas); 456 457 req = smb_raw_trans2_send(tree, &t2); 458 459 talloc_free(mem_ctx); 460 461 return req; 462} 463 464 465/**************************************************************************** 466 Open a file using TRANSACT2_OPEN - async recv 467****************************************************************************/ 468static NTSTATUS smb_raw_t2open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, union smb_open *parms) 469{ 470 struct smbcli_transport *transport = req->transport; 471 struct smb_trans2 t2; 472 NTSTATUS status; 473 474 status = smb_raw_trans2_recv(req, mem_ctx, &t2); 475 if (!NT_STATUS_IS_OK(status)) return status; 476 477 if (t2.out.params.length < 30) { 478 return NT_STATUS_INFO_LENGTH_MISMATCH; 479 } 480 481 parms->t2open.out.file.fnum = SVAL(t2.out.params.data, VWV(0)); 482 parms->t2open.out.attrib = SVAL(t2.out.params.data, VWV(1)); 483 parms->t2open.out.write_time = raw_pull_dos_date3(transport, t2.out.params.data + VWV(2)); 484 parms->t2open.out.size = IVAL(t2.out.params.data, VWV(4)); 485 parms->t2open.out.access = SVAL(t2.out.params.data, VWV(6)); 486 parms->t2open.out.ftype = SVAL(t2.out.params.data, VWV(7)); 487 parms->t2open.out.devstate = SVAL(t2.out.params.data, VWV(8)); 488 parms->t2open.out.action = SVAL(t2.out.params.data, VWV(9)); 489 parms->t2open.out.file_id = SVAL(t2.out.params.data, VWV(10)); 490 491 return NT_STATUS_OK; 492} 493 494/**************************************************************************** 495 Open a file - async send 496****************************************************************************/ 497_PUBLIC_ struct smbcli_request *smb_raw_open_send(struct smbcli_tree *tree, union smb_open *parms) 498{ 499 int len; 500 struct smbcli_request *req = NULL; 501 bool bigoffset = false; 502 503 switch (parms->generic.level) { 504 case RAW_OPEN_T2OPEN: 505 return smb_raw_t2open_send(tree, parms); 506 507 case RAW_OPEN_OPEN: 508 SETUP_REQUEST(SMBopen, 2, 0); 509 SSVAL(req->out.vwv, VWV(0), parms->openold.in.open_mode); 510 SSVAL(req->out.vwv, VWV(1), parms->openold.in.search_attrs); 511 smbcli_req_append_ascii4(req, parms->openold.in.fname, STR_TERMINATE); 512 break; 513 514 case RAW_OPEN_OPENX: 515 SETUP_REQUEST(SMBopenX, 15, 0); 516 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); 517 SSVAL(req->out.vwv, VWV(1), 0); 518 SSVAL(req->out.vwv, VWV(2), parms->openx.in.flags); 519 SSVAL(req->out.vwv, VWV(3), parms->openx.in.open_mode); 520 SSVAL(req->out.vwv, VWV(4), parms->openx.in.search_attrs); 521 SSVAL(req->out.vwv, VWV(5), parms->openx.in.file_attrs); 522 raw_push_dos_date3(tree->session->transport, 523 req->out.vwv, VWV(6), parms->openx.in.write_time); 524 SSVAL(req->out.vwv, VWV(8), parms->openx.in.open_func); 525 SIVAL(req->out.vwv, VWV(9), parms->openx.in.size); 526 SIVAL(req->out.vwv, VWV(11),parms->openx.in.timeout); 527 SIVAL(req->out.vwv, VWV(13),0); /* reserved */ 528 smbcli_req_append_string(req, parms->openx.in.fname, STR_TERMINATE); 529 break; 530 531 case RAW_OPEN_MKNEW: 532 SETUP_REQUEST(SMBmknew, 3, 0); 533 SSVAL(req->out.vwv, VWV(0), parms->mknew.in.attrib); 534 raw_push_dos_date3(tree->session->transport, 535 req->out.vwv, VWV(1), parms->mknew.in.write_time); 536 smbcli_req_append_ascii4(req, parms->mknew.in.fname, STR_TERMINATE); 537 break; 538 539 case RAW_OPEN_CREATE: 540 SETUP_REQUEST(SMBcreate, 3, 0); 541 SSVAL(req->out.vwv, VWV(0), parms->create.in.attrib); 542 raw_push_dos_date3(tree->session->transport, 543 req->out.vwv, VWV(1), parms->create.in.write_time); 544 smbcli_req_append_ascii4(req, parms->create.in.fname, STR_TERMINATE); 545 break; 546 547 case RAW_OPEN_CTEMP: 548 SETUP_REQUEST(SMBctemp, 3, 0); 549 SSVAL(req->out.vwv, VWV(0), parms->ctemp.in.attrib); 550 raw_push_dos_date3(tree->session->transport, 551 req->out.vwv, VWV(1), parms->ctemp.in.write_time); 552 smbcli_req_append_ascii4(req, parms->ctemp.in.directory, STR_TERMINATE); 553 break; 554 555 case RAW_OPEN_SPLOPEN: 556 SETUP_REQUEST(SMBsplopen, 2, 0); 557 SSVAL(req->out.vwv, VWV(0), parms->splopen.in.setup_length); 558 SSVAL(req->out.vwv, VWV(1), parms->splopen.in.mode); 559 break; 560 561 case RAW_OPEN_NTCREATEX: 562 SETUP_REQUEST(SMBntcreateX, 24, 0); 563 SSVAL(req->out.vwv, VWV(0),SMB_CHAIN_NONE); 564 SSVAL(req->out.vwv, VWV(1),0); 565 SCVAL(req->out.vwv, VWV(2),0); /* padding */ 566 SIVAL(req->out.vwv, 7, parms->ntcreatex.in.flags); 567 SIVAL(req->out.vwv, 11, parms->ntcreatex.in.root_fid); 568 SIVAL(req->out.vwv, 15, parms->ntcreatex.in.access_mask); 569 SBVAL(req->out.vwv, 19, parms->ntcreatex.in.alloc_size); 570 SIVAL(req->out.vwv, 27, parms->ntcreatex.in.file_attr); 571 SIVAL(req->out.vwv, 31, parms->ntcreatex.in.share_access); 572 SIVAL(req->out.vwv, 35, parms->ntcreatex.in.open_disposition); 573 SIVAL(req->out.vwv, 39, parms->ntcreatex.in.create_options); 574 SIVAL(req->out.vwv, 43, parms->ntcreatex.in.impersonation); 575 SCVAL(req->out.vwv, 47, parms->ntcreatex.in.security_flags); 576 577 smbcli_req_append_string_len(req, parms->ntcreatex.in.fname, STR_TERMINATE, &len); 578 SSVAL(req->out.vwv, 5, len); 579 break; 580 581 case RAW_OPEN_NTTRANS_CREATE: 582 return smb_raw_nttrans_create_send(tree, parms); 583 584 585 case RAW_OPEN_OPENX_READX: 586 SETUP_REQUEST(SMBopenX, 15, 0); 587 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); 588 SSVAL(req->out.vwv, VWV(1), 0); 589 SSVAL(req->out.vwv, VWV(2), parms->openxreadx.in.flags); 590 SSVAL(req->out.vwv, VWV(3), parms->openxreadx.in.open_mode); 591 SSVAL(req->out.vwv, VWV(4), parms->openxreadx.in.search_attrs); 592 SSVAL(req->out.vwv, VWV(5), parms->openxreadx.in.file_attrs); 593 raw_push_dos_date3(tree->session->transport, 594 req->out.vwv, VWV(6), parms->openxreadx.in.write_time); 595 SSVAL(req->out.vwv, VWV(8), parms->openxreadx.in.open_func); 596 SIVAL(req->out.vwv, VWV(9), parms->openxreadx.in.size); 597 SIVAL(req->out.vwv, VWV(11),parms->openxreadx.in.timeout); 598 SIVAL(req->out.vwv, VWV(13),0); 599 smbcli_req_append_string(req, parms->openxreadx.in.fname, STR_TERMINATE); 600 601 if (tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES) { 602 bigoffset = true; 603 } 604 605 smbcli_chained_request_setup(req, SMBreadX, bigoffset ? 12 : 10, 0); 606 607 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); 608 SSVAL(req->out.vwv, VWV(1), 0); 609 SSVAL(req->out.vwv, VWV(2), 0); 610 SIVAL(req->out.vwv, VWV(3), parms->openxreadx.in.offset); 611 SSVAL(req->out.vwv, VWV(5), parms->openxreadx.in.maxcnt & 0xFFFF); 612 SSVAL(req->out.vwv, VWV(6), parms->openxreadx.in.mincnt); 613 SIVAL(req->out.vwv, VWV(7), parms->openxreadx.in.maxcnt >> 16); 614 SSVAL(req->out.vwv, VWV(9), parms->openxreadx.in.remaining); 615 if (bigoffset) { 616 SIVAL(req->out.vwv, VWV(10),parms->openxreadx.in.offset>>32); 617 } 618 break; 619 case RAW_OPEN_SMB2: 620 return NULL; 621 } 622 623 if (!smbcli_request_send(req)) { 624 smbcli_request_destroy(req); 625 return NULL; 626 } 627 628 return req; 629} 630 631/**************************************************************************** 632 Open a file - async recv 633****************************************************************************/ 634_PUBLIC_ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, union smb_open *parms) 635{ 636 NTSTATUS status; 637 638 if (!smbcli_request_receive(req) || 639 smbcli_request_is_error(req)) { 640 goto failed; 641 } 642 643 switch (parms->openold.level) { 644 case RAW_OPEN_T2OPEN: 645 return smb_raw_t2open_recv(req, mem_ctx, parms); 646 647 case RAW_OPEN_OPEN: 648 SMBCLI_CHECK_WCT(req, 7); 649 parms->openold.out.file.fnum = SVAL(req->in.vwv, VWV(0)); 650 parms->openold.out.attrib = SVAL(req->in.vwv, VWV(1)); 651 parms->openold.out.write_time = raw_pull_dos_date3(req->transport, 652 req->in.vwv + VWV(2)); 653 parms->openold.out.size = IVAL(req->in.vwv, VWV(4)); 654 parms->openold.out.rmode = SVAL(req->in.vwv, VWV(6)); 655 break; 656 657 case RAW_OPEN_OPENX: 658 SMBCLI_CHECK_MIN_WCT(req, 15); 659 parms->openx.out.file.fnum = SVAL(req->in.vwv, VWV(2)); 660 parms->openx.out.attrib = SVAL(req->in.vwv, VWV(3)); 661 parms->openx.out.write_time = raw_pull_dos_date3(req->transport, 662 req->in.vwv + VWV(4)); 663 parms->openx.out.size = IVAL(req->in.vwv, VWV(6)); 664 parms->openx.out.access = SVAL(req->in.vwv, VWV(8)); 665 parms->openx.out.ftype = SVAL(req->in.vwv, VWV(9)); 666 parms->openx.out.devstate = SVAL(req->in.vwv, VWV(10)); 667 parms->openx.out.action = SVAL(req->in.vwv, VWV(11)); 668 parms->openx.out.unique_fid = IVAL(req->in.vwv, VWV(12)); 669 if (req->in.wct >= 19) { 670 parms->openx.out.access_mask = IVAL(req->in.vwv, VWV(15)); 671 parms->openx.out.unknown = IVAL(req->in.vwv, VWV(17)); 672 } else { 673 parms->openx.out.access_mask = 0; 674 parms->openx.out.unknown = 0; 675 } 676 break; 677 678 case RAW_OPEN_MKNEW: 679 SMBCLI_CHECK_WCT(req, 1); 680 parms->mknew.out.file.fnum = SVAL(req->in.vwv, VWV(0)); 681 break; 682 683 case RAW_OPEN_CREATE: 684 SMBCLI_CHECK_WCT(req, 1); 685 parms->create.out.file.fnum = SVAL(req->in.vwv, VWV(0)); 686 break; 687 688 case RAW_OPEN_CTEMP: 689 SMBCLI_CHECK_WCT(req, 1); 690 parms->ctemp.out.file.fnum = SVAL(req->in.vwv, VWV(0)); 691 smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->ctemp.out.name, req->in.data, -1, STR_TERMINATE | STR_ASCII); 692 break; 693 694 case RAW_OPEN_SPLOPEN: 695 SMBCLI_CHECK_WCT(req, 1); 696 parms->splopen.out.file.fnum = SVAL(req->in.vwv, VWV(0)); 697 break; 698 699 case RAW_OPEN_NTCREATEX: 700 SMBCLI_CHECK_MIN_WCT(req, 34); 701 parms->ntcreatex.out.oplock_level = CVAL(req->in.vwv, 4); 702 parms->ntcreatex.out.file.fnum = SVAL(req->in.vwv, 5); 703 parms->ntcreatex.out.create_action = IVAL(req->in.vwv, 7); 704 parms->ntcreatex.out.create_time = smbcli_pull_nttime(req->in.vwv, 11); 705 parms->ntcreatex.out.access_time = smbcli_pull_nttime(req->in.vwv, 19); 706 parms->ntcreatex.out.write_time = smbcli_pull_nttime(req->in.vwv, 27); 707 parms->ntcreatex.out.change_time = smbcli_pull_nttime(req->in.vwv, 35); 708 parms->ntcreatex.out.attrib = IVAL(req->in.vwv, 43); 709 parms->ntcreatex.out.alloc_size = BVAL(req->in.vwv, 47); 710 parms->ntcreatex.out.size = BVAL(req->in.vwv, 55); 711 parms->ntcreatex.out.file_type = SVAL(req->in.vwv, 63); 712 parms->ntcreatex.out.ipc_state = SVAL(req->in.vwv, 65); 713 parms->ntcreatex.out.is_directory = CVAL(req->in.vwv, 67); 714 break; 715 716 case RAW_OPEN_NTTRANS_CREATE: 717 return smb_raw_nttrans_create_recv(req, mem_ctx, parms); 718 719 case RAW_OPEN_OPENX_READX: 720 SMBCLI_CHECK_MIN_WCT(req, 15); 721 parms->openxreadx.out.file.fnum = SVAL(req->in.vwv, VWV(2)); 722 parms->openxreadx.out.attrib = SVAL(req->in.vwv, VWV(3)); 723 parms->openxreadx.out.write_time = raw_pull_dos_date3(req->transport, 724 req->in.vwv + VWV(4)); 725 parms->openxreadx.out.size = IVAL(req->in.vwv, VWV(6)); 726 parms->openxreadx.out.access = SVAL(req->in.vwv, VWV(8)); 727 parms->openxreadx.out.ftype = SVAL(req->in.vwv, VWV(9)); 728 parms->openxreadx.out.devstate = SVAL(req->in.vwv, VWV(10)); 729 parms->openxreadx.out.action = SVAL(req->in.vwv, VWV(11)); 730 parms->openxreadx.out.unique_fid = IVAL(req->in.vwv, VWV(12)); 731 if (req->in.wct >= 19) { 732 parms->openxreadx.out.access_mask = IVAL(req->in.vwv, VWV(15)); 733 parms->openxreadx.out.unknown = IVAL(req->in.vwv, VWV(17)); 734 } else { 735 parms->openxreadx.out.access_mask = 0; 736 parms->openxreadx.out.unknown = 0; 737 } 738 739 status = smbcli_chained_advance(req); 740 if (!NT_STATUS_IS_OK(status)) { 741 return status; 742 } 743 744 SMBCLI_CHECK_WCT(req, 12); 745 parms->openxreadx.out.remaining = SVAL(req->in.vwv, VWV(2)); 746 parms->openxreadx.out.compaction_mode = SVAL(req->in.vwv, VWV(3)); 747 parms->openxreadx.out.nread = SVAL(req->in.vwv, VWV(5)); 748 if (parms->openxreadx.out.nread > 749 MAX(parms->openxreadx.in.mincnt, parms->openxreadx.in.maxcnt) || 750 !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)), 751 parms->openxreadx.out.nread, 752 parms->openxreadx.out.data)) { 753 req->status = NT_STATUS_BUFFER_TOO_SMALL; 754 } 755 break; 756 case RAW_OPEN_SMB2: 757 req->status = NT_STATUS_INTERNAL_ERROR; 758 break; 759 } 760 761failed: 762 return smbcli_request_destroy(req); 763} 764 765 766/**************************************************************************** 767 Open a file - sync interface 768****************************************************************************/ 769_PUBLIC_ NTSTATUS smb_raw_open(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, union smb_open *parms) 770{ 771 struct smbcli_request *req = smb_raw_open_send(tree, parms); 772 return smb_raw_open_recv(req, mem_ctx, parms); 773} 774 775 776/**************************************************************************** 777 Close a file - async send 778****************************************************************************/ 779_PUBLIC_ struct smbcli_request *smb_raw_close_send(struct smbcli_tree *tree, union smb_close *parms) 780{ 781 struct smbcli_request *req = NULL; 782 783 switch (parms->generic.level) { 784 case RAW_CLOSE_CLOSE: 785 SETUP_REQUEST(SMBclose, 3, 0); 786 SSVAL(req->out.vwv, VWV(0), parms->close.in.file.fnum); 787 raw_push_dos_date3(tree->session->transport, 788 req->out.vwv, VWV(1), parms->close.in.write_time); 789 break; 790 791 case RAW_CLOSE_SPLCLOSE: 792 SETUP_REQUEST(SMBsplclose, 3, 0); 793 SSVAL(req->out.vwv, VWV(0), parms->splclose.in.file.fnum); 794 SIVAL(req->out.vwv, VWV(1), 0); /* reserved */ 795 break; 796 797 case RAW_CLOSE_SMB2: 798 case RAW_CLOSE_GENERIC: 799 return NULL; 800 } 801 802 if (!req) return NULL; 803 804 if (!smbcli_request_send(req)) { 805 smbcli_request_destroy(req); 806 return NULL; 807 } 808 809 return req; 810} 811 812 813/**************************************************************************** 814 Close a file - sync interface 815****************************************************************************/ 816_PUBLIC_ NTSTATUS smb_raw_close(struct smbcli_tree *tree, union smb_close *parms) 817{ 818 struct smbcli_request *req = smb_raw_close_send(tree, parms); 819 return smbcli_request_simple_recv(req); 820} 821 822 823/**************************************************************************** 824 Locking calls - async interface 825****************************************************************************/ 826struct smbcli_request *smb_raw_lock_send(struct smbcli_tree *tree, union smb_lock *parms) 827{ 828 struct smbcli_request *req = NULL; 829 830 switch (parms->generic.level) { 831 case RAW_LOCK_LOCK: 832 SETUP_REQUEST(SMBlock, 5, 0); 833 SSVAL(req->out.vwv, VWV(0), parms->lock.in.file.fnum); 834 SIVAL(req->out.vwv, VWV(1), parms->lock.in.count); 835 SIVAL(req->out.vwv, VWV(3), parms->lock.in.offset); 836 break; 837 838 case RAW_LOCK_UNLOCK: 839 SETUP_REQUEST(SMBunlock, 5, 0); 840 SSVAL(req->out.vwv, VWV(0), parms->unlock.in.file.fnum); 841 SIVAL(req->out.vwv, VWV(1), parms->unlock.in.count); 842 SIVAL(req->out.vwv, VWV(3), parms->unlock.in.offset); 843 break; 844 845 case RAW_LOCK_LOCKX: { 846 struct smb_lock_entry *lockp; 847 uint_t lck_size = (parms->lockx.in.mode & LOCKING_ANDX_LARGE_FILES)? 20 : 10; 848 uint_t lock_count = parms->lockx.in.ulock_cnt + parms->lockx.in.lock_cnt; 849 int i; 850 851 SETUP_REQUEST(SMBlockingX, 8, lck_size * lock_count); 852 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); 853 SSVAL(req->out.vwv, VWV(1), 0); 854 SSVAL(req->out.vwv, VWV(2), parms->lockx.in.file.fnum); 855 SSVAL(req->out.vwv, VWV(3), parms->lockx.in.mode); 856 SIVAL(req->out.vwv, VWV(4), parms->lockx.in.timeout); 857 SSVAL(req->out.vwv, VWV(6), parms->lockx.in.ulock_cnt); 858 SSVAL(req->out.vwv, VWV(7), parms->lockx.in.lock_cnt); 859 860 /* copy in all the locks */ 861 lockp = &parms->lockx.in.locks[0]; 862 for (i = 0; i < lock_count; i++) { 863 uint8_t *p = req->out.data + lck_size * i; 864 SSVAL(p, 0, lockp[i].pid); 865 if (parms->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) { 866 SSVAL(p, 2, 0); /* reserved */ 867 SIVAL(p, 4, lockp[i].offset>>32); 868 SIVAL(p, 8, lockp[i].offset); 869 SIVAL(p, 12, lockp[i].count>>32); 870 SIVAL(p, 16, lockp[i].count); 871 } else { 872 SIVAL(p, 2, lockp[i].offset); 873 SIVAL(p, 6, lockp[i].count); 874 } 875 } 876 break; 877 } 878 case RAW_LOCK_SMB2: 879 return NULL; 880 } 881 882 if (!smbcli_request_send(req)) { 883 smbcli_request_destroy(req); 884 return NULL; 885 } 886 887 return req; 888} 889 890/**************************************************************************** 891 Locking calls - sync interface 892****************************************************************************/ 893_PUBLIC_ NTSTATUS smb_raw_lock(struct smbcli_tree *tree, union smb_lock *parms) 894{ 895 struct smbcli_request *req = smb_raw_lock_send(tree, parms); 896 return smbcli_request_simple_recv(req); 897} 898 899 900/**************************************************************************** 901 Check for existence of a dir - async send 902****************************************************************************/ 903struct smbcli_request *smb_raw_chkpath_send(struct smbcli_tree *tree, union smb_chkpath *parms) 904{ 905 struct smbcli_request *req; 906 907 SETUP_REQUEST(SMBchkpth, 0, 0); 908 909 smbcli_req_append_ascii4(req, parms->chkpath.in.path, STR_TERMINATE); 910 911 if (!smbcli_request_send(req)) { 912 smbcli_request_destroy(req); 913 return NULL; 914 } 915 916 return req; 917} 918 919/**************************************************************************** 920 Check for existence of a dir - sync interface 921****************************************************************************/ 922NTSTATUS smb_raw_chkpath(struct smbcli_tree *tree, union smb_chkpath *parms) 923{ 924 struct smbcli_request *req = smb_raw_chkpath_send(tree, parms); 925 return smbcli_request_simple_recv(req); 926} 927 928/**************************************************************************** 929 flush a file - async send 930 a flush with RAW_FLUSH_ALL will flush all files 931****************************************************************************/ 932struct smbcli_request *smb_raw_flush_send(struct smbcli_tree *tree, union smb_flush *parms) 933{ 934 struct smbcli_request *req; 935 uint16_t fnum=0; 936 937 switch (parms->generic.level) { 938 case RAW_FLUSH_FLUSH: 939 fnum = parms->flush.in.file.fnum; 940 break; 941 case RAW_FLUSH_ALL: 942 fnum = 0xFFFF; 943 break; 944 case RAW_FLUSH_SMB2: 945 return NULL; 946 } 947 948 SETUP_REQUEST(SMBflush, 1, 0); 949 SSVAL(req->out.vwv, VWV(0), fnum); 950 951 if (!smbcli_request_send(req)) { 952 smbcli_request_destroy(req); 953 return NULL; 954 } 955 956 return req; 957} 958 959 960/**************************************************************************** 961 flush a file - sync interface 962****************************************************************************/ 963_PUBLIC_ NTSTATUS smb_raw_flush(struct smbcli_tree *tree, union smb_flush *parms) 964{ 965 struct smbcli_request *req = smb_raw_flush_send(tree, parms); 966 return smbcli_request_simple_recv(req); 967} 968 969 970/**************************************************************************** 971 seek a file - async send 972****************************************************************************/ 973struct smbcli_request *smb_raw_seek_send(struct smbcli_tree *tree, 974 union smb_seek *parms) 975{ 976 struct smbcli_request *req; 977 978 SETUP_REQUEST(SMBlseek, 4, 0); 979 980 SSVAL(req->out.vwv, VWV(0), parms->lseek.in.file.fnum); 981 SSVAL(req->out.vwv, VWV(1), parms->lseek.in.mode); 982 SIVALS(req->out.vwv, VWV(2), parms->lseek.in.offset); 983 984 if (!smbcli_request_send(req)) { 985 smbcli_request_destroy(req); 986 return NULL; 987 } 988 return req; 989} 990 991/**************************************************************************** 992 seek a file - async receive 993****************************************************************************/ 994NTSTATUS smb_raw_seek_recv(struct smbcli_request *req, 995 union smb_seek *parms) 996{ 997 if (!smbcli_request_receive(req) || 998 smbcli_request_is_error(req)) { 999 return smbcli_request_destroy(req); 1000 } 1001 1002 SMBCLI_CHECK_WCT(req, 2); 1003 parms->lseek.out.offset = IVAL(req->in.vwv, VWV(0)); 1004 1005failed: 1006 return smbcli_request_destroy(req); 1007} 1008 1009/* 1010 seek a file - sync interface 1011*/ 1012_PUBLIC_ NTSTATUS smb_raw_seek(struct smbcli_tree *tree, 1013 union smb_seek *parms) 1014{ 1015 struct smbcli_request *req = smb_raw_seek_send(tree, parms); 1016 return smb_raw_seek_recv(req, parms); 1017} 1018