clipboard file: Implement MS-RDPECLIP 3.1.5.4.7 compliance

If the requested file data could not be retrieved or the sender received
an unsuccessful Format List Response PDU (section 3.1.5.2.4), then the
clipHeader field MUST contain the CB_RESPONSE_FAIL (0x0002) flag and the
requestedFileContentsData field MUST contain no data (zero-length).

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeclip/5d3991e9-440d-4e4d-8b8d-391c324c4007

Fixes #1997.
This commit is contained in:
Koichiro IWAO 2021-09-15 18:20:15 +09:00
parent e1bbef99aa
commit ad13956b12
No known key found for this signature in database
GPG Key ID: 03993B4065E7193B
2 changed files with 47 additions and 2 deletions

View File

@ -82,6 +82,37 @@ timeval2wintime(struct timeval *tv)
}
#endif
/***
* See MS-RDPECLIP 3.1.5.4.7
*
* Sends a failure response to a CLIPRDR_FILECONTENTS_REQUEST
* @param streamId Stream ID from CLIPRDR_FILECONTENTS_REQUEST
* @return 0 for success
*/
static int
clipboard_send_filecontents_response_fail(int streamId)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "clipboardn_send_filecontents_response_fail:");
struct stream *s;
int size;
int rv;
make_stream(s);
init_stream(s, 64);
out_uint16_le(s, CB_FILECONTENTS_RESPONSE);
out_uint16_le(s, CB_RESPONSE_FAIL);
out_uint32_le(s, 4);
out_uint32_le(s, streamId);
s_mark_end(s);
size = (int)(s->end - s->data);
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s);
return rv;
}
/*****************************************************************************/
/* this will replace %20 or any hex with the space or correct char
* returns error */
@ -318,12 +349,20 @@ clipboard_send_file_size(int streamId, int lindex)
if (g_files_list == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_size: error g_files_list is nil");
clipboard_send_filecontents_response_fail(streamId);
return 1;
}
cfi = (struct cb_file_info *)list_get_item(g_files_list, lindex);
if (cfi == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_size: error cfi is nil");
clipboard_send_filecontents_response_fail(streamId);
return 1;
}
if (cfi->size < 0)
{
LOG(LOG_LEVEL_ERROR, "clipboard_send_file_size: failed to get file size");
clipboard_send_filecontents_response_fail(streamId);
return 1;
}
file_size = cfi->size;
@ -397,12 +436,14 @@ clipboard_send_file_data(int streamId, int lindex,
if (g_files_list == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: error g_files_list is nil");
clipboard_send_filecontents_response_fail(streamId);
return 1;
}
cfi = (struct cb_file_info *)list_get_item(g_files_list, lindex);
if (cfi == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: error cfi is nil");
clipboard_send_filecontents_response_fail(streamId);
return 1;
}
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_send_file_data: streamId %d lindex %d "
@ -412,8 +453,9 @@ clipboard_send_file_data(int streamId, int lindex,
fd = g_file_open_ex(full_fn, 1, 0, 0, 0);
if (fd == -1)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: file open [%s] failed",
full_fn);
LOG(LOG_LEVEL_ERROR, "clipboard_send_file_data: file open [%s] failed: %s",
full_fn, g_get_strerror());
clipboard_send_filecontents_response_fail(streamId);
return 1;
}
if (g_file_seek(fd, nPositionLow) < 0)
@ -421,6 +463,7 @@ clipboard_send_file_data(int streamId, int lindex,
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: seek error "
"in file: %s", full_fn);
g_file_close(fd);
clipboard_send_filecontents_response_fail(streamId);
return 1;
}
make_stream(s);
@ -432,6 +475,7 @@ clipboard_send_file_data(int streamId, int lindex,
cbRequested, size);
free_stream(s);
g_file_close(fd);
clipboard_send_filecontents_response_fail(streamId);
return 1;
}
out_uint16_le(s, CB_FILECONTENTS_RESPONSE); /* 9 */

View File

@ -35,6 +35,7 @@ clipboard_c2s_in_files(struct stream *s, char *file_list);
int
clipboard_request_file_size(int stream_id, int lindex);
int
clipboard_request_file_data(int stream_id, int lindex, int offset,
int request_bytes);