channels/cliprdr: handle cliprdr 2 GB size limit
The file contents PDUs support 64-bit file sizes and offsets, but MS-RDPECLIP explicitly says in 2.2.5.3 File Contents Request PDU that file larger that 4 gigabytes are not supported by the server. It turns out that the supported size is even lower than that. The server cannot correctly handle files larger than 2 gigabytes (inclusive). When faced with such files it correctly retireves the lower part, but fails to accept any data past that boundary. After receiving a file range reply the server repeats the file range request with the same offset, and again, and again, and again, making no progress and blocking the file transfer indefinitely. This is not the behavior we would like to have. Microsoft support site acknowledges and documents the issue [1], suggesting the users to use disk drive redirection instead to transfer large files. (File transfers via cliprdr are considerably slower than disk drive redirection so the suggestion makes very much sense.) However, we would like to avoid the lockdown of the remote session if the user does attempt to transfer such files so we add a size check. Putting it into the conversion from FILEDESCRIPTOR to CLIPRDR_FILELIST is not an ideal place (the clients may not use the common utilities), but that's good enough currently. [1]: https://support.microsoft.com/en-us/help/2258090
This commit is contained in:
parent
f643a95820
commit
a1128872d3
@ -438,6 +438,8 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CLIPRDR_MAX_FILE_SIZE (2U * 1024 * 1024 * 1024)
|
||||
|
||||
/**
|
||||
* Serialize a packed file list.
|
||||
*
|
||||
@ -472,6 +474,20 @@ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array,
|
||||
UINT64 lastWriteTime;
|
||||
const FILEDESCRIPTOR* file = &file_descriptor_array[i];
|
||||
|
||||
/*
|
||||
* There is a known issue with Windows server getting stuck in
|
||||
* an infinite loop when downloading files that are larger than
|
||||
* 2 gigabytes. Do not allow clients to send such file lists.
|
||||
*
|
||||
* https://support.microsoft.com/en-us/help/2258090
|
||||
*/
|
||||
if ((file->nFileSizeHigh > 0) || (file->nFileSizeLow >= CLIPRDR_MAX_FILE_SIZE))
|
||||
{
|
||||
WLog_ERR(TAG, "cliprdr does not support files over 2 GB");
|
||||
result = ERROR_FILE_TOO_LARGE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(s, file->dwFlags); /* flags (4 bytes) */
|
||||
Stream_Zero(s, 32); /* reserved1 (32 bytes) */
|
||||
Stream_Write_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */
|
||||
@ -491,5 +507,10 @@ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array,
|
||||
|
||||
Stream_Free(s, FALSE);
|
||||
|
||||
return result;
|
||||
|
||||
error:
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user