Server: SMB2: Bugfix: Invalid change notify interim response was sent when the object store did not support change notifications

This commit is contained in:
Tal Aloni 2019-07-13 18:22:51 +03:00
parent 1ec238b756
commit a0a372dd16
2 changed files with 22 additions and 6 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2017-2019 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
@ -28,7 +28,9 @@ namespace SMBLibrary.Server.SMB2
{
state.LogToServer(Severity.Information, "Cancel: Requested cancel on '{0}{1}'. NTStatus: {2}, AsyncID: {3}.", share.Name, openFile.Path, status, context.AsyncID);
}
if (status == NTStatus.STATUS_SUCCESS || status == NTStatus.STATUS_CANCELLED)
if (status == NTStatus.STATUS_SUCCESS ||
status == NTStatus.STATUS_CANCELLED ||
status == NTStatus.STATUS_NOT_SUPPORTED) // See ChangeNotifyHelper.cs
{
state.RemoveAsyncContext(context);
// [MS-SMB2] If the target request is successfully canceled, the target request MUST be failed by sending
@ -39,6 +41,7 @@ namespace SMBLibrary.Server.SMB2
return response;
}
// [MS-SMB2] If the target request is not successfully canceled [..] no response is sent.
// Note: Failing to respond might cause the client to disconnect the connection as per [MS-SMB2] 3.2.6.1 Request Expiration Timer Event
return null;
}
else

View file

@ -30,11 +30,24 @@ namespace SMBLibrary.Server.SMB2
{
state.LogToServer(Severity.Verbose, "NotifyChange: Monitoring of '{0}{1}' started. AsyncID: {2}.", share.Name, openFile.Path, asyncContext.AsyncID);
}
// [MS-SMB2] If the underlying object store does not support change notifications, the server MUST fail this request with STATUS_NOT_SUPPORTED
else if (status == NTStatus.STATUS_NOT_SUPPORTED)
{
// [MS-SMB2] If the underlying object store does not support change notifications, the server MUST fail this request with STATUS_NOT_SUPPORTED.
// Unfortunately, Windows 7 / 8 / 10 will immediately retry sending another ChangeNotify request upon getting STATUS_NOT_SUPPORTED,
// To prevent flooding, we must return a valid interim response (Status set to STATUS_PENDING and SMB2_FLAGS_ASYNC_COMMAND bit is set in Flags).
status = NTStatus.STATUS_PENDING;
}
else
{
state.RemoveAsyncContext(asyncContext);
}
ErrorResponse response = new ErrorResponse(request.CommandName, status);
// Windows 7 / 8 / 10 will infinitely retry sending ChangeNotify requests if the response does not have SMB2_FLAGS_ASYNC_COMMAND set.
response.Header.IsAsync = true;
response.Header.AsyncID = asyncContext.AsyncID;
if (status == NTStatus.STATUS_PENDING)
{
response.Header.IsAsync = true;
response.Header.AsyncID = asyncContext.AsyncID;
}
return response;
}
}