From ad13956b126a764e14b0016d89feb8407b1fa938 Mon Sep 17 00:00:00 2001 From: Koichiro IWAO Date: Wed, 15 Sep 2021 18:20:15 +0900 Subject: [PATCH 1/2] 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. --- sesman/chansrv/clipboard_file.c | 48 +++++++++++++++++++++++++++++++-- sesman/chansrv/clipboard_file.h | 1 + 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/sesman/chansrv/clipboard_file.c b/sesman/chansrv/clipboard_file.c index c317da79..3af75c58 100644 --- a/sesman/chansrv/clipboard_file.c +++ b/sesman/chansrv/clipboard_file.c @@ -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 */ diff --git a/sesman/chansrv/clipboard_file.h b/sesman/chansrv/clipboard_file.h index 16377b0e..37eaee5c 100644 --- a/sesman/chansrv/clipboard_file.h +++ b/sesman/chansrv/clipboard_file.h @@ -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); From eb848747d2193b0390ad1699f614152a763a1736 Mon Sep 17 00:00:00 2001 From: Koichiro IWAO Date: Tue, 21 Sep 2021 18:19:47 +0900 Subject: [PATCH 2/2] clipboard file: adjust log level and add some detailed info --- sesman/chansrv/clipboard_file.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sesman/chansrv/clipboard_file.c b/sesman/chansrv/clipboard_file.c index 3af75c58..4834d9c4 100644 --- a/sesman/chansrv/clipboard_file.c +++ b/sesman/chansrv/clipboard_file.c @@ -361,7 +361,8 @@ clipboard_send_file_size(int streamId, int lindex) } if (cfi->size < 0) { - LOG(LOG_LEVEL_ERROR, "clipboard_send_file_size: failed to get file size"); + LOG(LOG_LEVEL_ERROR, "clipboard_send_file_size: error cfi->size is negative" + "value [%d]", cfi->size); clipboard_send_filecontents_response_fail(streamId); return 1; } @@ -460,8 +461,8 @@ clipboard_send_file_data(int streamId, int lindex, } if (g_file_seek(fd, nPositionLow) < 0) { - LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: seek error " - "in file: %s", full_fn); + LOG(LOG_LEVEL_ERROR, "clipboard_send_file_data: seek error in file [%s]: %s", + full_fn, g_get_strerror()); g_file_close(fd); clipboard_send_filecontents_response_fail(streamId); return 1;