diff options
author | Volker Lendecke <vl@samba.org> | 2019-06-13 03:59:54 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2019-06-20 17:18:19 +0000 |
commit | 4c1d574ebea5138eda1cfbdcab90d25618e0a4f3 (patch) | |
tree | 53e3bebfea2b01b3a51da1a8d2f00d6ea96d1d4a | |
parent | c4649b3ad6e6c41731b21da0c75632c38209d69c (diff) | |
download | samba-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/knownfail | 2 | ||||
-rw-r--r-- | source3/smbd/reply.c | 211 |
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); } |