The branch, master has been updated via f43498b selftest: we currently fail smb2.durable-v2-open.app-instance via 1c2f1a1 s4:torture:smb2: add a new test durable-v2-open.app-instance via a397c85 s4:libci: add a SMB2_CREATE_APP_INSTANCE_ID blob to the request if the in.app_instance_id is present via 562719f s4:libcli: add a app_instance_id member to the smb2_create input struct via 50c10cb libcli: add a define for the APP_INSTANCE_ID smb2 create context via e6c600a s4:torture/smb2: improve the smb2.create.blob test via aa5caf1 libcli/smb: fix padding in smb2_create_blob* from 98d90c0 pam_winbind: match more return codes when wbcGetPwnam has failed.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit f43498b7590e33f2c8939c4f04781068674335af Author: Michael Adam <ob...@samba.org> Date: Fri Sep 7 16:42:37 2012 +0200 selftest: we currently fail smb2.durable-v2-open.app-instance Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Wed Sep 19 23:05:43 CEST 2012 on sn-devel-104 commit 1c2f1a18623c9092fda6cb74788c17fc572e5791 Author: Michael Adam <ob...@samba.org> Date: Fri Sep 7 14:30:07 2012 +0200 s4:torture:smb2: add a new test durable-v2-open.app-instance Pair-Programmed-With: Stefan Metzmacher <me...@samba.org> commit a397c8516467b83d7e2cb5b4a15dea26798786d5 Author: Michael Adam <ob...@samba.org> Date: Fri Sep 7 12:06:36 2012 +0200 s4:libci: add a SMB2_CREATE_APP_INSTANCE_ID blob to the request if the in.app_instance_id is present commit 562719f75f9868d13f4838b36cc263ef5d3541b1 Author: Michael Adam <ob...@samba.org> Date: Fri Sep 7 12:06:05 2012 +0200 s4:libcli: add a app_instance_id member to the smb2_create input struct commit 50c10cbdcedc892e07297686dbe380cfb3f94cef Author: Michael Adam <ob...@samba.org> Date: Fri Sep 7 12:05:24 2012 +0200 libcli: add a define for the APP_INSTANCE_ID smb2 create context commit e6c600aa2c751e694917322378417816c3e58eb6 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 19 21:18:46 2012 +0200 s4:torture/smb2: improve the smb2.create.blob test metze commit aa5caf1fe92b159eae00c7b11499e9ec697cf9ae Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 19 08:11:23 2012 +0200 libcli/smb: fix padding in smb2_create_blob* metze ----------------------------------------------------------------------- Summary of changes: libcli/smb/smb2_constants.h | 1 + libcli/smb/smb2_create_blob.c | 41 +++++++--- selftest/knownfail | 1 + source4/libcli/raw/interfaces.h | 4 +- source4/libcli/smb2/create.c | 25 ++++++ source4/torture/smb2/create.c | 93 +++++++++++++++++++++- source4/torture/smb2/durable_v2_open.c | 134 ++++++++++++++++++++++++++++++++ 7 files changed, 285 insertions(+), 14 deletions(-) Changeset truncated at 500 lines: diff --git a/libcli/smb/smb2_constants.h b/libcli/smb/smb2_constants.h index 6b9ad85..22fe23a 100644 --- a/libcli/smb/smb2_constants.h +++ b/libcli/smb/smb2_constants.h @@ -204,6 +204,7 @@ #define SMB2_CREATE_TAG_RQLS "RqLs" #define SMB2_CREATE_TAG_DH2Q "DH2Q" #define SMB2_CREATE_TAG_DH2C "DH2C" +#define SMB2_CREATE_TAG_APP_INSTANCE_ID "\x45\xBC\xA6\x6A\xEF\xA7\xF7\x4A\x90\x08\xFA\x46\x2E\x14\x4D\x74" /* SMB2 notify flags */ #define SMB2_WATCH_TREE 0x0001 diff --git a/libcli/smb/smb2_create_blob.c b/libcli/smb/smb2_create_blob.c index 2175a0c..189bcd1 100644 --- a/libcli/smb/smb2_create_blob.c +++ b/libcli/smb/smb2_create_blob.c @@ -61,10 +61,10 @@ NTSTATUS smb2_create_blob_parse(TALLOC_CTX *mem_ctx, const DATA_BLOB buffer, if ((next & 0x7) != 0 || next > remaining || - name_offset < 16 || - name_offset > remaining || - name_length != 4 || /* windows enforces this */ + name_offset != 16 || + name_length < 4 || name_offset + name_length > remaining || + (data_offset & 0x7) != 0 || (data_offset && (data_offset < name_offset + name_length)) || (data_offset && (data_offset > remaining)) || (data_offset && data_length && @@ -108,25 +108,44 @@ static NTSTATUS smb2_create_blob_push_one(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer { uint32_t ofs = buffer->length; size_t tag_length = strlen(blob->tag); - uint8_t pad = smb2_create_blob_padding(blob->data.length+tag_length, 4); + size_t blob_offset = 0; + size_t blob_pad = 0; + size_t next_offset = 0; + size_t next_pad = 0; + bool ok; + + blob_offset = 0x14 + tag_length; + blob_pad = smb2_create_blob_padding(blob_offset, 8); + next_offset = blob_offset + blob_pad + blob->data.length; + if (!last) { + next_pad = smb2_create_blob_padding(next_offset, 8); + } - if (!data_blob_realloc(mem_ctx, buffer, - buffer->length + 0x14 + tag_length + blob->data.length + pad)) + ok = data_blob_realloc(mem_ctx, buffer, + buffer->length + next_offset + next_pad); + if (!ok) { return NT_STATUS_NO_MEMORY; + } if (last) { SIVAL(buffer->data, ofs+0x00, 0); } else { - SIVAL(buffer->data, ofs+0x00, 0x14 + tag_length + blob->data.length + pad); + SIVAL(buffer->data, ofs+0x00, next_offset + next_pad); } SSVAL(buffer->data, ofs+0x04, 0x10); /* offset of tag */ SIVAL(buffer->data, ofs+0x06, tag_length); /* tag length */ - SSVAL(buffer->data, ofs+0x0A, 0x14 + tag_length); /* offset of data */ + SSVAL(buffer->data, ofs+0x0A, blob_offset + blob_pad); /* offset of data */ SIVAL(buffer->data, ofs+0x0C, blob->data.length); memcpy(buffer->data+ofs+0x10, blob->tag, tag_length); - SIVAL(buffer->data, ofs+0x10+tag_length, 0); /* pad? */ - memcpy(buffer->data+ofs+0x14+tag_length, blob->data.data, blob->data.length); - memset(buffer->data+ofs+0x14+tag_length+blob->data.length, 0, pad); + if (blob_pad > 0) { + memset(buffer->data+ofs+blob_offset, 0, blob_pad); + blob_offset += blob_pad; + } + memcpy(buffer->data+ofs+blob_offset, blob->data.data, blob->data.length); + if (next_pad > 0) { + memset(buffer->data+ofs+next_offset, 0, next_pad); + next_offset += next_pad; + } return NT_STATUS_OK; } diff --git a/selftest/knownfail b/selftest/knownfail index 0180eb3..59fa2ee 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -180,6 +180,7 @@ ^samba3.smb2.durable-open.delete_on_close2 ^samba3.smb2.durable-v2-open.open-lease ^samba3.smb2.durable-v2-open.persistent-open-lease +^samba3.smb2.durable-v2-open.app-instance ^samba3.smb2.ioctl.shadow_copy ^samba3.smb2.ioctl.req_resume_key ^samba3.smb2.ioctl.copy_chunk_simple diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index 547f8a9..c13475b 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -1743,7 +1743,9 @@ union smb_open { NTTIME timewarp; bool query_on_disk_id; struct smb2_lease *lease_request; - + + struct GUID *app_instance_id; + /* and any additional blobs the caller wants */ struct smb2_create_blobs blobs; } in; diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c index c8424dc..db9abbe 100644 --- a/source4/libcli/smb2/create.c +++ b/source4/libcli/smb2/create.c @@ -226,6 +226,31 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create } } + if (io->in.app_instance_id) { + uint8_t data[20]; + DATA_BLOB guid_blob; + + SSVAL(data, 0, 20); /* structure size */ + SSVAL(data, 2, 0); /* reserved */ + + status = GUID_to_ndr_blob(io->in.app_instance_id, + req, /* TALLOC_CTX */ + &guid_blob); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(req); + return NULL; + } + memcpy(data+4, guid_blob.data, 16); + + status = smb2_create_blob_add(req, &blobs, + SMB2_CREATE_TAG_APP_INSTANCE_ID, + data_blob_const(data, 20)); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(req); + return NULL; + } + } + /* and any custom blobs */ for (i=0;i<io->in.blobs.num_blobs;i++) { status = smb2_create_blob_add(req, &blobs, diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index 4668e12..e36a078 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -445,14 +445,103 @@ static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tre status = smb2_util_close(tree, io.out.file.handle); CHECK_STATUS(status, NT_STATUS_OK); - torture_comment(tctx, "Testing bad tag length\n"); + torture_comment(tctx, "Testing bad tag length 0\n"); + ZERO_STRUCT(io.in.blobs); status = smb2_create_blob_add(tctx, &io.in.blobs, - "xxx", data_blob(NULL, 0)); + "x", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); + + torture_comment(tctx, "Testing bad tag length 1\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "x", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); + + torture_comment(tctx, "Testing bad tag length 2\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xx", data_blob(NULL, 0)); CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); + torture_comment(tctx, "Testing bad tag length 3\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xxx", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); + torture_comment(tctx, "Testing tag length 4\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xxxx", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + torture_comment(tctx, "Testing tag length 5\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xxxxx", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + torture_comment(tctx, "Testing tag length 6\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xxxxxx", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + torture_comment(tctx, "Testing tag length 7\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xxxxxxx", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + torture_comment(tctx, "Testing tag length 8\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xxxxxxxx", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + torture_comment(tctx, "Testing tag length 16\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xxxxxxxxxxxxxxxx", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + torture_comment(tctx, "Testing tag length 17\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xxxxxxxxxxxxxxxxx", data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + torture_comment(tctx, "Testing tag length 34\n"); + ZERO_STRUCT(io.in.blobs); + status = smb2_create_blob_add(tctx, &io.in.blobs, + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + data_blob(NULL, 0)); + CHECK_STATUS(status, NT_STATUS_OK); + status = smb2_create(tree, tctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + smb2_deltree(tree, FNAME); return true; diff --git a/source4/torture/smb2/durable_v2_open.c b/source4/torture/smb2/durable_v2_open.c index 0a46778..b9d0d8c 100644 --- a/source4/torture/smb2/durable_v2_open.c +++ b/source4/torture/smb2/durable_v2_open.c @@ -51,6 +51,38 @@ CHECK_VAL((__io)->out.reserved2, 0); \ } while(0) +static struct { + int count; + struct smb2_close cl; +} break_info; + +static void torture_oplock_close_callback(struct smb2_request *req) +{ + smb2_close_recv(req, &break_info.cl); +} + +/* A general oplock break notification handler. This should be used when a + * test expects to break from batch or exclusive to a lower level. */ +static bool torture_oplock_handler(struct smb2_transport *transport, + const struct smb2_handle *handle, + uint8_t level, + void *private_data) +{ + struct smb2_tree *tree = private_data; + const char *name; + struct smb2_request *req; + + break_info.count++; + + ZERO_STRUCT(break_info.cl); + break_info.cl.in.file.handle = *handle; + + req = smb2_close_send(tree, &break_info.cl); + req->async.fn = torture_oplock_close_callback; + req->async.private_data = NULL; + return true; +} + /** * basic durable_open test. * durable state should only be granted when requested @@ -554,6 +586,107 @@ done: } /** + * Test durable request / reconnect with AppInstanceId + */ +bool test_durable_v2_open_app_instance(struct torture_context *tctx, + struct smb2_tree *tree1, + struct smb2_tree *tree2) +{ + NTSTATUS status; + TALLOC_CTX *mem_ctx = talloc_new(tctx); + char fname[256]; + struct smb2_handle _h1, _h2; + struct smb2_handle *h1 = NULL, *h2 = NULL; + struct smb2_create io1, io2; + bool ret = true; + struct GUID create_guid_1 = GUID_random(); + struct GUID create_guid_2 = GUID_random(); + struct GUID app_instance_id = GUID_random(); + + /* Choose a random name in case the state is left a little funky. */ + snprintf(fname, 256, "durable_v2_open_app_instance_%s.dat", + generate_random_str(tctx, 8)); + + smb2_util_unlink(tree1, fname); + + ZERO_STRUCT(break_info); + tree1->session->transport->oplock.handler = torture_oplock_handler; + tree1->session->transport->oplock.private_data = tree1; + + smb2_oplock_create_share(&io1, fname, + smb2_util_share_access(""), + smb2_util_oplock_level("b")); + io1.in.durable_open = false; + io1.in.durable_open_v2 = true; + io1.in.persistent_open = false; + io1.in.create_guid = create_guid_1; + io1.in.app_instance_id = &app_instance_id; + io1.in.timeout = UINT32_MAX; + + status = smb2_create(tree1, mem_ctx, &io1); + CHECK_STATUS(status, NT_STATUS_OK); + _h1 = io1.out.file.handle; + h1 = &_h1; + CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b")); + CHECK_VAL(io1.out.durable_open, false); + CHECK_VAL(io1.out.durable_open_v2, true); + CHECK_VAL(io1.out.persistent_open, false); + CHECK_VAL(io1.out.timeout, io1.in.timeout); + + /* + * try to open the file as durable from a second tree with + * a different create guid but the same app_instance_id + * while the first handle is still open. + */ + + smb2_oplock_create_share(&io2, fname, + smb2_util_share_access(""), + smb2_util_oplock_level("b")); + io2.in.durable_open = false; + io2.in.durable_open_v2 = true; + io2.in.persistent_open = false; + io2.in.create_guid = create_guid_2; + io2.in.app_instance_id = &app_instance_id; + io2.in.timeout = UINT32_MAX; + + status = smb2_create(tree2, mem_ctx, &io2); + CHECK_STATUS(status, NT_STATUS_OK); + _h2 = io2.out.file.handle; + h2 = &_h2; + CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b")); + CHECK_VAL(io2.out.durable_open, false); + CHECK_VAL(io2.out.durable_open_v2, true); + CHECK_VAL(io2.out.persistent_open, false); + CHECK_VAL(io2.out.timeout, io2.in.timeout); + + CHECK_VAL(break_info.count, 0); + + status = smb2_util_close(tree1, *h1); + CHECK_STATUS(status, NT_STATUS_FILE_CLOSED); + h1 = NULL; + +done: + if (h1 != NULL) { + smb2_util_close(tree1, *h1); + } + if (h2 != NULL) { + smb2_util_close(tree2, *h2); + } + + smb2_util_unlink(tree2, fname); + + talloc_free(tree1); + talloc_free(tree2); + + talloc_free(mem_ctx); + + return ret; +} + + +/** * basic persistent open test. * * This test tests durable open with all possible oplock types. @@ -731,6 +864,7 @@ struct torture_suite *torture_smb2_durable_v2_open_init(void) torture_suite_add_1smb2_test(suite, "open-lease", test_durable_v2_open_lease); torture_suite_add_1smb2_test(suite, "reopen1", test_durable_v2_open_reopen1); torture_suite_add_1smb2_test(suite, "reopen2", test_durable_v2_open_reopen2); + torture_suite_add_2smb2_test(suite, "app-instance", test_durable_v2_open_app_instance); torture_suite_add_1smb2_test(suite, "persistent-open-oplock", test_persistent_open_oplock); torture_suite_add_1smb2_test(suite, "persistent-open-lease", test_persistent_open_lease); -- Samba Shared Repository