summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2019-06-13 03:59:54 -0700
committerJeremy Allison <jra@samba.org>2019-06-20 17:18:19 +0000
commit4c1d574ebea5138eda1cfbdcab90d25618e0a4f3 (patch)
tree53e3bebfea2b01b3a51da1a8d2f00d6ea96d1d4a
parentc4649b3ad6e6c41731b21da0c75632c38209d69c (diff)
downloadsamba-4c1d574ebea5138eda1cfbdcab90d25618e0a4f3.tar.gz
smbd: Use smbd_smb1_do_locks_send() in reply_lockingX()
Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
-rw-r--r--selftest/knownfail2
-rw-r--r--source3/smbd/reply.c211
2 files changed, 122 insertions, 91 deletions
diff --git a/selftest/knownfail b/selftest/knownfail
index 7b5d2ba7509..ded80b12259 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -13,8 +13,6 @@
^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.smbtorture_s3.*.LOCK12.*\(fileserver\)
^samba3.smbtorture_s3.*.LOCK12.*\(nt4_dc\)
^samba3.nbt.dgram.*netlogon2\(nt4_dc\)
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index a95159fc88f..727b619e299 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -8389,9 +8389,8 @@ void reply_lockingX(struct smb_request *req)
const uint8_t *data;
bool large_file_format;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
- struct smbd_lock_element *ulocks = NULL;
struct smbd_lock_element *locks = NULL;
- bool async = false;
+ struct tevent_req *subreq = NULL;
START_PROFILE(SMBlockingX);
@@ -8504,28 +8503,58 @@ void reply_lockingX(struct smb_request *req)
return;
}
- ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
- if (ulocks == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBlockingX);
- return;
- }
+ if (num_ulocks != 0) {
+ struct smbd_lock_element *ulocks = NULL;
+ bool ok;
- /* Data now points at the beginning of the list
- of smb_unlkrng structs */
- for (i = 0; i < num_ulocks; i++) {
- ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
- ulocks[i].count = get_lock_count(data, i, large_file_format);
- ulocks[i].offset = get_lock_offset(data, i, large_file_format);
- ulocks[i].brltype = UNLOCK_LOCK;
- }
+ ulocks = talloc_array(
+ req, struct smbd_lock_element, num_ulocks);
+ if (ulocks == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBlockingX);
+ return;
+ }
- status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
- TALLOC_FREE(ulocks);
- if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBlockingX);
- reply_nterror(req, status);
- return;
+ /*
+ * Data now points at the beginning of the list of
+ * smb_unlkrng structs
+ */
+ for (i = 0; i < num_ulocks; i++) {
+ ulocks[i].smblctx = get_lock_pid(
+ data, i, large_file_format);
+ ulocks[i].count = get_lock_count(
+ data, i, large_file_format);
+ ulocks[i].offset = get_lock_offset(
+ data, i, large_file_format);
+ ulocks[i].brltype = UNLOCK_LOCK;
+ }
+
+ /*
+ * Unlock cancels pending locks
+ */
+
+ ok = smbd_smb1_brl_finish_by_lock(
+ fsp,
+ large_file_format,
+ WINDOWS_LOCK,
+ ulocks[0],
+ NT_STATUS_OK);
+ if (ok) {
+ reply_outbuf(req, 2, 0);
+ SSVAL(req->outbuf, smb_vwv0, 0xff);
+ SSVAL(req->outbuf, smb_vwv1, 0);
+ END_PROFILE(SMBlockingX);
+ return;
+ }
+
+ status = smbd_do_unlocking(
+ req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
+ TALLOC_FREE(ulocks);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBlockingX);
+ reply_nterror(req, status);
+ return;
+ }
}
/* Now do any requested locks */
@@ -8535,17 +8564,9 @@ void reply_lockingX(struct smb_request *req)
of smb_lkrng structs */
if (locktype & LOCKING_ANDX_SHARED_LOCK) {
- if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
- brltype = PENDING_READ_LOCK;
- } else {
- brltype = READ_LOCK;
- }
+ brltype = READ_LOCK;
} else {
- if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
- brltype = PENDING_WRITE_LOCK;
- } else {
- brltype = WRITE_LOCK;
- }
+ brltype = WRITE_LOCK;
}
locks = talloc_array(req, struct smbd_lock_element, num_locks);
@@ -8563,81 +8584,93 @@ void reply_lockingX(struct smb_request *req)
}
if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
- struct smbd_lock_element *e = NULL;
+
+ bool ok;
if (num_locks == 0) {
/* See smbtorture3 lock11 test */
- goto done;
+ reply_outbuf(req, 2, 0);
+ /* andx chain ends */
+ SSVAL(req->outbuf, smb_vwv0, 0xff);
+ SSVAL(req->outbuf, smb_vwv1, 0);
+ END_PROFILE(SMBlockingX);
+ return;
}
- e = &locks[0];
+ ok = smbd_smb1_brl_finish_by_lock(
+ fsp,
+ large_file_format,
+ WINDOWS_LOCK,
+ locks[0], /* Windows only cancels the first lock */
+ NT_STATUS_FILE_LOCK_CONFLICT);
- /*
- * MS-CIFS (2.2.4.32.1) states that a cancel is
- * honored if and only if the lock vector contains one
- * entry. When given multiple cancel requests in a
- * single PDU we expect the server to return an
- * error. Windows servers seem to accept the request
- * but only cancel the first lock.
- *
- * JRA - Do what Windows does (tm) :-).
- */
-
- if (lp_blocking_locks(SNUM(conn))) {
- struct blocking_lock_record *blr = NULL;
-
- /* Schedule a message to ourselves to
- remove the blocking lock record and
- return the right error. */
-
- blr = blocking_lock_cancel_smb1(
- fsp,
- e->smblctx,
- e->offset,
- e->count,
- WINDOWS_LOCK,
- locktype,
- NT_STATUS_FILE_LOCK_CONFLICT);
- if (blr == NULL) {
- reply_force_doserror(
- req, ERRDOS, ERRcancelviolation);
- END_PROFILE(SMBlockingX);
- return;
- }
+ if (!ok) {
+ reply_force_doserror(req, ERRDOS, ERRcancelviolation);
+ END_PROFILE(SMBlockingX);
+ return;
}
- /* Remove a matching pending lock. */
- status = do_lock_cancel(fsp,
- e->smblctx,
- e->count,
- e->offset,
- WINDOWS_LOCK);
+ reply_outbuf(req, 2, 0);
+ SSVAL(req->outbuf, smb_vwv0, 0xff);
+ SSVAL(req->outbuf, smb_vwv1, 0);
END_PROFILE(SMBlockingX);
- reply_nterror(req, status);
return;
}
- status = smbd_do_locking(
- req, fsp, lock_timeout, num_locks, locks, &async);
- TALLOC_FREE(locks);
- if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBlockingX);
- reply_nterror(req, status);
- return;
- }
- if (async) {
+ subreq = smbd_smb1_do_locks_send(
+ fsp,
+ req->sconn->ev_ctx,
+ req->sconn->msg_ctx,
+ &req,
+ fsp,
+ lock_timeout,
+ large_file_format,
+ WINDOWS_LOCK,
+ num_locks,
+ locks);
+ if (subreq == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
END_PROFILE(SMBlockingX);
return;
}
+ tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
+ END_PROFILE(SMBlockingX);
+}
-done:
- reply_outbuf(req, 2, 0);
- SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
- SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
+static void reply_lockingx_done(struct tevent_req *subreq)
+{
+ struct smb_request *req = NULL;
+ NTSTATUS status;
+ bool ok;
+
+ START_PROFILE(SMBlockingX);
+
+ ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
+ SMB_ASSERT(ok);
- DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
- fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
+ status = smbd_smb1_do_locks_recv(subreq);
+ TALLOC_FREE(subreq);
+
+ DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
+
+ if (NT_STATUS_IS_OK(status)) {
+ reply_outbuf(req, 2, 0);
+ SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+ SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
+ } else {
+ reply_nterror(req, status);
+ }
+ ok = srv_send_smb(req->xconn,
+ (char *)req->outbuf,
+ true,
+ req->seqnum+1,
+ IS_CONN_ENCRYPTED(req->conn),
+ NULL);
+ if (!ok) {
+ exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
+ }
+ TALLOC_FREE(req);
END_PROFILE(SMBlockingX);
}