From 7dec53ed0c1c58b4ab7b7483b2da3e4cd58750fa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 30 May 2019 10:38:41 +0200 Subject: [PATCH] torture3: Add a test to block a locking&read Right now we fail this with smbd, we return LOCK_NOT_GRANTED instead of FILE_LOCK_CONFLICT. This will change with later commits. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- selftest/knownfail | 2 + source3/selftest/tests.py | 1 + source3/torture/torture.c | 171 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) diff --git a/selftest/knownfail b/selftest/knownfail index 2c31bf91619..81fe4e6df8e 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -12,6 +12,8 @@ ^samba3.smb2.session enc.reconnect # expected to give CONNECTION_DISCONNECTED, we need to fix the test ^samba3.raw.session enc # expected to give ACCESS_DENIED as SMB1 encryption isn't used ^samba3.smbtorture_s3.crypt_server # expected to give ACCESS_DENIED as SMB1 encryption isn't used +^samba3.smbtorture_s3.*.LOCK10.*\(fileserver\) +^samba3.smbtorture_s3.*.LOCK10.*\(nt4_dc\) ^samba3.nbt.dgram.*netlogon2\(nt4_dc\) ^samba3.*rap.sam.*.useradd # Not provided by Samba 3 ^samba3.*rap.sam.*.userdelete # Not provided by Samba 3 diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 512a0b2c421..9bc5bdd0e5f 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -79,6 +79,7 @@ plantestsuite("samba3.local_s3", "nt4_dc:local", [os.path.join(samba3srcdir, "sc plantestsuite("samba3.blackbox.registry.upgrade", "nt4_dc:local", [os.path.join(samba3srcdir, "script/tests/test_registry_upgrade.sh"), net, dbwrap_tool]) tests = ["FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7", "LOCK9", + "LOCK10", "UNLINK", "BROWSE", "ATTR", "TRANS2", "TORTURE", "OPLOCK1", "OPLOCK2", "OPLOCK4", "STREAMERROR", "DIR", "DIR1", "DIR-CREATETIME", "TCON", "TCONDEV", "RW1", "RW2", "RW3", "LARGE_READX", "RW-SIGNING", diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 45ef5c60f7b..fee101791d4 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -2727,6 +2727,173 @@ fail_nofd: return correct; } +struct locktest10_state { + bool ok; + bool done; +}; + +static void locktest10_lockingx_done(struct tevent_req *subreq); +static void locktest10_read_andx_done(struct tevent_req *subreq); + +static bool run_locktest10(int dummy) +{ + struct tevent_context *ev = NULL; + struct cli_state *cli1 = NULL; + struct cli_state *cli2 = NULL; + struct smb1_lock_element lck = { 0 }; + struct tevent_req *reqs[2] = { NULL }; + struct tevent_req *smbreqs[2] = { NULL }; + const char fname[] = "\\lockt10.lck"; + uint16_t fnum1, fnum2; + bool ret = false; + bool ok; + uint8_t data = 1; + struct locktest10_state state = { .ok = true }; + NTSTATUS status; + + printf("starting locktest10\n"); + + ev = samba_tevent_context_init(NULL); + if (ev == NULL) { + d_fprintf(stderr, "samba_tevent_context_init failed\n"); + goto done; + } + + ok = torture_open_connection(&cli1, 0); + if (!ok) { + goto done; + } + smbXcli_conn_set_sockopt(cli1->conn, sockops); + + ok = torture_open_connection(&cli2, 1); + if (!ok) { + goto done; + } + smbXcli_conn_set_sockopt(cli2->conn, sockops); + + status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, + "cli_openx failed: %s\n", + nt_errstr(status)); + goto done; + } + + status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, + "cli_writeall failed: %s\n", + nt_errstr(status)); + goto done; + } + + status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, + "cli_openx failed: %s\n", + nt_errstr(status)); + goto done; + } + + status = cli_locktype( + cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, + "cli_locktype failed: %s\n", + nt_errstr(status)); + goto done; + } + + lck = (struct smb1_lock_element) { + .pid = cli_getpid(cli1), .offset = 0, .length = 1, + }; + + reqs[0] = cli_lockingx_create( + ev, /* mem_ctx */ + ev, /* tevent_context */ + cli1, /* cli */ + fnum1, /* fnum */ + LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */ + 0, /* newoplocklevel */ + 1, /* timeout */ + 0, /* num_unlocks */ + NULL, /* unlocks */ + 1, /* num_locks */ + &lck, /* locks */ + &smbreqs[0]); /* psmbreq */ + if (reqs[0] == NULL) { + d_fprintf(stderr, "cli_lockingx_create failed\n"); + goto done; + } + tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state); + + reqs[1] = cli_read_andx_create( + ev, /* mem_ctx */ + ev, /* ev */ + cli1, /* cli */ + fnum1, /* fnum */ + 0, /* offset */ + 1, /* size */ + &smbreqs[1]); /* psmbreq */ + if (reqs[1] == NULL) { + d_fprintf(stderr, "cli_read_andx_create failed\n"); + goto done; + } + tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state); + + status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs)); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, + "smb1cli_req_chain_submit failed: %s\n", + nt_errstr(status)); + goto done; + } + + while (!state.done) { + tevent_loop_once(ev); + } + + torture_close_connection(cli1); + + if (state.ok) { + ret = true; + } +done: + return ret; +} + +static void locktest10_lockingx_done(struct tevent_req *subreq) +{ + struct locktest10_state *state = tevent_req_callback_data_void(subreq); + NTSTATUS status; + + status = cli_lockingx_recv(subreq); + TALLOC_FREE(subreq); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { + d_printf("cli_lockingx returned %s\n", nt_errstr(status)); + state->ok = false; + } +} + +static void locktest10_read_andx_done(struct tevent_req *subreq) +{ + struct locktest10_state *state = tevent_req_callback_data_void(subreq); + ssize_t received = -1; + uint8_t *rcvbuf = NULL; + NTSTATUS status; + + status = cli_read_andx_recv(subreq, &received, &rcvbuf); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) { + d_printf("cli_read_andx returned %s\n", nt_errstr(status)); + state->ok = false; + } + + state->done = true; + TALLOC_FREE(subreq); +} + /* test whether fnums and tids open on one VC are available on another (a major security hole) @@ -12046,6 +12213,10 @@ static struct { .name = "LOCK9", .fn = run_locktest9, }, + { + .name = "LOCK10", + .fn = run_locktest10, + }, { .name = "UNLINK", .fn = run_unlinktest, -- 2.34.1