Changeset 745 for trunk/server/source4/torture/smb2
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 deleted
- 14 edited
- 4 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/torture/smb2/compound.c
r414 r745 21 21 22 22 #include "includes.h" 23 #include "librpc/gen_ndr/security.h"24 23 #include "libcli/smb2/smb2.h" 25 24 #include "libcli/smb2/smb2_calls.h" … … 35 34 }} while (0) 36 35 36 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false)) 37 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false)) 38 37 39 static bool test_compound_related1(struct torture_context *tctx, 38 40 struct smb2_tree *tree) … … 45 47 bool ret = true; 46 48 struct smb2_request *req[2]; 47 DATA_BLOB data; 49 uint32_t saved_tid = tree->tid; 50 uint64_t saved_uid = tree->session->uid; 48 51 49 52 smb2_transport_credits_ask_num(tree->session->transport, 2); … … 82 85 ZERO_STRUCT(cl); 83 86 cl.in.file.handle = hd; 87 88 tree->tid = 0xFFFFFFFF; 89 tree->session->uid = UINT64_MAX; 90 84 91 req[1] = smb2_close_send(tree, &cl); 85 92 … … 88 95 status = smb2_close_recv(req[1], &cl); 89 96 CHECK_STATUS(status, NT_STATUS_OK); 97 98 tree->tid = saved_tid; 99 tree->session->uid = saved_uid; 90 100 91 101 smb2_util_unlink(tree, fname); … … 104 114 bool ret = true; 105 115 struct smb2_request *req[5]; 116 uint32_t saved_tid = tree->tid; 117 uint64_t saved_uid = tree->session->uid; 106 118 107 119 smb2_transport_credits_ask_num(tree->session->transport, 5); … … 140 152 ZERO_STRUCT(cl); 141 153 cl.in.file.handle = hd; 154 tree->tid = 0xFFFFFFFF; 155 tree->session->uid = UINT64_MAX; 156 142 157 req[1] = smb2_close_send(tree, &cl); 143 158 req[2] = smb2_close_send(tree, &cl); … … 155 170 status = smb2_close_recv(req[4], &cl); 156 171 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 172 173 tree->tid = saved_tid; 174 tree->session->uid = saved_uid; 157 175 158 176 smb2_util_unlink(tree, fname); … … 171 189 bool ret = true; 172 190 struct smb2_request *req[5]; 173 uint64_t uid;174 uint32_t tid;175 191 176 192 smb2_transport_credits_ask_num(tree->session->transport, 5); … … 238 254 bool ret = true; 239 255 struct smb2_request *req[2]; 240 DATA_BLOB data;241 256 242 257 smb2_transport_credits_ask_num(tree->session->transport, 2); … … 299 314 bool ret = true; 300 315 struct smb2_request *req[5]; 316 uint32_t saved_tid = tree->tid; 317 uint64_t saved_uid = tree->session->uid; 301 318 302 319 smb2_transport_credits_ask_num(tree->session->transport, 5); … … 335 352 ZERO_STRUCT(cl); 336 353 cl.in.file.handle = hd; 354 tree->tid = 0xFFFFFFFF; 355 tree->session->uid = UINT64_MAX; 356 337 357 req[1] = smb2_close_send(tree, &cl); 338 358 /* strange that this is not generating invalid parameter */ … … 353 373 status = smb2_close_recv(req[4], &cl); 354 374 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 375 376 tree->tid = saved_tid; 377 tree->session->uid = saved_uid; 355 378 356 379 smb2_util_unlink(tree, fname); … … 426 449 } 427 450 451 /* Send a compound request where we expect the last request (Create, Notify) 452 * to go asynchronous. This works against a Win7 server and the reply is 453 * sent in two different packets. */ 454 static bool test_compound_interim1(struct torture_context *tctx, 455 struct smb2_tree *tree) 456 { 457 struct smb2_handle hd; 458 struct smb2_create cr; 459 NTSTATUS status = NT_STATUS_OK; 460 const char *dname = "compound_interim_dir"; 461 struct smb2_notify nt; 462 bool ret = true; 463 struct smb2_request *req[2]; 464 465 /* Win7 compound request implementation deviates substantially from the 466 * SMB2 spec as noted in MS-SMB2 <159>, <162>. This, test currently 467 * verifies the Windows behavior, not the general spec behavior. */ 468 if (!TARGET_IS_WIN7(tctx) && !TARGET_IS_W2K8(tctx)) { 469 torture_skip(tctx, "Interim test is specific to Windows server " 470 "behavior.\n"); 471 } 472 473 smb2_transport_credits_ask_num(tree->session->transport, 5); 474 475 smb2_deltree(tree, dname); 476 477 smb2_transport_credits_ask_num(tree->session->transport, 1); 478 479 ZERO_STRUCT(cr); 480 cr.in.desired_access = SEC_RIGHTS_FILE_ALL; 481 cr.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 482 cr.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; 483 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 484 NTCREATEX_SHARE_ACCESS_WRITE | 485 NTCREATEX_SHARE_ACCESS_DELETE; 486 cr.in.create_disposition = NTCREATEX_DISP_CREATE; 487 cr.in.fname = dname; 488 489 smb2_transport_compound_start(tree->session->transport, 2); 490 491 req[0] = smb2_create_send(tree, &cr); 492 493 smb2_transport_compound_set_related(tree->session->transport, true); 494 495 hd.data[0] = UINT64_MAX; 496 hd.data[1] = UINT64_MAX; 497 498 ZERO_STRUCT(nt); 499 nt.in.recursive = true; 500 nt.in.buffer_size = 0x1000; 501 nt.in.file.handle = hd; 502 nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; 503 nt.in.unknown = 0x00000000; 504 505 req[1] = smb2_notify_send(tree, &nt); 506 507 status = smb2_create_recv(req[0], tree, &cr); 508 CHECK_STATUS(status, NT_STATUS_OK); 509 510 smb2_cancel(req[1]); 511 status = smb2_notify_recv(req[1], tree, &nt); 512 CHECK_STATUS(status, NT_STATUS_CANCELLED); 513 514 smb2_util_close(tree, cr.out.file.handle); 515 516 smb2_deltree(tree, dname); 517 done: 518 return ret; 519 } 520 521 /* Send a compound request where we expect the middle request (Create, Notify, 522 * GetInfo) to go asynchronous. Against Win7 the sync request succeed while 523 * the async fails. All are returned in the same compound response. */ 524 static bool test_compound_interim2(struct torture_context *tctx, 525 struct smb2_tree *tree) 526 { 527 struct smb2_handle hd; 528 struct smb2_create cr; 529 NTSTATUS status = NT_STATUS_OK; 530 const char *dname = "compound_interim_dir"; 531 struct smb2_getinfo gf; 532 struct smb2_notify nt; 533 bool ret = true; 534 struct smb2_request *req[3]; 535 536 /* Win7 compound request implementation deviates substantially from the 537 * SMB2 spec as noted in MS-SMB2 <159>, <162>. This, test currently 538 * verifies the Windows behavior, not the general spec behavior. */ 539 if (!TARGET_IS_WIN7(tctx) && !TARGET_IS_W2K8(tctx)) { 540 torture_skip(tctx, "Interim test is specific to Windows server " 541 "behavior.\n"); 542 } 543 544 smb2_transport_credits_ask_num(tree->session->transport, 5); 545 546 smb2_deltree(tree, dname); 547 548 smb2_transport_credits_ask_num(tree->session->transport, 1); 549 550 ZERO_STRUCT(cr); 551 cr.in.desired_access = SEC_RIGHTS_FILE_ALL; 552 cr.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 553 cr.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; 554 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 555 NTCREATEX_SHARE_ACCESS_WRITE | 556 NTCREATEX_SHARE_ACCESS_DELETE; 557 cr.in.create_disposition = NTCREATEX_DISP_CREATE; 558 cr.in.fname = dname; 559 560 smb2_transport_compound_start(tree->session->transport, 3); 561 562 req[0] = smb2_create_send(tree, &cr); 563 564 smb2_transport_compound_set_related(tree->session->transport, true); 565 566 hd.data[0] = UINT64_MAX; 567 hd.data[1] = UINT64_MAX; 568 569 ZERO_STRUCT(nt); 570 nt.in.recursive = true; 571 nt.in.buffer_size = 0x1000; 572 nt.in.file.handle = hd; 573 nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; 574 nt.in.unknown = 0x00000000; 575 576 req[1] = smb2_notify_send(tree, &nt); 577 578 ZERO_STRUCT(gf); 579 gf.in.file.handle = hd; 580 gf.in.info_type = SMB2_GETINFO_FILE; 581 gf.in.info_class = 0x04; // FILE_BASIC_INFORMATION 582 gf.in.output_buffer_length = 0x1000; 583 gf.in.input_buffer_length = 0; 584 585 req[2] = smb2_getinfo_send(tree, &gf); 586 587 status = smb2_create_recv(req[0], tree, &cr); 588 CHECK_STATUS(status, NT_STATUS_OK); 589 590 status = smb2_notify_recv(req[1], tree, &nt); 591 CHECK_STATUS(status, NT_STATUS_INTERNAL_ERROR); 592 593 status = smb2_getinfo_recv(req[2], tree, &gf); 594 CHECK_STATUS(status, NT_STATUS_OK); 595 596 smb2_util_close(tree, cr.out.file.handle); 597 598 smb2_deltree(tree, dname); 599 done: 600 return ret; 601 } 602 428 603 struct torture_suite *torture_smb2_compound_init(void) 429 604 { 430 struct torture_suite *suite = 431 torture_suite_create(talloc_autofree_context(), "COMPOUND"); 432 433 torture_suite_add_1smb2_test(suite, "RELATED1", test_compound_related1); 434 torture_suite_add_1smb2_test(suite, "RELATED2", test_compound_related2); 435 torture_suite_add_1smb2_test(suite, "UNRELATED1", test_compound_unrelated1); 436 torture_suite_add_1smb2_test(suite, "INVALID1", test_compound_invalid1); 437 torture_suite_add_1smb2_test(suite, "INVALID2", test_compound_invalid2); 438 torture_suite_add_1smb2_test(suite, "INVALID3", test_compound_invalid3); 605 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "compound"); 606 607 torture_suite_add_1smb2_test(suite, "related1", test_compound_related1); 608 torture_suite_add_1smb2_test(suite, "related2", test_compound_related2); 609 torture_suite_add_1smb2_test(suite, "unrelated1", test_compound_unrelated1); 610 torture_suite_add_1smb2_test(suite, "invalid1", test_compound_invalid1); 611 torture_suite_add_1smb2_test(suite, "invalid2", test_compound_invalid2); 612 torture_suite_add_1smb2_test(suite, "invalid3", test_compound_invalid3); 613 torture_suite_add_1smb2_test(suite, "interim1", test_compound_interim1); 614 torture_suite_add_1smb2_test(suite, "interim2", test_compound_interim2); 439 615 440 616 suite->description = talloc_strdup(suite, "SMB2-COMPOUND tests"); -
trunk/server/source4/torture/smb2/connect.c
r414 r745 21 21 22 22 #include "includes.h" 23 #include "librpc/gen_ndr/security.h"24 23 #include "libcli/smb2/smb2.h" 25 24 #include "libcli/smb2/smb2_calls.h" -
trunk/server/source4/torture/smb2/create.c
r414 r745 24 24 #include "libcli/smb2/smb2_calls.h" 25 25 #include "torture/torture.h" 26 #include "torture/util.h" 26 27 #include "torture/smb2/proto.h" 27 28 #include "librpc/gen_ndr/ndr_security.h" 28 29 #include "libcli/security/security.h" 29 30 31 #include "system/filesys.h" 32 #include "auth/credentials/credentials.h" 33 #include "lib/cmdline/popt_common.h" 34 #include "librpc/gen_ndr/security.h" 35 #include "lib/events/events.h" 36 30 37 #define FNAME "test_create.dat" 38 #define DNAME "smb2_open" 31 39 32 40 #define CHECK_STATUS(status, correct) do { \ 33 41 if (!NT_STATUS_EQUAL(status, correct)) { \ 34 printf("(%s) Incorrect status %s - should be %s\n", \ 35 __location__, nt_errstr(status), nt_errstr(correct)); \ 42 torture_result(tctx, TORTURE_FAIL, \ 43 "(%s) Incorrect status %s - should be %s\n", \ 44 __location__, nt_errstr(status), nt_errstr(correct)); \ 36 45 return false; \ 37 46 }} while (0) … … 39 48 #define CHECK_EQUAL(v, correct) do { \ 40 49 if (v != correct) { \ 41 printf("(%s) Incorrect value for %s 0x%08llx - should be 0x%08llx\n", \ 42 __location__, #v, (unsigned long long)v, (unsigned long long)correct); \ 50 torture_result(tctx, TORTURE_FAIL, \ 51 "(%s) Incorrect value for %s 0x%08llx - " \ 52 "should be 0x%08llx\n", \ 53 __location__, #v, \ 54 (unsigned long long)v, \ 55 (unsigned long long)correct); \ 43 56 return false; \ 44 57 }} while (0) 45 58 46 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false)) 59 #define CHECK_TIME(t, field) do { \ 60 time_t t1, t2; \ 61 finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \ 62 finfo.all_info.in.file.handle = h1; \ 63 status = smb2_getinfo_file(tree, tctx, &finfo); \ 64 CHECK_STATUS(status, NT_STATUS_OK); \ 65 t1 = t & ~1; \ 66 t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \ 67 if (abs(t1-t2) > 2) { \ 68 torture_result(tctx, TORTURE_FAIL, \ 69 "(%s) wrong time for field %s %s - %s\n", \ 70 __location__, #field, \ 71 timestring(tctx, t1), \ 72 timestring(tctx, t2)); \ 73 dump_all_info(tctx, &finfo); \ 74 ret = false; \ 75 }} while (0) 76 77 #define CHECK_NTTIME(t, field) do { \ 78 NTTIME t2; \ 79 finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \ 80 finfo.all_info.in.file.handle = h1; \ 81 status = smb2_getinfo_file(tree, tctx, &finfo); \ 82 CHECK_STATUS(status, NT_STATUS_OK); \ 83 t2 = finfo.all_info.out.field; \ 84 if (t != t2) { \ 85 torture_result(tctx, TORTURE_FAIL, \ 86 "(%s) wrong time for field %s %s - %s\n", \ 87 __location__, #field, \ 88 nt_time_string(tctx, t), \ 89 nt_time_string(tctx, t2)); \ 90 dump_all_info(tctx, &finfo); \ 91 ret = false; \ 92 }} while (0) 93 94 #define CHECK_ALL_INFO(v, field) do { \ 95 finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \ 96 finfo.all_info.in.file.handle = h1; \ 97 status = smb2_getinfo_file(tree, tctx, &finfo); \ 98 CHECK_STATUS(status, NT_STATUS_OK); \ 99 if ((v) != (finfo.all_info.out.field)) { \ 100 torture_result(tctx, TORTURE_FAIL, \ 101 "(%s) wrong value for field %s 0x%x - 0x%x\n", \ 102 __location__, #field, (int)v,\ 103 (int)(finfo.all_info.out.field)); \ 104 dump_all_info(tctx, &finfo); \ 105 ret = false; \ 106 }} while (0) 107 108 #define CHECK_VAL(v, correct) do { \ 109 if ((v) != (correct)) { \ 110 torture_result(tctx, TORTURE_FAIL, \ 111 "(%s) wrong value for %s 0x%x - should be 0x%x\n", \ 112 __location__, #v, (int)(v), (int)correct); \ 113 ret = false; \ 114 }} while (0) 115 116 #define SET_ATTRIB(sattrib) do { \ 117 union smb_setfileinfo sfinfo; \ 118 ZERO_STRUCT(sfinfo.basic_info.in); \ 119 sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \ 120 sfinfo.basic_info.in.file.handle = h1; \ 121 sfinfo.basic_info.in.attrib = sattrib; \ 122 status = smb2_setinfo_file(tree, &sfinfo); \ 123 if (!NT_STATUS_IS_OK(status)) { \ 124 torture_comment(tctx, \ 125 "(%s) Failed to set attrib 0x%x on %s\n", \ 126 __location__, sattrib, fname); \ 127 }} while (0) 47 128 48 129 /* 49 130 test some interesting combinations found by gentest 50 131 */ 51 static bool test_create_gentest(struct torture_context *t orture, struct smb2_tree *tree)132 static bool test_create_gentest(struct torture_context *tctx, struct smb2_tree *tree) 52 133 { 53 134 struct smb2_create io; 54 135 NTSTATUS status; 55 TALLOC_CTX *tmp_ctx = talloc_new(tree);56 136 uint32_t access_mask, file_attributes_set; 57 137 uint32_t ok_mask, not_supported_mask, invalid_parameter_mask; … … 70 150 io.in.fname = FNAME; 71 151 72 status = smb2_create(tree, t mp_ctx, &io);152 status = smb2_create(tree, tctx, &io); 73 153 CHECK_STATUS(status, NT_STATUS_OK); 74 154 … … 77 157 78 158 io.in.create_options = 0xF0000000; 79 status = smb2_create(tree, t mp_ctx, &io);159 status = smb2_create(tree, tctx, &io); 80 160 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 81 161 … … 83 163 84 164 io.in.file_attributes = FILE_ATTRIBUTE_DEVICE; 85 status = smb2_create(tree, t mp_ctx, &io);165 status = smb2_create(tree, tctx, &io); 86 166 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 87 167 88 168 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME; 89 status = smb2_create(tree, t mp_ctx, &io);169 status = smb2_create(tree, tctx, &io); 90 170 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 91 171 92 172 io.in.create_disposition = NTCREATEX_DISP_OPEN; 93 173 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME; 94 status = smb2_create(tree, t mp_ctx, &io);174 status = smb2_create(tree, tctx, &io); 95 175 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 96 176 97 177 io.in.create_disposition = NTCREATEX_DISP_CREATE; 98 178 io.in.desired_access = 0x08000000; 99 status = smb2_create(tree, t mp_ctx, &io);179 status = smb2_create(tree, tctx, &io); 100 180 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); 101 181 102 182 io.in.desired_access = 0x04000000; 103 status = smb2_create(tree, t mp_ctx, &io);183 status = smb2_create(tree, tctx, &io); 104 184 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); 105 185 … … 119 199 continue; 120 200 } 121 status = smb2_create(tree, t mp_ctx, &io);201 status = smb2_create(tree, tctx, &io); 122 202 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { 123 203 not_supported_mask |= 1<<i; … … 132 212 } else { 133 213 unexpected_mask |= 1<<i; 134 printf("create option 0x%08x returned %s\n", 1<<i, nt_errstr(status)); 214 torture_comment(tctx, 215 "create option 0x%08x returned %s\n", 216 1<<i, nt_errstr(status)); 135 217 } 136 218 } … … 151 233 for (i=0;i<32;i++) { 152 234 io.in.desired_access = 1<<i; 153 status = smb2_create(tree, t mp_ctx, &io);235 status = smb2_create(tree, tctx, &io); 154 236 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || 155 237 NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) { … … 163 245 } 164 246 165 if (TARGET_IS_WIN7(t orture)) {247 if (TARGET_IS_WIN7(tctx)) { 166 248 CHECK_EQUAL(access_mask, 0x0de0fe00); 249 } else if (torture_setting_bool(tctx, "samba4", false)) { 250 CHECK_EQUAL(access_mask, 0x0cf0fe00); 167 251 } else { 168 252 CHECK_EQUAL(access_mask, 0x0df0fe00); … … 184 268 } 185 269 smb2_deltree(tree, FNAME); 186 status = smb2_create(tree, t mp_ctx, &io);270 status = smb2_create(tree, tctx, &io); 187 271 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { 188 272 invalid_parameter_mask |= 1<<i; … … 199 283 } else { 200 284 unexpected_mask |= 1<<i; 201 printf("file attribute 0x%08x returned %s\n", 1<<i, nt_errstr(status)); 285 torture_comment(tctx, 286 "file attribute 0x%08x returned %s\n", 287 1<<i, nt_errstr(status)); 202 288 } 203 289 } … … 215 301 */ 216 302 io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED; 217 status = smb2_create(tree, t mp_ctx, &io);303 status = smb2_create(tree, tctx, &io); 218 304 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { 219 printf("FILE_ATTRIBUTE_ENCRYPTED returned %s\n", nt_errstr(status)); 305 torture_comment(tctx, 306 "FILE_ATTRIBUTE_ENCRYPTED returned %s\n", 307 nt_errstr(status)); 220 308 } else { 221 309 CHECK_STATUS(status, NT_STATUS_OK); … … 236 324 io.in.create_options = 0; 237 325 io.in.fname = FNAME ":stream1"; 238 status = smb2_create(tree, t mp_ctx, &io);326 status = smb2_create(tree, tctx, &io); 239 327 CHECK_STATUS(status, NT_STATUS_OK); 240 328 … … 246 334 io.in.share_access = 247 335 NTCREATEX_SHARE_ACCESS_READ; 248 status = smb2_create(tree, t mp_ctx, &io);336 status = smb2_create(tree, tctx, &io); 249 337 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 250 338 … … 253 341 io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA; 254 342 io.in.query_maximal_access = true; 255 status = smb2_create(tree, t mp_ctx, &io);343 status = smb2_create(tree, tctx, &io); 256 344 CHECK_STATUS(status, NT_STATUS_OK); 257 345 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff); … … 259 347 q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; 260 348 q.access_information.in.file.handle = io.out.file.handle; 261 status = smb2_getinfo_file(tree, t mp_ctx, &q);349 status = smb2_getinfo_file(tree, tctx, &q); 262 350 CHECK_STATUS(status, NT_STATUS_OK); 263 351 CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access); … … 267 355 io.in.query_maximal_access = false; 268 356 io.in.share_access = 0; 269 status = smb2_create(tree, t mp_ctx, &io);357 status = smb2_create(tree, tctx, &io); 270 358 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); 271 359 272 talloc_free(tmp_ctx);273 274 360 smb2_deltree(tree, FNAME); 275 361 276 362 return true; 277 363 } … … 281 367 try the various request blobs 282 368 */ 283 static bool test_create_blob(struct torture_context *t orture, struct smb2_tree *tree)369 static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tree) 284 370 { 285 371 struct smb2_create io; 286 372 NTSTATUS status; 287 TALLOC_CTX *tmp_ctx = talloc_new(tree);288 373 289 374 smb2_deltree(tree, FNAME); … … 303 388 io.in.fname = FNAME; 304 389 305 status = smb2_create(tree, t mp_ctx, &io);390 status = smb2_create(tree, tctx, &io); 306 391 CHECK_STATUS(status, NT_STATUS_OK); 307 392 … … 309 394 CHECK_STATUS(status, NT_STATUS_OK); 310 395 311 printf("testing alloc size\n");396 torture_comment(tctx, "Testing alloc size\n"); 312 397 io.in.alloc_size = 4096; 313 status = smb2_create(tree, t mp_ctx, &io);398 status = smb2_create(tree, tctx, &io); 314 399 CHECK_STATUS(status, NT_STATUS_OK); 315 400 CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size); … … 318 403 CHECK_STATUS(status, NT_STATUS_OK); 319 404 320 printf("testing durable open\n");405 torture_comment(tctx, "Testing durable open\n"); 321 406 io.in.durable_open = true; 322 status = smb2_create(tree, t mp_ctx, &io);407 status = smb2_create(tree, tctx, &io); 323 408 CHECK_STATUS(status, NT_STATUS_OK); 324 409 … … 326 411 CHECK_STATUS(status, NT_STATUS_OK); 327 412 328 printf("testing query maximal access\n");413 torture_comment(tctx, "Testing query maximal access\n"); 329 414 io.in.query_maximal_access = true; 330 status = smb2_create(tree, t mp_ctx, &io);415 status = smb2_create(tree, tctx, &io); 331 416 CHECK_STATUS(status, NT_STATUS_OK); 332 417 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff); … … 335 420 CHECK_STATUS(status, NT_STATUS_OK); 336 421 337 printf("testing timewarp\n");422 torture_comment(tctx, "Testing timewarp\n"); 338 423 io.in.timewarp = 10000; 339 status = smb2_create(tree, t mp_ctx, &io);424 status = smb2_create(tree, tctx, &io); 340 425 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); 341 426 io.in.timewarp = 0; 342 427 343 printf("testing query_on_disk\n");428 torture_comment(tctx, "Testing query_on_disk\n"); 344 429 io.in.query_on_disk_id = true; 345 status = smb2_create(tree, t mp_ctx, &io);430 status = smb2_create(tree, tctx, &io); 346 431 CHECK_STATUS(status, NT_STATUS_OK); 347 432 … … 349 434 CHECK_STATUS(status, NT_STATUS_OK); 350 435 351 printf("testing unknown tag\n");352 status = smb2_create_blob_add(t mp_ctx, &io.in.blobs,436 torture_comment(tctx, "Testing unknown tag\n"); 437 status = smb2_create_blob_add(tctx, &io.in.blobs, 353 438 "FooO", data_blob(NULL, 0)); 354 439 CHECK_STATUS(status, NT_STATUS_OK); 355 440 356 status = smb2_create(tree, t mp_ctx, &io);441 status = smb2_create(tree, tctx, &io); 357 442 CHECK_STATUS(status, NT_STATUS_OK); 358 443 … … 360 445 CHECK_STATUS(status, NT_STATUS_OK); 361 446 362 printf("testing bad tag length\n");363 status = smb2_create_blob_add(t mp_ctx, &io.in.blobs,447 torture_comment(tctx, "Testing bad tag length\n"); 448 status = smb2_create_blob_add(tctx, &io.in.blobs, 364 449 "xxx", data_blob(NULL, 0)); 365 450 CHECK_STATUS(status, NT_STATUS_OK); 366 451 367 status = smb2_create(tree, t mp_ctx, &io);452 status = smb2_create(tree, tctx, &io); 368 453 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 369 370 talloc_free(tmp_ctx);371 454 372 455 smb2_deltree(tree, FNAME); … … 375 458 } 376 459 460 #define FAIL_UNLESS(__cond) \ 461 do { \ 462 if (__cond) {} else { \ 463 torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n", \ 464 __location__, #__cond); \ 465 ret = false; goto done; \ 466 } \ 467 } while(0) 468 377 469 /* 378 470 try creating with acls 379 471 */ 380 static bool test_create_acl (struct torture_context *torture, struct smb2_tree *tree)472 static bool test_create_acl_ext(struct torture_context *tctx, struct smb2_tree *tree, bool test_dir) 381 473 { 474 bool ret = true; 382 475 struct smb2_create io; 383 476 NTSTATUS status; 384 TALLOC_CTX *tmp_ctx = talloc_new(tree);385 477 struct security_ace ace; 386 struct security_descriptor *sd , *sd2;478 struct security_descriptor *sd; 387 479 struct dom_sid *test_sid; 388 union smb_fileinfo q; 480 union smb_fileinfo q = {}; 481 uint32_t attrib = 482 FILE_ATTRIBUTE_HIDDEN | 483 FILE_ATTRIBUTE_SYSTEM | 484 (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0); 485 NTSTATUS (*delete_func)(struct smb2_tree *, const char *) = 486 test_dir ? smb2_util_rmdir : smb2_util_unlink; 389 487 390 488 smb2_deltree(tree, FNAME); … … 393 491 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; 394 492 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 395 io.in.create_disposition = NTCREATEX_DISP_ OVERWRITE_IF;493 io.in.create_disposition = NTCREATEX_DISP_CREATE; 396 494 io.in.share_access = 397 NTCREATEX_SHARE_ACCESS_DELETE |398 NTCREATEX_SHARE_ACCESS_READ |495 NTCREATEX_SHARE_ACCESS_DELETE | 496 NTCREATEX_SHARE_ACCESS_READ | 399 497 NTCREATEX_SHARE_ACCESS_WRITE; 400 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY|401 NTCREATEX_OPTIONS_ASYNC_ALERT |402 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |403 0x00200000; 498 io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT | 0x00200000 | 499 (test_dir ? NTCREATEX_OPTIONS_DIRECTORY : 500 (NTCREATEX_OPTIONS_NON_DIRECTORY_FILE)); 501 404 502 io.in.fname = FNAME; 405 503 406 status = smb2_create(tree, tmp_ctx, &io); 504 torture_comment(tctx, "basic create\n"); 505 506 status = smb2_create(tree, tctx, &io); 407 507 CHECK_STATUS(status, NT_STATUS_OK); 408 508 … … 413 513 SECINFO_GROUP | 414 514 SECINFO_DACL; 415 status = smb2_getinfo_file(tree, t mp_ctx, &q);515 status = smb2_getinfo_file(tree, tctx, &q); 416 516 CHECK_STATUS(status, NT_STATUS_OK); 417 517 sd = q.query_secdesc.out.sd; … … 419 519 status = smb2_util_close(tree, io.out.file.handle); 420 520 CHECK_STATUS(status, NT_STATUS_OK); 421 422 smb2_util_unlink(tree, FNAME);423 424 printf("adding a new ACE\n");425 test_sid = dom_sid_parse_talloc(t mp_ctx, "S-1-5-32-1234-54321");521 status = delete_func(tree, FNAME); 522 CHECK_STATUS(status, NT_STATUS_OK); 523 524 torture_comment(tctx, "adding a new ACE\n"); 525 test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS); 426 526 427 527 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; … … 432 532 status = security_descriptor_dacl_add(sd, &ace); 433 533 CHECK_STATUS(status, NT_STATUS_OK); 534 535 torture_comment(tctx, "creating a file with an initial ACL\n"); 536 537 io.in.sec_desc = sd; 538 status = smb2_create(tree, tctx, &io); 539 CHECK_STATUS(status, NT_STATUS_OK); 540 541 FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd)); 542 543 status = smb2_util_close(tree, io.out.file.handle); 544 CHECK_STATUS(status, NT_STATUS_OK); 545 status = delete_func(tree, FNAME); 546 CHECK_STATUS(status, NT_STATUS_OK); 547 548 torture_comment(tctx, "creating with attributes\n"); 549 550 io.in.sec_desc = NULL; 551 io.in.file_attributes = attrib; 552 status = smb2_create(tree, tctx, &io); 553 CHECK_STATUS(status, NT_STATUS_OK); 554 555 FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib)); 556 557 status = smb2_util_close(tree, io.out.file.handle); 558 CHECK_STATUS(status, NT_STATUS_OK); 559 status = delete_func(tree, FNAME); 560 CHECK_STATUS(status, NT_STATUS_OK); 561 562 torture_comment(tctx, "creating with attributes and ACL\n"); 563 564 io.in.sec_desc = sd; 565 io.in.file_attributes = attrib; 566 status = smb2_create(tree, tctx, &io); 567 CHECK_STATUS(status, NT_STATUS_OK); 568 569 FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd)); 570 FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib)); 434 571 435 printf("creating a file with an initial ACL\n"); 572 status = smb2_util_close(tree, io.out.file.handle); 573 CHECK_STATUS(status, NT_STATUS_OK); 574 status = delete_func(tree, FNAME); 575 CHECK_STATUS(status, NT_STATUS_OK); 576 577 torture_comment(tctx, "creating with attributes, ACL and owner\n"); 578 sd = security_descriptor_dacl_create(tctx, 579 0, SID_WORLD, SID_BUILTIN_USERS, 580 SID_WORLD, 581 SEC_ACE_TYPE_ACCESS_ALLOWED, 582 SEC_RIGHTS_FILE_READ | SEC_STD_ALL, 583 0, 584 NULL); 436 585 437 586 io.in.sec_desc = sd; 438 status = smb2_create(tree, tmp_ctx, &io); 439 CHECK_STATUS(status, NT_STATUS_OK); 440 441 q.query_secdesc.in.file.handle = io.out.file.handle; 442 status = smb2_getinfo_file(tree, tmp_ctx, &q); 443 CHECK_STATUS(status, NT_STATUS_OK); 444 sd2 = q.query_secdesc.out.sd; 445 446 if (!security_acl_equal(sd->dacl, sd2->dacl)) { 447 printf("%s: security descriptors don't match!\n", __location__); 448 printf("got:\n"); 449 NDR_PRINT_DEBUG(security_descriptor, sd2); 450 printf("expected:\n"); 451 NDR_PRINT_DEBUG(security_descriptor, sd); 452 return false; 453 } 454 455 talloc_free(tmp_ctx); 456 457 return true; 587 io.in.file_attributes = attrib; 588 status = smb2_create(tree, tctx, &io); 589 CHECK_STATUS(status, NT_STATUS_OK); 590 591 FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd)); 592 FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib)); 593 594 done: 595 status = smb2_util_close(tree, io.out.file.handle); 596 CHECK_STATUS(status, NT_STATUS_OK); 597 status = delete_func(tree, FNAME); 598 CHECK_STATUS(status, NT_STATUS_OK); 599 600 return ret; 458 601 } 459 602 460 /* 603 /* 604 test SMB2 open 605 */ 606 static bool test_smb2_open(struct torture_context *tctx, 607 struct smb2_tree *tree) 608 { 609 union smb_open io; 610 union smb_fileinfo finfo; 611 const char *fname = DNAME "\\torture_ntcreatex.txt"; 612 const char *dname = DNAME "\\torture_ntcreatex.dir"; 613 NTSTATUS status; 614 struct smb2_handle h, h1; 615 bool ret = true; 616 int i; 617 struct { 618 uint32_t create_disp; 619 bool with_file; 620 NTSTATUS correct_status; 621 } open_funcs[] = { 622 { NTCREATEX_DISP_SUPERSEDE, true, NT_STATUS_OK }, 623 { NTCREATEX_DISP_SUPERSEDE, false, NT_STATUS_OK }, 624 { NTCREATEX_DISP_OPEN, true, NT_STATUS_OK }, 625 { NTCREATEX_DISP_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND }, 626 { NTCREATEX_DISP_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION }, 627 { NTCREATEX_DISP_CREATE, false, NT_STATUS_OK }, 628 { NTCREATEX_DISP_OPEN_IF, true, NT_STATUS_OK }, 629 { NTCREATEX_DISP_OPEN_IF, false, NT_STATUS_OK }, 630 { NTCREATEX_DISP_OVERWRITE, true, NT_STATUS_OK }, 631 { NTCREATEX_DISP_OVERWRITE, false, NT_STATUS_OBJECT_NAME_NOT_FOUND }, 632 { NTCREATEX_DISP_OVERWRITE_IF, true, NT_STATUS_OK }, 633 { NTCREATEX_DISP_OVERWRITE_IF, false, NT_STATUS_OK }, 634 { 6, true, NT_STATUS_INVALID_PARAMETER }, 635 { 6, false, NT_STATUS_INVALID_PARAMETER }, 636 }; 637 638 torture_comment(tctx, "Checking SMB2 Open\n"); 639 640 smb2_util_unlink(tree, fname); 641 smb2_util_rmdir(tree, dname); 642 643 status = torture_smb2_testdir(tree, DNAME, &h); 644 CHECK_STATUS(status, NT_STATUS_OK); 645 646 ZERO_STRUCT(io.smb2); 647 /* reasonable default parameters */ 648 io.generic.level = RAW_OPEN_SMB2; 649 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED; 650 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL; 651 io.smb2.in.alloc_size = 1024*1024; 652 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 653 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; 654 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 655 io.smb2.in.create_options = 0; 656 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 657 io.smb2.in.security_flags = 0; 658 io.smb2.in.fname = fname; 659 660 /* test the create disposition */ 661 for (i=0; i<ARRAY_SIZE(open_funcs); i++) { 662 if (open_funcs[i].with_file) { 663 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 664 status= smb2_create(tree, tctx, &(io.smb2)); 665 if (!NT_STATUS_IS_OK(status)) { 666 torture_comment(tctx, 667 "Failed to create file %s status %s %d\n", 668 fname, nt_errstr(status), i); 669 670 ret = false; 671 goto done; 672 } 673 smb2_util_close(tree, io.smb2.out.file.handle); 674 } 675 io.smb2.in.create_disposition = open_funcs[i].create_disp; 676 status = smb2_create(tree, tctx, &(io.smb2)); 677 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) { 678 torture_comment(tctx, 679 "(%s) incorrect status %s should be %s (i=%d " 680 "with_file=%d open_disp=%d)\n", 681 __location__, nt_errstr(status), 682 nt_errstr(open_funcs[i].correct_status), 683 i, (int)open_funcs[i].with_file, 684 (int)open_funcs[i].create_disp); 685 686 ret = false; 687 goto done; 688 } 689 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) { 690 smb2_util_close(tree, io.smb2.out.file.handle); 691 smb2_util_unlink(tree, fname); 692 } 693 } 694 695 /* basic field testing */ 696 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 697 698 status = smb2_create(tree, tctx, &(io.smb2)); 699 CHECK_STATUS(status, NT_STATUS_OK); 700 h1 = io.smb2.out.file.handle; 701 702 CHECK_VAL(io.smb2.out.oplock_level, 0); 703 CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED); 704 CHECK_NTTIME(io.smb2.out.create_time, create_time); 705 CHECK_NTTIME(io.smb2.out.access_time, access_time); 706 CHECK_NTTIME(io.smb2.out.write_time, write_time); 707 CHECK_NTTIME(io.smb2.out.change_time, change_time); 708 CHECK_ALL_INFO(io.smb2.out.file_attr, attrib); 709 CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size); 710 CHECK_ALL_INFO(io.smb2.out.size, size); 711 712 /* check fields when the file already existed */ 713 smb2_util_close(tree, h1); 714 smb2_util_unlink(tree, fname); 715 716 status = smb2_create_complex_file(tree, fname, &h1); 717 CHECK_STATUS(status, NT_STATUS_OK); 718 719 smb2_util_close(tree, h1); 720 721 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; 722 status = smb2_create(tree, tctx, &(io.smb2)); 723 CHECK_STATUS(status, NT_STATUS_OK); 724 h1 = io.smb2.out.file.handle; 725 726 CHECK_VAL(io.smb2.out.oplock_level, 0); 727 CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_EXISTED); 728 CHECK_NTTIME(io.smb2.out.create_time, create_time); 729 CHECK_NTTIME(io.smb2.out.access_time, access_time); 730 CHECK_NTTIME(io.smb2.out.write_time, write_time); 731 CHECK_NTTIME(io.smb2.out.change_time, change_time); 732 CHECK_ALL_INFO(io.smb2.out.file_attr, attrib); 733 CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size); 734 CHECK_ALL_INFO(io.smb2.out.size, size); 735 smb2_util_close(tree, h1); 736 smb2_util_unlink(tree, fname); 737 738 /* create a directory */ 739 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 740 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL; 741 io.smb2.in.alloc_size = 0; 742 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; 743 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; 744 io.smb2.in.create_options = 0; 745 io.smb2.in.fname = dname; 746 fname = dname; 747 748 smb2_util_rmdir(tree, fname); 749 smb2_util_unlink(tree, fname); 750 751 io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; 752 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 753 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 754 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 755 NTCREATEX_SHARE_ACCESS_WRITE; 756 status = smb2_create(tree, tctx, &(io.smb2)); 757 CHECK_STATUS(status, NT_STATUS_OK); 758 h1 = io.smb2.out.file.handle; 759 760 CHECK_VAL(io.smb2.out.oplock_level, 0); 761 CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED); 762 CHECK_NTTIME(io.smb2.out.create_time, create_time); 763 CHECK_NTTIME(io.smb2.out.access_time, access_time); 764 CHECK_NTTIME(io.smb2.out.write_time, write_time); 765 CHECK_NTTIME(io.smb2.out.change_time, change_time); 766 CHECK_ALL_INFO(io.smb2.out.file_attr, attrib); 767 CHECK_VAL(io.smb2.out.file_attr & ~FILE_ATTRIBUTE_NONINDEXED, 768 FILE_ATTRIBUTE_DIRECTORY); 769 CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size); 770 CHECK_ALL_INFO(io.smb2.out.size, size); 771 CHECK_VAL(io.smb2.out.size, 0); 772 CHECK_VAL(io.smb2.out.alloc_size, 0); 773 smb2_util_unlink(tree, fname); 774 775 done: 776 smb2_util_close(tree, h1); 777 smb2_util_unlink(tree, fname); 778 smb2_deltree(tree, DNAME); 779 return ret; 780 } 781 782 /* 783 test with an already opened and byte range locked file 784 */ 785 786 static bool test_smb2_open_brlocked(struct torture_context *tctx, 787 struct smb2_tree *tree) 788 { 789 union smb_open io, io1; 790 union smb_lock io2; 791 struct smb2_lock_element lock[1]; 792 const char *fname = DNAME "\\torture_ntcreatex.txt"; 793 NTSTATUS status; 794 bool ret = true; 795 struct smb2_handle h; 796 char b = 42; 797 798 torture_comment(tctx, 799 "Testing SMB2 open with a byte range locked file\n"); 800 801 smb2_util_unlink(tree, fname); 802 803 status = torture_smb2_testdir(tree, DNAME, &h); 804 CHECK_STATUS(status, NT_STATUS_OK); 805 806 ZERO_STRUCT(io.smb2); 807 io.generic.level = RAW_OPEN_SMB2; 808 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED; 809 io.smb2.in.desired_access = 0x2019f; 810 io.smb2.in.alloc_size = 0; 811 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 812 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 813 NTCREATEX_SHARE_ACCESS_WRITE; 814 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 815 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; 816 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION; 817 io.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING; 818 io.smb2.in.fname = fname; 819 820 status = smb2_create(tree, tctx, &(io.smb2)); 821 CHECK_STATUS(status, NT_STATUS_OK); 822 823 status = smb2_util_write(tree, io.smb2.out.file.handle, &b, 0, 1); 824 CHECK_STATUS(status, NT_STATUS_OK); 825 826 ZERO_STRUCT(io2.smb2); 827 io2.smb2.level = RAW_LOCK_SMB2; 828 io2.smb2.in.file.handle = io.smb2.out.file.handle; 829 io2.smb2.in.lock_count = 1; 830 831 ZERO_STRUCT(lock); 832 lock[0].offset = 0; 833 lock[0].length = 1; 834 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 835 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 836 io2.smb2.in.locks = &lock[0]; 837 status = smb2_lock(tree, &(io2.smb2)); 838 CHECK_STATUS(status, NT_STATUS_OK); 839 840 ZERO_STRUCT(io1.smb2); 841 io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED; 842 io1.smb2.in.desired_access = 0x20196; 843 io1.smb2.in.alloc_size = 0; 844 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 845 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 846 NTCREATEX_SHARE_ACCESS_WRITE; 847 io1.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF; 848 io1.smb2.in.create_options = 0; 849 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION; 850 io1.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING; 851 io1.smb2.in.fname = fname; 852 853 status = smb2_create(tree, tctx, &(io1.smb2)); 854 CHECK_STATUS(status, NT_STATUS_OK); 855 856 smb2_util_close(tree, io.smb2.out.file.handle); 857 smb2_util_close(tree, io1.smb2.out.file.handle); 858 smb2_util_unlink(tree, fname); 859 smb2_deltree(tree, DNAME); 860 861 return ret; 862 } 863 864 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */ 865 866 static bool test_smb2_open_multi(struct torture_context *tctx, 867 struct smb2_tree *tree) 868 { 869 const char *fname = "test_oplock.dat"; 870 NTSTATUS status; 871 bool ret = true; 872 union smb_open io; 873 struct smb2_tree **trees; 874 struct smb2_request **requests; 875 union smb_open *ios; 876 int i, num_files = 3; 877 int num_ok = 0; 878 int num_collision = 0; 879 880 torture_comment(tctx, 881 "Testing SMB2 Open with multiple connections\n"); 882 trees = talloc_array(tctx, struct smb2_tree *, num_files); 883 requests = talloc_array(tctx, struct smb2_request *, num_files); 884 ios = talloc_array(tctx, union smb_open, num_files); 885 if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) || 886 (ios == NULL)) { 887 torture_comment(tctx, ("talloc failed\n")); 888 ret = false; 889 goto done; 890 } 891 892 tree->session->transport->options.request_timeout = 60; 893 894 for (i=0; i<num_files; i++) { 895 if (!torture_smb2_connection(tctx, &(trees[i]))) { 896 torture_comment(tctx, 897 "Could not open %d'th connection\n", i); 898 ret = false; 899 goto done; 900 } 901 trees[i]->session->transport->options.request_timeout = 60; 902 } 903 904 /* cleanup */ 905 smb2_util_unlink(tree, fname); 906 907 /* 908 base ntcreatex parms 909 */ 910 ZERO_STRUCT(io.smb2); 911 io.generic.level = RAW_OPEN_SMB2; 912 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL; 913 io.smb2.in.alloc_size = 0; 914 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 915 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ| 916 NTCREATEX_SHARE_ACCESS_WRITE| 917 NTCREATEX_SHARE_ACCESS_DELETE; 918 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 919 io.smb2.in.create_options = 0; 920 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 921 io.smb2.in.security_flags = 0; 922 io.smb2.in.fname = fname; 923 io.smb2.in.create_flags = 0; 924 925 for (i=0; i<num_files; i++) { 926 ios[i] = io; 927 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2)); 928 if (requests[i] == NULL) { 929 torture_comment(tctx, 930 "could not send %d'th request\n", i); 931 ret = false; 932 goto done; 933 } 934 } 935 936 torture_comment(tctx, "waiting for replies\n"); 937 while (1) { 938 bool unreplied = false; 939 for (i=0; i<num_files; i++) { 940 if (requests[i] == NULL) { 941 continue; 942 } 943 if (requests[i]->state < SMB2_REQUEST_DONE) { 944 unreplied = true; 945 break; 946 } 947 status = smb2_create_recv(requests[i], tctx, 948 &(ios[i].smb2)); 949 950 torture_comment(tctx, 951 "File %d returned status %s\n", i, 952 nt_errstr(status)); 953 954 if (NT_STATUS_IS_OK(status)) { 955 num_ok += 1; 956 } 957 958 if (NT_STATUS_EQUAL(status, 959 NT_STATUS_OBJECT_NAME_COLLISION)) { 960 num_collision += 1; 961 } 962 963 requests[i] = NULL; 964 } 965 if (!unreplied) { 966 break; 967 } 968 969 if (event_loop_once(tctx->ev) != 0) { 970 torture_comment(tctx, "event_loop_once failed\n"); 971 ret = false; 972 goto done; 973 } 974 } 975 976 if ((num_ok != 1) || (num_ok + num_collision != num_files)) { 977 ret = false; 978 } 979 done: 980 smb2_deltree(tree, fname); 981 982 return ret; 983 } 984 985 /* 986 test opening for delete on a read-only attribute file. 987 */ 988 989 static bool test_smb2_open_for_delete(struct torture_context *tctx, 990 struct smb2_tree *tree) 991 { 992 union smb_open io; 993 union smb_fileinfo finfo; 994 const char *fname = DNAME "\\torture_open_for_delete.txt"; 995 NTSTATUS status; 996 struct smb2_handle h, h1; 997 bool ret = true; 998 999 torture_comment(tctx, 1000 "Checking SMB2_OPEN for delete on a readonly file.\n"); 1001 smb2_util_unlink(tree, fname); 1002 smb2_deltree(tree, fname); 1003 1004 status = torture_smb2_testdir(tree, DNAME, &h); 1005 CHECK_STATUS(status, NT_STATUS_OK); 1006 1007 /* reasonable default parameters */ 1008 ZERO_STRUCT(io.smb2); 1009 io.generic.level = RAW_OPEN_SMB2; 1010 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED; 1011 io.smb2.in.alloc_size = 0; 1012 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL; 1013 io.smb2.in.file_attributes = FILE_ATTRIBUTE_READONLY; 1014 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; 1015 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 1016 io.smb2.in.create_options = 0; 1017 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1018 io.smb2.in.security_flags = 0; 1019 io.smb2.in.fname = fname; 1020 1021 /* Create the readonly file. */ 1022 1023 status = smb2_create(tree, tctx, &(io.smb2)); 1024 CHECK_STATUS(status, NT_STATUS_OK); 1025 h1 = io.smb2.out.file.handle; 1026 1027 CHECK_VAL(io.smb2.out.oplock_level, 0); 1028 io.smb2.in.create_options = 0; 1029 CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED); 1030 CHECK_ALL_INFO(io.smb2.out.file_attr, attrib); 1031 smb2_util_close(tree, h1); 1032 1033 /* Now try and open for delete only - should succeed. */ 1034 io.smb2.in.desired_access = SEC_STD_DELETE; 1035 io.smb2.in.file_attributes = 0; 1036 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1037 NTCREATEX_SHARE_ACCESS_WRITE | 1038 NTCREATEX_SHARE_ACCESS_DELETE; 1039 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; 1040 status = smb2_create(tree, tctx, &(io.smb2)); 1041 CHECK_STATUS(status, NT_STATUS_OK); 1042 1043 smb2_util_unlink(tree, fname); 1044 1045 smb2_util_close(tree, h1); 1046 smb2_util_unlink(tree, fname); 1047 smb2_deltree(tree, DNAME); 1048 1049 return ret; 1050 } 1051 1052 /* 1053 test SMB2 open with a leading slash on the path. 1054 Trying to create a directory with a leading slash 1055 should give NT_STATUS_INVALID_PARAMETER error 1056 */ 1057 static bool test_smb2_leading_slash(struct torture_context *tctx, 1058 struct smb2_tree *tree) 1059 { 1060 union smb_open io; 1061 const char *dnameslash = "\\"DNAME; 1062 NTSTATUS status; 1063 bool ret = true; 1064 1065 torture_comment(tctx, 1066 "Trying to create a directory with leading slash on path\n"); 1067 smb2_deltree(tree, dnameslash); 1068 1069 ZERO_STRUCT(io.smb2); 1070 io.generic.level = RAW_OPEN_SMB2; 1071 io.smb2.in.oplock_level = 0; 1072 io.smb2.in.desired_access = SEC_RIGHTS_DIR_ALL; 1073 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; 1074 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; 1075 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1076 NTCREATEX_SHARE_ACCESS_WRITE | 1077 NTCREATEX_SHARE_ACCESS_DELETE; 1078 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1079 io.smb2.in.fname = dnameslash; 1080 1081 status = smb2_create(tree, tree, &(io.smb2)); 1082 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 1083 1084 smb2_deltree(tree, dnameslash); 1085 return ret; 1086 } 1087 1088 1089 static bool test_create_acl_file(struct torture_context *tctx, 1090 struct smb2_tree *tree) 1091 { 1092 torture_comment(tctx, "Testing nttrans create with sec_desc on files\n"); 1093 1094 return test_create_acl_ext(tctx, tree, false); 1095 } 1096 1097 static bool test_create_acl_dir(struct torture_context *tctx, 1098 struct smb2_tree *tree) 1099 { 1100 torture_comment(tctx, "Testing nttrans create with sec_desc on directories\n"); 1101 1102 return test_create_acl_ext(tctx, tree, true); 1103 } 1104 1105 #define CHECK_ACCESS_FLAGS(_fh, flags) do { \ 1106 union smb_fileinfo _q; \ 1107 _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \ 1108 _q.access_information.in.file.handle = (_fh); \ 1109 status = smb2_getinfo_file(tree, tctx, &_q); \ 1110 CHECK_STATUS(status, NT_STATUS_OK); \ 1111 if (_q.access_information.out.access_flags != (flags)) { \ 1112 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \ 1113 __location__, _q.access_information.out.access_flags, (flags)); \ 1114 ret = false; \ 1115 goto done; \ 1116 } \ 1117 } while (0) 1118 1119 /* 1120 * Test creating a file with a NULL DACL. 1121 */ 1122 static bool test_create_null_dacl(struct torture_context *tctx, 1123 struct smb2_tree *tree) 1124 { 1125 NTSTATUS status; 1126 struct smb2_create io; 1127 const char *fname = "nulldacl.txt"; 1128 bool ret = true; 1129 struct smb2_handle handle; 1130 union smb_fileinfo q; 1131 union smb_setfileinfo s; 1132 struct security_descriptor *sd = security_descriptor_initialise(tctx); 1133 struct security_acl dacl; 1134 1135 torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n"); 1136 1137 smb2_util_unlink(tree, fname); 1138 1139 ZERO_STRUCT(io); 1140 io.level = RAW_OPEN_SMB2; 1141 io.in.create_flags = 0; 1142 io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC 1143 | SEC_STD_WRITE_OWNER; 1144 io.in.create_options = 0; 1145 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1146 io.in.share_access = 1147 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; 1148 io.in.alloc_size = 0; 1149 io.in.create_disposition = NTCREATEX_DISP_CREATE; 1150 io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS; 1151 io.in.security_flags = 0; 1152 io.in.fname = fname; 1153 io.in.sec_desc = sd; 1154 /* XXX create_options ? */ 1155 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY | 1156 NTCREATEX_OPTIONS_ASYNC_ALERT | 1157 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE | 1158 0x00200000; 1159 1160 torture_comment(tctx, "creating a file with a empty sd\n"); 1161 status = smb2_create(tree, tctx, &io); 1162 CHECK_STATUS(status, NT_STATUS_OK); 1163 handle = io.out.file.handle; 1164 1165 torture_comment(tctx, "get the original sd\n"); 1166 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; 1167 q.query_secdesc.in.file.handle = handle; 1168 q.query_secdesc.in.secinfo_flags = 1169 SECINFO_OWNER | 1170 SECINFO_GROUP | 1171 SECINFO_DACL; 1172 status = smb2_getinfo_file(tree, tctx, &q); 1173 CHECK_STATUS(status, NT_STATUS_OK); 1174 1175 /* 1176 * Testing the created DACL, 1177 * the server should add the inherited DACL 1178 * when SEC_DESC_DACL_PRESENT isn't specified 1179 */ 1180 if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { 1181 ret = false; 1182 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); 1183 } 1184 if (q.query_secdesc.out.sd->dacl == NULL) { 1185 ret = false; 1186 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n"); 1187 } 1188 1189 torture_comment(tctx, "set NULL DACL\n"); 1190 sd->type |= SEC_DESC_DACL_PRESENT; 1191 1192 s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; 1193 s.set_secdesc.in.file.handle = handle; 1194 s.set_secdesc.in.secinfo_flags = SECINFO_DACL; 1195 s.set_secdesc.in.sd = sd; 1196 status = smb2_setinfo_file(tree, &s); 1197 CHECK_STATUS(status, NT_STATUS_OK); 1198 1199 torture_comment(tctx, "get the sd\n"); 1200 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; 1201 q.query_secdesc.in.file.handle = handle; 1202 q.query_secdesc.in.secinfo_flags = 1203 SECINFO_OWNER | 1204 SECINFO_GROUP | 1205 SECINFO_DACL; 1206 status = smb2_getinfo_file(tree, tctx, &q); 1207 CHECK_STATUS(status, NT_STATUS_OK); 1208 1209 /* Testing the modified DACL */ 1210 if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { 1211 ret = false; 1212 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); 1213 } 1214 if (q.query_secdesc.out.sd->dacl != NULL) { 1215 ret = false; 1216 torture_fail_goto(tctx, done, "DACL has been created on the server!\n"); 1217 } 1218 1219 io.in.create_disposition = NTCREATEX_DISP_OPEN; 1220 1221 torture_comment(tctx, "try open for read control\n"); 1222 io.in.desired_access = SEC_STD_READ_CONTROL; 1223 status = smb2_create(tree, tctx, &io); 1224 CHECK_STATUS(status, NT_STATUS_OK); 1225 CHECK_ACCESS_FLAGS(io.out.file.handle, 1226 SEC_STD_READ_CONTROL); 1227 smb2_util_close(tree, io.out.file.handle); 1228 1229 torture_comment(tctx, "try open for write\n"); 1230 io.in.desired_access = SEC_FILE_WRITE_DATA; 1231 status = smb2_create(tree, tctx, &io); 1232 CHECK_STATUS(status, NT_STATUS_OK); 1233 CHECK_ACCESS_FLAGS(io.out.file.handle, 1234 SEC_FILE_WRITE_DATA); 1235 smb2_util_close(tree, io.out.file.handle); 1236 1237 torture_comment(tctx, "try open for read\n"); 1238 io.in.desired_access = SEC_FILE_READ_DATA; 1239 status = smb2_create(tree, tctx, &io); 1240 CHECK_STATUS(status, NT_STATUS_OK); 1241 CHECK_ACCESS_FLAGS(io.out.file.handle, 1242 SEC_FILE_READ_DATA); 1243 smb2_util_close(tree, io.out.file.handle); 1244 1245 torture_comment(tctx, "try open for generic write\n"); 1246 io.in.desired_access = SEC_GENERIC_WRITE; 1247 status = smb2_create(tree, tctx, &io); 1248 CHECK_STATUS(status, NT_STATUS_OK); 1249 CHECK_ACCESS_FLAGS(io.out.file.handle, 1250 SEC_RIGHTS_FILE_WRITE); 1251 smb2_util_close(tree, io.out.file.handle); 1252 1253 torture_comment(tctx, "try open for generic read\n"); 1254 io.in.desired_access = SEC_GENERIC_READ; 1255 status = smb2_create(tree, tctx, &io); 1256 CHECK_STATUS(status, NT_STATUS_OK); 1257 CHECK_ACCESS_FLAGS(io.out.file.handle, 1258 SEC_RIGHTS_FILE_READ); 1259 smb2_util_close(tree, io.out.file.handle); 1260 1261 torture_comment(tctx, "set DACL with 0 aces\n"); 1262 ZERO_STRUCT(dacl); 1263 dacl.revision = SECURITY_ACL_REVISION_NT4; 1264 dacl.num_aces = 0; 1265 sd->dacl = &dacl; 1266 1267 s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; 1268 s.set_secdesc.in.file.handle = handle; 1269 s.set_secdesc.in.secinfo_flags = SECINFO_DACL; 1270 s.set_secdesc.in.sd = sd; 1271 status = smb2_setinfo_file(tree, &s); 1272 CHECK_STATUS(status, NT_STATUS_OK); 1273 1274 torture_comment(tctx, "get the sd\n"); 1275 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; 1276 q.query_secdesc.in.file.handle = handle; 1277 q.query_secdesc.in.secinfo_flags = 1278 SECINFO_OWNER | 1279 SECINFO_GROUP | 1280 SECINFO_DACL; 1281 status = smb2_getinfo_file(tree, tctx, &q); 1282 CHECK_STATUS(status, NT_STATUS_OK); 1283 1284 /* Testing the modified DACL */ 1285 if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { 1286 ret = false; 1287 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); 1288 } 1289 if (q.query_secdesc.out.sd->dacl == NULL) { 1290 ret = false; 1291 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n"); 1292 } 1293 if (q.query_secdesc.out.sd->dacl->num_aces != 0) { 1294 torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n", 1295 q.query_secdesc.out.sd->dacl->num_aces); 1296 ret = false; 1297 goto done; 1298 } 1299 1300 torture_comment(tctx, "try open for read control\n"); 1301 io.in.desired_access = SEC_STD_READ_CONTROL; 1302 status = smb2_create(tree, tctx, &io); 1303 CHECK_STATUS(status, NT_STATUS_OK); 1304 CHECK_ACCESS_FLAGS(io.out.file.handle, 1305 SEC_STD_READ_CONTROL); 1306 smb2_util_close(tree, io.out.file.handle); 1307 1308 torture_comment(tctx, "try open for write => access_denied\n"); 1309 io.in.desired_access = SEC_FILE_WRITE_DATA; 1310 status = smb2_create(tree, tctx, &io); 1311 if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { 1312 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); 1313 } else { 1314 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); 1315 } 1316 1317 torture_comment(tctx, "try open for read => access_denied\n"); 1318 io.in.desired_access = SEC_FILE_READ_DATA; 1319 status = smb2_create(tree, tctx, &io); 1320 if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { 1321 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); 1322 } else { 1323 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); 1324 } 1325 1326 torture_comment(tctx, "try open for generic write => access_denied\n"); 1327 io.in.desired_access = SEC_GENERIC_WRITE; 1328 status = smb2_create(tree, tctx, &io); 1329 if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { 1330 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); 1331 } else { 1332 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); 1333 } 1334 1335 torture_comment(tctx, "try open for generic read => access_denied\n"); 1336 io.in.desired_access = SEC_GENERIC_READ; 1337 status = smb2_create(tree, tctx, &io); 1338 if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { 1339 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); 1340 } else { 1341 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); 1342 } 1343 1344 torture_comment(tctx, "set empty sd\n"); 1345 sd->type &= ~SEC_DESC_DACL_PRESENT; 1346 sd->dacl = NULL; 1347 1348 s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; 1349 s.set_secdesc.in.file.handle = handle; 1350 s.set_secdesc.in.secinfo_flags = SECINFO_DACL; 1351 s.set_secdesc.in.sd = sd; 1352 status = smb2_setinfo_file(tree, &s); 1353 CHECK_STATUS(status, NT_STATUS_OK); 1354 1355 torture_comment(tctx, "get the sd\n"); 1356 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; 1357 q.query_secdesc.in.file.handle = handle; 1358 q.query_secdesc.in.secinfo_flags = 1359 SECINFO_OWNER | 1360 SECINFO_GROUP | 1361 SECINFO_DACL; 1362 status = smb2_getinfo_file(tree, tctx, &q); 1363 CHECK_STATUS(status, NT_STATUS_OK); 1364 1365 /* Testing the modified DACL */ 1366 if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { 1367 ret = false; 1368 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); 1369 } 1370 if (q.query_secdesc.out.sd->dacl != NULL) { 1371 ret = false; 1372 torture_fail_goto(tctx, done, "DACL has been created on the server!\n"); 1373 } 1374 done: 1375 smb2_util_close(tree, handle); 1376 smb2_util_unlink(tree, fname); 1377 smb2_tdis(tree); 1378 smb2_logoff(tree->session); 1379 return ret; 1380 } 1381 1382 /* 461 1383 basic testing of SMB2 read 462 1384 */ 463 1385 struct torture_suite *torture_smb2_create_init(void) 464 1386 { 465 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE"); 466 467 torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest); 468 torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob); 469 torture_suite_add_1smb2_test(suite, "ACL", test_create_acl); 1387 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "create"); 1388 1389 torture_suite_add_1smb2_test(suite, "gentest", test_create_gentest); 1390 torture_suite_add_1smb2_test(suite, "blob", test_create_blob); 1391 torture_suite_add_1smb2_test(suite, "open", test_smb2_open); 1392 torture_suite_add_1smb2_test(suite, "brlocked", test_smb2_open_brlocked); 1393 torture_suite_add_1smb2_test(suite, "multi", test_smb2_open_multi); 1394 torture_suite_add_1smb2_test(suite, "delete", test_smb2_open_for_delete); 1395 torture_suite_add_1smb2_test(suite, "leading-slash", test_smb2_leading_slash); 1396 torture_suite_add_1smb2_test(suite, "aclfile", test_create_acl_file); 1397 torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir); 1398 torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl); 470 1399 471 1400 suite->description = talloc_strdup(suite, "SMB2-CREATE tests"); -
trunk/server/source4/torture/smb2/dir.c
r414 r745 35 35 36 36 #include "system/filesys.h" 37 #include "lib/util/tsort.h" 37 38 38 39 #define DNAME "smb2_dir" … … 109 110 NTSTATUS status; 110 111 bool ret = true; 111 u int_t count;112 unsigned int count; 112 113 int i, j, file_count = 0; 113 114 … … 194 195 NTSTATUS status; 195 196 bool ret = true; 196 u int_t count;197 unsigned int count; 197 198 int i; 198 199 … … 267 268 268 269 torture_result(tctx, TORTURE_FAIL, 269 "(%s): didn't expect %s\n",270 __location__, found);270 "(%s): didn't expect %s (count=%u)\n", 271 __location__, found, count); 271 272 ret = false; 272 273 goto done; … … 361 362 union smb_search_data *data, 362 363 union smb_search_data *d, 363 u int_t count,364 unsigned int count, 364 365 uint8_t level, 365 366 enum smb_search_data_level data_level) … … 386 387 int idx, 387 388 union smb_search_data *d, 388 u int_t *count,389 unsigned int *count, 389 390 struct smb2_handle *h) 390 391 { … … 417 418 NTSTATUS status; 418 419 int i; 419 u int_t count;420 unsigned int count; 420 421 union smb_fileinfo all_info2, alt_info, internal_info; 421 422 union smb_search_data *s; … … 432 433 /* call all the File Information Classes */ 433 434 for (i=0;i<ARRAY_SIZE(levels);i++) { 434 torture_comment(tctx, " testing %s %d\n", levels[i].name,435 torture_comment(tctx, "Testing %s %d\n", levels[i].name, 435 436 levels[i].level); 436 437 … … 672 673 struct smb2_find f; 673 674 bool ret = true; 674 u int_t count = 0;675 unsigned int count = 0; 675 676 union smb_search_data *d; 676 677 NTSTATUS status; … … 809 810 level_sort = search_types[t].level; 810 811 811 qsort(result.list, result.count, sizeof(result.list[0]), 812 QSORT_CAST search_compare); 812 TYPESAFE_QSORT(result.list, result.count, search_compare); 813 813 814 814 for (i=0;i<result.count;i++) { … … 896 896 bool ret = true; 897 897 int i; 898 u int_t count;898 unsigned int count; 899 899 900 900 smb2_deltree(tree, DNAME); … … 1106 1106 struct smb2_handle h; 1107 1107 union smb_search_data *d; 1108 intcount;1108 unsigned count; 1109 1109 1110 1110 smb2_deltree(tree, DNAME); … … 1224 1224 struct smb2_handle h; 1225 1225 union smb_search_data *d; 1226 int count, file_count = 0;1226 int i, j, file_count = 0; 1227 1227 char **strs = NULL; 1228 int i, j;1228 unsigned count; 1229 1229 1230 1230 torture_comment(tctx, … … 1331 1331 { 1332 1332 struct torture_suite *suite = 1333 torture_suite_create(talloc_autofree_context(), " DIR");1334 1335 torture_suite_add_1smb2_test(suite, " FIND", test_find);1336 torture_suite_add_1smb2_test(suite, " FIXED", test_fixed);1337 torture_suite_add_1smb2_test(suite, " ONE", test_one_file);1338 torture_suite_add_1smb2_test(suite, " MANY", test_many_files);1339 torture_suite_add_1smb2_test(suite, " MODIFY", test_modify_search);1340 torture_suite_add_1smb2_test(suite, " SORTED", test_sorted);1341 torture_suite_add_1smb2_test(suite, " FILE-INDEX", test_file_index);1342 torture_suite_add_1smb2_test(suite, " LARGE-FILES", test_large_files);1333 torture_suite_create(talloc_autofree_context(), "dir"); 1334 1335 torture_suite_add_1smb2_test(suite, "find", test_find); 1336 torture_suite_add_1smb2_test(suite, "fixed", test_fixed); 1337 torture_suite_add_1smb2_test(suite, "one", test_one_file); 1338 torture_suite_add_1smb2_test(suite, "many", test_many_files); 1339 torture_suite_add_1smb2_test(suite, "modify", test_modify_search); 1340 torture_suite_add_1smb2_test(suite, "sorted", test_sorted); 1341 torture_suite_add_1smb2_test(suite, "file-index", test_file_index); 1342 torture_suite_add_1smb2_test(suite, "large-files", test_large_files); 1343 1343 suite->description = talloc_strdup(suite, "SMB2-DIR tests"); 1344 1344 -
trunk/server/source4/torture/smb2/durable_open.c
r414 r745 21 21 22 22 #include "includes.h" 23 #include "librpc/gen_ndr/security.h"24 23 #include "libcli/smb2/smb2.h" 25 24 #include "libcli/smb2/smb2_calls.h" … … 435 434 lck.in.locks = el; 436 435 lck.in.lock_count = 0x0001; 437 lck.in. reserved= 0x00000000;436 lck.in.lock_sequence = 0x00000000; 438 437 lck.in.file.handle = h; 439 438 el[0].offset = 0; … … 588 587 { 589 588 struct torture_suite *suite = 590 torture_suite_create(talloc_autofree_context(), " DURABLE-OPEN");591 592 torture_suite_add_2smb2_test(suite, " FILE-POSITION",589 torture_suite_create(talloc_autofree_context(), "durable-open"); 590 591 torture_suite_add_2smb2_test(suite, "file-position", 593 592 test_durable_open_file_position); 594 torture_suite_add_2smb2_test(suite, " OPLOCK", test_durable_open_oplock);595 torture_suite_add_2smb2_test(suite, " LEASE", test_durable_open_lease);596 torture_suite_add_1smb2_test(suite, " LOCK", test_durable_open_lock);597 torture_suite_add_2smb2_test(suite, " OPEN", test_durable_open_open);593 torture_suite_add_2smb2_test(suite, "oplock", test_durable_open_oplock); 594 torture_suite_add_2smb2_test(suite, "lease", test_durable_open_lease); 595 torture_suite_add_1smb2_test(suite, "lock", test_durable_open_lock); 596 torture_suite_add_2smb2_test(suite, "open", test_durable_open_open); 598 597 599 598 suite->description = talloc_strdup(suite, "SMB2-DURABLE-OPEN tests"); -
trunk/server/source4/torture/smb2/lease.c
r414 r745 21 21 22 22 #include "includes.h" 23 #include "lib/events/events.h"24 #include "librpc/gen_ndr/security.h"25 23 #include "libcli/smb2/smb2.h" 26 24 #include "libcli/smb2/smb2_calls.h" … … 806 804 807 805 /* Sleep, use a write to clear the recv queue. */ 808 msleep(250);806 smb_msleep(250); 809 807 ZERO_STRUCT(w); 810 808 w.in.file.handle = h3; … … 835 833 { 836 834 struct torture_suite *suite = 837 torture_suite_create(talloc_autofree_context(), " LEASE");838 839 torture_suite_add_1smb2_test(suite, " REQUEST", test_lease_request);840 torture_suite_add_1smb2_test(suite, " UPGRADE", test_lease_upgrade);841 torture_suite_add_1smb2_test(suite, " BREAK", test_lease_break);842 torture_suite_add_1smb2_test(suite, " OPLOCK", test_lease_oplock);843 torture_suite_add_1smb2_test(suite, " MULTIBREAK", test_lease_multibreak);835 torture_suite_create(talloc_autofree_context(), "lease"); 836 837 torture_suite_add_1smb2_test(suite, "request", test_lease_request); 838 torture_suite_add_1smb2_test(suite, "upgrade", test_lease_upgrade); 839 torture_suite_add_1smb2_test(suite, "break", test_lease_break); 840 torture_suite_add_1smb2_test(suite, "oplock", test_lease_oplock); 841 torture_suite_add_1smb2_test(suite, "multibreak", test_lease_multibreak); 844 842 845 843 suite->description = talloc_strdup(suite, "SMB2-LEASE tests"); -
trunk/server/source4/torture/smb2/lock.c
r414 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 … … 5 5 6 6 Copyright (C) Stefan Metzmacher 2006 7 7 8 8 This program is free software; you can redistribute it and/or modify 9 9 it under the terms of the GNU General Public License as published by 10 10 the Free Software Foundation; either version 3 of the License, or 11 11 (at your option) any later version. 12 12 13 13 This program is distributed in the hope that it will be useful, 14 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 16 GNU General Public License for more details. 17 17 18 18 You should have received a copy of the GNU General Public License 19 19 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 26 26 #include "torture/torture.h" 27 27 #include "torture/smb2/proto.h" 28 29 #include "librpc/gen_ndr/ndr_security.h" 30 31 #define TARGET_IS_WINDOWS(_tctx) (torture_setting_bool(_tctx, "win7", false) || torture_setting_bool(torture, "windows", false)) 32 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false)) 28 #include "torture/util.h" 29 30 #include "lib/events/events.h" 31 #include "param/param.h" 33 32 34 33 #define CHECK_STATUS(status, correct) do { \ 34 const char *_cmt = "(" __location__ ")"; \ 35 torture_assert_ntstatus_equal_goto(torture,status,correct, \ 36 ret,done,_cmt); \ 37 } while (0) 38 39 #define CHECK_STATUS_CMT(status, correct, cmt) do { \ 40 torture_assert_ntstatus_equal_goto(torture,status,correct, \ 41 ret,done,cmt); \ 42 } while (0) 43 44 #define CHECK_STATUS_CONT(status, correct) do { \ 35 45 if (!NT_STATUS_EQUAL(status, correct)) { \ 36 printf("(%s) Incorrect status %s - should be %s\n", \ 37 __location__, nt_errstr(status), nt_errstr(correct)); \ 46 torture_result(torture, TORTURE_FAIL, \ 47 "(%s) Incorrect status %s - should be %s\n", \ 48 __location__, nt_errstr(status), nt_errstr(correct)); \ 38 49 ret = false; \ 39 goto done; \40 50 }} while (0) 41 51 42 52 #define CHECK_VALUE(v, correct) do { \ 43 if ((v) != (correct)) { \ 44 printf("(%s) Incorrect value %s=%d - should be %d\n", \ 45 __location__, #v, v, correct); \ 46 ret = false; \ 47 goto done; \ 48 }} while (0) 49 50 static bool test_valid_request(struct torture_context *torture, struct smb2_tree *tree) 53 const char *_cmt = "(" __location__ ")"; \ 54 torture_assert_int_equal_goto(torture,v,correct,ret,done,_cmt); \ 55 } while (0) 56 57 #define BASEDIR "testlock" 58 59 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \ 60 (torture_setting_bool(_tctx, "invalid_lock_range_support", true)) 61 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false)) 62 63 #define WAIT_FOR_ASYNC_RESPONSE(req) \ 64 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \ 65 if (event_loop_once(req->transport->socket->event.ctx) != 0) { \ 66 break; \ 67 } \ 68 } 69 70 static bool test_valid_request(struct torture_context *torture, 71 struct smb2_tree *tree) 51 72 { 52 73 bool ret = true; … … 67 88 lck.in.locks = el; 68 89 90 torture_comment(torture, "Test request with 0 locks.\n"); 91 69 92 lck.in.lock_count = 0x0000; 70 lck.in. reserved= 0x00000000;93 lck.in.lock_sequence = 0x00000000; 71 94 lck.in.file.handle = h; 72 95 el[0].offset = 0x0000000000000000; … … 77 100 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 78 101 79 lck.in.lock_count = 0x0001; 80 lck.in.reserved = 0x00000000; 102 lck.in.lock_count = 0x0000; 103 lck.in.lock_sequence = 0x00000000; 104 lck.in.file.handle = h; 105 el[0].offset = 0; 106 el[0].length = 0; 107 el[0].reserved = 0x00000000; 108 el[0].flags = SMB2_LOCK_FLAG_SHARED; 109 status = smb2_lock(tree, &lck); 110 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 111 112 lck.in.lock_count = 0x0001; 113 lck.in.lock_sequence = 0x00000000; 81 114 lck.in.file.handle = h; 82 115 el[0].offset = 0; … … 85 118 el[0].flags = SMB2_LOCK_FLAG_NONE; 86 119 status = smb2_lock(tree, &lck); 87 CHECK_STATUS(status, NT_STATUS_OK); 88 CHECK_VALUE(lck.out.reserved, 0); 120 if (TARGET_IS_W2K8(torture)) { 121 CHECK_STATUS(status, NT_STATUS_OK); 122 torture_warning(torture, "Target has bug validating lock flags " 123 "parameter.\n"); 124 } else { 125 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 126 } 127 128 torture_comment(torture, "Test >63-bit lock requests.\n"); 89 129 90 130 lck.in.file.handle.data[0] +=1; … … 94 134 95 135 lck.in.lock_count = 0x0001; 96 lck.in. reserved= 0x123ab1;136 lck.in.lock_sequence = 0x123ab1; 97 137 lck.in.file.handle = h; 98 138 el[0].offset = UINT64_MAX; 99 139 el[0].length = UINT64_MAX; 100 140 el[0].reserved = 0x00000000; 101 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 102 status = smb2_lock(tree, &lck); 103 if (TARGET_IS_WIN7(torture)) { 141 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 142 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 143 status = smb2_lock(tree, &lck); 144 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) { 104 145 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE); 105 146 } else { 106 147 CHECK_STATUS(status, NT_STATUS_OK); 148 CHECK_VALUE(lck.out.reserved, 0); 107 149 } 108 CHECK_VALUE(lck.out.reserved, 0); 109 110 lck.in.reserved = 0x123ab2; 111 status = smb2_lock(tree, &lck); 112 if (TARGET_IS_WIN7(torture)) { 150 151 lck.in.lock_sequence = 0x123ab2; 152 status = smb2_lock(tree, &lck); 153 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) { 113 154 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE); 114 } else if (TARGET_IS_WINDOWS(torture)) {115 CHECK_STATUS(status, NT_STATUS_OK);116 155 } else { 117 156 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 118 157 } 119 CHECK_VALUE(lck.out.reserved, 0); 120 121 lck.in.reserved = 0x123ab3; 122 status = smb2_lock(tree, &lck); 123 if (TARGET_IS_WIN7(torture)) { 124 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE); 125 } else if (TARGET_IS_WINDOWS(torture)) { 126 CHECK_STATUS(status, NT_STATUS_OK); 127 } else { 128 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 129 } 130 CHECK_VALUE(lck.out.reserved, 0); 131 132 lck.in.reserved = 0x123ab4; 133 status = smb2_lock(tree, &lck); 134 if (TARGET_IS_WIN7(torture)) { 135 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE); 136 } else if (TARGET_IS_WINDOWS(torture)) { 137 CHECK_STATUS(status, NT_STATUS_OK); 138 } else { 139 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 140 } 141 CHECK_VALUE(lck.out.reserved, 0); 142 143 lck.in.reserved = 0x123ab5; 144 status = smb2_lock(tree, &lck); 145 if (TARGET_IS_WIN7(torture)) { 146 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE); 147 } else if (TARGET_IS_WINDOWS(torture)) { 148 CHECK_STATUS(status, NT_STATUS_OK); 149 } else { 150 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 151 } 152 CHECK_VALUE(lck.out.reserved, 0); 153 154 lck.in.lock_count = 0x0001; 155 lck.in.reserved = 0x12345678; 158 159 torture_comment(torture, "Test basic lock stacking.\n"); 160 161 lck.in.lock_count = 0x0001; 162 lck.in.lock_sequence = 0x12345678; 156 163 lck.in.file.handle = h; 157 164 el[0].offset = UINT32_MAX; 158 165 el[0].length = UINT32_MAX; 159 166 el[0].reserved = 0x87654321; 160 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 167 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 168 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 161 169 status = smb2_lock(tree, &lck); 162 170 CHECK_STATUS(status, NT_STATUS_OK); 163 171 CHECK_VALUE(lck.out.reserved, 0); 164 172 165 status = smb2_lock(tree, &lck); 166 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 167 168 status = smb2_lock(tree, &lck); 169 if (TARGET_IS_WINDOWS(torture)) { 170 CHECK_STATUS(status, NT_STATUS_OK); 171 } else { 172 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 173 } 173 el[0].flags = SMB2_LOCK_FLAG_SHARED; 174 status = smb2_lock(tree, &lck); 175 CHECK_STATUS(status, NT_STATUS_OK); 174 176 CHECK_VALUE(lck.out.reserved, 0); 175 177 176 178 status = smb2_lock(tree, &lck); 177 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 178 179 status = smb2_lock(tree, &lck); 180 if (TARGET_IS_WINDOWS(torture)) { 181 CHECK_STATUS(status, NT_STATUS_OK); 182 } else { 183 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 184 } 179 CHECK_STATUS(status, NT_STATUS_OK); 185 180 CHECK_VALUE(lck.out.reserved, 0); 186 181 187 el[0].flags = 0x00000000; 188 status = smb2_lock(tree, &lck); 189 CHECK_STATUS(status, NT_STATUS_OK); 190 CHECK_VALUE(lck.out.reserved, 0); 191 192 status = smb2_lock(tree, &lck); 193 CHECK_STATUS(status, NT_STATUS_OK); 194 CHECK_VALUE(lck.out.reserved, 0); 195 196 el[0].flags = 0x00000001; 197 status = smb2_lock(tree, &lck); 198 CHECK_STATUS(status, NT_STATUS_OK); 199 CHECK_VALUE(lck.out.reserved, 0); 200 201 status = smb2_lock(tree, &lck); 202 CHECK_STATUS(status, NT_STATUS_OK); 203 CHECK_VALUE(lck.out.reserved, 0); 204 205 lck.in.lock_count = 0x0001; 206 lck.in.reserved = 0x87654321; 182 lck.in.lock_count = 0x0001; 183 lck.in.lock_sequence = 0x87654321; 207 184 lck.in.file.handle = h; 208 185 el[0].offset = 0x00000000FFFFFFFF; … … 214 191 215 192 lck.in.lock_count = 0x0001; 216 lck.in. reserved= 0x1234567;193 lck.in.lock_sequence = 0x1234567; 217 194 lck.in.file.handle = h; 218 195 el[0].offset = 0x00000000FFFFFFFF; … … 226 203 CHECK_STATUS(status, NT_STATUS_OK); 227 204 status = smb2_lock(tree, &lck); 228 CHECK_STATUS(status, NT_STATUS_OK);229 status = smb2_lock(tree, &lck);230 CHECK_STATUS(status, NT_STATUS_OK);231 status = smb2_lock(tree, &lck);232 205 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 233 206 234 lck.in.lock_count = 0x0001; 235 lck.in.reserved = 0; 207 torture_comment(torture, "Test flags field permutations.\n"); 208 209 lck.in.lock_count = 0x0001; 210 lck.in.lock_sequence = 0; 236 211 lck.in.file.handle = h; 237 212 el[0].offset = 1; … … 241 216 242 217 status = smb2_lock(tree, &lck); 243 CHECK_STATUS(status, NT_STATUS_OK); 244 245 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 246 status = smb2_lock(tree, &lck); 247 CHECK_STATUS(status, NT_STATUS_OK); 218 if (TARGET_IS_W2K8(torture)) { 219 CHECK_STATUS(status, NT_STATUS_OK); 220 torture_warning(torture, "Target has bug validating lock flags " 221 "parameter.\n"); 222 } else { 223 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 224 } 225 226 if (TARGET_IS_W2K8(torture)) { 227 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 228 status = smb2_lock(tree, &lck); 229 CHECK_STATUS(status, NT_STATUS_OK); 230 } 248 231 249 232 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; … … 251 234 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 252 235 253 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_EXCLUSIVE; 236 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | 237 SMB2_LOCK_FLAG_EXCLUSIVE; 254 238 status = smb2_lock(tree, &lck); 255 239 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 256 240 257 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_SHARED; 241 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | 242 SMB2_LOCK_FLAG_SHARED; 258 243 status = smb2_lock(tree, &lck); 259 244 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 260 245 261 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 262 status = smb2_lock(tree, &lck); 263 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 246 el[0].flags = SMB2_LOCK_FLAG_UNLOCK | 247 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 248 status = smb2_lock(tree, &lck); 249 if (TARGET_IS_W2K8(torture)) { 250 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 251 torture_warning(torture, "Target has bug validating lock flags " 252 "parameter.\n"); 253 } else { 254 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 255 } 256 257 torture_comment(torture, "Test return error when 2 locks are " 258 "requested\n"); 264 259 265 260 lck.in.lock_count = 2; 266 lck.in. reserved= 0;261 lck.in.lock_sequence = 0; 267 262 lck.in.file.handle = h; 268 263 el[0].offset = 9999; … … 283 278 el[1].flags = 0; 284 279 status = smb2_lock(tree, &lck); 285 CHECK_STATUS(status, NT_STATUS_OK); 280 if (TARGET_IS_W2K8(torture)) { 281 CHECK_STATUS(status, NT_STATUS_OK); 282 torture_warning(torture, "Target has bug validating lock flags " 283 "parameter.\n"); 284 } else { 285 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 286 } 286 287 287 288 lck.in.lock_count = 2; … … 289 290 el[1].flags = 0; 290 291 status = smb2_lock(tree, &lck); 291 CHECK_STATUS(status, NT_STATUS_OK); 292 if (TARGET_IS_W2K8(torture)) { 293 CHECK_STATUS(status, NT_STATUS_OK); 294 torture_warning(torture, "Target has bug validating lock flags " 295 "parameter.\n"); 296 } else { 297 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 298 } 292 299 293 300 lck.in.lock_count = 1; … … 307 314 308 315 lck.in.lock_count = 1; 309 el[0].flags = 0;316 el[0].flags = SMB2_LOCK_FLAG_SHARED; 310 317 status = smb2_lock(tree, &lck); 311 318 CHECK_STATUS(status, NT_STATUS_OK); … … 324 331 status = smb2_lock(tree, &lck); 325 332 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 326 327 333 328 334 done: … … 364 370 365 371 lck.in.lock_count = 0x0001; 366 lck.in. reserved= 0x00000000;372 lck.in.lock_sequence = 0x00000000; 367 373 lck.in.file.handle = h1; 368 374 el[0].offset = 0; … … 375 381 376 382 lck.in.lock_count = 0x0001; 377 lck.in. reserved= 0x00000000;383 lck.in.lock_sequence = 0x00000000; 378 384 lck.in.file.handle = h1; 379 385 el[0].offset = ARRAY_SIZE(buf)/2; … … 390 396 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 391 397 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF; 392 cr.in.share_access = 398 cr.in.share_access = 393 399 NTCREATEX_SHARE_ACCESS_DELETE| 394 400 NTCREATEX_SHARE_ACCESS_READ| … … 435 441 436 442 lck.in.lock_count = 0x0001; 437 lck.in. reserved= 0x00000000;443 lck.in.lock_sequence = 0x00000000; 438 444 lck.in.file.handle = h1; 439 445 el[0].offset = ARRAY_SIZE(buf)/2; … … 465 471 } 466 472 467 static bool test_lock_rw_none(struct torture_context *torture, struct smb2_tree *tree) 473 static bool test_lock_rw_none(struct torture_context *torture, 474 struct smb2_tree *tree) 468 475 { 469 476 struct test_lock_read_write_state s = { … … 476 483 }; 477 484 485 if (!TARGET_IS_W2K8(torture)) { 486 torture_skip(torture, "RW-NONE tests the behavior of a " 487 "NONE-type lock, which is the same as a SHARED " 488 "lock but is granted due to a bug in W2K8. If " 489 "target is not W2K8 we skip this test.\n"); 490 } 491 478 492 return test_lock_read_write(torture, tree, &s); 479 493 } 480 494 481 static bool test_lock_rw_shared(struct torture_context *torture, struct smb2_tree *tree) 495 static bool test_lock_rw_shared(struct torture_context *torture, 496 struct smb2_tree *tree) 482 497 { 483 498 struct test_lock_read_write_state s = { … … 493 508 } 494 509 495 static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_tree *tree) 510 static bool test_lock_rw_exclusive(struct torture_context *torture, 511 struct smb2_tree *tree) 496 512 { 497 513 struct test_lock_read_write_state s = { 498 .fname = "lock_rw_exclusiv .dat",514 .fname = "lock_rw_exclusive.dat", 499 515 .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE, 500 516 .write_h1_status = NT_STATUS_OK, … … 507 523 } 508 524 509 static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree) 525 static bool test_lock_auto_unlock(struct torture_context *torture, 526 struct smb2_tree *tree) 510 527 { 511 528 bool ret = true; … … 514 531 uint8_t buf[200]; 515 532 struct smb2_lock lck; 516 struct smb2_lock_element el[ 2];533 struct smb2_lock_element el[1]; 517 534 518 535 ZERO_STRUCT(buf); … … 525 542 526 543 ZERO_STRUCT(lck); 544 ZERO_STRUCT(el[0]); 527 545 lck.in.locks = el; 528 546 lck.in.lock_count = 0x0001; … … 530 548 el[0].offset = 0; 531 549 el[0].length = 1; 532 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 533 status = smb2_lock(tree, &lck); 534 CHECK_STATUS(status, NT_STATUS_OK); 535 536 status = smb2_lock(tree, &lck); 537 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 538 539 status = smb2_lock(tree, &lck); 540 if (TARGET_IS_WINDOWS(torture)) { 550 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 551 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 552 status = smb2_lock(tree, &lck); 553 CHECK_STATUS(status, NT_STATUS_OK); 554 555 status = smb2_lock(tree, &lck); 556 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 557 558 status = smb2_lock(tree, &lck); 559 if (TARGET_IS_W2K8(torture)) { 541 560 CHECK_STATUS(status, NT_STATUS_OK); 561 torture_warning(torture, "Target has \"pretty please\" bug. " 562 "A contending lock request on the same handle " 563 "unlocks the lock.\n"); 542 564 } else { 543 565 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); … … 551 573 } 552 574 575 /* 576 test different lock ranges and see if different handles conflict 577 */ 578 static bool test_lock(struct torture_context *torture, 579 struct smb2_tree *tree) 580 { 581 NTSTATUS status; 582 bool ret = true; 583 struct smb2_handle h, h2; 584 uint8_t buf[200]; 585 struct smb2_lock lck; 586 struct smb2_lock_element el[2]; 587 588 const char *fname = BASEDIR "\\async.txt"; 589 590 status = torture_smb2_testdir(tree, BASEDIR, &h); 591 CHECK_STATUS(status, NT_STATUS_OK); 592 smb2_util_close(tree, h); 593 594 status = torture_smb2_testfile(tree, fname, &h); 595 CHECK_STATUS(status, NT_STATUS_OK); 596 597 ZERO_STRUCT(buf); 598 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 599 CHECK_STATUS(status, NT_STATUS_OK); 600 601 status = torture_smb2_testfile(tree, fname, &h2); 602 CHECK_STATUS(status, NT_STATUS_OK); 603 604 lck.in.locks = el; 605 606 lck.in.lock_count = 0x0001; 607 lck.in.lock_sequence = 0x00000000; 608 lck.in.file.handle = h; 609 el[0].reserved = 0x00000000; 610 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 611 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 612 613 torture_comment(torture, "Trying 0/0 lock\n"); 614 el[0].offset = 0x0000000000000000; 615 el[0].length = 0x0000000000000000; 616 status = smb2_lock(tree, &lck); 617 CHECK_STATUS(status, NT_STATUS_OK); 618 lck.in.file.handle = h2; 619 status = smb2_lock(tree, &lck); 620 CHECK_STATUS(status, NT_STATUS_OK); 621 lck.in.file.handle = h; 622 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 623 status = smb2_lock(tree, &lck); 624 CHECK_STATUS(status, NT_STATUS_OK); 625 626 torture_comment(torture, "Trying 0/1 lock\n"); 627 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 628 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 629 el[0].offset = 0x0000000000000000; 630 el[0].length = 0x0000000000000001; 631 status = smb2_lock(tree, &lck); 632 CHECK_STATUS(status, NT_STATUS_OK); 633 lck.in.file.handle = h2; 634 status = smb2_lock(tree, &lck); 635 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 636 lck.in.file.handle = h; 637 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 638 status = smb2_lock(tree, &lck); 639 CHECK_STATUS(status, NT_STATUS_OK); 640 status = smb2_lock(tree, &lck); 641 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 642 643 torture_comment(torture, "Trying 0xEEFFFFF lock\n"); 644 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 645 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 646 el[0].offset = 0xEEFFFFFF; 647 el[0].length = 4000; 648 status = smb2_lock(tree, &lck); 649 CHECK_STATUS(status, NT_STATUS_OK); 650 lck.in.file.handle = h2; 651 status = smb2_lock(tree, &lck); 652 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 653 lck.in.file.handle = h; 654 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 655 status = smb2_lock(tree, &lck); 656 CHECK_STATUS(status, NT_STATUS_OK); 657 status = smb2_lock(tree, &lck); 658 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 659 660 torture_comment(torture, "Trying 0xEF00000 lock\n"); 661 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 662 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 663 el[0].offset = 0xEF000000; 664 el[0].length = 4000; 665 status = smb2_lock(tree, &lck); 666 CHECK_STATUS(status, NT_STATUS_OK); 667 lck.in.file.handle = h2; 668 status = smb2_lock(tree, &lck); 669 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 670 lck.in.file.handle = h; 671 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 672 status = smb2_lock(tree, &lck); 673 CHECK_STATUS(status, NT_STATUS_OK); 674 status = smb2_lock(tree, &lck); 675 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 676 677 torture_comment(torture, "Trying (2^63 - 1)/1\n"); 678 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 679 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 680 el[0].offset = 1; 681 el[0].offset <<= 63; 682 el[0].offset--; 683 el[0].length = 1; 684 status = smb2_lock(tree, &lck); 685 CHECK_STATUS(status, NT_STATUS_OK); 686 lck.in.file.handle = h2; 687 status = smb2_lock(tree, &lck); 688 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 689 lck.in.file.handle = h; 690 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 691 status = smb2_lock(tree, &lck); 692 CHECK_STATUS(status, NT_STATUS_OK); 693 status = smb2_lock(tree, &lck); 694 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 695 696 torture_comment(torture, "Trying 2^63/1\n"); 697 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 698 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 699 el[0].offset = 1; 700 el[0].offset <<= 63; 701 el[0].length = 1; 702 status = smb2_lock(tree, &lck); 703 CHECK_STATUS(status, NT_STATUS_OK); 704 lck.in.file.handle = h2; 705 status = smb2_lock(tree, &lck); 706 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 707 lck.in.file.handle = h; 708 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 709 status = smb2_lock(tree, &lck); 710 CHECK_STATUS(status, NT_STATUS_OK); 711 status = smb2_lock(tree, &lck); 712 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 713 714 torture_comment(torture, "Trying max/0 lock\n"); 715 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 716 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 717 el[0].offset = ~0; 718 el[0].length = 0; 719 status = smb2_lock(tree, &lck); 720 CHECK_STATUS(status, NT_STATUS_OK); 721 lck.in.file.handle = h2; 722 status = smb2_lock(tree, &lck); 723 CHECK_STATUS(status, NT_STATUS_OK); 724 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 725 status = smb2_lock(tree, &lck); 726 CHECK_STATUS(status, NT_STATUS_OK); 727 lck.in.file.handle = h; 728 status = smb2_lock(tree, &lck); 729 CHECK_STATUS(status, NT_STATUS_OK); 730 status = smb2_lock(tree, &lck); 731 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 732 733 torture_comment(torture, "Trying max/1 lock\n"); 734 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 735 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 736 el[0].offset = ~0; 737 el[0].length = 1; 738 status = smb2_lock(tree, &lck); 739 CHECK_STATUS(status, NT_STATUS_OK); 740 lck.in.file.handle = h2; 741 status = smb2_lock(tree, &lck); 742 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 743 lck.in.file.handle = h; 744 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 745 status = smb2_lock(tree, &lck); 746 CHECK_STATUS(status, NT_STATUS_OK); 747 status = smb2_lock(tree, &lck); 748 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 749 750 torture_comment(torture, "Trying max/2 lock\n"); 751 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 752 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 753 el[0].offset = ~0; 754 el[0].length = 2; 755 status = smb2_lock(tree, &lck); 756 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) { 757 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE); 758 } else { 759 CHECK_STATUS(status, NT_STATUS_OK); 760 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 761 status = smb2_lock(tree, &lck); 762 CHECK_STATUS(status, NT_STATUS_OK); 763 } 764 765 torture_comment(torture, "Trying wrong handle unlock\n"); 766 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 767 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 768 el[0].offset = 10001; 769 el[0].length = 40002; 770 status = smb2_lock(tree, &lck); 771 CHECK_STATUS(status, NT_STATUS_OK); 772 lck.in.file.handle = h2; 773 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 774 status = smb2_lock(tree, &lck); 775 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 776 lck.in.file.handle = h; 777 status = smb2_lock(tree, &lck); 778 CHECK_STATUS(status, NT_STATUS_OK); 779 780 done: 781 smb2_util_close(tree, h2); 782 smb2_util_close(tree, h); 783 smb2_deltree(tree, BASEDIR); 784 return ret; 785 } 786 787 /* 788 test SMB2 LOCK async operation 789 */ 790 static bool test_async(struct torture_context *torture, 791 struct smb2_tree *tree) 792 { 793 NTSTATUS status; 794 bool ret = true; 795 struct smb2_handle h, h2; 796 uint8_t buf[200]; 797 struct smb2_lock lck; 798 struct smb2_lock_element el[2]; 799 struct smb2_request *req = NULL; 800 801 const char *fname = BASEDIR "\\async.txt"; 802 803 status = torture_smb2_testdir(tree, BASEDIR, &h); 804 CHECK_STATUS(status, NT_STATUS_OK); 805 smb2_util_close(tree, h); 806 807 status = torture_smb2_testfile(tree, fname, &h); 808 CHECK_STATUS(status, NT_STATUS_OK); 809 810 ZERO_STRUCT(buf); 811 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 812 CHECK_STATUS(status, NT_STATUS_OK); 813 814 status = torture_smb2_testfile(tree, fname, &h2); 815 CHECK_STATUS(status, NT_STATUS_OK); 816 817 lck.in.locks = el; 818 819 lck.in.lock_count = 0x0001; 820 lck.in.lock_sequence = 0x00000000; 821 lck.in.file.handle = h; 822 el[0].offset = 100; 823 el[0].length = 50; 824 el[0].reserved = 0x00000000; 825 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 826 827 torture_comment(torture, " Acquire first lock\n"); 828 status = smb2_lock(tree, &lck); 829 CHECK_STATUS(status, NT_STATUS_OK); 830 831 torture_comment(torture, " Second lock should pend on first\n"); 832 lck.in.file.handle = h2; 833 req = smb2_lock_send(tree, &lck); 834 WAIT_FOR_ASYNC_RESPONSE(req); 835 836 torture_comment(torture, " Unlock first lock\n"); 837 lck.in.file.handle = h; 838 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 839 status = smb2_lock(tree, &lck); 840 CHECK_STATUS(status, NT_STATUS_OK); 841 842 torture_comment(torture, " Second lock should now succeed\n"); 843 lck.in.file.handle = h2; 844 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 845 status = smb2_lock_recv(req, &lck); 846 CHECK_STATUS(status, NT_STATUS_OK); 847 848 done: 849 smb2_util_close(tree, h2); 850 smb2_util_close(tree, h); 851 smb2_deltree(tree, BASEDIR); 852 return ret; 853 } 854 855 /* 856 test SMB2 LOCK Cancel operation 857 */ 858 static bool test_cancel(struct torture_context *torture, 859 struct smb2_tree *tree) 860 { 861 NTSTATUS status; 862 bool ret = true; 863 struct smb2_handle h, h2; 864 uint8_t buf[200]; 865 struct smb2_lock lck; 866 struct smb2_lock_element el[2]; 867 struct smb2_request *req = NULL; 868 869 const char *fname = BASEDIR "\\cancel.txt"; 870 871 status = torture_smb2_testdir(tree, BASEDIR, &h); 872 CHECK_STATUS(status, NT_STATUS_OK); 873 smb2_util_close(tree, h); 874 875 status = torture_smb2_testfile(tree, fname, &h); 876 CHECK_STATUS(status, NT_STATUS_OK); 877 878 ZERO_STRUCT(buf); 879 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 880 CHECK_STATUS(status, NT_STATUS_OK); 881 882 status = torture_smb2_testfile(tree, fname, &h2); 883 CHECK_STATUS(status, NT_STATUS_OK); 884 885 lck.in.locks = el; 886 887 lck.in.lock_count = 0x0001; 888 lck.in.lock_sequence = 0x00000000; 889 lck.in.file.handle = h; 890 el[0].offset = 100; 891 el[0].length = 10; 892 el[0].reserved = 0x00000000; 893 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 894 895 torture_comment(torture, "Testing basic cancel\n"); 896 897 torture_comment(torture, " Acquire first lock\n"); 898 status = smb2_lock(tree, &lck); 899 CHECK_STATUS(status, NT_STATUS_OK); 900 901 torture_comment(torture, " Second lock should pend on first\n"); 902 lck.in.file.handle = h2; 903 req = smb2_lock_send(tree, &lck); 904 WAIT_FOR_ASYNC_RESPONSE(req); 905 906 torture_comment(torture, " Cancel the second lock\n"); 907 smb2_cancel(req); 908 lck.in.file.handle = h2; 909 status = smb2_lock_recv(req, &lck); 910 CHECK_STATUS(status, NT_STATUS_CANCELLED); 911 912 torture_comment(torture, " Unlock first lock\n"); 913 lck.in.file.handle = h; 914 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 915 status = smb2_lock(tree, &lck); 916 CHECK_STATUS(status, NT_STATUS_OK); 917 918 919 torture_comment(torture, "Testing cancel by unlock\n"); 920 921 torture_comment(torture, " Acquire first lock\n"); 922 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 923 status = smb2_lock(tree, &lck); 924 CHECK_STATUS(status, NT_STATUS_OK); 925 926 torture_comment(torture, " Second lock should pend on first\n"); 927 lck.in.file.handle = h2; 928 req = smb2_lock_send(tree, &lck); 929 WAIT_FOR_ASYNC_RESPONSE(req); 930 931 torture_comment(torture, " Attempt to unlock pending second lock\n"); 932 lck.in.file.handle = h2; 933 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 934 status = smb2_lock(tree, &lck); 935 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 936 937 torture_comment(torture, " Now cancel the second lock\n"); 938 smb2_cancel(req); 939 lck.in.file.handle = h2; 940 status = smb2_lock_recv(req, &lck); 941 CHECK_STATUS(status, NT_STATUS_CANCELLED); 942 943 torture_comment(torture, " Unlock first lock\n"); 944 lck.in.file.handle = h; 945 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 946 status = smb2_lock(tree, &lck); 947 CHECK_STATUS(status, NT_STATUS_OK); 948 949 950 torture_comment(torture, "Testing cancel by close\n"); 951 952 torture_comment(torture, " Acquire first lock\n"); 953 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 954 status = smb2_lock(tree, &lck); 955 CHECK_STATUS(status, NT_STATUS_OK); 956 957 torture_comment(torture, " Second lock should pend on first\n"); 958 lck.in.file.handle = h2; 959 req = smb2_lock_send(tree, &lck); 960 WAIT_FOR_ASYNC_RESPONSE(req); 961 962 torture_comment(torture, " Close the second lock handle\n"); 963 smb2_util_close(tree, h2); 964 CHECK_STATUS(status, NT_STATUS_OK); 965 966 torture_comment(torture, " Check pending lock reply\n"); 967 status = smb2_lock_recv(req, &lck); 968 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 969 970 torture_comment(torture, " Unlock first lock\n"); 971 lck.in.file.handle = h; 972 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 973 status = smb2_lock(tree, &lck); 974 CHECK_STATUS(status, NT_STATUS_OK); 975 976 done: 977 smb2_util_close(tree, h2); 978 smb2_util_close(tree, h); 979 smb2_deltree(tree, BASEDIR); 980 return ret; 981 } 982 983 /* 984 test SMB2 LOCK Cancel by tree disconnect 985 */ 986 static bool test_cancel_tdis(struct torture_context *torture, 987 struct smb2_tree *tree) 988 { 989 NTSTATUS status; 990 bool ret = true; 991 struct smb2_handle h, h2; 992 uint8_t buf[200]; 993 struct smb2_lock lck; 994 struct smb2_lock_element el[2]; 995 struct smb2_request *req = NULL; 996 997 const char *fname = BASEDIR "\\cancel_tdis.txt"; 998 999 status = torture_smb2_testdir(tree, BASEDIR, &h); 1000 CHECK_STATUS(status, NT_STATUS_OK); 1001 smb2_util_close(tree, h); 1002 1003 status = torture_smb2_testfile(tree, fname, &h); 1004 CHECK_STATUS(status, NT_STATUS_OK); 1005 1006 ZERO_STRUCT(buf); 1007 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 1008 CHECK_STATUS(status, NT_STATUS_OK); 1009 1010 status = torture_smb2_testfile(tree, fname, &h2); 1011 CHECK_STATUS(status, NT_STATUS_OK); 1012 1013 lck.in.locks = el; 1014 1015 lck.in.lock_count = 0x0001; 1016 lck.in.lock_sequence = 0x00000000; 1017 lck.in.file.handle = h; 1018 el[0].offset = 100; 1019 el[0].length = 10; 1020 el[0].reserved = 0x00000000; 1021 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 1022 1023 torture_comment(torture, "Testing cancel by tree disconnect\n"); 1024 1025 status = torture_smb2_testfile(tree, fname, &h); 1026 CHECK_STATUS(status, NT_STATUS_OK); 1027 1028 status = torture_smb2_testfile(tree, fname, &h2); 1029 CHECK_STATUS(status, NT_STATUS_OK); 1030 1031 torture_comment(torture, " Acquire first lock\n"); 1032 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 1033 status = smb2_lock(tree, &lck); 1034 CHECK_STATUS(status, NT_STATUS_OK); 1035 1036 torture_comment(torture, " Second lock should pend on first\n"); 1037 lck.in.file.handle = h2; 1038 req = smb2_lock_send(tree, &lck); 1039 WAIT_FOR_ASYNC_RESPONSE(req); 1040 1041 torture_comment(torture, " Disconnect the tree\n"); 1042 smb2_tdis(tree); 1043 CHECK_STATUS(status, NT_STATUS_OK); 1044 1045 torture_comment(torture, " Check pending lock reply\n"); 1046 status = smb2_lock_recv(req, &lck); 1047 if (torture_setting_bool(torture, "samba4", false)) { 1048 /* saying that this lock succeeded is nonsense - the 1049 * tree is gone!! */ 1050 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 1051 } else { 1052 CHECK_STATUS(status, NT_STATUS_OK); 1053 } 1054 1055 torture_comment(torture, " Attempt to unlock first lock\n"); 1056 lck.in.file.handle = h; 1057 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1058 status = smb2_lock(tree, &lck); 1059 if (torture_setting_bool(torture, "samba4", false)) { 1060 /* checking if the tcon supplied are still valid 1061 * should happen before you validate a file handle, 1062 * so we should return USER_SESSION_DELETED */ 1063 CHECK_STATUS(status, NT_STATUS_NETWORK_NAME_DELETED); 1064 } else { 1065 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED); 1066 } 1067 1068 done: 1069 smb2_util_close(tree, h2); 1070 smb2_util_close(tree, h); 1071 smb2_deltree(tree, BASEDIR); 1072 return ret; 1073 } 1074 1075 /* 1076 test SMB2 LOCK Cancel by user logoff 1077 */ 1078 static bool test_cancel_logoff(struct torture_context *torture, 1079 struct smb2_tree *tree) 1080 { 1081 NTSTATUS status; 1082 bool ret = true; 1083 struct smb2_handle h, h2; 1084 uint8_t buf[200]; 1085 struct smb2_lock lck; 1086 struct smb2_lock_element el[2]; 1087 struct smb2_request *req = NULL; 1088 1089 const char *fname = BASEDIR "\\cancel_tdis.txt"; 1090 1091 status = torture_smb2_testdir(tree, BASEDIR, &h); 1092 CHECK_STATUS(status, NT_STATUS_OK); 1093 smb2_util_close(tree, h); 1094 1095 status = torture_smb2_testfile(tree, fname, &h); 1096 CHECK_STATUS(status, NT_STATUS_OK); 1097 1098 ZERO_STRUCT(buf); 1099 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 1100 CHECK_STATUS(status, NT_STATUS_OK); 1101 1102 status = torture_smb2_testfile(tree, fname, &h2); 1103 CHECK_STATUS(status, NT_STATUS_OK); 1104 1105 lck.in.locks = el; 1106 1107 lck.in.lock_count = 0x0001; 1108 lck.in.lock_sequence = 0x00000000; 1109 lck.in.file.handle = h; 1110 el[0].offset = 100; 1111 el[0].length = 10; 1112 el[0].reserved = 0x00000000; 1113 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 1114 1115 torture_comment(torture, "Testing cancel by ulogoff\n"); 1116 1117 torture_comment(torture, " Acquire first lock\n"); 1118 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 1119 status = smb2_lock(tree, &lck); 1120 CHECK_STATUS(status, NT_STATUS_OK); 1121 1122 torture_comment(torture, " Second lock should pend on first\n"); 1123 lck.in.file.handle = h2; 1124 req = smb2_lock_send(tree, &lck); 1125 WAIT_FOR_ASYNC_RESPONSE(req); 1126 1127 torture_comment(torture, " Logoff user\n"); 1128 smb2_logoff(tree->session); 1129 1130 torture_comment(torture, " Check pending lock reply\n"); 1131 status = smb2_lock_recv(req, &lck); 1132 if (torture_setting_bool(torture, "samba4", false)) { 1133 /* another bogus 'success' code from windows. The lock 1134 * cannot have succeeded, as we are now logged off */ 1135 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 1136 } else { 1137 CHECK_STATUS(status, NT_STATUS_OK); 1138 } 1139 1140 torture_comment(torture, " Attempt to unlock first lock\n"); 1141 lck.in.file.handle = h; 1142 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1143 status = smb2_lock(tree, &lck); 1144 if (torture_setting_bool(torture, "samba4", false)) { 1145 /* checking if the credential supplied are still valid 1146 * should happen before you validate a file handle, 1147 * so we should return USER_SESSION_DELETED */ 1148 CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED); 1149 } else { 1150 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED); 1151 } 1152 1153 done: 1154 smb2_util_close(tree, h2); 1155 smb2_util_close(tree, h); 1156 smb2_deltree(tree, BASEDIR); 1157 return ret; 1158 } 1159 1160 /* 1161 * Test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT 1162 * 1163 * The SMBv1 protocol returns a different error code on lock acquisition 1164 * failure depending on a number of parameters, including what error code 1165 * was returned to the previous failure. 1166 * 1167 * SMBv2 has cleaned up these semantics and should always return 1168 * NT_STATUS_LOCK_NOT_GRANTED to failed lock requests, and 1169 * NT_STATUS_FILE_LOCK_CONFLICT to failed read/write requests due to a lock 1170 * being held on that range. 1171 */ 1172 static bool test_errorcode(struct torture_context *torture, 1173 struct smb2_tree *tree) 1174 { 1175 NTSTATUS status; 1176 bool ret = true; 1177 struct smb2_handle h, h2; 1178 uint8_t buf[200]; 1179 struct smb2_lock lck; 1180 struct smb2_lock_element el[2]; 1181 1182 const char *fname = BASEDIR "\\errorcode.txt"; 1183 1184 status = torture_smb2_testdir(tree, BASEDIR, &h); 1185 CHECK_STATUS(status, NT_STATUS_OK); 1186 smb2_util_close(tree, h); 1187 1188 status = torture_smb2_testfile(tree, fname, &h); 1189 CHECK_STATUS(status, NT_STATUS_OK); 1190 1191 ZERO_STRUCT(buf); 1192 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 1193 CHECK_STATUS(status, NT_STATUS_OK); 1194 1195 status = torture_smb2_testfile(tree, fname, &h2); 1196 CHECK_STATUS(status, NT_STATUS_OK); 1197 1198 lck.in.locks = el; 1199 1200 lck.in.lock_count = 0x0001; 1201 lck.in.lock_sequence = 0x00000000; 1202 lck.in.file.handle = h; 1203 el[0].offset = 100; 1204 el[0].length = 10; 1205 el[0].reserved = 0x00000000; 1206 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1207 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1208 1209 torture_comment(torture, "Testing LOCK_NOT_GRANTED vs. " 1210 "FILE_LOCK_CONFLICT\n"); 1211 1212 if (TARGET_IS_W2K8(torture)) { 1213 torture_result(torture, TORTURE_SKIP, 1214 "Target has \"pretty please\" bug. A contending lock " 1215 "request on the same handle unlocks the lock."); 1216 goto done; 1217 } 1218 1219 status = smb2_lock(tree, &lck); 1220 CHECK_STATUS(status, NT_STATUS_OK); 1221 1222 /* Demonstrate that the first conflicting lock on each handle gives 1223 * LOCK_NOT_GRANTED. */ 1224 lck.in.file.handle = h; 1225 status = smb2_lock(tree, &lck); 1226 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1227 1228 lck.in.file.handle = h2; 1229 status = smb2_lock(tree, &lck); 1230 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1231 1232 /* Demonstrate that each following conflict also gives 1233 * LOCK_NOT_GRANTED */ 1234 lck.in.file.handle = h; 1235 status = smb2_lock(tree, &lck); 1236 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1237 1238 lck.in.file.handle = h2; 1239 status = smb2_lock(tree, &lck); 1240 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1241 1242 lck.in.file.handle = h; 1243 status = smb2_lock(tree, &lck); 1244 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1245 1246 lck.in.file.handle = h2; 1247 status = smb2_lock(tree, &lck); 1248 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1249 1250 /* Demonstrate that the smbpid doesn't matter */ 1251 tree->session->pid++; 1252 lck.in.file.handle = h; 1253 status = smb2_lock(tree, &lck); 1254 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1255 1256 lck.in.file.handle = h2; 1257 status = smb2_lock(tree, &lck); 1258 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1259 tree->session->pid--; 1260 1261 /* Demonstrate that a 0-byte lock inside the locked range still 1262 * gives the same error. */ 1263 1264 el[0].offset = 102; 1265 el[0].length = 0; 1266 lck.in.file.handle = h; 1267 status = smb2_lock(tree, &lck); 1268 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1269 1270 lck.in.file.handle = h2; 1271 status = smb2_lock(tree, &lck); 1272 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1273 1274 /* Demonstrate that a lock inside the locked range still gives the 1275 * same error. */ 1276 1277 el[0].offset = 102; 1278 el[0].length = 5; 1279 lck.in.file.handle = h; 1280 status = smb2_lock(tree, &lck); 1281 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1282 1283 lck.in.file.handle = h2; 1284 status = smb2_lock(tree, &lck); 1285 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1286 1287 done: 1288 smb2_util_close(tree, h2); 1289 smb2_util_close(tree, h); 1290 smb2_deltree(tree, BASEDIR); 1291 return ret; 1292 } 1293 1294 /** 1295 * Tests zero byte locks. 1296 */ 1297 1298 struct double_lock_test { 1299 struct smb2_lock_element lock1; 1300 struct smb2_lock_element lock2; 1301 NTSTATUS status; 1302 }; 1303 1304 static struct double_lock_test zero_byte_tests[] = { 1305 /* {offset, count, reserved, flags}, 1306 * {offset, count, reserved, flags}, 1307 * status */ 1308 1309 /** First, takes a zero byte lock at offset 10. Then: 1310 * - Taking 0 byte lock at 10 should succeed. 1311 * - Taking 1 byte locks at 9,10,11 should succeed. 1312 * - Taking 2 byte lock at 9 should fail. 1313 * - Taking 2 byte lock at 10 should succeed. 1314 * - Taking 3 byte lock at 9 should fail. 1315 */ 1316 {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK}, 1317 {{10, 0, 0, 0}, {9, 1, 0, 0}, NT_STATUS_OK}, 1318 {{10, 0, 0, 0}, {10, 1, 0, 0}, NT_STATUS_OK}, 1319 {{10, 0, 0, 0}, {11, 1, 0, 0}, NT_STATUS_OK}, 1320 {{10, 0, 0, 0}, {9, 2, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED}, 1321 {{10, 0, 0, 0}, {10, 2, 0, 0}, NT_STATUS_OK}, 1322 {{10, 0, 0, 0}, {9, 3, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED}, 1323 1324 /** Same, but opposite order. */ 1325 {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK}, 1326 {{9, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK}, 1327 {{10, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK}, 1328 {{11, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK}, 1329 {{9, 2, 0, 0}, {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED}, 1330 {{10, 2, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK}, 1331 {{9, 3, 0, 0}, {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED}, 1332 1333 /** Zero zero case. */ 1334 {{0, 0, 0, 0}, {0, 0, 0, 0}, NT_STATUS_OK}, 1335 }; 1336 1337 static bool test_zerobytelength(struct torture_context *torture, 1338 struct smb2_tree *tree) 1339 { 1340 NTSTATUS status; 1341 bool ret = true; 1342 struct smb2_handle h, h2; 1343 uint8_t buf[200]; 1344 struct smb2_lock lck; 1345 int i; 1346 1347 const char *fname = BASEDIR "\\zero.txt"; 1348 1349 torture_comment(torture, "Testing zero length byte range locks:\n"); 1350 1351 status = torture_smb2_testdir(tree, BASEDIR, &h); 1352 CHECK_STATUS(status, NT_STATUS_OK); 1353 smb2_util_close(tree, h); 1354 1355 status = torture_smb2_testfile(tree, fname, &h); 1356 CHECK_STATUS(status, NT_STATUS_OK); 1357 1358 ZERO_STRUCT(buf); 1359 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 1360 CHECK_STATUS(status, NT_STATUS_OK); 1361 1362 status = torture_smb2_testfile(tree, fname, &h2); 1363 CHECK_STATUS(status, NT_STATUS_OK); 1364 1365 /* Setup initial parameters */ 1366 lck.in.lock_count = 0x0001; 1367 lck.in.lock_sequence = 0x00000000; 1368 lck.in.file.handle = h; 1369 1370 /* Try every combination of locks in zero_byte_tests, using the same 1371 * handle for both locks. The first lock is assumed to succeed. The 1372 * second lock may contend, depending on the expected status. */ 1373 for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) { 1374 torture_comment(torture, 1375 " ... {%llu, %llu} + {%llu, %llu} = %s\n", 1376 (unsigned long long) zero_byte_tests[i].lock1.offset, 1377 (unsigned long long) zero_byte_tests[i].lock1.length, 1378 (unsigned long long) zero_byte_tests[i].lock2.offset, 1379 (unsigned long long) zero_byte_tests[i].lock2.length, 1380 nt_errstr(zero_byte_tests[i].status)); 1381 1382 /* Lock both locks. */ 1383 lck.in.locks = &zero_byte_tests[i].lock1; 1384 lck.in.locks[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1385 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1386 status = smb2_lock(tree, &lck); 1387 CHECK_STATUS(status, NT_STATUS_OK); 1388 1389 lck.in.locks = &zero_byte_tests[i].lock2; 1390 lck.in.locks[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1391 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1392 status = smb2_lock(tree, &lck); 1393 CHECK_STATUS_CONT(status, zero_byte_tests[i].status); 1394 1395 /* Unlock both locks in reverse order. */ 1396 lck.in.locks[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1397 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) { 1398 status = smb2_lock(tree, &lck); 1399 CHECK_STATUS(status, NT_STATUS_OK); 1400 } 1401 1402 lck.in.locks = &zero_byte_tests[i].lock1; 1403 lck.in.locks[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1404 status = smb2_lock(tree, &lck); 1405 CHECK_STATUS(status, NT_STATUS_OK); 1406 } 1407 1408 /* Try every combination of locks in zero_byte_tests, using two 1409 * different handles. */ 1410 for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) { 1411 torture_comment(torture, 1412 " ... {%llu, %llu} + {%llu, %llu} = %s\n", 1413 (unsigned long long) zero_byte_tests[i].lock1.offset, 1414 (unsigned long long) zero_byte_tests[i].lock1.length, 1415 (unsigned long long) zero_byte_tests[i].lock2.offset, 1416 (unsigned long long) zero_byte_tests[i].lock2.length, 1417 nt_errstr(zero_byte_tests[i].status)); 1418 1419 /* Lock both locks. */ 1420 lck.in.file.handle = h; 1421 lck.in.locks = &zero_byte_tests[i].lock1; 1422 lck.in.locks[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1423 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1424 status = smb2_lock(tree, &lck); 1425 CHECK_STATUS(status, NT_STATUS_OK); 1426 1427 lck.in.file.handle = h2; 1428 lck.in.locks = &zero_byte_tests[i].lock2; 1429 lck.in.locks[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1430 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1431 status = smb2_lock(tree, &lck); 1432 CHECK_STATUS_CONT(status, zero_byte_tests[i].status); 1433 1434 /* Unlock both locks in reverse order. */ 1435 lck.in.file.handle = h2; 1436 lck.in.locks[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1437 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) { 1438 status = smb2_lock(tree, &lck); 1439 CHECK_STATUS(status, NT_STATUS_OK); 1440 } 1441 1442 lck.in.file.handle = h; 1443 lck.in.locks = &zero_byte_tests[i].lock1; 1444 lck.in.locks[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1445 status = smb2_lock(tree, &lck); 1446 CHECK_STATUS(status, NT_STATUS_OK); 1447 } 1448 1449 done: 1450 smb2_util_close(tree, h2); 1451 smb2_util_close(tree, h); 1452 smb2_deltree(tree, BASEDIR); 1453 return ret; 1454 } 1455 1456 static bool test_zerobyteread(struct torture_context *torture, 1457 struct smb2_tree *tree) 1458 { 1459 NTSTATUS status; 1460 bool ret = true; 1461 struct smb2_handle h, h2; 1462 uint8_t buf[200]; 1463 struct smb2_lock lck; 1464 struct smb2_lock_element el[1]; 1465 struct smb2_read rd; 1466 1467 const char *fname = BASEDIR "\\zerobyteread.txt"; 1468 1469 status = torture_smb2_testdir(tree, BASEDIR, &h); 1470 CHECK_STATUS(status, NT_STATUS_OK); 1471 smb2_util_close(tree, h); 1472 1473 status = torture_smb2_testfile(tree, fname, &h); 1474 CHECK_STATUS(status, NT_STATUS_OK); 1475 1476 ZERO_STRUCT(buf); 1477 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 1478 CHECK_STATUS(status, NT_STATUS_OK); 1479 1480 status = torture_smb2_testfile(tree, fname, &h2); 1481 CHECK_STATUS(status, NT_STATUS_OK); 1482 1483 /* Setup initial parameters */ 1484 lck.in.locks = el; 1485 lck.in.lock_count = 0x0001; 1486 lck.in.lock_sequence = 0x00000000; 1487 lck.in.file.handle = h; 1488 1489 ZERO_STRUCT(rd); 1490 rd.in.file.handle = h2; 1491 1492 torture_comment(torture, "Testing zero byte read on lock range:\n"); 1493 1494 /* Take an exclusive lock */ 1495 torture_comment(torture, " taking exclusive lock.\n"); 1496 el[0].offset = 0; 1497 el[0].length = 10; 1498 el[0].reserved = 0x00000000; 1499 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1500 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1501 status = smb2_lock(tree, &lck); 1502 CHECK_STATUS(status, NT_STATUS_OK); 1503 CHECK_VALUE(lck.out.reserved, 0); 1504 1505 /* Try a zero byte read */ 1506 torture_comment(torture, " reading 0 bytes.\n"); 1507 rd.in.offset = 5; 1508 rd.in.length = 0; 1509 status = smb2_read(tree, tree, &rd); 1510 torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done, 1511 "zero byte read did not return 0 bytes"); 1512 CHECK_STATUS(status, NT_STATUS_OK); 1513 1514 /* Unlock lock */ 1515 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1516 status = smb2_lock(tree, &lck); 1517 CHECK_STATUS(status, NT_STATUS_OK); 1518 CHECK_VALUE(lck.out.reserved, 0); 1519 1520 torture_comment(torture, "Testing zero byte read on zero byte lock " 1521 "range:\n"); 1522 1523 /* Take an exclusive lock */ 1524 torture_comment(torture, " taking exclusive 0-byte lock.\n"); 1525 el[0].offset = 5; 1526 el[0].length = 0; 1527 el[0].reserved = 0x00000000; 1528 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1529 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1530 status = smb2_lock(tree, &lck); 1531 CHECK_STATUS(status, NT_STATUS_OK); 1532 CHECK_VALUE(lck.out.reserved, 0); 1533 1534 /* Try a zero byte read before the lock */ 1535 torture_comment(torture, " reading 0 bytes before the lock.\n"); 1536 rd.in.offset = 4; 1537 rd.in.length = 0; 1538 status = smb2_read(tree, tree, &rd); 1539 torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done, 1540 "zero byte read did not return 0 bytes"); 1541 CHECK_STATUS(status, NT_STATUS_OK); 1542 1543 /* Try a zero byte read on the lock */ 1544 torture_comment(torture, " reading 0 bytes on the lock.\n"); 1545 rd.in.offset = 5; 1546 rd.in.length = 0; 1547 status = smb2_read(tree, tree, &rd); 1548 torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done, 1549 "zero byte read did not return 0 bytes"); 1550 CHECK_STATUS(status, NT_STATUS_OK); 1551 1552 /* Try a zero byte read after the lock */ 1553 torture_comment(torture, " reading 0 bytes after the lock.\n"); 1554 rd.in.offset = 6; 1555 rd.in.length = 0; 1556 status = smb2_read(tree, tree, &rd); 1557 torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done, 1558 "zero byte read did not return 0 bytes"); 1559 CHECK_STATUS(status, NT_STATUS_OK); 1560 1561 /* Unlock lock */ 1562 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1563 status = smb2_lock(tree, &lck); 1564 CHECK_STATUS(status, NT_STATUS_OK); 1565 CHECK_VALUE(lck.out.reserved, 0); 1566 1567 done: 1568 smb2_util_close(tree, h2); 1569 smb2_util_close(tree, h); 1570 smb2_deltree(tree, BASEDIR); 1571 return ret; 1572 } 1573 1574 static bool test_unlock(struct torture_context *torture, 1575 struct smb2_tree *tree) 1576 { 1577 NTSTATUS status; 1578 bool ret = true; 1579 struct smb2_handle h, h2; 1580 uint8_t buf[200]; 1581 struct smb2_lock lck; 1582 struct smb2_lock_element el1[1]; 1583 struct smb2_lock_element el2[1]; 1584 1585 const char *fname = BASEDIR "\\unlock.txt"; 1586 1587 status = torture_smb2_testdir(tree, BASEDIR, &h); 1588 CHECK_STATUS(status, NT_STATUS_OK); 1589 smb2_util_close(tree, h); 1590 1591 status = torture_smb2_testfile(tree, fname, &h); 1592 CHECK_STATUS(status, NT_STATUS_OK); 1593 1594 ZERO_STRUCT(buf); 1595 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 1596 CHECK_STATUS(status, NT_STATUS_OK); 1597 1598 status = torture_smb2_testfile(tree, fname, &h2); 1599 CHECK_STATUS(status, NT_STATUS_OK); 1600 1601 /* Setup initial parameters */ 1602 lck.in.locks = el1; 1603 lck.in.lock_count = 0x0001; 1604 lck.in.lock_sequence = 0x00000000; 1605 el1[0].offset = 0; 1606 el1[0].length = 10; 1607 el1[0].reserved = 0x00000000; 1608 1609 /* Take exclusive lock, then unlock it with a shared-unlock call. */ 1610 1611 torture_comment(torture, "Testing unlock exclusive with shared\n"); 1612 1613 torture_comment(torture, " taking exclusive lock.\n"); 1614 lck.in.file.handle = h; 1615 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; 1616 status = smb2_lock(tree, &lck); 1617 CHECK_STATUS(status, NT_STATUS_OK); 1618 1619 torture_comment(torture, " try to unlock the exclusive with a shared " 1620 "unlock call.\n"); 1621 el1[0].flags = SMB2_LOCK_FLAG_SHARED | 1622 SMB2_LOCK_FLAG_UNLOCK; 1623 status = smb2_lock(tree, &lck); 1624 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 1625 1626 torture_comment(torture, " try shared lock on h2, to test the " 1627 "unlock.\n"); 1628 lck.in.file.handle = h2; 1629 el1[0].flags = SMB2_LOCK_FLAG_SHARED | 1630 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1631 status = smb2_lock(tree, &lck); 1632 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1633 1634 torture_comment(torture, " unlock the exclusive lock\n"); 1635 lck.in.file.handle = h; 1636 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1637 status = smb2_lock(tree, &lck); 1638 CHECK_STATUS(status, NT_STATUS_OK); 1639 1640 /* Unlock a shared lock with an exclusive-unlock call. */ 1641 1642 torture_comment(torture, "Testing unlock shared with exclusive\n"); 1643 1644 torture_comment(torture, " taking shared lock.\n"); 1645 lck.in.file.handle = h; 1646 el1[0].flags = SMB2_LOCK_FLAG_SHARED; 1647 status = smb2_lock(tree, &lck); 1648 CHECK_STATUS(status, NT_STATUS_OK); 1649 1650 torture_comment(torture, " try to unlock the shared with an exclusive " 1651 "unlock call.\n"); 1652 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1653 SMB2_LOCK_FLAG_UNLOCK; 1654 status = smb2_lock(tree, &lck); 1655 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 1656 1657 torture_comment(torture, " try exclusive lock on h2, to test the " 1658 "unlock.\n"); 1659 lck.in.file.handle = h2; 1660 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1661 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1662 status = smb2_lock(tree, &lck); 1663 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1664 1665 torture_comment(torture, " unlock the exclusive lock\n"); 1666 lck.in.file.handle = h; 1667 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1668 status = smb2_lock(tree, &lck); 1669 CHECK_STATUS(status, NT_STATUS_OK); 1670 1671 /* Test unlocking of stacked 0-byte locks. SMB2 0-byte lock behavior 1672 * should be the same as >0-byte behavior. Exclusive locks should be 1673 * unlocked before shared. */ 1674 1675 torture_comment(torture, "Test unlocking stacked 0-byte locks\n"); 1676 1677 lck.in.locks = el1; 1678 lck.in.file.handle = h; 1679 el1[0].offset = 10; 1680 el1[0].length = 0; 1681 el1[0].reserved = 0x00000000; 1682 el2[0].offset = 5; 1683 el2[0].length = 10; 1684 el2[0].reserved = 0x00000000; 1685 1686 /* lock 0-byte exclusive */ 1687 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1688 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1689 status = smb2_lock(tree, &lck); 1690 CHECK_STATUS(status, NT_STATUS_OK); 1691 1692 /* lock 0-byte shared */ 1693 el1[0].flags = SMB2_LOCK_FLAG_SHARED | 1694 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1695 status = smb2_lock(tree, &lck); 1696 CHECK_STATUS(status, NT_STATUS_OK); 1697 1698 /* test contention */ 1699 lck.in.locks = el2; 1700 lck.in.file.handle = h2; 1701 el2[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1702 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1703 status = smb2_lock(tree, &lck); 1704 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1705 1706 lck.in.locks = el2; 1707 lck.in.file.handle = h2; 1708 el2[0].flags = SMB2_LOCK_FLAG_SHARED | 1709 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1710 status = smb2_lock(tree, &lck); 1711 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1712 1713 /* unlock */ 1714 lck.in.locks = el1; 1715 lck.in.file.handle = h; 1716 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1717 status = smb2_lock(tree, &lck); 1718 CHECK_STATUS(status, NT_STATUS_OK); 1719 1720 /* test - can we take a shared lock? */ 1721 lck.in.locks = el2; 1722 lck.in.file.handle = h2; 1723 el2[0].flags = SMB2_LOCK_FLAG_SHARED | 1724 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1725 status = smb2_lock(tree, &lck); 1726 CHECK_STATUS(status, NT_STATUS_OK); 1727 1728 el2[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1729 status = smb2_lock(tree, &lck); 1730 CHECK_STATUS(status, NT_STATUS_OK); 1731 1732 /* cleanup */ 1733 lck.in.locks = el1; 1734 lck.in.file.handle = h; 1735 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1736 status = smb2_lock(tree, &lck); 1737 CHECK_STATUS(status, NT_STATUS_OK); 1738 1739 /* Test unlocking of stacked exclusive, shared locks. Exclusive 1740 * should be unlocked before any shared. */ 1741 1742 torture_comment(torture, "Test unlocking stacked exclusive/shared " 1743 "locks\n"); 1744 1745 lck.in.locks = el1; 1746 lck.in.file.handle = h; 1747 el1[0].offset = 10; 1748 el1[0].length = 10; 1749 el1[0].reserved = 0x00000000; 1750 el2[0].offset = 5; 1751 el2[0].length = 10; 1752 el2[0].reserved = 0x00000000; 1753 1754 /* lock exclusive */ 1755 el1[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1756 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1757 status = smb2_lock(tree, &lck); 1758 CHECK_STATUS(status, NT_STATUS_OK); 1759 1760 /* lock shared */ 1761 el1[0].flags = SMB2_LOCK_FLAG_SHARED | 1762 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1763 status = smb2_lock(tree, &lck); 1764 CHECK_STATUS(status, NT_STATUS_OK); 1765 1766 /* test contention */ 1767 lck.in.locks = el2; 1768 lck.in.file.handle = h2; 1769 el2[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1770 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1771 status = smb2_lock(tree, &lck); 1772 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1773 1774 lck.in.locks = el2; 1775 lck.in.file.handle = h2; 1776 el2[0].flags = SMB2_LOCK_FLAG_SHARED | 1777 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1778 status = smb2_lock(tree, &lck); 1779 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1780 1781 /* unlock */ 1782 lck.in.locks = el1; 1783 lck.in.file.handle = h; 1784 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1785 status = smb2_lock(tree, &lck); 1786 CHECK_STATUS(status, NT_STATUS_OK); 1787 1788 /* test - can we take a shared lock? */ 1789 lck.in.locks = el2; 1790 lck.in.file.handle = h2; 1791 el2[0].flags = SMB2_LOCK_FLAG_SHARED | 1792 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1793 status = smb2_lock(tree, &lck); 1794 CHECK_STATUS(status, NT_STATUS_OK); 1795 1796 el2[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1797 status = smb2_lock(tree, &lck); 1798 CHECK_STATUS(status, NT_STATUS_OK); 1799 1800 /* cleanup */ 1801 lck.in.locks = el1; 1802 lck.in.file.handle = h; 1803 el1[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1804 status = smb2_lock(tree, &lck); 1805 CHECK_STATUS(status, NT_STATUS_OK); 1806 1807 done: 1808 smb2_util_close(tree, h2); 1809 smb2_util_close(tree, h); 1810 smb2_deltree(tree, BASEDIR); 1811 return ret; 1812 } 1813 1814 static bool test_multiple_unlock(struct torture_context *torture, 1815 struct smb2_tree *tree) 1816 { 1817 NTSTATUS status; 1818 bool ret = true; 1819 struct smb2_handle h; 1820 uint8_t buf[200]; 1821 struct smb2_lock lck; 1822 struct smb2_lock_element el[2]; 1823 1824 const char *fname = BASEDIR "\\unlock_multiple.txt"; 1825 1826 status = torture_smb2_testdir(tree, BASEDIR, &h); 1827 CHECK_STATUS(status, NT_STATUS_OK); 1828 smb2_util_close(tree, h); 1829 1830 status = torture_smb2_testfile(tree, fname, &h); 1831 CHECK_STATUS(status, NT_STATUS_OK); 1832 1833 ZERO_STRUCT(buf); 1834 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 1835 CHECK_STATUS(status, NT_STATUS_OK); 1836 1837 torture_comment(torture, "Testing multiple unlocks:\n"); 1838 1839 /* Setup initial parameters */ 1840 lck.in.lock_count = 0x0002; 1841 lck.in.lock_sequence = 0x00000000; 1842 lck.in.file.handle = h; 1843 el[0].offset = 0; 1844 el[0].length = 10; 1845 el[0].reserved = 0x00000000; 1846 el[1].offset = 10; 1847 el[1].length = 10; 1848 el[1].reserved = 0x00000000; 1849 1850 /* Test1: Acquire second lock, but not first. */ 1851 torture_comment(torture, " unlock 2 locks, first one not locked. " 1852 "Expect no locks unlocked. \n"); 1853 1854 lck.in.lock_count = 0x0001; 1855 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1856 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1857 lck.in.locks = &el[1]; 1858 status = smb2_lock(tree, &lck); 1859 CHECK_STATUS(status, NT_STATUS_OK); 1860 1861 /* Try to unlock both locks */ 1862 lck.in.lock_count = 0x0002; 1863 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1864 el[1].flags = SMB2_LOCK_FLAG_UNLOCK; 1865 lck.in.locks = el; 1866 status = smb2_lock(tree, &lck); 1867 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 1868 1869 /* Second lock should not be unlocked. */ 1870 lck.in.lock_count = 0x0001; 1871 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1872 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1873 lck.in.locks = &el[1]; 1874 status = smb2_lock(tree, &lck); 1875 if (TARGET_IS_W2K8(torture)) { 1876 CHECK_STATUS(status, NT_STATUS_OK); 1877 torture_warning(torture, "Target has \"pretty please\" bug. " 1878 "A contending lock request on the same handle " 1879 "unlocks the lock.\n"); 1880 } else { 1881 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1882 } 1883 1884 /* cleanup */ 1885 lck.in.lock_count = 0x0001; 1886 el[1].flags = SMB2_LOCK_FLAG_UNLOCK; 1887 lck.in.locks = &el[1]; 1888 status = smb2_lock(tree, &lck); 1889 CHECK_STATUS(status, NT_STATUS_OK); 1890 1891 /* Test2: Acquire first lock, but not second. */ 1892 torture_comment(torture, " unlock 2 locks, second one not locked. " 1893 "Expect first lock unlocked.\n"); 1894 1895 lck.in.lock_count = 0x0001; 1896 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1897 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1898 lck.in.locks = &el[0]; 1899 status = smb2_lock(tree, &lck); 1900 CHECK_STATUS(status, NT_STATUS_OK); 1901 1902 /* Try to unlock both locks */ 1903 lck.in.lock_count = 0x0002; 1904 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1905 el[1].flags = SMB2_LOCK_FLAG_UNLOCK; 1906 lck.in.locks = el; 1907 status = smb2_lock(tree, &lck); 1908 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 1909 1910 /* First lock should be unlocked. */ 1911 lck.in.lock_count = 0x0001; 1912 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1913 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1914 lck.in.locks = &el[0]; 1915 status = smb2_lock(tree, &lck); 1916 CHECK_STATUS(status, NT_STATUS_OK); 1917 1918 /* cleanup */ 1919 lck.in.lock_count = 0x0001; 1920 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1921 lck.in.locks = &el[0]; 1922 status = smb2_lock(tree, &lck); 1923 CHECK_STATUS(status, NT_STATUS_OK); 1924 1925 /* Test3: Request 2 locks, second will contend. What happens to the 1926 * first? */ 1927 torture_comment(torture, " request 2 locks, second one will contend. " 1928 "Expect both to fail.\n"); 1929 1930 /* Lock the second range */ 1931 lck.in.lock_count = 0x0001; 1932 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1933 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1934 lck.in.locks = &el[1]; 1935 status = smb2_lock(tree, &lck); 1936 CHECK_STATUS(status, NT_STATUS_OK); 1937 1938 /* Request both locks */ 1939 lck.in.lock_count = 0x0002; 1940 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1941 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1942 lck.in.locks = el; 1943 status = smb2_lock(tree, &lck); 1944 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 1945 1946 /* First lock should be unlocked. */ 1947 lck.in.lock_count = 0x0001; 1948 lck.in.locks = &el[0]; 1949 status = smb2_lock(tree, &lck); 1950 CHECK_STATUS(status, NT_STATUS_OK); 1951 1952 /* cleanup */ 1953 if (TARGET_IS_W2K8(torture)) { 1954 lck.in.lock_count = 0x0001; 1955 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1956 lck.in.locks = &el[0]; 1957 status = smb2_lock(tree, &lck); 1958 CHECK_STATUS(status, NT_STATUS_OK); 1959 torture_warning(torture, "Target has \"pretty please\" bug. " 1960 "A contending lock request on the same handle " 1961 "unlocks the lock.\n"); 1962 } else { 1963 lck.in.lock_count = 0x0002; 1964 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1965 el[1].flags = SMB2_LOCK_FLAG_UNLOCK; 1966 lck.in.locks = el; 1967 status = smb2_lock(tree, &lck); 1968 CHECK_STATUS(status, NT_STATUS_OK); 1969 } 1970 1971 /* Test4: Request unlock and lock. The lock contends, is the unlock 1972 * then relocked? SMB2 doesn't like the lock and unlock requests in the 1973 * same packet. The unlock will succeed, but the lock will return 1974 * INVALID_PARAMETER. This behavior is described in MS-SMB2 1975 * 3.3.5.14.1 */ 1976 torture_comment(torture, " request unlock and lock, second one will " 1977 "error. Expect the unlock to succeed.\n"); 1978 1979 /* Lock both ranges */ 1980 lck.in.lock_count = 0x0002; 1981 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1982 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1983 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1984 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1985 lck.in.locks = el; 1986 status = smb2_lock(tree, &lck); 1987 CHECK_STATUS(status, NT_STATUS_OK); 1988 1989 /* Attempt to unlock the first range and lock the second. The lock 1990 * request will error. */ 1991 lck.in.lock_count = 0x0002; 1992 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 1993 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 1994 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 1995 lck.in.locks = el; 1996 status = smb2_lock(tree, &lck); 1997 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 1998 1999 /* The first lock should've been unlocked */ 2000 lck.in.lock_count = 0x0001; 2001 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2002 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2003 lck.in.locks = &el[0]; 2004 status = smb2_lock(tree, &lck); 2005 CHECK_STATUS(status, NT_STATUS_OK); 2006 2007 /* cleanup */ 2008 lck.in.lock_count = 0x0002; 2009 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2010 el[1].flags = SMB2_LOCK_FLAG_UNLOCK; 2011 lck.in.locks = el; 2012 status = smb2_lock(tree, &lck); 2013 CHECK_STATUS(status, NT_STATUS_OK); 2014 2015 /* Test10: SMB2 only test. Request unlock and lock in same packet. 2016 * Neither contend. SMB2 doesn't like lock and unlock requests in the 2017 * same packet. The unlock will succeed, but the lock will return 2018 * INVALID_PARAMETER. */ 2019 torture_comment(torture, " request unlock and lock. Unlock will " 2020 "succeed, but lock will fail.\n"); 2021 2022 /* Lock first range */ 2023 lck.in.lock_count = 0x0001; 2024 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2025 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2026 lck.in.locks = &el[0]; 2027 status = smb2_lock(tree, &lck); 2028 CHECK_STATUS(status, NT_STATUS_OK); 2029 2030 /* Attempt to unlock the first range and lock the second */ 2031 lck.in.lock_count = 0x0002; 2032 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2033 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2034 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2035 lck.in.locks = el; 2036 status = smb2_lock(tree, &lck); 2037 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 2038 2039 /* Neither lock should still be locked */ 2040 lck.in.lock_count = 0x0002; 2041 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2042 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2043 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2044 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2045 lck.in.locks = el; 2046 status = smb2_lock(tree, &lck); 2047 CHECK_STATUS(status, NT_STATUS_OK); 2048 2049 /* cleanup */ 2050 lck.in.lock_count = 0x0002; 2051 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2052 el[1].flags = SMB2_LOCK_FLAG_UNLOCK; 2053 lck.in.locks = el; 2054 status = smb2_lock(tree, &lck); 2055 CHECK_STATUS(status, NT_STATUS_OK); 2056 2057 /* Test11: SMB2 only test. Request lock and unlock in same packet. 2058 * Neither contend. SMB2 doesn't like lock and unlock requests in the 2059 * same packet. The lock will succeed, the unlock will fail with 2060 * INVALID_PARAMETER, and the lock will be unlocked before return. */ 2061 torture_comment(torture, " request lock and unlock. Both will " 2062 "fail.\n"); 2063 2064 /* Lock second range */ 2065 lck.in.lock_count = 0x0001; 2066 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2067 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2068 lck.in.locks = &el[1]; 2069 status = smb2_lock(tree, &lck); 2070 CHECK_STATUS(status, NT_STATUS_OK); 2071 2072 /* Attempt to lock the first range and unlock the second */ 2073 lck.in.lock_count = 0x0002; 2074 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2075 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2076 el[1].flags = SMB2_LOCK_FLAG_UNLOCK; 2077 lck.in.locks = el; 2078 status = smb2_lock(tree, &lck); 2079 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 2080 2081 /* First range should be unlocked, second locked. */ 2082 lck.in.lock_count = 0x0001; 2083 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2084 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2085 lck.in.locks = &el[0]; 2086 status = smb2_lock(tree, &lck); 2087 CHECK_STATUS(status, NT_STATUS_OK); 2088 2089 lck.in.lock_count = 0x0001; 2090 el[1].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2091 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2092 lck.in.locks = &el[1]; 2093 status = smb2_lock(tree, &lck); 2094 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 2095 2096 /* cleanup */ 2097 if (TARGET_IS_W2K8(torture)) { 2098 lck.in.lock_count = 0x0001; 2099 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2100 lck.in.locks = &el[0]; 2101 status = smb2_lock(tree, &lck); 2102 CHECK_STATUS(status, NT_STATUS_OK); 2103 torture_warning(torture, "Target has \"pretty please\" bug. " 2104 "A contending lock request on the same handle " 2105 "unlocks the lock.\n"); 2106 } else { 2107 lck.in.lock_count = 0x0002; 2108 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2109 el[1].flags = SMB2_LOCK_FLAG_UNLOCK; 2110 lck.in.locks = el; 2111 status = smb2_lock(tree, &lck); 2112 CHECK_STATUS(status, NT_STATUS_OK); 2113 } 2114 2115 done: 2116 smb2_util_close(tree, h); 2117 smb2_deltree(tree, BASEDIR); 2118 return ret; 2119 } 2120 2121 /** 2122 * Test lock stacking 2123 * - some tests ported from BASE-LOCK-LOCK5 2124 */ 2125 static bool test_stacking(struct torture_context *torture, 2126 struct smb2_tree *tree) 2127 { 2128 NTSTATUS status; 2129 bool ret = true; 2130 struct smb2_handle h, h2; 2131 uint8_t buf[200]; 2132 struct smb2_lock lck; 2133 struct smb2_lock_element el[1]; 2134 2135 const char *fname = BASEDIR "\\stacking.txt"; 2136 2137 status = torture_smb2_testdir(tree, BASEDIR, &h); 2138 CHECK_STATUS(status, NT_STATUS_OK); 2139 smb2_util_close(tree, h); 2140 2141 status = torture_smb2_testfile(tree, fname, &h); 2142 CHECK_STATUS(status, NT_STATUS_OK); 2143 2144 ZERO_STRUCT(buf); 2145 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 2146 CHECK_STATUS(status, NT_STATUS_OK); 2147 2148 status = torture_smb2_testfile(tree, fname, &h2); 2149 CHECK_STATUS(status, NT_STATUS_OK); 2150 2151 torture_comment(torture, "Testing lock stacking:\n"); 2152 2153 /* Setup initial parameters */ 2154 lck.in.locks = el; 2155 lck.in.lock_count = 0x0001; 2156 lck.in.lock_sequence = 0x00000000; 2157 lck.in.file.handle = h; 2158 el[0].offset = 0; 2159 el[0].length = 10; 2160 el[0].reserved = 0x00000000; 2161 2162 /* Try to take a shared lock, then a shared lock on same handle */ 2163 torture_comment(torture, " stacking a shared on top of a shared" 2164 "lock succeeds.\n"); 2165 2166 el[0].flags = SMB2_LOCK_FLAG_SHARED | 2167 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2168 status = smb2_lock(tree, &lck); 2169 CHECK_STATUS(status, NT_STATUS_OK); 2170 2171 el[0].flags = SMB2_LOCK_FLAG_SHARED | 2172 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2173 status = smb2_lock(tree, &lck); 2174 CHECK_STATUS(status, NT_STATUS_OK); 2175 2176 /* cleanup */ 2177 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2178 status = smb2_lock(tree, &lck); 2179 CHECK_STATUS(status, NT_STATUS_OK); 2180 2181 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2182 status = smb2_lock(tree, &lck); 2183 CHECK_STATUS(status, NT_STATUS_OK); 2184 2185 2186 /* Try to take an exclusive lock, then a shared lock on same handle */ 2187 torture_comment(torture, " stacking a shared on top of an exclusive " 2188 "lock succeeds.\n"); 2189 2190 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2191 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2192 status = smb2_lock(tree, &lck); 2193 CHECK_STATUS(status, NT_STATUS_OK); 2194 2195 el[0].flags = SMB2_LOCK_FLAG_SHARED | 2196 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2197 status = smb2_lock(tree, &lck); 2198 CHECK_STATUS(status, NT_STATUS_OK); 2199 2200 el[0].flags = SMB2_LOCK_FLAG_SHARED | 2201 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2202 status = smb2_lock(tree, &lck); 2203 CHECK_STATUS(status, NT_STATUS_OK); 2204 2205 /* stacking a shared from a different handle should fail */ 2206 lck.in.file.handle = h2; 2207 el[0].flags = SMB2_LOCK_FLAG_SHARED | 2208 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2209 status = smb2_lock(tree, &lck); 2210 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 2211 2212 /* cleanup */ 2213 lck.in.file.handle = h; 2214 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2215 status = smb2_lock(tree, &lck); 2216 CHECK_STATUS(status, NT_STATUS_OK); 2217 2218 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2219 status = smb2_lock(tree, &lck); 2220 CHECK_STATUS(status, NT_STATUS_OK); 2221 2222 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2223 status = smb2_lock(tree, &lck); 2224 CHECK_STATUS(status, NT_STATUS_OK); 2225 2226 /* ensure the 4th unlock fails */ 2227 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2228 status = smb2_lock(tree, &lck); 2229 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 2230 2231 /* ensure a second handle can now take an exclusive lock */ 2232 lck.in.file.handle = h2; 2233 el[0].flags = SMB2_LOCK_FLAG_SHARED | 2234 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2235 status = smb2_lock(tree, &lck); 2236 CHECK_STATUS(status, NT_STATUS_OK); 2237 2238 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2239 status = smb2_lock(tree, &lck); 2240 CHECK_STATUS(status, NT_STATUS_OK); 2241 2242 /* Try to take an exclusive lock, then a shared lock on a 2243 * different handle */ 2244 torture_comment(torture, " stacking a shared on top of an exclusive " 2245 "lock with different handles fails.\n"); 2246 2247 lck.in.file.handle = h; 2248 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2249 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2250 status = smb2_lock(tree, &lck); 2251 CHECK_STATUS(status, NT_STATUS_OK); 2252 2253 lck.in.file.handle = h2; 2254 el[0].flags = SMB2_LOCK_FLAG_SHARED | 2255 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2256 status = smb2_lock(tree, &lck); 2257 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 2258 2259 /* cleanup */ 2260 lck.in.file.handle = h; 2261 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2262 status = smb2_lock(tree, &lck); 2263 CHECK_STATUS(status, NT_STATUS_OK); 2264 2265 /* Try to take a shared lock, then stack an exclusive with same 2266 * handle. */ 2267 torture_comment(torture, " stacking an exclusive on top of a shared " 2268 "lock fails.\n"); 2269 2270 el[0].flags = SMB2_LOCK_FLAG_SHARED | 2271 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2272 status = smb2_lock(tree, &lck); 2273 CHECK_STATUS(status, NT_STATUS_OK); 2274 2275 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2276 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2277 status = smb2_lock(tree, &lck); 2278 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 2279 2280 /* cleanup */ 2281 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2282 status = smb2_lock(tree, &lck); 2283 if (TARGET_IS_W2K8(torture)) { 2284 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 2285 torture_warning(torture, "Target has \"pretty please\" bug. " 2286 "A contending lock request on the same handle " 2287 "unlocks the lock.\n"); 2288 } else { 2289 CHECK_STATUS(status, NT_STATUS_OK); 2290 } 2291 2292 /* Prove that two exclusive locks do not stack on the same handle. */ 2293 torture_comment(torture, " two exclusive locks do not stack.\n"); 2294 2295 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2296 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2297 status = smb2_lock(tree, &lck); 2298 CHECK_STATUS(status, NT_STATUS_OK); 2299 2300 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2301 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2302 status = smb2_lock(tree, &lck); 2303 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 2304 2305 /* cleanup */ 2306 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2307 status = smb2_lock(tree, &lck); 2308 if (TARGET_IS_W2K8(torture)) { 2309 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 2310 torture_warning(torture, "Target has \"pretty please\" bug. " 2311 "A contending lock request on the same handle " 2312 "unlocks the lock.\n"); 2313 } else { 2314 CHECK_STATUS(status, NT_STATUS_OK); 2315 } 2316 2317 done: 2318 smb2_util_close(tree, h2); 2319 smb2_util_close(tree, h); 2320 smb2_deltree(tree, BASEDIR); 2321 return ret; 2322 } 2323 2324 /** 2325 * Test lock contention 2326 * - shared lock should contend with exclusive lock on different handle 2327 */ 2328 static bool test_contend(struct torture_context *torture, 2329 struct smb2_tree *tree) 2330 { 2331 NTSTATUS status; 2332 bool ret = true; 2333 struct smb2_handle h, h2; 2334 uint8_t buf[200]; 2335 struct smb2_lock lck; 2336 struct smb2_lock_element el[1]; 2337 2338 const char *fname = BASEDIR "\\contend.txt"; 2339 2340 status = torture_smb2_testdir(tree, BASEDIR, &h); 2341 CHECK_STATUS(status, NT_STATUS_OK); 2342 smb2_util_close(tree, h); 2343 2344 status = torture_smb2_testfile(tree, fname, &h); 2345 CHECK_STATUS(status, NT_STATUS_OK); 2346 2347 ZERO_STRUCT(buf); 2348 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 2349 CHECK_STATUS(status, NT_STATUS_OK); 2350 2351 status = torture_smb2_testfile(tree, fname, &h2); 2352 CHECK_STATUS(status, NT_STATUS_OK); 2353 2354 torture_comment(torture, "Testing lock contention:\n"); 2355 2356 /* Setup initial parameters */ 2357 lck.in.locks = el; 2358 lck.in.lock_count = 0x0001; 2359 lck.in.lock_sequence = 0x00000000; 2360 lck.in.file.handle = h; 2361 el[0].offset = 0; 2362 el[0].length = 10; 2363 el[0].reserved = 0x00000000; 2364 2365 /* Take an exclusive lock, then a shared lock on different handle */ 2366 torture_comment(torture, " shared should contend on exclusive on " 2367 "different handle.\n"); 2368 2369 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2370 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2371 status = smb2_lock(tree, &lck); 2372 CHECK_STATUS(status, NT_STATUS_OK); 2373 2374 lck.in.file.handle = h2; 2375 el[0].flags = SMB2_LOCK_FLAG_SHARED | 2376 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2377 status = smb2_lock(tree, &lck); 2378 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); 2379 2380 /* cleanup */ 2381 lck.in.file.handle = h; 2382 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2383 status = smb2_lock(tree, &lck); 2384 CHECK_STATUS(status, NT_STATUS_OK); 2385 2386 done: 2387 smb2_util_close(tree, h2); 2388 smb2_util_close(tree, h); 2389 smb2_deltree(tree, BASEDIR); 2390 return ret; 2391 } 2392 2393 /** 2394 * Test locker context 2395 * - test that pid does not affect the locker context 2396 */ 2397 static bool test_context(struct torture_context *torture, 2398 struct smb2_tree *tree) 2399 { 2400 NTSTATUS status; 2401 bool ret = true; 2402 struct smb2_handle h, h2; 2403 uint8_t buf[200]; 2404 struct smb2_lock lck; 2405 struct smb2_lock_element el[1]; 2406 2407 const char *fname = BASEDIR "\\context.txt"; 2408 2409 status = torture_smb2_testdir(tree, BASEDIR, &h); 2410 CHECK_STATUS(status, NT_STATUS_OK); 2411 smb2_util_close(tree, h); 2412 2413 status = torture_smb2_testfile(tree, fname, &h); 2414 CHECK_STATUS(status, NT_STATUS_OK); 2415 2416 ZERO_STRUCT(buf); 2417 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 2418 CHECK_STATUS(status, NT_STATUS_OK); 2419 2420 status = torture_smb2_testfile(tree, fname, &h2); 2421 CHECK_STATUS(status, NT_STATUS_OK); 2422 2423 torture_comment(torture, "Testing locker context:\n"); 2424 2425 /* Setup initial parameters */ 2426 lck.in.locks = el; 2427 lck.in.lock_count = 0x0001; 2428 lck.in.lock_sequence = 0x00000000; 2429 lck.in.file.handle = h; 2430 el[0].offset = 0; 2431 el[0].length = 10; 2432 el[0].reserved = 0x00000000; 2433 2434 /* Take an exclusive lock, then try to unlock with a different pid, 2435 * same handle. This shows that the pid doesn't affect the locker 2436 * context in SMB2. */ 2437 torture_comment(torture, " pid shouldn't affect locker context\n"); 2438 2439 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2440 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2441 status = smb2_lock(tree, &lck); 2442 CHECK_STATUS(status, NT_STATUS_OK); 2443 2444 tree->session->pid++; 2445 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2446 status = smb2_lock(tree, &lck); 2447 CHECK_STATUS(status, NT_STATUS_OK); 2448 2449 tree->session->pid--; 2450 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2451 status = smb2_lock(tree, &lck); 2452 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); 2453 2454 done: 2455 smb2_util_close(tree, h2); 2456 smb2_util_close(tree, h); 2457 smb2_deltree(tree, BASEDIR); 2458 return ret; 2459 } 2460 2461 /** 2462 * Test as much of the potential lock range as possible 2463 * - test ported from BASE-LOCK-LOCK3 2464 */ 2465 static bool test_range(struct torture_context *torture, 2466 struct smb2_tree *tree) 2467 { 2468 NTSTATUS status; 2469 bool ret = true; 2470 struct smb2_handle h, h2; 2471 uint8_t buf[200]; 2472 struct smb2_lock lck; 2473 struct smb2_lock_element el[1]; 2474 uint64_t offset, i; 2475 extern int torture_numops; 2476 2477 const char *fname = BASEDIR "\\range.txt"; 2478 2479 #define NEXT_OFFSET offset += (~(uint64_t)0) / torture_numops 2480 2481 status = torture_smb2_testdir(tree, BASEDIR, &h); 2482 CHECK_STATUS(status, NT_STATUS_OK); 2483 smb2_util_close(tree, h); 2484 2485 status = torture_smb2_testfile(tree, fname, &h); 2486 CHECK_STATUS(status, NT_STATUS_OK); 2487 2488 ZERO_STRUCT(buf); 2489 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 2490 CHECK_STATUS(status, NT_STATUS_OK); 2491 2492 status = torture_smb2_testfile(tree, fname, &h2); 2493 CHECK_STATUS(status, NT_STATUS_OK); 2494 2495 torture_comment(torture, "Testing locks spread across the 64-bit " 2496 "offset range\n"); 2497 2498 if (TARGET_IS_W2K8(torture)) { 2499 torture_result(torture, TORTURE_SKIP, 2500 "Target has \"pretty please\" bug. A contending lock " 2501 "request on the same handle unlocks the lock."); 2502 goto done; 2503 } 2504 2505 /* Setup initial parameters */ 2506 lck.in.locks = el; 2507 lck.in.lock_count = 0x0001; 2508 lck.in.lock_sequence = 0x00000000; 2509 lck.in.file.handle = h; 2510 el[0].offset = 0; 2511 el[0].length = 1; 2512 el[0].reserved = 0x00000000; 2513 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2514 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2515 2516 torture_comment(torture, " establishing %d locks\n", torture_numops); 2517 2518 for (offset=i=0; i<torture_numops; i++) { 2519 NEXT_OFFSET; 2520 2521 lck.in.file.handle = h; 2522 el[0].offset = offset - 1; 2523 status = smb2_lock(tree, &lck); 2524 CHECK_STATUS_CMT(status, NT_STATUS_OK, 2525 talloc_asprintf(torture, 2526 "lock h failed at offset %#llx ", 2527 (unsigned long long) el[0].offset)); 2528 2529 lck.in.file.handle = h2; 2530 el[0].offset = offset - 2; 2531 status = smb2_lock(tree, &lck); 2532 CHECK_STATUS_CMT(status, NT_STATUS_OK, 2533 talloc_asprintf(torture, 2534 "lock h2 failed at offset %#llx ", 2535 (unsigned long long) el[0].offset)); 2536 } 2537 2538 torture_comment(torture, " testing %d locks\n", torture_numops); 2539 2540 for (offset=i=0; i<torture_numops; i++) { 2541 NEXT_OFFSET; 2542 2543 lck.in.file.handle = h; 2544 el[0].offset = offset - 1; 2545 status = smb2_lock(tree, &lck); 2546 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED, 2547 talloc_asprintf(torture, 2548 "lock h at offset %#llx should not have " 2549 "succeeded ", 2550 (unsigned long long) el[0].offset)); 2551 2552 lck.in.file.handle = h; 2553 el[0].offset = offset - 2; 2554 status = smb2_lock(tree, &lck); 2555 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED, 2556 talloc_asprintf(torture, 2557 "lock h2 at offset %#llx should not have " 2558 "succeeded ", 2559 (unsigned long long) el[0].offset)); 2560 2561 lck.in.file.handle = h2; 2562 el[0].offset = offset - 1; 2563 status = smb2_lock(tree, &lck); 2564 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED, 2565 talloc_asprintf(torture, 2566 "lock h at offset %#llx should not have " 2567 "succeeded ", 2568 (unsigned long long) el[0].offset)); 2569 2570 lck.in.file.handle = h2; 2571 el[0].offset = offset - 2; 2572 status = smb2_lock(tree, &lck); 2573 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED, 2574 talloc_asprintf(torture, 2575 "lock h2 at offset %#llx should not have " 2576 "succeeded ", 2577 (unsigned long long) el[0].offset)); 2578 } 2579 2580 torture_comment(torture, " removing %d locks\n", torture_numops); 2581 2582 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2583 2584 for (offset=i=0; i<torture_numops; i++) { 2585 NEXT_OFFSET; 2586 2587 lck.in.file.handle = h; 2588 el[0].offset = offset - 1; 2589 status = smb2_lock(tree, &lck); 2590 CHECK_STATUS_CMT(status, NT_STATUS_OK, 2591 talloc_asprintf(torture, 2592 "unlock from h failed at offset %#llx ", 2593 (unsigned long long) el[0].offset)); 2594 2595 lck.in.file.handle = h2; 2596 el[0].offset = offset - 2; 2597 status = smb2_lock(tree, &lck); 2598 CHECK_STATUS_CMT(status, NT_STATUS_OK, 2599 talloc_asprintf(torture, 2600 "unlock from h2 failed at offset %#llx ", 2601 (unsigned long long) el[0].offset)); 2602 } 2603 2604 done: 2605 smb2_util_close(tree, h2); 2606 smb2_util_close(tree, h); 2607 smb2_deltree(tree, BASEDIR); 2608 return ret; 2609 } 2610 2611 static NTSTATUS smb2cli_lock(struct smb2_tree *tree, struct smb2_handle h, 2612 uint64_t offset, uint64_t length, bool exclusive) 2613 { 2614 struct smb2_lock lck; 2615 struct smb2_lock_element el[1]; 2616 NTSTATUS status; 2617 2618 lck.in.locks = el; 2619 lck.in.lock_count = 0x0001; 2620 lck.in.lock_sequence = 0x00000000; 2621 lck.in.file.handle = h; 2622 el[0].offset = offset; 2623 el[0].length = length; 2624 el[0].reserved = 0x00000000; 2625 el[0].flags = (exclusive ? 2626 SMB2_LOCK_FLAG_EXCLUSIVE : 2627 SMB2_LOCK_FLAG_SHARED) | 2628 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2629 2630 status = smb2_lock(tree, &lck); 2631 2632 return status; 2633 } 2634 2635 static NTSTATUS smb2cli_unlock(struct smb2_tree *tree, struct smb2_handle h, 2636 uint64_t offset, uint64_t length) 2637 { 2638 struct smb2_lock lck; 2639 struct smb2_lock_element el[1]; 2640 NTSTATUS status; 2641 2642 lck.in.locks = el; 2643 lck.in.lock_count = 0x0001; 2644 lck.in.lock_sequence = 0x00000000; 2645 lck.in.file.handle = h; 2646 el[0].offset = offset; 2647 el[0].length = length; 2648 el[0].reserved = 0x00000000; 2649 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2650 2651 status = smb2_lock(tree, &lck); 2652 2653 return status; 2654 } 2655 2656 #define EXPECTED(ret, v) if ((ret) != (v)) { \ 2657 torture_result(torture, TORTURE_FAIL, __location__": subtest failed");\ 2658 torture_comment(torture, "** "); correct = false; \ 2659 } 2660 2661 /** 2662 * Test overlapping lock ranges from various lockers 2663 * - some tests ported from BASE-LOCK-LOCK4 2664 */ 2665 static bool test_overlap(struct torture_context *torture, 2666 struct smb2_tree *tree, 2667 struct smb2_tree *tree2) 2668 { 2669 NTSTATUS status; 2670 bool ret = true; 2671 struct smb2_handle h, h2, h3; 2672 uint8_t buf[200]; 2673 bool correct = true; 2674 2675 const char *fname = BASEDIR "\\overlap.txt"; 2676 2677 status = torture_smb2_testdir(tree, BASEDIR, &h); 2678 CHECK_STATUS(status, NT_STATUS_OK); 2679 smb2_util_close(tree, h); 2680 2681 status = torture_smb2_testfile(tree, fname, &h); 2682 CHECK_STATUS(status, NT_STATUS_OK); 2683 2684 ZERO_STRUCT(buf); 2685 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 2686 CHECK_STATUS(status, NT_STATUS_OK); 2687 2688 status = torture_smb2_testfile(tree, fname, &h2); 2689 CHECK_STATUS(status, NT_STATUS_OK); 2690 2691 status = torture_smb2_testfile(tree2, fname, &h3); 2692 CHECK_STATUS(status, NT_STATUS_OK); 2693 2694 torture_comment(torture, "Testing overlapping locks:\n"); 2695 2696 ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 0, 4, true)) && 2697 NT_STATUS_IS_OK(smb2cli_lock(tree, h, 2, 4, true)); 2698 EXPECTED(ret, false); 2699 torture_comment(torture, "the same session/handle %s set overlapping " 2700 "exclusive locks\n", ret?"can":"cannot"); 2701 2702 ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 10, 4, false)) && 2703 NT_STATUS_IS_OK(smb2cli_lock(tree, h, 12, 4, false)); 2704 EXPECTED(ret, true); 2705 torture_comment(torture, "the same session/handle %s set overlapping " 2706 "shared locks\n", ret?"can":"cannot"); 2707 2708 ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 20, 4, true)) && 2709 NT_STATUS_IS_OK(smb2cli_lock(tree2, h3, 22, 4, true)); 2710 EXPECTED(ret, false); 2711 torture_comment(torture, "a different session %s set overlapping " 2712 "exclusive locks\n", ret?"can":"cannot"); 2713 2714 ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 30, 4, false)) && 2715 NT_STATUS_IS_OK(smb2cli_lock(tree2, h3, 32, 4, false)); 2716 EXPECTED(ret, true); 2717 torture_comment(torture, "a different session %s set overlapping " 2718 "shared locks\n", ret?"can":"cannot"); 2719 2720 ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 40, 4, true)) && 2721 NT_STATUS_IS_OK(smb2cli_lock(tree, h2, 42, 4, true)); 2722 EXPECTED(ret, false); 2723 torture_comment(torture, "a different handle %s set overlapping " 2724 "exclusive locks\n", ret?"can":"cannot"); 2725 2726 ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 50, 4, false)) && 2727 NT_STATUS_IS_OK(smb2cli_lock(tree, h2, 52, 4, false)); 2728 EXPECTED(ret, true); 2729 torture_comment(torture, "a different handle %s set overlapping " 2730 "shared locks\n", ret?"can":"cannot"); 2731 2732 ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 110, 4, false)) && 2733 NT_STATUS_IS_OK(smb2cli_lock(tree, h, 112, 4, false)) && 2734 NT_STATUS_IS_OK(smb2cli_unlock(tree, h, 110, 6)); 2735 EXPECTED(ret, false); 2736 torture_comment(torture, "the same handle %s coalesce read locks\n", 2737 ret?"can":"cannot"); 2738 2739 smb2_util_close(tree, h2); 2740 smb2_util_close(tree, h); 2741 status = torture_smb2_testfile(tree, fname, &h); 2742 CHECK_STATUS(status, NT_STATUS_OK); 2743 status = torture_smb2_testfile(tree, fname, &h2); 2744 CHECK_STATUS(status, NT_STATUS_OK); 2745 ret = NT_STATUS_IS_OK(smb2cli_lock(tree, h, 0, 8, false)) && 2746 NT_STATUS_IS_OK(smb2cli_lock(tree, h2, 0, 1, false)) && 2747 NT_STATUS_IS_OK(smb2_util_close(tree, h)) && 2748 NT_STATUS_IS_OK(torture_smb2_testfile(tree, fname, &h)) && 2749 NT_STATUS_IS_OK(smb2cli_lock(tree, h, 7, 1, true)); 2750 EXPECTED(ret, true); 2751 torture_comment(torture, "the server %s have the NT byte range lock " 2752 "bug\n", !ret?"does":"doesn't"); 2753 2754 done: 2755 smb2_util_close(tree2, h3); 2756 smb2_util_close(tree, h2); 2757 smb2_util_close(tree, h); 2758 smb2_deltree(tree, BASEDIR); 2759 return correct; 2760 } 2761 2762 /** 2763 * Test truncation of locked file 2764 * - some tests ported from BASE-LOCK-LOCK7 2765 */ 2766 static bool test_truncate(struct torture_context *torture, 2767 struct smb2_tree *tree) 2768 { 2769 NTSTATUS status; 2770 bool ret = true; 2771 struct smb2_handle h, h2; 2772 uint8_t buf[200]; 2773 struct smb2_lock lck; 2774 struct smb2_lock_element el[1]; 2775 struct smb2_create io; 2776 2777 const char *fname = BASEDIR "\\truncate.txt"; 2778 2779 status = torture_smb2_testdir(tree, BASEDIR, &h); 2780 CHECK_STATUS(status, NT_STATUS_OK); 2781 smb2_util_close(tree, h); 2782 2783 status = torture_smb2_testfile(tree, fname, &h); 2784 CHECK_STATUS(status, NT_STATUS_OK); 2785 2786 ZERO_STRUCT(buf); 2787 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); 2788 CHECK_STATUS(status, NT_STATUS_OK); 2789 2790 torture_comment(torture, "Testing truncation of locked file:\n"); 2791 2792 /* Setup initial parameters */ 2793 lck.in.locks = el; 2794 lck.in.lock_count = 0x0001; 2795 lck.in.lock_sequence = 0x00000000; 2796 lck.in.file.handle = h; 2797 el[0].offset = 0; 2798 el[0].length = 10; 2799 el[0].reserved = 0x00000000; 2800 2801 ZERO_STRUCT(io); 2802 io.in.oplock_level = 0; 2803 io.in.desired_access = SEC_RIGHTS_FILE_ALL; 2804 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 2805 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE; 2806 io.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE | 2807 NTCREATEX_SHARE_ACCESS_READ | 2808 NTCREATEX_SHARE_ACCESS_WRITE; 2809 io.in.create_options = 0; 2810 io.in.fname = fname; 2811 2812 /* Take an exclusive lock */ 2813 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | 2814 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; 2815 status = smb2_lock(tree, &lck); 2816 CHECK_STATUS(status, NT_STATUS_OK); 2817 2818 /* On second handle open the file with OVERWRITE disposition */ 2819 torture_comment(torture, " overwrite disposition is allowed on a " 2820 "locked file.\n"); 2821 2822 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE; 2823 status = smb2_create(tree, tree, &io); 2824 CHECK_STATUS(status, NT_STATUS_OK); 2825 h2 = io.out.file.handle; 2826 smb2_util_close(tree, h2); 2827 2828 /* On second handle open the file with SUPERSEDE disposition */ 2829 torture_comment(torture, " supersede disposition is allowed on a " 2830 "locked file.\n"); 2831 2832 io.in.create_disposition = NTCREATEX_DISP_SUPERSEDE; 2833 status = smb2_create(tree, tree, &io); 2834 CHECK_STATUS(status, NT_STATUS_OK); 2835 h2 = io.out.file.handle; 2836 smb2_util_close(tree, h2); 2837 2838 /* cleanup */ 2839 lck.in.file.handle = h; 2840 el[0].flags = SMB2_LOCK_FLAG_UNLOCK; 2841 status = smb2_lock(tree, &lck); 2842 CHECK_STATUS(status, NT_STATUS_OK); 2843 2844 done: 2845 smb2_util_close(tree, h2); 2846 smb2_util_close(tree, h); 2847 smb2_deltree(tree, BASEDIR); 2848 return ret; 2849 } 553 2850 554 2851 /* basic testing of SMB2 locking … … 556 2853 struct torture_suite *torture_smb2_lock_init(void) 557 2854 { 558 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "LOCK"); 559 560 torture_suite_add_1smb2_test(suite, "VALID-REQUEST", test_valid_request); 561 torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none); 562 torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared); 563 torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv); 564 torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK", test_lock_auto_unlock); 2855 struct torture_suite *suite = 2856 torture_suite_create(talloc_autofree_context(), "lock"); 2857 2858 torture_suite_add_1smb2_test(suite, "valid-request", 2859 test_valid_request); 2860 torture_suite_add_1smb2_test(suite, "rw-none", test_lock_rw_none); 2861 torture_suite_add_1smb2_test(suite, "rw-shared", test_lock_rw_shared); 2862 torture_suite_add_1smb2_test(suite, "rw-exclusive", 2863 test_lock_rw_exclusive); 2864 torture_suite_add_1smb2_test(suite, "auto-unlock", 2865 test_lock_auto_unlock); 2866 torture_suite_add_1smb2_test(suite, "lock", test_lock); 2867 torture_suite_add_1smb2_test(suite, "async", test_async); 2868 torture_suite_add_1smb2_test(suite, "cancel", test_cancel); 2869 torture_suite_add_1smb2_test(suite, "cancel-tdis", test_cancel_tdis); 2870 torture_suite_add_1smb2_test(suite, "cancel-logoff", 2871 test_cancel_logoff); 2872 torture_suite_add_1smb2_test(suite, "errorcode", test_errorcode); 2873 torture_suite_add_1smb2_test(suite, "zerobytelength", 2874 test_zerobytelength); 2875 torture_suite_add_1smb2_test(suite, "zerobyteread", 2876 test_zerobyteread); 2877 torture_suite_add_1smb2_test(suite, "unlock", test_unlock); 2878 torture_suite_add_1smb2_test(suite, "multiple-unlock", 2879 test_multiple_unlock); 2880 torture_suite_add_1smb2_test(suite, "stacking", test_stacking); 2881 torture_suite_add_1smb2_test(suite, "contend", test_contend); 2882 torture_suite_add_1smb2_test(suite, "context", test_context); 2883 torture_suite_add_1smb2_test(suite, "range", test_range); 2884 torture_suite_add_2smb2_test(suite, "overlap", test_overlap); 2885 torture_suite_add_1smb2_test(suite, "truncate", test_truncate); 565 2886 566 2887 suite->description = talloc_strdup(suite, "SMB2-LOCK tests"); … … 568 2889 return suite; 569 2890 } 570 -
trunk/server/source4/torture/smb2/notify.c
r414 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 … … 5 5 6 6 Copyright (C) Stefan Metzmacher 2006 7 7 Copyright (C) Andrew Tridgell 2009 8 8 9 This program is free software; you can redistribute it and/or modify 9 10 it under the terms of the GNU General Public License as published by 10 11 the Free Software Foundation; either version 3 of the License, or 11 12 (at your option) any later version. 12 13 13 14 This program is distributed in the hope that it will be useful, 14 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 17 GNU General Public License for more details. 17 18 18 19 You should have received a copy of the GNU General Public License 19 20 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 26 27 #include "torture/torture.h" 27 28 #include "torture/smb2/proto.h" 29 #include "librpc/gen_ndr/ndr_security.h" 30 #include "libcli/security/security.h" 31 #include "torture/util.h" 32 33 #include "system/filesys.h" 34 #include "auth/credentials/credentials.h" 35 #include "lib/cmdline/popt_common.h" 36 #include "librpc/gen_ndr/security.h" 37 38 #include "lib/events/events.h" 28 39 29 40 #include "libcli/raw/libcliraw.h" 30 #include "lib/events/events.h" 41 #include "libcli/raw/raw_proto.h" 42 #include "libcli/libcli.h" 31 43 32 44 #define CHECK_STATUS(status, correct) do { \ 33 45 if (!NT_STATUS_EQUAL(status, correct)) { \ 34 printf("(%s) Incorrect status %s - should be %s\n", \ 46 torture_result(torture, TORTURE_FAIL, \ 47 "(%s) Incorrect status %s - should be %s\n", \ 35 48 __location__, nt_errstr(status), nt_errstr(correct)); \ 36 49 ret = false; \ … … 38 51 }} while (0) 39 52 40 #define CHECK_VAL UE(v, correct) do { \53 #define CHECK_VAL(v, correct) do { \ 41 54 if ((v) != (correct)) { \ 42 printf("(%s) Incorrect value %s=%d - should be %d\n", \ 43 __location__, #v, v, correct); \ 55 torture_result(torture, TORTURE_FAIL, \ 56 "(%s) wrong value for %s 0x%x should be 0x%x\n", \ 57 __location__, #v, (int)v, (int)correct); \ 44 58 ret = false; \ 45 59 goto done; \ … … 48 62 #define CHECK_WIRE_STR(field, value) do { \ 49 63 if (!field.s || strcmp(field.s, value)) { \ 50 printf("(%s) %s [%s] != %s\n", \ 51 __location__, #field, field.s, value); \ 64 torture_result(torture, TORTURE_FAIL, \ 65 "(%s) %s [%s] != %s\n", __location__, #field, \ 66 field.s, value); \ 52 67 ret = false; \ 53 68 goto done; \ 54 69 }} while (0) 55 70 71 #define BASEDIR "test_notify" 56 72 #define FNAME "smb2-notify01.dat" 57 73 58 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false)) 59 60 static bool test_valid_request(struct torture_context *tctx, struct smb2_tree *tree) 74 static bool test_valid_request(struct torture_context *torture, 75 struct smb2_tree *tree) 61 76 { 62 77 bool ret = true; … … 65 80 struct smb2_notify n; 66 81 struct smb2_request *req; 67 uint32_t max_buffer_size = 0x00080000; 68 69 if (TARGET_IS_WIN7(tctx)) { 70 max_buffer_size = 0x00010000; 71 } 82 uint32_t max_buffer_size; 83 84 torture_comment(torture, "TESTING VALIDITY OF CHANGE NOTIFY REQUEST\n"); 72 85 73 86 smb2_util_unlink(tree, FNAME); … … 75 88 status = smb2_util_roothandle(tree, &dh); 76 89 CHECK_STATUS(status, NT_STATUS_OK); 90 91 /* 0x00080000 is the default max buffer size for Windows servers 92 * pre-Win7 */ 93 max_buffer_size = torture_setting_ulong(torture, "cn_max_buffer_size", 94 0x00080000); 77 95 78 96 n.in.recursive = 0x0000; 79 97 n.in.buffer_size = max_buffer_size; 80 98 n.in.file.handle = dh; 81 n.in.completion_filter = 0x00000FFF;99 n.in.completion_filter = FILE_NOTIFY_CHANGE_ALL; 82 100 n.in.unknown = 0x00000000; 83 101 req = smb2_notify_send(tree, &n); … … 92 110 CHECK_STATUS(status, NT_STATUS_OK); 93 111 94 status = smb2_notify_recv(req, t ctx, &n);95 CHECK_STATUS(status, NT_STATUS_OK); 96 CHECK_VAL UE(n.out.num_changes, 1);97 CHECK_VAL UE(n.out.changes[0].action, NOTIFY_ACTION_ADDED);112 status = smb2_notify_recv(req, torture, &n); 113 CHECK_STATUS(status, NT_STATUS_OK); 114 CHECK_VAL(n.out.num_changes, 1); 115 CHECK_VAL(n.out.changes[0].action, NOTIFY_ACTION_ADDED); 98 116 CHECK_WIRE_STR(n.out.changes[0].name, FNAME); 99 117 100 /* 118 /* 101 119 * if the change response doesn't fit in the buffer 102 120 * NOTIFY_ENUM_DIR is returned. … … 114 132 CHECK_STATUS(status, NT_STATUS_OK); 115 133 116 status = smb2_notify_recv(req, t ctx, &n);134 status = smb2_notify_recv(req, torture, &n); 117 135 CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR); 118 136 119 /* 137 /* 120 138 * if the change response fits in the buffer we get 121 139 * NT_STATUS_OK again … … 133 151 CHECK_STATUS(status, NT_STATUS_OK); 134 152 135 status = smb2_notify_recv(req, t ctx, &n);136 CHECK_STATUS(status, NT_STATUS_OK); 137 CHECK_VAL UE(n.out.num_changes, 3);138 CHECK_VAL UE(n.out.changes[0].action, NOTIFY_ACTION_REMOVED);153 status = smb2_notify_recv(req, torture, &n); 154 CHECK_STATUS(status, NT_STATUS_OK); 155 CHECK_VAL(n.out.num_changes, 3); 156 CHECK_VAL(n.out.changes[0].action, NOTIFY_ACTION_REMOVED); 139 157 CHECK_WIRE_STR(n.out.changes[0].name, FNAME); 140 CHECK_VAL UE(n.out.changes[1].action, NOTIFY_ACTION_ADDED);158 CHECK_VAL(n.out.changes[1].action, NOTIFY_ACTION_ADDED); 141 159 CHECK_WIRE_STR(n.out.changes[1].name, FNAME); 142 CHECK_VAL UE(n.out.changes[2].action, NOTIFY_ACTION_MODIFIED);160 CHECK_VAL(n.out.changes[2].action, NOTIFY_ACTION_MODIFIED); 143 161 CHECK_WIRE_STR(n.out.changes[2].name, FNAME); 144 162 … … 152 170 n.in.buffer_size = 0x00000001; 153 171 n.in.file.handle = dh; 154 n.in.completion_filter = 0x00000FFF;172 n.in.completion_filter = FILE_NOTIFY_CHANGE_ALL; 155 173 n.in.unknown = 0x00000000; 156 174 req = smb2_notify_send(tree, &n); … … 165 183 CHECK_STATUS(status, NT_STATUS_OK); 166 184 167 status = smb2_notify_recv(req, t ctx, &n);185 status = smb2_notify_recv(req, torture, &n); 168 186 CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR); 169 187 170 n.in.buffer_size 188 n.in.buffer_size = max_buffer_size; 171 189 req = smb2_notify_send(tree, &n); 172 190 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { … … 179 197 CHECK_STATUS(status, NT_STATUS_OK); 180 198 181 status = smb2_notify_recv(req, t ctx, &n);199 status = smb2_notify_recv(req, torture, &n); 182 200 CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR); 183 201 … … 186 204 n.in.buffer_size = max_buffer_size + 1; 187 205 n.in.file.handle = dh; 188 n.in.completion_filter = 0x00000FFF;206 n.in.completion_filter = FILE_NOTIFY_CHANGE_ALL; 189 207 n.in.unknown = 0x00000000; 190 208 req = smb2_notify_send(tree, &n); 191 status = smb2_notify_recv(req, t ctx, &n);209 status = smb2_notify_recv(req, torture, &n); 192 210 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 193 211 … … 196 214 } 197 215 198 /* basic testing of SMB2 notify 216 /* 217 basic testing of change notify on directories 199 218 */ 200 bool torture_smb2_notify(struct torture_context *torture) 219 static bool torture_smb2_notify_dir(struct torture_context *torture, 220 struct smb2_tree *tree1, 221 struct smb2_tree *tree2) 201 222 { 202 struct smb2_tree *tree;203 223 bool ret = true; 204 205 if (!torture_smb2_connection(torture, &tree)) { 206 return false; 224 NTSTATUS status; 225 union smb_notify notify; 226 union smb_open io; 227 union smb_close cl; 228 int i, count; 229 struct smb2_handle h1, h2; 230 struct smb2_request *req, *req2; 231 const char *fname = BASEDIR "\\subdir-name"; 232 extern int torture_numops; 233 234 torture_comment(torture, "TESTING CHANGE NOTIFY ON DIRECTORIES\n"); 235 236 smb2_deltree(tree1, BASEDIR); 237 smb2_util_rmdir(tree1, BASEDIR); 238 /* 239 get a handle on the directory 240 */ 241 ZERO_STRUCT(io.smb2); 242 io.generic.level = RAW_OPEN_SMB2; 243 io.smb2.in.create_flags = 0; 244 io.smb2.in.desired_access = SEC_FILE_ALL; 245 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 246 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 247 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 248 NTCREATEX_SHARE_ACCESS_WRITE; 249 io.smb2.in.alloc_size = 0; 250 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 251 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 252 io.smb2.in.security_flags = 0; 253 io.smb2.in.fname = BASEDIR; 254 255 status = smb2_create(tree1, torture, &(io.smb2)); 256 CHECK_STATUS(status, NT_STATUS_OK); 257 h1 = io.smb2.out.file.handle; 258 259 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; 260 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ; 261 status = smb2_create(tree1, torture, &(io.smb2)); 262 CHECK_STATUS(status, NT_STATUS_OK); 263 h2 = io.smb2.out.file.handle; 264 265 /* ask for a change notify, 266 on file or directory name changes */ 267 ZERO_STRUCT(notify.smb2); 268 notify.smb2.level = RAW_NOTIFY_SMB2; 269 notify.smb2.in.buffer_size = 1000; 270 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; 271 notify.smb2.in.file.handle = h1; 272 notify.smb2.in.recursive = true; 273 274 torture_comment(torture, "Testing notify cancel\n"); 275 276 req = smb2_notify_send(tree1, &(notify.smb2)); 277 smb2_cancel(req); 278 status = smb2_notify_recv(req, torture, &(notify.smb2)); 279 CHECK_STATUS(status, NT_STATUS_CANCELLED); 280 281 torture_comment(torture, "Testing notify mkdir\n"); 282 283 req = smb2_notify_send(tree1, &(notify.smb2)); 284 smb2_util_mkdir(tree2, fname); 285 286 status = smb2_notify_recv(req, torture, &(notify.smb2)); 287 CHECK_STATUS(status, NT_STATUS_OK); 288 289 CHECK_VAL(notify.smb2.out.num_changes, 1); 290 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED); 291 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 292 293 torture_comment(torture, "Testing notify rmdir\n"); 294 295 req = smb2_notify_send(tree1, &(notify.smb2)); 296 smb2_util_rmdir(tree2, fname); 297 298 status = smb2_notify_recv(req, torture, &(notify.smb2)); 299 CHECK_STATUS(status, NT_STATUS_OK); 300 CHECK_VAL(notify.smb2.out.num_changes, 1); 301 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED); 302 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 303 304 torture_comment(torture, 305 "Testing notify mkdir - rmdir - mkdir - rmdir\n"); 306 307 smb2_util_mkdir(tree2, fname); 308 smb2_util_rmdir(tree2, fname); 309 smb2_util_mkdir(tree2, fname); 310 smb2_util_rmdir(tree2, fname); 311 smb_msleep(200); 312 req = smb2_notify_send(tree1, &(notify.smb2)); 313 status = smb2_notify_recv(req, torture, &(notify.smb2)); 314 CHECK_STATUS(status, NT_STATUS_OK); 315 CHECK_VAL(notify.smb2.out.num_changes, 4); 316 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED); 317 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 318 CHECK_VAL(notify.smb2.out.changes[1].action, NOTIFY_ACTION_REMOVED); 319 CHECK_WIRE_STR(notify.smb2.out.changes[1].name, "subdir-name"); 320 CHECK_VAL(notify.smb2.out.changes[2].action, NOTIFY_ACTION_ADDED); 321 CHECK_WIRE_STR(notify.smb2.out.changes[2].name, "subdir-name"); 322 CHECK_VAL(notify.smb2.out.changes[3].action, NOTIFY_ACTION_REMOVED); 323 CHECK_WIRE_STR(notify.smb2.out.changes[3].name, "subdir-name"); 324 325 count = torture_numops; 326 torture_comment(torture, 327 "Testing buffered notify on create of %d files\n", count); 328 for (i=0;i<count;i++) { 329 struct smb2_handle h12; 330 char *fname2 = talloc_asprintf(torture, BASEDIR "\\test%d.txt", 331 i); 332 333 ZERO_STRUCT(io.smb2); 334 io.generic.level = RAW_OPEN_SMB2; 335 io.smb2.in.create_flags = 0; 336 io.smb2.in.desired_access = SEC_FILE_ALL; 337 io.smb2.in.create_options = 338 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; 339 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 340 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 341 NTCREATEX_SHARE_ACCESS_WRITE; 342 io.smb2.in.alloc_size = 0; 343 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 344 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 345 io.smb2.in.security_flags = 0; 346 io.smb2.in.fname = fname2; 347 348 status = smb2_create(tree1, torture, &(io.smb2)); 349 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) { 350 torture_comment(torture, "Failed to create %s \n", 351 fname); 352 ret = false; 353 goto done; 354 } 355 h12 = io.smb2.out.file.handle; 356 talloc_free(fname2); 357 smb2_util_close(tree1, h12); 207 358 } 208 359 209 ret &= test_valid_request(torture, tree); 210 360 /* (1st notify) setup a new notify on a different directory handle. 361 This new notify won't see the events above. */ 362 notify.smb2.in.file.handle = h2; 363 req2 = smb2_notify_send(tree1, &(notify.smb2)); 364 365 /* (2nd notify) whereas this notify will see the above buffered events, 366 and it directly returns the buffered events */ 367 notify.smb2.in.file.handle = h1; 368 req = smb2_notify_send(tree1, &(notify.smb2)); 369 370 status = smb2_util_unlink(tree1, BASEDIR "\\nonexistant.txt"); 371 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); 372 373 /* (1st unlink) as the 2nd notify directly returns, 374 this unlink is only seen by the 1st notify and 375 the 3rd notify (later) */ 376 torture_comment(torture, 377 "Testing notify on unlink for the first file\n"); 378 status = smb2_util_unlink(tree2, BASEDIR "\\test0.txt"); 379 CHECK_STATUS(status, NT_STATUS_OK); 380 381 /* receive the reply from the 2nd notify */ 382 status = smb2_notify_recv(req, torture, &(notify.smb2)); 383 CHECK_STATUS(status, NT_STATUS_OK); 384 385 CHECK_VAL(notify.smb2.out.num_changes, count); 386 for (i=1;i<count;i++) { 387 CHECK_VAL(notify.smb2.out.changes[i].action, 388 NOTIFY_ACTION_ADDED); 389 } 390 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt"); 391 392 torture_comment(torture, "and now from the 1st notify\n"); 393 status = smb2_notify_recv(req2, torture, &(notify.smb2)); 394 CHECK_STATUS(status, NT_STATUS_OK); 395 CHECK_VAL(notify.smb2.out.num_changes, 1); 396 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED); 397 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt"); 398 399 torture_comment(torture, 400 "(3rd notify) this notify will only see the 1st unlink\n"); 401 req = smb2_notify_send(tree1, &(notify.smb2)); 402 403 status = smb2_util_unlink(tree1, BASEDIR "\\nonexistant.txt"); 404 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); 405 406 for (i=1;i<count;i++) { 407 char *fname2 = talloc_asprintf(torture, 408 BASEDIR "\\test%d.txt", i); 409 status = smb2_util_unlink(tree2, fname2); 410 CHECK_STATUS(status, NT_STATUS_OK); 411 talloc_free(fname2); 412 } 413 414 /* receive the 3rd notify */ 415 status = smb2_notify_recv(req, torture, &(notify.smb2)); 416 CHECK_STATUS(status, NT_STATUS_OK); 417 CHECK_VAL(notify.smb2.out.num_changes, 1); 418 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED); 419 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt"); 420 421 /* and we now see the rest of the unlink calls on both 422 * directory handles */ 423 notify.smb2.in.file.handle = h1; 424 sleep(3); 425 req = smb2_notify_send(tree1, &(notify.smb2)); 426 status = smb2_notify_recv(req, torture, &(notify.smb2)); 427 CHECK_STATUS(status, NT_STATUS_OK); 428 CHECK_VAL(notify.smb2.out.num_changes, count-1); 429 for (i=0;i<notify.smb2.out.num_changes;i++) { 430 CHECK_VAL(notify.smb2.out.changes[i].action, 431 NOTIFY_ACTION_REMOVED); 432 } 433 notify.smb2.in.file.handle = h2; 434 req = smb2_notify_send(tree1, &(notify.smb2)); 435 status = smb2_notify_recv(req, torture, &(notify.smb2)); 436 CHECK_STATUS(status, NT_STATUS_OK); 437 CHECK_VAL(notify.smb2.out.num_changes, count-1); 438 for (i=0;i<notify.smb2.out.num_changes;i++) { 439 CHECK_VAL(notify.smb2.out.changes[i].action, 440 NOTIFY_ACTION_REMOVED); 441 } 442 443 torture_comment(torture, 444 "Testing if a close() on the dir handle triggers the notify reply\n"); 445 446 notify.smb2.in.file.handle = h1; 447 req = smb2_notify_send(tree1, &(notify.smb2)); 448 449 ZERO_STRUCT(cl.smb2); 450 cl.smb2.level = RAW_CLOSE_SMB2; 451 cl.smb2.in.file.handle = h1; 452 status = smb2_close(tree1, &(cl.smb2)); 453 CHECK_STATUS(status, NT_STATUS_OK); 454 455 status = smb2_notify_recv(req, torture, &(notify.smb2)); 456 CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP); 457 CHECK_VAL(notify.smb2.out.num_changes, 9); 458 459 done: 460 smb2_util_close(tree1, h1); 461 smb2_util_close(tree1, h2); 462 smb2_deltree(tree1, BASEDIR); 211 463 return ret; 212 464 } 465 466 static struct smb2_handle custom_smb2_create(struct smb2_tree *tree, 467 struct torture_context *torture, 468 struct smb2_create *smb2) 469 { 470 struct smb2_handle h1; 471 bool ret = true; 472 NTSTATUS status; 473 smb2_deltree(tree, smb2->in.fname); 474 status = smb2_create(tree, torture, smb2); 475 CHECK_STATUS(status, NT_STATUS_OK); 476 h1 = smb2->out.file.handle; 477 done: 478 return h1; 479 } 480 481 /* 482 testing of recursive change notify 483 */ 484 485 static bool torture_smb2_notify_recursive(struct torture_context *torture, 486 struct smb2_tree *tree1, 487 struct smb2_tree *tree2) 488 { 489 bool ret = true; 490 NTSTATUS status; 491 union smb_notify notify; 492 union smb_open io, io1; 493 union smb_setfileinfo sinfo; 494 struct smb2_handle h1; 495 struct smb2_request *req1, *req2; 496 497 smb2_deltree(tree1, BASEDIR); 498 smb2_util_rmdir(tree1, BASEDIR); 499 500 torture_comment(torture, "TESTING CHANGE NOTIFY WITH RECURSION\n"); 501 502 /* 503 get a handle on the directory 504 */ 505 ZERO_STRUCT(io.smb2); 506 io.generic.level = RAW_OPEN_SMB2; 507 io.smb2.in.create_flags = 0; 508 io.smb2.in.desired_access = SEC_FILE_ALL; 509 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 510 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 511 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 512 NTCREATEX_SHARE_ACCESS_WRITE; 513 io.smb2.in.alloc_size = 0; 514 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 515 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 516 io.smb2.in.security_flags = 0; 517 io.smb2.in.fname = BASEDIR; 518 519 status = smb2_create(tree1, torture, &(io.smb2)); 520 CHECK_STATUS(status, NT_STATUS_OK); 521 h1 = io.smb2.out.file.handle; 522 523 /* ask for a change notify, on file or directory name 524 changes. Setup both with and without recursion */ 525 ZERO_STRUCT(notify.smb2); 526 notify.smb2.level = RAW_NOTIFY_SMB2; 527 notify.smb2.in.buffer_size = 1000; 528 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME | 529 FILE_NOTIFY_CHANGE_ATTRIBUTES | 530 FILE_NOTIFY_CHANGE_CREATION; 531 notify.smb2.in.file.handle = h1; 532 533 notify.smb2.in.recursive = true; 534 req1 = smb2_notify_send(tree1, &(notify.smb2)); 535 smb2_cancel(req1); 536 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 537 CHECK_STATUS(status, NT_STATUS_CANCELLED); 538 539 notify.smb2.in.recursive = false; 540 req2 = smb2_notify_send(tree1, &(notify.smb2)); 541 smb2_cancel(req2); 542 status = smb2_notify_recv(req2, torture, &(notify.smb2)); 543 CHECK_STATUS(status, NT_STATUS_CANCELLED); 544 545 ZERO_STRUCT(io1.smb2); 546 io1.generic.level = RAW_OPEN_SMB2; 547 io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED; 548 io1.smb2.in.desired_access = SEC_RIGHTS_FILE_READ | 549 SEC_RIGHTS_FILE_WRITE| 550 SEC_RIGHTS_FILE_ALL; 551 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 552 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 553 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 554 NTCREATEX_SHARE_ACCESS_WRITE | 555 NTCREATEX_SHARE_ACCESS_DELETE; 556 io1.smb2.in.alloc_size = 0; 557 io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; 558 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 559 io1.smb2.in.security_flags = 0; 560 io1.smb2.in.fname = BASEDIR "\\subdir-name"; 561 status = smb2_create(tree2, torture, &(io1.smb2)); 562 CHECK_STATUS(status, NT_STATUS_OK); 563 smb2_util_close(tree2, io1.smb2.out.file.handle); 564 565 io1.smb2.in.fname = BASEDIR "\\subdir-name\\subname1"; 566 status = smb2_create(tree2, torture, &(io1.smb2)); 567 CHECK_STATUS(status, NT_STATUS_OK); 568 ZERO_STRUCT(sinfo); 569 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; 570 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle; 571 sinfo.rename_information.in.overwrite = 0; 572 sinfo.rename_information.in.root_fid = 0; 573 sinfo.rename_information.in.new_name = 574 BASEDIR "\\subdir-name\\subname1-r"; 575 status = smb2_setinfo_file(tree2, &sinfo); 576 CHECK_STATUS(status, NT_STATUS_OK); 577 578 io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; 579 io1.smb2.in.fname = BASEDIR "\\subdir-name\\subname2"; 580 status = smb2_create(tree2, torture, &(io1.smb2)); 581 CHECK_STATUS(status, NT_STATUS_OK); 582 ZERO_STRUCT(sinfo); 583 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; 584 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle; 585 sinfo.rename_information.in.overwrite = true; 586 sinfo.rename_information.in.root_fid = 0; 587 sinfo.rename_information.in.new_name = BASEDIR "\\subname2-r"; 588 status = smb2_setinfo_file(tree2, &sinfo); 589 CHECK_STATUS(status, NT_STATUS_OK); 590 591 io1.smb2.in.fname = BASEDIR "\\subname2-r"; 592 io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; 593 status = smb2_create(tree2, torture, &(io1.smb2)); 594 CHECK_STATUS(status, NT_STATUS_OK); 595 ZERO_STRUCT(sinfo); 596 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; 597 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle; 598 sinfo.rename_information.in.overwrite = true; 599 sinfo.rename_information.in.root_fid = 0; 600 sinfo.rename_information.in.new_name = BASEDIR "\\subname3-r"; 601 status = smb2_setinfo_file(tree2, &sinfo); 602 CHECK_STATUS(status, NT_STATUS_OK); 603 604 notify.smb2.in.completion_filter = 0; 605 notify.smb2.in.recursive = true; 606 smb_msleep(200); 607 req1 = smb2_notify_send(tree1, &(notify.smb2)); 608 609 status = smb2_util_rmdir(tree2, BASEDIR "\\subdir-name\\subname1-r"); 610 CHECK_STATUS(status, NT_STATUS_OK); 611 status = smb2_util_rmdir(tree2, BASEDIR "\\subdir-name"); 612 CHECK_STATUS(status, NT_STATUS_OK); 613 status = smb2_util_unlink(tree2, BASEDIR "\\subname3-r"); 614 CHECK_STATUS(status, NT_STATUS_OK); 615 616 notify.smb2.in.recursive = false; 617 req2 = smb2_notify_send(tree1, &(notify.smb2)); 618 619 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 620 CHECK_STATUS(status, NT_STATUS_OK); 621 622 CHECK_VAL(notify.smb2.out.num_changes, 9); 623 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED); 624 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 625 CHECK_VAL(notify.smb2.out.changes[1].action, NOTIFY_ACTION_ADDED); 626 CHECK_WIRE_STR(notify.smb2.out.changes[1].name, "subdir-name\\subname1"); 627 CHECK_VAL(notify.smb2.out.changes[2].action, NOTIFY_ACTION_OLD_NAME); 628 CHECK_WIRE_STR(notify.smb2.out.changes[2].name, "subdir-name\\subname1"); 629 CHECK_VAL(notify.smb2.out.changes[3].action, NOTIFY_ACTION_NEW_NAME); 630 CHECK_WIRE_STR(notify.smb2.out.changes[3].name, "subdir-name\\subname1-r"); 631 CHECK_VAL(notify.smb2.out.changes[4].action, NOTIFY_ACTION_ADDED); 632 CHECK_WIRE_STR(notify.smb2.out.changes[4].name, "subdir-name\\subname2"); 633 CHECK_VAL(notify.smb2.out.changes[5].action, NOTIFY_ACTION_REMOVED); 634 CHECK_WIRE_STR(notify.smb2.out.changes[5].name, "subdir-name\\subname2"); 635 CHECK_VAL(notify.smb2.out.changes[6].action, NOTIFY_ACTION_ADDED); 636 CHECK_WIRE_STR(notify.smb2.out.changes[6].name, "subname2-r"); 637 CHECK_VAL(notify.smb2.out.changes[7].action, NOTIFY_ACTION_OLD_NAME); 638 CHECK_WIRE_STR(notify.smb2.out.changes[7].name, "subname2-r"); 639 CHECK_VAL(notify.smb2.out.changes[8].action, NOTIFY_ACTION_NEW_NAME); 640 CHECK_WIRE_STR(notify.smb2.out.changes[8].name, "subname3-r"); 641 642 done: 643 smb2_deltree(tree1, BASEDIR); 644 return ret; 645 } 646 647 /* 648 testing of change notify mask change 649 */ 650 651 static bool torture_smb2_notify_mask_change(struct torture_context *torture, 652 struct smb2_tree *tree1, 653 struct smb2_tree *tree2) 654 { 655 bool ret = true; 656 NTSTATUS status; 657 union smb_notify notify; 658 union smb_open io, io1; 659 struct smb2_handle h1; 660 struct smb2_request *req1, *req2; 661 union smb_setfileinfo sinfo; 662 663 smb2_deltree(tree1, BASEDIR); 664 smb2_util_rmdir(tree1, BASEDIR); 665 666 torture_comment(torture, "TESTING CHANGE NOTIFY WITH MASK CHANGE\n"); 667 668 /* 669 get a handle on the directory 670 */ 671 ZERO_STRUCT(io.smb2); 672 io.generic.level = RAW_OPEN_SMB2; 673 io.smb2.in.create_flags = 0; 674 io.smb2.in.desired_access = SEC_FILE_ALL; 675 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 676 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 677 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 678 NTCREATEX_SHARE_ACCESS_WRITE; 679 io.smb2.in.alloc_size = 0; 680 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 681 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 682 io.smb2.in.security_flags = 0; 683 io.smb2.in.fname = BASEDIR; 684 685 status = smb2_create(tree1, torture, &(io.smb2)); 686 CHECK_STATUS(status, NT_STATUS_OK); 687 h1 = io.smb2.out.file.handle; 688 689 /* ask for a change notify, on file or directory name 690 changes. Setup both with and without recursion */ 691 ZERO_STRUCT(notify.smb2); 692 notify.smb2.level = RAW_NOTIFY_SMB2; 693 notify.smb2.in.buffer_size = 1000; 694 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES; 695 notify.smb2.in.file.handle = h1; 696 697 notify.smb2.in.recursive = true; 698 req1 = smb2_notify_send(tree1, &(notify.smb2)); 699 700 smb2_cancel(req1); 701 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 702 CHECK_STATUS(status, NT_STATUS_CANCELLED); 703 704 705 notify.smb2.in.recursive = false; 706 req2 = smb2_notify_send(tree1, &(notify.smb2)); 707 708 smb2_cancel(req2); 709 status = smb2_notify_recv(req2, torture, &(notify.smb2)); 710 CHECK_STATUS(status, NT_STATUS_CANCELLED); 711 712 notify.smb2.in.recursive = true; 713 req1 = smb2_notify_send(tree1, &(notify.smb2)); 714 715 /* Set to hidden then back again. */ 716 ZERO_STRUCT(io1.smb2); 717 io1.generic.level = RAW_OPEN_SMB2; 718 io1.smb2.in.create_flags = 0; 719 io1.smb2.in.desired_access = SEC_RIGHTS_FILE_READ | 720 SEC_RIGHTS_FILE_WRITE| 721 SEC_RIGHTS_FILE_ALL; 722 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 723 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 724 NTCREATEX_SHARE_ACCESS_WRITE | 725 NTCREATEX_SHARE_ACCESS_DELETE; 726 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 727 io1.smb2.in.security_flags = 0; 728 io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; 729 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 730 io1.smb2.in.fname = BASEDIR "\\tname1"; 731 732 smb2_util_close(tree1, 733 custom_smb2_create(tree1, torture, &(io1.smb2))); 734 status = smb2_util_setatr(tree1, BASEDIR "\\tname1", 735 FILE_ATTRIBUTE_HIDDEN); 736 CHECK_STATUS(status, NT_STATUS_OK); 737 smb2_util_unlink(tree1, BASEDIR "\\tname1"); 738 739 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 740 CHECK_STATUS(status, NT_STATUS_OK); 741 742 CHECK_VAL(notify.smb2.out.num_changes, 1); 743 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED); 744 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "tname1"); 745 746 /* Now try and change the mask to include other events. 747 * This should not work - once the mask is set on a directory 748 * h1 it seems to be fixed until the fnum is closed. */ 749 750 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME | 751 FILE_NOTIFY_CHANGE_ATTRIBUTES | 752 FILE_NOTIFY_CHANGE_CREATION; 753 notify.smb2.in.recursive = true; 754 req1 = smb2_notify_send(tree1, &(notify.smb2)); 755 756 notify.smb2.in.recursive = false; 757 req2 = smb2_notify_send(tree1, &(notify.smb2)); 758 759 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 760 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 761 io1.smb2.in.fname = BASEDIR "\\subdir-name"; 762 status = smb2_create(tree2, torture, &(io1.smb2)); 763 CHECK_STATUS(status, NT_STATUS_OK); 764 smb2_util_close(tree2, io1.smb2.out.file.handle); 765 766 ZERO_STRUCT(sinfo); 767 io1.smb2.in.fname = BASEDIR "\\subdir-name\\subname1"; 768 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 769 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 770 status = smb2_create(tree2, torture, &(io1.smb2)); 771 CHECK_STATUS(status, NT_STATUS_OK); 772 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; 773 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle; 774 sinfo.rename_information.in.overwrite = true; 775 sinfo.rename_information.in.root_fid = 0; 776 sinfo.rename_information.in.new_name = 777 BASEDIR "\\subdir-name\\subname1-r"; 778 status = smb2_setinfo_file(tree2, &sinfo); 779 CHECK_STATUS(status, NT_STATUS_OK); 780 781 io1.smb2.in.fname = BASEDIR "\\subdir-name\\subname2"; 782 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 783 io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; 784 status = smb2_create(tree2, torture, &(io1.smb2)); 785 CHECK_STATUS(status, NT_STATUS_OK); 786 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle; 787 sinfo.rename_information.in.new_name = BASEDIR "\\subname2-r"; 788 status = smb2_setinfo_file(tree2, &sinfo); 789 CHECK_STATUS(status, NT_STATUS_OK); 790 smb2_util_close(tree2, io1.smb2.out.file.handle); 791 792 io1.smb2.in.fname = BASEDIR "\\subname2-r"; 793 io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; 794 status = smb2_create(tree2, torture, &(io1.smb2)); 795 CHECK_STATUS(status, NT_STATUS_OK); 796 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle; 797 sinfo.rename_information.in.new_name = BASEDIR "\\subname3-r"; 798 status = smb2_setinfo_file(tree2, &sinfo); 799 CHECK_STATUS(status, NT_STATUS_OK); 800 smb2_util_close(tree2, io1.smb2.out.file.handle); 801 802 status = smb2_util_rmdir(tree2, BASEDIR "\\subdir-name\\subname1-r"); 803 CHECK_STATUS(status, NT_STATUS_OK); 804 status = smb2_util_rmdir(tree2, BASEDIR "\\subdir-name"); 805 CHECK_STATUS(status, NT_STATUS_OK); 806 status = smb2_util_unlink(tree2, BASEDIR "\\subname3-r"); 807 CHECK_STATUS(status, NT_STATUS_OK); 808 809 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 810 CHECK_STATUS(status, NT_STATUS_OK); 811 812 CHECK_VAL(notify.smb2.out.num_changes, 1); 813 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED); 814 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subname2-r"); 815 816 status = smb2_notify_recv(req2, torture, &(notify.smb2)); 817 CHECK_STATUS(status, NT_STATUS_OK); 818 819 CHECK_VAL(notify.smb2.out.num_changes, 1); 820 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED); 821 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subname3-r"); 822 823 if (!ret) { 824 goto done; 825 } 826 827 done: 828 smb2_deltree(tree1, BASEDIR); 829 return ret; 830 } 831 832 /* 833 testing of mask bits for change notify 834 */ 835 836 static bool torture_smb2_notify_mask(struct torture_context *torture, 837 struct smb2_tree *tree1, 838 struct smb2_tree *tree2) 839 { 840 bool ret = true; 841 NTSTATUS status; 842 union smb_notify notify; 843 union smb_open io, io1; 844 struct smb2_handle h1, h2; 845 uint32_t mask; 846 int i; 847 char c = 1; 848 struct timeval tv; 849 NTTIME t; 850 union smb_setfileinfo sinfo; 851 852 smb2_deltree(tree1, BASEDIR); 853 smb2_util_rmdir(tree1, BASEDIR); 854 855 torture_comment(torture, "TESTING CHANGE NOTIFY COMPLETION FILTERS\n"); 856 857 tv = timeval_current_ofs(1000, 0); 858 t = timeval_to_nttime(&tv); 859 860 /* 861 get a handle on the directory 862 */ 863 ZERO_STRUCT(io.smb2); 864 io.generic.level = RAW_OPEN_SMB2; 865 io.smb2.in.create_flags = 0; 866 io.smb2.in.desired_access = SEC_FILE_ALL; 867 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 868 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 869 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 870 NTCREATEX_SHARE_ACCESS_WRITE; 871 io.smb2.in.alloc_size = 0; 872 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; 873 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 874 io.smb2.in.security_flags = 0; 875 io.smb2.in.fname = BASEDIR; 876 877 ZERO_STRUCT(notify.smb2); 878 notify.smb2.level = RAW_NOTIFY_SMB2; 879 notify.smb2.in.buffer_size = 1000; 880 notify.smb2.in.recursive = true; 881 882 #define NOTIFY_MASK_TEST(test_name, setup, op, cleanup, Action, \ 883 expected, nchanges) \ 884 do { \ 885 do { for (mask=i=0;i<32;i++) { \ 886 struct smb2_request *req; \ 887 status = smb2_create(tree1, torture, &(io.smb2)); \ 888 CHECK_STATUS(status, NT_STATUS_OK); \ 889 h1 = io.smb2.out.file.handle; \ 890 setup \ 891 notify.smb2.in.file.handle = h1; \ 892 notify.smb2.in.completion_filter = (1<<i); \ 893 /* cancel initial requests so the buffer is setup */ \ 894 req = smb2_notify_send(tree1, &(notify.smb2)); \ 895 smb2_cancel(req); \ 896 status = smb2_notify_recv(req, torture, &(notify.smb2)); \ 897 CHECK_STATUS(status, NT_STATUS_CANCELLED); \ 898 /* send the change notify request */ \ 899 req = smb2_notify_send(tree1, &(notify.smb2)); \ 900 op \ 901 smb_msleep(200); smb2_cancel(req); \ 902 status = smb2_notify_recv(req, torture, &(notify.smb2)); \ 903 cleanup \ 904 smb2_util_close(tree1, h1); \ 905 if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) continue; \ 906 CHECK_STATUS(status, NT_STATUS_OK); \ 907 /* special case to cope with file rename behaviour */ \ 908 if (nchanges == 2 && notify.smb2.out.num_changes == 1 && \ 909 notify.smb2.out.changes[0].action == \ 910 NOTIFY_ACTION_MODIFIED && \ 911 ((expected) & FILE_NOTIFY_CHANGE_ATTRIBUTES) && \ 912 Action == NOTIFY_ACTION_OLD_NAME) { \ 913 torture_comment(torture, \ 914 "(rename file special handling OK)\n"); \ 915 } else if (nchanges != notify.smb2.out.num_changes) { \ 916 torture_result(torture, TORTURE_FAIL, \ 917 "ERROR: nchanges=%d expected=%d "\ 918 "action=%d filter=0x%08x\n", \ 919 notify.smb2.out.num_changes, \ 920 nchanges, \ 921 notify.smb2.out.changes[0].action, \ 922 notify.smb2.in.completion_filter); \ 923 ret = false; \ 924 } else if (notify.smb2.out.changes[0].action != Action) { \ 925 torture_result(torture, TORTURE_FAIL, \ 926 "ERROR: nchanges=%d action=%d " \ 927 "expectedAction=%d filter=0x%08x\n", \ 928 notify.smb2.out.num_changes, \ 929 notify.smb2.out.changes[0].action, \ 930 Action, \ 931 notify.smb2.in.completion_filter); \ 932 ret = false; \ 933 } else if (strcmp(notify.smb2.out.changes[0].name.s, \ 934 "tname1") != 0) { \ 935 torture_result(torture, TORTURE_FAIL, \ 936 "ERROR: nchanges=%d action=%d " \ 937 "filter=0x%08x name=%s\n", \ 938 notify.smb2.out.num_changes, \ 939 notify.smb2.out.changes[0].action, \ 940 notify.smb2.in.completion_filter, \ 941 notify.smb2.out.changes[0].name.s); \ 942 ret = false; \ 943 } \ 944 mask |= (1<<i); \ 945 } \ 946 } while (0); \ 947 } while (0); 948 949 torture_comment(torture, "Testing mkdir\n"); 950 NOTIFY_MASK_TEST("Testing mkdir",;, 951 smb2_util_mkdir(tree2, BASEDIR "\\tname1");, 952 smb2_util_rmdir(tree2, BASEDIR "\\tname1");, 953 NOTIFY_ACTION_ADDED, 954 FILE_NOTIFY_CHANGE_DIR_NAME, 1); 955 956 torture_comment(torture, "Testing create file\n"); 957 ZERO_STRUCT(io1.smb2); 958 io1.generic.level = RAW_OPEN_SMB2; 959 io1.smb2.in.create_flags = 0; 960 io1.smb2.in.desired_access = SEC_FILE_ALL; 961 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 962 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 963 NTCREATEX_SHARE_ACCESS_WRITE; 964 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 965 io1.smb2.in.security_flags = 0; 966 io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; 967 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 968 io1.smb2.in.fname = BASEDIR "\\tname1"; 969 970 NOTIFY_MASK_TEST("Testing create file",;, 971 smb2_util_close(tree2, custom_smb2_create(tree2, 972 torture, &(io1.smb2)));, 973 smb2_util_unlink(tree2, BASEDIR "\\tname1");, 974 NOTIFY_ACTION_ADDED, 975 FILE_NOTIFY_CHANGE_FILE_NAME, 1); 976 977 torture_comment(torture, "Testing unlink\n"); 978 NOTIFY_MASK_TEST("Testing unlink", 979 smb2_util_close(tree2, custom_smb2_create(tree2, 980 torture, &(io1.smb2)));, 981 smb2_util_unlink(tree2, BASEDIR "\\tname1");, 982 ;, 983 NOTIFY_ACTION_REMOVED, 984 FILE_NOTIFY_CHANGE_FILE_NAME, 1); 985 986 torture_comment(torture, "Testing rmdir\n"); 987 NOTIFY_MASK_TEST("Testing rmdir", 988 smb2_util_mkdir(tree2, BASEDIR "\\tname1");, 989 smb2_util_rmdir(tree2, BASEDIR "\\tname1");, 990 ;, 991 NOTIFY_ACTION_REMOVED, 992 FILE_NOTIFY_CHANGE_DIR_NAME, 1); 993 994 torture_comment(torture, "Testing rename file\n"); 995 ZERO_STRUCT(sinfo); 996 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; 997 sinfo.rename_information.in.file.handle = h1; 998 sinfo.rename_information.in.overwrite = true; 999 sinfo.rename_information.in.root_fid = 0; 1000 sinfo.rename_information.in.new_name = BASEDIR "\\tname2"; 1001 NOTIFY_MASK_TEST("Testing rename file", 1002 smb2_util_close(tree2, custom_smb2_create(tree2, 1003 torture, &(io1.smb2)));, 1004 smb2_setinfo_file(tree2, &sinfo);, 1005 smb2_util_unlink(tree2, BASEDIR "\\tname2");, 1006 NOTIFY_ACTION_OLD_NAME, 1007 FILE_NOTIFY_CHANGE_FILE_NAME, 2); 1008 1009 torture_comment(torture, "Testing rename dir\n"); 1010 ZERO_STRUCT(sinfo); 1011 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; 1012 sinfo.rename_information.in.file.handle = h1; 1013 sinfo.rename_information.in.overwrite = true; 1014 sinfo.rename_information.in.root_fid = 0; 1015 sinfo.rename_information.in.new_name = BASEDIR "\\tname2"; 1016 NOTIFY_MASK_TEST("Testing rename dir", 1017 smb2_util_mkdir(tree2, BASEDIR "\\tname1");, 1018 smb2_setinfo_file(tree2, &sinfo);, 1019 smb2_util_rmdir(tree2, BASEDIR "\\tname2");, 1020 NOTIFY_ACTION_OLD_NAME, 1021 FILE_NOTIFY_CHANGE_DIR_NAME, 2); 1022 1023 torture_comment(torture, "Testing set path attribute\n"); 1024 NOTIFY_MASK_TEST("Testing set path attribute", 1025 smb2_util_close(tree2, custom_smb2_create(tree2, 1026 torture, &(io.smb2)));, 1027 smb2_util_setatr(tree2, BASEDIR "\\tname1", 1028 FILE_ATTRIBUTE_HIDDEN);, 1029 smb2_util_unlink(tree2, BASEDIR "\\tname1");, 1030 NOTIFY_ACTION_MODIFIED, 1031 FILE_NOTIFY_CHANGE_ATTRIBUTES, 1); 1032 1033 torture_comment(torture, "Testing set path write time\n"); 1034 ZERO_STRUCT(sinfo); 1035 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION; 1036 sinfo.generic.in.file.handle = h1; 1037 sinfo.basic_info.in.write_time = 1000; 1038 NOTIFY_MASK_TEST("Testing set path write time", 1039 smb2_util_close(tree2, custom_smb2_create(tree2, 1040 torture, &(io1.smb2)));, 1041 smb2_setinfo_file(tree2, &sinfo);, 1042 smb2_util_unlink(tree2, BASEDIR "\\tname1");, 1043 NOTIFY_ACTION_MODIFIED, 1044 FILE_NOTIFY_CHANGE_LAST_WRITE, 1); 1045 1046 if (torture_setting_bool(torture, "samba3", false)) { 1047 torture_comment(torture, 1048 "Samba3 does not yet support create times " 1049 "everywhere\n"); 1050 } 1051 else { 1052 ZERO_STRUCT(sinfo); 1053 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION; 1054 sinfo.generic.in.file.handle = h1; 1055 sinfo.basic_info.in.create_time = 0; 1056 torture_comment(torture, "Testing set file create time\n"); 1057 NOTIFY_MASK_TEST("Testing set file create time", 1058 smb2_create_complex_file(tree2, 1059 BASEDIR "\\tname1", &h2);, 1060 smb2_setinfo_file(tree2, &sinfo);, 1061 (smb2_util_close(tree2, h2), 1062 smb2_util_unlink(tree2, BASEDIR "\\tname1"));, 1063 NOTIFY_ACTION_MODIFIED, 1064 FILE_NOTIFY_CHANGE_CREATION, 1); 1065 } 1066 1067 ZERO_STRUCT(sinfo); 1068 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION; 1069 sinfo.generic.in.file.handle = h1; 1070 sinfo.basic_info.in.access_time = 0; 1071 torture_comment(torture, "Testing set file access time\n"); 1072 NOTIFY_MASK_TEST("Testing set file access time", 1073 smb2_create_complex_file(tree2, BASEDIR "\\tname1", &h2);, 1074 smb2_setinfo_file(tree2, &sinfo);, 1075 (smb2_util_close(tree2, h2), 1076 smb2_util_unlink(tree2, BASEDIR "\\tname1"));, 1077 NOTIFY_ACTION_MODIFIED, 1078 FILE_NOTIFY_CHANGE_LAST_ACCESS, 1); 1079 1080 ZERO_STRUCT(sinfo); 1081 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION; 1082 sinfo.generic.in.file.handle = h1; 1083 sinfo.basic_info.in.change_time = 0; 1084 torture_comment(torture, "Testing set file change time\n"); 1085 NOTIFY_MASK_TEST("Testing set file change time", 1086 smb2_create_complex_file(tree2, BASEDIR "\\tname1", &h2);, 1087 smb2_setinfo_file(tree2, &sinfo);, 1088 (smb2_util_close(tree2, h2), 1089 smb2_util_unlink(tree2, BASEDIR "\\tname1"));, 1090 NOTIFY_ACTION_MODIFIED, 1091 0, 1); 1092 1093 1094 torture_comment(torture, "Testing write\n"); 1095 NOTIFY_MASK_TEST("Testing write", 1096 smb2_create_complex_file(tree2, BASEDIR "\\tname1", &h2);, 1097 smb2_util_write(tree2, h2, &c, 10000, 1);, 1098 (smb2_util_close(tree2, h2), 1099 smb2_util_unlink(tree2, BASEDIR "\\tname1"));, 1100 NOTIFY_ACTION_MODIFIED, 1101 0, 1); 1102 1103 done: 1104 smb2_deltree(tree1, BASEDIR); 1105 return ret; 1106 } 1107 1108 /* 1109 basic testing of change notify on files 1110 */ 1111 static bool torture_smb2_notify_file(struct torture_context *torture, 1112 struct smb2_tree *tree) 1113 { 1114 NTSTATUS status; 1115 bool ret = true; 1116 union smb_open io; 1117 union smb_close cl; 1118 union smb_notify notify; 1119 struct smb2_request *req; 1120 struct smb2_handle h1; 1121 const char *fname = BASEDIR "\\file.txt"; 1122 1123 smb2_deltree(tree, BASEDIR); 1124 smb2_util_rmdir(tree, BASEDIR); 1125 1126 torture_comment(torture, "TESTING CHANGE NOTIFY ON FILES\n"); 1127 status = torture_smb2_testdir(tree, BASEDIR, &h1); 1128 CHECK_STATUS(status, NT_STATUS_OK); 1129 1130 ZERO_STRUCT(io.smb2); 1131 io.generic.level = RAW_OPEN_SMB2; 1132 io.smb2.in.create_flags = 0; 1133 io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; 1134 io.smb2.in.create_options = 0; 1135 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1136 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1137 NTCREATEX_SHARE_ACCESS_WRITE; 1138 io.smb2.in.alloc_size = 0; 1139 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 1140 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1141 io.smb2.in.security_flags = 0; 1142 io.smb2.in.fname = fname; 1143 status = smb2_create(tree, torture, &(io.smb2)); 1144 CHECK_STATUS(status, NT_STATUS_OK); 1145 h1 = io.smb2.out.file.handle; 1146 1147 /* ask for a change notify, 1148 on file or directory name changes */ 1149 ZERO_STRUCT(notify.smb2); 1150 notify.smb2.level = RAW_NOTIFY_SMB2; 1151 notify.smb2.in.file.handle = h1; 1152 notify.smb2.in.buffer_size = 1000; 1153 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_STREAM_NAME; 1154 notify.smb2.in.recursive = false; 1155 1156 torture_comment(torture, 1157 "Testing if notifies on file handles are invalid (should be)\n"); 1158 1159 req = smb2_notify_send(tree, &(notify.smb2)); 1160 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1161 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); 1162 1163 ZERO_STRUCT(cl.smb2); 1164 cl.close.level = RAW_CLOSE_SMB2; 1165 cl.close.in.file.handle = h1; 1166 status = smb2_close(tree, &(cl.smb2)); 1167 CHECK_STATUS(status, NT_STATUS_OK); 1168 1169 status = smb2_util_unlink(tree, fname); 1170 CHECK_STATUS(status, NT_STATUS_OK); 1171 1172 done: 1173 smb2_deltree(tree, BASEDIR); 1174 return ret; 1175 } 1176 /* 1177 basic testing of change notifies followed by a tdis 1178 */ 1179 1180 static bool torture_smb2_notify_tree_disconnect( 1181 struct torture_context *torture, 1182 struct smb2_tree *tree) 1183 { 1184 bool ret = true; 1185 NTSTATUS status; 1186 union smb_notify notify; 1187 union smb_open io; 1188 struct smb2_handle h1; 1189 struct smb2_request *req; 1190 1191 smb2_deltree(tree, BASEDIR); 1192 smb2_util_rmdir(tree, BASEDIR); 1193 1194 torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY " 1195 "TREE-DISCONNECT\n"); 1196 1197 /* 1198 get a handle on the directory 1199 */ 1200 ZERO_STRUCT(io.smb2); 1201 io.generic.level = RAW_OPEN_SMB2; 1202 io.smb2.in.create_flags = 0; 1203 io.smb2.in.desired_access = SEC_FILE_ALL; 1204 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1205 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1206 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1207 NTCREATEX_SHARE_ACCESS_WRITE; 1208 io.smb2.in.alloc_size = 0; 1209 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 1210 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1211 io.smb2.in.security_flags = 0; 1212 io.smb2.in.fname = BASEDIR; 1213 1214 status = smb2_create(tree, torture, &(io.smb2)); 1215 CHECK_STATUS(status, NT_STATUS_OK); 1216 h1 = io.smb2.out.file.handle; 1217 1218 /* ask for a change notify, 1219 on file or directory name changes */ 1220 ZERO_STRUCT(notify.smb2); 1221 notify.smb2.level = RAW_NOTIFY_SMB2; 1222 notify.smb2.in.buffer_size = 1000; 1223 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; 1224 notify.smb2.in.file.handle = h1; 1225 notify.smb2.in.recursive = true; 1226 1227 req = smb2_notify_send(tree, &(notify.smb2)); 1228 smb2_cancel(req); 1229 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1230 1231 status = smb2_tdis(tree); 1232 CHECK_STATUS(status, NT_STATUS_OK); 1233 1234 req = smb2_notify_send(tree, &(notify.smb2)); 1235 1236 smb2_notify_recv(req, torture, &(notify.smb2)); 1237 CHECK_STATUS(status, NT_STATUS_OK); 1238 CHECK_VAL(notify.smb2.out.num_changes, 0); 1239 1240 done: 1241 smb2_deltree(tree, BASEDIR); 1242 return ret; 1243 } 1244 1245 /* 1246 basic testing of change notifies followed by a ulogoff 1247 */ 1248 1249 static bool torture_smb2_notify_ulogoff(struct torture_context *torture, 1250 struct smb2_tree *tree1, 1251 struct smb2_tree *tree2) 1252 { 1253 bool ret = true; 1254 NTSTATUS status; 1255 union smb_notify notify; 1256 union smb_open io; 1257 struct smb2_handle h1; 1258 struct smb2_request *req; 1259 1260 smb2_deltree(tree1, BASEDIR); 1261 smb2_util_rmdir(tree1, BASEDIR); 1262 1263 torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n"); 1264 1265 /* 1266 get a handle on the directory 1267 */ 1268 ZERO_STRUCT(io.smb2); 1269 io.generic.level = RAW_OPEN_SMB2; 1270 io.smb2.in.create_flags = 0; 1271 io.smb2.in.desired_access = SEC_FILE_ALL; 1272 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1273 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1274 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1275 NTCREATEX_SHARE_ACCESS_WRITE; 1276 io.smb2.in.alloc_size = 0; 1277 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 1278 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1279 io.smb2.in.security_flags = 0; 1280 io.smb2.in.fname = BASEDIR; 1281 1282 status = smb2_create(tree2, torture, &(io.smb2)); 1283 CHECK_STATUS(status, NT_STATUS_OK); 1284 1285 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; 1286 status = smb2_create(tree2, torture, &(io.smb2)); 1287 CHECK_STATUS(status, NT_STATUS_OK); 1288 h1 = io.smb2.out.file.handle; 1289 1290 /* ask for a change notify, 1291 on file or directory name changes */ 1292 ZERO_STRUCT(notify.smb2); 1293 notify.smb2.level = RAW_NOTIFY_SMB2; 1294 notify.smb2.in.buffer_size = 1000; 1295 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; 1296 notify.smb2.in.file.handle = h1; 1297 notify.smb2.in.recursive = true; 1298 1299 req = smb2_notify_send(tree1, &(notify.smb2)); 1300 1301 status = smb2_logoff(tree2->session); 1302 CHECK_STATUS(status, NT_STATUS_OK); 1303 1304 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1305 CHECK_VAL(notify.smb2.out.num_changes, 0); 1306 1307 done: 1308 smb2_deltree(tree1, BASEDIR); 1309 return ret; 1310 } 1311 1312 static void tcp_dis_handler(struct smb2_transport *t, void *p) 1313 { 1314 struct smb2_tree *tree = (struct smb2_tree *)p; 1315 smb2_transport_dead(tree->session->transport, 1316 NT_STATUS_LOCAL_DISCONNECT); 1317 t = NULL; 1318 tree = NULL; 1319 } 1320 1321 /* 1322 basic testing of change notifies followed by tcp disconnect 1323 */ 1324 1325 static bool torture_smb2_notify_tcp_disconnect( 1326 struct torture_context *torture, 1327 struct smb2_tree *tree) 1328 { 1329 bool ret = true; 1330 NTSTATUS status; 1331 union smb_notify notify; 1332 union smb_open io; 1333 struct smb2_handle h1; 1334 struct smb2_request *req; 1335 1336 smb2_deltree(tree, BASEDIR); 1337 smb2_util_rmdir(tree, BASEDIR); 1338 1339 torture_comment(torture, 1340 "TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n"); 1341 1342 /* 1343 get a handle on the directory 1344 */ 1345 ZERO_STRUCT(io.smb2); 1346 io.generic.level = RAW_OPEN_SMB2; 1347 io.smb2.in.create_flags = 0; 1348 io.smb2.in.desired_access = SEC_FILE_ALL; 1349 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1350 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1351 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1352 NTCREATEX_SHARE_ACCESS_WRITE; 1353 io.smb2.in.alloc_size = 0; 1354 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; 1355 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1356 io.smb2.in.security_flags = 0; 1357 io.smb2.in.fname = BASEDIR; 1358 1359 status = smb2_create(tree, torture, &(io.smb2)); 1360 CHECK_STATUS(status, NT_STATUS_OK); 1361 h1 = io.smb2.out.file.handle; 1362 1363 /* ask for a change notify, 1364 on file or directory name changes */ 1365 ZERO_STRUCT(notify.smb2); 1366 notify.smb2.level = RAW_NOTIFY_SMB2; 1367 notify.smb2.in.buffer_size = 1000; 1368 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; 1369 notify.smb2.in.file.handle = h1; 1370 notify.smb2.in.recursive = true; 1371 1372 req = smb2_notify_send(tree, &(notify.smb2)); 1373 smb2_cancel(req); 1374 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1375 CHECK_STATUS(status, NT_STATUS_CANCELLED); 1376 1377 notify.smb2.in.recursive = true; 1378 req = smb2_notify_send(tree, &(notify.smb2)); 1379 smb2_transport_idle_handler(tree->session->transport, 1380 tcp_dis_handler, 250, tree); 1381 tree = NULL; 1382 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1383 CHECK_STATUS(status, NT_STATUS_LOCAL_DISCONNECT); 1384 1385 done: 1386 return ret; 1387 } 1388 1389 /* 1390 test setting up two change notify requests on one handle 1391 */ 1392 1393 static bool torture_smb2_notify_double(struct torture_context *torture, 1394 struct smb2_tree *tree1, 1395 struct smb2_tree *tree2) 1396 { 1397 bool ret = true; 1398 NTSTATUS status; 1399 union smb_notify notify; 1400 union smb_open io; 1401 struct smb2_handle h1; 1402 struct smb2_request *req1, *req2; 1403 1404 smb2_deltree(tree1, BASEDIR); 1405 smb2_util_rmdir(tree1, BASEDIR); 1406 1407 torture_comment(torture, 1408 "TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n"); 1409 1410 /* 1411 get a handle on the directory 1412 */ 1413 ZERO_STRUCT(io.smb2); 1414 io.generic.level = RAW_OPEN_SMB2; 1415 io.smb2.in.create_flags = 0; 1416 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ| 1417 SEC_RIGHTS_FILE_WRITE| 1418 SEC_RIGHTS_FILE_ALL; 1419 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1420 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1421 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1422 NTCREATEX_SHARE_ACCESS_WRITE; 1423 io.smb2.in.alloc_size = 0; 1424 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 1425 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1426 io.smb2.in.security_flags = 0; 1427 io.smb2.in.fname = BASEDIR; 1428 1429 status = smb2_create(tree1, torture, &(io.smb2)); 1430 CHECK_STATUS(status, NT_STATUS_OK); 1431 h1 = io.smb2.out.file.handle; 1432 1433 /* ask for a change notify, 1434 on file or directory name changes */ 1435 ZERO_STRUCT(notify.smb2); 1436 notify.smb2.level = RAW_NOTIFY_SMB2; 1437 notify.smb2.in.buffer_size = 1000; 1438 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; 1439 notify.smb2.in.file.handle = h1; 1440 notify.smb2.in.recursive = true; 1441 1442 req1 = smb2_notify_send(tree1, &(notify.smb2)); 1443 smb2_cancel(req1); 1444 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 1445 CHECK_STATUS(status, NT_STATUS_CANCELLED); 1446 1447 req2 = smb2_notify_send(tree1, &(notify.smb2)); 1448 smb2_cancel(req2); 1449 status = smb2_notify_recv(req2, torture, &(notify.smb2)); 1450 CHECK_STATUS(status, NT_STATUS_CANCELLED); 1451 1452 smb2_util_mkdir(tree2, BASEDIR "\\subdir-name"); 1453 req1 = smb2_notify_send(tree1, &(notify.smb2)); 1454 req2 = smb2_notify_send(tree1, &(notify.smb2)); 1455 1456 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 1457 CHECK_STATUS(status, NT_STATUS_OK); 1458 CHECK_VAL(notify.smb2.out.num_changes, 1); 1459 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 1460 1461 smb2_util_mkdir(tree2, BASEDIR "\\subdir-name2"); 1462 1463 status = smb2_notify_recv(req2, torture, &(notify.smb2)); 1464 CHECK_STATUS(status, NT_STATUS_OK); 1465 CHECK_VAL(notify.smb2.out.num_changes, 1); 1466 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name2"); 1467 1468 done: 1469 smb2_deltree(tree1, BASEDIR); 1470 return ret; 1471 } 1472 1473 1474 /* 1475 test multiple change notifies at different depths and with/without recursion 1476 */ 1477 1478 static bool torture_smb2_notify_tree(struct torture_context *torture, 1479 struct smb2_tree *tree) 1480 { 1481 bool ret = true; 1482 union smb_notify notify; 1483 union smb_open io; 1484 struct smb2_request *req; 1485 struct timeval tv; 1486 struct { 1487 const char *path; 1488 bool recursive; 1489 uint32_t filter; 1490 int expected; 1491 struct smb2_handle h1; 1492 int counted; 1493 } dirs[] = { 1494 {BASEDIR "\\abc", true, FILE_NOTIFY_CHANGE_NAME, 30 }, 1495 {BASEDIR "\\zqy", true, FILE_NOTIFY_CHANGE_NAME, 8 }, 1496 {BASEDIR "\\atsy", true, FILE_NOTIFY_CHANGE_NAME, 4 }, 1497 {BASEDIR "\\abc\\foo", true, FILE_NOTIFY_CHANGE_NAME, 2 }, 1498 {BASEDIR "\\abc\\blah", true, FILE_NOTIFY_CHANGE_NAME, 13 }, 1499 {BASEDIR "\\abc\\blah", false, FILE_NOTIFY_CHANGE_NAME, 7 }, 1500 {BASEDIR "\\abc\\blah\\a", true, FILE_NOTIFY_CHANGE_NAME, 2 }, 1501 {BASEDIR "\\abc\\blah\\b", true, FILE_NOTIFY_CHANGE_NAME, 2 }, 1502 {BASEDIR "\\abc\\blah\\c", true, FILE_NOTIFY_CHANGE_NAME, 2 }, 1503 {BASEDIR "\\abc\\fooblah", true, FILE_NOTIFY_CHANGE_NAME, 2 }, 1504 {BASEDIR "\\zqy\\xx", true, FILE_NOTIFY_CHANGE_NAME, 2 }, 1505 {BASEDIR "\\zqy\\yyy", true, FILE_NOTIFY_CHANGE_NAME, 2 }, 1506 {BASEDIR "\\zqy\\..", true, FILE_NOTIFY_CHANGE_NAME, 40 }, 1507 {BASEDIR, true, FILE_NOTIFY_CHANGE_NAME, 40 }, 1508 {BASEDIR, false,FILE_NOTIFY_CHANGE_NAME, 6 }, 1509 {BASEDIR "\\atsy", false,FILE_NOTIFY_CHANGE_NAME, 4 }, 1510 {BASEDIR "\\abc", true, FILE_NOTIFY_CHANGE_NAME, 24 }, 1511 {BASEDIR "\\abc", false,FILE_NOTIFY_CHANGE_FILE_NAME, 0 }, 1512 {BASEDIR "\\abc", true, FILE_NOTIFY_CHANGE_FILE_NAME, 0 }, 1513 {BASEDIR "\\abc", true, FILE_NOTIFY_CHANGE_NAME, 24 }, 1514 }; 1515 int i; 1516 NTSTATUS status; 1517 bool all_done = false; 1518 1519 smb2_deltree(tree, BASEDIR); 1520 smb2_util_rmdir(tree, BASEDIR); 1521 1522 torture_comment(torture, "TESTING NOTIFY FOR DIFFERENT DEPTHS\n"); 1523 1524 ZERO_STRUCT(io.smb2); 1525 io.generic.level = RAW_OPEN_SMB2; 1526 io.smb2.in.create_flags = 0; 1527 io.smb2.in.desired_access = SEC_FILE_ALL; 1528 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1529 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1530 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1531 NTCREATEX_SHARE_ACCESS_WRITE; 1532 io.smb2.in.alloc_size = 0; 1533 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; 1534 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1535 io.smb2.in.security_flags = 0; 1536 io.smb2.in.fname = BASEDIR; 1537 status = smb2_create(tree, torture, &(io.smb2)); 1538 CHECK_STATUS(status, NT_STATUS_OK); 1539 1540 ZERO_STRUCT(notify.smb2); 1541 notify.smb2.level = RAW_NOTIFY_SMB2; 1542 notify.smb2.in.buffer_size = 20000; 1543 1544 /* 1545 setup the directory tree, and the notify buffer on each directory 1546 */ 1547 for (i=0;i<ARRAY_SIZE(dirs);i++) { 1548 io.smb2.in.fname = dirs[i].path; 1549 status = smb2_create(tree, torture, &(io.smb2)); 1550 CHECK_STATUS(status, NT_STATUS_OK); 1551 dirs[i].h1 = io.smb2.out.file.handle; 1552 1553 notify.smb2.in.completion_filter = dirs[i].filter; 1554 notify.smb2.in.file.handle = dirs[i].h1; 1555 notify.smb2.in.recursive = dirs[i].recursive; 1556 req = smb2_notify_send(tree, &(notify.smb2)); 1557 smb2_cancel(req); 1558 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1559 CHECK_STATUS(status, NT_STATUS_CANCELLED); 1560 } 1561 1562 /* trigger 2 events in each dir */ 1563 for (i=0;i<ARRAY_SIZE(dirs);i++) { 1564 char *path = talloc_asprintf(torture, "%s\\test.dir", 1565 dirs[i].path); 1566 smb2_util_mkdir(tree, path); 1567 smb2_util_rmdir(tree, path); 1568 talloc_free(path); 1569 } 1570 1571 /* give a bit of time for the events to propogate */ 1572 tv = timeval_current(); 1573 1574 do { 1575 /* count events that have happened in each dir */ 1576 for (i=0;i<ARRAY_SIZE(dirs);i++) { 1577 notify.smb2.in.file.handle = dirs[i].h1; 1578 req = smb2_notify_send(tree, &(notify.smb2)); 1579 smb2_cancel(req); 1580 notify.smb2.out.num_changes = 0; 1581 status = smb2_notify_recv(req, torture, 1582 &(notify.smb2)); 1583 dirs[i].counted += notify.smb2.out.num_changes; 1584 } 1585 1586 all_done = true; 1587 1588 for (i=0;i<ARRAY_SIZE(dirs);i++) { 1589 if (dirs[i].counted != dirs[i].expected) { 1590 all_done = false; 1591 } 1592 } 1593 } while (!all_done && timeval_elapsed(&tv) < 20); 1594 1595 torture_comment(torture, "took %.4f seconds to propogate all events\n", 1596 timeval_elapsed(&tv)); 1597 1598 for (i=0;i<ARRAY_SIZE(dirs);i++) { 1599 if (dirs[i].counted != dirs[i].expected) { 1600 torture_comment(torture, 1601 "ERROR: i=%d expected %d got %d for '%s'\n", 1602 i, dirs[i].expected, dirs[i].counted, 1603 dirs[i].path); 1604 ret = false; 1605 } 1606 } 1607 1608 /* 1609 run from the back, closing and deleting 1610 */ 1611 for (i=ARRAY_SIZE(dirs)-1;i>=0;i--) { 1612 smb2_util_close(tree, dirs[i].h1); 1613 smb2_util_rmdir(tree, dirs[i].path); 1614 } 1615 1616 done: 1617 smb2_deltree(tree, BASEDIR); 1618 smb2_util_rmdir(tree, BASEDIR); 1619 return ret; 1620 } 1621 1622 /* 1623 Test response when cached server events exceed single NT NOTFIY response 1624 packet size. 1625 */ 1626 1627 static bool torture_smb2_notify_overflow(struct torture_context *torture, 1628 struct smb2_tree *tree) 1629 { 1630 bool ret = true; 1631 NTSTATUS status; 1632 union smb_notify notify; 1633 union smb_open io; 1634 struct smb2_handle h1, h2; 1635 int count = 100; 1636 struct smb2_request *req1; 1637 int i; 1638 1639 smb2_deltree(tree, BASEDIR); 1640 smb2_util_rmdir(tree, BASEDIR); 1641 1642 torture_comment(torture, "TESTING CHANGE NOTIFY EVENT OVERFLOW\n"); 1643 1644 /* get a handle on the directory */ 1645 ZERO_STRUCT(io.smb2); 1646 io.generic.level = RAW_OPEN_SMB2; 1647 io.smb2.in.create_flags = 0; 1648 io.smb2.in.desired_access = SEC_FILE_ALL; 1649 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1650 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1651 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1652 NTCREATEX_SHARE_ACCESS_WRITE; 1653 io.smb2.in.alloc_size = 0; 1654 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 1655 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1656 io.smb2.in.security_flags = 0; 1657 io.smb2.in.fname = BASEDIR; 1658 1659 status = smb2_create(tree, torture, &(io.smb2)); 1660 CHECK_STATUS(status, NT_STATUS_OK); 1661 h1 = io.smb2.out.file.handle; 1662 1663 /* ask for a change notify, on name changes. */ 1664 ZERO_STRUCT(notify.smb2); 1665 notify.smb2.level = RAW_NOTIFY_NTTRANS; 1666 notify.smb2.in.buffer_size = 1000; 1667 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; 1668 notify.smb2.in.file.handle = h1; 1669 1670 notify.smb2.in.recursive = true; 1671 req1 = smb2_notify_send(tree, &(notify.smb2)); 1672 1673 /* cancel initial requests so the buffer is setup */ 1674 smb2_cancel(req1); 1675 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 1676 CHECK_STATUS(status, NT_STATUS_CANCELLED); 1677 1678 /* open a lot of files, filling up the server side notify buffer */ 1679 torture_comment(torture, 1680 "Testing overflowed buffer notify on create of %d files\n", 1681 count); 1682 1683 for (i=0;i<count;i++) { 1684 char *fname = talloc_asprintf(torture, 1685 BASEDIR "\\test%d.txt", i); 1686 union smb_open io1; 1687 ZERO_STRUCT(io1.smb2); 1688 io1.generic.level = RAW_OPEN_SMB2; 1689 io1.smb2.in.create_flags = 0; 1690 io1.smb2.in.desired_access = SEC_FILE_ALL; 1691 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1692 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1693 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1694 NTCREATEX_SHARE_ACCESS_WRITE; 1695 io1.smb2.in.alloc_size = 0; 1696 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; 1697 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1698 io1.smb2.in.security_flags = 0; 1699 io1.smb2.in.fname = fname; 1700 1701 h2 = custom_smb2_create(tree, torture, &(io1.smb2)); 1702 talloc_free(fname); 1703 smb2_util_close(tree, h2); 1704 } 1705 1706 req1 = smb2_notify_send(tree, &(notify.smb2)); 1707 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 1708 CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR); 1709 CHECK_VAL(notify.smb2.out.num_changes, 0); 1710 1711 done: 1712 smb2_deltree(tree, BASEDIR); 1713 return ret; 1714 } 1715 1716 /* 1717 Test if notifications are returned for changes to the base directory. 1718 They shouldn't be. 1719 */ 1720 1721 static bool torture_smb2_notify_basedir(struct torture_context *torture, 1722 struct smb2_tree *tree1, 1723 struct smb2_tree *tree2) 1724 { 1725 bool ret = true; 1726 NTSTATUS status; 1727 union smb_notify notify; 1728 union smb_open io; 1729 struct smb2_handle h1; 1730 struct smb2_request *req1; 1731 1732 smb2_deltree(tree1, BASEDIR); 1733 smb2_util_rmdir(tree1, BASEDIR); 1734 1735 torture_comment(torture, "TESTING CHANGE NOTIFY BASEDIR EVENTS\n"); 1736 1737 /* get a handle on the directory */ 1738 ZERO_STRUCT(io.smb2); 1739 io.generic.level = RAW_OPEN_SMB2; 1740 io.smb2.in.create_flags = 0; 1741 io.smb2.in.desired_access = SEC_FILE_ALL; 1742 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1743 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; 1744 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1745 NTCREATEX_SHARE_ACCESS_WRITE; 1746 io.smb2.in.alloc_size = 0; 1747 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; 1748 io.smb2.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS; 1749 io.smb2.in.security_flags = 0; 1750 io.smb2.in.fname = BASEDIR; 1751 1752 status = smb2_create(tree1, torture, &(io.smb2)); 1753 CHECK_STATUS(status, NT_STATUS_OK); 1754 h1 = io.smb2.out.file.handle; 1755 1756 /* create a test file that will also be modified */ 1757 io.smb2.in.fname = BASEDIR "\\tname1"; 1758 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; 1759 status = smb2_create(tree2, torture, &(io.smb2)); 1760 CHECK_STATUS(status,NT_STATUS_OK); 1761 smb2_util_close(tree2, io.smb2.out.file.handle); 1762 1763 /* ask for a change notify, on attribute changes. */ 1764 ZERO_STRUCT(notify.smb2); 1765 notify.smb2.level = RAW_NOTIFY_SMB2; 1766 notify.smb2.in.buffer_size = 1000; 1767 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES; 1768 notify.smb2.in.file.handle = h1; 1769 notify.smb2.in.recursive = true; 1770 1771 req1 = smb2_notify_send(tree1, &(notify.smb2)); 1772 1773 /* set attribute on the base dir */ 1774 smb2_util_setatr(tree2, BASEDIR, FILE_ATTRIBUTE_HIDDEN); 1775 1776 /* set attribute on a file to assure we receive a notification */ 1777 smb2_util_setatr(tree2, BASEDIR "\\tname1", FILE_ATTRIBUTE_HIDDEN); 1778 smb_msleep(200); 1779 1780 /* check how many responses were given, expect only 1 for the file */ 1781 status = smb2_notify_recv(req1, torture, &(notify.smb2)); 1782 CHECK_STATUS(status, NT_STATUS_OK); 1783 CHECK_VAL(notify.smb2.out.num_changes, 1); 1784 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED); 1785 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "tname1"); 1786 1787 done: 1788 smb2_deltree(tree1, BASEDIR); 1789 return ret; 1790 } 1791 1792 1793 /* 1794 create a secondary tree connect - used to test for a bug in Samba3 messaging 1795 with change notify 1796 */ 1797 static struct smb2_tree *secondary_tcon(struct smb2_tree *tree, 1798 struct torture_context *tctx) 1799 { 1800 NTSTATUS status; 1801 const char *share, *host; 1802 struct smb2_tree *tree1; 1803 union smb_tcon tcon; 1804 1805 share = torture_setting_string(tctx, "share", NULL); 1806 host = torture_setting_string(tctx, "host", NULL); 1807 1808 torture_comment(tctx, 1809 "create a second tree context on the same session\n"); 1810 tree1 = smb2_tree_init(tree->session, tctx, false); 1811 1812 ZERO_STRUCT(tcon.smb2); 1813 tcon.generic.level = RAW_TCON_SMB2; 1814 tcon.smb2.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share); 1815 status = smb2_tree_connect(tree, &(tcon.smb2)); 1816 if (!NT_STATUS_IS_OK(status)) { 1817 talloc_free(tree); 1818 torture_comment(tctx,"Failed to create secondary tree\n"); 1819 return NULL; 1820 } 1821 1822 tree1->tid = tcon.smb2.out.tid; 1823 torture_comment(tctx,"tid1=%d tid2=%d\n", tree->tid, tree1->tid); 1824 1825 return tree1; 1826 } 1827 1828 1829 /* 1830 very simple change notify test 1831 */ 1832 static bool torture_smb2_notify_tcon(struct torture_context *torture, 1833 struct smb2_tree *tree) 1834 { 1835 bool ret = true; 1836 NTSTATUS status; 1837 union smb_notify notify; 1838 union smb_open io; 1839 struct smb2_handle h1; 1840 struct smb2_request *req = NULL; 1841 struct smb2_tree *tree1 = NULL; 1842 const char *fname = BASEDIR "\\subdir-name"; 1843 1844 smb2_deltree(tree, BASEDIR); 1845 smb2_util_rmdir(tree, BASEDIR); 1846 1847 torture_comment(torture, "TESTING SIMPLE CHANGE NOTIFY\n"); 1848 1849 /* 1850 get a handle on the directory 1851 */ 1852 1853 ZERO_STRUCT(io.smb2); 1854 io.generic.level = RAW_OPEN_SMB2; 1855 io.smb2.in.create_flags = 0; 1856 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL; 1857 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; 1858 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL | 1859 FILE_ATTRIBUTE_DIRECTORY; 1860 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | 1861 NTCREATEX_SHARE_ACCESS_WRITE; 1862 io.smb2.in.alloc_size = 0; 1863 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; 1864 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; 1865 io.smb2.in.security_flags = 0; 1866 io.smb2.in.fname = BASEDIR; 1867 1868 status = smb2_create(tree, torture, &(io.smb2)); 1869 CHECK_STATUS(status, NT_STATUS_OK); 1870 h1 = io.smb2.out.file.handle; 1871 1872 /* ask for a change notify, 1873 on file or directory name changes */ 1874 ZERO_STRUCT(notify.smb2); 1875 notify.smb2.level = RAW_NOTIFY_SMB2; 1876 notify.smb2.in.buffer_size = 1000; 1877 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; 1878 notify.smb2.in.file.handle = h1; 1879 notify.smb2.in.recursive = true; 1880 1881 torture_comment(torture, "Testing notify mkdir\n"); 1882 req = smb2_notify_send(tree, &(notify.smb2)); 1883 smb2_cancel(req); 1884 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1885 CHECK_STATUS(status, NT_STATUS_CANCELLED); 1886 1887 notify.smb2.in.recursive = true; 1888 req = smb2_notify_send(tree, &(notify.smb2)); 1889 status = smb2_util_mkdir(tree, fname); 1890 CHECK_STATUS(status, NT_STATUS_OK); 1891 1892 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1893 CHECK_STATUS(status, NT_STATUS_OK); 1894 1895 CHECK_VAL(notify.smb2.out.num_changes, 1); 1896 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED); 1897 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 1898 1899 torture_comment(torture, "Testing notify rmdir\n"); 1900 req = smb2_notify_send(tree, &(notify.smb2)); 1901 status = smb2_util_rmdir(tree, fname); 1902 CHECK_STATUS(status, NT_STATUS_OK); 1903 1904 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1905 CHECK_STATUS(status, NT_STATUS_OK); 1906 CHECK_VAL(notify.smb2.out.num_changes, 1); 1907 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED); 1908 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 1909 1910 torture_comment(torture, "SIMPLE CHANGE NOTIFY OK\n"); 1911 1912 torture_comment(torture, "TESTING WITH SECONDARY TCON\n"); 1913 tree1 = secondary_tcon(tree, torture); 1914 1915 torture_comment(torture, "Testing notify mkdir\n"); 1916 req = smb2_notify_send(tree, &(notify.smb2)); 1917 smb2_util_mkdir(tree1, fname); 1918 1919 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1920 CHECK_STATUS(status, NT_STATUS_OK); 1921 1922 CHECK_VAL(notify.smb2.out.num_changes, 1); 1923 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED); 1924 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 1925 1926 torture_comment(torture, "Testing notify rmdir\n"); 1927 req = smb2_notify_send(tree, &(notify.smb2)); 1928 smb2_util_rmdir(tree, fname); 1929 1930 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1931 CHECK_STATUS(status, NT_STATUS_OK); 1932 CHECK_VAL(notify.smb2.out.num_changes, 1); 1933 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED); 1934 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 1935 1936 torture_comment(torture, "CHANGE NOTIFY WITH TCON OK\n"); 1937 1938 torture_comment(torture, "Disconnecting secondary tree\n"); 1939 status = smb2_tdis(tree1); 1940 CHECK_STATUS(status, NT_STATUS_OK); 1941 talloc_free(tree1); 1942 1943 torture_comment(torture, "Testing notify mkdir\n"); 1944 req = smb2_notify_send(tree, &(notify.smb2)); 1945 smb2_util_mkdir(tree, fname); 1946 1947 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1948 CHECK_STATUS(status, NT_STATUS_OK); 1949 1950 CHECK_VAL(notify.smb2.out.num_changes, 1); 1951 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED); 1952 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 1953 1954 torture_comment(torture, "Testing notify rmdir\n"); 1955 req = smb2_notify_send(tree, &(notify.smb2)); 1956 smb2_util_rmdir(tree, fname); 1957 1958 status = smb2_notify_recv(req, torture, &(notify.smb2)); 1959 CHECK_STATUS(status, NT_STATUS_OK); 1960 CHECK_VAL(notify.smb2.out.num_changes, 1); 1961 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED); 1962 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name"); 1963 1964 torture_comment(torture, "CHANGE NOTIFY WITH TDIS OK\n"); 1965 done: 1966 smb2_util_close(tree, h1); 1967 smb2_deltree(tree, BASEDIR); 1968 1969 return ret; 1970 } 1971 1972 /* 1973 basic testing of SMB2 change notify 1974 */ 1975 struct torture_suite *torture_smb2_notify_init(void) 1976 { 1977 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "notify"); 1978 1979 torture_suite_add_1smb2_test(suite, "valid-req", test_valid_request); 1980 torture_suite_add_1smb2_test(suite, "tcon", torture_smb2_notify_tcon); 1981 torture_suite_add_2smb2_test(suite, "dir", torture_smb2_notify_dir); 1982 torture_suite_add_2smb2_test(suite, "mask", torture_smb2_notify_mask); 1983 torture_suite_add_1smb2_test(suite, "tdis", torture_smb2_notify_tree_disconnect); 1984 torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change); 1985 torture_suite_add_2smb2_test(suite, "logoff", torture_smb2_notify_ulogoff); 1986 torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree); 1987 torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir); 1988 torture_suite_add_2smb2_test(suite, "double", torture_smb2_notify_double); 1989 torture_suite_add_1smb2_test(suite, "file", torture_smb2_notify_file); 1990 torture_suite_add_1smb2_test(suite, "tcp", torture_smb2_notify_tcp_disconnect); 1991 torture_suite_add_2smb2_test(suite, "rec", torture_smb2_notify_recursive); 1992 torture_suite_add_1smb2_test(suite, "overflow", torture_smb2_notify_overflow); 1993 1994 suite->description = talloc_strdup(suite, "SMB2-NOTIFY tests"); 1995 1996 return suite; 1997 } 1998 -
trunk/server/source4/torture/smb2/read.c
r414 r745 27 27 #include "torture/smb2/proto.h" 28 28 29 #include "librpc/gen_ndr/ndr_security.h"30 29 31 30 #define CHECK_STATUS(status, correct) do { \ … … 233 232 struct torture_suite *torture_smb2_read_init(void) 234 233 { 235 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), " READ");236 237 torture_suite_add_1smb2_test(suite, " EOF", test_read_eof);238 torture_suite_add_1smb2_test(suite, " POSITION", test_read_position);239 torture_suite_add_1smb2_test(suite, " DIR", test_read_dir);234 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "read"); 235 236 torture_suite_add_1smb2_test(suite, "eof", test_read_eof); 237 torture_suite_add_1smb2_test(suite, "position", test_read_position); 238 torture_suite_add_1smb2_test(suite, "dir", test_read_dir); 240 239 241 240 suite->description = talloc_strdup(suite, "SMB2-READ tests"); -
trunk/server/source4/torture/smb2/scan.c
r414 r745 24 24 #include "libcli/smb2/smb2_calls.h" 25 25 #include "lib/cmdline/popt_common.h" 26 #include "lib/events/events.h"27 26 #include "torture/torture.h" 28 27 #include "param/param.h" … … 203 202 struct smbcli_options options; 204 203 205 lp _smbcli_options(torture->lp_ctx, &options);204 lpcfg_smbcli_options(torture->lp_ctx, &options); 206 205 207 206 status = smb2_connect(mem_ctx, host, 208 lp _smb_ports(torture->lp_ctx),207 lpcfg_smb_ports(torture->lp_ctx), 209 208 share, 210 lp _resolve_context(torture->lp_ctx),209 lpcfg_resolve_context(torture->lp_ctx), 211 210 credentials, &tree, torture->ev, &options, 212 lp _socket_options(torture->lp_ctx),213 lp _gensec_settings(torture, torture->lp_ctx));211 lpcfg_socket_options(torture->lp_ctx), 212 lpcfg_gensec_settings(torture, torture->lp_ctx)); 214 213 if (!NT_STATUS_IS_OK(status)) { 215 214 printf("Connection failed - %s\n", nt_errstr(status)); … … 226 225 talloc_free(tree); 227 226 status = smb2_connect(mem_ctx, host, 228 lp _smb_ports(torture->lp_ctx),227 lpcfg_smb_ports(torture->lp_ctx), 229 228 share, 230 lp _resolve_context(torture->lp_ctx),229 lpcfg_resolve_context(torture->lp_ctx), 231 230 credentials, &tree, torture->ev, &options, 232 lp _socket_options(torture->lp_ctx),233 lp _gensec_settings(mem_ctx, torture->lp_ctx));231 lpcfg_socket_options(torture->lp_ctx), 232 lpcfg_gensec_settings(mem_ctx, torture->lp_ctx)); 234 233 if (!NT_STATUS_IS_OK(status)) { 235 234 printf("Connection failed - %s\n", nt_errstr(status)); -
trunk/server/source4/torture/smb2/setinfo.c
r414 r745 33 33 #define BASEDIR "" 34 34 35 #define FAIL_UNLESS(__cond) \ 36 do { \ 37 if (__cond) {} else { \ 38 torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n", \ 39 __location__, #__cond); \ 40 ret = false; goto done; \ 41 } \ 42 } while(0) 43 35 44 /* basic testing of all SMB2 setinfo calls 36 45 for each call we test that it succeeds, and where possible test 37 46 for consistency between the calls. 38 47 */ 39 bool torture_smb2_setinfo(struct torture_context *t orture)48 bool torture_smb2_setinfo(struct torture_context *tctx) 40 49 { 41 50 struct smb2_tree *tree; … … 56 65 ZERO_STRUCT(handle); 57 66 58 fname = talloc_asprintf(t orture, BASEDIR "fnum_test_%d.txt", n);59 fname_new = talloc_asprintf(t orture, BASEDIR "fnum_test_new_%d.txt", n);60 61 if (!torture_smb2_connection(t orture, &tree)) {67 fname = talloc_asprintf(tctx, BASEDIR "fnum_test_%d.txt", n); 68 fname_new = talloc_asprintf(tctx, BASEDIR "fnum_test_new_%d.txt", n); 69 70 if (!torture_smb2_connection(tctx, &tree)) { 62 71 return false; 63 72 } … … 67 76 status = smb2_create_complex_file(tree, fname, &handle); \ 68 77 if (!NT_STATUS_IS_OK(status)) { \ 69 printf("(%s) ERROR: open of %s failed (%s)\n", \78 torture_result(tctx, TORTURE_ERROR, "(%s) ERROR: open of %s failed (%s)\n", \ 70 79 __location__, fname, nt_errstr(status)); \ 71 80 ret = false; \ … … 85 94 status = smb2_setinfo_file(tree, &sfinfo); \ 86 95 if (!NT_STATUS_EQUAL(status, rightstatus)) { \ 87 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \96 torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s (should be %s)\n", __location__, #call, \ 88 97 nt_errstr(status), nt_errstr(rightstatus)); \ 89 98 ret = false; \ … … 96 105 finfo2.generic.level = RAW_FILEINFO_ ## call; \ 97 106 finfo2.generic.in.file.handle = handle; \ 98 status2 = smb2_getinfo_file(tree, t orture, &finfo2); \107 status2 = smb2_getinfo_file(tree, tctx, &finfo2); \ 99 108 if (!NT_STATUS_IS_OK(status2)) { \ 100 printf("(%s) %s - %s\n", __location__, #call, nt_errstr(status2)); \109 torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__, #call, nt_errstr(status2)); \ 101 110 ret = false; \ 102 111 goto done; \ … … 107 116 CHECK1(call); \ 108 117 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \ 109 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \118 torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \ 110 119 call_name, #stype, #field, \ 111 (u int_t)value, (uint_t)finfo2.stype.out.field); \120 (unsigned int)value, (unsigned int)finfo2.stype.out.field); \ 112 121 torture_smb2_all_info(tree, handle); \ 113 122 ret = false; \ … … 118 127 CHECK1(call); \ 119 128 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \ 120 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \129 torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \ 121 130 call_name, #stype, #field, \ 122 (u int_t)value, \123 (u int_t)nt_time_to_unix(finfo2.stype.out.field)); \124 printf("\t%s", timestring(torture, value)); \125 printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \131 (unsigned int)value, \ 132 (unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \ 133 torture_warning(tctx, "\t%s", timestring(tctx, value)); \ 134 torture_warning(tctx, "\t%s\n", nt_time_string(tctx, finfo2.stype.out.field)); \ 126 135 torture_smb2_all_info(tree, handle); \ 127 136 ret = false; \ … … 131 140 #define CHECK_STATUS(status, correct) do { \ 132 141 if (!NT_STATUS_EQUAL(status, correct)) { \ 133 printf("(%s) Incorrect status %s - should be %s\n", \142 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \ 134 143 __location__, nt_errstr(status), nt_errstr(correct)); \ 135 144 ret = false; \ … … 139 148 torture_smb2_all_info(tree, handle); 140 149 141 printf("test basic_information level\n");150 torture_comment(tctx, "Test basic_information level\n"); 142 151 basetime += 86400; 143 152 unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100); … … 153 162 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_READONLY); 154 163 155 printf("a zero time means don't change\n");164 torture_comment(tctx, "a zero time means don't change\n"); 156 165 unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0); 157 166 unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0); … … 166 175 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL); 167 176 168 printf("change the attribute\n");177 torture_comment(tctx, "change the attribute\n"); 169 178 sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN; 170 179 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK); 171 180 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN); 172 181 173 printf("zero attrib means don't change\n");182 torture_comment(tctx, "zero attrib means don't change\n"); 174 183 sfinfo.basic_info.in.attrib = 0; 175 184 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK); 176 185 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN); 177 186 178 printf("can't change a file to a directory\n");187 torture_comment(tctx, "can't change a file to a directory\n"); 179 188 sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY; 180 189 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_INVALID_PARAMETER); 181 190 182 printf("restore attribute\n");191 torture_comment(tctx, "restore attribute\n"); 183 192 sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL; 184 193 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK); 185 194 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL); 186 195 187 printf("test disposition_information level\n");196 torture_comment(tctx, "Test disposition_information level\n"); 188 197 sfinfo.disposition_info.in.delete_on_close = 1; 189 198 CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK); … … 196 205 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 1); 197 206 198 printf("test allocation_information level\n");207 torture_comment(tctx, "Test allocation_information level\n"); 199 208 sfinfo.allocation_info.in.alloc_size = 0; 200 209 CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK); … … 207 216 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0); 208 217 209 printf("test end_of_file_info level\n");218 torture_comment(tctx, "Test end_of_file_info level\n"); 210 219 sfinfo.end_of_file_info.in.size = 37; 211 220 CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK); … … 216 225 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 7); 217 226 218 printf("test position_information level\n");227 torture_comment(tctx, "Test position_information level\n"); 219 228 sfinfo.position_information.in.position = 123456; 220 229 CHECK_CALL(POSITION_INFORMATION, NT_STATUS_OK); … … 222 231 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, position, 123456); 223 232 224 printf("test mode_information level\n");233 torture_comment(tctx, "Test mode_information level\n"); 225 234 sfinfo.mode_information.in.mode = 2; 226 235 CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK); … … 235 244 CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0); 236 245 237 printf("test sec_desc level\n");246 torture_comment(tctx, "Test sec_desc level\n"); 238 247 ZERO_STRUCT(finfo2); 239 248 finfo2.query_secdesc.in.secinfo_flags = … … 244 253 sd = finfo2.query_secdesc.out.sd; 245 254 246 test_sid = dom_sid_parse_talloc(t orture, "S-1-5-32-1234-5432");255 test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS); 247 256 ZERO_STRUCT(ace); 248 257 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; … … 253 262 CHECK_STATUS(status, NT_STATUS_OK); 254 263 255 printf("add a new ACE to the DACL\n");264 torture_comment(tctx, "add a new ACE to the DACL\n"); 256 265 257 266 sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags; 258 267 sfinfo.set_secdesc.in.sd = sd; 259 268 CHECK_CALL(SEC_DESC, NT_STATUS_OK); 260 CHECK1(SEC_DESC); 261 262 if (!security_acl_equal(finfo2.query_secdesc.out.sd->dacl, sd->dacl)) { 263 printf("%s: security descriptors don't match!\n", __location__); 264 printf("got:\n"); 265 NDR_PRINT_DEBUG(security_descriptor, finfo2.query_secdesc.out.sd); 266 printf("expected:\n"); 267 NDR_PRINT_DEBUG(security_descriptor, sd); 268 ret = false; 269 } 270 271 printf("remove it again\n"); 269 FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, handle, sd)); 270 271 torture_comment(tctx, "remove it again\n"); 272 272 273 273 status = security_descriptor_dacl_del(sd, test_sid); … … 277 277 sfinfo.set_secdesc.in.sd = sd; 278 278 CHECK_CALL(SEC_DESC, NT_STATUS_OK); 279 CHECK1(SEC_DESC); 280 281 if (!security_acl_equal(finfo2.query_secdesc.out.sd->dacl, sd->dacl)) { 282 printf("%s: security descriptors don't match!\n", __location__); 283 printf("got:\n"); 284 NDR_PRINT_DEBUG(security_descriptor, finfo2.query_secdesc.out.sd); 285 printf("expected:\n"); 286 NDR_PRINT_DEBUG(security_descriptor, sd); 287 ret = false; 288 } 279 FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, handle, sd)); 289 280 290 281 done: 291 282 status = smb2_util_close(tree, handle); 292 283 if (NT_STATUS_IS_ERR(status)) { 293 printf("Failed to delete %s - %s\n", fname, nt_errstr(status));284 torture_warning(tctx, "Failed to delete %s - %s\n", fname, nt_errstr(status)); 294 285 } 295 286 smb2_util_unlink(tree, fname); -
trunk/server/source4/torture/smb2/smb2.c
r414 r745 20 20 #include "includes.h" 21 21 #include "libcli/smb2/smb2.h" 22 #include "libcli/smb2/smb2_calls.h"23 22 24 23 #include "torture/smbtorture.h" … … 127 126 NTSTATUS torture_smb2_init(void) 128 127 { 129 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), " SMB2");130 torture_suite_add_simple_test(suite, " CONNECT", torture_smb2_connect);131 torture_suite_add_simple_test(suite, " SCAN", torture_smb2_scan);132 torture_suite_add_simple_test(suite, " SCANGETINFO", torture_smb2_getinfo_scan);133 torture_suite_add_simple_test(suite, " SCANSETINFO", torture_smb2_setinfo_scan);134 torture_suite_add_simple_test(suite, " SCANFIND", torture_smb2_find_scan);135 torture_suite_add_simple_test(suite, " GETINFO", torture_smb2_getinfo);136 torture_suite_add_simple_test(suite, " SETINFO", torture_smb2_setinfo);128 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "smb2"); 129 torture_suite_add_simple_test(suite, "connect", torture_smb2_connect); 130 torture_suite_add_simple_test(suite, "scan", torture_smb2_scan); 131 torture_suite_add_simple_test(suite, "scangetinfo", torture_smb2_getinfo_scan); 132 torture_suite_add_simple_test(suite, "scansetinfo", torture_smb2_setinfo_scan); 133 torture_suite_add_simple_test(suite, "scanfind", torture_smb2_find_scan); 134 torture_suite_add_simple_test(suite, "getinfo", torture_smb2_getinfo); 135 torture_suite_add_simple_test(suite, "setinfo", torture_smb2_setinfo); 137 136 torture_suite_add_suite(suite, torture_smb2_lock_init()); 138 137 torture_suite_add_suite(suite, torture_smb2_read_init()); 139 138 torture_suite_add_suite(suite, torture_smb2_create_init()); 140 torture_suite_add_simple_test(suite, "NOTIFY", torture_smb2_notify); 139 torture_suite_add_suite(suite, torture_smb2_acls_init()); 140 torture_suite_add_suite(suite, torture_smb2_notify_init()); 141 141 torture_suite_add_suite(suite, torture_smb2_durable_open_init()); 142 torture_suite_add_1smb2_test(suite, "OPLOCK-BATCH1", torture_smb2_oplock_batch1);143 142 torture_suite_add_suite(suite, torture_smb2_dir_init()); 144 143 torture_suite_add_suite(suite, torture_smb2_lease_init()); 145 144 torture_suite_add_suite(suite, torture_smb2_compound_init()); 145 torture_suite_add_suite(suite, torture_smb2_oplocks_init()); 146 torture_suite_add_suite(suite, torture_smb2_streams_init()); 147 torture_suite_add_1smb2_test(suite, "bench-oplock", test_smb2_bench_oplock); 148 torture_suite_add_1smb2_test(suite, "hold-oplock", test_smb2_hold_oplock); 146 149 147 150 suite->description = talloc_strdup(suite, "SMB2-specific tests"); -
trunk/server/source4/torture/smb2/util.c
r414 r745 21 21 22 22 #include "includes.h" 23 #include "libcli/security/security_descriptor.h" 23 24 #include "libcli/smb2/smb2.h" 24 25 #include "libcli/smb2/smb2_calls.h" 25 #include "libcli/smb_composite/smb_composite.h"26 26 #include "lib/cmdline/popt_common.h" 27 #include "lib/events/events.h"28 27 #include "system/time.h" 29 28 #include "librpc/gen_ndr/ndr_security.h" … … 32 31 33 32 #include "torture/torture.h" 34 #include "torture/smb2/proto.h"35 33 36 34 … … 273 271 struct smbcli_options options; 274 272 275 lp _smbcli_options(tctx->lp_ctx, &options);273 lpcfg_smbcli_options(tctx->lp_ctx, &options); 276 274 277 275 status = smb2_connect(tctx, host, 278 lp _smb_ports(tctx->lp_ctx),276 lpcfg_smb_ports(tctx->lp_ctx), 279 277 share, 280 lp _resolve_context(tctx->lp_ctx),278 lpcfg_resolve_context(tctx->lp_ctx), 281 279 credentials, tree, 282 280 tctx->ev, &options, 283 lp _socket_options(tctx->lp_ctx),284 lp _gensec_settings(tctx, tctx->lp_ctx)281 lpcfg_socket_options(tctx->lp_ctx), 282 lpcfg_gensec_settings(tctx, tctx->lp_ctx) 285 283 ); 286 284 if (!NT_STATUS_IS_OK(status)) { … … 325 323 r.in.offset = 0; 326 324 325 // What is the purpose of this? Server returns EOF. 327 326 smb2_read(tree, tree, &r); 328 327 … … 358 357 359 358 /* 360 create a complex file using the old SMB protocol, to make it easier to359 create a complex file using SMB2, to make it easier to 361 360 find fields in SMB2 getinfo levels 362 361 */ … … 371 370 372 371 /* 373 create a complex dir using the old SMB protocol, to make it easier to372 create a complex dir using SMB2, to make it easier to 374 373 find fields in SMB2 getinfo levels 375 374 */ … … 407 406 return NT_STATUS_OK; 408 407 } 408 409 /* Comparable to torture_setup_dir, but for SMB2. */ 410 bool smb2_util_setup_dir(struct torture_context *tctx, struct smb2_tree *tree, 411 const char *dname) 412 { 413 NTSTATUS status; 414 415 /* XXX: smb_raw_exit equivalent? 416 smb_raw_exit(cli->session); */ 417 if (smb2_deltree(tree, dname) == -1) { 418 torture_result(tctx, TORTURE_ERROR, "Unable to deltree when setting up %s.\n", dname); 419 return false; 420 } 421 422 status = smb2_util_mkdir(tree, dname); 423 if (NT_STATUS_IS_ERR(status)) { 424 torture_result(tctx, TORTURE_ERROR, "Unable to mkdir when setting up %s - %s\n", dname, 425 nt_errstr(status)); 426 return false; 427 } 428 429 return true; 430 } 431 432 #define CHECK_STATUS(status, correct) do { \ 433 if (!NT_STATUS_EQUAL(status, correct)) { \ 434 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \ 435 __location__, nt_errstr(status), nt_errstr(correct)); \ 436 ret = false; \ 437 goto done; \ 438 }} while (0) 439 440 /* 441 * Helper function to verify a security descriptor, by querying 442 * and comparing against the passed in sd. 443 */ 444 bool smb2_util_verify_sd(TALLOC_CTX *tctx, struct smb2_tree *tree, 445 struct smb2_handle handle, struct security_descriptor *sd) 446 { 447 NTSTATUS status; 448 bool ret = true; 449 union smb_fileinfo q = {}; 450 451 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; 452 q.query_secdesc.in.file.handle = handle; 453 q.query_secdesc.in.secinfo_flags = 454 SECINFO_OWNER | 455 SECINFO_GROUP | 456 SECINFO_DACL; 457 status = smb2_getinfo_file(tree, tctx, &q); 458 CHECK_STATUS(status, NT_STATUS_OK); 459 460 if (!security_acl_equal( 461 q.query_secdesc.out.sd->dacl, sd->dacl)) { 462 torture_warning(tctx, "%s: security descriptors don't match!\n", 463 __location__); 464 torture_warning(tctx, "got:\n"); 465 NDR_PRINT_DEBUG(security_descriptor, 466 q.query_secdesc.out.sd); 467 torture_warning(tctx, "expected:\n"); 468 NDR_PRINT_DEBUG(security_descriptor, sd); 469 ret = false; 470 } 471 472 done: 473 return ret; 474 } 475 476 /* 477 * Helper function to verify attributes, by querying 478 * and comparing against the passed in attrib. 479 */ 480 bool smb2_util_verify_attrib(TALLOC_CTX *tctx, struct smb2_tree *tree, 481 struct smb2_handle handle, uint32_t attrib) 482 { 483 NTSTATUS status; 484 bool ret = true; 485 union smb_fileinfo q = {}; 486 487 q.standard.level = RAW_FILEINFO_SMB2_ALL_INFORMATION; 488 q.standard.in.file.handle = handle; 489 status = smb2_getinfo_file(tree, tctx, &q); 490 CHECK_STATUS(status, NT_STATUS_OK); 491 492 q.all_info2.out.attrib &= ~FILE_ATTRIBUTE_ARCHIVE; 493 494 if (q.all_info2.out.attrib != attrib) { 495 torture_warning(tctx, "%s: attributes don't match! " 496 "got %x, expected %x\n", __location__, 497 (uint32_t)q.standard.out.attrib, 498 (uint32_t)attrib); 499 ret = false; 500 } 501 502 done: 503 return ret; 504 } 505 506
Note:
See TracChangeset
for help on using the changeset viewer.