1/* 2 Unix SMB/CIFS implementation. 3 Core SMB2 server 4 5 Copyright (C) Stefan Metzmacher 2009 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19*/ 20 21#include "includes.h" 22#include "smbd/globals.h" 23#include "../libcli/smb/smb_common.h" 24 25static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, 26 struct tevent_context *ev, 27 struct smbd_smb2_request *smb2req, 28 uint8_t in_oplock_level, 29 uint32_t in_impersonation_level, 30 uint32_t in_desired_access, 31 uint32_t in_file_attributes, 32 uint32_t in_share_access, 33 uint32_t in_create_disposition, 34 uint32_t in_create_options, 35 const char *in_name, 36 struct smb2_create_blobs in_context_blobs); 37static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req, 38 TALLOC_CTX *mem_ctx, 39 uint8_t *out_oplock_level, 40 uint32_t *out_create_action, 41 NTTIME *out_creation_time, 42 NTTIME *out_last_access_time, 43 NTTIME *out_last_write_time, 44 NTTIME *out_change_time, 45 uint64_t *out_allocation_size, 46 uint64_t *out_end_of_file, 47 uint32_t *out_file_attributes, 48 uint64_t *out_file_id_volatile, 49 struct smb2_create_blobs *out_context_blobs); 50 51static void smbd_smb2_request_create_done(struct tevent_req *subreq); 52NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *req) 53{ 54 const uint8_t *inbody; 55 int i = req->current_idx; 56 size_t expected_body_size = 0x39; 57 size_t body_size; 58 uint8_t in_oplock_level; 59 uint32_t in_impersonation_level; 60 uint32_t in_desired_access; 61 uint32_t in_file_attributes; 62 uint32_t in_share_access; 63 uint32_t in_create_disposition; 64 uint32_t in_create_options; 65 uint16_t in_name_offset; 66 uint16_t in_name_length; 67 DATA_BLOB in_name_buffer; 68 char *in_name_string; 69 size_t in_name_string_size; 70 uint32_t name_offset = 0; 71 uint32_t name_available_length = 0; 72 uint32_t in_context_offset; 73 uint32_t in_context_length; 74 DATA_BLOB in_context_buffer; 75 struct smb2_create_blobs in_context_blobs; 76 uint32_t context_offset = 0; 77 uint32_t context_available_length = 0; 78 uint32_t dyn_offset; 79 NTSTATUS status; 80 bool ok; 81 struct tevent_req *subreq; 82 83 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) { 84 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); 85 } 86 87 inbody = (const uint8_t *)req->in.vector[i+1].iov_base; 88 89 body_size = SVAL(inbody, 0x00); 90 if (body_size != expected_body_size) { 91 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); 92 } 93 94 in_oplock_level = CVAL(inbody, 0x03); 95 in_impersonation_level = IVAL(inbody, 0x04); 96 in_desired_access = IVAL(inbody, 0x18); 97 in_file_attributes = IVAL(inbody, 0x1C); 98 in_share_access = IVAL(inbody, 0x20); 99 in_create_disposition = IVAL(inbody, 0x24); 100 in_create_options = IVAL(inbody, 0x28); 101 in_name_offset = SVAL(inbody, 0x2C); 102 in_name_length = SVAL(inbody, 0x2E); 103 in_context_offset = IVAL(inbody, 0x30); 104 in_context_length = IVAL(inbody, 0x34); 105 106 /* 107 * First check if the dynamic name and context buffers 108 * are correctly specified. 109 * 110 * Note: That we don't check if the name and context buffers 111 * overlap 112 */ 113 114 dyn_offset = SMB2_HDR_BODY + (body_size & 0xFFFFFFFE); 115 116 if (in_name_offset == 0 && in_name_length == 0) { 117 /* This is ok */ 118 name_offset = 0; 119 } else if (in_name_offset < dyn_offset) { 120 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); 121 } else { 122 name_offset = in_name_offset - dyn_offset; 123 } 124 125 if (name_offset > req->in.vector[i+2].iov_len) { 126 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); 127 } 128 129 name_available_length = req->in.vector[i+2].iov_len - name_offset; 130 131 if (in_name_length > name_available_length) { 132 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); 133 } 134 135 in_name_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base + 136 name_offset; 137 in_name_buffer.length = in_name_length; 138 139 if (in_context_offset == 0 && in_context_length == 0) { 140 /* This is ok */ 141 context_offset = 0; 142 } else if (in_context_offset < dyn_offset) { 143 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); 144 } else { 145 context_offset = in_context_offset - dyn_offset; 146 } 147 148 if (context_offset > req->in.vector[i+2].iov_len) { 149 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); 150 } 151 152 context_available_length = req->in.vector[i+2].iov_len - context_offset; 153 154 if (in_context_length > context_available_length) { 155 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); 156 } 157 158 in_context_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base + 159 context_offset; 160 in_context_buffer.length = in_context_length; 161 162 /* 163 * Now interpret the name and context buffers 164 */ 165 166 ok = convert_string_talloc(req, CH_UTF16, CH_UNIX, 167 in_name_buffer.data, 168 in_name_buffer.length, 169 &in_name_string, 170 &in_name_string_size, false); 171 if (!ok) { 172 return smbd_smb2_request_error(req, NT_STATUS_ILLEGAL_CHARACTER); 173 } 174 175 ZERO_STRUCT(in_context_blobs); 176 status = smb2_create_blob_parse(req, in_context_buffer, &in_context_blobs); 177 if (!NT_STATUS_IS_OK(status)) { 178 return smbd_smb2_request_error(req, status); 179 } 180 181 subreq = smbd_smb2_create_send(req, 182 req->sconn->smb2.event_ctx, 183 req, 184 in_oplock_level, 185 in_impersonation_level, 186 in_desired_access, 187 in_file_attributes, 188 in_share_access, 189 in_create_disposition, 190 in_create_options, 191 in_name_string, 192 in_context_blobs); 193 if (subreq == NULL) { 194 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); 195 } 196 tevent_req_set_callback(subreq, smbd_smb2_request_create_done, req); 197 198 return smbd_smb2_request_pending_queue(req, subreq); 199} 200 201static void smbd_smb2_request_create_done(struct tevent_req *subreq) 202{ 203 struct smbd_smb2_request *req = tevent_req_callback_data(subreq, 204 struct smbd_smb2_request); 205 int i = req->current_idx; 206 uint8_t *outhdr; 207 DATA_BLOB outbody; 208 DATA_BLOB outdyn; 209 uint8_t out_oplock_level = 0; 210 uint32_t out_create_action = 0; 211 NTTIME out_creation_time = 0; 212 NTTIME out_last_access_time = 0; 213 NTTIME out_last_write_time = 0; 214 NTTIME out_change_time = 0; 215 uint64_t out_allocation_size = 0; 216 uint64_t out_end_of_file = 0; 217 uint32_t out_file_attributes = 0; 218 uint64_t out_file_id_volatile = 0; 219 struct smb2_create_blobs out_context_blobs; 220 DATA_BLOB out_context_buffer; 221 uint16_t out_context_buffer_offset = 0; 222 NTSTATUS status; 223 NTSTATUS error; /* transport error */ 224 225 status = smbd_smb2_create_recv(subreq, 226 req, 227 &out_oplock_level, 228 &out_create_action, 229 &out_creation_time, 230 &out_last_access_time, 231 &out_last_write_time, 232 &out_change_time, 233 &out_allocation_size, 234 &out_end_of_file, 235 &out_file_attributes, 236 &out_file_id_volatile, 237 &out_context_blobs); 238 TALLOC_FREE(subreq); 239 if (!NT_STATUS_IS_OK(status)) { 240 error = smbd_smb2_request_error(req, status); 241 if (!NT_STATUS_IS_OK(error)) { 242 smbd_server_connection_terminate(req->sconn, 243 nt_errstr(error)); 244 return; 245 } 246 return; 247 } 248 249 status = smb2_create_blob_push(req, &out_context_buffer, out_context_blobs); 250 if (!NT_STATUS_IS_OK(status)) { 251 error = smbd_smb2_request_error(req, status); 252 if (!NT_STATUS_IS_OK(error)) { 253 smbd_server_connection_terminate(req->sconn, 254 nt_errstr(error)); 255 return; 256 } 257 return; 258 } 259 260 if (out_context_buffer.length > 0) { 261 out_context_buffer_offset = SMB2_HDR_BODY + 0x58; 262 } 263 264 outhdr = (uint8_t *)req->out.vector[i].iov_base; 265 266 outbody = data_blob_talloc(req->out.vector, NULL, 0x58); 267 if (outbody.data == NULL) { 268 error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); 269 if (!NT_STATUS_IS_OK(error)) { 270 smbd_server_connection_terminate(req->sconn, 271 nt_errstr(error)); 272 return; 273 } 274 return; 275 } 276 277 SSVAL(outbody.data, 0x00, 0x58 + 1); /* struct size */ 278 SCVAL(outbody.data, 0x02, 279 out_oplock_level); /* oplock level */ 280 SCVAL(outbody.data, 0x03, 0); /* reserved */ 281 SIVAL(outbody.data, 0x04, 282 out_create_action); /* create action */ 283 SBVAL(outbody.data, 0x08, 284 out_creation_time); /* creation time */ 285 SBVAL(outbody.data, 0x10, 286 out_last_access_time); /* last access time */ 287 SBVAL(outbody.data, 0x18, 288 out_last_write_time); /* last write time */ 289 SBVAL(outbody.data, 0x20, 290 out_change_time); /* change time */ 291 SBVAL(outbody.data, 0x28, 292 out_allocation_size); /* allocation size */ 293 SBVAL(outbody.data, 0x30, 294 out_end_of_file); /* end of file */ 295 SIVAL(outbody.data, 0x38, 296 out_file_attributes); /* file attributes */ 297 SIVAL(outbody.data, 0x3C, 0); /* reserved */ 298 SBVAL(outbody.data, 0x40, 0); /* file id (persistent) */ 299 SBVAL(outbody.data, 0x48, 300 out_file_id_volatile); /* file id (volatile) */ 301 SIVAL(outbody.data, 0x50, 302 out_context_buffer_offset); /* create contexts offset */ 303 SIVAL(outbody.data, 0x54, 304 out_context_buffer.length); /* create contexts length */ 305 306 outdyn = out_context_buffer; 307 308 error = smbd_smb2_request_done(req, outbody, &outdyn); 309 if (!NT_STATUS_IS_OK(error)) { 310 smbd_server_connection_terminate(req->sconn, 311 nt_errstr(error)); 312 return; 313 } 314} 315 316struct smbd_smb2_create_state { 317 struct smbd_smb2_request *smb2req; 318 uint8_t out_oplock_level; 319 uint32_t out_create_action; 320 NTTIME out_creation_time; 321 NTTIME out_last_access_time; 322 NTTIME out_last_write_time; 323 NTTIME out_change_time; 324 uint64_t out_allocation_size; 325 uint64_t out_end_of_file; 326 uint32_t out_file_attributes; 327 uint64_t out_file_id_volatile; 328 struct smb2_create_blobs out_context_blobs; 329}; 330 331static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, 332 struct tevent_context *ev, 333 struct smbd_smb2_request *smb2req, 334 uint8_t in_oplock_level, 335 uint32_t in_impersonation_level, 336 uint32_t in_desired_access, 337 uint32_t in_file_attributes, 338 uint32_t in_share_access, 339 uint32_t in_create_disposition, 340 uint32_t in_create_options, 341 const char *in_name, 342 struct smb2_create_blobs in_context_blobs) 343{ 344 struct tevent_req *req; 345 struct smbd_smb2_create_state *state; 346 NTSTATUS status; 347 struct smb_request *smbreq; 348 files_struct *result; 349 int info; 350 struct timespec write_time_ts; 351 struct smb2_create_blobs out_context_blobs; 352 353 ZERO_STRUCT(out_context_blobs); 354 355 req = tevent_req_create(mem_ctx, &state, 356 struct smbd_smb2_create_state); 357 if (req == NULL) { 358 return NULL; 359 } 360 state->smb2req = smb2req; 361 362 DEBUG(10,("smbd_smb2_create: name[%s]\n", 363 in_name)); 364 365 smbreq = smbd_smb2_fake_smb_request(smb2req); 366 if (tevent_req_nomem(smbreq, req)) { 367 return tevent_req_post(req, ev); 368 } 369 370 if (IS_IPC(smbreq->conn)) { 371 const char *pipe_name = in_name; 372 373 if (!lp_nt_pipe_support()) { 374 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); 375 return tevent_req_post(req, ev); 376 } 377 378 /* Strip \\ off the name. */ 379 if (pipe_name[0] == '\\') { 380 pipe_name++; 381 } 382 383 status = open_np_file(smbreq, pipe_name, &result); 384 if (!NT_STATUS_IS_OK(status)) { 385 tevent_req_nterror(req, status); 386 return tevent_req_post(req, ev); 387 } 388 info = FILE_WAS_OPENED; 389 } else if (CAN_PRINT(smbreq->conn)) { 390 status = file_new(smbreq, smbreq->conn, &result); 391 if(!NT_STATUS_IS_OK(status)) { 392 tevent_req_nterror(req, status); 393 return tevent_req_post(req, ev); 394 } 395 396 status = print_fsp_open(smbreq, 397 smbreq->conn, 398 in_name, 399 smbreq->vuid, 400 result); 401 if (!NT_STATUS_IS_OK(status)) { 402 file_free(smbreq, result); 403 tevent_req_nterror(req, status); 404 return tevent_req_post(req, ev); 405 } 406 info = FILE_WAS_CREATED; 407 } else { 408 char *fname; 409 struct smb_filename *smb_fname = NULL; 410 struct smb2_create_blob *exta = NULL; 411 struct ea_list *ea_list = NULL; 412 struct smb2_create_blob *mxac = NULL; 413 NTTIME max_access_time = 0; 414 struct smb2_create_blob *secd = NULL; 415 struct security_descriptor *sec_desc = NULL; 416 struct smb2_create_blob *dhnq = NULL; 417 struct smb2_create_blob *dhnc = NULL; 418 struct smb2_create_blob *alsi = NULL; 419 uint64_t allocation_size = 0; 420 struct smb2_create_blob *twrp = NULL; 421 struct smb2_create_blob *qfid = NULL; 422 423 exta = smb2_create_blob_find(&in_context_blobs, 424 SMB2_CREATE_TAG_EXTA); 425 mxac = smb2_create_blob_find(&in_context_blobs, 426 SMB2_CREATE_TAG_MXAC); 427 secd = smb2_create_blob_find(&in_context_blobs, 428 SMB2_CREATE_TAG_SECD); 429 dhnq = smb2_create_blob_find(&in_context_blobs, 430 SMB2_CREATE_TAG_DHNQ); 431 dhnc = smb2_create_blob_find(&in_context_blobs, 432 SMB2_CREATE_TAG_DHNC); 433 alsi = smb2_create_blob_find(&in_context_blobs, 434 SMB2_CREATE_TAG_ALSI); 435 twrp = smb2_create_blob_find(&in_context_blobs, 436 SMB2_CREATE_TAG_TWRP); 437 qfid = smb2_create_blob_find(&in_context_blobs, 438 SMB2_CREATE_TAG_QFID); 439 440 fname = talloc_strdup(state, in_name); 441 if (tevent_req_nomem(fname, req)) { 442 return tevent_req_post(req, ev); 443 } 444 445 if (exta) { 446 if (dhnc) { 447 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 448 return tevent_req_post(req, ev); 449 } 450 451 ea_list = read_nttrans_ea_list(mem_ctx, 452 (const char *)exta->data.data, exta->data.length); 453 if (!ea_list) { 454 DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n")); 455 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 456 return tevent_req_post(req, ev); 457 } 458 } 459 460 if (mxac) { 461 if (dhnc) { 462 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 463 return tevent_req_post(req, ev); 464 } 465 466 if (mxac->data.length == 0) { 467 max_access_time = 0; 468 } else if (mxac->data.length == 8) { 469 max_access_time = BVAL(mxac->data.data, 0); 470 } else { 471 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 472 return tevent_req_post(req, ev); 473 } 474 } 475 476 if (secd) { 477 enum ndr_err_code ndr_err; 478 479 if (dhnc) { 480 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 481 return tevent_req_post(req, ev); 482 } 483 484 sec_desc = talloc_zero(state, struct security_descriptor); 485 if (tevent_req_nomem(sec_desc, req)) { 486 return tevent_req_post(req, ev); 487 } 488 489 ndr_err = ndr_pull_struct_blob(&secd->data, 490 sec_desc, NULL, sec_desc, 491 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); 492 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 493 DEBUG(2,("ndr_pull_security_descriptor failed: %s\n", 494 ndr_errstr(ndr_err))); 495 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 496 return tevent_req_post(req, ev); 497 } 498 } 499 500 if (dhnq) { 501 if (dhnc) { 502 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 503 return tevent_req_post(req, ev); 504 } 505 506 if (dhnq->data.length != 16) { 507 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 508 return tevent_req_post(req, ev); 509 } 510 /* 511 * we don't support durable handles yet 512 * and have to ignore this 513 */ 514 } 515 516 if (dhnc) { 517 if (dhnc->data.length != 16) { 518 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 519 return tevent_req_post(req, ev); 520 } 521 /* we don't support durable handles yet */ 522 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND); 523 return tevent_req_post(req, ev); 524 } 525 526 if (alsi) { 527 if (dhnc) { 528 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 529 return tevent_req_post(req, ev); 530 } 531 532 if (alsi->data.length != 8) { 533 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 534 return tevent_req_post(req, ev); 535 } 536 allocation_size = BVAL(alsi->data.data, 0); 537 } 538 539 if (twrp) { 540 NTTIME nttime; 541 time_t t; 542 struct tm *tm; 543 544 if (dhnc) { 545 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 546 return tevent_req_post(req, ev); 547 } 548 549 if (twrp->data.length != 8) { 550 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 551 return tevent_req_post(req, ev); 552 } 553 554 nttime = BVAL(twrp->data.data, 0); 555 t = nt_time_to_unix(nttime); 556 tm = gmtime(&t); 557 558 TALLOC_FREE(fname); 559 fname = talloc_asprintf(state, 560 "@GMT-%04u.%02u.%02u-%02u.%02u.%02u\\%s", 561 tm->tm_year + 1900, 562 tm->tm_mon + 1, 563 tm->tm_mday, 564 tm->tm_hour, 565 tm->tm_min, 566 tm->tm_sec, 567 in_name); 568 if (tevent_req_nomem(fname, req)) { 569 return tevent_req_post(req, ev); 570 } 571 } 572 573 if (qfid) { 574 if (qfid->data.length != 0) { 575 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 576 return tevent_req_post(req, ev); 577 } 578 } 579 580 /* these are ignored for SMB2 */ 581 in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */ 582 in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */ 583 584 /* convert '\\' into '/' */ 585 status = check_path_syntax(fname); 586 if (!NT_STATUS_IS_OK(status)) { 587 tevent_req_nterror(req, status); 588 return tevent_req_post(req, ev); 589 } 590 591 status = filename_convert(req, 592 smbreq->conn, 593 smbreq->flags2 & FLAGS2_DFS_PATHNAMES, 594 fname, 595 0, 596 NULL, 597 &smb_fname); 598 if (!NT_STATUS_IS_OK(status)) { 599 tevent_req_nterror(req, status); 600 return tevent_req_post(req, ev); 601 } 602 603 status = SMB_VFS_CREATE_FILE(smbreq->conn, 604 smbreq, 605 0, /* root_dir_fid */ 606 smb_fname, 607 in_desired_access, 608 in_share_access, 609 in_create_disposition, 610 in_create_options, 611 in_file_attributes, 612 0, /* oplock_request */ 613 allocation_size, 614 sec_desc, 615 ea_list, 616 &result, 617 &info); 618 if (!NT_STATUS_IS_OK(status)) { 619 tevent_req_nterror(req, status); 620 return tevent_req_post(req, ev); 621 } 622 623 if (mxac) { 624 NTTIME last_write_time; 625 626 unix_timespec_to_nt_time(&last_write_time, 627 result->fsp_name->st.st_ex_mtime); 628 if (last_write_time != max_access_time) { 629 uint8_t p[8]; 630 uint32_t max_access_granted; 631 DATA_BLOB blob = data_blob_const(p, sizeof(p)); 632 633 status = smbd_check_open_rights(smbreq->conn, 634 result->fsp_name, 635 SEC_FLAG_MAXIMUM_ALLOWED, 636 &max_access_granted); 637 638 SIVAL(p, 0, NT_STATUS_V(status)); 639 SIVAL(p, 4, max_access_granted); 640 641 status = smb2_create_blob_add(state, 642 &out_context_blobs, 643 SMB2_CREATE_TAG_MXAC, 644 blob); 645 if (!NT_STATUS_IS_OK(status)) { 646 tevent_req_nterror(req, status); 647 return tevent_req_post(req, ev); 648 } 649 } 650 } 651 652 if (qfid) { 653 uint8_t p[32]; 654 uint64_t file_index = get_FileIndex(result->conn, 655 &result->fsp_name->st); 656 DATA_BLOB blob = data_blob_const(p, sizeof(p)); 657 658 ZERO_STRUCT(p); 659 660 /* From conversations with Microsoft engineers at 661 the MS plugfest. The first 8 bytes are the "volume index" 662 == inode, the second 8 bytes are the "volume id", 663 == dev. This will be updated in the SMB2 doc. */ 664 SBVAL(p, 0, file_index); 665 SIVAL(p, 8, result->fsp_name->st.st_ex_dev);/* FileIndexHigh */ 666 667 status = smb2_create_blob_add(state, &out_context_blobs, 668 SMB2_CREATE_TAG_QFID, 669 blob); 670 if (!NT_STATUS_IS_OK(status)) { 671 tevent_req_nterror(req, status); 672 return tevent_req_post(req, ev); 673 } 674 } 675 } 676 677 smb2req->compat_chain_fsp = smbreq->chain_fsp; 678 679 state->out_oplock_level = 0; 680 if ((in_create_disposition == FILE_SUPERSEDE) 681 && (info == FILE_WAS_OVERWRITTEN)) { 682 state->out_create_action = FILE_WAS_SUPERSEDED; 683 } else { 684 state->out_create_action = info; 685 } 686 state->out_file_attributes = dos_mode(result->conn, 687 result->fsp_name); 688 /* Deal with other possible opens having a modified 689 write time. JRA. */ 690 ZERO_STRUCT(write_time_ts); 691 get_file_infos(result->file_id, NULL, &write_time_ts); 692 if (!null_timespec(write_time_ts)) { 693 update_stat_ex_mtime(&result->fsp_name->st, write_time_ts); 694 } 695 696 unix_timespec_to_nt_time(&state->out_creation_time, 697 get_create_timespec(smbreq->conn, result, 698 result->fsp_name)); 699 unix_timespec_to_nt_time(&state->out_last_access_time, 700 result->fsp_name->st.st_ex_atime); 701 unix_timespec_to_nt_time(&state->out_last_write_time, 702 result->fsp_name->st.st_ex_mtime); 703 unix_timespec_to_nt_time(&state->out_change_time, 704 get_change_timespec(smbreq->conn, result, 705 result->fsp_name)); 706 state->out_allocation_size = 707 result->fsp_name->st.st_ex_blksize * 708 result->fsp_name->st.st_ex_blocks; 709 state->out_end_of_file = result->fsp_name->st.st_ex_size; 710 if (state->out_file_attributes == 0) { 711 state->out_file_attributes = FILE_ATTRIBUTE_NORMAL; 712 } 713 state->out_file_id_volatile = result->fnum; 714 state->out_context_blobs = out_context_blobs; 715 716 tevent_req_done(req); 717 return tevent_req_post(req, ev); 718} 719 720static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req, 721 TALLOC_CTX *mem_ctx, 722 uint8_t *out_oplock_level, 723 uint32_t *out_create_action, 724 NTTIME *out_creation_time, 725 NTTIME *out_last_access_time, 726 NTTIME *out_last_write_time, 727 NTTIME *out_change_time, 728 uint64_t *out_allocation_size, 729 uint64_t *out_end_of_file, 730 uint32_t *out_file_attributes, 731 uint64_t *out_file_id_volatile, 732 struct smb2_create_blobs *out_context_blobs) 733{ 734 NTSTATUS status; 735 struct smbd_smb2_create_state *state = tevent_req_data(req, 736 struct smbd_smb2_create_state); 737 738 if (tevent_req_is_nterror(req, &status)) { 739 tevent_req_received(req); 740 return status; 741 } 742 743 *out_oplock_level = state->out_oplock_level; 744 *out_create_action = state->out_create_action; 745 *out_creation_time = state->out_creation_time; 746 *out_last_access_time = state->out_last_access_time; 747 *out_last_write_time = state->out_last_write_time; 748 *out_change_time = state->out_change_time; 749 *out_allocation_size = state->out_allocation_size; 750 *out_end_of_file = state->out_end_of_file; 751 *out_file_attributes = state->out_file_attributes; 752 *out_file_id_volatile = state->out_file_id_volatile; 753 *out_context_blobs = state->out_context_blobs; 754 755 talloc_steal(mem_ctx, state->out_context_blobs.blobs); 756 757 tevent_req_received(req); 758 return NT_STATUS_OK; 759} 760