Issue:
We have a scenario where an application sends a Compound Related chain
consisting of:
SMB2_CREATE
SMB2_IOCTL
SMB2_SET_INFO
SMB2_CLOSE
SMB2_CREATE failed with NT_STATUS_ACCESS_DENIED and subsequent
requests all fail. In Samba they return NT_STATUS_FILE_CLOSED.
When I tried the same against a Win2k12 server, I noticed that all the
failed requests of the chain would return NT_STATUS_ACCESS_DENIED.
I believe this behaviour is also mentioned in the [MS-SMB2] Specs
3.3.5.2.7.2: Handling Compounded Related Requests
"When the current operation requires a FileId and the previous
operation either contains or generates a FileId, if the previous
operation fails with an error, the server SHOULD<223> fail the current
operation with the same error code returned by the previous
operation."
Fix:
Save NTATUS of a failed Create request. When we process subsequent
requests of the chain we check if the previous Create has failed. In
case of a Create failure we returned the saved NTSTATUS.
Signed-off-by: Anubhav Rakshit <anubhav.rakshit@gmail.com>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Thu Apr 8 17:30:50 UTC 2021 on sn-devel-184
+++ /dev/null
-^samba3.smb2.compound.related4
-^samba3.smb2.compound aio.related4
-^samba3.smb2.compound.related7
-^samba3.smb2.compound aio.related7
-^samba3.smb2.compound.related8
-^samba3.smb2.compound aio.related8
bool do_encryption;
struct tevent_timer *async_te;
bool compound_related;
+ NTSTATUS compound_create_err;
/*
* Give the implementation of an SMB2 req a way to tell the SMB2 request
&out_file_id_volatile,
&out_context_blobs);
if (!NT_STATUS_IS_OK(status)) {
+ if (smbd_smb2_is_compound(smb2req)) {
+ smb2req->compound_create_err = status;
+ }
error = smbd_smb2_request_error(smb2req, status);
if (!NT_STATUS_IS_OK(error)) {
smbd_server_connection_terminate(smb2req->xconn,
fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
if (fsp == NULL) {
+ if (req->compound_related &&
+ !NT_STATUS_IS_OK(req->compound_create_err))
+ {
+ return smbd_smb2_request_error(req,
+ req->compound_create_err);
+ }
if (!call->allow_invalid_fileid) {
return smbd_smb2_request_error(req,
NT_STATUS_FILE_CLOSED);